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.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);
|
|
@@ -4645,7 +4751,7 @@ const colorPropToSVG = function (prop, value) {
|
|
|
4645
4751
|
if (!value) {
|
|
4646
4752
|
colorValue = 'none';
|
|
4647
4753
|
} else if (value.toLive) {
|
|
4648
|
-
colorValue = `url(#SVGID_${value.id})`;
|
|
4754
|
+
colorValue = `url(#SVGID_${escapeXml(value.id)})`;
|
|
4649
4755
|
} else {
|
|
4650
4756
|
const color = new Color(value),
|
|
4651
4757
|
opacity = color.getAlpha();
|
|
@@ -4698,7 +4804,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4698
4804
|
filter = skipShadow ? '' : this.getSvgFilter(),
|
|
4699
4805
|
fill = colorPropToSVG(FILL, this.fill),
|
|
4700
4806
|
stroke = colorPropToSVG(STROKE, this.stroke);
|
|
4701
|
-
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('');
|
|
4702
4808
|
}
|
|
4703
4809
|
|
|
4704
4810
|
/**
|
|
@@ -4706,7 +4812,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4706
4812
|
* @return {String}
|
|
4707
4813
|
*/
|
|
4708
4814
|
getSvgFilter() {
|
|
4709
|
-
return this.shadow ? `filter: url(#SVGID_${this.shadow.id});` : '';
|
|
4815
|
+
return this.shadow ? `filter: url(#SVGID_${escapeXml(this.shadow.id)});` : '';
|
|
4710
4816
|
}
|
|
4711
4817
|
|
|
4712
4818
|
/**
|
|
@@ -4714,7 +4820,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4714
4820
|
* @return {String}
|
|
4715
4821
|
*/
|
|
4716
4822
|
getSvgCommons() {
|
|
4717
|
-
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('');
|
|
4718
4824
|
}
|
|
4719
4825
|
|
|
4720
4826
|
/**
|
|
@@ -4827,7 +4933,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4827
4933
|
return reviver ? reviver(markup.join('')) : markup.join('');
|
|
4828
4934
|
}
|
|
4829
4935
|
addPaintOrder() {
|
|
4830
|
-
return this.paintFirst !== FILL ? ` paint-order="${this.paintFirst}" ` : '';
|
|
4936
|
+
return this.paintFirst !== FILL ? ` paint-order="${escapeXml(this.paintFirst)}" ` : '';
|
|
4831
4937
|
}
|
|
4832
4938
|
}
|
|
4833
4939
|
|
|
@@ -4965,7 +5071,6 @@ const reViewBoxAttrValue = new RegExp(String.raw`^\s*(${reNum})${viewportSeparat
|
|
|
4965
5071
|
|
|
4966
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.
|
|
4967
5073
|
*/
|
|
4968
|
-
// eslint-disable-next-line max-len
|
|
4969
5074
|
|
|
4970
5075
|
const shadowOffsetRegex = '(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?';
|
|
4971
5076
|
const reOffsetsAndBlur = new RegExp('(?:\\s|^)' + shadowOffsetRegex + shadowOffsetRegex + '(' + reNum + '?(?:px)?)?(?:\\s?|$)(?:$|\\s)');
|
|
@@ -5024,14 +5129,15 @@ class Shadow {
|
|
|
5024
5129
|
toSVG(object) {
|
|
5025
5130
|
const offset = rotateVector(new Point(this.offsetX, this.offsetY), degreesToRadians(-object.angle)),
|
|
5026
5131
|
BLUR_BOX = 20,
|
|
5132
|
+
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,
|
|
5027
5133
|
color = new Color(this.color);
|
|
5028
5134
|
let fBoxX = 40,
|
|
5029
5135
|
fBoxY = 40;
|
|
5030
5136
|
if (object.width && object.height) {
|
|
5031
5137
|
//http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
|
|
5032
5138
|
// we add some extra space to filter box to contain the blur ( 20 )
|
|
5033
|
-
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width,
|
|
5034
|
-
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;
|
|
5035
5141
|
}
|
|
5036
5142
|
if (object.flipX) {
|
|
5037
5143
|
offset.x *= -1;
|
|
@@ -5039,7 +5145,7 @@ class Shadow {
|
|
|
5039
5145
|
if (object.flipY) {
|
|
5040
5146
|
offset.y *= -1;
|
|
5041
5147
|
}
|
|
5042
|
-
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`;
|
|
5043
5149
|
}
|
|
5044
5150
|
|
|
5045
5151
|
/**
|
|
@@ -7190,6 +7296,9 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
|
|
|
7190
7296
|
} else {
|
|
7191
7297
|
this._renderBackground(ctx);
|
|
7192
7298
|
}
|
|
7299
|
+
this.fire('before:render', {
|
|
7300
|
+
ctx
|
|
7301
|
+
});
|
|
7193
7302
|
this._render(ctx);
|
|
7194
7303
|
this._drawClipPath(ctx, this.clipPath, context);
|
|
7195
7304
|
this.fill = originalFill;
|
|
@@ -8480,6 +8589,14 @@ class Control {
|
|
|
8480
8589
|
_defineProperty(this, "withConnection", false);
|
|
8481
8590
|
Object.assign(this, options);
|
|
8482
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
|
+
}
|
|
8483
8600
|
|
|
8484
8601
|
/**
|
|
8485
8602
|
* The control actionHandler, provide one to handle action ( control being moved )
|
|
@@ -10295,111 +10412,6 @@ const cloneStyles = style => {
|
|
|
10295
10412
|
return newObj;
|
|
10296
10413
|
};
|
|
10297
10414
|
|
|
10298
|
-
/**
|
|
10299
|
-
* Capitalizes a string
|
|
10300
|
-
* @param {String} string String to capitalize
|
|
10301
|
-
* @param {Boolean} [firstLetterOnly] If true only first letter is capitalized
|
|
10302
|
-
* and other letters stay untouched, if false first letter is capitalized
|
|
10303
|
-
* and other letters are converted to lowercase.
|
|
10304
|
-
* @return {String} Capitalized version of a string
|
|
10305
|
-
*/
|
|
10306
|
-
const capitalize = function (string) {
|
|
10307
|
-
let firstLetterOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
10308
|
-
return `${string.charAt(0).toUpperCase()}${firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()}`;
|
|
10309
|
-
};
|
|
10310
|
-
|
|
10311
|
-
/**
|
|
10312
|
-
* Escapes XML in a string
|
|
10313
|
-
* @param {String} string String to escape
|
|
10314
|
-
* @return {String} Escaped version of a string
|
|
10315
|
-
*/
|
|
10316
|
-
const escapeXml = string => string.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
10317
|
-
let segmenter;
|
|
10318
|
-
const getSegmenter = () => {
|
|
10319
|
-
if (!segmenter) {
|
|
10320
|
-
segmenter = 'Intl' in getFabricWindow() && 'Segmenter' in Intl && new Intl.Segmenter(undefined, {
|
|
10321
|
-
granularity: 'grapheme'
|
|
10322
|
-
});
|
|
10323
|
-
}
|
|
10324
|
-
return segmenter;
|
|
10325
|
-
};
|
|
10326
|
-
|
|
10327
|
-
/**
|
|
10328
|
-
* Divide a string in the user perceived single units
|
|
10329
|
-
* @param {String} textstring String to escape
|
|
10330
|
-
* @return {Array} array containing the graphemes
|
|
10331
|
-
*/
|
|
10332
|
-
const graphemeSplit = textstring => {
|
|
10333
|
-
segmenter || getSegmenter();
|
|
10334
|
-
if (segmenter) {
|
|
10335
|
-
const segments = segmenter.segment(textstring);
|
|
10336
|
-
return Array.from(segments).map(_ref => {
|
|
10337
|
-
let {
|
|
10338
|
-
segment
|
|
10339
|
-
} = _ref;
|
|
10340
|
-
return segment;
|
|
10341
|
-
});
|
|
10342
|
-
}
|
|
10343
|
-
|
|
10344
|
-
//Fallback
|
|
10345
|
-
return graphemeSplitImpl(textstring);
|
|
10346
|
-
};
|
|
10347
|
-
const graphemeSplitImpl = textstring => {
|
|
10348
|
-
const graphemes = [];
|
|
10349
|
-
for (let i = 0, chr; i < textstring.length; i++) {
|
|
10350
|
-
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
10351
|
-
continue;
|
|
10352
|
-
}
|
|
10353
|
-
graphemes.push(chr);
|
|
10354
|
-
}
|
|
10355
|
-
return graphemes;
|
|
10356
|
-
};
|
|
10357
|
-
|
|
10358
|
-
// taken from mdn in the charAt doc page.
|
|
10359
|
-
const getWholeChar = (str, i) => {
|
|
10360
|
-
const code = str.charCodeAt(i);
|
|
10361
|
-
if (isNaN(code)) {
|
|
10362
|
-
return ''; // Position not found
|
|
10363
|
-
}
|
|
10364
|
-
if (code < 0xd800 || code > 0xdfff) {
|
|
10365
|
-
return str.charAt(i);
|
|
10366
|
-
}
|
|
10367
|
-
|
|
10368
|
-
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
10369
|
-
// surrogates as single characters)
|
|
10370
|
-
if (0xd800 <= code && code <= 0xdbff) {
|
|
10371
|
-
if (str.length <= i + 1) {
|
|
10372
|
-
throw 'High surrogate without following low surrogate';
|
|
10373
|
-
}
|
|
10374
|
-
const next = str.charCodeAt(i + 1);
|
|
10375
|
-
if (0xdc00 > next || next > 0xdfff) {
|
|
10376
|
-
throw 'High surrogate without following low surrogate';
|
|
10377
|
-
}
|
|
10378
|
-
return str.charAt(i) + str.charAt(i + 1);
|
|
10379
|
-
}
|
|
10380
|
-
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
10381
|
-
if (i === 0) {
|
|
10382
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10383
|
-
}
|
|
10384
|
-
const prev = str.charCodeAt(i - 1);
|
|
10385
|
-
|
|
10386
|
-
// (could change last hex to 0xDB7F to treat high private
|
|
10387
|
-
// surrogates as single characters)
|
|
10388
|
-
if (0xd800 > prev || prev > 0xdbff) {
|
|
10389
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10390
|
-
}
|
|
10391
|
-
// We can pass over low surrogates now as the second component
|
|
10392
|
-
// in a pair which we have already processed
|
|
10393
|
-
return false;
|
|
10394
|
-
};
|
|
10395
|
-
|
|
10396
|
-
var lang_string = /*#__PURE__*/Object.freeze({
|
|
10397
|
-
__proto__: null,
|
|
10398
|
-
capitalize: capitalize,
|
|
10399
|
-
escapeXml: escapeXml,
|
|
10400
|
-
graphemeSplit: graphemeSplit
|
|
10401
|
-
});
|
|
10402
|
-
|
|
10403
10415
|
/**
|
|
10404
10416
|
* @param {Object} prevStyle first style to compare
|
|
10405
10417
|
* @param {Object} thisStyle second style to compare
|
|
@@ -10983,7 +10995,7 @@ class Rect extends FabricObject {
|
|
|
10983
10995
|
rx,
|
|
10984
10996
|
ry
|
|
10985
10997
|
} = this;
|
|
10986
|
-
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`];
|
|
10987
10999
|
}
|
|
10988
11000
|
|
|
10989
11001
|
/**
|
|
@@ -11948,7 +11960,7 @@ class Group extends createCollectionMixin(FabricObject) {
|
|
|
11948
11960
|
* @return {String}
|
|
11949
11961
|
*/
|
|
11950
11962
|
getSvgStyles() {
|
|
11951
|
-
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)};` : '',
|
|
11952
11964
|
visibility = this.visible ? '' : ' visibility: hidden;';
|
|
11953
11965
|
return [opacity, this.getSvgFilter(), visibility].join('');
|
|
11954
11966
|
}
|
|
@@ -13902,11 +13914,13 @@ class SelectableCanvas extends StaticCanvas$1 {
|
|
|
13902
13914
|
* Given the control clicked, determine the origin of the transform.
|
|
13903
13915
|
* This is bad because controls can totally have custom names
|
|
13904
13916
|
* should disappear before release 4.0
|
|
13917
|
+
* Fabric 7.1, jan 2026 we are still using this.
|
|
13918
|
+
* Needs to go.
|
|
13905
13919
|
* @private
|
|
13906
13920
|
* @deprecated
|
|
13907
13921
|
*/
|
|
13908
13922
|
_getOriginFromCorner(target, controlName) {
|
|
13909
|
-
const origin = {
|
|
13923
|
+
const origin = controlName ? target.controls[controlName].getTransformAnchorPoint() : {
|
|
13910
13924
|
x: target.originX,
|
|
13911
13925
|
y: target.originY
|
|
13912
13926
|
};
|
|
@@ -13914,6 +13928,9 @@ class SelectableCanvas extends StaticCanvas$1 {
|
|
|
13914
13928
|
return origin;
|
|
13915
13929
|
}
|
|
13916
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
|
|
13917
13934
|
// is a left control ?
|
|
13918
13935
|
if (['ml', 'tl', 'bl'].includes(controlName)) {
|
|
13919
13936
|
origin.x = RIGHT;
|
|
@@ -16411,7 +16428,8 @@ class Gradient {
|
|
|
16411
16428
|
}
|
|
16412
16429
|
transform[4] -= offsetX;
|
|
16413
16430
|
transform[5] -= offsetY;
|
|
16414
|
-
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));
|
|
16415
16433
|
if (this.type === 'linear') {
|
|
16416
16434
|
const {
|
|
16417
16435
|
x1,
|
|
@@ -16419,7 +16437,11 @@ class Gradient {
|
|
|
16419
16437
|
x2,
|
|
16420
16438
|
y2
|
|
16421
16439
|
} = this.coords;
|
|
16422
|
-
|
|
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');
|
|
16423
16445
|
} else if (this.type === 'radial') {
|
|
16424
16446
|
const {
|
|
16425
16447
|
x1,
|
|
@@ -16429,9 +16451,15 @@ class Gradient {
|
|
|
16429
16451
|
r1,
|
|
16430
16452
|
r2
|
|
16431
16453
|
} = this.coords;
|
|
16432
|
-
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;
|
|
16433
16461
|
// svg radial gradient has just 1 radius. the biggest.
|
|
16434
|
-
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');
|
|
16435
16463
|
if (needsSwap) {
|
|
16436
16464
|
// svg goes from internal to external radius. if radius are inverted, swap color stops.
|
|
16437
16465
|
colorStops.reverse(); // mutates array
|
|
@@ -16439,16 +16467,17 @@ class Gradient {
|
|
|
16439
16467
|
colorStop.offset = 1 - colorStop.offset;
|
|
16440
16468
|
});
|
|
16441
16469
|
}
|
|
16442
|
-
const minRadius = Math.min(
|
|
16470
|
+
const minRadius = Math.min(sr1, sr2);
|
|
16443
16471
|
if (minRadius > 0) {
|
|
16444
16472
|
// i have to shift all colorStops and add new one in 0.
|
|
16445
|
-
const maxRadius = Math.max(
|
|
16473
|
+
const maxRadius = Math.max(sr1, sr2),
|
|
16446
16474
|
percentageShift = minRadius / maxRadius;
|
|
16447
16475
|
colorStops.forEach(colorStop => {
|
|
16448
16476
|
colorStop.offset += percentageShift * (1 - colorStop.offset);
|
|
16449
16477
|
});
|
|
16450
16478
|
}
|
|
16451
16479
|
}
|
|
16480
|
+
// todo make a malicious script tag injection test with color and also apply a fix with escapeXml
|
|
16452
16481
|
colorStops.forEach(_ref => {
|
|
16453
16482
|
let {
|
|
16454
16483
|
color,
|
|
@@ -16764,7 +16793,7 @@ class Pattern {
|
|
|
16764
16793
|
patternOffsetY = ifNaN(this.offsetY / height, 0),
|
|
16765
16794
|
patternWidth = repeat === 'repeat-y' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetX || 0) : ifNaN(patternSource.width / width, 0),
|
|
16766
16795
|
patternHeight = repeat === 'repeat-x' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetY || 0) : ifNaN(patternSource.height / height, 0);
|
|
16767
|
-
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');
|
|
16768
16797
|
}
|
|
16769
16798
|
/* _TO_SVG_END_ */
|
|
16770
16799
|
|
|
@@ -17046,8 +17075,7 @@ class Path extends FabricObject {
|
|
|
17046
17075
|
* of the instance
|
|
17047
17076
|
*/
|
|
17048
17077
|
_toSVG() {
|
|
17049
|
-
|
|
17050
|
-
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`];
|
|
17051
17079
|
}
|
|
17052
17080
|
|
|
17053
17081
|
/**
|
|
@@ -17598,15 +17626,17 @@ class Circle extends FabricObject {
|
|
|
17598
17626
|
* of the instance
|
|
17599
17627
|
*/
|
|
17600
17628
|
_toSVG() {
|
|
17601
|
-
const
|
|
17629
|
+
const {
|
|
17630
|
+
radius,
|
|
17631
|
+
startAngle,
|
|
17632
|
+
endAngle
|
|
17633
|
+
} = this;
|
|
17634
|
+
const angle = (endAngle - startAngle) % 360;
|
|
17602
17635
|
if (angle === 0) {
|
|
17603
|
-
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${
|
|
17636
|
+
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${escapeXml(radius)}`, '" />\n'];
|
|
17604
17637
|
} else {
|
|
17605
|
-
const
|
|
17606
|
-
|
|
17607
|
-
} = this;
|
|
17608
|
-
const start = degreesToRadians(this.startAngle),
|
|
17609
|
-
end = degreesToRadians(this.endAngle),
|
|
17638
|
+
const start = degreesToRadians(startAngle),
|
|
17639
|
+
end = degreesToRadians(endAngle),
|
|
17610
17640
|
startX = cos(start) * radius,
|
|
17611
17641
|
startY = sin(start) * radius,
|
|
17612
17642
|
endX = cos(end) * radius,
|
|
@@ -18178,17 +18208,13 @@ class Line extends FabricObject {
|
|
|
18178
18208
|
width,
|
|
18179
18209
|
height
|
|
18180
18210
|
} = this;
|
|
18181
|
-
const xMult = _x1 <= _x2 ? -
|
|
18182
|
-
yMult = _y1 <= _y2 ? -
|
|
18183
|
-
x1 = xMult * width / 2,
|
|
18184
|
-
y1 = yMult * height / 2,
|
|
18185
|
-
x2 = xMult * -width / 2,
|
|
18186
|
-
y2 = yMult * -height / 2;
|
|
18211
|
+
const xMult = _x1 <= _x2 ? -0.5 : 0.5,
|
|
18212
|
+
yMult = _y1 <= _y2 ? -0.5 : 0.5;
|
|
18187
18213
|
return {
|
|
18188
|
-
x1,
|
|
18189
|
-
x2,
|
|
18190
|
-
y1,
|
|
18191
|
-
y2
|
|
18214
|
+
x1: xMult * width,
|
|
18215
|
+
x2: xMult * -width,
|
|
18216
|
+
y1: yMult * height,
|
|
18217
|
+
y2: yMult * -height
|
|
18192
18218
|
};
|
|
18193
18219
|
}
|
|
18194
18220
|
|
|
@@ -18406,7 +18432,7 @@ class Ellipse extends FabricObject {
|
|
|
18406
18432
|
* of the instance
|
|
18407
18433
|
*/
|
|
18408
18434
|
_toSVG() {
|
|
18409
|
-
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`];
|
|
18410
18436
|
}
|
|
18411
18437
|
|
|
18412
18438
|
/**
|
|
@@ -18724,14 +18750,17 @@ class Polyline extends FabricObject {
|
|
|
18724
18750
|
* of the instance
|
|
18725
18751
|
*/
|
|
18726
18752
|
_toSVG() {
|
|
18727
|
-
const
|
|
18728
|
-
diffX = this.pathOffset.x,
|
|
18753
|
+
const diffX = this.pathOffset.x,
|
|
18729
18754
|
diffY = this.pathOffset.y,
|
|
18730
18755
|
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;
|
|
18731
|
-
|
|
18732
|
-
|
|
18733
|
-
|
|
18734
|
-
|
|
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`];
|
|
18735
18764
|
}
|
|
18736
18765
|
|
|
18737
18766
|
/**
|
|
@@ -19155,7 +19184,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19155
19184
|
} = _ref;
|
|
19156
19185
|
const noShadow = true,
|
|
19157
19186
|
textDecoration = this.getSvgTextDecoration(this);
|
|
19158
|
-
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'];
|
|
19159
19188
|
}
|
|
19160
19189
|
|
|
19161
19190
|
/**
|
|
@@ -19171,7 +19200,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19171
19200
|
lineOffset;
|
|
19172
19201
|
|
|
19173
19202
|
// bounding-box background
|
|
19174
|
-
this.backgroundColor && textBgRects.push(
|
|
19203
|
+
this.backgroundColor && textBgRects.push(createSVGInlineRect(this.backgroundColor, -this.width / 2, -this.height / 2, this.width, this.height));
|
|
19175
19204
|
|
|
19176
19205
|
// text and text-background
|
|
19177
19206
|
for (let i = 0, len = this._textLines.length; i < len; i++) {
|
|
@@ -19279,7 +19308,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19279
19308
|
} = this.__charBounds[i][j];
|
|
19280
19309
|
currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');
|
|
19281
19310
|
if (currentColor !== lastColor) {
|
|
19282
|
-
lastColor && textBgRects.push(
|
|
19311
|
+
lastColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
19283
19312
|
boxStart = left;
|
|
19284
19313
|
boxWidth = width;
|
|
19285
19314
|
lastColor = currentColor;
|
|
@@ -19287,7 +19316,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19287
19316
|
boxWidth += kernedWidth;
|
|
19288
19317
|
}
|
|
19289
19318
|
}
|
|
19290
|
-
currentColor && textBgRects.push(
|
|
19319
|
+
currentColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
19291
19320
|
}
|
|
19292
19321
|
|
|
19293
19322
|
/**
|
|
@@ -19325,7 +19354,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19325
19354
|
linethrough: linethrough !== null && linethrough !== void 0 ? linethrough : this.linethrough
|
|
19326
19355
|
});
|
|
19327
19356
|
const thickness = textDecorationThickness || this.textDecorationThickness;
|
|
19328
|
-
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('');
|
|
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('');
|
|
19329
19358
|
}
|
|
19330
19359
|
|
|
19331
19360
|
/**
|
|
@@ -24889,13 +24918,13 @@ class FabricImage extends FabricObject {
|
|
|
24889
24918
|
}
|
|
24890
24919
|
if (this.hasCrop()) {
|
|
24891
24920
|
const clipPathId = uid();
|
|
24892
|
-
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');
|
|
24893
24922
|
clipPath = ' clip-path="url(#imageCrop_' + clipPathId + ')" ';
|
|
24894
24923
|
}
|
|
24895
24924
|
if (!this.imageSmoothing) {
|
|
24896
24925
|
imageRendering = ' image-rendering="optimizeSpeed"';
|
|
24897
24926
|
}
|
|
24898
|
-
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
|
|
24899
24928
|
// we're essentially moving origin of transformation from top/left corner to the center of the shape
|
|
24900
24929
|
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
|
|
24901
24930
|
// so that object's center aligns with container's left/top
|
|
@@ -24903,7 +24932,7 @@ class FabricImage extends FabricObject {
|
|
|
24903
24932
|
if (this.stroke || this.strokeDashArray) {
|
|
24904
24933
|
const origFill = this.fill;
|
|
24905
24934
|
this.fill = null;
|
|
24906
|
-
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`];
|
|
24907
24936
|
this.fill = origFill;
|
|
24908
24937
|
}
|
|
24909
24938
|
if (this.paintFirst !== FILL) {
|