svgedit/dist/svgcanvas-iife.min.js.map

1 line
817 KiB
Plaintext

{"version":3,"file":"svgcanvas-iife.min.js","sources":["../src/common/jQuery.attr.js","../src/common/svgpathseg.js","../src/common/namespaces.js","../src/common/browser.js","../src/common/svgtransformlist.js","../src/common/math.js","../src/common/utilities.js","../src/common/units.js","../src/svgcanvas/history.js","../src/svgcanvas/path.js","../src/common/layer.js","../src/svgcanvas/historyrecording.js","../src/svgcanvas/copy-elem.js","../src/svgcanvas/draw.js","../src/svgcanvas/sanitize.js","../src/external/dynamic-import-polyfill/importModule.js","../src/svgcanvas/coords.js","../src/svgcanvas/recalculate.js","../src/svgcanvas/select.js","../src/svgcanvas/svgcanvas.js","../src/svgcanvas/dbox.js"],"sourcesContent":["/**\n * A jQuery module to work with SVG attributes.\n * @module jQueryAttr\n * @license MIT\n */\n\n/**\n* This fixes `$(...).attr()` to work as expected with SVG elements.\n* Does not currently use `*AttributeNS()` since we rarely need that.\n* Adds {@link external:jQuery.fn.attr}.\n* See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()`.\n*\n* Additional functionality:\n* - When getting attributes, a string that's a number is returned as type number.\n* - If an array is supplied as the first parameter, multiple values are returned\n* as an object with values for each given attribute.\n* @function module:jQueryAttr.jQueryAttr\n* @param {external:jQuery} $ The jQuery object to which to add the plug-in\n* @returns {external:jQuery}\n*/\nexport default function jQueryPluginSVG ($) {\n const proxied = $.fn.attr,\n svgns = 'http://www.w3.org/2000/svg';\n /**\n * @typedef {PlainObject<string, string|Float>} module:jQueryAttr.Attributes\n */\n /**\n * @function external:jQuery.fn.attr\n * @param {string|string[]|PlainObject<string, string>} key\n * @param {string} value\n * @returns {external:jQuery|module:jQueryAttr.Attributes}\n */\n $.fn.attr = function (key, value) {\n const len = this.length;\n if (!len) { return proxied.call(this, key, value); }\n for (let i = 0; i < len; ++i) {\n const elem = this[i];\n // set/get SVG attribute\n if (elem.namespaceURI === svgns) {\n // Setting attribute\n if (value !== undefined) {\n elem.setAttribute(key, value);\n } else if (Array.isArray(key)) {\n // Getting attributes from array\n const obj = {};\n let j = key.length;\n\n while (j--) {\n const aname = key[j];\n let attr = elem.getAttribute(aname);\n // This returns a number when appropriate\n if (attr || attr === '0') {\n attr = isNaN(attr) ? attr : (attr - 0);\n }\n obj[aname] = attr;\n }\n return obj;\n }\n if (typeof key === 'object') {\n // Setting attributes from object\n for (const [name, val] of Object.entries(key)) {\n elem.setAttribute(name, val);\n }\n // Getting attribute\n } else {\n let attr = elem.getAttribute(key);\n if (attr || attr === '0') {\n attr = isNaN(attr) ? attr : (attr - 0);\n }\n return attr;\n }\n } else {\n return proxied.call(this, key, value);\n }\n }\n return this;\n };\n return $;\n}\n","/* eslint-disable import/unambiguous */\n/* globals SVGPathSeg, SVGPathSegMovetoRel, SVGPathSegMovetoAbs,\n SVGPathSegMovetoRel, SVGPathSegLinetoRel, SVGPathSegLinetoAbs,\n SVGPathSegLinetoHorizontalRel, SVGPathSegLinetoHorizontalAbs,\n SVGPathSegLinetoVerticalRel, SVGPathSegLinetoVerticalAbs,\n SVGPathSegClosePath, SVGPathSegCurvetoCubicRel,\n SVGPathSegCurvetoCubicAbs, SVGPathSegCurvetoCubicSmoothRel,\n SVGPathSegCurvetoCubicSmoothAbs, SVGPathSegCurvetoQuadraticRel,\n SVGPathSegCurvetoQuadraticAbs, SVGPathSegCurvetoQuadraticSmoothRel,\n SVGPathSegCurvetoQuadraticSmoothAbs, SVGPathSegArcRel, SVGPathSegArcAbs */\n/**\n* SVGPathSeg API polyfill\n* https://github.com/progers/pathseg\n*\n* This is a drop-in replacement for the `SVGPathSeg` and `SVGPathSegList` APIs\n* that were removed from SVG2 ({@link https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html}),\n* including the latest spec changes which were implemented in Firefox 43 and\n* Chrome 46.\n*/\n/* eslint-disable no-shadow, class-methods-use-this, jsdoc/require-jsdoc */\n// Linting: We avoid `no-shadow` as ESLint thinks these are still available globals\n// Linting: We avoid `class-methods-use-this` as this is a polyfill that must\n// follow the conventions\n(() => {\nif (!('SVGPathSeg' in window)) {\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg\n class SVGPathSeg {\n constructor (type, typeAsLetter, owningPathSegList) {\n this.pathSegType = type;\n this.pathSegTypeAsLetter = typeAsLetter;\n this._owningPathSegList = owningPathSegList;\n }\n // Notify owning PathSegList on any changes so they can be synchronized back to the path element.\n _segmentChanged () {\n if (this._owningPathSegList) {\n this._owningPathSegList.segmentChanged(this);\n }\n }\n }\n SVGPathSeg.prototype.classname = 'SVGPathSeg';\n\n SVGPathSeg.PATHSEG_UNKNOWN = 0;\n SVGPathSeg.PATHSEG_CLOSEPATH = 1;\n SVGPathSeg.PATHSEG_MOVETO_ABS = 2;\n SVGPathSeg.PATHSEG_MOVETO_REL = 3;\n SVGPathSeg.PATHSEG_LINETO_ABS = 4;\n SVGPathSeg.PATHSEG_LINETO_REL = 5;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;\n SVGPathSeg.PATHSEG_ARC_ABS = 10;\n SVGPathSeg.PATHSEG_ARC_REL = 11;\n SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;\n SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;\n SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;\n SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;\n\n class SVGPathSegClosePath extends SVGPathSeg {\n constructor (owningPathSegList) {\n super(SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList);\n }\n toString () { return '[object SVGPathSegClosePath]'; }\n _asPathString () { return this.pathSegTypeAsLetter; }\n clone () { return new SVGPathSegClosePath(undefined); }\n }\n\n class SVGPathSegMovetoAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegMovetoAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegMovetoAbs(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegMovetoAbs.prototype, {\n x: {\n get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true\n },\n y: {\n get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true\n }\n });\n\n class SVGPathSegMovetoRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegMovetoRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegMovetoRel(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegMovetoRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegLinetoAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoAbs(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegLinetoAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegLinetoRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoRel(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegLinetoRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoCubicAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoCubicRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegArcAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {\n super(SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList);\n this._x = x;\n this._y = y;\n this._r1 = r1;\n this._r2 = r2;\n this._angle = angle;\n this._largeArcFlag = largeArcFlag;\n this._sweepFlag = sweepFlag;\n }\n toString () { return '[object SVGPathSegArcAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }\n }\n Object.defineProperties(SVGPathSegArcAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n r1: {get () { return this._r1; }, set (r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true},\n r2: {get () { return this._r2; }, set (r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true},\n angle: {get () { return this._angle; }, set (angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true},\n largeArcFlag: {get () { return this._largeArcFlag; }, set (largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true},\n sweepFlag: {get () { return this._sweepFlag; }, set (sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegArcRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {\n super(SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList);\n this._x = x;\n this._y = y;\n this._r1 = r1;\n this._r2 = r2;\n this._angle = angle;\n this._largeArcFlag = largeArcFlag;\n this._sweepFlag = sweepFlag;\n }\n toString () { return '[object SVGPathSegArcRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }\n }\n Object.defineProperties(SVGPathSegArcRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n r1: {get () { return this._r1; }, set (r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true},\n r2: {get () { return this._r2; }, set (r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true},\n angle: {get () { return this._angle; }, set (angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true},\n largeArcFlag: {get () { return this._largeArcFlag; }, set (largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true},\n sweepFlag: {get () { return this._sweepFlag; }, set (sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegLinetoHorizontalAbs extends SVGPathSeg {\n constructor (owningPathSegList, x) {\n super(SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList);\n this._x = x;\n }\n toString () { return '[object SVGPathSegLinetoHorizontalAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x; }\n clone () { return new SVGPathSegLinetoHorizontalAbs(undefined, this._x); }\n }\n Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype, 'x', {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegLinetoHorizontalRel extends SVGPathSeg {\n constructor (owningPathSegList, x) {\n super(SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList);\n this._x = x;\n }\n toString () { return '[object SVGPathSegLinetoHorizontalRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x; }\n clone () { return new SVGPathSegLinetoHorizontalRel(undefined, this._x); }\n }\n Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype, 'x', {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegLinetoVerticalAbs extends SVGPathSeg {\n constructor (owningPathSegList, y) {\n super(SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList);\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoVerticalAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoVerticalAbs(undefined, this._y); }\n }\n Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype, 'y', {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegLinetoVerticalRel extends SVGPathSeg {\n constructor (owningPathSegList, y) {\n super(SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList);\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoVerticalRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoVerticalRel(undefined, this._y); }\n }\n Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype, 'y', {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegCurvetoCubicSmoothAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicSmoothAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicSmoothAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoCubicSmoothRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicSmoothRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicSmoothRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticSmoothAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticSmoothAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticSmoothRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticSmoothRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticSmoothRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n // Add createSVGPathSeg* functions to SVGPathElement.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement.\n SVGPathElement.prototype.createSVGPathSegClosePath = function () { return new SVGPathSegClosePath(undefined); };\n SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) { return new SVGPathSegMovetoAbs(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) { return new SVGPathSegMovetoRel(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) { return new SVGPathSegLinetoAbs(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) { return new SVGPathSegLinetoRel(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); };\n SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); };\n SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); };\n SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) { return new SVGPathSegLinetoHorizontalAbs(undefined, x); };\n SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) { return new SVGPathSegLinetoHorizontalRel(undefined, x); };\n SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) { return new SVGPathSegLinetoVerticalAbs(undefined, y); };\n SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) { return new SVGPathSegLinetoVerticalRel(undefined, y); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); };\n\n if (!('getPathSegAtLength' in SVGPathElement.prototype)) {\n // Add getPathSegAtLength to SVGPathElement.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength\n // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.\n SVGPathElement.prototype.getPathSegAtLength = function (distance) {\n if (distance === undefined || !isFinite(distance)) {\n throw new Error('Invalid arguments.');\n }\n\n const measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n measurementElement.setAttribute('d', this.getAttribute('d'));\n let lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;\n\n // If the path is empty, return 0.\n if (lastPathSegment <= 0) {\n return 0;\n }\n\n do {\n measurementElement.pathSegList.removeItem(lastPathSegment);\n if (distance > measurementElement.getTotalLength()) {\n break;\n }\n lastPathSegment--;\n } while (lastPathSegment > 0);\n return lastPathSegment;\n };\n }\n\n window.SVGPathSeg = SVGPathSeg;\n window.SVGPathSegClosePath = SVGPathSegClosePath;\n window.SVGPathSegMovetoAbs = SVGPathSegMovetoAbs;\n window.SVGPathSegMovetoRel = SVGPathSegMovetoRel;\n window.SVGPathSegLinetoAbs = SVGPathSegLinetoAbs;\n window.SVGPathSegLinetoRel = SVGPathSegLinetoRel;\n window.SVGPathSegCurvetoCubicAbs = SVGPathSegCurvetoCubicAbs;\n window.SVGPathSegCurvetoCubicRel = SVGPathSegCurvetoCubicRel;\n window.SVGPathSegCurvetoQuadraticAbs = SVGPathSegCurvetoQuadraticAbs;\n window.SVGPathSegCurvetoQuadraticRel = SVGPathSegCurvetoQuadraticRel;\n window.SVGPathSegArcAbs = SVGPathSegArcAbs;\n window.SVGPathSegArcRel = SVGPathSegArcRel;\n window.SVGPathSegLinetoHorizontalAbs = SVGPathSegLinetoHorizontalAbs;\n window.SVGPathSegLinetoHorizontalRel = SVGPathSegLinetoHorizontalRel;\n window.SVGPathSegLinetoVerticalAbs = SVGPathSegLinetoVerticalAbs;\n window.SVGPathSegLinetoVerticalRel = SVGPathSegLinetoVerticalRel;\n window.SVGPathSegCurvetoCubicSmoothAbs = SVGPathSegCurvetoCubicSmoothAbs;\n window.SVGPathSegCurvetoCubicSmoothRel = SVGPathSegCurvetoCubicSmoothRel;\n window.SVGPathSegCurvetoQuadraticSmoothAbs = SVGPathSegCurvetoQuadraticSmoothAbs;\n window.SVGPathSegCurvetoQuadraticSmoothRel = SVGPathSegCurvetoQuadraticSmoothRel;\n}\n\n// Checking for SVGPathSegList in window checks for the case of an implementation without the\n// SVGPathSegList API.\n// The second check for appendItem is specific to Firefox 59+ which removed only parts of the\n// SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API\n// so the polyfill data (i.e., _list) is used throughout.\nif (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.prototype)) {\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList\n class SVGPathSegList {\n constructor (pathElement) {\n this._pathElement = pathElement;\n this._list = this._parsePath(this._pathElement.getAttribute('d'));\n\n // Use a MutationObserver to catch changes to the path's \"d\" attribute.\n this._mutationObserverConfig = {attributes: true, attributeFilter: ['d']};\n this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));\n this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);\n }\n // Process any pending mutations to the path element and update the list as needed.\n // This should be the first call of all public functions and is needed because\n // MutationObservers are not synchronous so we can have pending asynchronous mutations.\n _checkPathSynchronizedToList () {\n this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());\n }\n\n _updateListFromPathMutations (mutationRecords) {\n if (!this._pathElement) {\n return;\n }\n let hasPathMutations = false;\n mutationRecords.forEach((record) => {\n if (record.attributeName === 'd') {\n hasPathMutations = true;\n }\n });\n if (hasPathMutations) {\n this._list = this._parsePath(this._pathElement.getAttribute('d'));\n }\n }\n\n // Serialize the list and update the path's 'd' attribute.\n _writeListToPath () {\n this._pathElementMutationObserver.disconnect();\n this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list));\n this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);\n }\n\n // When a path segment changes the list needs to be synchronized back to the path element.\n segmentChanged (pathSeg) {\n this._writeListToPath();\n }\n\n clear () {\n this._checkPathSynchronizedToList();\n\n this._list.forEach((pathSeg) => {\n pathSeg._owningPathSegList = null;\n });\n this._list = [];\n this._writeListToPath();\n }\n\n initialize (newItem) {\n this._checkPathSynchronizedToList();\n\n this._list = [newItem];\n newItem._owningPathSegList = this;\n this._writeListToPath();\n return newItem;\n }\n\n _checkValidIndex (index) {\n if (isNaN(index) || index < 0 || index >= this.numberOfItems) {\n throw new Error('INDEX_SIZE_ERR');\n }\n }\n\n getItem (index) {\n this._checkPathSynchronizedToList();\n\n this._checkValidIndex(index);\n return this._list[index];\n }\n\n insertItemBefore (newItem, index) {\n this._checkPathSynchronizedToList();\n\n // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.\n if (index > this.numberOfItems) {\n index = this.numberOfItems;\n }\n if (newItem._owningPathSegList) {\n // SVG2 spec says to make a copy.\n newItem = newItem.clone();\n }\n this._list.splice(index, 0, newItem);\n newItem._owningPathSegList = this;\n this._writeListToPath();\n return newItem;\n }\n\n replaceItem (newItem, index) {\n this._checkPathSynchronizedToList();\n\n if (newItem._owningPathSegList) {\n // SVG2 spec says to make a copy.\n newItem = newItem.clone();\n }\n this._checkValidIndex(index);\n this._list[index] = newItem;\n newItem._owningPathSegList = this;\n this._writeListToPath();\n return newItem;\n }\n\n removeItem (index) {\n this._checkPathSynchronizedToList();\n\n this._checkValidIndex(index);\n const item = this._list[index];\n this._list.splice(index, 1);\n this._writeListToPath();\n return item;\n }\n\n appendItem (newItem) {\n this._checkPathSynchronizedToList();\n\n if (newItem._owningPathSegList) {\n // SVG2 spec says to make a copy.\n newItem = newItem.clone();\n }\n this._list.push(newItem);\n newItem._owningPathSegList = this;\n // TODO: Optimize this to just append to the existing attribute.\n this._writeListToPath();\n return newItem;\n }\n\n // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.\n _parsePath (string) {\n if (!string || !string.length) {\n return [];\n }\n\n const owningPathSegList = this; // eslint-disable-line consistent-this\n\n class Builder {\n constructor () {\n this.pathSegList = [];\n }\n appendSegment (pathSeg) {\n this.pathSegList.push(pathSeg);\n }\n }\n\n class Source {\n constructor (string) {\n this._string = string;\n this._currentIndex = 0;\n this._endIndex = this._string.length;\n this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN;\n\n this._skipOptionalSpaces();\n }\n _isCurrentSpace () {\n const character = this._string[this._currentIndex];\n return character <= ' ' && (character === ' ' || character === '\\n' || character === '\\t' || character === '\\r' || character === '\\f');\n }\n\n _skipOptionalSpaces () {\n while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {\n this._currentIndex++;\n }\n return this._currentIndex < this._endIndex;\n }\n\n _skipOptionalSpacesOrDelimiter () {\n if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) !== ',') {\n return false;\n }\n if (this._skipOptionalSpaces()) {\n if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === ',') {\n this._currentIndex++;\n this._skipOptionalSpaces();\n }\n }\n return this._currentIndex < this._endIndex;\n }\n\n hasMoreData () {\n return this._currentIndex < this._endIndex;\n }\n\n peekSegmentType () {\n const lookahead = this._string[this._currentIndex];\n return this._pathSegTypeFromChar(lookahead);\n }\n\n _pathSegTypeFromChar (lookahead) {\n switch (lookahead) {\n case 'Z':\n case 'z':\n return SVGPathSeg.PATHSEG_CLOSEPATH;\n case 'M':\n return SVGPathSeg.PATHSEG_MOVETO_ABS;\n case 'm':\n return SVGPathSeg.PATHSEG_MOVETO_REL;\n case 'L':\n return SVGPathSeg.PATHSEG_LINETO_ABS;\n case 'l':\n return SVGPathSeg.PATHSEG_LINETO_REL;\n case 'C':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;\n case 'c':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;\n case 'Q':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;\n case 'q':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;\n case 'A':\n return SVGPathSeg.PATHSEG_ARC_ABS;\n case 'a':\n return SVGPathSeg.PATHSEG_ARC_REL;\n case 'H':\n return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;\n case 'h':\n return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;\n case 'V':\n return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;\n case 'v':\n return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;\n case 'S':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;\n case 's':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;\n case 'T':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;\n case 't':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;\n default:\n return SVGPathSeg.PATHSEG_UNKNOWN;\n }\n }\n\n _nextCommandHelper (lookahead, previousCommand) {\n // Check for remaining coordinates in the current command.\n if ((lookahead === '+' || lookahead === '-' || lookahead === '.' || (lookahead >= '0' && lookahead <= '9')) && previousCommand !== SVGPathSeg.PATHSEG_CLOSEPATH) {\n if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_ABS) {\n return SVGPathSeg.PATHSEG_LINETO_ABS;\n }\n if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_REL) {\n return SVGPathSeg.PATHSEG_LINETO_REL;\n }\n return previousCommand;\n }\n return SVGPathSeg.PATHSEG_UNKNOWN;\n }\n\n initialCommandIsMoveTo () {\n // If the path is empty it is still valid, so return true.\n if (!this.hasMoreData()) {\n return true;\n }\n const command = this.peekSegmentType();\n // Path must start with moveTo.\n return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL;\n }\n\n // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF\n _parseNumber () {\n let exponent = 0;\n let integer = 0;\n let frac = 1;\n let decimal = 0;\n let sign = 1;\n let expsign = 1;\n\n const startIndex = this._currentIndex;\n\n this._skipOptionalSpaces();\n\n // Read the sign.\n if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '+') {\n this._currentIndex++;\n } else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '-') {\n this._currentIndex++;\n sign = -1;\n }\n\n if (this._currentIndex === this._endIndex || ((this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') && this._string.charAt(this._currentIndex) !== '.')) {\n // The first character of a number must be one of [0-9+-.].\n return undefined;\n }\n\n // Read the integer part, build right-to-left.\n const startIntPartIndex = this._currentIndex;\n while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {\n this._currentIndex++; // Advance to first non-digit.\n }\n\n if (this._currentIndex !== startIntPartIndex) {\n let scanIntPartIndex = this._currentIndex - 1;\n let multiplier = 1;\n while (scanIntPartIndex >= startIntPartIndex) {\n integer += multiplier * (this._string.charAt(scanIntPartIndex--) - '0');\n multiplier *= 10;\n }\n }\n\n // Read the decimals.\n if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '.') {\n this._currentIndex++;\n\n // There must be a least one digit following the .\n if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') {\n return undefined;\n }\n while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {\n frac *= 10;\n decimal += (this._string.charAt(this._currentIndex) - '0') / frac;\n this._currentIndex += 1;\n }\n }\n\n // Read the exponent part.\n if (this._currentIndex !== startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) === 'e' || this._string.charAt(this._currentIndex) === 'E') && (this._string.charAt(this._currentIndex + 1) !== 'x' && this._string.charAt(this._currentIndex + 1) !== 'm')) {\n this._currentIndex++;\n\n // Read the sign of the exponent.\n if (this._string.charAt(this._currentIndex) === '+') {\n this._currentIndex++;\n } else if (this._string.charAt(this._currentIndex) === '-') {\n this._currentIndex++;\n expsign = -1;\n }\n\n // There must be an exponent.\n if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') {\n return undefined;\n }\n\n while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {\n exponent *= 10;\n exponent += (this._string.charAt(this._currentIndex) - '0');\n this._currentIndex++;\n }\n }\n\n let number = integer + decimal;\n number *= sign;\n\n if (exponent) {\n number *= 10 ** (expsign * exponent);\n }\n\n if (startIndex === this._currentIndex) {\n return undefined;\n }\n\n this._skipOptionalSpacesOrDelimiter();\n\n return number;\n }\n\n _parseArcFlag () {\n if (this._currentIndex >= this._endIndex) {\n return undefined;\n }\n let flag = false;\n const flagChar = this._string.charAt(this._currentIndex++);\n if (flagChar === '0') {\n flag = false;\n } else if (flagChar === '1') {\n flag = true;\n } else {\n return undefined;\n }\n\n this._skipOptionalSpacesOrDelimiter();\n return flag;\n }\n\n parseSegment () {\n const lookahead = this._string[this._currentIndex];\n let command = this._pathSegTypeFromChar(lookahead);\n if (command === SVGPathSeg.PATHSEG_UNKNOWN) {\n // Possibly an implicit command. Not allowed if this is the first command.\n if (this._previousCommand === SVGPathSeg.PATHSEG_UNKNOWN) {\n return null;\n }\n command = this._nextCommandHelper(lookahead, this._previousCommand);\n if (command === SVGPathSeg.PATHSEG_UNKNOWN) {\n return null;\n }\n } else {\n this._currentIndex++;\n }\n\n this._previousCommand = command;\n\n switch (command) {\n case SVGPathSeg.PATHSEG_MOVETO_REL:\n return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_MOVETO_ABS:\n return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_REL:\n return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_ABS:\n return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:\n return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:\n return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:\n return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:\n return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_CLOSEPATH:\n this._skipOptionalSpaces();\n return new SVGPathSegClosePath(owningPathSegList);\n case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: {\n const points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: {\n const points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);\n } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);\n } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:\n return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:\n return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_ARC_REL: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);\n } case SVGPathSeg.PATHSEG_ARC_ABS: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);\n } default:\n throw new Error('Unknown path seg type.');\n }\n }\n }\n\n const builder = new Builder();\n const source = new Source(string);\n\n if (!source.initialCommandIsMoveTo()) {\n return [];\n }\n while (source.hasMoreData()) {\n const pathSeg = source.parseSegment();\n if (!pathSeg) {\n return [];\n }\n builder.appendSegment(pathSeg);\n }\n\n return builder.pathSegList;\n }\n\n // STATIC\n static _pathSegArrayAsString (pathSegArray) {\n let string = '';\n let first = true;\n pathSegArray.forEach((pathSeg) => {\n if (first) {\n first = false;\n string += pathSeg._asPathString();\n } else {\n string += ' ' + pathSeg._asPathString();\n }\n });\n return string;\n }\n }\n\n SVGPathSegList.prototype.classname = 'SVGPathSegList';\n\n Object.defineProperty(SVGPathSegList.prototype, 'numberOfItems', {\n get () {\n this._checkPathSynchronizedToList();\n return this._list.length;\n },\n enumerable: true\n });\n\n // Add the pathSegList accessors to SVGPathElement.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData\n Object.defineProperties(SVGPathElement.prototype, {\n pathSegList: {\n get () {\n if (!this._pathSegList) {\n this._pathSegList = new SVGPathSegList(this);\n }\n return this._pathSegList;\n },\n enumerable: true\n },\n // TODO: The following are not implemented and simply return SVGPathElement.pathSegList.\n normalizedPathSegList: {get () { return this.pathSegList; }, enumerable: true},\n animatedPathSegList: {get () { return this.pathSegList; }, enumerable: true},\n animatedNormalizedPathSegList: {get () { return this.pathSegList; }, enumerable: true}\n });\n window.SVGPathSegList = SVGPathSegList;\n}\n})();\n","/**\n * Namespaces or tools therefor.\n * @module namespaces\n * @license MIT\n*/\n\n/**\n* Common namepaces constants in alpha order.\n* @enum {string}\n* @type {PlainObject}\n* @memberof module:namespaces\n*/\nexport const NS = {\n HTML: 'http://www.w3.org/1999/xhtml',\n MATH: 'http://www.w3.org/1998/Math/MathML',\n SE: 'http://svg-edit.googlecode.com',\n SVG: 'http://www.w3.org/2000/svg',\n XLINK: 'http://www.w3.org/1999/xlink',\n XML: 'http://www.w3.org/XML/1998/namespace',\n XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved\n};\n\n/**\n* @function module:namespaces.getReverseNS\n* @returns {string} The NS with key values switched and lowercase\n*/\nexport const getReverseNS = function () {\n const reverseNS = {};\n Object.entries(NS).forEach(([name, URI]) => {\n reverseNS[URI] = name.toLowerCase();\n });\n return reverseNS;\n};\n","/* globals jQuery */\n/**\n * Browser detection.\n * @module browser\n * @license MIT\n *\n * @copyright 2010 Jeff Schiller, 2010 Alexis Deveria\n */\n\n// Dependencies:\n// 1) jQuery (for $.alert())\n\nimport './svgpathseg.js';\nimport {NS} from './namespaces.js';\n\nconst $ = jQuery;\n\nconst supportsSVG_ = (function () {\nreturn Boolean(document.createElementNS && document.createElementNS(NS.SVG, 'svg').createSVGRect);\n}());\n\n/**\n * @function module:browser.supportsSvg\n * @returns {boolean}\n*/\nexport const supportsSvg = () => supportsSVG_;\n\nconst {userAgent} = navigator;\nconst svg = document.createElementNS(NS.SVG, 'svg');\n\n// Note: Browser sniffing should only be used if no other detection method is possible\nconst isOpera_ = Boolean(window.opera);\nconst isWebkit_ = userAgent.includes('AppleWebKit');\nconst isGecko_ = userAgent.includes('Gecko/');\nconst isIE_ = userAgent.includes('MSIE');\nconst isChrome_ = userAgent.includes('Chrome/');\nconst isWindows_ = userAgent.includes('Windows');\nconst isMac_ = userAgent.includes('Macintosh');\nconst isTouch_ = 'ontouchstart' in window;\n\nconst supportsSelectors_ = (function () {\nreturn Boolean(svg.querySelector);\n}());\n\nconst supportsXpath_ = (function () {\nreturn Boolean(document.evaluate);\n}());\n\n// segList functions (for FF1.5 and 2.0)\nconst supportsPathReplaceItem_ = (function () {\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 10,10');\nconst seglist = path.pathSegList;\nconst seg = path.createSVGPathSegLinetoAbs(5, 5);\ntry {\n seglist.replaceItem(seg, 1);\n return true;\n} catch (err) {}\nreturn false;\n}());\n\nconst supportsPathInsertItemBefore_ = (function () {\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 10,10');\nconst seglist = path.pathSegList;\nconst seg = path.createSVGPathSegLinetoAbs(5, 5);\ntry {\n seglist.insertItemBefore(seg, 1);\n return true;\n} catch (err) {}\nreturn false;\n}());\n\n// text character positioning (for IE9 and now Chrome)\nconst supportsGoodTextCharPos_ = (function () {\nconst svgroot = document.createElementNS(NS.SVG, 'svg');\nconst svgcontent = document.createElementNS(NS.SVG, 'svg');\ndocument.documentElement.append(svgroot);\nsvgcontent.setAttribute('x', 5);\nsvgroot.append(svgcontent);\nconst text = document.createElementNS(NS.SVG, 'text');\ntext.textContent = 'a';\nsvgcontent.append(text);\ntry { // Chrome now fails here\n const pos = text.getStartPositionOfChar(0).x;\n return (pos === 0);\n} catch (err) {\n return false;\n} finally {\n svgroot.remove();\n}\n}());\n\nconst supportsPathBBox_ = (function () {\nconst svgcontent = document.createElementNS(NS.SVG, 'svg');\ndocument.documentElement.append(svgcontent);\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 C0,0 10,10 10,0');\nsvgcontent.append(path);\nconst bbox = path.getBBox();\nsvgcontent.remove();\nreturn (bbox.height > 4 && bbox.height < 5);\n}());\n\n// Support for correct bbox sizing on groups with horizontal/vertical lines\nconst supportsHVLineContainerBBox_ = (function () {\nconst svgcontent = document.createElementNS(NS.SVG, 'svg');\ndocument.documentElement.append(svgcontent);\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 10,0');\nconst path2 = document.createElementNS(NS.SVG, 'path');\npath2.setAttribute('d', 'M5,0 15,0');\nconst g = document.createElementNS(NS.SVG, 'g');\ng.append(path, path2);\nsvgcontent.append(g);\nconst bbox = g.getBBox();\nsvgcontent.remove();\n// Webkit gives 0, FF gives 10, Opera (correctly) gives 15\nreturn (bbox.width === 15);\n}());\n\nconst supportsEditableText_ = (function () {\n// TODO: Find better way to check support for this\nreturn isOpera_;\n}());\n\nconst supportsGoodDecimals_ = (function () {\n// Correct decimals on clone attributes (Opera < 10.5/win/non-en)\nconst rect = document.createElementNS(NS.SVG, 'rect');\nrect.setAttribute('x', 0.1);\nconst crect = rect.cloneNode(false);\nconst retValue = (!crect.getAttribute('x').includes(','));\nif (!retValue) {\n // Todo: i18nize or remove\n $.alert(\n 'NOTE: This version of Opera is known to contain bugs in SVG-edit.\\n' +\n 'Please upgrade to the <a href=\"http://opera.com\">latest version</a> in which the problems have been fixed.'\n );\n}\nreturn retValue;\n}());\n\nconst supportsNonScalingStroke_ = (function () {\nconst rect = document.createElementNS(NS.SVG, 'rect');\nrect.setAttribute('style', 'vector-effect:non-scaling-stroke');\nreturn rect.style.vectorEffect === 'non-scaling-stroke';\n}());\n\nlet supportsNativeSVGTransformLists_ = (function () {\nconst rect = document.createElementNS(NS.SVG, 'rect');\nconst rxform = rect.transform.baseVal;\nconst t1 = svg.createSVGTransform();\nrxform.appendItem(t1);\nconst r1 = rxform.getItem(0);\nconst isSVGTransform = (o) => {\n // https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform\n return o && typeof o === 'object' && typeof o.setMatrix === 'function' && 'angle' in o;\n};\nreturn isSVGTransform(r1) && isSVGTransform(t1) &&\n r1.type === t1.type && r1.angle === t1.angle &&\n r1.matrix.a === t1.matrix.a &&\n r1.matrix.b === t1.matrix.b &&\n r1.matrix.c === t1.matrix.c &&\n r1.matrix.d === t1.matrix.d &&\n r1.matrix.e === t1.matrix.e &&\n r1.matrix.f === t1.matrix.f;\n}());\n\n// Public API\n\n/**\n * @function module:browser.isOpera\n * @returns {boolean}\n*/\nexport const isOpera = () => isOpera_;\n/**\n * @function module:browser.isWebkit\n * @returns {boolean}\n*/\nexport const isWebkit = () => isWebkit_;\n/**\n * @function module:browser.isGecko\n * @returns {boolean}\n*/\nexport const isGecko = () => isGecko_;\n/**\n * @function module:browser.isIE\n * @returns {boolean}\n*/\nexport const isIE = () => isIE_;\n/**\n * @function module:browser.isChrome\n * @returns {boolean}\n*/\nexport const isChrome = () => isChrome_;\n/**\n * @function module:browser.isWindows\n * @returns {boolean}\n*/\nexport const isWindows = () => isWindows_;\n/**\n * @function module:browser.isMac\n * @returns {boolean}\n*/\nexport const isMac = () => isMac_;\n/**\n * @function module:browser.isTouch\n * @returns {boolean}\n*/\nexport const isTouch = () => isTouch_;\n\n/**\n * @function module:browser.supportsSelectors\n * @returns {boolean}\n*/\nexport const supportsSelectors = () => supportsSelectors_;\n\n/**\n * @function module:browser.supportsXpath\n * @returns {boolean}\n*/\nexport const supportsXpath = () => supportsXpath_;\n\n/**\n * @function module:browser.supportsPathReplaceItem\n * @returns {boolean}\n*/\nexport const supportsPathReplaceItem = () => supportsPathReplaceItem_;\n\n/**\n * @function module:browser.supportsPathInsertItemBefore\n * @returns {boolean}\n*/\nexport const supportsPathInsertItemBefore = () => supportsPathInsertItemBefore_;\n\n/**\n * @function module:browser.supportsPathBBox\n * @returns {boolean}\n*/\nexport const supportsPathBBox = () => supportsPathBBox_;\n\n/**\n * @function module:browser.supportsHVLineContainerBBox\n * @returns {boolean}\n*/\nexport const supportsHVLineContainerBBox = () => supportsHVLineContainerBBox_;\n\n/**\n * @function module:browser.supportsGoodTextCharPos\n * @returns {boolean}\n*/\nexport const supportsGoodTextCharPos = () => supportsGoodTextCharPos_;\n\n/**\n* @function module:browser.supportsEditableText\n * @returns {boolean}\n*/\nexport const supportsEditableText = () => supportsEditableText_;\n\n/**\n * @function module:browser.supportsGoodDecimals\n * @returns {boolean}\n*/\nexport const supportsGoodDecimals = () => supportsGoodDecimals_;\n\n/**\n* @function module:browser.supportsNonScalingStroke\n* @returns {boolean}\n*/\nexport const supportsNonScalingStroke = () => supportsNonScalingStroke_;\n\n/**\n* @function module:browser.supportsNativeTransformLists\n* @returns {boolean}\n*/\nexport const supportsNativeTransformLists = () => supportsNativeSVGTransformLists_;\n\n/**\n * Set `supportsNativeSVGTransformLists_` to `false` (for unit testing).\n * @function module:browser.disableSupportsNativeTransformLists\n * @returns {void}\n*/\nexport const disableSupportsNativeTransformLists = () => {\n supportsNativeSVGTransformLists_ = false;\n};\n","/**\n * Partial polyfill of `SVGTransformList`\n * @module SVGTransformList\n *\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {NS} from './namespaces.js';\nimport {supportsNativeTransformLists} from './browser.js';\n\nconst svgroot = document.createElementNS(NS.SVG, 'svg');\n\n/**\n * Helper function to convert `SVGTransform` to a string.\n * @param {SVGTransform} xform\n * @returns {string}\n */\nfunction transformToString (xform) {\n const m = xform.matrix;\n let text = '';\n switch (xform.type) {\n case 1: // MATRIX\n text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';\n break;\n case 2: // TRANSLATE\n text = 'translate(' + m.e + ',' + m.f + ')';\n break;\n case 3: // SCALE\n if (m.a === m.d) {\n text = 'scale(' + m.a + ')';\n } else {\n text = 'scale(' + m.a + ',' + m.d + ')';\n }\n break;\n case 4: { // ROTATE\n let cx = 0;\n let cy = 0;\n // this prevents divide by zero\n if (xform.angle !== 0) {\n const K = 1 - m.a;\n cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);\n cx = (m.e - m.b * cy) / K;\n }\n text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';\n break;\n }\n }\n return text;\n}\n\n/**\n * Map of SVGTransformList objects.\n */\nlet listMap_ = {};\n\n/**\n* @interface module:SVGTransformList.SVGEditTransformList\n* @property {Integer} numberOfItems unsigned long\n*/\n/**\n* @function module:SVGTransformList.SVGEditTransformList#clear\n* @returns {void}\n*/\n/**\n* @function module:SVGTransformList.SVGEditTransformList#initialize\n* @param {SVGTransform} newItem\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#getItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#insertItemBefore\n* @param {SVGTransform} newItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#replaceItem\n* @param {SVGTransform} newItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#removeItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* @function module:SVGTransformList.SVGEditTransformList#appendItem\n* @param {SVGTransform} newItem\n* @returns {SVGTransform}\n*/\n/**\n* NOT IMPLEMENTED.\n* @ignore\n* @function module:SVGTransformList.SVGEditTransformList#createSVGTransformFromMatrix\n* @param {SVGMatrix} matrix\n* @returns {SVGTransform}\n*/\n/**\n* NOT IMPLEMENTED.\n* @ignore\n* @function module:SVGTransformList.SVGEditTransformList#consolidate\n* @returns {SVGTransform}\n*/\n\n/**\n* SVGTransformList implementation for Webkit.\n* These methods do not currently raise any exceptions.\n* These methods also do not check that transforms are being inserted. This is basically\n* implementing as much of SVGTransformList that we need to get the job done.\n* @implements {module:SVGTransformList.SVGEditTransformList}\n*/\nexport class SVGTransformList { // eslint-disable-line no-shadow\n /**\n * @param {Element} elem\n * @returns {SVGTransformList}\n */\n constructor (elem) {\n this._elem = elem || null;\n this._xforms = [];\n // TODO: how do we capture the undo-ability in the changed transform list?\n this._update = function () {\n let tstr = '';\n // /* const concatMatrix = */ svgroot.createSVGMatrix();\n for (let i = 0; i < this.numberOfItems; ++i) {\n const xform = this._list.getItem(i);\n tstr += transformToString(xform) + ' ';\n }\n this._elem.setAttribute('transform', tstr);\n };\n this._list = this;\n this._init = function () {\n // Transform attribute parser\n let str = this._elem.getAttribute('transform');\n if (!str) { return; }\n\n // TODO: Add skew support in future\n const re = /\\s*((scale|matrix|rotate|translate)\\s*\\(.*?\\))\\s*,?\\s*/;\n // const re = /\\s*(?<xform>(?:scale|matrix|rotate|translate)\\s*\\(.*?\\))\\s*,?\\s*/;\n let m = true;\n while (m) {\n m = str.match(re);\n str = str.replace(re, '');\n if (m && m[1]) {\n const x = m[1];\n const bits = x.split(/\\s*\\(/);\n const name = bits[0];\n const valBits = bits[1].match(/\\s*(.*?)\\s*\\)/);\n valBits[1] = valBits[1].replace(/(\\d)-/g, '$1 -');\n const valArr = valBits[1].split(/[, ]+/);\n const letters = 'abcdef'.split('');\n /*\n if (m && m.groups.xform) {\n const x = m.groups.xform;\n const [name, bits] = x.split(/\\s*\\(/);\n const valBits = bits.match(/\\s*(?<nonWhitespace>.*?)\\s*\\)/);\n valBits.groups.nonWhitespace = valBits.groups.nonWhitespace.replace(\n /(?<digit>\\d)-/g, '$<digit> -'\n );\n const valArr = valBits.groups.nonWhitespace.split(/[, ]+/);\n const letters = [...'abcdef'];\n */\n const mtx = svgroot.createSVGMatrix();\n Object.values(valArr).forEach(function (item, i) {\n valArr[i] = Number.parseFloat(item);\n if (name === 'matrix') {\n mtx[letters[i]] = valArr[i];\n }\n });\n const xform = svgroot.createSVGTransform();\n const fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);\n const values = name === 'matrix' ? [mtx] : valArr;\n\n if (name === 'scale' && values.length === 1) {\n values.push(values[0]);\n } else if (name === 'translate' && values.length === 1) {\n values.push(0);\n } else if (name === 'rotate' && values.length === 1) {\n values.push(0, 0);\n }\n xform[fname](...values);\n this._list.appendItem(xform);\n }\n }\n };\n this._removeFromOtherLists = function (item) {\n if (item) {\n // Check if this transform is already in a transformlist, and\n // remove it if so.\n Object.values(listMap_).some((tl) => {\n for (let i = 0, len = tl._xforms.length; i < len; ++i) {\n if (tl._xforms[i] === item) {\n tl.removeItem(i);\n return true;\n }\n }\n return false;\n });\n }\n };\n\n this.numberOfItems = 0;\n }\n /**\n * @returns {void}\n */\n clear () {\n this.numberOfItems = 0;\n this._xforms = [];\n }\n\n /**\n * @param {SVGTransform} newItem\n * @returns {void}\n */\n initialize (newItem) {\n this.numberOfItems = 1;\n this._removeFromOtherLists(newItem);\n this._xforms = [newItem];\n }\n\n /**\n * @param {Integer} index unsigned long\n * @throws {Error}\n * @returns {SVGTransform}\n */\n getItem (index) {\n if (index < this.numberOfItems && index >= 0) {\n return this._xforms[index];\n }\n const err = new Error('DOMException with code=INDEX_SIZE_ERR');\n err.code = 1;\n throw err;\n }\n\n /**\n * @param {SVGTransform} newItem\n * @param {Integer} index unsigned long\n * @returns {SVGTransform}\n */\n insertItemBefore (newItem, index) {\n let retValue = null;\n if (index >= 0) {\n if (index < this.numberOfItems) {\n this._removeFromOtherLists(newItem);\n const newxforms = new Array(this.numberOfItems + 1);\n // TODO: use array copying and slicing\n let i;\n for (i = 0; i < index; ++i) {\n newxforms[i] = this._xforms[i];\n }\n newxforms[i] = newItem;\n for (let j = i + 1; i < this.numberOfItems; ++j, ++i) {\n newxforms[j] = this._xforms[i];\n }\n this.numberOfItems++;\n this._xforms = newxforms;\n retValue = newItem;\n this._list._update();\n } else {\n retValue = this._list.appendItem(newItem);\n }\n }\n return retValue;\n }\n\n /**\n * @param {SVGTransform} newItem\n * @param {Integer} index unsigned long\n * @returns {SVGTransform}\n */\n replaceItem (newItem, index) {\n let retValue = null;\n if (index < this.numberOfItems && index >= 0) {\n this._removeFromOtherLists(newItem);\n this._xforms[index] = newItem;\n retValue = newItem;\n this._list._update();\n }\n return retValue;\n }\n\n /**\n * @param {Integer} index unsigned long\n * @throws {Error}\n * @returns {SVGTransform}\n */\n removeItem (index) {\n if (index < this.numberOfItems && index >= 0) {\n const retValue = this._xforms[index];\n const newxforms = new Array(this.numberOfItems - 1);\n let i;\n for (i = 0; i < index; ++i) {\n newxforms[i] = this._xforms[i];\n }\n for (let j = i; j < this.numberOfItems - 1; ++j, ++i) {\n newxforms[j] = this._xforms[i + 1];\n }\n this.numberOfItems--;\n this._xforms = newxforms;\n this._list._update();\n return retValue;\n }\n const err = new Error('DOMException with code=INDEX_SIZE_ERR');\n err.code = 1;\n throw err;\n }\n\n /**\n * @param {SVGTransform} newItem\n * @returns {SVGTransform}\n */\n appendItem (newItem) {\n this._removeFromOtherLists(newItem);\n this._xforms.push(newItem);\n this.numberOfItems++;\n this._list._update();\n return newItem;\n }\n}\n\n/**\n* @function module:SVGTransformList.resetListMap\n* @returns {void}\n*/\nexport const resetListMap = function () {\n listMap_ = {};\n};\n\n/**\n * Removes transforms of the given element from the map.\n * @function module:SVGTransformList.removeElementFromListMap\n * @param {Element} elem - a DOM Element\n * @returns {void}\n */\nexport let removeElementFromListMap = function (elem) { // eslint-disable-line import/no-mutable-exports\n if (elem.id && listMap_[elem.id]) {\n delete listMap_[elem.id];\n }\n};\n\n/**\n* Returns an object that behaves like a `SVGTransformList` for the given DOM element.\n* @function module:SVGTransformList.getTransformList\n* @param {Element} elem - DOM element to get a transformlist from\n* @todo The polyfill should have `SVGAnimatedTransformList` and this should use it\n* @returns {SVGAnimatedTransformList|SVGTransformList}\n*/\nexport const getTransformList = function (elem) {\n if (!supportsNativeTransformLists()) {\n const id = elem.id || 'temp';\n let t = listMap_[id];\n if (!t || id === 'temp') {\n listMap_[id] = new SVGTransformList(elem);\n listMap_[id]._init();\n t = listMap_[id];\n }\n return t;\n }\n if (elem.transform) {\n return elem.transform.baseVal;\n }\n if (elem.gradientTransform) {\n return elem.gradientTransform.baseVal;\n }\n if (elem.patternTransform) {\n return elem.patternTransform.baseVal;\n }\n\n return null;\n};\n\n/**\n* @callback module:SVGTransformList.removeElementFromListMap\n* @param {Element} elem\n* @returns {void}\n*/\n/**\n* Replace `removeElementFromListMap` for unit-testing.\n* @function module:SVGTransformList.changeRemoveElementFromListMap\n* @param {module:SVGTransformList.removeElementFromListMap} cb Passed a single argument `elem`\n* @returns {void}\n*/\n\nexport const changeRemoveElementFromListMap = function (cb) { // eslint-disable-line promise/prefer-await-to-callbacks\n removeElementFromListMap = cb;\n};\n","/**\n * Mathematical utilities.\n * @module math\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\n/**\n* @typedef {PlainObject} module:math.AngleCoord45\n* @property {Float} x - The angle-snapped x value\n* @property {Float} y - The angle-snapped y value\n* @property {Integer} a - The angle at which to snap\n*/\n\n/**\n* @typedef {PlainObject} module:math.XYObject\n* @property {Float} x\n* @property {Float} y\n*/\n\nimport {NS} from './namespaces.js';\nimport {getTransformList} from './svgtransformlist.js';\nimport {isNullish} from './utilities.js';\n\n// Constants\nconst NEAR_ZERO = 1e-14;\n\n// Throw away SVGSVGElement used for creating matrices/transforms.\nconst svg = document.createElementNS(NS.SVG, 'svg');\n\n/**\n * A (hopefully) quicker function to transform a point by a matrix\n * (this function avoids any DOM calls and just does the math).\n * @function module:math.transformPoint\n * @param {Float} x - Float representing the x coordinate\n * @param {Float} y - Float representing the y coordinate\n * @param {SVGMatrix} m - Matrix object to transform the point with\n * @returns {module:math.XYObject} An x, y object representing the transformed point\n*/\nexport const transformPoint = function (x, y, m) {\n return {x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};\n};\n\n/**\n * Helper function to check if the matrix performs no actual transform\n * (i.e. exists for identity purposes).\n * @function module:math.isIdentity\n * @param {SVGMatrix} m - The matrix object to check\n * @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0\n*/\nexport const isIdentity = function (m) {\n return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);\n};\n\n/**\n * This function tries to return a `SVGMatrix` that is the multiplication `m1 * m2`.\n * We also round to zero when it's near zero.\n * @function module:math.matrixMultiply\n * @param {...SVGMatrix} args - Matrix objects to multiply\n * @returns {SVGMatrix} The matrix object resulting from the calculation\n*/\nexport const matrixMultiply = function (...args) {\n const m = args.reduceRight((prev, m1) => {\n return m1.multiply(prev);\n });\n\n if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; }\n if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; }\n if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; }\n if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; }\n if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; }\n if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; }\n\n return m;\n};\n\n/**\n * See if the given transformlist includes a non-indentity matrix transform.\n * @function module:math.hasMatrixTransform\n * @param {SVGTransformList} [tlist] - The transformlist to check\n * @returns {boolean} Whether or not a matrix transform was found\n*/\nexport const hasMatrixTransform = function (tlist) {\n if (!tlist) { return false; }\n let num = tlist.numberOfItems;\n while (num--) {\n const xform = tlist.getItem(num);\n if (xform.type === 1 && !isIdentity(xform.matrix)) { return true; }\n }\n return false;\n};\n\n/**\n* @typedef {PlainObject} module:math.TransformedBox An object with the following values\n* @property {module:math.XYObject} tl - The top left coordinate\n* @property {module:math.XYObject} tr - The top right coordinate\n* @property {module:math.XYObject} bl - The bottom left coordinate\n* @property {module:math.XYObject} br - The bottom right coordinate\n* @property {PlainObject} aabox - Object with the following values:\n* @property {Float} aabox.x - Float with the axis-aligned x coordinate\n* @property {Float} aabox.y - Float with the axis-aligned y coordinate\n* @property {Float} aabox.width - Float with the axis-aligned width coordinate\n* @property {Float} aabox.height - Float with the axis-aligned height coordinate\n*/\n\n/**\n * Transforms a rectangle based on the given matrix.\n * @function module:math.transformBox\n * @param {Float} l - Float with the box's left coordinate\n * @param {Float} t - Float with the box's top coordinate\n * @param {Float} w - Float with the box width\n * @param {Float} h - Float with the box height\n * @param {SVGMatrix} m - Matrix object to transform the box by\n * @returns {module:math.TransformedBox}\n*/\nexport const transformBox = function (l, t, w, h, m) {\n const tl = transformPoint(l, t, m),\n tr = transformPoint((l + w), t, m),\n bl = transformPoint(l, (t + h), m),\n br = transformPoint((l + w), (t + h), m),\n\n minx = Math.min(tl.x, tr.x, bl.x, br.x),\n maxx = Math.max(tl.x, tr.x, bl.x, br.x),\n miny = Math.min(tl.y, tr.y, bl.y, br.y),\n maxy = Math.max(tl.y, tr.y, bl.y, br.y);\n\n return {\n tl,\n tr,\n bl,\n br,\n aabox: {\n x: minx,\n y: miny,\n width: (maxx - minx),\n height: (maxy - miny)\n }\n };\n};\n\n/**\n * This returns a single matrix Transform for a given Transform List\n * (this is the equivalent of `SVGTransformList.consolidate()` but unlike\n * that method, this one does not modify the actual `SVGTransformList`).\n * This function is very liberal with its `min`, `max` arguments.\n * @function module:math.transformListToTransform\n * @param {SVGTransformList} tlist - The transformlist object\n * @param {Integer} [min=0] - Optional integer indicating start transform position\n * @param {Integer} [max] - Optional integer indicating end transform position;\n * defaults to one less than the tlist's `numberOfItems`\n * @returns {SVGTransform} A single matrix transform object\n*/\nexport const transformListToTransform = function (tlist, min, max) {\n if (isNullish(tlist)) {\n // Or should tlist = null have been prevented before this?\n return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());\n }\n min = min || 0;\n max = max || (tlist.numberOfItems - 1);\n min = Number.parseInt(min);\n max = Number.parseInt(max);\n if (min > max) { const temp = max; max = min; min = temp; }\n let m = svg.createSVGMatrix();\n for (let i = min; i <= max; ++i) {\n // if our indices are out of range, just use a harmless identity matrix\n const mtom = (i >= 0 && i < tlist.numberOfItems\n ? tlist.getItem(i).matrix\n : svg.createSVGMatrix());\n m = matrixMultiply(m, mtom);\n }\n return svg.createSVGTransformFromMatrix(m);\n};\n\n/**\n * Get the matrix object for a given element.\n * @function module:math.getMatrix\n * @param {Element} elem - The DOM element to check\n * @returns {SVGMatrix} The matrix object associated with the element's transformlist\n*/\nexport const getMatrix = function (elem) {\n const tlist = getTransformList(elem);\n return transformListToTransform(tlist).matrix;\n};\n\n/**\n * Returns a 45 degree angle coordinate associated with the two given\n * coordinates.\n * @function module:math.snapToAngle\n * @param {Integer} x1 - First coordinate's x value\n * @param {Integer} y1 - First coordinate's y value\n * @param {Integer} x2 - Second coordinate's x value\n * @param {Integer} y2 - Second coordinate's y value\n * @returns {module:math.AngleCoord45}\n*/\nexport const snapToAngle = function (x1, y1, x2, y2) {\n const snap = Math.PI / 4; // 45 degrees\n const dx = x2 - x1;\n const dy = y2 - y1;\n const angle = Math.atan2(dy, dx);\n const dist = Math.sqrt(dx * dx + dy * dy);\n const snapangle = Math.round(angle / snap) * snap;\n\n return {\n x: x1 + dist * Math.cos(snapangle),\n y: y1 + dist * Math.sin(snapangle),\n a: snapangle\n };\n};\n\n/**\n * Check if two rectangles (BBoxes objects) intersect each other.\n * @function module:math.rectsIntersect\n * @param {SVGRect} r1 - The first BBox-like object\n * @param {SVGRect} r2 - The second BBox-like object\n * @returns {boolean} True if rectangles intersect\n */\nexport const rectsIntersect = function (r1, r2) {\n return r2.x < (r1.x + r1.width) &&\n (r2.x + r2.width) > r1.x &&\n r2.y < (r1.y + r1.height) &&\n (r2.y + r2.height) > r1.y;\n};\n","/* eslint-disable node/no-unsupported-features/node-builtins */\n/* globals jQuery */\n/**\n * Miscellaneous utilities.\n * @module utilities\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport './svgpathseg.js';\nimport jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport {NS} from './namespaces.js';\nimport {getTransformList} from './svgtransformlist.js';\nimport {setUnitAttr, getTypeMap} from './units.js';\nimport {\n hasMatrixTransform, transformListToTransform, transformBox\n} from './math.js';\nimport {\n isWebkit, supportsHVLineContainerBBox, supportsPathBBox, supportsXpath,\n supportsSelectors\n} from './browser.js';\n\n// Constants\nconst $ = jQueryPluginSVG(jQuery);\n\n// String used to encode base64.\nconst KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\n// Much faster than running getBBox() every time\nconst visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use,clipPath';\nconst visElemsArr = visElems.split(',');\n// const hidElems = 'defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath';\n\nlet editorContext_ = null;\nlet domdoc_ = null;\nlet domcontainer_ = null;\nlet svgroot_ = null;\n\n/**\n* Object with the following keys/values.\n* @typedef {PlainObject} module:utilities.SVGElementJSON\n* @property {string} element - Tag name of the SVG element to create\n* @property {PlainObject<string, string>} attr - Has key-value attributes to assign to the new element. An `id` should be set so that {@link module:utilities.EditorContext#addSVGElementFromJson} can later re-identify the element for modification or replacement.\n* @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first\n* @property {module:utilities.SVGElementJSON[]} [children] - Data objects to be added recursively as children\n* @property {string} [namespace=\"http://www.w3.org/2000/svg\"] - Indicate a (non-SVG) namespace\n*/\n\n/**\n * An object that creates SVG elements for the canvas.\n *\n * @interface module:utilities.EditorContext\n * @property {module:path.pathActions} pathActions\n */\n/**\n * @function module:utilities.EditorContext#getSVGContent\n * @returns {SVGSVGElement}\n */\n/**\n * Create a new SVG element based on the given object keys/values and add it\n * to the current layer.\n * The element will be run through `cleanupElement` before being returned.\n * @function module:utilities.EditorContext#addSVGElementFromJson\n * @param {module:utilities.SVGElementJSON} data\n * @returns {Element} The new element\n*/\n/**\n * @function module:utilities.EditorContext#getSelectedElements\n * @returns {Element[]} the array with selected DOM elements\n*/\n/**\n * @function module:utilities.EditorContext#getDOMDocument\n * @returns {HTMLDocument}\n*/\n/**\n * @function module:utilities.EditorContext#getDOMContainer\n * @returns {HTMLElement}\n*/\n/**\n * @function module:utilities.EditorContext#getSVGRoot\n * @returns {SVGSVGElement}\n*/\n/**\n * @function module:utilities.EditorContext#getBaseUnit\n * @returns {string}\n*/\n/**\n * @function module:utilities.EditorContext#getSnappingStep\n * @returns {Float|string}\n*/\n\n/**\n* @function module:utilities.init\n* @param {module:utilities.EditorContext} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n editorContext_ = editorContext;\n domdoc_ = editorContext.getDOMDocument();\n domcontainer_ = editorContext.getDOMContainer();\n svgroot_ = editorContext.getSVGRoot();\n};\n\n/**\n * Used to prevent the [Billion laughs attack]{@link https://en.wikipedia.org/wiki/Billion_laughs_attack}.\n * @function module:utilities.dropXMLInternalSubset\n * @param {string} str String to be processed\n * @returns {string} The string with entity declarations in the internal subset removed\n * @todo This might be needed in other places `parseFromString` is used even without LGTM flagging\n */\nexport const dropXMLInternalSubset = (str) => {\n return str.replace(/(<!DOCTYPE\\s+\\w*\\s*\\[).*(\\?]>)/, '$1$2');\n // return str.replace(/(?<doctypeOpen><!DOCTYPE\\s+\\w*\\s*\\[).*(?<doctypeClose>\\?\\]>)/, '$<doctypeOpen>$<doctypeClose>');\n};\n\n/**\n* Converts characters in a string to XML-friendly entities.\n* @function module:utilities.toXml\n* @example `&` becomes `&amp;`\n* @param {string} str - The string to be converted\n* @returns {string} The converted string\n*/\nexport const toXml = function (str) {\n // &apos; is ok in XML, but not HTML\n // &gt; does not normally need escaping, though it can if within a CDATA expression (and preceded by \"]]\")\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#x27;'); // Note: `&apos;` is XML only\n};\n\n/**\n* Converts XML entities in a string to single characters.\n* @function module:utilities.fromXml\n* @example `&amp;` becomes `&`\n* @param {string} str - The string to be converted\n* @returns {string} The converted string\n*/\nexport function fromXml (str) {\n return $('<p/>').html(str).text();\n}\n\n// This code was written by Tyler Akins and has been placed in the\n// public domain. It would be nice if you left this header intact.\n// Base64 code from Tyler Akins -- http://rumkin.com\n\n// schiller: Removed string concatenation in favour of Array.join() optimization,\n// also precalculate the size of the array needed.\n\n/**\n* Converts a string to base64.\n* @function module:utilities.encode64\n* @param {string} input\n* @returns {string} Base64 output\n*/\nexport function encode64 (input) {\n // base64 strings are 4/3 larger than the original string\n input = encodeUTF8(input); // convert non-ASCII characters\n // input = convertToXMLReferences(input);\n if (window.btoa) {\n return window.btoa(input); // Use native if available\n }\n const output = new Array(Math.floor((input.length + 2) / 3) * 4);\n\n let i = 0,\n p = 0;\n do {\n const chr1 = input.charCodeAt(i++);\n const chr2 = input.charCodeAt(i++);\n const chr3 = input.charCodeAt(i++);\n\n /* eslint-disable no-bitwise */\n const enc1 = chr1 >> 2;\n const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n\n let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n let enc4 = chr3 & 63;\n /* eslint-enable no-bitwise */\n\n if (Number.isNaN(chr2)) {\n enc3 = 64;\n enc4 = 64;\n } else if (Number.isNaN(chr3)) {\n enc4 = 64;\n }\n\n output[p++] = KEYSTR.charAt(enc1);\n output[p++] = KEYSTR.charAt(enc2);\n output[p++] = KEYSTR.charAt(enc3);\n output[p++] = KEYSTR.charAt(enc4);\n } while (i < input.length);\n\n return output.join('');\n}\n\n/**\n* Converts a string from base64.\n* @function module:utilities.decode64\n* @param {string} input Base64-encoded input\n* @returns {string} Decoded output\n*/\nexport function decode64 (input) {\n if (window.atob) {\n return decodeUTF8(window.atob(input));\n }\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n input = input.replace(/[^A-Za-z\\d+/=]/g, '');\n\n let output = '';\n let i = 0;\n\n do {\n const enc1 = KEYSTR.indexOf(input.charAt(i++));\n const enc2 = KEYSTR.indexOf(input.charAt(i++));\n const enc3 = KEYSTR.indexOf(input.charAt(i++));\n const enc4 = KEYSTR.indexOf(input.charAt(i++));\n\n /* eslint-disable no-bitwise */\n const chr1 = (enc1 << 2) | (enc2 >> 4);\n const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n const chr3 = ((enc3 & 3) << 6) | enc4;\n /* eslint-enable no-bitwise */\n\n output += String.fromCharCode(chr1);\n\n if (enc3 !== 64) {\n output += String.fromCharCode(chr2);\n }\n if (enc4 !== 64) {\n output += String.fromCharCode(chr3);\n }\n } while (i < input.length);\n return decodeUTF8(output);\n}\n\n/**\n* @function module:utilities.decodeUTF8\n* @param {string} argString\n* @returns {string}\n*/\nexport function decodeUTF8 (argString) {\n return decodeURIComponent(escape(argString));\n}\n\n// codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded\n/**\n* @function module:utilities.encodeUTF8\n* @param {string} argString\n* @returns {string}\n*/\nexport const encodeUTF8 = function (argString) {\n return unescape(encodeURIComponent(argString));\n};\n\n/**\n * Convert dataURL to object URL.\n * @function module:utilities.dataURLToObjectURL\n * @param {string} dataurl\n * @returns {string} object URL or empty string\n */\nexport const dataURLToObjectURL = function (dataurl) {\n if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) {\n return '';\n }\n const arr = dataurl.split(','),\n mime = arr[0].match(/:(.*?);/)[1],\n bstr = atob(arr[1]);\n /*\n const [prefix, suffix] = dataurl.split(','),\n {groups: {mime}} = prefix.match(/:(?<mime>.*?);/),\n bstr = atob(suffix);\n */\n let n = bstr.length;\n const u8arr = new Uint8Array(n);\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n);\n }\n const blob = new Blob([u8arr], {type: mime});\n return URL.createObjectURL(blob);\n};\n\n/**\n * Get object URL for a blob object.\n * @function module:utilities.createObjectURL\n * @param {Blob} blob A Blob object or File object\n * @returns {string} object URL or empty string\n */\nexport const createObjectURL = function (blob) {\n if (!blob || typeof URL === 'undefined' || !URL.createObjectURL) {\n return '';\n }\n return URL.createObjectURL(blob);\n};\n\n/**\n * @property {string} blankPageObjectURL\n */\nexport const blankPageObjectURL = (function () {\n if (typeof Blob === 'undefined') {\n return '';\n }\n const blob = new Blob(['<html><head><title>SVG-edit</title></head><body>&nbsp;</body></html>'], {type: 'text/html'});\n return createObjectURL(blob);\n})();\n\n/**\n* Converts a string to use XML references (for non-ASCII).\n* @function module:utilities.convertToXMLReferences\n* @param {string} input\n* @returns {string} Decimal numeric character references\n*/\nexport const convertToXMLReferences = function (input) {\n let output = '';\n [...input].forEach((ch) => {\n const c = ch.charCodeAt();\n if (c <= 127) {\n output += ch;\n } else {\n output += `&#${c};`;\n }\n });\n return output;\n};\n\n/**\n* Cross-browser compatible method of converting a string to an XML tree.\n* Found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f}.\n* @function module:utilities.text2xml\n* @param {string} sXML\n* @throws {Error}\n* @returns {XMLDocument}\n*/\nexport const text2xml = function (sXML) {\n if (sXML.includes('<svg:svg')) {\n sXML = sXML.replace(/<(\\/?)svg:/g, '<$1').replace('xmlns:svg', 'xmlns');\n }\n\n let out, dXML;\n try {\n dXML = (window.DOMParser) ? new DOMParser() : new window.ActiveXObject('Microsoft.XMLDOM');\n dXML.async = false;\n } catch (e) {\n throw new Error('XML Parser could not be instantiated');\n }\n try {\n if (dXML.loadXML) {\n out = (dXML.loadXML(sXML)) ? dXML : false;\n } else {\n out = dXML.parseFromString(sXML, 'text/xml');\n }\n } catch (e2) { throw new Error('Error parsing XML string'); }\n return out;\n};\n\n/**\n* @typedef {PlainObject} module:utilities.BBoxObject (like `DOMRect`)\n* @property {Float} x\n* @property {Float} y\n* @property {Float} width\n* @property {Float} height\n*/\n\n/**\n* Converts a `SVGRect` into an object.\n* @function module:utilities.bboxToObj\n* @param {SVGRect} bbox - a SVGRect\n* @returns {module:utilities.BBoxObject} An object with properties names x, y, width, height.\n*/\nexport const bboxToObj = function ({x, y, width, height}) {\n return {x, y, width, height};\n};\n\n/**\n* @callback module:utilities.TreeWalker\n* @param {Element} elem - DOM element being traversed\n* @returns {void}\n*/\n\n/**\n* Walks the tree and executes the callback on each element in a top-down fashion.\n* @function module:utilities.walkTree\n* @param {Element} elem - DOM element to traverse\n* @param {module:utilities.TreeWalker} cbFn - Callback function to run on each element\n* @returns {void}\n*/\nexport const walkTree = function (elem, cbFn) {\n if (elem && elem.nodeType === 1) {\n cbFn(elem);\n let i = elem.childNodes.length;\n while (i--) {\n walkTree(elem.childNodes.item(i), cbFn);\n }\n }\n};\n\n/**\n* Walks the tree and executes the callback on each element in a depth-first fashion.\n* @function module:utilities.walkTreePost\n* @todo Shouldn't this be calling walkTreePost?\n* @param {Element} elem - DOM element to traverse\n* @param {module:utilities.TreeWalker} cbFn - Callback function to run on each element\n* @returns {void}\n*/\nexport const walkTreePost = function (elem, cbFn) {\n if (elem && elem.nodeType === 1) {\n let i = elem.childNodes.length;\n while (i--) {\n walkTree(elem.childNodes.item(i), cbFn);\n }\n cbFn(elem);\n }\n};\n\n/**\n* Extracts the URL from the `url(...)` syntax of some attributes.\n* Three variants:\n* - `<circle fill=\"url(someFile.svg#foo)\" />`\n* - `<circle fill=\"url('someFile.svg#foo')\" />`\n* - `<circle fill='url(\"someFile.svg#foo\")' />`\n* @function module:utilities.getUrlFromAttr\n* @param {string} attrVal The attribute value as a string\n* @returns {string} String with just the URL, like \"someFile.svg#foo\"\n*/\nexport const getUrlFromAttr = function (attrVal) {\n if (attrVal) {\n // url('#somegrad')\n if (attrVal.startsWith('url(\"')) {\n return attrVal.substring(5, attrVal.indexOf('\"', 6));\n }\n // url('#somegrad')\n if (attrVal.startsWith(\"url('\")) {\n return attrVal.substring(5, attrVal.indexOf(\"'\", 6));\n }\n if (attrVal.startsWith('url(')) {\n return attrVal.substring(4, attrVal.indexOf(')'));\n }\n }\n return null;\n};\n\n/**\n* @function module:utilities.getHref\n* @param {Element} elem\n* @returns {string} The given element's `xlink:href` value\n*/\nexport let getHref = function (elem) { // eslint-disable-line import/no-mutable-exports\n return elem.getAttributeNS(NS.XLINK, 'href');\n};\n\n/**\n* Sets the given element's `xlink:href` value.\n* @function module:utilities.setHref\n* @param {Element} elem\n* @param {string} val\n* @returns {void}\n*/\nexport let setHref = function (elem, val) { // eslint-disable-line import/no-mutable-exports\n elem.setAttributeNS(NS.XLINK, 'xlink:href', val);\n};\n\n/**\n* @function module:utilities.findDefs\n* @returns {SVGDefsElement} The document's `<defs>` element, creating it first if necessary\n*/\nexport const findDefs = function () {\n const svgElement = editorContext_.getSVGContent();\n let defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs');\n if (defs.length > 0) {\n defs = defs[0];\n } else {\n defs = svgElement.ownerDocument.createElementNS(NS.SVG, 'defs');\n if (svgElement.firstChild) {\n // first child is a comment, so call nextSibling\n svgElement.insertBefore(defs, svgElement.firstChild.nextSibling);\n // svgElement.firstChild.nextSibling.before(defs); // Not safe\n } else {\n svgElement.append(defs);\n }\n }\n return defs;\n};\n\n// TODO(codedread): Consider moving the next to functions to bbox.js\n\n/**\n* Get correct BBox for a path in Webkit.\n* Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html}.\n* @function module:utilities.getPathBBox\n* @param {SVGPathElement} path - The path DOM element to get the BBox for\n* @returns {module:utilities.BBoxObject} A BBox-like object\n*/\nexport const getPathBBox = function (path) {\n const seglist = path.pathSegList;\n const tot = seglist.numberOfItems;\n\n const bounds = [[], []];\n const start = seglist.getItem(0);\n let P0 = [start.x, start.y];\n\n const getCalc = function (j, P1, P2, P3) {\n return function (t) {\n return 1 - (t ** 3) * P0[j] +\n 3 * 1 - (t ** 2) * t * P1[j] +\n 3 * (1 - t) * (t ** 2) * P2[j] +\n (t ** 3) * P3[j];\n };\n };\n\n for (let i = 0; i < tot; i++) {\n const seg = seglist.getItem(i);\n\n if (seg.x === undefined) { continue; }\n\n // Add actual points to limits\n bounds[0].push(P0[0]);\n bounds[1].push(P0[1]);\n\n if (seg.x1) {\n const P1 = [seg.x1, seg.y1],\n P2 = [seg.x2, seg.y2],\n P3 = [seg.x, seg.y];\n\n for (let j = 0; j < 2; j++) {\n const calc = getCalc(j, P1, P2, P3);\n\n const b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];\n const a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];\n const c = 3 * P1[j] - 3 * P0[j];\n\n if (a === 0) {\n if (b === 0) { continue; }\n const t = -c / b;\n if (t > 0 && t < 1) {\n bounds[j].push(calc(t));\n }\n continue;\n }\n const b2ac = (b ** 2) - 4 * c * a;\n if (b2ac < 0) { continue; }\n const t1 = (-b + Math.sqrt(b2ac)) / (2 * a);\n if (t1 > 0 && t1 < 1) { bounds[j].push(calc(t1)); }\n const t2 = (-b - Math.sqrt(b2ac)) / (2 * a);\n if (t2 > 0 && t2 < 1) { bounds[j].push(calc(t2)); }\n }\n P0 = P3;\n } else {\n bounds[0].push(seg.x);\n bounds[1].push(seg.y);\n }\n }\n\n const x = Math.min.apply(null, bounds[0]);\n const w = Math.max.apply(null, bounds[0]) - x;\n const y = Math.min.apply(null, bounds[1]);\n const h = Math.max.apply(null, bounds[1]) - y;\n return {\n x,\n y,\n width: w,\n height: h\n };\n};\n\n/**\n* Get the given/selected element's bounding box object, checking for\n* horizontal/vertical lines (see issue 717)\n* Note that performance is currently terrible, so some way to improve would\n* be great.\n* @param {Element} selected - Container or `<use>` DOM element\n* @returns {DOMRect} Bounding box object\n*/\nfunction groupBBFix (selected) {\n if (supportsHVLineContainerBBox()) {\n try { return selected.getBBox(); } catch (e) {}\n }\n const ref = $.data(selected, 'ref');\n let matched = null;\n let ret, copy;\n\n if (ref) {\n copy = $(ref).children().clone().attr('visibility', 'hidden');\n $(svgroot_).append(copy);\n matched = copy.filter('line, path');\n } else {\n matched = $(selected).find('line, path');\n }\n\n let issue = false;\n if (matched.length) {\n matched.each(function () {\n const bb = this.getBBox();\n if (!bb.width || !bb.height) {\n issue = true;\n }\n });\n if (issue) {\n const elems = ref ? copy : $(selected).children();\n ret = getStrokedBBox(elems);\n } else {\n ret = selected.getBBox();\n }\n } else {\n ret = selected.getBBox();\n }\n if (ref) {\n copy.remove();\n }\n return ret;\n}\n\n/**\n* Get the given/selected element's bounding box object, convert it to be more\n* usable when necessary.\n* @function module:utilities.getBBox\n* @param {Element} elem - Optional DOM element to get the BBox for\n* @returns {module:utilities.BBoxObject} Bounding box object\n*/\nexport const getBBox = function (elem) {\n const selected = elem || editorContext_.geSelectedElements()[0];\n if (elem.nodeType !== 1) { return null; }\n const elname = selected.nodeName;\n\n let ret = null;\n switch (elname) {\n case 'text':\n if (selected.textContent === '') {\n selected.textContent = 'a'; // Some character needed for the selector to use.\n ret = selected.getBBox();\n selected.textContent = '';\n } else if (selected.getBBox) {\n ret = selected.getBBox();\n }\n break;\n case 'path':\n if (!supportsPathBBox()) {\n ret = getPathBBox(selected);\n } else if (selected.getBBox) {\n ret = selected.getBBox();\n }\n break;\n case 'g':\n case 'a':\n ret = groupBBFix(selected);\n break;\n default:\n\n if (elname === 'use') {\n ret = groupBBFix(selected); // , true);\n }\n if (elname === 'use' || (elname === 'foreignObject' && isWebkit())) {\n if (!ret) { ret = selected.getBBox(); }\n // This is resolved in later versions of webkit, perhaps we should\n // have a featured detection for correct 'use' behavior?\n // ——————————\n if (!isWebkit()) {\n const {x, y, width, height} = ret;\n const bb = {\n width,\n height,\n x: x + Number.parseFloat(selected.getAttribute('x') || 0),\n y: y + Number.parseFloat(selected.getAttribute('y') || 0)\n };\n ret = bb;\n }\n } else if (visElemsArr.includes(elname)) {\n if (selected) {\n try {\n ret = selected.getBBox();\n } catch (err) {\n // tspan (and textPath apparently) have no `getBBox` in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=937268\n // Re: Chrome returning bbox for containing text element, see: https://bugs.chromium.org/p/chromium/issues/detail?id=349835\n const extent = selected.getExtentOfChar(0); // pos+dimensions of the first glyph\n const width = selected.getComputedTextLength(); // width of the tspan\n ret = {\n x: extent.x,\n y: extent.y,\n width,\n height: extent.height\n };\n }\n } else {\n // Check if element is child of a foreignObject\n const fo = $(selected).closest('foreignObject');\n if (fo.length) {\n if (fo[0].getBBox) {\n ret = fo[0].getBBox();\n }\n }\n }\n }\n }\n if (ret) {\n ret = bboxToObj(ret);\n }\n\n // get the bounding box from the DOM (which is in that element's coordinate system)\n return ret;\n};\n\n/**\n* @typedef {GenericArray} module:utilities.PathSegmentArray\n* @property {Integer} length 2\n* @property {\"M\"|\"L\"|\"C\"|\"Z\"} 0\n* @property {Float[]} 1\n*/\n\n/**\n* Create a path 'd' attribute from path segments.\n* Each segment is an array of the form: `[singleChar, [x,y, x,y, ...]]`\n* @function module:utilities.getPathDFromSegments\n* @param {module:utilities.PathSegmentArray[]} pathSegments - An array of path segments to be converted\n* @returns {string} The converted path d attribute.\n*/\nexport const getPathDFromSegments = function (pathSegments) {\n let d = '';\n\n $.each(pathSegments, function (j, [singleChar, pts]) {\n d += singleChar;\n for (let i = 0; i < pts.length; i += 2) {\n d += (pts[i] + ',' + pts[i + 1]) + ' ';\n }\n });\n\n return d;\n};\n\n/**\n* Make a path 'd' attribute from a simple SVG element shape.\n* @function module:utilities.getPathDFromElement\n* @param {Element} elem - The element to be converted\n* @returns {string} The path d attribute or `undefined` if the element type is unknown.\n*/\nexport const getPathDFromElement = function (elem) {\n // Possibly the cubed root of 6, but 1.81 works best\n let num = 1.81;\n let d, a, rx, ry;\n switch (elem.tagName) {\n case 'ellipse':\n case 'circle': {\n a = $(elem).attr(['rx', 'ry', 'cx', 'cy']);\n const {cx, cy} = a;\n ({rx, ry} = a);\n if (elem.tagName === 'circle') {\n ry = $(elem).attr('r');\n rx = ry;\n }\n\n d = getPathDFromSegments([\n ['M', [(cx - rx), (cy)]],\n ['C', [(cx - rx), (cy - ry / num), (cx - rx / num), (cy - ry), (cx), (cy - ry)]],\n ['C', [(cx + rx / num), (cy - ry), (cx + rx), (cy - ry / num), (cx + rx), (cy)]],\n ['C', [(cx + rx), (cy + ry / num), (cx + rx / num), (cy + ry), (cx), (cy + ry)]],\n ['C', [(cx - rx / num), (cy + ry), (cx - rx), (cy + ry / num), (cx - rx), (cy)]],\n ['Z', []]\n ]);\n break;\n } case 'path':\n d = elem.getAttribute('d');\n break;\n case 'line':\n a = $(elem).attr(['x1', 'y1', 'x2', 'y2']);\n d = 'M' + a.x1 + ',' + a.y1 + 'L' + a.x2 + ',' + a.y2;\n break;\n case 'polyline':\n d = 'M' + elem.getAttribute('points');\n break;\n case 'polygon':\n d = 'M' + elem.getAttribute('points') + ' Z';\n break;\n case 'rect': {\n const r = $(elem).attr(['rx', 'ry']);\n ({rx, ry} = r);\n const b = elem.getBBox();\n const {x, y} = b,\n w = b.width,\n h = b.height;\n num = 4 - num; // Why? Because!\n\n if (!rx && !ry) {\n // Regular rect\n d = getPathDFromSegments([\n ['M', [x, y]],\n ['L', [x + w, y]],\n ['L', [x + w, y + h]],\n ['L', [x, y + h]],\n ['L', [x, y]],\n ['Z', []]\n ]);\n } else {\n d = getPathDFromSegments([\n ['M', [x, y + ry]],\n ['C', [x, y + ry / num, x + rx / num, y, x + rx, y]],\n ['L', [x + w - rx, y]],\n ['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]],\n ['L', [x + w, y + h - ry]],\n ['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]],\n ['L', [x + rx, y + h]],\n ['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]],\n ['L', [x, y + ry]],\n ['Z', []]\n ]);\n }\n break;\n } default:\n break;\n }\n\n return d;\n};\n\n/**\n* Get a set of attributes from an element that is useful for convertToPath.\n* @function module:utilities.getExtraAttributesForConvertToPath\n* @param {Element} elem - The element to be probed\n* @returns {PlainObject<\"marker-start\"|\"marker-end\"|\"marker-mid\"|\"filter\"|\"clip-path\", string>} An object with attributes.\n*/\nexport const getExtraAttributesForConvertToPath = function (elem) {\n const attrs = {};\n // TODO: make this list global so that we can properly maintain it\n // TODO: what about @transform, @clip-rule, @fill-rule, etc?\n $.each(['marker-start', 'marker-end', 'marker-mid', 'filter', 'clip-path'], function () {\n const a = elem.getAttribute(this);\n if (a) {\n attrs[this] = a;\n }\n });\n return attrs;\n};\n\n/**\n* Get the BBox of an element-as-path.\n* @function module:utilities.getBBoxOfElementAsPath\n* @param {Element} elem - The DOM element to be probed\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, `pathActions.resetOrientation()` is used. See: canvas.pathActions.\n* @returns {DOMRect|false} The resulting path's bounding box object.\n*/\nexport const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pathActions) {\n const path = addSVGElementFromJson({\n element: 'path',\n attr: getExtraAttributesForConvertToPath(elem)\n });\n\n const eltrans = elem.getAttribute('transform');\n if (eltrans) {\n path.setAttribute('transform', eltrans);\n }\n\n const {parentNode} = elem;\n if (elem.nextSibling) {\n elem.before(path);\n } else {\n parentNode.append(path);\n }\n\n const d = getPathDFromElement(elem);\n if (d) {\n path.setAttribute('d', d);\n } else {\n path.remove();\n }\n\n // Get the correct BBox of the new path, then discard it\n pathActions.resetOrientation(path);\n let bb = false;\n try {\n bb = path.getBBox();\n } catch (e) {\n // Firefox fails\n }\n path.remove();\n return bb;\n};\n\n/**\n* Convert selected element to a path.\n* @function module:utilities.convertToPath\n* @param {Element} elem - The DOM element to be converted\n* @param {module:utilities.SVGElementJSON} attrs - Apply attributes to new path. see canvas.convertToPath\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.\n* @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection}\n* @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection}\n* @param {module:history} hstry - see history module\n* @param {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} addCommandToHistory - see [canvas.addCommandToHistory]{@link module:svgcanvas~addCommandToHistory}\n* @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized.\n*/\nexport const convertToPath = function (elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory) {\n const batchCmd = new hstry.BatchCommand('Convert element to Path');\n\n // Any attribute on the element not covered by the passed-in attributes\n attrs = $.extend({}, attrs, getExtraAttributesForConvertToPath(elem));\n\n const path = addSVGElementFromJson({\n element: 'path',\n attr: attrs\n });\n\n const eltrans = elem.getAttribute('transform');\n if (eltrans) {\n path.setAttribute('transform', eltrans);\n }\n\n const {id} = elem;\n const {parentNode} = elem;\n if (elem.nextSibling) {\n elem.before(path);\n } else {\n parentNode.append(path);\n }\n\n const d = getPathDFromElement(elem);\n if (d) {\n path.setAttribute('d', d);\n\n // Replace the current element with the converted one\n\n // Reorient if it has a matrix\n if (eltrans) {\n const tlist = getTransformList(path);\n if (hasMatrixTransform(tlist)) {\n pathActions.resetOrientation(path);\n }\n }\n\n const {nextSibling} = elem;\n batchCmd.addSubCommand(new hstry.RemoveElementCommand(elem, nextSibling, parent));\n batchCmd.addSubCommand(new hstry.InsertElementCommand(path));\n\n clearSelection();\n elem.remove();\n path.setAttribute('id', id);\n path.removeAttribute('visibility');\n addToSelection([path], true);\n\n addCommandToHistory(batchCmd);\n\n return path;\n }\n // the elem.tagName was not recognized, so no \"d\" attribute. Remove it, so we've haven't changed anything.\n path.remove();\n return null;\n};\n\n/**\n* Can the bbox be optimized over the native getBBox? The optimized bbox is the same as the native getBBox when\n* the rotation angle is a multiple of 90 degrees and there are no complex transforms.\n* Getting an optimized bbox can be dramatically slower, so we want to make sure it's worth it.\n*\n* The best example for this is a circle rotate 45 degrees. The circle doesn't get wider or taller when rotated\n* about it's center.\n*\n* The standard, unoptimized technique gets the native bbox of the circle, rotates the box 45 degrees, uses\n* that width and height, and applies any transforms to get the final bbox. This means the calculated bbox\n* is much wider than the original circle. If the angle had been 0, 90, 180, etc. both techniques render the\n* same bbox.\n*\n* The optimization is not needed if the rotation is a multiple 90 degrees. The default technique is to call\n* getBBox then apply the angle and any transforms.\n*\n* @param {Float} angle - The rotation angle in degrees\n* @param {boolean} hasAMatrixTransform - True if there is a matrix transform\n* @returns {boolean} True if the bbox can be optimized.\n*/\nfunction bBoxCanBeOptimizedOverNativeGetBBox (angle, hasAMatrixTransform) {\n const angleModulo90 = angle % 90;\n const closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99;\n const closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001;\n return hasAMatrixTransform || !(closeTo0 || closeTo90);\n}\n\n/**\n* Get bounding box that includes any transforms.\n* @function module:utilities.getBBoxWithTransform\n* @param {Element} elem - The DOM element to be converted\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.\n* @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object\n*/\nexport const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathActions) {\n // TODO: Fix issue with rotated groups. Currently they work\n // fine in FF, but not in other browsers (same problem mentioned\n // in Issue 339 comment #2).\n\n let bb = getBBox(elem);\n\n if (!bb) {\n return null;\n }\n\n const tlist = getTransformList(elem);\n const angle = getRotationAngleFromTransformList(tlist);\n const hasMatrixXForm = hasMatrixTransform(tlist);\n\n if (angle || hasMatrixXForm) {\n let goodBb = false;\n if (bBoxCanBeOptimizedOverNativeGetBBox(angle, hasMatrixXForm)) {\n // Get the BBox from the raw path for these elements\n // TODO: why ellipse and not circle\n const elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon'];\n if (elemNames.includes(elem.tagName)) {\n goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);\n bb = goodBb;\n } else if (elem.tagName === 'rect') {\n // Look for radius\n const rx = elem.getAttribute('rx');\n const ry = elem.getAttribute('ry');\n if (rx || ry) {\n goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);\n bb = goodBb;\n }\n }\n }\n\n if (!goodBb) {\n const {matrix} = transformListToTransform(tlist);\n bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox;\n\n // Old technique that was exceedingly slow with large documents.\n //\n // Accurate way to get BBox of rotated element in Firefox:\n // Put element in group and get its BBox\n //\n // Must use clone else FF freaks out\n // const clone = elem.cloneNode(true);\n // const g = document.createElementNS(NS.SVG, 'g');\n // const parent = elem.parentNode;\n // parent.append(g);\n // g.append(clone);\n // const bb2 = bboxToObj(g.getBBox());\n // g.remove();\n }\n }\n return bb;\n};\n\n/**\n * @param {Element} elem\n * @returns {Float}\n * @todo This is problematic with large stroke-width and, for example, a single\n * horizontal line. The calculated BBox extends way beyond left and right sides.\n */\nfunction getStrokeOffsetForBBox (elem) {\n const sw = elem.getAttribute('stroke-width');\n return (!isNaN(sw) && elem.getAttribute('stroke') !== 'none') ? sw / 2 : 0;\n}\n\n/**\n * @typedef {PlainObject} BBox\n * @property {Integer} x The x value\n * @property {Integer} y The y value\n * @property {Float} width\n * @property {Float} height\n */\n\n/**\n* Get the bounding box for one or more stroked and/or transformed elements.\n* @function module:utilities.getStrokedBBox\n* @param {Element[]} elems - Array with DOM elements to check\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.\n* @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object\n*/\nexport const getStrokedBBox = function (elems, addSVGElementFromJson, pathActions) {\n if (!elems || !elems.length) { return false; }\n\n let fullBb;\n $.each(elems, function () {\n if (fullBb) { return; }\n if (!this.parentNode) { return; }\n fullBb = getBBoxWithTransform(this, addSVGElementFromJson, pathActions);\n });\n\n // This shouldn't ever happen...\n if (fullBb === undefined) { return null; }\n\n // fullBb doesn't include the stoke, so this does no good!\n // if (elems.length == 1) return fullBb;\n\n let maxX = fullBb.x + fullBb.width;\n let maxY = fullBb.y + fullBb.height;\n let minX = fullBb.x;\n let minY = fullBb.y;\n\n // If only one elem, don't call the potentially slow getBBoxWithTransform method again.\n if (elems.length === 1) {\n const offset = getStrokeOffsetForBBox(elems[0]);\n minX -= offset;\n minY -= offset;\n maxX += offset;\n maxY += offset;\n } else {\n $.each(elems, function (i, elem) {\n const curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions);\n if (curBb) {\n const offset = getStrokeOffsetForBBox(elem);\n minX = Math.min(minX, curBb.x - offset);\n minY = Math.min(minY, curBb.y - offset);\n // TODO: The old code had this test for max, but not min. I suspect this test should be for both min and max\n if (elem.nodeType === 1) {\n maxX = Math.max(maxX, curBb.x + curBb.width + offset);\n maxY = Math.max(maxY, curBb.y + curBb.height + offset);\n }\n }\n });\n }\n\n fullBb.x = minX;\n fullBb.y = minY;\n fullBb.width = maxX - minX;\n fullBb.height = maxY - minY;\n return fullBb;\n};\n\n/**\n* Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc).\n* Note that 0-opacity, off-screen etc elements are still considered \"visible\"\n* for this function.\n* @function module:utilities.getVisibleElements\n* @param {Element} parentElement - The parent DOM element to search within\n* @returns {Element[]} All \"visible\" elements.\n*/\nexport const getVisibleElements = function (parentElement) {\n if (!parentElement) {\n parentElement = $(editorContext_.getSVGContent()).children(); // Prevent layers from being included\n }\n\n const contentElems = [];\n $(parentElement).children().each(function (i, elem) {\n if (elem.getBBox) {\n contentElems.push(elem);\n }\n });\n return contentElems.reverse();\n};\n\n/**\n* Get the bounding box for one or more stroked and/or transformed elements.\n* @function module:utilities.getStrokedBBoxDefaultVisible\n* @param {Element[]} elems - Array with DOM elements to check\n* @returns {module:utilities.BBoxObject} A single bounding box object\n*/\nexport const getStrokedBBoxDefaultVisible = function (elems) {\n if (!elems) { elems = getVisibleElements(); }\n return getStrokedBBox(\n elems,\n editorContext_.addSVGElementFromJson,\n editorContext_.pathActions\n );\n};\n\n/**\n* Get the rotation angle of the given transform list.\n* @function module:utilities.getRotationAngleFromTransformList\n* @param {SVGTransformList} tlist - List of transforms\n* @param {boolean} toRad - When true returns the value in radians rather than degrees\n* @returns {Float} The angle in degrees or radians\n*/\nexport const getRotationAngleFromTransformList = function (tlist, toRad) {\n if (!tlist) { return 0; } // <svg> elements have no tlist\n const N = tlist.numberOfItems;\n for (let i = 0; i < N; ++i) {\n const xform = tlist.getItem(i);\n if (xform.type === 4) {\n return toRad ? xform.angle * Math.PI / 180.0 : xform.angle;\n }\n }\n return 0.0;\n};\n\n/**\n* Get the rotation angle of the given/selected DOM element.\n* @function module:utilities.getRotationAngle\n* @param {Element} [elem] - DOM element to get the angle for. Default to first of selected elements.\n* @param {boolean} [toRad=false] - When true returns the value in radians rather than degrees\n* @returns {Float} The angle in degrees or radians\n*/\nexport let getRotationAngle = function (elem, toRad) { // eslint-disable-line import/no-mutable-exports\n const selected = elem || editorContext_.getSelectedElements()[0];\n // find the rotation transform (if any) and set it\n const tlist = getTransformList(selected);\n return getRotationAngleFromTransformList(tlist, toRad);\n};\n\n/**\n* Get the reference element associated with the given attribute value.\n* @function module:utilities.getRefElem\n* @param {string} attrVal - The attribute value as a string\n* @returns {Element} Reference element\n*/\nexport const getRefElem = function (attrVal) {\n return getElem(getUrlFromAttr(attrVal).substr(1));\n};\n\n/**\n* Get a DOM element by ID within the SVG root element.\n* @function module:utilities.getElem\n* @param {string} id - String with the element's new ID\n* @returns {?Element}\n*/\nexport const getElem = (supportsSelectors())\n ? function (id) {\n // querySelector lookup\n return svgroot_.querySelector('#' + id);\n }\n : supportsXpath()\n ? function (id) {\n // xpath lookup\n return domdoc_.evaluate(\n 'svg:svg[@id=\"svgroot\"]//svg:*[@id=\"' + id + '\"]',\n domcontainer_,\n function () { return NS.SVG; },\n 9,\n null\n ).singleNodeValue;\n }\n : function (id) {\n // jQuery lookup: twice as slow as xpath in FF\n // eslint-disable-next-line unicorn/no-fn-reference-in-iterator\n return $(svgroot_).find('[id=' + id + ']')[0];\n };\n\n/**\n* Assigns multiple attributes to an element.\n* @function module:utilities.assignAttributes\n* @param {Element} elem - DOM element to apply new attribute values to\n* @param {PlainObject<string, string>} attrs - Object with attribute keys/values\n* @param {Integer} [suspendLength] - Milliseconds to suspend redraw\n* @param {boolean} [unitCheck=false] - Boolean to indicate the need to use units.setUnitAttr\n* @returns {void}\n*/\nexport const assignAttributes = function (elem, attrs, suspendLength, unitCheck) {\n for (const [key, value] of Object.entries(attrs)) {\n const ns = (key.substr(0, 4) === 'xml:'\n ? NS.XML\n : key.substr(0, 6) === 'xlink:' ? NS.XLINK : null);\n if (isNullish(value)) {\n if (ns) {\n elem.removeAttributeNS(ns, key);\n } else {\n elem.removeAttribute(key);\n }\n continue;\n }\n if (ns) {\n elem.setAttributeNS(ns, key, value);\n } else if (!unitCheck) {\n elem.setAttribute(key, value);\n } else {\n setUnitAttr(elem, key, value);\n }\n }\n};\n\n/**\n* Remove unneeded (default) attributes, making resulting SVG smaller.\n* @function module:utilities.cleanupElement\n* @param {Element} element - DOM element to clean up\n* @returns {void}\n*/\nexport const cleanupElement = function (element) {\n const defaults = {\n 'fill-opacity': 1,\n 'stop-opacity': 1,\n opacity: 1,\n stroke: 'none',\n 'stroke-dasharray': 'none',\n 'stroke-linejoin': 'miter',\n 'stroke-linecap': 'butt',\n 'stroke-opacity': 1,\n 'stroke-width': 1,\n rx: 0,\n ry: 0\n };\n\n if (element.nodeName === 'ellipse') {\n // Ellipse elements require rx and ry attributes\n delete defaults.rx;\n delete defaults.ry;\n }\n\n Object.entries(defaults).forEach(([attr, val]) => {\n if (element.getAttribute(attr) === String(val)) {\n element.removeAttribute(attr);\n }\n });\n};\n\n/**\n* Round value to for snapping.\n* @function module:utilities.snapToGrid\n* @param {Float} value\n* @returns {Integer}\n*/\nexport const snapToGrid = function (value) {\n const unit = editorContext_.getBaseUnit();\n let stepSize = editorContext_.getSnappingStep();\n if (unit !== 'px') {\n stepSize *= getTypeMap()[unit];\n }\n value = Math.round(value / stepSize) * stepSize;\n return value;\n};\n\n/**\n* Escapes special characters in a regular expression.\n* @function module:utilities.regexEscape\n* @param {string} str\n* @returns {string}\n*/\nexport const regexEscape = function (str) {\n // Originally from: http://phpjs.org/functions\n return String(str).replace(/[.\\\\+*?[^\\]$(){}=!<>|:-]/g, '\\\\$&');\n};\n\n/**\n * Prevents default browser click behaviour on the given element.\n * @function module:utilities.preventClickDefault\n * @param {Element} img - The DOM element to prevent the click on\n * @returns {void}\n */\nexport const preventClickDefault = function (img) {\n $(img).click(function (e) { e.preventDefault(); });\n};\n\n/**\n * @callback module:utilities.GetNextID\n * @returns {string} The ID\n */\n\n/**\n * Whether a value is `null` or `undefined`.\n * @param {any} val\n * @returns {boolean}\n */\nexport const isNullish = (val) => {\n return val === null || val === undefined;\n};\n\n/**\n* Overwrite methods for unit testing.\n* @function module:utilities.mock\n* @param {PlainObject} mockMethods\n* @param {module:utilities.getHref} mockMethods.getHref\n* @param {module:utilities.setHref} mockMethods.setHref\n* @param {module:utilities.getRotationAngle} mockMethods.getRotationAngle\n* @returns {void}\n*/\nexport const mock = ({\n getHref: getHrefUser, setHref: setHrefUser, getRotationAngle: getRotationAngleUser\n}) => {\n getHref = getHrefUser;\n setHref = setHrefUser;\n getRotationAngle = getRotationAngleUser;\n};\n\nexport const $q = (sel) => document.querySelector(sel);\nexport const $qq = (sel) => [...document.querySelectorAll(sel)];\n","/**\n * Tools for working with units.\n * @module units\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {NS} from './namespaces.js';\nimport {isNullish} from './utilities.js';\n\nconst wAttrs = ['x', 'x1', 'cx', 'rx', 'width'];\nconst hAttrs = ['y', 'y1', 'cy', 'ry', 'height'];\nconst unitAttrs = ['r', 'radius', ...wAttrs, ...hAttrs];\n// unused\n/*\nconst unitNumMap = {\n '%': 2,\n em: 3,\n ex: 4,\n px: 5,\n cm: 6,\n mm: 7,\n in: 8,\n pt: 9,\n pc: 10\n};\n*/\n// Container of elements.\nlet elementContainer_;\n\n// Stores mapping of unit type to user coordinates.\nlet typeMap_ = {};\n\n/**\n * @interface module:units.ElementContainer\n */\n/**\n * @function module:units.ElementContainer#getBaseUnit\n * @returns {string} The base unit type of the container ('em')\n */\n/**\n * @function module:units.ElementContainer#getElement\n * @returns {?Element} An element in the container given an id\n */\n/**\n * @function module:units.ElementContainer#getHeight\n * @returns {Float} The container's height\n */\n/**\n * @function module:units.ElementContainer#getWidth\n * @returns {Float} The container's width\n */\n/**\n * @function module:units.ElementContainer#getRoundDigits\n * @returns {Integer} The number of digits number should be rounded to\n */\n\n/* eslint-disable jsdoc/valid-types */\n/**\n * @typedef {PlainObject} module:units.TypeMap\n * @property {Float} em\n * @property {Float} ex\n * @property {Float} in\n * @property {Float} cm\n * @property {Float} mm\n * @property {Float} pt\n * @property {Float} pc\n * @property {Integer} px\n * @property {0} %\n */\n/* eslint-enable jsdoc/valid-types */\n\n/**\n * Initializes this module.\n *\n * @function module:units.init\n * @param {module:units.ElementContainer} elementContainer - An object implementing the ElementContainer interface.\n * @returns {void}\n */\nexport const init = function (elementContainer) {\n elementContainer_ = elementContainer;\n\n // Get correct em/ex values by creating a temporary SVG.\n const svg = document.createElementNS(NS.SVG, 'svg');\n document.body.append(svg);\n const rect = document.createElementNS(NS.SVG, 'rect');\n rect.setAttribute('width', '1em');\n rect.setAttribute('height', '1ex');\n rect.setAttribute('x', '1in');\n svg.append(rect);\n const bb = rect.getBBox();\n svg.remove();\n\n const inch = bb.x;\n typeMap_ = {\n em: bb.width,\n ex: bb.height,\n in: inch,\n cm: inch / 2.54,\n mm: inch / 25.4,\n pt: inch / 72,\n pc: inch / 6,\n px: 1,\n '%': 0\n };\n};\n\n/**\n* Group: Unit conversion functions.\n*/\n\n/**\n * @function module:units.getTypeMap\n * @returns {module:units.TypeMap} The unit object with values for each unit\n*/\nexport const getTypeMap = function () {\n return typeMap_;\n};\n\n/**\n* @typedef {GenericArray} module:units.CompareNumbers\n* @property {Integer} length 2\n* @property {Float} 0\n* @property {Float} 1\n*/\n\n/**\n* Rounds a given value to a float with number of digits defined in\n* `round_digits` of `saveOptions`\n*\n* @function module:units.shortFloat\n* @param {string|Float|module:units.CompareNumbers} val - The value (or Array of two numbers) to be rounded\n* @returns {Float|string} If a string/number was given, returns a Float. If an array, return a string\n* with comma-separated floats\n*/\nexport const shortFloat = function (val) {\n const digits = elementContainer_.getRoundDigits();\n if (!isNaN(val)) {\n return Number(Number(val).toFixed(digits));\n }\n if (Array.isArray(val)) {\n return shortFloat(val[0]) + ',' + shortFloat(val[1]);\n }\n return Number.parseFloat(val).toFixed(digits) - 0;\n};\n\n/**\n* Converts the number to given unit or baseUnit.\n* @function module:units.convertUnit\n* @param {string|Float} val\n* @param {\"em\"|\"ex\"|\"in\"|\"cm\"|\"mm\"|\"pt\"|\"pc\"|\"px\"|\"%\"} [unit]\n* @returns {Float}\n*/\nexport const convertUnit = function (val, unit) {\n unit = unit || elementContainer_.getBaseUnit();\n // baseVal.convertToSpecifiedUnits(unitNumMap[unit]);\n // const val = baseVal.valueInSpecifiedUnits;\n // baseVal.convertToSpecifiedUnits(1);\n return shortFloat(val / typeMap_[unit]);\n};\n\n/**\n* Sets an element's attribute based on the unit in its current value.\n*\n* @function module:units.setUnitAttr\n* @param {Element} elem - DOM element to be changed\n* @param {string} attr - Name of the attribute associated with the value\n* @param {string} val - Attribute value to convert\n* @returns {void}\n*/\nexport const setUnitAttr = function (elem, attr, val) {\n // if (!isNaN(val)) {\n // New value is a number, so check currently used unit\n // const oldVal = elem.getAttribute(attr);\n\n // Enable this for alternate mode\n // if (oldVal !== null && (isNaN(oldVal) || elementContainer_.getBaseUnit() !== 'px')) {\n // // Old value was a number, so get unit, then convert\n // let unit;\n // if (oldVal.substr(-1) === '%') {\n // const res = getResolution();\n // unit = '%';\n // val *= 100;\n // if (wAttrs.includes(attr)) {\n // val = val / res.w;\n // } else if (hAttrs.includes(attr)) {\n // val = val / res.h;\n // } else {\n // return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);\n // }\n // } else {\n // if (elementContainer_.getBaseUnit() !== 'px') {\n // unit = elementContainer_.getBaseUnit();\n // } else {\n // unit = oldVal.substr(-2);\n // }\n // val = val / typeMap_[unit];\n // }\n //\n // val += unit;\n // }\n // }\n elem.setAttribute(attr, val);\n};\n\nconst attrsToConvert = {\n line: ['x1', 'x2', 'y1', 'y2'],\n circle: ['cx', 'cy', 'r'],\n ellipse: ['cx', 'cy', 'rx', 'ry'],\n foreignObject: ['x', 'y', 'width', 'height'],\n rect: ['x', 'y', 'width', 'height'],\n image: ['x', 'y', 'width', 'height'],\n use: ['x', 'y', 'width', 'height'],\n text: ['x', 'y']\n};\n\n/**\n* Converts all applicable attributes to the configured baseUnit.\n* @function module:units.convertAttrs\n* @param {Element} element - A DOM element whose attributes should be converted\n* @returns {void}\n*/\nexport const convertAttrs = function (element) {\n const elName = element.tagName;\n const unit = elementContainer_.getBaseUnit();\n const attrs = attrsToConvert[elName];\n if (!attrs) { return; }\n\n const len = attrs.length;\n for (let i = 0; i < len; i++) {\n const attr = attrs[i];\n const cur = element.getAttribute(attr);\n if (cur) {\n if (!isNaN(cur)) {\n element.setAttribute(attr, (cur / typeMap_[unit]) + unit);\n }\n // else {\n // Convert existing?\n // }\n }\n }\n};\n\n/**\n* Converts given values to numbers. Attributes must be supplied in\n* case a percentage is given.\n*\n* @function module:units.convertToNum\n* @param {string} attr - Name of the attribute associated with the value\n* @param {string} val - Attribute value to convert\n* @returns {Float} The converted number\n*/\nexport const convertToNum = function (attr, val) {\n // Return a number if that's what it already is\n if (!isNaN(val)) { return val - 0; }\n if (val.substr(-1) === '%') {\n // Deal with percentage, depends on attribute\n const num = val.substr(0, val.length - 1) / 100;\n const width = elementContainer_.getWidth();\n const height = elementContainer_.getHeight();\n\n if (wAttrs.includes(attr)) {\n return num * width;\n }\n if (hAttrs.includes(attr)) {\n return num * height;\n }\n return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2);\n }\n const unit = val.substr(-2);\n const num = val.substr(0, val.length - 2);\n // Note that this multiplication turns the string into a number\n return num * typeMap_[unit];\n};\n\n/**\n* Check if an attribute's value is in a valid format.\n* @function module:units.isValidUnit\n* @param {string} attr - The name of the attribute associated with the value\n* @param {string} val - The attribute value to check\n* @param {Element} selectedElement\n* @returns {boolean} Whether the unit is valid\n*/\nexport const isValidUnit = function (attr, val, selectedElement) {\n if (unitAttrs.includes(attr)) {\n // True if it's just a number\n if (!isNaN(val)) {\n return true;\n }\n // Not a number, check if it has a valid unit\n val = val.toLowerCase();\n return Object.keys(typeMap_).some((unit) => {\n const re = new RegExp('^-?[\\\\d\\\\.]+' + unit + '$');\n return re.test(val);\n });\n }\n if (attr === 'id') {\n // if we're trying to change the id, make sure it's not already present in the doc\n // and the id value is valid.\n\n let result = false;\n // because getElem() can throw an exception in the case of an invalid id\n // (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName)\n // we wrap it in an exception and only return true if the ID was valid and\n // not already present\n try {\n const elem = elementContainer_.getElement(val);\n result = (isNullish(elem) || elem === selectedElement);\n } catch (e) {}\n return result;\n }\n return true;\n};\n","/* eslint-disable no-console */\n/**\n * For command history tracking and undo functionality.\n * @module history\n * @license MIT\n * @copyright 2010 Jeff Schiller\n */\n\nimport {getHref, setHref, getRotationAngle, isNullish} from '../common/utilities.js';\nimport {removeElementFromListMap} from '../common/svgtransformlist.js';\n\n/**\n* Group: Undo/Redo history management.\n*/\nexport const HistoryEventTypes = {\n BEFORE_APPLY: 'before_apply',\n AFTER_APPLY: 'after_apply',\n BEFORE_UNAPPLY: 'before_unapply',\n AFTER_UNAPPLY: 'after_unapply'\n};\n\n/**\n* Base class for commands.\n*/\nclass Command {\n /**\n * @returns {string}\n */\n getText () {\n return this.text;\n }\n /**\n * @param {module:history.HistoryEventHandler} handler\n * @param {callback} applyFunction\n * @returns {void}\n */\n apply (handler, applyFunction) {\n handler && handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this);\n applyFunction(handler);\n handler && handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this);\n }\n\n /**\n * @param {module:history.HistoryEventHandler} handler\n * @param {callback} unapplyFunction\n * @returns {void}\n */\n unapply (handler, unapplyFunction) {\n handler && handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this);\n unapplyFunction();\n handler && handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this);\n }\n\n /**\n * @returns {Element[]} Array with element associated with this command\n * This function needs to be surcharged if multiple elements are returned.\n */\n elements () {\n return [this.elem];\n }\n\n /**\n * @returns {string} String with element associated with this command\n */\n type () {\n return this.constructor.name;\n }\n}\n\n// Todo: Figure out why the interface members aren't showing\n// up (with or without modules applied), despite our apparently following\n// http://usejsdoc.org/tags-interface.html#virtual-comments\n\n/**\n * An interface that all command objects must implement.\n * @interface module:history.HistoryCommand\n*/\n/**\n * Applies.\n *\n * @function module:history.HistoryCommand#apply\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void|true}\n */\n/**\n *\n * Unapplies.\n * @function module:history.HistoryCommand#unapply\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void|true}\n */\n/**\n * Returns the elements.\n * @function module:history.HistoryCommand#elements\n * @returns {Element[]}\n */\n/**\n * Gets the text.\n * @function module:history.HistoryCommand#getText\n * @returns {string}\n */\n/**\n * Gives the type.\n * @function module:history.HistoryCommand.type\n * @returns {string}\n */\n\n/**\n * @event module:history~Command#event:history\n * @type {module:history.HistoryCommand}\n */\n\n/**\n * An interface for objects that will handle history events.\n * @interface module:history.HistoryEventHandler\n */\n/**\n *\n * @function module:history.HistoryEventHandler#handleHistoryEvent\n * @param {string} eventType One of the HistoryEvent types\n * @param {module:history~Command#event:history} command\n * @listens module:history~Command#event:history\n * @returns {void}\n *\n */\n\n/**\n * History command for an element that had its DOM position changed.\n * @implements {module:history.HistoryCommand}\n*/\nexport class MoveElementCommand extends Command {\n /**\n * @param {Element} elem - The DOM element that was moved\n * @param {Element} oldNextSibling - The element's next sibling before it was moved\n * @param {Element} oldParent - The element's parent before it was moved\n * @param {string} [text] - An optional string visible to user related to this change\n */\n constructor (elem, oldNextSibling, oldParent, text) {\n super();\n this.elem = elem;\n this.text = text ? ('Move ' + elem.tagName + ' to ' + text) : ('Move ' + elem.tagName);\n this.oldNextSibling = oldNextSibling;\n this.oldParent = oldParent;\n this.newNextSibling = elem.nextSibling;\n this.newParent = elem.parentNode;\n }\n\n /**\n * Re-positions the element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n super.apply(handler, () => {\n this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling);\n });\n }\n\n /**\n * Positions the element back to its original location.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n super.unapply(handler, () => {\n this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling);\n });\n }\n}\n\n/**\n* History command for an element that was added to the DOM.\n* @implements {module:history.HistoryCommand}\n*/\nexport class InsertElementCommand extends Command {\n /**\n * @param {Element} elem - The newly added DOM element\n * @param {string} text - An optional string visible to user related to this change\n */\n constructor (elem, text) {\n super();\n this.elem = elem;\n this.text = text || ('Create ' + elem.tagName);\n this.parent = elem.parentNode;\n this.nextSibling = this.elem.nextSibling;\n }\n\n /**\n * Re-inserts the new element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n super.apply(handler, () => {\n this.elem = this.parent.insertBefore(this.elem, this.nextSibling);\n });\n }\n\n /**\n * Removes the element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n super.unapply(handler, () => {\n this.parent = this.elem.parentNode;\n this.elem.remove();\n });\n }\n}\n\n/**\n* History command for an element removed from the DOM.\n* @implements {module:history.HistoryCommand}\n*/\nexport class RemoveElementCommand extends Command {\n /**\n * @param {Element} elem - The removed DOM element\n * @param {Node} oldNextSibling - The DOM element's nextSibling when it was in the DOM\n * @param {Element} oldParent - The DOM element's parent\n * @param {string} [text] - An optional string visible to user related to this change\n */\n constructor (elem, oldNextSibling, oldParent, text) {\n super();\n this.elem = elem;\n this.text = text || ('Delete ' + elem.tagName);\n this.nextSibling = oldNextSibling;\n this.parent = oldParent;\n\n // special hack for webkit: remove this element's entry in the svgTransformLists map\n removeElementFromListMap(elem);\n }\n\n /**\n * Re-removes the new element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n super.apply(handler, () => {\n removeElementFromListMap(this.elem);\n this.parent = this.elem.parentNode;\n this.elem.remove();\n });\n }\n\n /**\n * Re-adds the new element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n super.unapply(handler, () => {\n removeElementFromListMap(this.elem);\n if (isNullish(this.nextSibling)) {\n if (window.console) {\n console.error('Reference element was lost');\n }\n }\n this.parent.insertBefore(this.elem, this.nextSibling); // Don't use `before` or `prepend` as `this.nextSibling` may be `null`\n });\n }\n}\n\n/**\n* @typedef {\"#text\"|\"#href\"|string} module:history.CommandAttributeName\n*/\n/**\n* @typedef {PlainObject<module:history.CommandAttributeName, string>} module:history.CommandAttributes\n*/\n\n/**\n* History command to make a change to an element.\n* Usually an attribute change, but can also be textcontent.\n* @implements {module:history.HistoryCommand}\n*/\nexport class ChangeElementCommand extends Command {\n /**\n * @param {Element} elem - The DOM element that was changed\n * @param {module:history.CommandAttributes} attrs - Attributes to be changed with the values they had *before* the change\n * @param {string} text - An optional string visible to user related to this change\n */\n constructor (elem, attrs, text) {\n super();\n this.elem = elem;\n this.text = text ? ('Change ' + elem.tagName + ' ' + text) : ('Change ' + elem.tagName);\n this.newValues = {};\n this.oldValues = attrs;\n for (const attr in attrs) {\n if (attr === '#text') {\n this.newValues[attr] = elem.textContent;\n } else if (attr === '#href') {\n this.newValues[attr] = getHref(elem);\n } else {\n this.newValues[attr] = elem.getAttribute(attr);\n }\n }\n }\n\n /**\n * Performs the stored change action.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n super.apply(handler, () => {\n let bChangedTransform = false;\n Object.entries(this.newValues).forEach(([attr, value]) => {\n if (value) {\n if (attr === '#text') {\n this.elem.textContent = value;\n } else if (attr === '#href') {\n setHref(this.elem, value);\n } else {\n this.elem.setAttribute(attr, value);\n }\n } else if (attr === '#text') {\n this.elem.textContent = '';\n } else {\n this.elem.setAttribute(attr, '');\n this.elem.removeAttribute(attr);\n }\n\n if (attr === 'transform') { bChangedTransform = true; }\n });\n\n // relocate rotational transform, if necessary\n if (!bChangedTransform) {\n const angle = getRotationAngle(this.elem);\n if (angle) {\n const bbox = this.elem.getBBox();\n const cx = bbox.x + bbox.width / 2;\n const cy = bbox.y + bbox.height / 2;\n const rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');\n if (rotate !== this.elem.getAttribute('transform')) {\n this.elem.setAttribute('transform', rotate);\n }\n }\n }\n });\n }\n\n /**\n * Reverses the stored change action.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n super.unapply(handler, () => {\n let bChangedTransform = false;\n Object.entries(this.oldValues).forEach(([attr, value]) => {\n if (value) {\n if (attr === '#text') {\n this.elem.textContent = value;\n } else if (attr === '#href') {\n setHref(this.elem, value);\n } else {\n this.elem.setAttribute(attr, value);\n }\n } else if (attr === '#text') {\n this.elem.textContent = '';\n } else {\n this.elem.removeAttribute(attr);\n }\n if (attr === 'transform') { bChangedTransform = true; }\n });\n // relocate rotational transform, if necessary\n if (!bChangedTransform) {\n const angle = getRotationAngle(this.elem);\n if (angle) {\n const bbox = this.elem.getBBox();\n const cx = bbox.x + bbox.width / 2,\n cy = bbox.y + bbox.height / 2;\n const rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');\n if (rotate !== this.elem.getAttribute('transform')) {\n this.elem.setAttribute('transform', rotate);\n }\n }\n }\n // Remove transformlist to prevent confusion that causes bugs like 575.\n removeElementFromListMap(this.elem);\n });\n }\n}\n\n// TODO: create a 'typing' command object that tracks changes in text\n// if a new Typing command is created and the top command on the stack is also a Typing\n// and they both affect the same element, then collapse the two commands into one\n\n/**\n* History command that can contain/execute multiple other commands.\n* @implements {module:history.HistoryCommand}\n*/\nexport class BatchCommand extends Command {\n /**\n * @param {string} [text] - An optional string visible to user related to this change\n */\n constructor (text) {\n super();\n this.text = text || 'Batch Command';\n this.stack = [];\n }\n\n /**\n * Runs \"apply\" on all subcommands.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n super.apply(handler, () => {\n this.stack.forEach((stackItem) => {\n console.assert(stackItem, 'stack item should not be null');\n stackItem && stackItem.apply(handler);\n });\n });\n }\n\n /**\n * Runs \"unapply\" on all subcommands.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n super.unapply(handler, () => {\n this.stack.forEach((stackItem) => {\n console.assert(stackItem, 'stack item should not be null');\n stackItem && stackItem.unapply(handler);\n });\n });\n }\n\n /**\n * Iterate through all our subcommands.\n * @returns {Element[]} All the elements we are changing\n */\n elements () {\n const elems = [];\n let cmd = this.stack.length;\n while (cmd--) {\n if (!this.stack[cmd]) continue;\n const thisElems = this.stack[cmd].elements();\n let elem = thisElems.length;\n while (elem--) {\n if (!elems.includes(thisElems[elem])) { elems.push(thisElems[elem]); }\n }\n }\n return elems;\n }\n\n /**\n * Adds a given command to the history stack.\n * @param {Command} cmd - The undo command object to add\n * @returns {void}\n */\n addSubCommand (cmd) {\n console.assert(cmd !== null, 'cmd should not be null');\n this.stack.push(cmd);\n }\n\n /**\n * @returns {boolean} Indicates whether or not the batch command is empty\n */\n isEmpty () {\n return !this.stack.length;\n }\n}\n\n/**\n*\n*/\nexport class UndoManager {\n /**\n * @param {module:history.HistoryEventHandler} historyEventHandler\n */\n constructor (historyEventHandler) {\n this.handler_ = historyEventHandler || null;\n this.undoStackPointer = 0;\n this.undoStack = [];\n\n // this is the stack that stores the original values, the elements and\n // the attribute name for begin/finish\n this.undoChangeStackPointer = -1;\n this.undoableChangeStack = [];\n }\n\n /**\n * Resets the undo stack, effectively clearing the undo/redo history.\n * @returns {void}\n */\n resetUndoStack () {\n this.undoStack = [];\n this.undoStackPointer = 0;\n }\n\n /**\n * @returns {Integer} Current size of the undo history stack\n */\n getUndoStackSize () {\n return this.undoStackPointer;\n }\n\n /**\n * @returns {Integer} Current size of the redo history stack\n */\n getRedoStackSize () {\n return this.undoStack.length - this.undoStackPointer;\n }\n\n /**\n * @returns {string} String associated with the next undo command\n */\n getNextUndoCommandText () {\n return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : '';\n }\n\n /**\n * @returns {string} String associated with the next redo command\n */\n getNextRedoCommandText () {\n return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : '';\n }\n\n /**\n * Performs an undo step.\n * @returns {void}\n */\n undo () {\n if (this.undoStackPointer > 0) {\n const cmd = this.undoStack[--this.undoStackPointer];\n cmd.unapply(this.handler_);\n }\n }\n\n /**\n * Performs a redo step.\n * @returns {void}\n */\n redo () {\n if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {\n const cmd = this.undoStack[this.undoStackPointer++];\n cmd.apply(this.handler_);\n }\n }\n\n /**\n * Adds a command object to the undo history stack.\n * @param {Command} cmd - The command object to add\n * @returns {void}\n */\n addCommandToHistory (cmd) {\n // TODO: we MUST compress consecutive text changes to the same element\n // (right now each keystroke is saved as a separate command that includes the\n // entire text contents of the text element)\n // TODO: consider limiting the history that we store here (need to do some slicing)\n\n // if our stack pointer is not at the end, then we have to remove\n // all commands after the pointer and insert the new command\n if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {\n this.undoStack = this.undoStack.splice(0, this.undoStackPointer);\n }\n this.undoStack.push(cmd);\n this.undoStackPointer = this.undoStack.length;\n }\n\n /**\n * This function tells the canvas to remember the old values of the\n * `attrName` attribute for each element sent in. The elements and values\n * are stored on a stack, so the next call to `finishUndoableChange()` will\n * pop the elements and old values off the stack, gets the current values\n * from the DOM and uses all of these to construct the undo-able command.\n * @param {string} attrName - The name of the attribute being changed\n * @param {Element[]} elems - Array of DOM elements being changed\n * @returns {void}\n */\n beginUndoableChange (attrName, elems) {\n const p = ++this.undoChangeStackPointer;\n let i = elems.length;\n const oldValues = new Array(i), elements = new Array(i);\n while (i--) {\n const elem = elems[i];\n if (isNullish(elem)) { continue; }\n elements[i] = elem;\n oldValues[i] = elem.getAttribute(attrName);\n }\n this.undoableChangeStack[p] = {\n attrName,\n oldValues,\n elements\n };\n }\n\n /**\n * This function returns a `BatchCommand` object which summarizes the\n * change since `beginUndoableChange` was called. The command can then\n * be added to the command history.\n * @returns {BatchCommand} Batch command object with resulting changes\n */\n finishUndoableChange () {\n const p = this.undoChangeStackPointer--;\n const changeset = this.undoableChangeStack[p];\n const {attrName} = changeset;\n const batchCmd = new BatchCommand('Change ' + attrName);\n let i = changeset.elements.length;\n while (i--) {\n const elem = changeset.elements[i];\n if (isNullish(elem)) { continue; }\n const changes = {};\n changes[attrName] = changeset.oldValues[i];\n if (changes[attrName] !== elem.getAttribute(attrName)) {\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes, attrName));\n }\n }\n this.undoableChangeStack[p] = null;\n return batchCmd;\n }\n}\n","/* globals jQuery */\n/**\n * Path functionality.\n * @module path\n * @license MIT\n *\n * @copyright 2011 Alexis Deveria, 2011 Jeff Schiller\n */\n\nimport '../common/svgpathseg.js';\nimport {NS} from '../common/namespaces.js';\nimport {getTransformList} from '../common/svgtransformlist.js';\nimport {shortFloat} from '../common/units.js';\nimport {ChangeElementCommand, BatchCommand} from './history.js';\nimport {\n transformPoint, getMatrix, snapToAngle, rectsIntersect,\n transformListToTransform\n} from '../common/math.js';\nimport {\n assignAttributes, getElem, getRotationAngle, getBBox,\n getRefElem, findDefs, snapToGrid, isNullish,\n getBBox as utilsGetBBox\n} from '../common/utilities.js';\nimport {\n supportsPathInsertItemBefore, supportsPathReplaceItem, isWebkit\n} from '../common/browser.js';\n\nconst $ = jQuery;\n\nconst segData = {\n 2: ['x', 'y'], // PATHSEG_MOVETO_ABS\n 4: ['x', 'y'], // PATHSEG_LINETO_ABS\n 6: ['x', 'y', 'x1', 'y1', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_ABS\n 8: ['x', 'y', 'x1', 'y1'], // PATHSEG_CURVETO_QUADRATIC_ABS\n 10: ['x', 'y', 'r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag'], // PATHSEG_ARC_ABS\n 12: ['x'], // PATHSEG_LINETO_HORIZONTAL_ABS\n 14: ['y'], // PATHSEG_LINETO_VERTICAL_ABS\n 16: ['x', 'y', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_SMOOTH_ABS\n 18: ['x', 'y'] // PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS\n};\n\n/**\n * @tutorial LocaleDocs\n * @typedef {module:locale.LocaleStrings|PlainObject} module:path.uiStrings\n * @property {PlainObject<string, string>} ui\n*/\n\nconst uiStrings = {};\n/**\n* @function module:path.setUiStrings\n* @param {module:path.uiStrings} strs\n* @returns {void}\n*/\nexport const setUiStrings = function (strs) {\n Object.assign(uiStrings, strs.ui);\n};\n\nlet pathFuncs = [];\n\nlet linkControlPts = true;\n\n// Stores references to paths via IDs.\n// TODO: Make this cross-document happy.\nlet pathData = {};\n\n/**\n* @function module:path.setLinkControlPoints\n* @param {boolean} lcp\n* @returns {void}\n*/\nexport const setLinkControlPoints = function (lcp) {\n linkControlPts = lcp;\n};\n\n/**\n * @name module:path.path\n * @type {null|module:path.Path}\n * @memberof module:path\n*/\nexport let path = null; // eslint-disable-line import/no-mutable-exports\n\nlet editorContext_ = null;\n\n/**\n* @external MouseEvent\n*/\n\n/**\n* Object with the following keys/values.\n* @typedef {PlainObject} module:path.SVGElementJSON\n* @property {string} element - Tag name of the SVG element to create\n* @property {PlainObject<string, string>} attr - Has key-value attributes to assign to the new element. An `id` should be set so that {@link module:utilities.EditorContext#addSVGElementFromJson} can later re-identify the element for modification or replacement.\n* @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first\n* @property {module:path.SVGElementJSON[]} [children] - Data objects to be added recursively as children\n* @property {string} [namespace=\"http://www.w3.org/2000/svg\"] - Indicate a (non-SVG) namespace\n*/\n/**\n * @interface module:path.EditorContext\n * @property {module:select.SelectorManager} selectorManager\n * @property {module:svgcanvas.SvgCanvas} canvas\n */\n/**\n * @function module:path.EditorContext#call\n * @param {\"selected\"|\"changed\"} ev - String with the event name\n * @param {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed} arg - Argument to pass through to the callback function. If the event is \"changed\", an array of `Element`s is passed; if \"selected\", a single-item array of `Element` is passed.\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#resetD\n * @param {SVGPathElement} p\n * @returns {void}\n*/\n/**\n * Note: This doesn't round to an integer necessarily.\n * @function module:path.EditorContext#round\n * @param {Float} val\n * @returns {Float} Rounded value to nearest value based on `currentZoom`\n */\n/**\n * @function module:path.EditorContext#clearSelection\n * @param {boolean} [noCall] - When `true`, does not call the \"selected\" handler\n * @returns {void}\n*/\n/**\n * @function module:path.EditorContext#addToSelection\n * @param {Element[]} elemsToAdd - An array of DOM elements to add to the selection\n * @param {boolean} showGrips - Indicates whether the resize grips should be shown\n * @returns {void}\n*/\n/**\n * @function module:path.EditorContext#addCommandToHistory\n * @param {Command} cmd\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#remapElement\n * @param {Element} selected - DOM element to be changed\n * @param {PlainObject<string, string>} changes - Object with changes to be remapped\n * @param {SVGMatrix} m - Matrix object to use for remapping coordinates\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#addSVGElementFromJson\n * @param {module:path.SVGElementJSON} data\n * @returns {Element} The new element\n*/\n/**\n * @function module:path.EditorContext#getGridSnapping\n * @returns {boolean}\n */\n/**\n * @function module:path.EditorContext#getOpacity\n * @returns {Float}\n */\n/**\n * @function module:path.EditorContext#getSelectedElements\n * @returns {Element[]} the array with selected DOM elements\n*/\n/**\n * @function module:path.EditorContext#getContainer\n * @returns {Element}\n */\n/**\n * @function module:path.EditorContext#setStarted\n * @param {boolean} s\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#getRubberBox\n * @returns {SVGRectElement}\n*/\n/**\n * @function module:path.EditorContext#setRubberBox\n * @param {SVGRectElement} rb\n * @returns {SVGRectElement} Same as parameter passed in\n */\n/**\n * @function module:path.EditorContext#addPtsToSelection\n * @param {PlainObject} cfg\n * @param {boolean} cfg.closedSubpath\n * @param {SVGCircleElement[]} cfg.grips\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#endChanges\n * @param {PlainObject} cfg\n * @param {string} cfg.cmd\n * @param {Element} cfg.elem\n * @returns {void}\n*/\n/**\n * @function module:path.EditorContext#getCurrentZoom\n * @returns {Float} The current zoom level\n */\n/**\n * Returns the last created DOM element ID string.\n * @function module:path.EditorContext#getId\n * @returns {string}\n */\n/**\n * Creates and returns a unique ID string for a DOM element.\n * @function module:path.EditorContext#getNextId\n * @returns {string}\n*/\n/**\n * Gets the desired element from a mouse event.\n * @function module:path.EditorContext#getMouseTarget\n * @param {external:MouseEvent} evt - Event object from the mouse event\n * @returns {Element} DOM element we want\n */\n/**\n * @function module:path.EditorContext#getCurrentMode\n * @returns {string}\n */\n/**\n * @function module:path.EditorContext#setCurrentMode\n * @param {string} cm The mode\n * @returns {string} The same mode as passed in\n*/\n/**\n * @function module:path.EditorContext#getDrawnPath\n * @returns {SVGPathElement|null}\n */\n/**\n * @function module:path.EditorContext#setDrawnPath\n * @param {SVGPathElement|null} dp\n * @returns {SVGPathElement|null} The same value as passed in\n */\n/**\n * @function module:path.EditorContext#getSVGRoot\n * @returns {SVGSVGElement}\n*/\n\n/**\n* @function module:path.init\n* @param {module:path.EditorContext} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n editorContext_ = editorContext;\n\n pathFuncs = [0, 'ClosePath'];\n const pathFuncsStrs = [\n 'Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc',\n 'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth'\n ];\n $.each(pathFuncsStrs, function (i, s) {\n pathFuncs.push(s + 'Abs');\n pathFuncs.push(s + 'Rel');\n });\n};\n\n/**\n* @function module:path.insertItemBefore\n* @param {Element} elem\n* @param {Segment} newseg\n* @param {Integer} index\n* @returns {void}\n*/\nexport const insertItemBefore = function (elem, newseg, index) {\n // Support insertItemBefore on paths for FF2\n const list = elem.pathSegList;\n\n if (supportsPathInsertItemBefore()) {\n list.insertItemBefore(newseg, index);\n return;\n }\n const len = list.numberOfItems;\n const arr = [];\n for (let i = 0; i < len; i++) {\n const curSeg = list.getItem(i);\n arr.push(curSeg);\n }\n list.clear();\n for (let i = 0; i < len; i++) {\n if (i === index) { // index + 1\n list.appendItem(newseg);\n }\n list.appendItem(arr[i]);\n }\n};\n\n/**\n* @function module:path.ptObjToArr\n* @todo See if this should just live in `replacePathSeg`\n* @param {string} type\n* @param {SVGPathSegMovetoAbs|SVGPathSegLinetoAbs|SVGPathSegCurvetoCubicAbs|SVGPathSegCurvetoQuadraticAbs|SVGPathSegArcAbs|SVGPathSegLinetoHorizontalAbs|SVGPathSegLinetoVerticalAbs|SVGPathSegCurvetoCubicSmoothAbs|SVGPathSegCurvetoQuadraticSmoothAbs} segItem\n* @returns {ArgumentsArray}\n*/\nexport const ptObjToArr = function (type, segItem) {\n const props = segData[type];\n return props.map((prop) => {\n return segItem[prop];\n });\n};\n\n/**\n* @function module:path.getGripPt\n* @param {Segment} seg\n* @param {module:math.XYObject} altPt\n* @returns {module:math.XYObject}\n*/\nexport const getGripPt = function (seg, altPt) {\n const {path: pth} = seg;\n let out = {\n x: altPt ? altPt.x : seg.item.x,\n y: altPt ? altPt.y : seg.item.y\n };\n\n if (pth.matrix) {\n const pt = transformPoint(out.x, out.y, pth.matrix);\n out = pt;\n }\n\n const currentZoom = editorContext_.getCurrentZoom();\n out.x *= currentZoom;\n out.y *= currentZoom;\n\n return out;\n};\n\n/**\n* @function module:path.getPointFromGrip\n* @param {module:math.XYObject} pt\n* @param {module:path.Path} pth\n* @returns {module:math.XYObject}\n*/\nexport const getPointFromGrip = function (pt, pth) {\n const out = {\n x: pt.x,\n y: pt.y\n };\n\n if (pth.matrix) {\n pt = transformPoint(out.x, out.y, pth.imatrix);\n out.x = pt.x;\n out.y = pt.y;\n }\n\n const currentZoom = editorContext_.getCurrentZoom();\n out.x /= currentZoom;\n out.y /= currentZoom;\n\n return out;\n};\n\n/**\n* Requires prior call to `setUiStrings` if `xlink:title`\n* to be set on the grip.\n* @function module:path.addPointGrip\n* @param {Integer} index\n* @param {Integer} x\n* @param {Integer} y\n* @returns {SVGCircleElement}\n*/\nexport const addPointGrip = function (index, x, y) {\n // create the container of all the point grips\n const pointGripContainer = getGripContainer();\n\n let pointGrip = getElem('pathpointgrip_' + index);\n // create it\n if (!pointGrip) {\n pointGrip = document.createElementNS(NS.SVG, 'circle');\n const atts = {\n id: 'pathpointgrip_' + index,\n display: 'none',\n r: 4,\n fill: '#0FF',\n stroke: '#00F',\n 'stroke-width': 2,\n cursor: 'move',\n style: 'pointer-events:all'\n };\n if ('pathNodeTooltip' in uiStrings) { // May be empty if running path.js without svg-editor\n atts['xlink:title'] = uiStrings.pathNodeTooltip;\n }\n assignAttributes(pointGrip, atts);\n pointGrip = pointGripContainer.appendChild(pointGrip);\n\n const grip = $('#pathpointgrip_' + index);\n grip.dblclick(function () {\n if (path) {\n path.setSegType();\n }\n });\n }\n if (x && y) {\n // set up the point grip element and display it\n assignAttributes(pointGrip, {\n cx: x,\n cy: y,\n display: 'inline'\n });\n }\n return pointGrip;\n};\n\n/**\n* @function module:path.getGripContainer\n* @returns {Element}\n*/\nexport const getGripContainer = function () {\n let c = getElem('pathpointgrip_container');\n if (!c) {\n const parentElement = getElem('selectorParentGroup');\n c = parentElement.appendChild(document.createElementNS(NS.SVG, 'g'));\n c.id = 'pathpointgrip_container';\n }\n return c;\n};\n\n/**\n* Requires prior call to `setUiStrings` if `xlink:title`\n* to be set on the grip.\n* @function module:path.addCtrlGrip\n* @param {string} id\n* @returns {SVGCircleElement}\n*/\nexport const addCtrlGrip = function (id) {\n let pointGrip = getElem('ctrlpointgrip_' + id);\n if (pointGrip) { return pointGrip; }\n\n pointGrip = document.createElementNS(NS.SVG, 'circle');\n const atts = {\n id: 'ctrlpointgrip_' + id,\n display: 'none',\n r: 4,\n fill: '#0FF',\n stroke: '#55F',\n 'stroke-width': 1,\n cursor: 'move',\n style: 'pointer-events:all'\n };\n if ('pathCtrlPtTooltip' in uiStrings) { // May be empty if running path.js without svg-editor\n atts['xlink:title'] = uiStrings.pathCtrlPtTooltip;\n }\n assignAttributes(pointGrip, atts);\n getGripContainer().append(pointGrip);\n return pointGrip;\n};\n\n/**\n* @function module:path.getCtrlLine\n* @param {string} id\n* @returns {SVGLineElement}\n*/\nexport const getCtrlLine = function (id) {\n let ctrlLine = getElem('ctrlLine_' + id);\n if (ctrlLine) { return ctrlLine; }\n\n ctrlLine = document.createElementNS(NS.SVG, 'line');\n assignAttributes(ctrlLine, {\n id: 'ctrlLine_' + id,\n stroke: '#555',\n 'stroke-width': 1,\n style: 'pointer-events:none'\n });\n getGripContainer().append(ctrlLine);\n return ctrlLine;\n};\n\n/**\n* @function module:path.getPointGrip\n* @param {Segment} seg\n* @param {boolean} update\n* @returns {SVGCircleElement}\n*/\nexport const getPointGrip = function (seg, update) {\n const {index} = seg;\n const pointGrip = addPointGrip(index);\n\n if (update) {\n const pt = getGripPt(seg);\n assignAttributes(pointGrip, {\n cx: pt.x,\n cy: pt.y,\n display: 'inline'\n });\n }\n\n return pointGrip;\n};\n\n/**\n* @function module:path.getControlPoints\n* @param {Segment} seg\n* @returns {PlainObject<string, SVGLineElement|SVGCircleElement>}\n*/\nexport const getControlPoints = function (seg) {\n const {item, index} = seg;\n if (!('x1' in item) || !('x2' in item)) { return null; }\n const cpt = {};\n /* const pointGripContainer = */ getGripContainer();\n\n // Note that this is intentionally not seg.prev.item\n const prev = path.segs[index - 1].item;\n\n const segItems = [prev, item];\n\n for (let i = 1; i < 3; i++) {\n const id = index + 'c' + i;\n\n const ctrlLine = cpt['c' + i + '_line'] = getCtrlLine(id);\n\n const pt = getGripPt(seg, {x: item['x' + i], y: item['y' + i]});\n const gpt = getGripPt(seg, {x: segItems[i - 1].x, y: segItems[i - 1].y});\n\n assignAttributes(ctrlLine, {\n x1: pt.x,\n y1: pt.y,\n x2: gpt.x,\n y2: gpt.y,\n display: 'inline'\n });\n\n cpt['c' + i + '_line'] = ctrlLine;\n\n // create it\n const pointGrip = cpt['c' + i] = addCtrlGrip(id);\n\n assignAttributes(pointGrip, {\n cx: pt.x,\n cy: pt.y,\n display: 'inline'\n });\n cpt['c' + i] = pointGrip;\n }\n return cpt;\n};\n\n/**\n* This replaces the segment at the given index. Type is given as number.\n* @function module:path.replacePathSeg\n* @param {Integer} type Possible values set during {@link module:path.init}\n* @param {Integer} index\n* @param {ArgumentsArray} pts\n* @param {SVGPathElement} elem\n* @returns {void}\n*/\nexport const replacePathSeg = function (type, index, pts, elem) {\n const pth = elem || path.elem;\n\n const func = 'createSVGPathSeg' + pathFuncs[type];\n const seg = pth[func](...pts);\n\n if (supportsPathReplaceItem()) {\n pth.pathSegList.replaceItem(seg, index);\n } else {\n const segList = pth.pathSegList;\n const len = segList.numberOfItems;\n const arr = [];\n for (let i = 0; i < len; i++) {\n const curSeg = segList.getItem(i);\n arr.push(curSeg);\n }\n segList.clear();\n for (let i = 0; i < len; i++) {\n if (i === index) {\n segList.appendItem(seg);\n } else {\n segList.appendItem(arr[i]);\n }\n }\n }\n};\n\n/**\n* @function module:path.getSegSelector\n* @param {Segment} seg\n* @param {boolean} update\n* @returns {SVGPathElement}\n*/\nexport const getSegSelector = function (seg, update) {\n const {index} = seg;\n let segLine = getElem('segline_' + index);\n if (!segLine) {\n const pointGripContainer = getGripContainer();\n // create segline\n segLine = document.createElementNS(NS.SVG, 'path');\n assignAttributes(segLine, {\n id: 'segline_' + index,\n display: 'none',\n fill: 'none',\n stroke: '#0FF',\n 'stroke-width': 2,\n style: 'pointer-events:none',\n d: 'M0,0 0,0'\n });\n pointGripContainer.append(segLine);\n }\n\n if (update) {\n const {prev} = seg;\n if (!prev) {\n segLine.setAttribute('display', 'none');\n return segLine;\n }\n\n const pt = getGripPt(prev);\n // Set start point\n replacePathSeg(2, 0, [pt.x, pt.y], segLine);\n\n const pts = ptObjToArr(seg.type, seg.item); // , true);\n for (let i = 0; i < pts.length; i += 2) {\n const point = getGripPt(seg, {x: pts[i], y: pts[i + 1]});\n pts[i] = point.x;\n pts[i + 1] = point.y;\n }\n\n replacePathSeg(seg.type, 1, pts, segLine);\n }\n return segLine;\n};\n\n/**\n * @typedef {PlainObject} Point\n * @property {Integer} x The x value\n * @property {Integer} y The y value\n */\n\n/**\n* Takes three points and creates a smoother line based on them.\n* @function module:path.smoothControlPoints\n* @param {Point} ct1 - Object with x and y values (first control point)\n* @param {Point} ct2 - Object with x and y values (second control point)\n* @param {Point} pt - Object with x and y values (third point)\n* @returns {Point[]} Array of two \"smoothed\" point objects\n*/\nexport const smoothControlPoints = function (ct1, ct2, pt) {\n // each point must not be the origin\n const x1 = ct1.x - pt.x,\n y1 = ct1.y - pt.y,\n x2 = ct2.x - pt.x,\n y2 = ct2.y - pt.y;\n\n if ((x1 !== 0 || y1 !== 0) && (x2 !== 0 || y2 !== 0)) {\n const\n r1 = Math.sqrt(x1 * x1 + y1 * y1),\n r2 = Math.sqrt(x2 * x2 + y2 * y2),\n nct1 = editorContext_.getSVGRoot().createSVGPoint(),\n nct2 = editorContext_.getSVGRoot().createSVGPoint();\n let anglea = Math.atan2(y1, x1),\n angleb = Math.atan2(y2, x2);\n if (anglea < 0) { anglea += 2 * Math.PI; }\n if (angleb < 0) { angleb += 2 * Math.PI; }\n\n const angleBetween = Math.abs(anglea - angleb),\n angleDiff = Math.abs(Math.PI - angleBetween) / 2;\n\n let newAnglea, newAngleb;\n if (anglea - angleb > 0) {\n newAnglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff);\n newAngleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff);\n } else {\n newAnglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff);\n newAngleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff);\n }\n\n // rotate the points\n nct1.x = r1 * Math.cos(newAnglea) + pt.x;\n nct1.y = r1 * Math.sin(newAnglea) + pt.y;\n nct2.x = r2 * Math.cos(newAngleb) + pt.x;\n nct2.y = r2 * Math.sin(newAngleb) + pt.y;\n\n return [nct1, nct2];\n }\n return undefined;\n};\n\n/**\n*\n*/\nexport class Segment {\n /**\n * @param {Integer} index\n * @param {SVGPathSeg} item\n * @todo Is `item` be more constrained here?\n */\n constructor (index, item) {\n this.selected = false;\n this.index = index;\n this.item = item;\n this.type = item.pathSegType;\n\n this.ctrlpts = [];\n this.ptgrip = null;\n this.segsel = null;\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n showCtrlPts (y) {\n for (const i in this.ctrlpts) {\n if ({}.hasOwnProperty.call(this.ctrlpts, i)) {\n this.ctrlpts[i].setAttribute('display', y ? 'inline' : 'none');\n }\n }\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n selectCtrls (y) {\n $('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2')\n .attr('fill', y ? '#0FF' : '#EEE');\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n show (y) {\n if (this.ptgrip) {\n this.ptgrip.setAttribute('display', y ? 'inline' : 'none');\n this.segsel.setAttribute('display', y ? 'inline' : 'none');\n // Show/hide all control points if available\n this.showCtrlPts(y);\n }\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n select (y) {\n if (this.ptgrip) {\n this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F');\n this.segsel.setAttribute('display', y ? 'inline' : 'none');\n if (this.ctrlpts) {\n this.selectCtrls(y);\n }\n this.selected = y;\n }\n }\n\n /**\n * @returns {void}\n */\n addGrip () {\n this.ptgrip = getPointGrip(this, true);\n this.ctrlpts = getControlPoints(this); // , true);\n this.segsel = getSegSelector(this, true);\n }\n\n /**\n * @param {boolean} full\n * @returns {void}\n */\n update (full) {\n if (this.ptgrip) {\n const pt = getGripPt(this);\n assignAttributes(this.ptgrip, {\n cx: pt.x,\n cy: pt.y\n });\n\n getSegSelector(this, true);\n\n if (this.ctrlpts) {\n if (full) {\n this.item = path.elem.pathSegList.getItem(this.index);\n this.type = this.item.pathSegType;\n }\n getControlPoints(this);\n }\n // this.segsel.setAttribute('display', y ? 'inline' : 'none');\n }\n }\n\n /**\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n move (dx, dy) {\n const {item} = this;\n\n const curPts = this.ctrlpts\n ? [\n item.x += dx, item.y += dy,\n item.x1, item.y1, item.x2 += dx, item.y2 += dy\n ]\n : [item.x += dx, item.y += dy];\n\n replacePathSeg(\n this.type,\n this.index,\n // type 10 means ARC\n this.type === 10 ? ptObjToArr(this.type, item) : curPts\n );\n\n if (this.next && this.next.ctrlpts) {\n const next = this.next.item;\n const nextPts = [\n next.x, next.y,\n next.x1 += dx, next.y1 += dy, next.x2, next.y2\n ];\n replacePathSeg(this.next.type, this.next.index, nextPts);\n }\n\n if (this.mate) {\n // The last point of a closed subpath has a 'mate',\n // which is the 'M' segment of the subpath\n const {item: itm} = this.mate;\n const pts = [itm.x += dx, itm.y += dy];\n replacePathSeg(this.mate.type, this.mate.index, pts);\n // Has no grip, so does not need 'updating'?\n }\n\n this.update(true);\n if (this.next) { this.next.update(true); }\n }\n\n /**\n * @param {Integer} num\n * @returns {void}\n */\n setLinked (num) {\n let seg, anum, pt;\n if (num === 2) {\n anum = 1;\n seg = this.next;\n if (!seg) { return; }\n pt = this.item;\n } else {\n anum = 2;\n seg = this.prev;\n if (!seg) { return; }\n pt = seg.item;\n }\n\n const {item} = seg;\n item['x' + anum] = pt.x + (pt.x - this.item['x' + num]);\n item['y' + anum] = pt.y + (pt.y - this.item['y' + num]);\n\n const pts = [\n item.x, item.y,\n item.x1, item.y1,\n item.x2, item.y2\n ];\n\n replacePathSeg(seg.type, seg.index, pts);\n seg.update(true);\n }\n\n /**\n * @param {Integer} num\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n moveCtrl (num, dx, dy) {\n const {item} = this;\n item['x' + num] += dx;\n item['y' + num] += dy;\n\n const pts = [\n item.x, item.y,\n item.x1, item.y1, item.x2, item.y2\n ];\n\n replacePathSeg(this.type, this.index, pts);\n this.update(true);\n }\n\n /**\n * @param {Integer} newType Possible values set during {@link module:path.init}\n * @param {ArgumentsArray} pts\n * @returns {void}\n */\n setType (newType, pts) {\n replacePathSeg(newType, this.index, pts);\n this.type = newType;\n this.item = path.elem.pathSegList.getItem(this.index);\n this.showCtrlPts(newType === 6);\n this.ctrlpts = getControlPoints(this);\n this.update(true);\n }\n}\n\n/**\n*\n*/\nexport class Path {\n /**\n * @param {SVGPathElement} elem\n * @throws {Error} If constructed without a path element\n */\n constructor (elem) {\n if (!elem || elem.tagName !== 'path') {\n throw new Error('svgedit.path.Path constructed without a <path> element');\n }\n\n this.elem = elem;\n this.segs = [];\n this.selected_pts = [];\n path = this; // eslint-disable-line consistent-this\n\n this.init();\n }\n\n /**\n * Reset path data.\n * @returns {module:path.Path}\n */\n init () {\n // Hide all grips, etc\n\n // fixed, needed to work on all found elements, not just first\n $(getGripContainer()).find('*').each(function () {\n $(this).attr('display', 'none');\n });\n\n const segList = this.elem.pathSegList;\n const len = segList.numberOfItems;\n this.segs = [];\n this.selected_pts = [];\n this.first_seg = null;\n\n // Set up segs array\n for (let i = 0; i < len; i++) {\n const item = segList.getItem(i);\n const segment = new Segment(i, item);\n segment.path = this;\n this.segs.push(segment);\n }\n\n const {segs} = this;\n\n let startI = null;\n for (let i = 0; i < len; i++) {\n const seg = segs[i];\n const nextSeg = (i + 1) >= len ? null : segs[i + 1];\n const prevSeg = (i - 1) < 0 ? null : segs[i - 1];\n if (seg.type === 2) {\n if (prevSeg && prevSeg.type !== 1) {\n // New sub-path, last one is open,\n // so add a grip to last sub-path's first point\n const startSeg = segs[startI];\n startSeg.next = segs[startI + 1];\n startSeg.next.prev = startSeg;\n startSeg.addGrip();\n }\n // Remember that this is a starter seg\n startI = i;\n } else if (nextSeg && nextSeg.type === 1) {\n // This is the last real segment of a closed sub-path\n // Next is first seg after \"M\"\n seg.next = segs[startI + 1];\n\n // First seg after \"M\"'s prev is this\n seg.next.prev = seg;\n seg.mate = segs[startI];\n seg.addGrip();\n if (isNullish(this.first_seg)) {\n this.first_seg = seg;\n }\n } else if (!nextSeg) {\n if (seg.type !== 1) {\n // Last seg, doesn't close so add a grip\n // to last sub-path's first point\n const startSeg = segs[startI];\n startSeg.next = segs[startI + 1];\n startSeg.next.prev = startSeg;\n startSeg.addGrip();\n seg.addGrip();\n\n if (!this.first_seg) {\n // Open path, so set first as real first and add grip\n this.first_seg = segs[startI];\n }\n }\n } else if (seg.type !== 1) {\n // Regular segment, so add grip and its \"next\"\n seg.addGrip();\n\n // Don't set its \"next\" if it's an \"M\"\n if (nextSeg && nextSeg.type !== 2) {\n seg.next = nextSeg;\n seg.next.prev = seg;\n }\n }\n }\n return this;\n }\n\n /**\n * @callback module:path.PathEachSegCallback\n * @this module:path.Segment\n * @param {Integer} i The index of the seg being iterated\n * @returns {boolean|void} Will stop execution of `eachSeg` if returns `false`\n */\n /**\n * @param {module:path.PathEachSegCallback} fn\n * @returns {void}\n */\n eachSeg (fn) {\n const len = this.segs.length;\n for (let i = 0; i < len; i++) {\n const ret = fn.call(this.segs[i], i);\n if (ret === false) { break; }\n }\n }\n\n /**\n * @param {Integer} index\n * @returns {void}\n */\n addSeg (index) {\n // Adds a new segment\n const seg = this.segs[index];\n if (!seg.prev) { return; }\n\n const {prev} = seg;\n let newseg, newX, newY;\n switch (seg.item.pathSegType) {\n case 4: {\n newX = (seg.item.x + prev.item.x) / 2;\n newY = (seg.item.y + prev.item.y) / 2;\n newseg = this.elem.createSVGPathSegLinetoAbs(newX, newY);\n break;\n } case 6: { // make it a curved segment to preserve the shape (WRS)\n // https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation\n const p0x = (prev.item.x + seg.item.x1) / 2;\n const p1x = (seg.item.x1 + seg.item.x2) / 2;\n const p2x = (seg.item.x2 + seg.item.x) / 2;\n const p01x = (p0x + p1x) / 2;\n const p12x = (p1x + p2x) / 2;\n newX = (p01x + p12x) / 2;\n const p0y = (prev.item.y + seg.item.y1) / 2;\n const p1y = (seg.item.y1 + seg.item.y2) / 2;\n const p2y = (seg.item.y2 + seg.item.y) / 2;\n const p01y = (p0y + p1y) / 2;\n const p12y = (p1y + p2y) / 2;\n newY = (p01y + p12y) / 2;\n newseg = this.elem.createSVGPathSegCurvetoCubicAbs(newX, newY, p0x, p0y, p01x, p01y);\n const pts = [seg.item.x, seg.item.y, p12x, p12y, p2x, p2y];\n replacePathSeg(seg.type, index, pts);\n break;\n }\n }\n\n insertItemBefore(this.elem, newseg, index);\n }\n\n /**\n * @param {Integer} index\n * @returns {void}\n */\n deleteSeg (index) {\n const seg = this.segs[index];\n const list = this.elem.pathSegList;\n\n seg.show(false);\n const {next} = seg;\n if (seg.mate) {\n // Make the next point be the \"M\" point\n const pt = [next.item.x, next.item.y];\n replacePathSeg(2, next.index, pt);\n\n // Reposition last node\n replacePathSeg(4, seg.index, pt);\n\n list.removeItem(seg.mate.index);\n } else if (!seg.prev) {\n // First node of open path, make next point the M\n // const {item} = seg;\n const pt = [next.item.x, next.item.y];\n replacePathSeg(2, seg.next.index, pt);\n list.removeItem(index);\n } else {\n list.removeItem(index);\n }\n }\n\n /**\n * @param {Integer} index\n * @returns {void}\n */\n removePtFromSelection (index) {\n const pos = this.selected_pts.indexOf(index);\n if (pos === -1) {\n return;\n }\n this.segs[index].select(false);\n this.selected_pts.splice(pos, 1);\n }\n\n /**\n * @returns {void}\n */\n clearSelection () {\n this.eachSeg(function () {\n // 'this' is the segment here\n this.select(false);\n });\n this.selected_pts = [];\n }\n\n /**\n * @returns {void}\n */\n storeD () {\n this.last_d = this.elem.getAttribute('d');\n }\n\n /**\n * @param {Integer} y\n * @returns {Path}\n */\n show (y) {\n // Shows this path's segment grips\n this.eachSeg(function () {\n // 'this' is the segment here\n this.show(y);\n });\n if (y) {\n this.selectPt(this.first_seg.index);\n }\n return this;\n }\n\n /**\n * Move selected points.\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n movePts (dx, dy) {\n let i = this.selected_pts.length;\n while (i--) {\n const seg = this.segs[this.selected_pts[i]];\n seg.move(dx, dy);\n }\n }\n\n /**\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n moveCtrl (dx, dy) {\n const seg = this.segs[this.selected_pts[0]];\n seg.moveCtrl(this.dragctrl, dx, dy);\n if (linkControlPts) {\n seg.setLinked(this.dragctrl);\n }\n }\n\n /**\n * @param {?Integer} newType See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg}\n * @returns {void}\n */\n setSegType (newType) {\n this.storeD();\n let i = this.selected_pts.length;\n let text;\n while (i--) {\n const selPt = this.selected_pts[i];\n\n // Selected seg\n const cur = this.segs[selPt];\n const {prev} = cur;\n if (!prev) { continue; }\n\n if (!newType) { // double-click, so just toggle\n text = 'Toggle Path Segment Type';\n\n // Toggle segment to curve/straight line\n const oldType = cur.type;\n\n newType = (oldType === 6) ? 4 : 6;\n }\n\n newType = Number(newType);\n\n const curX = cur.item.x;\n const curY = cur.item.y;\n const prevX = prev.item.x;\n const prevY = prev.item.y;\n let points;\n switch (newType) {\n case 6: {\n if (cur.olditem) {\n const old = cur.olditem;\n points = [curX, curY, old.x1, old.y1, old.x2, old.y2];\n } else {\n const diffX = curX - prevX;\n const diffY = curY - prevY;\n // get control points from straight line segment\n /*\n const ct1x = (prevX + (diffY/2));\n const ct1y = (prevY - (diffX/2));\n const ct2x = (curX + (diffY/2));\n const ct2y = (curY - (diffX/2));\n */\n // create control points on the line to preserve the shape (WRS)\n const ct1x = (prevX + (diffX / 3));\n const ct1y = (prevY + (diffY / 3));\n const ct2x = (curX - (diffX / 3));\n const ct2y = (curY - (diffY / 3));\n points = [curX, curY, ct1x, ct1y, ct2x, ct2y];\n }\n break;\n } case 4: {\n points = [curX, curY];\n\n // Store original prevve segment nums\n cur.olditem = cur.item;\n break;\n }\n }\n\n cur.setType(newType, points);\n }\n path.endChanges(text);\n }\n\n /**\n * @param {Integer} pt\n * @param {Integer} ctrlNum\n * @returns {void}\n */\n selectPt (pt, ctrlNum) {\n this.clearSelection();\n if (isNullish(pt)) {\n this.eachSeg(function (i) {\n // 'this' is the segment here.\n if (this.prev) {\n pt = i;\n }\n });\n }\n this.addPtsToSelection(pt);\n if (ctrlNum) {\n this.dragctrl = ctrlNum;\n\n if (linkControlPts) {\n this.segs[pt].setLinked(ctrlNum);\n }\n }\n }\n\n /**\n * Update position of all points.\n * @returns {Path}\n */\n update () {\n const {elem} = this;\n if (getRotationAngle(elem)) {\n this.matrix = getMatrix(elem);\n this.imatrix = this.matrix.inverse();\n } else {\n this.matrix = null;\n this.imatrix = null;\n }\n\n this.eachSeg(function (i) {\n this.item = elem.pathSegList.getItem(i);\n this.update();\n });\n\n return this;\n }\n\n /**\n * @param {string} text\n * @returns {void}\n */\n endChanges (text) {\n if (isWebkit()) { editorContext_.resetD(this.elem); }\n const cmd = new ChangeElementCommand(this.elem, {d: this.last_d}, text);\n editorContext_.endChanges({cmd, elem: this.elem});\n }\n\n /**\n * @param {Integer|Integer[]} indexes\n * @returns {void}\n */\n addPtsToSelection (indexes) {\n if (!Array.isArray(indexes)) { indexes = [indexes]; }\n indexes.forEach((index) => {\n const seg = this.segs[index];\n if (seg.ptgrip) {\n if (!this.selected_pts.includes(index) && index >= 0) {\n this.selected_pts.push(index);\n }\n }\n });\n this.selected_pts.sort();\n let i = this.selected_pts.length;\n const grips = [];\n grips.length = i;\n // Loop through points to be selected and highlight each\n while (i--) {\n const pt = this.selected_pts[i];\n const seg = this.segs[pt];\n seg.select(true);\n grips[i] = seg.ptgrip;\n }\n\n const closedSubpath = Path.subpathIsClosed(this.selected_pts[0]);\n editorContext_.addPtsToSelection({grips, closedSubpath});\n }\n\n // STATIC\n /**\n * @param {Integer} index\n * @returns {boolean}\n */\n static subpathIsClosed (index) {\n let clsd = false;\n // Check if subpath is already open\n path.eachSeg(function (i) {\n if (i <= index) { return true; }\n if (this.type === 2) {\n // Found M first, so open\n return false;\n }\n if (this.type === 1) {\n // Found Z first, so closed\n clsd = true;\n return false;\n }\n return true;\n });\n\n return clsd;\n }\n}\n\n/**\n* @function module:path.getPath_\n* @param {SVGPathElement} elem\n* @returns {module:path.Path}\n*/\nexport const getPath_ = function (elem) {\n let p = pathData[elem.id];\n if (!p) {\n p = pathData[elem.id] = new Path(elem);\n }\n return p;\n};\n\n/**\n* @function module:path.removePath_\n* @param {string} id\n* @returns {void}\n*/\nexport const removePath_ = function (id) {\n if (id in pathData) { delete pathData[id]; }\n};\n\nlet newcx, newcy, oldcx, oldcy, angle;\n\nconst getRotVals = function (x, y) {\n let dx = x - oldcx;\n let dy = y - oldcy;\n\n // rotate the point around the old center\n let r = Math.sqrt(dx * dx + dy * dy);\n let theta = Math.atan2(dy, dx) + angle;\n dx = r * Math.cos(theta) + oldcx;\n dy = r * Math.sin(theta) + oldcy;\n\n // dx,dy should now hold the actual coordinates of each\n // point after being rotated\n\n // now we want to rotate them around the new center in the reverse direction\n dx -= newcx;\n dy -= newcy;\n\n r = Math.sqrt(dx * dx + dy * dy);\n theta = Math.atan2(dy, dx) - angle;\n\n return {x: r * Math.cos(theta) + newcx,\n y: r * Math.sin(theta) + newcy};\n};\n\n// If the path was rotated, we must now pay the piper:\n// Every path point must be rotated into the rotated coordinate system of\n// its old center, then determine the new center, then rotate it back\n// This is because we want the path to remember its rotation\n\n/**\n* @function module:path.recalcRotatedPath\n* @todo This is still using ye olde transform methods, can probably\n* be optimized or even taken care of by `recalculateDimensions`\n* @returns {void}\n*/\nexport const recalcRotatedPath = function () {\n const currentPath = path.elem;\n angle = getRotationAngle(currentPath, true);\n if (!angle) { return; }\n // selectedBBoxes[0] = path.oldbbox;\n const oldbox = path.oldbbox; // selectedBBoxes[0],\n oldcx = oldbox.x + oldbox.width / 2;\n oldcy = oldbox.y + oldbox.height / 2;\n const box = getBBox(currentPath);\n newcx = box.x + box.width / 2;\n newcy = box.y + box.height / 2;\n\n // un-rotate the new center to the proper position\n const dx = newcx - oldcx,\n dy = newcy - oldcy,\n r = Math.sqrt(dx * dx + dy * dy),\n theta = Math.atan2(dy, dx) + angle;\n\n newcx = r * Math.cos(theta) + oldcx;\n newcy = r * Math.sin(theta) + oldcy;\n\n const list = currentPath.pathSegList;\n\n let i = list.numberOfItems;\n while (i) {\n i -= 1;\n const seg = list.getItem(i),\n type = seg.pathSegType;\n if (type === 1) { continue; }\n\n const rvals = getRotVals(seg.x, seg.y),\n points = [rvals.x, rvals.y];\n if (!isNullish(seg.x1) && !isNullish(seg.x2)) {\n const cVals1 = getRotVals(seg.x1, seg.y1);\n const cVals2 = getRotVals(seg.x2, seg.y2);\n points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y);\n }\n replacePathSeg(type, i, points);\n } // loop for each point\n\n /* box = */ getBBox(currentPath);\n // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y;\n // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height;\n\n // now we must set the new transform to be rotated around the new center\n const Rnc = editorContext_.getSVGRoot().createSVGTransform(),\n tlist = getTransformList(currentPath);\n Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);\n tlist.replaceItem(Rnc, 0);\n};\n\n// ====================================\n// Public API starts here\n\n/**\n* @function module:path.clearData\n* @returns {void}\n*/\nexport const clearData = function () {\n pathData = {};\n};\n\n// Making public for mocking\n/**\n* @function module:path.reorientGrads\n* @param {Element} elem\n* @param {SVGMatrix} m\n* @returns {void}\n*/\nexport const reorientGrads = function (elem, m) {\n const bb = utilsGetBBox(elem);\n for (let i = 0; i < 2; i++) {\n const type = i === 0 ? 'fill' : 'stroke';\n const attrVal = elem.getAttribute(type);\n if (attrVal && attrVal.startsWith('url(')) {\n const grad = getRefElem(attrVal);\n if (grad.tagName === 'linearGradient') {\n let x1 = grad.getAttribute('x1') || 0;\n let y1 = grad.getAttribute('y1') || 0;\n let x2 = grad.getAttribute('x2') || 1;\n let y2 = grad.getAttribute('y2') || 0;\n\n // Convert to USOU points\n x1 = (bb.width * x1) + bb.x;\n y1 = (bb.height * y1) + bb.y;\n x2 = (bb.width * x2) + bb.x;\n y2 = (bb.height * y2) + bb.y;\n\n // Transform those points\n const pt1 = transformPoint(x1, y1, m);\n const pt2 = transformPoint(x2, y2, m);\n\n // Convert back to BB points\n const gCoords = {\n x1: (pt1.x - bb.x) / bb.width,\n y1: (pt1.y - bb.y) / bb.height,\n x2: (pt2.x - bb.x) / bb.width,\n y2: (pt2.y - bb.y) / bb.height\n };\n\n const newgrad = grad.cloneNode(true);\n $(newgrad).attr(gCoords);\n\n newgrad.id = editorContext_.getNextId();\n findDefs().append(newgrad);\n elem.setAttribute(type, 'url(#' + newgrad.id + ')');\n }\n }\n }\n};\n\n/**\n* This is how we map paths to our preferred relative segment types.\n* @name module:path.pathMap\n* @type {GenericArray}\n*/\nconst pathMap = [\n 0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',\n 'H', 'h', 'V', 'v', 'S', 's', 'T', 't'\n];\n\n/**\n * Convert a path to one with only absolute or relative values.\n * @todo move to pathActions.js\n * @function module:path.convertPath\n * @param {SVGPathElement} pth - the path to convert\n * @param {boolean} toRel - true of convert to relative\n * @returns {string}\n */\nexport const convertPath = function (pth, toRel) {\n const {pathSegList} = pth;\n const len = pathSegList.numberOfItems;\n let curx = 0, cury = 0;\n let d = '';\n let lastM = null;\n\n for (let i = 0; i < len; ++i) {\n const seg = pathSegList.getItem(i);\n // if these properties are not in the segment, set them to zero\n let x = seg.x || 0,\n y = seg.y || 0,\n x1 = seg.x1 || 0,\n y1 = seg.y1 || 0,\n x2 = seg.x2 || 0,\n y2 = seg.y2 || 0;\n\n const type = seg.pathSegType;\n let letter = pathMap[type][toRel ? 'toLowerCase' : 'toUpperCase']();\n\n switch (type) {\n case 1: // z,Z closepath (Z/z)\n d += 'z';\n if (lastM && !toRel) {\n curx = lastM[0];\n cury = lastM[1];\n }\n break;\n case 12: // absolute horizontal line (H)\n x -= curx;\n // Fallthrough\n case 13: // relative horizontal line (h)\n if (toRel) {\n y = 0;\n curx += x;\n letter = 'l';\n } else {\n y = cury;\n x += curx;\n curx = x;\n letter = 'L';\n }\n // Convert to \"line\" for easier editing\n d += pathDSegment(letter, [[x, y]]);\n break;\n case 14: // absolute vertical line (V)\n y -= cury;\n // Fallthrough\n case 15: // relative vertical line (v)\n if (toRel) {\n x = 0;\n cury += y;\n letter = 'l';\n } else {\n x = curx;\n y += cury;\n cury = y;\n letter = 'L';\n }\n // Convert to \"line\" for easier editing\n d += pathDSegment(letter, [[x, y]]);\n break;\n case 2: // absolute move (M)\n case 4: // absolute line (L)\n case 18: // absolute smooth quad (T)\n x -= curx;\n y -= cury;\n // Fallthrough\n case 5: // relative line (l)\n case 3: // relative move (m)\n case 19: // relative smooth quad (t)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx;\n y += cury;\n curx = x;\n cury = y;\n }\n if (type === 2 || type === 3) { lastM = [curx, cury]; }\n\n d += pathDSegment(letter, [[x, y]]);\n break;\n case 6: // absolute cubic (C)\n x -= curx; x1 -= curx; x2 -= curx;\n y -= cury; y1 -= cury; y2 -= cury;\n // Fallthrough\n case 7: // relative cubic (c)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx; x1 += curx; x2 += curx;\n y += cury; y1 += cury; y2 += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[x1, y1], [x2, y2], [x, y]]);\n break;\n case 8: // absolute quad (Q)\n x -= curx; x1 -= curx;\n y -= cury; y1 -= cury;\n // Fallthrough\n case 9: // relative quad (q)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx; x1 += curx;\n y += cury; y1 += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[x1, y1], [x, y]]);\n break;\n // eslint-disable-next-line sonarjs/no-duplicated-branches\n case 10: // absolute elliptical arc (A)\n x -= curx;\n y -= cury;\n // Fallthrough\n case 11: // relative elliptical arc (a)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx;\n y += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[seg.r1, seg.r2]], [\n seg.angle,\n (seg.largeArcFlag ? 1 : 0),\n (seg.sweepFlag ? 1 : 0)\n ], [x, y]);\n break;\n case 16: // absolute smooth cubic (S)\n x -= curx; x2 -= curx;\n y -= cury; y2 -= cury;\n // Fallthrough\n case 17: // relative smooth cubic (s)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx; x2 += curx;\n y += cury; y2 += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[x2, y2], [x, y]]);\n break;\n } // switch on path segment type\n } // for each segment\n return d;\n};\n\n/**\n * TODO: refactor callers in `convertPath` to use `getPathDFromSegments` instead of this function.\n * Legacy code refactored from `svgcanvas.pathActions.convertPath`.\n * @param {string} letter - path segment command (letter in potentially either case from {@link module:path.pathMap}; see [SVGPathSeg#pathSegTypeAsLetter]{@link https://www.w3.org/TR/SVG/single-page.html#paths-__svg__SVGPathSeg__pathSegTypeAsLetter})\n * @param {GenericArray<GenericArray<Integer>>} points - x,y points\n * @param {GenericArray<GenericArray<Integer>>} [morePoints] - x,y points\n * @param {Integer[]} [lastPoint] - x,y point\n * @returns {string}\n */\nfunction pathDSegment (letter, points, morePoints, lastPoint) {\n $.each(points, function (i, pnt) {\n points[i] = shortFloat(pnt);\n });\n let segment = letter + points.join(' ');\n if (morePoints) {\n segment += ' ' + morePoints.join(' ');\n }\n if (lastPoint) {\n segment += ' ' + shortFloat(lastPoint);\n }\n return segment;\n}\n\n/* eslint-disable jsdoc/require-property */\n/**\n* Group: Path edit functions.\n* Functions relating to editing path elements.\n* @namespace {PlainObject} pathActions\n* @memberof module:path\n*/\nexport const pathActions = (function () {\n /* eslint-enable jsdoc/require-property */\n let subpath = false;\n let newPoint, firstCtrl;\n\n let currentPath = null;\n let hasMoved = false;\n // No `editorContext_` yet but should be ok as is `null` by default\n // editorContext_.setDrawnPath(null);\n\n /**\n * This function converts a polyline (created by the fh_path tool) into\n * a path element and coverts every three line segments into a single bezier\n * curve in an attempt to smooth out the free-hand.\n * @function smoothPolylineIntoPath\n * @param {Element} element\n * @returns {Element}\n */\n const smoothPolylineIntoPath = function (element) {\n let i;\n const {points} = element;\n const N = points.numberOfItems;\n if (N >= 4) {\n // loop through every 3 points and convert to a cubic bezier curve segment\n //\n // NOTE: this is cheating, it means that every 3 points has the potential to\n // be a corner instead of treating each point in an equal manner. In general,\n // this technique does not look that good.\n //\n // I am open to better ideas!\n //\n // Reading:\n // - http://www.efg2.com/Lab/Graphics/Jean-YvesQueinecBezierCurves.htm\n // - https://www.codeproject.com/KB/graphics/BezierSpline.aspx?msg=2956963\n // - https://www.ian-ko.com/ET_GeoWizards/UserGuide/smooth.htm\n // - https://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html\n let curpos = points.getItem(0), prevCtlPt = null;\n let d = [];\n d.push(['M', curpos.x, ',', curpos.y, ' C'].join(''));\n for (i = 1; i <= (N - 4); i += 3) {\n let ct1 = points.getItem(i);\n const ct2 = points.getItem(i + 1);\n const end = points.getItem(i + 2);\n\n // if the previous segment had a control point, we want to smooth out\n // the control points on both sides\n if (prevCtlPt) {\n const newpts = smoothControlPoints(prevCtlPt, ct1, curpos);\n if (newpts && newpts.length === 2) {\n const prevArr = d[d.length - 1].split(',');\n prevArr[2] = newpts[0].x;\n prevArr[3] = newpts[0].y;\n d[d.length - 1] = prevArr.join(',');\n ct1 = newpts[1];\n }\n }\n\n d.push([ct1.x, ct1.y, ct2.x, ct2.y, end.x, end.y].join(','));\n\n curpos = end;\n prevCtlPt = ct2;\n }\n // handle remaining line segments\n d.push('L');\n while (i < N) {\n const pt = points.getItem(i);\n d.push([pt.x, pt.y].join(','));\n i++;\n }\n d = d.join(' ');\n\n // create new path element\n element = editorContext_.addSVGElementFromJson({\n element: 'path',\n curStyles: true,\n attr: {\n id: editorContext_.getId(),\n d,\n fill: 'none'\n }\n });\n // No need to call \"changed\", as this is already done under mouseUp\n }\n return element;\n };\n\n return (/** @lends module:path.pathActions */ {\n /**\n * @param {MouseEvent} evt\n * @param {Element} mouseTarget\n * @param {Float} startX\n * @param {Float} startY\n * @returns {boolean|void}\n */\n mouseDown (evt, mouseTarget, startX, startY) {\n let id;\n if (editorContext_.getCurrentMode() === 'path') {\n let mouseX = startX; // Was this meant to work with the other `mouseX`? (was defined globally so adding `let` to at least avoid a global)\n let mouseY = startY; // Was this meant to work with the other `mouseY`? (was defined globally so adding `let` to at least avoid a global)\n\n const currentZoom = editorContext_.getCurrentZoom();\n let x = mouseX / currentZoom,\n y = mouseY / currentZoom,\n stretchy = getElem('path_stretch_line');\n newPoint = [x, y];\n\n if (editorContext_.getGridSnapping()) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n mouseX = snapToGrid(mouseX);\n mouseY = snapToGrid(mouseY);\n }\n\n if (!stretchy) {\n stretchy = document.createElementNS(NS.SVG, 'path');\n assignAttributes(stretchy, {\n id: 'path_stretch_line',\n stroke: '#22C',\n 'stroke-width': '0.5',\n fill: 'none'\n });\n stretchy = getElem('selectorParentGroup').appendChild(stretchy);\n }\n stretchy.setAttribute('display', 'inline');\n\n let keep = null;\n let index;\n // if pts array is empty, create path element with M at current point\n const drawnPath = editorContext_.getDrawnPath();\n if (!drawnPath) {\n const dAttr = 'M' + x + ',' + y + ' '; // Was this meant to work with the other `dAttr`? (was defined globally so adding `var` to at least avoid a global)\n /* drawnPath = */ editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({\n element: 'path',\n curStyles: true,\n attr: {\n d: dAttr,\n id: editorContext_.getNextId(),\n opacity: editorContext_.getOpacity() / 2\n }\n }));\n // set stretchy line to first point\n stretchy.setAttribute('d', ['M', mouseX, mouseY, mouseX, mouseY].join(' '));\n index = subpath ? path.segs.length : 0;\n addPointGrip(index, mouseX, mouseY);\n } else {\n // determine if we clicked on an existing point\n const seglist = drawnPath.pathSegList;\n let i = seglist.numberOfItems;\n const FUZZ = 6 / currentZoom;\n let clickOnPoint = false;\n while (i) {\n i--;\n const item = seglist.getItem(i);\n const px = item.x, py = item.y;\n // found a matching point\n if (x >= (px - FUZZ) && x <= (px + FUZZ) &&\n y >= (py - FUZZ) && y <= (py + FUZZ)\n ) {\n clickOnPoint = true;\n break;\n }\n }\n\n // get path element that we are in the process of creating\n id = editorContext_.getId();\n\n // Remove previous path object if previously created\n removePath_(id);\n\n const newpath = getElem(id);\n let newseg;\n let sSeg;\n const len = seglist.numberOfItems;\n // if we clicked on an existing point, then we are done this path, commit it\n // (i, i+1) are the x,y that were clicked on\n if (clickOnPoint) {\n // if clicked on any other point but the first OR\n // the first point was clicked on and there are less than 3 points\n // then leave the path open\n // otherwise, close the path\n if (i <= 1 && len >= 2) {\n // Create end segment\n const absX = seglist.getItem(0).x;\n const absY = seglist.getItem(0).y;\n\n sSeg = stretchy.pathSegList.getItem(1);\n if (sSeg.pathSegType === 4) {\n newseg = drawnPath.createSVGPathSegLinetoAbs(absX, absY);\n } else {\n newseg = drawnPath.createSVGPathSegCurvetoCubicAbs(\n absX,\n absY,\n sSeg.x1 / currentZoom,\n sSeg.y1 / currentZoom,\n absX,\n absY\n );\n }\n\n const endseg = drawnPath.createSVGPathSegClosePath();\n seglist.appendItem(newseg);\n seglist.appendItem(endseg);\n } else if (len < 3) {\n keep = false;\n return keep;\n }\n $(stretchy).remove();\n\n // This will signal to commit the path\n // const element = newpath; // Other event handlers define own `element`, so this was probably not meant to interact with them or one which shares state (as there were none); I therefore adding a missing `var` to avoid a global\n /* drawnPath = */ editorContext_.setDrawnPath(null);\n editorContext_.setStarted(false);\n\n if (subpath) {\n if (path.matrix) {\n editorContext_.remapElement(newpath, {}, path.matrix.inverse());\n }\n\n const newD = newpath.getAttribute('d');\n const origD = $(path.elem).attr('d');\n $(path.elem).attr('d', origD + newD);\n $(newpath).remove();\n if (path.matrix) {\n recalcRotatedPath();\n }\n init();\n pathActions.toEditMode(path.elem);\n path.selectPt();\n return false;\n }\n // else, create a new point, update path element\n } else {\n // Checks if current target or parents are #svgcontent\n if (!$.contains(\n editorContext_.getContainer(),\n editorContext_.getMouseTarget(evt)\n )) {\n // Clicked outside canvas, so don't make point\n // console.log('Clicked outside canvas');\n return false;\n }\n\n const num = drawnPath.pathSegList.numberOfItems;\n const last = drawnPath.pathSegList.getItem(num - 1);\n const lastx = last.x, lasty = last.y;\n\n if (evt.shiftKey) {\n const xya = snapToAngle(lastx, lasty, x, y);\n ({x, y} = xya);\n }\n\n // Use the segment defined by stretchy\n sSeg = stretchy.pathSegList.getItem(1);\n if (sSeg.pathSegType === 4) {\n newseg = drawnPath.createSVGPathSegLinetoAbs(\n editorContext_.round(x),\n editorContext_.round(y)\n );\n } else {\n newseg = drawnPath.createSVGPathSegCurvetoCubicAbs(\n editorContext_.round(x),\n editorContext_.round(y),\n sSeg.x1 / currentZoom,\n sSeg.y1 / currentZoom,\n sSeg.x2 / currentZoom,\n sSeg.y2 / currentZoom\n );\n }\n\n drawnPath.pathSegList.appendItem(newseg);\n\n x *= currentZoom;\n y *= currentZoom;\n\n // set stretchy line to latest point\n stretchy.setAttribute('d', ['M', x, y, x, y].join(' '));\n index = num;\n if (subpath) { index += path.segs.length; }\n addPointGrip(index, x, y);\n }\n // keep = true;\n }\n\n return undefined;\n }\n\n // TODO: Make sure currentPath isn't null at this point\n if (!path) { return undefined; }\n\n path.storeD();\n\n ({id} = evt.target);\n let curPt;\n if (id.substr(0, 14) === 'pathpointgrip_') {\n // Select this point\n curPt = path.cur_pt = Number.parseInt(id.substr(14));\n path.dragging = [startX, startY];\n const seg = path.segs[curPt];\n\n // only clear selection if shift is not pressed (otherwise, add\n // node to selection)\n if (!evt.shiftKey) {\n if (path.selected_pts.length <= 1 || !seg.selected) {\n path.clearSelection();\n }\n path.addPtsToSelection(curPt);\n } else if (seg.selected) {\n path.removePtFromSelection(curPt);\n } else {\n path.addPtsToSelection(curPt);\n }\n } else if (id.startsWith('ctrlpointgrip_')) {\n path.dragging = [startX, startY];\n\n const parts = id.split('_')[1].split('c');\n curPt = Number(parts[0]);\n const ctrlNum = Number(parts[1]);\n path.selectPt(curPt, ctrlNum);\n }\n\n // Start selection box\n if (!path.dragging) {\n let rubberBox = editorContext_.getRubberBox();\n if (isNullish(rubberBox)) {\n rubberBox = editorContext_.setRubberBox(\n editorContext_.selectorManager.getRubberBandBox()\n );\n }\n const currentZoom = editorContext_.getCurrentZoom();\n assignAttributes(rubberBox, {\n x: startX * currentZoom,\n y: startY * currentZoom,\n width: 0,\n height: 0,\n display: 'inline'\n }, 100);\n }\n return undefined;\n },\n /**\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\n mouseMove (mouseX, mouseY) {\n const currentZoom = editorContext_.getCurrentZoom();\n hasMoved = true;\n const drawnPath = editorContext_.getDrawnPath();\n if (editorContext_.getCurrentMode() === 'path') {\n if (!drawnPath) { return; }\n const seglist = drawnPath.pathSegList;\n const index = seglist.numberOfItems - 1;\n\n if (newPoint) {\n // First point\n // if (!index) { return; }\n\n // Set control points\n const pointGrip1 = addCtrlGrip('1c1');\n const pointGrip2 = addCtrlGrip('0c2');\n\n // dragging pointGrip1\n pointGrip1.setAttribute('cx', mouseX);\n pointGrip1.setAttribute('cy', mouseY);\n pointGrip1.setAttribute('display', 'inline');\n\n const ptX = newPoint[0];\n const ptY = newPoint[1];\n\n // set curve\n // const seg = seglist.getItem(index);\n const curX = mouseX / currentZoom;\n const curY = mouseY / currentZoom;\n const altX = (ptX + (ptX - curX));\n const altY = (ptY + (ptY - curY));\n\n pointGrip2.setAttribute('cx', altX * currentZoom);\n pointGrip2.setAttribute('cy', altY * currentZoom);\n pointGrip2.setAttribute('display', 'inline');\n\n const ctrlLine = getCtrlLine(1);\n assignAttributes(ctrlLine, {\n x1: mouseX,\n y1: mouseY,\n x2: altX * currentZoom,\n y2: altY * currentZoom,\n display: 'inline'\n });\n\n if (index === 0) {\n firstCtrl = [mouseX, mouseY];\n } else {\n const last = seglist.getItem(index - 1);\n let lastX = last.x;\n let lastY = last.y;\n\n if (last.pathSegType === 6) {\n lastX += (lastX - last.x2);\n lastY += (lastY - last.y2);\n } else if (firstCtrl) {\n lastX = firstCtrl[0] / currentZoom;\n lastY = firstCtrl[1] / currentZoom;\n }\n replacePathSeg(6, index, [ptX, ptY, lastX, lastY, altX, altY], drawnPath);\n }\n } else {\n const stretchy = getElem('path_stretch_line');\n if (stretchy) {\n const prev = seglist.getItem(index);\n if (prev.pathSegType === 6) {\n const prevX = prev.x + (prev.x - prev.x2);\n const prevY = prev.y + (prev.y - prev.y2);\n replacePathSeg(6, 1, [mouseX, mouseY, prevX * currentZoom, prevY * currentZoom, mouseX, mouseY], stretchy);\n } else if (firstCtrl) {\n replacePathSeg(6, 1, [mouseX, mouseY, firstCtrl[0], firstCtrl[1], mouseX, mouseY], stretchy);\n } else {\n replacePathSeg(4, 1, [mouseX, mouseY], stretchy);\n }\n }\n }\n return;\n }\n // if we are dragging a point, let's move it\n if (path.dragging) {\n const pt = getPointFromGrip({\n x: path.dragging[0],\n y: path.dragging[1]\n }, path);\n const mpt = getPointFromGrip({\n x: mouseX,\n y: mouseY\n }, path);\n const diffX = mpt.x - pt.x;\n const diffY = mpt.y - pt.y;\n path.dragging = [mouseX, mouseY];\n\n if (path.dragctrl) {\n path.moveCtrl(diffX, diffY);\n } else {\n path.movePts(diffX, diffY);\n }\n } else {\n path.selected_pts = [];\n path.eachSeg(function (i) {\n const seg = this; // eslint-disable-line consistent-this\n if (!seg.next && !seg.prev) { return; }\n\n // const {item} = seg;\n const rubberBox = editorContext_.getRubberBox();\n const rbb = rubberBox.getBBox();\n\n const pt = getGripPt(seg);\n const ptBb = {\n x: pt.x,\n y: pt.y,\n width: 0,\n height: 0\n };\n\n const sel = rectsIntersect(rbb, ptBb);\n\n this.select(sel);\n // Note that addPtsToSelection is not being run\n if (sel) { path.selected_pts.push(seg.index); }\n });\n }\n },\n /**\n * @typedef module:path.keepElement\n * @type {PlainObject}\n * @property {boolean} keep\n * @property {Element} element\n */\n /**\n * @param {Event} evt\n * @param {Element} element\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {module:path.keepElement|void}\n */\n mouseUp (evt, element, mouseX, mouseY) {\n const drawnPath = editorContext_.getDrawnPath();\n // Create mode\n if (editorContext_.getCurrentMode() === 'path') {\n newPoint = null;\n if (!drawnPath) {\n element = getElem(editorContext_.getId());\n editorContext_.setStarted(false);\n firstCtrl = null;\n }\n\n return {\n keep: true,\n element\n };\n }\n\n // Edit mode\n const rubberBox = editorContext_.getRubberBox();\n if (path.dragging) {\n const lastPt = path.cur_pt;\n\n path.dragging = false;\n path.dragctrl = false;\n path.update();\n\n if (hasMoved) {\n path.endChanges('Move path point(s)');\n }\n\n if (!evt.shiftKey && !hasMoved) {\n path.selectPt(lastPt);\n }\n } else if (rubberBox && rubberBox.getAttribute('display') !== 'none') {\n // Done with multi-node-select\n rubberBox.setAttribute('display', 'none');\n\n if (rubberBox.getAttribute('width') <= 2 && rubberBox.getAttribute('height') <= 2) {\n pathActions.toSelectMode(evt.target);\n }\n\n // else, move back to select mode\n } else {\n pathActions.toSelectMode(evt.target);\n }\n hasMoved = false;\n return undefined;\n },\n /**\n * @param {Element} element\n * @returns {void}\n */\n toEditMode (element) {\n path = getPath_(element);\n editorContext_.setCurrentMode('pathedit');\n editorContext_.clearSelection();\n path.show(true).update();\n path.oldbbox = utilsGetBBox(path.elem);\n subpath = false;\n },\n /**\n * @param {Element} elem\n * @fires module:svgcanvas.SvgCanvas#event:selected\n * @returns {void}\n */\n toSelectMode (elem) {\n const selPath = (elem === path.elem);\n editorContext_.setCurrentMode('select');\n path.show(false);\n currentPath = false;\n editorContext_.clearSelection();\n\n if (path.matrix) {\n // Rotated, so may need to re-calculate the center\n recalcRotatedPath();\n }\n\n if (selPath) {\n editorContext_.call('selected', [elem]);\n editorContext_.addToSelection([elem], true);\n }\n },\n /**\n * @param {boolean} on\n * @returns {void}\n */\n addSubPath (on) {\n if (on) {\n // Internally we go into \"path\" mode, but in the UI it will\n // still appear as if in \"pathedit\" mode.\n editorContext_.setCurrentMode('path');\n subpath = true;\n } else {\n pathActions.clear(true);\n pathActions.toEditMode(path.elem);\n }\n },\n /**\n * @param {Element} target\n * @returns {void}\n */\n select (target) {\n if (currentPath === target) {\n pathActions.toEditMode(target);\n editorContext_.setCurrentMode('pathedit');\n // going into pathedit mode\n } else {\n currentPath = target;\n }\n },\n /**\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n reorient () {\n const elem = editorContext_.getSelectedElements()[0];\n if (!elem) { return; }\n const angl = getRotationAngle(elem);\n if (angl === 0) { return; }\n\n const batchCmd = new BatchCommand('Reorient path');\n const changes = {\n d: elem.getAttribute('d'),\n transform: elem.getAttribute('transform')\n };\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n editorContext_.clearSelection();\n this.resetOrientation(elem);\n\n editorContext_.addCommandToHistory(batchCmd);\n\n // Set matrix to null\n getPath_(elem).show(false).matrix = null;\n\n this.clear();\n\n editorContext_.addToSelection([elem], true);\n editorContext_.call('changed', editorContext_.getSelectedElements());\n },\n\n /**\n * @param {boolean} remove Not in use\n * @returns {void}\n */\n clear (remove) {\n const drawnPath = editorContext_.getDrawnPath();\n currentPath = null;\n if (drawnPath) {\n const elem = getElem(editorContext_.getId());\n $(getElem('path_stretch_line')).remove();\n $(elem).remove();\n $(getElem('pathpointgrip_container')).find('*').attr('display', 'none');\n firstCtrl = null;\n editorContext_.setDrawnPath(null);\n editorContext_.setStarted(false);\n } else if (editorContext_.getCurrentMode() === 'pathedit') {\n this.toSelectMode();\n }\n if (path) { path.init().show(false); }\n },\n /**\n * @param {?(Element|SVGPathElement)} pth\n * @returns {false|void}\n */\n resetOrientation (pth) {\n if (isNullish(pth) || pth.nodeName !== 'path') { return false; }\n const tlist = getTransformList(pth);\n const m = transformListToTransform(tlist).matrix;\n tlist.clear();\n pth.removeAttribute('transform');\n const segList = pth.pathSegList;\n\n // Opera/win/non-EN throws an error here.\n // TODO: Find out why!\n // Presumed fixed in Opera 10.5, so commented out for now\n\n // try {\n const len = segList.numberOfItems;\n // } catch(err) {\n // const fixed_d = pathActions.convertPath(pth);\n // pth.setAttribute('d', fixed_d);\n // segList = pth.pathSegList;\n // const len = segList.numberOfItems;\n // }\n // let lastX, lastY;\n for (let i = 0; i < len; ++i) {\n const seg = segList.getItem(i);\n const type = seg.pathSegType;\n if (type === 1) { continue; }\n const pts = [];\n $.each(['', 1, 2], function (j, n) {\n const x = seg['x' + n], y = seg['y' + n];\n if (x !== undefined && y !== undefined) {\n const pt = transformPoint(x, y, m);\n pts.splice(pts.length, 0, pt.x, pt.y);\n }\n });\n replacePathSeg(type, i, pts, pth);\n }\n\n reorientGrads(pth, m);\n return undefined;\n },\n /**\n * @returns {void}\n */\n zoomChange () {\n if (editorContext_.getCurrentMode() === 'pathedit') {\n path.update();\n }\n },\n /**\n * @typedef {PlainObject} module:path.NodePoint\n * @property {Float} x\n * @property {Float} y\n * @property {Integer} type\n */\n /**\n * @returns {module:path.NodePoint}\n */\n getNodePoint () {\n const selPt = path.selected_pts.length ? path.selected_pts[0] : 1;\n\n const seg = path.segs[selPt];\n return {\n x: seg.item.x,\n y: seg.item.y,\n type: seg.type\n };\n },\n /**\n * @param {boolean} linkPoints\n * @returns {void}\n */\n linkControlPoints (linkPoints) {\n setLinkControlPoints(linkPoints);\n },\n /**\n * @returns {void}\n */\n clonePathNode () {\n path.storeD();\n\n const selPts = path.selected_pts;\n // const {segs} = path;\n\n let i = selPts.length;\n const nums = [];\n\n while (i--) {\n const pt = selPts[i];\n path.addSeg(pt);\n\n nums.push(pt + i);\n nums.push(pt + i + 1);\n }\n path.init().addPtsToSelection(nums);\n\n path.endChanges('Clone path node(s)');\n },\n /**\n * @returns {void}\n */\n opencloseSubPath () {\n const selPts = path.selected_pts;\n // Only allow one selected node for now\n if (selPts.length !== 1) { return; }\n\n const {elem} = path;\n const list = elem.pathSegList;\n\n // const len = list.numberOfItems;\n\n const index = selPts[0];\n\n let openPt = null;\n let startItem = null;\n\n // Check if subpath is already open\n path.eachSeg(function (i) {\n if (this.type === 2 && i <= index) {\n startItem = this.item;\n }\n if (i <= index) { return true; }\n if (this.type === 2) {\n // Found M first, so open\n openPt = i;\n return false;\n }\n if (this.type === 1) {\n // Found Z first, so closed\n openPt = false;\n return false;\n }\n return true;\n });\n\n if (isNullish(openPt)) {\n // Single path, so close last seg\n openPt = path.segs.length - 1;\n }\n\n if (openPt !== false) {\n // Close this path\n\n // Create a line going to the previous \"M\"\n const newseg = elem.createSVGPathSegLinetoAbs(startItem.x, startItem.y);\n\n const closer = elem.createSVGPathSegClosePath();\n if (openPt === path.segs.length - 1) {\n list.appendItem(newseg);\n list.appendItem(closer);\n } else {\n insertItemBefore(elem, closer, openPt);\n insertItemBefore(elem, newseg, openPt);\n }\n\n path.init().selectPt(openPt + 1);\n return;\n }\n\n // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2\n // M 2,2 L 3,3 L 1,1\n\n // M 1,1 L 2,2 L 1,1 z M 4,4 L 5,5 L6,6 L 5,5 z\n // M 1,1 L 2,2 L 1,1 z [M 4,4] L 5,5 L(M)6,6 L 5,5 z\n\n const seg = path.segs[index];\n\n if (seg.mate) {\n list.removeItem(index); // Removes last \"L\"\n list.removeItem(index); // Removes the \"Z\"\n path.init().selectPt(index - 1);\n return;\n }\n\n let lastM, zSeg;\n\n // Find this sub-path's closing point and remove\n for (let i = 0; i < list.numberOfItems; i++) {\n const item = list.getItem(i);\n\n if (item.pathSegType === 2) {\n // Find the preceding M\n lastM = i;\n } else if (i === index) {\n // Remove it\n list.removeItem(lastM);\n // index--;\n } else if (item.pathSegType === 1 && index < i) {\n // Remove the closing seg of this subpath\n zSeg = i - 1;\n list.removeItem(i);\n break;\n }\n }\n\n let num = (index - lastM) - 1;\n\n while (num--) {\n insertItemBefore(elem, list.getItem(lastM), zSeg);\n }\n\n const pt = list.getItem(lastM);\n\n // Make this point the new \"M\"\n replacePathSeg(2, lastM, [pt.x, pt.y]);\n\n // i = index; // i is local here, so has no effect; what was the intent for this?\n\n path.init().selectPt(0);\n },\n /**\n * @returns {void}\n */\n deletePathNode () {\n if (!pathActions.canDeleteNodes) { return; }\n path.storeD();\n\n const selPts = path.selected_pts;\n\n let i = selPts.length;\n while (i--) {\n const pt = selPts[i];\n path.deleteSeg(pt);\n }\n\n // Cleanup\n const cleanup = function () {\n const segList = path.elem.pathSegList;\n let len = segList.numberOfItems;\n\n const remItems = function (pos, count) {\n while (count--) {\n segList.removeItem(pos);\n }\n };\n\n if (len <= 1) { return true; }\n\n while (len--) {\n const item = segList.getItem(len);\n if (item.pathSegType === 1) {\n const prev = segList.getItem(len - 1);\n const nprev = segList.getItem(len - 2);\n if (prev.pathSegType === 2) {\n remItems(len - 1, 2);\n cleanup();\n break;\n } else if (nprev.pathSegType === 2) {\n remItems(len - 2, 3);\n cleanup();\n break;\n }\n } else if (item.pathSegType === 2) {\n if (len > 0) {\n const prevType = segList.getItem(len - 1).pathSegType;\n // Path has M M\n if (prevType === 2) {\n remItems(len - 1, 1);\n cleanup();\n break;\n // Entire path ends with Z M\n } else if (prevType === 1 && segList.numberOfItems - 1 === len) {\n remItems(len, 1);\n cleanup();\n break;\n }\n }\n }\n }\n return false;\n };\n\n cleanup();\n\n // Completely delete a path with 1 or 0 segments\n if (path.elem.pathSegList.numberOfItems <= 1) {\n pathActions.toSelectMode(path.elem);\n editorContext_.canvas.deleteSelectedElements();\n return;\n }\n\n path.init();\n path.clearSelection();\n\n // TODO: Find right way to select point now\n // path.selectPt(selPt);\n if (window.opera) { // Opera repaints incorrectly\n const cp = $(path.elem);\n cp.attr('d', cp.attr('d'));\n }\n path.endChanges('Delete path node(s)');\n },\n /* eslint-disable jsdoc/require-returns */\n // Can't seem to use `@borrows` here, so using `@see`\n /**\n * Smooth polyline into path.\n * @function module:path.pathActions.smoothPolylineIntoPath\n * @see module:path~smoothPolylineIntoPath\n */\n smoothPolylineIntoPath,\n /* eslint-enable jsdoc/require-returns */\n /**\n * @param {?Integer} v See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg}\n * @returns {void}\n */\n setSegType (v) {\n path.setSegType(v);\n },\n /**\n * @param {string} attr\n * @param {Float} newValue\n * @returns {void}\n */\n moveNode (attr, newValue) {\n const selPts = path.selected_pts;\n if (!selPts.length) { return; }\n\n path.storeD();\n\n // Get first selected point\n const seg = path.segs[selPts[0]];\n const diff = {x: 0, y: 0};\n diff[attr] = newValue - seg.item[attr];\n\n seg.move(diff.x, diff.y);\n path.endChanges('Move path point');\n },\n /**\n * @param {Element} elem\n * @returns {void}\n */\n fixEnd (elem) {\n // Adds an extra segment if the last seg before a Z doesn't end\n // at its M point\n // M0,0 L0,100 L100,100 z\n const segList = elem.pathSegList;\n const len = segList.numberOfItems;\n let lastM;\n for (let i = 0; i < len; ++i) {\n const item = segList.getItem(i);\n if (item.pathSegType === 2) {\n lastM = item;\n }\n\n if (item.pathSegType === 1) {\n const prev = segList.getItem(i - 1);\n if (prev.x !== lastM.x || prev.y !== lastM.y) {\n // Add an L segment here\n const newseg = elem.createSVGPathSegLinetoAbs(lastM.x, lastM.y);\n insertItemBefore(elem, newseg, i);\n // Can this be done better?\n pathActions.fixEnd(elem);\n break;\n }\n }\n }\n if (isWebkit()) { editorContext_.resetD(elem); }\n },\n /* eslint-disable jsdoc/require-returns */\n // Can't seem to use `@borrows` here, so using `@see`\n /**\n * Convert a path to one with only absolute or relative values.\n * @function module:path.pathActions.convertPath\n * @see module:path.convertPath\n */\n convertPath\n /* eslint-enable jsdoc/require-returns */\n });\n})();\n// end pathActions\n","/* globals jQuery */\n/**\n * Provides tools for the layer concept.\n * @module layer\n * @license MIT\n *\n * @copyright 2011 Jeff Schiller, 2016 Flint O'Brien\n */\n\nimport {NS} from './namespaces.js';\nimport {toXml, walkTree, isNullish} from './utilities.js';\n\nconst $ = jQuery;\n\n/**\n * This class encapsulates the concept of a layer in the drawing. It can be constructed with\n * an existing group element or, with three parameters, will create a new layer group element.\n *\n * @example\n * const l1 = new Layer('name', group); // Use the existing group for this layer.\n * const l2 = new Layer('name', group, svgElem); // Create a new group and add it to the DOM after group.\n * const l3 = new Layer('name', null, svgElem); // Create a new group and add it to the DOM as the last layer.\n * @memberof module:layer\n */\nclass Layer {\n /**\n * @param {string} name - Layer name\n * @param {SVGGElement|null} group - An existing SVG group element or null.\n * If group and no svgElem, use group for this layer.\n * If group and svgElem, create a new group element and insert it in the DOM after group.\n * If no group and svgElem, create a new group element and insert it in the DOM as the last layer.\n * @param {SVGGElement} [svgElem] - The SVG DOM element. If defined, use this to add\n * a new layer to the document.\n */\n constructor (name, group, svgElem) {\n this.name_ = name;\n this.group_ = svgElem ? null : group;\n\n if (svgElem) {\n // Create a group element with title and add it to the DOM.\n const svgdoc = svgElem.ownerDocument;\n this.group_ = svgdoc.createElementNS(NS.SVG, 'g');\n const layerTitle = svgdoc.createElementNS(NS.SVG, 'title');\n layerTitle.textContent = name;\n this.group_.append(layerTitle);\n if (group) {\n $(group).after(this.group_);\n } else {\n svgElem.append(this.group_);\n }\n }\n\n addLayerClass(this.group_);\n walkTree(this.group_, function (e) {\n e.setAttribute('style', 'pointer-events:inherit');\n });\n\n this.group_.setAttribute('style', svgElem ? 'pointer-events:all' : 'pointer-events:none');\n }\n\n /**\n * Get the layer's name.\n * @returns {string} The layer name\n */\n getName () {\n return this.name_;\n }\n\n /**\n * Get the group element for this layer.\n * @returns {SVGGElement} The layer SVG group\n */\n getGroup () {\n return this.group_;\n }\n\n /**\n * Active this layer so it takes pointer events.\n * @returns {void}\n */\n activate () {\n this.group_.setAttribute('style', 'pointer-events:all');\n }\n\n /**\n * Deactive this layer so it does NOT take pointer events.\n * @returns {void}\n */\n deactivate () {\n this.group_.setAttribute('style', 'pointer-events:none');\n }\n\n /**\n * Set this layer visible or hidden based on 'visible' parameter.\n * @param {boolean} visible - If true, make visible; otherwise, hide it.\n * @returns {void}\n */\n setVisible (visible) {\n const expected = visible === undefined || visible ? 'inline' : 'none';\n const oldDisplay = this.group_.getAttribute('display');\n if (oldDisplay !== expected) {\n this.group_.setAttribute('display', expected);\n }\n }\n\n /**\n * Is this layer visible?\n * @returns {boolean} True if visible.\n */\n isVisible () {\n return this.group_.getAttribute('display') !== 'none';\n }\n\n /**\n * Get layer opacity.\n * @returns {Float} Opacity value.\n */\n getOpacity () {\n const opacity = this.group_.getAttribute('opacity');\n if (isNullish(opacity)) {\n return 1;\n }\n return Number.parseFloat(opacity);\n }\n\n /**\n * Sets the opacity of this layer. If opacity is not a value between 0.0 and 1.0,\n * nothing happens.\n * @param {Float} opacity - A float value in the range 0.0-1.0\n * @returns {void}\n */\n setOpacity (opacity) {\n if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) {\n this.group_.setAttribute('opacity', opacity);\n }\n }\n\n /**\n * Append children to this layer.\n * @param {SVGGElement} children - The children to append to this layer.\n * @returns {void}\n */\n appendChildren (children) {\n for (const child of children) {\n this.group_.append(child);\n }\n }\n\n /**\n * @returns {SVGTitleElement|null}\n */\n getTitleElement () {\n const len = this.group_.childNodes.length;\n for (let i = 0; i < len; ++i) {\n const child = this.group_.childNodes.item(i);\n if (child && child.tagName === 'title') {\n return child;\n }\n }\n return null;\n }\n\n /**\n * Set the name of this layer.\n * @param {string} name - The new name.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {string|null} The new name if changed; otherwise, null.\n */\n setName (name, hrService) {\n const previousName = this.name_;\n name = toXml(name);\n // now change the underlying title element contents\n const title = this.getTitleElement();\n if (title) {\n $(title).empty();\n title.textContent = name;\n this.name_ = name;\n if (hrService) {\n hrService.changeElement(title, {'#text': previousName});\n }\n return this.name_;\n }\n return null;\n }\n\n /**\n * Remove this layer's group from the DOM. No more functions on group can be called after this.\n * @returns {SVGGElement} The layer SVG group that was just removed.\n */\n removeGroup () {\n const group = this.group_;\n this.group_.remove();\n this.group_ = undefined;\n return group;\n }\n}\n/**\n * @property {string} CLASS_NAME - class attribute assigned to all layer groups.\n */\nLayer.CLASS_NAME = 'layer';\n\n/**\n * @property {RegExp} CLASS_REGEX - Used to test presence of class Layer.CLASS_NAME\n */\nLayer.CLASS_REGEX = new RegExp('(\\\\s|^)' + Layer.CLASS_NAME + '(\\\\s|$)');\n\n/**\n * Add class `Layer.CLASS_NAME` to the element (usually `class='layer'`).\n *\n * @param {SVGGElement} elem - The SVG element to update\n * @returns {void}\n */\nfunction addLayerClass (elem) {\n const classes = elem.getAttribute('class');\n if (isNullish(classes) || !classes.length) {\n elem.setAttribute('class', Layer.CLASS_NAME);\n } else if (!Layer.CLASS_REGEX.test(classes)) {\n elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME);\n }\n}\n\nexport default Layer;\n","/**\n * HistoryRecordingService component of history.\n * @module history\n * @license MIT\n * @copyright 2016 Flint O'Brien\n */\n\nimport {\n BatchCommand, MoveElementCommand, InsertElementCommand, RemoveElementCommand,\n ChangeElementCommand\n} from './history.js';\n\n/**\n * History recording service.\n *\n * A self-contained service interface for recording history. Once injected, no other dependencies\n * or globals are required (example: UndoManager, command types, etc.). Easy to mock for unit tests.\n * Built on top of history classes in history.js.\n *\n * There is a simple start/end interface for batch commands.\n *\n * HistoryRecordingService.NO_HISTORY is a singleton that can be passed in to functions\n * that record history. This helps when the caller requires that no history be recorded.\n *\n * The following will record history: insert, batch, insert.\n * @example\n * hrService = new HistoryRecordingService(this.undoMgr);\n * hrService.insertElement(elem, text); // add simple command to history.\n * hrService.startBatchCommand('create two elements');\n * hrService.changeElement(elem, attrs, text); // add to batchCommand\n * hrService.changeElement(elem, attrs2, text); // add to batchCommand\n * hrService.endBatchCommand(); // add batch command with two change commands to history.\n * hrService.insertElement(elem, text); // add simple command to history.\n *\n * @example\n * // Note that all functions return this, so commands can be chained, like so:\n * hrService\n * .startBatchCommand('create two elements')\n * .insertElement(elem, text)\n * .changeElement(elem, attrs, text)\n * .endBatchCommand();\n *\n * @memberof module:history\n */\nclass HistoryRecordingService {\n /**\n * @param {history.UndoManager|null} undoManager - The undo manager.\n * A value of `null` is valid for cases where no history recording is required.\n * See singleton: {@link module:history.HistoryRecordingService.HistoryRecordingService.NO_HISTORY}\n */\n constructor (undoManager) {\n this.undoManager_ = undoManager;\n this.currentBatchCommand_ = null;\n this.batchCommandStack_ = [];\n }\n\n /**\n * Start a batch command so multiple commands can recorded as a single history command.\n * Requires a corresponding call to endBatchCommand. Start and end commands can be nested.\n *\n * @param {string} text - Optional string describing the batch command.\n * @returns {module:history.HistoryRecordingService}\n */\n startBatchCommand (text) {\n if (!this.undoManager_) { return this; }\n this.currentBatchCommand_ = new BatchCommand(text);\n this.batchCommandStack_.push(this.currentBatchCommand_);\n return this;\n }\n\n /**\n * End a batch command and add it to the history or a parent batch command.\n * @returns {module:history.HistoryRecordingService}\n */\n endBatchCommand () {\n if (!this.undoManager_) { return this; }\n if (this.currentBatchCommand_) {\n const batchCommand = this.currentBatchCommand_;\n this.batchCommandStack_.pop();\n const {length: len} = this.batchCommandStack_;\n this.currentBatchCommand_ = len ? this.batchCommandStack_[len - 1] : null;\n this.addCommand_(batchCommand);\n }\n return this;\n }\n\n /**\n * Add a `MoveElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was moved\n * @param {Element} oldNextSibling - The element's next sibling before it was moved\n * @param {Element} oldParent - The element's parent before it was moved\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n moveElement (elem, oldNextSibling, oldParent, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new MoveElementCommand(elem, oldNextSibling, oldParent, text));\n return this;\n }\n\n /**\n * Add an `InsertElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was added\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n insertElement (elem, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new InsertElementCommand(elem, text));\n return this;\n }\n\n /**\n * Add a `RemoveElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was removed\n * @param {Element} oldNextSibling - The element's next sibling before it was removed\n * @param {Element} oldParent - The element's parent before it was removed\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n removeElement (elem, oldNextSibling, oldParent, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new RemoveElementCommand(elem, oldNextSibling, oldParent, text));\n return this;\n }\n\n /**\n * Add a `ChangeElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was changed\n * @param {module:history.CommandAttributes} attrs - An object with the attributes to be changed and the values they had *before* the change\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n changeElement (elem, attrs, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new ChangeElementCommand(elem, attrs, text));\n return this;\n }\n\n /**\n * Private function to add a command to the history or current batch command.\n * @private\n * @param {Command} cmd\n * @returns {module:history.HistoryRecordingService|void}\n */\n addCommand_ (cmd) {\n if (!this.undoManager_) { return this; }\n if (this.currentBatchCommand_) {\n this.currentBatchCommand_.addSubCommand(cmd);\n } else {\n this.undoManager_.addCommandToHistory(cmd);\n }\n return undefined;\n }\n}\n/**\n * @memberof module:history.HistoryRecordingService\n * @property {module:history.HistoryRecordingService} NO_HISTORY - Singleton that can be passed to functions that record history, but the caller requires that no history be recorded.\n */\nHistoryRecordingService.NO_HISTORY = new HistoryRecordingService();\nexport default HistoryRecordingService;\n","/* globals jQuery */\n\nimport jQueryPluginSVG from '../common/jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport {isWebkit} from '../common/browser.js';\nimport {convertPath} from './path.js';\nimport {preventClickDefault} from '../common/utilities.js';\n\n// Constants\nconst $ = jQueryPluginSVG(jQuery);\n\n/**\n * Create a clone of an element, updating its ID and its children's IDs when needed.\n * @function module:utilities.copyElem\n * @param {Element} el - DOM element to clone\n * @param {module:utilities.GetNextID} getNextId - The getter of the next unique ID.\n * @returns {Element} The cloned element\n */\nexport const copyElem = function (el, getNextId) {\n // manually create a copy of the element\n const newEl = document.createElementNS(el.namespaceURI, el.nodeName);\n $.each(el.attributes, function (i, attr) {\n if (attr.localName !== '-moz-math-font-style') {\n newEl.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value);\n }\n });\n // set the copied element's new id\n newEl.removeAttribute('id');\n newEl.id = getNextId();\n\n // Opera's \"d\" value needs to be reset for Opera/Win/non-EN\n // Also needed for webkit (else does not keep curved segments on clone)\n if (isWebkit() && el.nodeName === 'path') {\n const fixedD = convertPath(el);\n newEl.setAttribute('d', fixedD);\n }\n\n // now create copies of all children\n $.each(el.childNodes, function (i, child) {\n switch (child.nodeType) {\n case 1: // element node\n newEl.append(copyElem(child, getNextId));\n break;\n case 3: // text node\n newEl.textContent = child.nodeValue;\n break;\n default:\n break;\n }\n });\n\n if ($(el).data('gsvg')) {\n $(newEl).data('gsvg', newEl.firstChild);\n } else if ($(el).data('symbol')) {\n const ref = $(el).data('symbol');\n $(newEl).data('ref', ref).data('symbol', ref);\n } else if (newEl.tagName === 'image') {\n preventClickDefault(newEl);\n }\n\n return newEl;\n};\n","/* globals jQuery */\n/**\n * Tools for drawing.\n * @module draw\n * @license MIT\n * @copyright 2011 Jeff Schiller\n */\n\nimport Layer from '../common/layer.js';\nimport HistoryRecordingService from './historyrecording.js';\n\nimport {NS} from '../common/namespaces.js';\nimport {isOpera} from '../common/browser.js';\nimport {\n toXml, getElem\n} from '../common/utilities.js';\nimport {\n copyElem as utilCopyElem\n} from './copy-elem.js';\nimport {\n BatchCommand, RemoveElementCommand, MoveElementCommand, ChangeElementCommand\n} from './history.js';\n\nconst $ = jQuery;\n\nconst visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(',');\n\nconst RandomizeModes = {\n LET_DOCUMENT_DECIDE: 0,\n ALWAYS_RANDOMIZE: 1,\n NEVER_RANDOMIZE: 2\n};\nlet randIds = RandomizeModes.LET_DOCUMENT_DECIDE;\n// Array with current disabled elements (for in-group editing)\nlet disabledElems = [];\n\n/**\n * Get a HistoryRecordingService.\n * @param {module:history.HistoryRecordingService} [hrService] - if exists, return it instead of creating a new service.\n * @returns {module:history.HistoryRecordingService}\n */\nfunction historyRecordingService (hrService) {\n return hrService || new HistoryRecordingService(canvas_.undoMgr);\n}\n\n/**\n * Find the layer name in a group element.\n * @param {Element} group The group element to search in.\n * @returns {string} The layer name or empty string.\n */\nfunction findLayerNameInGroup (group) {\n return $('title', group).text() ||\n (isOpera() && group.querySelectorAll\n // Hack for Opera 10.60\n ? $(group.querySelectorAll('title')).text()\n : '');\n}\n\n/**\n * Given a set of names, return a new unique name.\n * @param {string[]} existingLayerNames - Existing layer names.\n * @returns {string} - The new name.\n */\nfunction getNewLayerName (existingLayerNames) {\n let i = 1;\n // TODO(codedread): What about internationalization of \"Layer\"?\n while (existingLayerNames.includes(('Layer ' + i))) { i++; }\n return 'Layer ' + i;\n}\n\n/**\n * This class encapsulates the concept of a SVG-edit drawing.\n */\nexport class Drawing {\n /**\n * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object\n * encapsulates. If the svgElem has a se:nonce attribute on it, then\n * IDs will use the nonce as they are generated.\n * @param {string} [optIdPrefix=svg_] - The ID prefix to use.\n * @throws {Error} If not initialized with an SVG element\n */\n constructor (svgElem, optIdPrefix) {\n if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI ||\n svgElem.tagName !== 'svg' || svgElem.namespaceURI !== NS.SVG) {\n throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element');\n }\n\n /**\n * The SVG DOM Element that represents this drawing.\n * @type {SVGSVGElement}\n */\n this.svgElem_ = svgElem;\n\n /**\n * The latest object number used in this drawing.\n * @type {Integer}\n */\n this.obj_num = 0;\n\n /**\n * The prefix to prepend to each element id in the drawing.\n * @type {string}\n */\n this.idPrefix = optIdPrefix || 'svg_';\n\n /**\n * An array of released element ids to immediately reuse.\n * @type {Integer[]}\n */\n this.releasedNums = [];\n\n /**\n * The z-ordered array of Layer objects. Each layer has a name\n * and group element.\n * The first layer is the one at the bottom of the rendering.\n * @type {Layer[]}\n */\n this.all_layers = [];\n\n /**\n * Map of all_layers by name.\n *\n * Note: Layers are ordered, but referenced externally by name; so, we need both container\n * types depending on which function is called (i.e. all_layers and layer_map).\n *\n * @type {PlainObject<string, Layer>}\n */\n this.layer_map = {};\n\n /**\n * The current layer being used.\n * @type {Layer}\n */\n this.current_layer = null;\n\n /**\n * The nonce to use to uniquely identify elements across drawings.\n * @type {!string}\n */\n this.nonce_ = '';\n const n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');\n // If already set in the DOM, use the nonce throughout the document\n // else, if randomizeIds(true) has been called, create and set the nonce.\n if (n && randIds !== RandomizeModes.NEVER_RANDOMIZE) {\n this.nonce_ = n;\n } else if (randIds === RandomizeModes.ALWAYS_RANDOMIZE) {\n this.setNonce(Math.floor(Math.random() * 100001));\n }\n }\n\n /**\n * @param {string} id Element ID to retrieve\n * @returns {Element} SVG element within the root SVGSVGElement\n */\n getElem_ (id) {\n if (this.svgElem_.querySelector) {\n // querySelector lookup\n return this.svgElem_.querySelector('#' + id);\n }\n // jQuery lookup: twice as slow as xpath in FF\n // eslint-disable-next-line unicorn/no-fn-reference-in-iterator\n return $(this.svgElem_).find('[id=' + id + ']')[0];\n }\n\n /**\n * @returns {SVGSVGElement}\n */\n getSvgElem () {\n return this.svgElem_;\n }\n\n /**\n * @returns {!(string|Integer)} The previously set nonce\n */\n getNonce () {\n return this.nonce_;\n }\n\n /**\n * @param {!(string|Integer)} n The nonce to set\n * @returns {void}\n */\n setNonce (n) {\n this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE);\n this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n);\n this.nonce_ = n;\n }\n\n /**\n * Clears any previously set nonce.\n * @returns {void}\n */\n clearNonce () {\n // We deliberately leave any se:nonce attributes alone,\n // we just don't use it to randomize ids.\n this.nonce_ = '';\n }\n\n /**\n * Returns the latest object id as a string.\n * @returns {string} The latest object Id.\n */\n getId () {\n return this.nonce_\n ? this.idPrefix + this.nonce_ + '_' + this.obj_num\n : this.idPrefix + this.obj_num;\n }\n\n /**\n * Returns the next object Id as a string.\n * @returns {string} The next object Id to use.\n */\n getNextId () {\n const oldObjNum = this.obj_num;\n let restoreOldObjNum = false;\n\n // If there are any released numbers in the release stack,\n // use the last one instead of the next obj_num.\n // We need to temporarily use obj_num as that is what getId() depends on.\n if (this.releasedNums.length > 0) {\n this.obj_num = this.releasedNums.pop();\n restoreOldObjNum = true;\n } else {\n // If we are not using a released id, then increment the obj_num.\n this.obj_num++;\n }\n\n // Ensure the ID does not exist.\n let id = this.getId();\n while (this.getElem_(id)) {\n if (restoreOldObjNum) {\n this.obj_num = oldObjNum;\n restoreOldObjNum = false;\n }\n this.obj_num++;\n id = this.getId();\n }\n // Restore the old object number if required.\n if (restoreOldObjNum) {\n this.obj_num = oldObjNum;\n }\n return id;\n }\n\n /**\n * Releases the object Id, letting it be used as the next id in getNextId().\n * This method DOES NOT remove any elements from the DOM, it is expected\n * that client code will do this.\n * @param {string} id - The id to release.\n * @returns {boolean} True if the id was valid to be released, false otherwise.\n */\n releaseId (id) {\n // confirm if this is a valid id for this Document, else return false\n const front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : '');\n if (typeof id !== 'string' || !id.startsWith(front)) {\n return false;\n }\n // extract the obj_num of this id\n const num = Number.parseInt(id.substr(front.length));\n\n // if we didn't get a positive number or we already released this number\n // then return false.\n if (typeof num !== 'number' || num <= 0 || this.releasedNums.includes(num)) {\n return false;\n }\n\n // push the released number into the released queue\n this.releasedNums.push(num);\n\n return true;\n }\n\n /**\n * Returns the number of layers in the current drawing.\n * @returns {Integer} The number of layers in the current drawing.\n */\n getNumLayers () {\n return this.all_layers.length;\n }\n\n /**\n * Check if layer with given name already exists.\n * @param {string} name - The layer name to check\n * @returns {boolean}\n */\n hasLayer (name) {\n return this.layer_map[name] !== undefined;\n }\n\n /**\n * Returns the name of the ith layer. If the index is out of range, an empty string is returned.\n * @param {Integer} i - The zero-based index of the layer you are querying.\n * @returns {string} The name of the ith layer (or the empty string if none found)\n */\n getLayerName (i) {\n return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : '';\n }\n\n /**\n * @returns {SVGGElement|null} The SVGGElement representing the current layer.\n */\n getCurrentLayer () {\n return this.current_layer ? this.current_layer.getGroup() : null;\n }\n\n /**\n * Get a layer by name.\n * @param {string} name\n * @returns {SVGGElement} The SVGGElement representing the named layer or null.\n */\n getLayerByName (name) {\n const layer = this.layer_map[name];\n return layer ? layer.getGroup() : null;\n }\n\n /**\n * Returns the name of the currently selected layer. If an error occurs, an empty string\n * is returned.\n * @returns {string} The name of the currently active layer (or the empty string if none found).\n */\n getCurrentLayerName () {\n return this.current_layer ? this.current_layer.getName() : '';\n }\n\n /**\n * Set the current layer's name.\n * @param {string} name - The new name.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {string|null} The new name if changed; otherwise, null.\n */\n setCurrentLayerName (name, hrService) {\n let finalName = null;\n if (this.current_layer) {\n const oldName = this.current_layer.getName();\n finalName = this.current_layer.setName(name, hrService);\n if (finalName) {\n delete this.layer_map[oldName];\n this.layer_map[finalName] = this.current_layer;\n }\n }\n return finalName;\n }\n\n /**\n * Set the current layer's position.\n * @param {Integer} newpos - The zero-based index of the new position of the layer. Range should be 0 to layers-1\n * @returns {{title: SVGGElement, previousName: string}|null} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null.\n */\n setCurrentLayerPosition (newpos) {\n const layerCount = this.getNumLayers();\n if (!this.current_layer || newpos < 0 || newpos >= layerCount) {\n return null;\n }\n\n let oldpos;\n for (oldpos = 0; oldpos < layerCount; ++oldpos) {\n if (this.all_layers[oldpos] === this.current_layer) { break; }\n }\n // some unknown error condition (current_layer not in all_layers)\n if (oldpos === layerCount) { return null; }\n\n if (oldpos !== newpos) {\n // if our new position is below us, we need to insert before the node after newpos\n const currentGroup = this.current_layer.getGroup();\n const oldNextSibling = currentGroup.nextSibling;\n\n let refGroup = null;\n if (newpos > oldpos) {\n if (newpos < layerCount - 1) {\n refGroup = this.all_layers[newpos + 1].getGroup();\n }\n // if our new position is above us, we need to insert before the node at newpos\n } else {\n refGroup = this.all_layers[newpos].getGroup();\n }\n this.svgElem_.insertBefore(currentGroup, refGroup); // Ok to replace with `refGroup.before(currentGroup);`?\n\n this.identifyLayers();\n this.setCurrentLayer(this.getLayerName(newpos));\n\n return {\n currentGroup,\n oldNextSibling\n };\n }\n return null;\n }\n\n /**\n * @param {module:history.HistoryRecordingService} hrService\n * @returns {void}\n */\n mergeLayer (hrService) {\n const currentGroup = this.current_layer.getGroup();\n const prevGroup = $(currentGroup).prev()[0];\n if (!prevGroup) { return; }\n\n hrService.startBatchCommand('Merge Layer');\n\n const layerNextSibling = currentGroup.nextSibling;\n hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_);\n\n while (currentGroup.firstChild) {\n const child = currentGroup.firstChild;\n if (child.localName === 'title') {\n hrService.removeElement(child, child.nextSibling, currentGroup);\n child.remove();\n continue;\n }\n const oldNextSibling = child.nextSibling;\n prevGroup.append(child);\n hrService.moveElement(child, oldNextSibling, currentGroup);\n }\n\n // Remove current layer's group\n this.current_layer.removeGroup();\n // Remove the current layer and set the previous layer as the new current layer\n const index = this.all_layers.indexOf(this.current_layer);\n if (index > 0) {\n const name = this.current_layer.getName();\n this.current_layer = this.all_layers[index - 1];\n this.all_layers.splice(index, 1);\n delete this.layer_map[name];\n }\n\n hrService.endBatchCommand();\n }\n\n /**\n * @param {module:history.HistoryRecordingService} hrService\n * @returns {void}\n */\n mergeAllLayers (hrService) {\n // Set the current layer to the last layer.\n this.current_layer = this.all_layers[this.all_layers.length - 1];\n\n hrService.startBatchCommand('Merge all Layers');\n while (this.all_layers.length > 1) {\n this.mergeLayer(hrService);\n }\n hrService.endBatchCommand();\n }\n\n /**\n * Sets the current layer. If the name is not a valid layer name, then this\n * function returns `false`. Otherwise it returns `true`. This is not an\n * undo-able action.\n * @param {string} name - The name of the layer you want to switch to.\n * @returns {boolean} `true` if the current layer was switched, otherwise `false`\n */\n setCurrentLayer (name) {\n const layer = this.layer_map[name];\n if (layer) {\n if (this.current_layer) {\n this.current_layer.deactivate();\n }\n this.current_layer = layer;\n this.current_layer.activate();\n return true;\n }\n return false;\n }\n\n /**\n * Deletes the current layer from the drawing and then clears the selection.\n * This function then calls the 'changed' handler. This is an undoable action.\n * @todo Does this actually call the 'changed' handler?\n * @returns {SVGGElement} The SVGGElement of the layer removed or null.\n */\n deleteCurrentLayer () {\n if (this.current_layer && this.getNumLayers() > 1) {\n const oldLayerGroup = this.current_layer.removeGroup();\n this.identifyLayers();\n return oldLayerGroup;\n }\n return null;\n }\n\n /**\n * Updates layer system and sets the current layer to the\n * top-most layer (last `<g>` child of this drawing).\n * @returns {void}\n */\n identifyLayers () {\n this.all_layers = [];\n this.layer_map = {};\n const numchildren = this.svgElem_.childNodes.length;\n // loop through all children of SVG element\n const orphans = [], layernames = [];\n let layer = null;\n let childgroups = false;\n for (let i = 0; i < numchildren; ++i) {\n const child = this.svgElem_.childNodes.item(i);\n // for each g, find its layer name\n if (child && child.nodeType === 1) {\n if (child.tagName === 'g') {\n childgroups = true;\n const name = findLayerNameInGroup(child);\n if (name) {\n layernames.push(name);\n layer = new Layer(name, child);\n this.all_layers.push(layer);\n this.layer_map[name] = layer;\n } else {\n // if group did not have a name, it is an orphan\n orphans.push(child);\n }\n } else if (visElems.includes(child.nodeName)) {\n // Child is \"visible\" (i.e. not a <title> or <defs> element), so it is an orphan\n orphans.push(child);\n }\n }\n }\n\n // If orphans or no layers found, create a new layer and add all the orphans to it\n if (orphans.length > 0 || !childgroups) {\n layer = new Layer(getNewLayerName(layernames), null, this.svgElem_);\n layer.appendChildren(orphans);\n this.all_layers.push(layer);\n this.layer_map[name] = layer;\n } else {\n layer.activate();\n }\n this.current_layer = layer;\n }\n\n /**\n * Creates a new top-level layer in the drawing with the given name and\n * makes it the current layer.\n * @param {string} name - The given name. If the layer name exists, a new name will be generated.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {SVGGElement} The SVGGElement of the new layer, which is\n * also the current layer of this drawing.\n */\n createLayer (name, hrService) {\n if (this.current_layer) {\n this.current_layer.deactivate();\n }\n // Check for duplicate name.\n if (name === undefined || name === null || name === '' || this.layer_map[name]) {\n name = getNewLayerName(Object.keys(this.layer_map));\n }\n\n // Crate new layer and add to DOM as last layer\n const layer = new Layer(name, null, this.svgElem_);\n // Like to assume hrService exists, but this is backwards compatible with old version of createLayer.\n if (hrService) {\n hrService.startBatchCommand('Create Layer');\n hrService.insertElement(layer.getGroup());\n hrService.endBatchCommand();\n }\n\n this.all_layers.push(layer);\n this.layer_map[name] = layer;\n this.current_layer = layer;\n return layer.getGroup();\n }\n\n /**\n * Creates a copy of the current layer with the given name and makes it the current layer.\n * @param {string} name - The given name. If the layer name exists, a new name will be generated.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {SVGGElement} The SVGGElement of the new layer, which is\n * also the current layer of this drawing.\n */\n cloneLayer (name, hrService) {\n if (!this.current_layer) { return null; }\n this.current_layer.deactivate();\n // Check for duplicate name.\n if (name === undefined || name === null || name === '' || this.layer_map[name]) {\n name = getNewLayerName(Object.keys(this.layer_map));\n }\n\n // Create new group and add to DOM just after current_layer\n const currentGroup = this.current_layer.getGroup();\n const layer = new Layer(name, currentGroup, this.svgElem_);\n const group = layer.getGroup();\n\n // Clone children\n const children = [...currentGroup.childNodes];\n children.forEach((child) => {\n if (child.localName === 'title') { return; }\n group.append(this.copyElem(child));\n });\n\n if (hrService) {\n hrService.startBatchCommand('Duplicate Layer');\n hrService.insertElement(group);\n hrService.endBatchCommand();\n }\n\n // Update layer containers and current_layer.\n const index = this.all_layers.indexOf(this.current_layer);\n if (index >= 0) {\n this.all_layers.splice(index + 1, 0, layer);\n } else {\n this.all_layers.push(layer);\n }\n this.layer_map[name] = layer;\n this.current_layer = layer;\n return group;\n }\n\n /**\n * Returns whether the layer is visible. If the layer name is not valid,\n * then this function returns `false`.\n * @param {string} layerName - The name of the layer which you want to query.\n * @returns {boolean} The visibility state of the layer, or `false` if the layer name was invalid.\n */\n getLayerVisibility (layerName) {\n const layer = this.layer_map[layerName];\n return layer ? layer.isVisible() : false;\n }\n\n /**\n * Sets the visibility of the layer. If the layer name is not valid, this\n * function returns `null`, otherwise it returns the `SVGElement` representing\n * the layer. This is an undo-able action.\n * @param {string} layerName - The name of the layer to change the visibility\n * @param {boolean} bVisible - Whether the layer should be visible\n * @returns {?SVGGElement} The SVGGElement representing the layer if the\n * `layerName` was valid, otherwise `null`.\n */\n setLayerVisibility (layerName, bVisible) {\n if (typeof bVisible !== 'boolean') {\n return null;\n }\n const layer = this.layer_map[layerName];\n if (!layer) { return null; }\n layer.setVisible(bVisible);\n return layer.getGroup();\n }\n\n /**\n * Returns the opacity of the given layer. If the input name is not a layer, `null` is returned.\n * @param {string} layerName - name of the layer on which to get the opacity\n * @returns {?Float} The opacity value of the given layer. This will be a value between 0.0 and 1.0, or `null`\n * if `layerName` is not a valid layer\n */\n getLayerOpacity (layerName) {\n const layer = this.layer_map[layerName];\n if (!layer) { return null; }\n return layer.getOpacity();\n }\n\n /**\n * Sets the opacity of the given layer. If the input name is not a layer,\n * nothing happens. If opacity is not a value between 0.0 and 1.0, then\n * nothing happens.\n * NOTE: this function exists solely to apply a highlighting/de-emphasis\n * effect to a layer. When it is possible for a user to affect the opacity\n * of a layer, we will need to allow this function to produce an undo-able\n * action.\n * @param {string} layerName - Name of the layer on which to set the opacity\n * @param {Float} opacity - A float value in the range 0.0-1.0\n * @returns {void}\n */\n setLayerOpacity (layerName, opacity) {\n if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {\n return;\n }\n const layer = this.layer_map[layerName];\n if (layer) {\n layer.setOpacity(opacity);\n }\n }\n\n /**\n * Create a clone of an element, updating its ID and its children's IDs when needed.\n * @param {Element} el - DOM element to clone\n * @returns {Element}\n */\n copyElem (el) {\n const that = this;\n const getNextIdClosure = function () { return that.getNextId(); };\n return utilCopyElem(el, getNextIdClosure);\n }\n}\n\n/**\n * Called to ensure that drawings will or will not have randomized ids.\n * The currentDrawing will have its nonce set if it doesn't already.\n * @function module:draw.randomizeIds\n * @param {boolean} enableRandomization - flag indicating if documents should have randomized ids\n * @param {draw.Drawing} currentDrawing\n * @returns {void}\n */\nexport const randomizeIds = function (enableRandomization, currentDrawing) {\n randIds = enableRandomization === false\n ? RandomizeModes.NEVER_RANDOMIZE\n : RandomizeModes.ALWAYS_RANDOMIZE;\n\n if (randIds === RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) {\n currentDrawing.setNonce(Math.floor(Math.random() * 100001));\n } else if (randIds === RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) {\n currentDrawing.clearNonce();\n }\n};\n\n// Layer API Functions\n\n/**\n* Group: Layers.\n*/\n\n/**\n * @see {@link https://api.jquery.com/jQuery.data/}\n * @name external:jQuery.data\n */\n\n/**\n * @interface module:draw.DrawCanvasInit\n * @property {module:path.pathActions} pathActions\n * @property {external:jQuery.data} elData\n * @property {module:history.UndoManager} undoMgr\n */\n/**\n * @function module:draw.DrawCanvasInit#getCurrentGroup\n * @returns {Element}\n */\n/**\n * @function module:draw.DrawCanvasInit#setCurrentGroup\n * @param {Element} cg\n * @returns {void}\n*/\n/**\n * @function module:draw.DrawCanvasInit#getSelectedElements\n * @returns {Element[]} the array with selected DOM elements\n*/\n/**\n * @function module:draw.DrawCanvasInit#getSVGContent\n * @returns {SVGSVGElement}\n */\n/**\n * @function module:draw.DrawCanvasInit#getCurrentDrawing\n * @returns {module:draw.Drawing}\n */\n/**\n * @function module:draw.DrawCanvasInit#clearSelection\n * @param {boolean} [noCall] - When `true`, does not call the \"selected\" handler\n * @returns {void}\n*/\n/**\n * Run the callback function associated with the given event.\n * @function module:draw.DrawCanvasInit#call\n * @param {\"changed\"|\"contextset\"} ev - String with the event name\n * @param {module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset} arg - Argument to pass through to the callback\n * function. If the event is \"changed\", a (single-item) array of `Element`s is\n * passed. If the event is \"contextset\", the arg is `null` or `Element`.\n * @returns {void}\n */\n/**\n * @function module:draw.DrawCanvasInit#addCommandToHistory\n * @param {Command} cmd\n * @returns {void}\n*/\n/**\n * @function module:draw.DrawCanvasInit#changeSVGContent\n * @returns {void}\n */\n\nlet canvas_;\n/**\n* @function module:draw.init\n* @param {module:draw.DrawCanvasInit} canvas\n* @returns {void}\n*/\nexport const init = function (canvas) {\n canvas_ = canvas;\n};\n\n/**\n* Updates layer system.\n* @function module:draw.identifyLayers\n* @returns {void}\n*/\nexport const identifyLayers = function () {\n leaveContext();\n canvas_.getCurrentDrawing().identifyLayers();\n};\n\n/**\n* Creates a new top-level layer in the drawing with the given name, sets the current layer\n* to it, and then clears the selection. This function then calls the 'changed' handler.\n* This is an undoable action.\n* @function module:draw.createLayer\n* @param {string} name - The given name\n* @param {module:history.HistoryRecordingService} hrService\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nexport const createLayer = function (name, hrService) {\n const newLayer = canvas_.getCurrentDrawing().createLayer(\n name,\n historyRecordingService(hrService)\n );\n canvas_.clearSelection();\n canvas_.call('changed', [newLayer]);\n};\n\n/**\n * Creates a new top-level layer in the drawing with the given name, copies all the current layer's contents\n * to it, and then clears the selection. This function then calls the 'changed' handler.\n * This is an undoable action.\n * @function module:draw.cloneLayer\n * @param {string} name - The given name. If the layer name exists, a new name will be generated.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\nexport const cloneLayer = function (name, hrService) {\n // Clone the current layer and make the cloned layer the new current layer\n const newLayer = canvas_.getCurrentDrawing().cloneLayer(name, historyRecordingService(hrService));\n\n canvas_.clearSelection();\n leaveContext();\n canvas_.call('changed', [newLayer]);\n};\n\n/**\n* Deletes the current layer from the drawing and then clears the selection. This function\n* then calls the 'changed' handler. This is an undoable action.\n* @function module:draw.deleteCurrentLayer\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} `true` if an old layer group was found to delete\n*/\nexport const deleteCurrentLayer = function () {\n let currentLayer = canvas_.getCurrentDrawing().getCurrentLayer();\n const {nextSibling} = currentLayer;\n const parent = currentLayer.parentNode;\n currentLayer = canvas_.getCurrentDrawing().deleteCurrentLayer();\n if (currentLayer) {\n const batchCmd = new BatchCommand('Delete Layer');\n // store in our Undo History\n batchCmd.addSubCommand(new RemoveElementCommand(currentLayer, nextSibling, parent));\n canvas_.addCommandToHistory(batchCmd);\n canvas_.clearSelection();\n canvas_.call('changed', [parent]);\n return true;\n }\n return false;\n};\n\n/**\n* Sets the current layer. If the name is not a valid layer name, then this function returns\n* false. Otherwise it returns true. This is not an undo-able action.\n* @function module:draw.setCurrentLayer\n* @param {string} name - The name of the layer you want to switch to.\n* @returns {boolean} true if the current layer was switched, otherwise false\n*/\nexport const setCurrentLayer = function (name) {\n const result = canvas_.getCurrentDrawing().setCurrentLayer(toXml(name));\n if (result) {\n canvas_.clearSelection();\n }\n return result;\n};\n\n/**\n* Renames the current layer. If the layer name is not valid (i.e. unique), then this function\n* does nothing and returns `false`, otherwise it returns `true`. This is an undo-able action.\n* @function module:draw.renameCurrentLayer\n* @param {string} newName - the new name you want to give the current layer. This name must\n* be unique among all layer names.\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} Whether the rename succeeded\n*/\nexport const renameCurrentLayer = function (newName) {\n const drawing = canvas_.getCurrentDrawing();\n const layer = drawing.getCurrentLayer();\n if (layer) {\n const result = drawing.setCurrentLayerName(newName, historyRecordingService());\n if (result) {\n canvas_.call('changed', [layer]);\n return true;\n }\n }\n return false;\n};\n\n/**\n* Changes the position of the current layer to the new value. If the new index is not valid,\n* this function does nothing and returns false, otherwise it returns true. This is an\n* undo-able action.\n* @function module:draw.setCurrentLayerPosition\n* @param {Integer} newPos - The zero-based index of the new position of the layer. This should be between\n* 0 and (number of layers - 1)\n* @returns {boolean} `true` if the current layer position was changed, `false` otherwise.\n*/\nexport const setCurrentLayerPosition = function (newPos) {\n const drawing = canvas_.getCurrentDrawing();\n const result = drawing.setCurrentLayerPosition(newPos);\n if (result) {\n canvas_.addCommandToHistory(new MoveElementCommand(result.currentGroup, result.oldNextSibling, canvas_.getSVGContent()));\n return true;\n }\n return false;\n};\n\n/**\n* Sets the visibility of the layer. If the layer name is not valid, this function return\n* `false`, otherwise it returns `true`. This is an undo-able action.\n* @function module:draw.setLayerVisibility\n* @param {string} layerName - The name of the layer to change the visibility\n* @param {boolean} bVisible - Whether the layer should be visible\n* @returns {boolean} true if the layer's visibility was set, false otherwise\n*/\nexport const setLayerVisibility = function (layerName, bVisible) {\n const drawing = canvas_.getCurrentDrawing();\n const prevVisibility = drawing.getLayerVisibility(layerName);\n const layer = drawing.setLayerVisibility(layerName, bVisible);\n if (layer) {\n const oldDisplay = prevVisibility ? 'inline' : 'none';\n canvas_.addCommandToHistory(new ChangeElementCommand(layer, {display: oldDisplay}, 'Layer Visibility'));\n } else {\n return false;\n }\n\n if (layer === drawing.getCurrentLayer()) {\n canvas_.clearSelection();\n canvas_.pathActions.clear();\n }\n // call('changed', [selected]);\n return true;\n};\n\n/**\n* Moves the selected elements to layerName. If the name is not a valid layer name, then `false`\n* is returned. Otherwise it returns `true`. This is an undo-able action.\n* @function module:draw.moveSelectedToLayer\n* @param {string} layerName - The name of the layer you want to which you want to move the selected elements\n* @returns {boolean} Whether the selected elements were moved to the layer.\n*/\nexport const moveSelectedToLayer = function (layerName) {\n // find the layer\n const drawing = canvas_.getCurrentDrawing();\n const layer = drawing.getLayerByName(layerName);\n if (!layer) { return false; }\n\n const batchCmd = new BatchCommand('Move Elements to Layer');\n\n // loop for each selected element and move it\n const selElems = canvas_.getSelectedElements();\n let i = selElems.length;\n while (i--) {\n const elem = selElems[i];\n if (!elem) { continue; }\n const oldNextSibling = elem.nextSibling;\n // TODO: this is pretty brittle!\n const oldLayer = elem.parentNode;\n layer.append(elem);\n batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer));\n }\n\n canvas_.addCommandToHistory(batchCmd);\n\n return true;\n};\n\n/**\n* @function module:draw.mergeLayer\n* @param {module:history.HistoryRecordingService} hrService\n* @returns {void}\n*/\nexport const mergeLayer = function (hrService) {\n canvas_.getCurrentDrawing().mergeLayer(historyRecordingService(hrService));\n canvas_.clearSelection();\n leaveContext();\n canvas_.changeSVGContent();\n};\n\n/**\n* @function module:draw.mergeAllLayers\n* @param {module:history.HistoryRecordingService} hrService\n* @returns {void}\n*/\nexport const mergeAllLayers = function (hrService) {\n canvas_.getCurrentDrawing().mergeAllLayers(historyRecordingService(hrService));\n canvas_.clearSelection();\n leaveContext();\n canvas_.changeSVGContent();\n};\n\n/**\n* Return from a group context to the regular kind, make any previously\n* disabled elements enabled again.\n* @function module:draw.leaveContext\n* @fires module:svgcanvas.SvgCanvas#event:contextset\n* @returns {void}\n*/\nexport const leaveContext = function () {\n const len = disabledElems.length;\n if (len) {\n for (let i = 0; i < len; i++) {\n const elem = disabledElems[i];\n const orig = canvas_.elData(elem, 'orig_opac');\n if (orig !== 1) {\n elem.setAttribute('opacity', orig);\n } else {\n elem.removeAttribute('opacity');\n }\n elem.setAttribute('style', 'pointer-events: inherit');\n }\n disabledElems = [];\n canvas_.clearSelection(true);\n canvas_.call('contextset', null);\n }\n canvas_.setCurrentGroup(null);\n};\n\n/**\n* Set the current context (for in-group editing).\n* @function module:draw.setContext\n* @param {Element} elem\n* @fires module:svgcanvas.SvgCanvas#event:contextset\n* @returns {void}\n*/\nexport const setContext = function (elem) {\n leaveContext();\n if (typeof elem === 'string') {\n elem = getElem(elem);\n }\n\n // Edit inside this group\n canvas_.setCurrentGroup(elem);\n\n // Disable other elements\n $(elem).parentsUntil('#svgcontent').andSelf().siblings().each(function () {\n const opac = this.getAttribute('opacity') || 1;\n // Store the original's opacity\n canvas_.elData(this, 'orig_opac', opac);\n this.setAttribute('opacity', opac * 0.33);\n this.setAttribute('style', 'pointer-events: none');\n disabledElems.push(this);\n });\n\n canvas_.clearSelection();\n canvas_.call('contextset', canvas_.getCurrentGroup());\n};\n\n/**\n* @memberof module:draw\n* @class Layer\n* @see {@link module:layer.Layer}\n*/\nexport {Layer};\n","/**\n * Tools for SVG sanitization.\n * @module sanitize\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {getReverseNS, NS} from '../common/namespaces.js';\nimport {isGecko} from '../common/browser.js';\nimport {getHref, setHref, getUrlFromAttr} from '../common/utilities.js';\n\nconst REVERSE_NS = getReverseNS();\n\n// Todo: Split out into core attributes, presentation attributes, etc. so consistent\n/**\n * This defines which elements and attributes that we support (or at least\n * don't remove).\n * @type {PlainObject}\n */\nconst svgWhiteList_ = {\n // SVG Elements\n a: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'],\n circle: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n clipPath: ['class', 'clipPathUnits', 'id'],\n defs: [],\n style: ['type'],\n desc: [],\n ellipse: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n feGaussianBlur: ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],\n feMorphology: ['class', 'in', 'operator', 'radius'],\n filter: ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],\n foreignObject: ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],\n g: ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],\n image: ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],\n line: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],\n linearGradient: ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],\n marker: ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],\n mask: ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],\n metadata: ['class', 'id'],\n path: ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n pattern: ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],\n polygon: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n polyline: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n radialGradient: ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],\n rect: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],\n stop: ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],\n svg: ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],\n switch: ['class', 'id', 'requiredFeatures', 'systemLanguage'],\n symbol: ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],\n text: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],\n textPath: ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],\n title: [],\n tspan: ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],\n use: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],\n\n // MathML Elements\n annotation: ['encoding'],\n 'annotation-xml': ['encoding'],\n maction: ['actiontype', 'other', 'selection'],\n math: ['class', 'id', 'display', 'xmlns'],\n menclose: ['notation'],\n merror: [],\n mfrac: ['linethickness'],\n mi: ['mathvariant'],\n mmultiscripts: [],\n mn: [],\n mo: ['fence', 'lspace', 'maxsize', 'minsize', 'rspace', 'stretchy'],\n mover: [],\n mpadded: ['lspace', 'width', 'height', 'depth', 'voffset'],\n mphantom: [],\n mprescripts: [],\n mroot: [],\n mrow: ['xlink:href', 'xlink:type', 'xmlns:xlink'],\n mspace: ['depth', 'height', 'width'],\n msqrt: [],\n mstyle: ['displaystyle', 'mathbackground', 'mathcolor', 'mathvariant', 'scriptlevel'],\n msub: [],\n msubsup: [],\n msup: [],\n mtable: ['align', 'columnalign', 'columnlines', 'columnspacing', 'displaystyle', 'equalcolumns', 'equalrows', 'frame', 'rowalign', 'rowlines', 'rowspacing', 'width'],\n mtd: ['columnalign', 'columnspan', 'rowalign', 'rowspan'],\n mtext: [],\n mtr: ['columnalign', 'rowalign'],\n munder: [],\n munderover: [],\n none: [],\n semantics: []\n};\n\n// Produce a Namespace-aware version of svgWhitelist\nconst svgWhiteListNS_ = {};\nObject.entries(svgWhiteList_).forEach(function ([elt, atts]) {\n const attNS = {};\n Object.entries(atts).forEach(function ([i, att]) {\n if (att.includes(':')) {\n const v = att.split(':');\n attNS[v[1]] = NS[(v[0]).toUpperCase()];\n } else {\n attNS[att] = att === 'xmlns' ? NS.XMLNS : null;\n }\n });\n svgWhiteListNS_[elt] = attNS;\n});\n\n/**\n* Sanitizes the input node and its children.\n* It only keeps what is allowed from our whitelist defined above.\n* @function module:sanitize.sanitizeSvg\n* @param {Text|Element} node - The DOM element to be checked (we'll also check its children) or text node to be cleaned up\n* @returns {void}\n*/\nexport const sanitizeSvg = function (node) {\n // Cleanup text nodes\n if (node.nodeType === 3) { // 3 === TEXT_NODE\n // Trim whitespace\n node.nodeValue = node.nodeValue.replace(/^\\s+|\\s+$/g, '');\n // Remove if empty\n if (!node.nodeValue.length) {\n node.remove();\n }\n }\n\n // We only care about element nodes.\n // Automatically return for all non-element nodes, such as comments, etc.\n if (node.nodeType !== 1) { // 1 == ELEMENT_NODE\n return;\n }\n\n const doc = node.ownerDocument;\n const parent = node.parentNode;\n // can parent ever be null here? I think the root node's parent is the document...\n if (!doc || !parent) {\n return;\n }\n\n const allowedAttrs = svgWhiteList_[node.nodeName];\n const allowedAttrsNS = svgWhiteListNS_[node.nodeName];\n // if this element is supported, sanitize it\n if (typeof allowedAttrs !== 'undefined') {\n const seAttrs = [];\n let i = node.attributes.length;\n while (i--) {\n // if the attribute is not in our whitelist, then remove it\n // could use jQuery's inArray(), but I don't know if that's any better\n const attr = node.attributes.item(i);\n const attrName = attr.nodeName;\n const attrLocalName = attr.localName;\n const attrNsURI = attr.namespaceURI;\n // Check that an attribute with the correct localName in the correct namespace is on\n // our whitelist or is a namespace declaration for one of our allowed namespaces\n if (!({}.hasOwnProperty.call(allowedAttrsNS, attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) &&\n !(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) {\n // TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.\n // Bypassing the whitelist to allow se: prefixes.\n // Is there a more appropriate way to do this?\n if (attrName.startsWith('se:') || attrName.startsWith('data-')) {\n seAttrs.push([attrName, attr.value]);\n }\n node.removeAttributeNS(attrNsURI, attrLocalName);\n }\n\n // Add spaces before negative signs where necessary\n if (isGecko()) {\n switch (attrName) {\n case 'transform':\n case 'gradientTransform':\n case 'patternTransform': {\n const val = attr.value.replace(/(\\d)-/g, '$1 -');\n // const val = attr.value.replace(/(?<digit>\\d)-/g, '$<digit> -');\n node.setAttribute(attrName, val);\n break;\n }\n }\n }\n\n // For the style attribute, rewrite it in terms of XML presentational attributes\n if (attrName === 'style') {\n const props = attr.value.split(';');\n let p = props.length;\n while (p--) {\n const [name, val] = props[p].split(':');\n const styleAttrName = (name || '').trim();\n const styleAttrVal = (val || '').trim();\n // Now check that this attribute is supported\n if (allowedAttrs.includes(styleAttrName)) {\n node.setAttribute(styleAttrName, styleAttrVal);\n }\n }\n node.removeAttribute('style');\n }\n }\n\n Object.values(seAttrs).forEach(([att, val]) => {\n node.setAttributeNS(NS.SE, att, val);\n });\n\n // for some elements that have a xlink:href, ensure the URI refers to a local element\n // (but not for links)\n const href = getHref(node);\n if (href &&\n ['filter', 'linearGradient', 'pattern',\n 'radialGradient', 'textPath', 'use'].includes(node.nodeName)) {\n // TODO: we simply check if the first character is a #, is this bullet-proof?\n if (href[0] !== '#') {\n // remove the attribute (but keep the element)\n setHref(node, '');\n node.removeAttributeNS(NS.XLINK, 'href');\n }\n }\n\n // Safari crashes on a <use> without a xlink:href, so we just remove the node here\n if (node.nodeName === 'use' && !getHref(node)) {\n node.remove();\n return;\n }\n // if the element has attributes pointing to a non-local reference,\n // need to remove the attribute\n Object.values(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (attr) {\n let val = node.getAttribute(attr);\n if (val) {\n val = getUrlFromAttr(val);\n // simply check for first character being a '#'\n if (val && val[0] !== '#') {\n node.setAttribute(attr, '');\n node.removeAttribute(attr);\n }\n }\n });\n\n // recurse to children\n i = node.childNodes.length;\n while (i--) { sanitizeSvg(node.childNodes.item(i)); }\n // else (element not supported), remove it\n } else {\n // remove all children from this node and insert them before this node\n // TODO: in the case of animation elements this will hardly ever be correct\n const children = [];\n while (node.hasChildNodes()) {\n children.push(parent.insertBefore(node.firstChild, node));\n }\n\n // remove this node from the document altogether\n node.remove();\n\n // call sanitizeSvg on each of those children\n let i = children.length;\n while (i--) { sanitizeSvg(children[i]); }\n }\n};\n","/* eslint-disable jsdoc/require-file-overview */\n/**\n * Adapted from {@link https://github.com/uupaa/dynamic-import-polyfill/blob/master/importModule.js}.\n * @module importModule\n * @license MIT\n */\n\n/**\n * Converts a possible relative URL into an absolute one.\n * @param {string} url\n * @returns {string}\n */\nfunction toAbsoluteURL (url) {\n const a = document.createElement('a');\n a.setAttribute('href', url); // <a href=\"hoge.html\">\n return a.cloneNode(false).href; // -> \"http://example.com/hoge.html\"\n}\n\n/**\n * Add any of the whitelisted attributes to the script tag.\n * @param {HTMLScriptElement} script\n * @param {PlainObject<string, string>} atts\n * @returns {void}\n */\nfunction addScriptAtts (script, atts) {\n ['id', 'class', 'type'].forEach((prop) => {\n if (prop in atts) {\n script[prop] = atts[prop];\n }\n });\n}\n\n// Additions by Brett\n/**\n* @typedef {PlainObject} module:importModule.ImportConfig\n* @property {string} global The variable name to set on `window` (when not using the modular version)\n* @property {boolean} [returnDefault=false]\n*/\n\n/**\n* @function module:importModule.importSetGlobalDefault\n* @param {string|GenericArray<any>} url\n* @param {module:importModule.ImportConfig} config\n* @returns {Promise<any>} The value to which it resolves depends on the export of the targeted module.\n*/\nexport function importSetGlobalDefault (url, config) {\n return importSetGlobal(url, {...config, returnDefault: true});\n}\n/**\n* @function module:importModule.importSetGlobal\n* @param {string|string[]} url\n* @param {module:importModule.ImportConfig} config\n* @returns {Promise<ArbitraryModule>} The promise resolves to either an `ArbitraryModule` or\n* any other value depends on the export of the targeted module.\n*/\nexport async function importSetGlobal (url, {global: glob, returnDefault}) {\n // Todo: Replace calls to this function with `import()` when supported\n const modularVersion = !('svgEditor' in window) ||\n !window.svgEditor ||\n window.svgEditor.modules !== false;\n if (modularVersion) {\n return importModule(url, undefined, {returnDefault});\n }\n await importScript(url);\n return window[glob];\n}\n\n/**\n *\n * @author Brett Zamir (other items are from `dynamic-import-polyfill`)\n * @param {string|string[]} url\n * @param {PlainObject} [atts={}]\n * @returns {Promise<void|Error>} Resolves to `undefined` or rejects with an `Error` upon a\n * script loading error\n */\nexport function importScript (url, atts = {}) {\n if (Array.isArray(url)) {\n return Promise.all(url.map((u) => {\n return importScript(u, atts);\n }));\n }\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n const script = document.createElement('script');\n /**\n *\n * @returns {void}\n */\n function scriptOnError () {\n reject(new Error(`Failed to import: ${url}`));\n destructor();\n }\n /**\n *\n * @returns {void}\n */\n function scriptOnLoad () {\n resolve();\n destructor();\n }\n const destructor = () => {\n script.removeEventListener('error', scriptOnError);\n script.removeEventListener('load', scriptOnLoad);\n script.remove();\n script.src = '';\n };\n script.defer = 'defer';\n addScriptAtts(script, atts);\n script.addEventListener('error', scriptOnError);\n script.addEventListener('load', scriptOnLoad);\n script.src = url;\n\n document.head.append(script);\n });\n}\n\n/**\n*\n* @param {string|string[]} url\n* @param {PlainObject} [atts={}]\n* @param {PlainObject} opts\n* @param {boolean} [opts.returnDefault=false} = {}]\n* @returns {Promise<any>} Resolves to value of loading module or rejects with\n* `Error` upon a script loading error.\n*/\nexport function importModule (url, atts = {}, {returnDefault = false} = {}) {\n if (Array.isArray(url)) {\n return Promise.all(url.map((u) => {\n return importModule(u, atts);\n }));\n }\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n const vector = '$importModule$' + Math.random().toString(32).slice(2);\n const script = document.createElement('script');\n /**\n *\n * @returns {void}\n */\n function scriptOnError () {\n reject(new Error(`Failed to import: ${url}`));\n destructor();\n }\n /**\n *\n * @returns {void}\n */\n function scriptOnLoad () {\n resolve(window[vector]);\n destructor();\n }\n const destructor = () => {\n delete window[vector];\n script.removeEventListener('error', scriptOnError);\n script.removeEventListener('load', scriptOnLoad);\n script.remove();\n URL.revokeObjectURL(script.src);\n script.src = '';\n };\n addScriptAtts(script, atts);\n script.defer = 'defer';\n script.type = 'module';\n script.addEventListener('error', scriptOnError);\n script.addEventListener('load', scriptOnLoad);\n const absURL = toAbsoluteURL(url);\n const loader = `import * as m from '${absURL.replace(/'/g, \"\\\\'\")}'; window.${vector} = ${returnDefault ? 'm.default || ' : ''}m;`; // export Module\n const blob = new Blob([loader], {type: 'text/javascript'});\n script.src = URL.createObjectURL(blob);\n\n document.head.append(script);\n });\n}\n\nexport default importModule;\n","/* globals jQuery */\n/**\n * Manipulating coordinates.\n * @module coords\n * @license MIT\n */\n\nimport '../common/svgpathseg.js';\nimport {\n snapToGrid, assignAttributes, getBBox, getRefElem, findDefs\n} from '../common/utilities.js';\nimport {\n transformPoint, transformListToTransform, matrixMultiply, transformBox\n} from '../common/math.js';\nimport {getTransformList} from '../common/svgtransformlist.js';\n\nconst $ = jQuery;\n\n// this is how we map paths to our preferred relative segment types\nconst pathMap = [\n 0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',\n 'H', 'h', 'V', 'v', 'S', 's', 'T', 't'\n];\n\n/**\n * @interface module:coords.EditorContext\n */\n/**\n * @function module:coords.EditorContext#getGridSnapping\n * @returns {boolean}\n */\n/**\n * @function module:coords.EditorContext#getDrawing\n * @returns {module:draw.Drawing}\n*/\n/**\n * @function module:coords.EditorContext#getSVGRoot\n * @returns {SVGSVGElement}\n*/\n\nlet editorContext_ = null;\n\n/**\n* @function module:coords.init\n* @param {module:svgcanvas.SvgCanvas#event:pointsAdded} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n editorContext_ = editorContext;\n};\n\n/**\n * Applies coordinate changes to an element based on the given matrix.\n * @name module:coords.remapElement\n * @type {module:path.EditorContext#remapElement}\n*/\nexport const remapElement = function (selected, changes, m) {\n const remap = function (x, y) { return transformPoint(x, y, m); },\n scalew = function (w) { return m.a * w; },\n scaleh = function (h) { return m.d * h; },\n doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',\n finishUp = function () {\n if (doSnapping) {\n Object.entries(changes).forEach(([o, value]) => {\n changes[o] = snapToGrid(value);\n });\n }\n assignAttributes(selected, changes, 1000, true);\n },\n box = getBBox(selected);\n\n for (let i = 0; i < 2; i++) {\n const type = i === 0 ? 'fill' : 'stroke';\n const attrVal = selected.getAttribute(type);\n if (attrVal && attrVal.startsWith('url(')) {\n if (m.a < 0 || m.d < 0) {\n const grad = getRefElem(attrVal);\n const newgrad = grad.cloneNode(true);\n if (m.a < 0) {\n // flip x\n const x1 = newgrad.getAttribute('x1');\n const x2 = newgrad.getAttribute('x2');\n newgrad.setAttribute('x1', -(x1 - 1));\n newgrad.setAttribute('x2', -(x2 - 1));\n }\n\n if (m.d < 0) {\n // flip y\n const y1 = newgrad.getAttribute('y1');\n const y2 = newgrad.getAttribute('y2');\n newgrad.setAttribute('y1', -(y1 - 1));\n newgrad.setAttribute('y2', -(y2 - 1));\n }\n newgrad.id = editorContext_.getDrawing().getNextId();\n findDefs().append(newgrad);\n selected.setAttribute(type, 'url(#' + newgrad.id + ')');\n }\n\n // Not really working :(\n // if (selected.tagName === 'path') {\n // reorientGrads(selected, m);\n // }\n }\n }\n\n const elName = selected.tagName;\n if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') {\n // if it was a translate, then just update x,y\n if (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && (m.e !== 0 || m.f !== 0)) {\n // [T][M] = [M][T']\n // therefore [T'] = [M_inv][T][M]\n const existing = transformListToTransform(selected).matrix,\n tNew = matrixMultiply(existing.inverse(), m, existing);\n changes.x = Number.parseFloat(changes.x) + tNew.e;\n changes.y = Number.parseFloat(changes.y) + tNew.f;\n } else {\n // we just absorb all matrices into the element and don't do any remapping\n const chlist = getTransformList(selected);\n const mt = editorContext_.getSVGRoot().createSVGTransform();\n mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));\n chlist.clear();\n chlist.appendItem(mt);\n }\n }\n\n // now we have a set of changes and an applied reduced transform list\n // we apply the changes directly to the DOM\n switch (elName) {\n case 'foreignObject':\n case 'rect':\n case 'image': {\n // Allow images to be inverted (give them matrix when flipped)\n if (elName === 'image' && (m.a < 0 || m.d < 0)) {\n // Convert to matrix\n const chlist = getTransformList(selected);\n const mt = editorContext_.getSVGRoot().createSVGTransform();\n mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));\n chlist.clear();\n chlist.appendItem(mt);\n } else {\n const pt1 = remap(changes.x, changes.y);\n changes.width = scalew(changes.width);\n changes.height = scaleh(changes.height);\n changes.x = pt1.x + Math.min(0, changes.width);\n changes.y = pt1.y + Math.min(0, changes.height);\n changes.width = Math.abs(changes.width);\n changes.height = Math.abs(changes.height);\n }\n finishUp();\n break;\n } case 'ellipse': {\n const c = remap(changes.cx, changes.cy);\n changes.cx = c.x;\n changes.cy = c.y;\n changes.rx = scalew(changes.rx);\n changes.ry = scaleh(changes.ry);\n changes.rx = Math.abs(changes.rx);\n changes.ry = Math.abs(changes.ry);\n finishUp();\n break;\n } case 'circle': {\n const c = remap(changes.cx, changes.cy);\n changes.cx = c.x;\n changes.cy = c.y;\n // take the minimum of the new selected box's dimensions for the new circle radius\n const tbox = transformBox(box.x, box.y, box.width, box.height, m);\n const w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;\n changes.r = Math.min(w / 2, h / 2);\n\n if (changes.r) { changes.r = Math.abs(changes.r); }\n finishUp();\n break;\n } case 'line': {\n const pt1 = remap(changes.x1, changes.y1);\n const pt2 = remap(changes.x2, changes.y2);\n changes.x1 = pt1.x;\n changes.y1 = pt1.y;\n changes.x2 = pt2.x;\n changes.y2 = pt2.y;\n } // Fallthrough\n case 'text':\n case 'tspan':\n case 'use': {\n finishUp();\n break;\n } case 'g': {\n const gsvg = $(selected).data('gsvg');\n if (gsvg) {\n assignAttributes(gsvg, changes, 1000, true);\n }\n break;\n } case 'polyline':\n case 'polygon': {\n const len = changes.points.length;\n for (let i = 0; i < len; ++i) {\n const pt = changes.points[i];\n const {x, y} = remap(pt.x, pt.y);\n changes.points[i].x = x;\n changes.points[i].y = y;\n }\n\n // const len = changes.points.length;\n let pstr = '';\n for (let i = 0; i < len; ++i) {\n const pt = changes.points[i];\n pstr += pt.x + ',' + pt.y + ' ';\n }\n selected.setAttribute('points', pstr);\n break;\n } case 'path': {\n const segList = selected.pathSegList;\n let len = segList.numberOfItems;\n changes.d = [];\n for (let i = 0; i < len; ++i) {\n const seg = segList.getItem(i);\n changes.d[i] = {\n type: seg.pathSegType,\n x: seg.x,\n y: seg.y,\n x1: seg.x1,\n y1: seg.y1,\n x2: seg.x2,\n y2: seg.y2,\n r1: seg.r1,\n r2: seg.r2,\n angle: seg.angle,\n largeArcFlag: seg.largeArcFlag,\n sweepFlag: seg.sweepFlag\n };\n }\n\n len = changes.d.length;\n const firstseg = changes.d[0],\n currentpt = remap(firstseg.x, firstseg.y);\n changes.d[0].x = currentpt.x;\n changes.d[0].y = currentpt.y;\n for (let i = 1; i < len; ++i) {\n const seg = changes.d[i];\n const {type} = seg;\n // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2\n // if relative, we want to scalew, scaleh\n if (type % 2 === 0) { // absolute\n const thisx = (seg.x !== undefined) ? seg.x : currentpt.x, // for V commands\n thisy = (seg.y !== undefined) ? seg.y : currentpt.y; // for H commands\n const pt = remap(thisx, thisy);\n const pt1 = remap(seg.x1, seg.y1);\n const pt2 = remap(seg.x2, seg.y2);\n seg.x = pt.x;\n seg.y = pt.y;\n seg.x1 = pt1.x;\n seg.y1 = pt1.y;\n seg.x2 = pt2.x;\n seg.y2 = pt2.y;\n seg.r1 = scalew(seg.r1);\n seg.r2 = scaleh(seg.r2);\n } else { // relative\n seg.x = scalew(seg.x);\n seg.y = scaleh(seg.y);\n seg.x1 = scalew(seg.x1);\n seg.y1 = scaleh(seg.y1);\n seg.x2 = scalew(seg.x2);\n seg.y2 = scaleh(seg.y2);\n seg.r1 = scalew(seg.r1);\n seg.r2 = scaleh(seg.r2);\n }\n } // for each segment\n\n let dstr = '';\n len = changes.d.length;\n for (let i = 0; i < len; ++i) {\n const seg = changes.d[i];\n const {type} = seg;\n dstr += pathMap[type];\n switch (type) {\n case 13: // relative horizontal line (h)\n case 12: // absolute horizontal line (H)\n dstr += seg.x + ' ';\n break;\n case 15: // relative vertical line (v)\n case 14: // absolute vertical line (V)\n dstr += seg.y + ' ';\n break;\n case 3: // relative move (m)\n case 5: // relative line (l)\n case 19: // relative smooth quad (t)\n case 2: // absolute move (M)\n case 4: // absolute line (L)\n case 18: // absolute smooth quad (T)\n dstr += seg.x + ',' + seg.y + ' ';\n break;\n case 7: // relative cubic (c)\n case 6: // absolute cubic (C)\n dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +\n seg.x + ',' + seg.y + ' ';\n break;\n case 9: // relative quad (q)\n case 8: // absolute quad (Q)\n dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';\n break;\n case 11: // relative elliptical arc (a)\n case 10: // absolute elliptical arc (A)\n dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + Number(seg.largeArcFlag) +\n ' ' + Number(seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';\n break;\n case 17: // relative smooth cubic (s)\n case 16: // absolute smooth cubic (S)\n dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';\n break;\n }\n }\n\n selected.setAttribute('d', dstr);\n break;\n }\n }\n};\n","/* globals jQuery */\n/**\n * Recalculate.\n * @module recalculate\n * @license MIT\n */\n\nimport jQueryPluginSVG from '../common/jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport {NS} from '../common/namespaces.js';\nimport {convertToNum} from '../common/units.js';\nimport {isWebkit} from '../common/browser.js';\nimport {getTransformList} from '../common/svgtransformlist.js';\nimport {getRotationAngle, getHref, getBBox, getRefElem, isNullish} from '../common/utilities.js';\nimport {BatchCommand, ChangeElementCommand} from './history.js';\nimport {remapElement} from './coords.js';\nimport {\n isIdentity, matrixMultiply, transformPoint, transformListToTransform,\n hasMatrixTransform\n} from '../common/math.js';\n\nconst $ = jQueryPluginSVG(jQuery);\n\nlet context_;\n\n/**\n* @interface module:recalculate.EditorContext\n*/\n/**\n * @function module:recalculate.EditorContext#getSVGRoot\n * @returns {SVGSVGElement} The root DOM element\n */\n/**\n * @function module:recalculate.EditorContext#getStartTransform\n * @returns {string}\n*/\n/**\n * @function module:recalculate.EditorContext#setStartTransform\n * @param {string} transform\n * @returns {void}\n */\n\n/**\n* @function module:recalculate.init\n* @param {module:recalculate.EditorContext} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n context_ = editorContext;\n};\n\n/**\n* Updates a `<clipPath>`s values based on the given translation of an element.\n* @function module:recalculate.updateClipPath\n* @param {string} attr - The clip-path attribute value with the clipPath's ID\n* @param {Float} tx - The translation's x value\n* @param {Float} ty - The translation's y value\n* @returns {void}\n*/\nexport const updateClipPath = function (attr, tx, ty) {\n const path = getRefElem(attr).firstChild;\n const cpXform = getTransformList(path);\n const newxlate = context_.getSVGRoot().createSVGTransform();\n newxlate.setTranslate(tx, ty);\n\n cpXform.appendItem(newxlate);\n\n // Update clipPath's dimensions\n recalculateDimensions(path);\n};\n\n/**\n* Decides the course of action based on the element's transform list.\n* @function module:recalculate.recalculateDimensions\n* @param {Element} selected - The DOM element to recalculate\n* @returns {Command} Undo command object with the resulting change\n*/\nexport const recalculateDimensions = function (selected) {\n if (isNullish(selected)) { return null; }\n\n // Firefox Issue - 1081\n if (selected.nodeName === 'svg' && navigator.userAgent.includes('Firefox/20')) {\n return null;\n }\n\n const svgroot = context_.getSVGRoot();\n const tlist = getTransformList(selected);\n\n // remove any unnecessary transforms\n if (tlist && tlist.numberOfItems > 0) {\n let k = tlist.numberOfItems;\n const noi = k;\n while (k--) {\n const xform = tlist.getItem(k);\n if (xform.type === 0) {\n tlist.removeItem(k);\n // remove identity matrices\n } else if (xform.type === 1) {\n if (isIdentity(xform.matrix)) {\n if (noi === 1) {\n // Overcome Chrome bug (though only when noi is 1) with\n // `removeItem` preventing `removeAttribute` from\n // subsequently working\n // See https://bugs.chromium.org/p/chromium/issues/detail?id=843901\n selected.removeAttribute('transform');\n return null;\n }\n tlist.removeItem(k);\n }\n // remove zero-degree rotations\n } else if (xform.type === 4) {\n if (xform.angle === 0) {\n tlist.removeItem(k);\n }\n }\n }\n // End here if all it has is a rotation\n if (tlist.numberOfItems === 1 &&\n getRotationAngle(selected)) { return null; }\n }\n\n // if this element had no transforms, we are done\n if (!tlist || tlist.numberOfItems === 0) {\n // Chrome apparently had a bug that requires clearing the attribute first.\n selected.setAttribute('transform', '');\n // However, this still next line currently doesn't work at all in Chrome\n selected.removeAttribute('transform');\n // selected.transform.baseVal.clear(); // Didn't help for Chrome bug\n return null;\n }\n\n // TODO: Make this work for more than 2\n if (tlist) {\n let mxs = [];\n let k = tlist.numberOfItems;\n while (k--) {\n const xform = tlist.getItem(k);\n if (xform.type === 1) {\n mxs.push([xform.matrix, k]);\n } else if (mxs.length) {\n mxs = [];\n }\n }\n if (mxs.length === 2) {\n const mNew = svgroot.createSVGTransformFromMatrix(matrixMultiply(mxs[1][0], mxs[0][0]));\n tlist.removeItem(mxs[0][1]);\n tlist.removeItem(mxs[1][1]);\n tlist.insertItemBefore(mNew, mxs[1][1]);\n }\n\n // combine matrix + translate\n k = tlist.numberOfItems;\n if (k >= 2 && tlist.getItem(k - 2).type === 1 && tlist.getItem(k - 1).type === 2) {\n const mt = svgroot.createSVGTransform();\n\n const m = matrixMultiply(\n tlist.getItem(k - 2).matrix,\n tlist.getItem(k - 1).matrix\n );\n mt.setMatrix(m);\n tlist.removeItem(k - 2);\n tlist.removeItem(k - 2);\n tlist.appendItem(mt);\n }\n }\n\n // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned).\n switch (selected.tagName) {\n // Ignore these elements, as they can absorb the [M]\n case 'line':\n case 'polyline':\n case 'polygon':\n case 'path':\n break;\n default:\n if ((tlist.numberOfItems === 1 && tlist.getItem(0).type === 1) ||\n (tlist.numberOfItems === 2 && tlist.getItem(0).type === 1 && tlist.getItem(0).type === 4)) {\n return null;\n }\n }\n\n // Grouped SVG element\n const gsvg = $(selected).data('gsvg');\n\n // we know we have some transforms, so set up return variable\n const batchCmd = new BatchCommand('Transform');\n\n // store initial values that will be affected by reducing the transform list\n let changes = {};\n let initial = null;\n let attrs = [];\n switch (selected.tagName) {\n case 'line':\n attrs = ['x1', 'y1', 'x2', 'y2'];\n break;\n case 'circle':\n attrs = ['cx', 'cy', 'r'];\n break;\n case 'ellipse':\n attrs = ['cx', 'cy', 'rx', 'ry'];\n break;\n case 'foreignObject':\n case 'rect':\n case 'image':\n attrs = ['width', 'height', 'x', 'y'];\n break;\n case 'use':\n case 'text':\n case 'tspan':\n attrs = ['x', 'y'];\n break;\n case 'polygon':\n case 'polyline': {\n initial = {};\n initial.points = selected.getAttribute('points');\n const list = selected.points;\n const len = list.numberOfItems;\n changes.points = new Array(len);\n for (let i = 0; i < len; ++i) {\n const pt = list.getItem(i);\n changes.points[i] = {x: pt.x, y: pt.y};\n }\n break;\n } case 'path':\n initial = {};\n initial.d = selected.getAttribute('d');\n changes.d = selected.getAttribute('d');\n break;\n } // switch on element type to get initial values\n\n if (attrs.length) {\n changes = $(selected).attr(attrs);\n $.each(changes, function (attr, val) {\n changes[attr] = convertToNum(attr, val);\n });\n } else if (gsvg) {\n // GSVG exception\n changes = {\n x: $(gsvg).attr('x') || 0,\n y: $(gsvg).attr('y') || 0\n };\n }\n\n // if we haven't created an initial array in polygon/polyline/path, then\n // make a copy of initial values and include the transform\n if (isNullish(initial)) {\n initial = $.extend(true, {}, changes);\n $.each(initial, function (attr, val) {\n initial[attr] = convertToNum(attr, val);\n });\n }\n // save the start transform value too\n initial.transform = context_.getStartTransform() || '';\n\n let oldcenter, newcenter;\n\n // if it's a regular group, we have special processing to flatten transforms\n if ((selected.tagName === 'g' && !gsvg) || selected.tagName === 'a') {\n const box = getBBox(selected);\n\n oldcenter = {x: box.x + box.width / 2, y: box.y + box.height / 2};\n newcenter = transformPoint(\n box.x + box.width / 2,\n box.y + box.height / 2,\n transformListToTransform(tlist).matrix\n );\n // let m = svgroot.createSVGMatrix();\n\n // temporarily strip off the rotate and save the old center\n const gangle = getRotationAngle(selected);\n if (gangle) {\n const a = gangle * Math.PI / 180;\n let s;\n if (Math.abs(a) > (1.0e-10)) {\n s = Math.sin(a) / (1 - Math.cos(a));\n } else {\n // TODO: This blows up if the angle is exactly 0!\n s = 2 / a;\n }\n for (let i = 0; i < tlist.numberOfItems; ++i) {\n const xform = tlist.getItem(i);\n if (xform.type === 4) {\n // extract old center through mystical arts\n const rm = xform.matrix;\n oldcenter.y = (s * rm.e + rm.f) / 2;\n oldcenter.x = (rm.e - s * rm.f) / 2;\n tlist.removeItem(i);\n break;\n }\n }\n }\n const N = tlist.numberOfItems;\n let tx = 0, ty = 0, operation = 0;\n\n let firstM;\n if (N) {\n firstM = tlist.getItem(0).matrix;\n }\n\n let oldStartTransform;\n // first, if it was a scale then the second-last transform will be it\n if (N >= 3 && tlist.getItem(N - 2).type === 3 &&\n tlist.getItem(N - 3).type === 2 && tlist.getItem(N - 1).type === 2) {\n operation = 3; // scale\n\n // if the children are unrotated, pass the scale down directly\n // otherwise pass the equivalent matrix() down directly\n const tm = tlist.getItem(N - 3).matrix,\n sm = tlist.getItem(N - 2).matrix,\n tmn = tlist.getItem(N - 1).matrix;\n\n const children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n tx = 0;\n ty = 0;\n if (child.nodeType === 1) {\n const childTlist = getTransformList(child);\n\n // some children might not have a transform (<metadata>, <defs>, etc)\n if (!childTlist) { continue; }\n\n const m = transformListToTransform(childTlist).matrix;\n\n // Convert a matrix to a scale if applicable\n // if (hasMatrixTransform(childTlist) && childTlist.numberOfItems == 1) {\n // if (m.b==0 && m.c==0 && m.e==0 && m.f==0) {\n // childTlist.removeItem(0);\n // const translateOrigin = svgroot.createSVGTransform(),\n // scale = svgroot.createSVGTransform(),\n // translateBack = svgroot.createSVGTransform();\n // translateOrigin.setTranslate(0, 0);\n // scale.setScale(m.a, m.d);\n // translateBack.setTranslate(0, 0);\n // childTlist.appendItem(translateBack);\n // childTlist.appendItem(scale);\n // childTlist.appendItem(translateOrigin);\n // }\n // }\n\n const angle = getRotationAngle(child);\n oldStartTransform = context_.getStartTransform();\n // const childxforms = [];\n context_.setStartTransform(child.getAttribute('transform'));\n if (angle || hasMatrixTransform(childTlist)) {\n const e2t = svgroot.createSVGTransform();\n e2t.setMatrix(matrixMultiply(tm, sm, tmn, m));\n childTlist.clear();\n childTlist.appendItem(e2t);\n // childxforms.push(e2t);\n // if not rotated or skewed, push the [T][S][-T] down to the child\n } else {\n // update the transform list with translate,scale,translate\n\n // slide the [T][S][-T] from the front to the back\n // [T][S][-T][M] = [M][T2][S2][-T2]\n\n // (only bringing [-T] to the right of [M])\n // [T][S][-T][M] = [T][S][M][-T2]\n // [-T2] = [M_inv][-T][M]\n const t2n = matrixMultiply(m.inverse(), tmn, m);\n // [T2] is always negative translation of [-T2]\n const t2 = svgroot.createSVGMatrix();\n t2.e = -t2n.e;\n t2.f = -t2n.f;\n\n // [T][S][-T][M] = [M][T2][S2][-T2]\n // [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv]\n const s2 = matrixMultiply(t2.inverse(), m.inverse(), tm, sm, tmn, m, t2n.inverse());\n\n const translateOrigin = svgroot.createSVGTransform(),\n scale = svgroot.createSVGTransform(),\n translateBack = svgroot.createSVGTransform();\n translateOrigin.setTranslate(t2n.e, t2n.f);\n scale.setScale(s2.a, s2.d);\n translateBack.setTranslate(t2.e, t2.f);\n childTlist.appendItem(translateBack);\n childTlist.appendItem(scale);\n childTlist.appendItem(translateOrigin);\n // childxforms.push(translateBack);\n // childxforms.push(scale);\n // childxforms.push(translateOrigin);\n // logMatrix(translateBack.matrix);\n // logMatrix(scale.matrix);\n } // not rotated\n batchCmd.addSubCommand(recalculateDimensions(child));\n // TODO: If any <use> have this group as a parent and are\n // referencing this child, then we need to impose a reverse\n // scale on it so that when it won't get double-translated\n // const uses = selected.getElementsByTagNameNS(NS.SVG, 'use');\n // const href = '#' + child.id;\n // let u = uses.length;\n // while (u--) {\n // const useElem = uses.item(u);\n // if (href == getHref(useElem)) {\n // const usexlate = svgroot.createSVGTransform();\n // usexlate.setTranslate(-tx,-ty);\n // getTransformList(useElem).insertItemBefore(usexlate,0);\n // batchCmd.addSubCommand( recalculateDimensions(useElem) );\n // }\n // }\n context_.setStartTransform(oldStartTransform);\n } // element\n } // for each child\n // Remove these transforms from group\n tlist.removeItem(N - 1);\n tlist.removeItem(N - 2);\n tlist.removeItem(N - 3);\n } else if (N >= 3 && tlist.getItem(N - 1).type === 1) {\n operation = 3; // scale\n const m = transformListToTransform(tlist).matrix;\n const e2t = svgroot.createSVGTransform();\n e2t.setMatrix(m);\n tlist.clear();\n tlist.appendItem(e2t);\n // next, check if the first transform was a translate\n // if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ]\n // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ]\n } else if ((N === 1 || (N > 1 && tlist.getItem(1).type !== 3)) &&\n tlist.getItem(0).type === 2) {\n operation = 2; // translate\n const T_M = transformListToTransform(tlist).matrix;\n tlist.removeItem(0);\n const mInv = transformListToTransform(tlist).matrix.inverse();\n const M2 = matrixMultiply(mInv, T_M);\n\n tx = M2.e;\n ty = M2.f;\n\n if (tx !== 0 || ty !== 0) {\n // we pass the translates down to the individual children\n const children = selected.childNodes;\n let c = children.length;\n\n const clipPathsDone = [];\n while (c--) {\n const child = children.item(c);\n if (child.nodeType === 1) {\n // Check if child has clip-path\n if (child.getAttribute('clip-path')) {\n // tx, ty\n const attr = child.getAttribute('clip-path');\n if (!clipPathsDone.includes(attr)) {\n updateClipPath(attr, tx, ty);\n clipPathsDone.push(attr);\n }\n }\n\n oldStartTransform = context_.getStartTransform();\n context_.setStartTransform(child.getAttribute('transform'));\n\n const childTlist = getTransformList(child);\n // some children might not have a transform (<metadata>, <defs>, etc)\n if (childTlist) {\n const newxlate = svgroot.createSVGTransform();\n newxlate.setTranslate(tx, ty);\n if (childTlist.numberOfItems) {\n childTlist.insertItemBefore(newxlate, 0);\n } else {\n childTlist.appendItem(newxlate);\n }\n batchCmd.addSubCommand(recalculateDimensions(child));\n // If any <use> have this group as a parent and are\n // referencing this child, then impose a reverse translate on it\n // so that when it won't get double-translated\n const uses = selected.getElementsByTagNameNS(NS.SVG, 'use');\n const href = '#' + child.id;\n let u = uses.length;\n while (u--) {\n const useElem = uses.item(u);\n if (href === getHref(useElem)) {\n const usexlate = svgroot.createSVGTransform();\n usexlate.setTranslate(-tx, -ty);\n getTransformList(useElem).insertItemBefore(usexlate, 0);\n batchCmd.addSubCommand(recalculateDimensions(useElem));\n }\n }\n context_.setStartTransform(oldStartTransform);\n }\n }\n }\n context_.setStartTransform(oldStartTransform);\n }\n // else, a matrix imposition from a parent group\n // keep pushing it down to the children\n } else if (N === 1 && tlist.getItem(0).type === 1 && !gangle) {\n operation = 1;\n const m = tlist.getItem(0).matrix,\n children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n if (child.nodeType === 1) {\n oldStartTransform = context_.getStartTransform();\n context_.setStartTransform(child.getAttribute('transform'));\n const childTlist = getTransformList(child);\n\n if (!childTlist) { continue; }\n\n const em = matrixMultiply(m, transformListToTransform(childTlist).matrix);\n const e2m = svgroot.createSVGTransform();\n e2m.setMatrix(em);\n childTlist.clear();\n childTlist.appendItem(e2m, 0);\n\n batchCmd.addSubCommand(recalculateDimensions(child));\n context_.setStartTransform(oldStartTransform);\n\n // Convert stroke\n // TODO: Find out if this should actually happen somewhere else\n const sw = child.getAttribute('stroke-width');\n if (child.getAttribute('stroke') !== 'none' && !isNaN(sw)) {\n const avg = (Math.abs(em.a) + Math.abs(em.d)) / 2;\n child.setAttribute('stroke-width', sw * avg);\n }\n }\n }\n tlist.clear();\n // else it was just a rotate\n } else {\n if (gangle) {\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(gangle, newcenter.x, newcenter.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n if (tlist.numberOfItems === 0) {\n selected.removeAttribute('transform');\n }\n return null;\n }\n\n // if it was a translate, put back the rotate at the new center\n if (operation === 2) {\n if (gangle) {\n newcenter = {\n x: oldcenter.x + firstM.e,\n y: oldcenter.y + firstM.f\n };\n\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(gangle, newcenter.x, newcenter.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n // if it was a resize\n } else if (operation === 3) {\n const m = transformListToTransform(tlist).matrix;\n const roldt = svgroot.createSVGTransform();\n roldt.setRotate(gangle, oldcenter.x, oldcenter.y);\n const rold = roldt.matrix;\n const rnew = svgroot.createSVGTransform();\n rnew.setRotate(gangle, newcenter.x, newcenter.y);\n const rnewInv = rnew.matrix.inverse(),\n mInv = m.inverse(),\n extrat = matrixMultiply(mInv, rnewInv, rold, m);\n\n tx = extrat.e;\n ty = extrat.f;\n\n if (tx !== 0 || ty !== 0) {\n // now push this transform down to the children\n // we pass the translates down to the individual children\n const children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n if (child.nodeType === 1) {\n oldStartTransform = context_.getStartTransform();\n context_.setStartTransform(child.getAttribute('transform'));\n const childTlist = getTransformList(child);\n const newxlate = svgroot.createSVGTransform();\n newxlate.setTranslate(tx, ty);\n if (childTlist.numberOfItems) {\n childTlist.insertItemBefore(newxlate, 0);\n } else {\n childTlist.appendItem(newxlate);\n }\n\n batchCmd.addSubCommand(recalculateDimensions(child));\n context_.setStartTransform(oldStartTransform);\n }\n }\n }\n\n if (gangle) {\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(rnew, 0);\n } else {\n tlist.appendItem(rnew);\n }\n }\n }\n // else, it's a non-group\n } else {\n // TODO: box might be null for some elements (<metadata> etc), need to handle this\n const box = getBBox(selected);\n\n // Paths (and possbly other shapes) will have no BBox while still in <defs>,\n // but we still may need to recalculate them (see issue 595).\n // TODO: Figure out how to get BBox from these elements in case they\n // have a rotation transform\n\n if (!box && selected.tagName !== 'path') return null;\n\n let m; // = svgroot.createSVGMatrix();\n // temporarily strip off the rotate and save the old center\n const angle = getRotationAngle(selected);\n if (angle) {\n oldcenter = {x: box.x + box.width / 2, y: box.y + box.height / 2};\n newcenter = transformPoint(\n box.x + box.width / 2,\n box.y + box.height / 2,\n transformListToTransform(tlist).matrix\n );\n\n const a = angle * Math.PI / 180;\n const s = (Math.abs(a) > (1.0e-10))\n ? Math.sin(a) / (1 - Math.cos(a))\n // TODO: This blows up if the angle is exactly 0!\n : 2 / a;\n\n for (let i = 0; i < tlist.numberOfItems; ++i) {\n const xform = tlist.getItem(i);\n if (xform.type === 4) {\n // extract old center through mystical arts\n const rm = xform.matrix;\n oldcenter.y = (s * rm.e + rm.f) / 2;\n oldcenter.x = (rm.e - s * rm.f) / 2;\n tlist.removeItem(i);\n break;\n }\n }\n }\n\n // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition\n let operation = 0;\n const N = tlist.numberOfItems;\n\n // Check if it has a gradient with userSpaceOnUse, in which case\n // adjust it by recalculating the matrix transform.\n // TODO: Make this work in Webkit using transformlist.SVGTransformList\n if (!isWebkit()) {\n const fill = selected.getAttribute('fill');\n if (fill && fill.startsWith('url(')) {\n const paint = getRefElem(fill);\n let type = 'pattern';\n if (paint.tagName !== type) type = 'gradient';\n const attrVal = paint.getAttribute(type + 'Units');\n if (attrVal === 'userSpaceOnUse') {\n // Update the userSpaceOnUse element\n m = transformListToTransform(tlist).matrix;\n const gtlist = getTransformList(paint);\n const gmatrix = transformListToTransform(gtlist).matrix;\n m = matrixMultiply(m, gmatrix);\n const mStr = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';\n paint.setAttribute(type + 'Transform', mStr);\n }\n }\n }\n\n // first, if it was a scale of a non-skewed element, then the second-last\n // transform will be the [S]\n // if we had [M][T][S][T] we want to extract the matrix equivalent of\n // [T][S][T] and push it down to the element\n if (N >= 3 && tlist.getItem(N - 2).type === 3 &&\n tlist.getItem(N - 3).type === 2 && tlist.getItem(N - 1).type === 2) {\n // Removed this so a <use> with a given [T][S][T] would convert to a matrix.\n // Is that bad?\n // && selected.nodeName != 'use'\n operation = 3; // scale\n m = transformListToTransform(tlist, N - 3, N - 1).matrix;\n tlist.removeItem(N - 1);\n tlist.removeItem(N - 2);\n tlist.removeItem(N - 3);\n // if we had [T][S][-T][M], then this was a skewed element being resized\n // Thus, we simply combine it all into one matrix\n } else if (N === 4 && tlist.getItem(N - 1).type === 1) {\n operation = 3; // scale\n m = transformListToTransform(tlist).matrix;\n const e2t = svgroot.createSVGTransform();\n e2t.setMatrix(m);\n tlist.clear();\n tlist.appendItem(e2t);\n // reset the matrix so that the element is not re-mapped\n m = svgroot.createSVGMatrix();\n // if we had [R][T][S][-T][M], then this was a rotated matrix-element\n // if we had [T1][M] we want to transform this into [M][T2]\n // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2]\n // down to the element\n } else if ((N === 1 || (N > 1 && tlist.getItem(1).type !== 3)) &&\n tlist.getItem(0).type === 2) {\n operation = 2; // translate\n const oldxlate = tlist.getItem(0).matrix,\n meq = transformListToTransform(tlist, 1).matrix,\n meqInv = meq.inverse();\n m = matrixMultiply(meqInv, oldxlate, meq);\n tlist.removeItem(0);\n // else if this child now has a matrix imposition (from a parent group)\n // we might be able to simplify\n } else if (N === 1 && tlist.getItem(0).type === 1 && !angle) {\n // Remap all point-based elements\n m = transformListToTransform(tlist).matrix;\n switch (selected.tagName) {\n case 'line':\n changes = $(selected).attr(['x1', 'y1', 'x2', 'y2']);\n // Fallthrough\n case 'polyline':\n case 'polygon':\n changes.points = selected.getAttribute('points');\n if (changes.points) {\n const list = selected.points;\n const len = list.numberOfItems;\n changes.points = new Array(len);\n for (let i = 0; i < len; ++i) {\n const pt = list.getItem(i);\n changes.points[i] = {x: pt.x, y: pt.y};\n }\n }\n // Fallthrough\n case 'path':\n changes.d = selected.getAttribute('d');\n operation = 1;\n tlist.clear();\n break;\n default:\n break;\n }\n // if it was a rotation, put the rotate back and return without a command\n // (this function has zero work to do for a rotate())\n } else {\n // operation = 4; // rotation\n if (angle) {\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(angle, newcenter.x, newcenter.y);\n\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n if (tlist.numberOfItems === 0) {\n selected.removeAttribute('transform');\n }\n return null;\n }\n\n // if it was a translate or resize, we need to remap the element and absorb the xform\n if (operation === 1 || operation === 2 || operation === 3) {\n remapElement(selected, changes, m);\n } // if we are remapping\n\n // if it was a translate, put back the rotate at the new center\n if (operation === 2) {\n if (angle) {\n if (!hasMatrixTransform(tlist)) {\n newcenter = {\n x: oldcenter.x + m.e,\n y: oldcenter.y + m.f\n };\n }\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(angle, newcenter.x, newcenter.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n // We have special processing for tspans: Tspans are not transformable\n // but they can have x,y coordinates (sigh). Thus, if this was a translate,\n // on a text element, also translate any tspan children.\n if (selected.tagName === 'text') {\n const children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n if (child.tagName === 'tspan') {\n const tspanChanges = {\n x: $(child).attr('x') || 0,\n y: $(child).attr('y') || 0\n };\n remapElement(child, tspanChanges, m);\n }\n }\n }\n // [Rold][M][T][S][-T] became [Rold][M]\n // we want it to be [Rnew][M][Tr] where Tr is the\n // translation required to re-center it\n // Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M]\n } else if (operation === 3 && angle) {\n const {matrix} = transformListToTransform(tlist);\n const roldt = svgroot.createSVGTransform();\n roldt.setRotate(angle, oldcenter.x, oldcenter.y);\n const rold = roldt.matrix;\n const rnew = svgroot.createSVGTransform();\n rnew.setRotate(angle, newcenter.x, newcenter.y);\n const rnewInv = rnew.matrix.inverse();\n const mInv = matrix.inverse();\n const extrat = matrixMultiply(mInv, rnewInv, rold, matrix);\n\n remapElement(selected, changes, extrat);\n if (angle) {\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(rnew, 0);\n } else {\n tlist.appendItem(rnew);\n }\n }\n }\n } // a non-group\n\n // if the transform list has been emptied, remove it\n if (tlist.numberOfItems === 0) {\n selected.removeAttribute('transform');\n }\n\n batchCmd.addSubCommand(new ChangeElementCommand(selected, initial));\n\n return batchCmd;\n};\n","/* globals jQuery */\n/**\n * DOM element selection box tools.\n * @module select\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {isTouch, isWebkit} from '../common/browser.js'; // , isOpera\nimport {getRotationAngle, getBBox, getStrokedBBox, isNullish} from '../common/utilities.js';\nimport {transformListToTransform, transformBox, transformPoint} from '../common/math.js';\nimport {getTransformList} from '../common/svgtransformlist.js';\n\nconst $ = jQuery;\n\nlet svgFactory_;\nlet config_;\nlet selectorManager_; // A Singleton\nconst gripRadius = isTouch() ? 10 : 4;\n\n/**\n* Private class for DOM element selection boxes.\n*/\nexport class Selector {\n /**\n * @param {Integer} id - Internally identify the selector\n * @param {Element} elem - DOM element associated with this selector\n * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for initialization (prevents duplicate `getBBox` call).\n */\n constructor (id, elem, bbox) {\n // this is the selector's unique number\n this.id = id;\n\n // this holds a reference to the element for which this selector is being used\n this.selectedElement = elem;\n\n // this is a flag used internally to track whether the selector is being used or not\n this.locked = true;\n\n // this holds a reference to the <g> element that holds all visual elements of the selector\n this.selectorGroup = svgFactory_.createSVGElement({\n element: 'g',\n attr: {id: ('selectorGroup' + this.id)}\n });\n\n // this holds a reference to the path rect\n this.selectorRect = this.selectorGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'path',\n attr: {\n id: ('selectedBox' + this.id),\n fill: 'none',\n stroke: '#22C',\n 'stroke-width': '1',\n 'stroke-dasharray': '5,5',\n // need to specify this so that the rect is not selectable\n style: 'pointer-events:none'\n }\n })\n );\n\n // this holds a reference to the grip coordinates for this selector\n this.gripCoords = {\n nw: null,\n n: null,\n ne: null,\n e: null,\n se: null,\n s: null,\n sw: null,\n w: null\n };\n\n this.reset(this.selectedElement, bbox);\n }\n\n /**\n * Used to reset the id and element that the selector is attached to.\n * @param {Element} e - DOM element associated with this selector\n * @param {module:utilities.BBoxObject} bbox - Optional bbox to use for reset (prevents duplicate getBBox call).\n * @returns {void}\n */\n reset (e, bbox) {\n this.locked = true;\n this.selectedElement = e;\n this.resize(bbox);\n this.selectorGroup.setAttribute('display', 'inline');\n }\n\n /**\n * Show the resize grips of this selector.\n * @param {boolean} show - Indicates whether grips should be shown or not\n * @returns {void}\n */\n showGrips (show) {\n const bShow = show ? 'inline' : 'none';\n selectorManager_.selectorGripsGroup.setAttribute('display', bShow);\n const elem = this.selectedElement;\n this.hasGrips = show;\n if (elem && show) {\n this.selectorGroup.append(selectorManager_.selectorGripsGroup);\n Selector.updateGripCursors(getRotationAngle(elem));\n }\n }\n\n /**\n * Updates the selector to match the element's size.\n * @param {module:utilities.BBoxObject} [bbox] - BBox to use for resize (prevents duplicate getBBox call).\n * @returns {void}\n */\n resize (bbox) {\n const selectedBox = this.selectorRect,\n mgr = selectorManager_,\n selectedGrips = mgr.selectorGrips,\n selected = this.selectedElement,\n sw = selected.getAttribute('stroke-width'),\n currentZoom = svgFactory_.getCurrentZoom();\n let offset = 1 / currentZoom;\n if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) {\n offset += (sw / 2);\n }\n\n const {tagName} = selected;\n if (tagName === 'text') {\n offset += 2 / currentZoom;\n }\n\n // loop and transform our bounding box until we reach our first rotation\n const tlist = getTransformList(selected);\n const m = transformListToTransform(tlist).matrix;\n\n // This should probably be handled somewhere else, but for now\n // it keeps the selection box correctly positioned when zoomed\n m.e *= currentZoom;\n m.f *= currentZoom;\n\n if (!bbox) {\n bbox = getBBox(selected);\n }\n // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this?\n // TODO: getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated?\n if (tagName === 'g' && !$.data(selected, 'gsvg')) {\n // The bbox for a group does not include stroke vals, so we\n // get the bbox based on its children.\n const strokedBbox = getStrokedBBox([selected.childNodes]);\n if (strokedBbox) {\n bbox = strokedBbox;\n }\n }\n\n // apply the transforms\n const l = bbox.x, t = bbox.y, w = bbox.width, h = bbox.height;\n // bbox = {x: l, y: t, width: w, height: h}; // Not in use\n\n // we need to handle temporary transforms too\n // if skewed, get its transformed box, then find its axis-aligned bbox\n\n // *\n offset *= currentZoom;\n\n const nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m),\n {aabox} = nbox;\n let nbax = aabox.x - offset,\n nbay = aabox.y - offset,\n nbaw = aabox.width + (offset * 2),\n nbah = aabox.height + (offset * 2);\n\n // now if the shape is rotated, un-rotate it\n const cx = nbax + nbaw / 2,\n cy = nbay + nbah / 2;\n\n const angle = getRotationAngle(selected);\n if (angle) {\n const rot = svgFactory_.svgRoot().createSVGTransform();\n rot.setRotate(-angle, cx, cy);\n const rotm = rot.matrix;\n nbox.tl = transformPoint(nbox.tl.x, nbox.tl.y, rotm);\n nbox.tr = transformPoint(nbox.tr.x, nbox.tr.y, rotm);\n nbox.bl = transformPoint(nbox.bl.x, nbox.bl.y, rotm);\n nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm);\n\n // calculate the axis-aligned bbox\n const {tl} = nbox;\n let minx = tl.x,\n miny = tl.y,\n maxx = tl.x,\n maxy = tl.y;\n\n const {min, max} = Math;\n\n minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset;\n miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset;\n maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset;\n maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset;\n\n nbax = minx;\n nbay = miny;\n nbaw = (maxx - minx);\n nbah = (maxy - miny);\n }\n\n const dstr = 'M' + nbax + ',' + nbay +\n ' L' + (nbax + nbaw) + ',' + nbay +\n ' ' + (nbax + nbaw) + ',' + (nbay + nbah) +\n ' ' + nbax + ',' + (nbay + nbah) + 'z';\n selectedBox.setAttribute('d', dstr);\n\n const xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : '';\n this.selectorGroup.setAttribute('transform', xform);\n\n // TODO(codedread): Is this needed?\n // if (selected === selectedElements[0]) {\n this.gripCoords = {\n nw: [nbax, nbay],\n ne: [nbax + nbaw, nbay],\n sw: [nbax, nbay + nbah],\n se: [nbax + nbaw, nbay + nbah],\n n: [nbax + (nbaw) / 2, nbay],\n w: [nbax, nbay + (nbah) / 2],\n e: [nbax + nbaw, nbay + (nbah) / 2],\n s: [nbax + (nbaw) / 2, nbay + nbah]\n };\n Object.entries(this.gripCoords).forEach(([dir, coords]) => {\n selectedGrips[dir].setAttribute('cx', coords[0]);\n selectedGrips[dir].setAttribute('cy', coords[1]);\n });\n\n // we want to go 20 pixels in the negative transformed y direction, ignoring scale\n mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);\n mgr.rotateGripConnector.setAttribute('y1', nbay);\n mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2);\n mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5));\n\n mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2);\n mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5));\n // }\n }\n\n // STATIC methods\n /**\n * Updates cursors for corner grips on rotation so arrows point the right way.\n * @param {Float} angle - Current rotation angle in degrees\n * @returns {void}\n */\n static updateGripCursors (angle) {\n const dirArr = Object.keys(selectorManager_.selectorGrips);\n let steps = Math.round(angle / 45);\n if (steps < 0) { steps += 8; }\n while (steps > 0) {\n dirArr.push(dirArr.shift());\n steps--;\n }\n Object.values(selectorManager_.selectorGrips).forEach((gripElement, i) => {\n gripElement.setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));\n });\n }\n}\n\n/**\n* Manage all selector objects (selection boxes).\n*/\nexport class SelectorManager {\n /**\n * Sets up properties and calls `initGroup`.\n */\n constructor () {\n // this will hold the <g> element that contains all selector rects/grips\n this.selectorParentGroup = null;\n\n // this is a special rect that is used for multi-select\n this.rubberBandBox = null;\n\n // this will hold objects of type Selector (see above)\n this.selectors = [];\n\n // this holds a map of SVG elements to their Selector object\n this.selectorMap = {};\n\n // this holds a reference to the grip elements\n this.selectorGrips = {\n nw: null,\n n: null,\n ne: null,\n e: null,\n se: null,\n s: null,\n sw: null,\n w: null\n };\n\n this.selectorGripsGroup = null;\n this.rotateGripConnector = null;\n this.rotateGrip = null;\n\n this.initGroup();\n }\n\n /**\n * Resets the parent selector group element.\n * @returns {void}\n */\n initGroup () {\n // remove old selector parent group if it existed\n if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {\n this.selectorParentGroup.remove();\n }\n\n // create parent selector group and add it to svgroot\n this.selectorParentGroup = svgFactory_.createSVGElement({\n element: 'g',\n attr: {id: 'selectorParentGroup'}\n });\n this.selectorGripsGroup = svgFactory_.createSVGElement({\n element: 'g',\n attr: {display: 'none'}\n });\n this.selectorParentGroup.append(this.selectorGripsGroup);\n svgFactory_.svgRoot().append(this.selectorParentGroup);\n\n this.selectorMap = {};\n this.selectors = [];\n this.rubberBandBox = null;\n\n // add the corner grips\n Object.keys(this.selectorGrips).forEach((dir) => {\n const grip = svgFactory_.createSVGElement({\n element: 'circle',\n attr: {\n id: ('selectorGrip_resize_' + dir),\n fill: '#22C',\n r: gripRadius,\n style: ('cursor:' + dir + '-resize'),\n // This expands the mouse-able area of the grips making them\n // easier to grab with the mouse.\n // This works in Opera and WebKit, but does not work in Firefox\n // see https://bugzilla.mozilla.org/show_bug.cgi?id=500174\n 'stroke-width': 2,\n 'pointer-events': 'all'\n }\n });\n\n $.data(grip, 'dir', dir);\n $.data(grip, 'type', 'resize');\n this.selectorGrips[dir] = this.selectorGripsGroup.appendChild(grip);\n });\n\n // add rotator elems\n this.rotateGripConnector = this.selectorGripsGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'line',\n attr: {\n id: ('selectorGrip_rotateconnector'),\n stroke: '#22C',\n 'stroke-width': '1'\n }\n })\n );\n\n this.rotateGrip = this.selectorGripsGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'circle',\n attr: {\n id: 'selectorGrip_rotate',\n fill: 'lime',\n r: gripRadius,\n stroke: '#22C',\n 'stroke-width': 2,\n style: 'cursor:url(' + config_.imgPath + 'rotate.png) 12 12, auto;'\n }\n })\n );\n $.data(this.rotateGrip, 'type', 'rotate');\n\n if ($('#canvasBackground').length) { return; }\n\n const [width, height] = config_.dimensions;\n const canvasbg = svgFactory_.createSVGElement({\n element: 'svg',\n attr: {\n id: 'canvasBackground',\n width,\n height,\n x: 0,\n y: 0,\n overflow: (isWebkit() ? 'none' : 'visible'), // Chrome 7 has a problem with this when zooming out\n style: 'pointer-events:none'\n }\n });\n\n const rect = svgFactory_.createSVGElement({\n element: 'rect',\n attr: {\n width: '100%',\n height: '100%',\n x: 0,\n y: 0,\n 'stroke-width': 1,\n stroke: '#000',\n fill: '#FFF',\n style: 'pointer-events:none'\n }\n });\n\n // Both Firefox and WebKit are too slow with this filter region (especially at higher\n // zoom levels) and Opera has at least one bug\n // if (!isOpera()) rect.setAttribute('filter', 'url(#canvashadow)');\n canvasbg.append(rect);\n svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent());\n // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`?\n }\n\n /**\n *\n * @param {Element} elem - DOM element to get the selector for\n * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for reset (prevents duplicate getBBox call).\n * @returns {Selector} The selector based on the given element\n */\n requestSelector (elem, bbox) {\n if (isNullish(elem)) { return null; }\n\n const N = this.selectors.length;\n // If we've already acquired one for this element, return it.\n if (typeof this.selectorMap[elem.id] === 'object') {\n this.selectorMap[elem.id].locked = true;\n return this.selectorMap[elem.id];\n }\n for (let i = 0; i < N; ++i) {\n if (this.selectors[i] && !this.selectors[i].locked) {\n this.selectors[i].locked = true;\n this.selectors[i].reset(elem, bbox);\n this.selectorMap[elem.id] = this.selectors[i];\n return this.selectors[i];\n }\n }\n // if we reached here, no available selectors were found, we create one\n this.selectors[N] = new Selector(N, elem, bbox);\n this.selectorParentGroup.append(this.selectors[N].selectorGroup);\n this.selectorMap[elem.id] = this.selectors[N];\n return this.selectors[N];\n }\n\n /**\n * Removes the selector of the given element (hides selection box).\n *\n * @param {Element} elem - DOM element to remove the selector for\n * @returns {void}\n */\n releaseSelector (elem) {\n if (isNullish(elem)) { return; }\n const N = this.selectors.length,\n sel = this.selectorMap[elem.id];\n if (!sel.locked) {\n // TODO(codedread): Ensure this exists in this module.\n console.log('WARNING! selector was released but was already unlocked'); // eslint-disable-line no-console\n }\n for (let i = 0; i < N; ++i) {\n if (this.selectors[i] && this.selectors[i] === sel) {\n delete this.selectorMap[elem.id];\n sel.locked = false;\n sel.selectedElement = null;\n sel.showGrips(false);\n\n // remove from DOM and store reference in JS but only if it exists in the DOM\n try {\n sel.selectorGroup.setAttribute('display', 'none');\n } catch (e) {}\n\n break;\n }\n }\n }\n\n /**\n * @returns {SVGRectElement} The rubberBandBox DOM element. This is the rectangle drawn by\n * the user for selecting/zooming\n */\n getRubberBandBox () {\n if (!this.rubberBandBox) {\n this.rubberBandBox = this.selectorParentGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'rect',\n attr: {\n id: 'selectorRubberBand',\n fill: '#22C',\n 'fill-opacity': 0.15,\n stroke: '#22C',\n 'stroke-width': 0.5,\n display: 'none',\n style: 'pointer-events:none'\n }\n })\n );\n }\n return this.rubberBandBox;\n }\n}\n\n/**\n * An object that creates SVG elements for the canvas.\n *\n * @interface module:select.SVGFactory\n */\n/**\n * @function module:select.SVGFactory#createSVGElement\n * @param {module:utilities.EditorContext#addSVGElementFromJson} jsonMap\n * @returns {SVGElement}\n */\n/**\n * @function module:select.SVGFactory#svgRoot\n * @returns {SVGSVGElement}\n */\n/**\n * @function module:select.SVGFactory#svgContent\n * @returns {SVGSVGElement}\n */\n/**\n * @function module:select.SVGFactory#getCurrentZoom\n * @returns {Float} The current zoom level\n */\n\n/**\n * @typedef {GenericArray} module:select.Dimensions\n * @property {Integer} length 2\n * @property {Float} 0 Width\n * @property {Float} 1 Height\n */\n/**\n * @typedef {PlainObject} module:select.Config\n * @property {string} imgPath\n * @property {module:select.Dimensions} dimensions\n */\n\n/**\n * Initializes this module.\n * @function module:select.init\n * @param {module:select.Config} config - An object containing configurable parameters (imgPath)\n * @param {module:select.SVGFactory} svgFactory - An object implementing the SVGFactory interface.\n * @returns {void}\n */\nexport const init = function (config, svgFactory) {\n config_ = config;\n svgFactory_ = svgFactory;\n selectorManager_ = new SelectorManager();\n};\n\n/**\n * @function module:select.getSelectorManager\n * @returns {module:select.SelectorManager} The SelectorManager instance.\n */\nexport const getSelectorManager = () => selectorManager_;\n","/* eslint-disable indent, unicorn/no-fn-reference-in-iterator */\n/* globals jQuery, jsPDF */\n/**\n * Numerous tools for working with the editor's \"canvas\".\n * @module svgcanvas\n *\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Pavol Rusnak, 2010 Jeff Schiller\n *\n */\n\n/* Dependencies:\n1. Also expects jQuery UI for `svgCanvasToString` and\n`convertToGroup` use of `:data()` selector\n*/\n\n// Todo: Obtain/adapt latest jsPDF to utilize ES Module for `jsPDF`/avoid global\n\nimport '../common/svgpathseg.js';\nimport jQueryPluginSVG from '../common/jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport jQueryPluginDBox from './dbox.js';\n\nimport * as pathModule from './path.js';\nimport * as hstry from './history.js';\nimport * as draw from './draw.js';\n// eslint-disable-next-line no-duplicate-imports\nimport {\n identifyLayers, createLayer, cloneLayer, deleteCurrentLayer,\n setCurrentLayer, renameCurrentLayer, setCurrentLayerPosition,\n setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers,\n leaveContext, setContext\n} from './draw.js';\nimport {sanitizeSvg} from './sanitize.js';\nimport {getReverseNS, NS} from '../common/namespaces.js';\nimport {importSetGlobal, importScript} from '../external/dynamic-import-polyfill/importModule.js';\nimport {\n text2xml, assignAttributes, cleanupElement, getElem, getUrlFromAttr,\n findDefs, getHref, setHref, getRefElem, getRotationAngle, getPathBBox,\n preventClickDefault, snapToGrid, walkTree, walkTreePost,\n getBBoxOfElementAsPath, convertToPath, toXml, encode64, decode64,\n dataURLToObjectURL, createObjectURL,\n getVisibleElements, dropXMLInternalSubset,\n init as utilsInit, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible,\n isNullish\n} from '../common/utilities.js';\nimport {\n transformPoint, matrixMultiply, hasMatrixTransform, transformListToTransform,\n getMatrix, snapToAngle, isIdentity, rectsIntersect, transformBox\n} from '../common/math.js';\nimport {\n convertToNum, convertAttrs, convertUnit, shortFloat, getTypeMap,\n init as unitsInit\n} from '../common/units.js';\nimport {\n isGecko, isChrome, isIE, isWebkit, supportsNonScalingStroke, supportsGoodTextCharPos\n} from '../common/browser.js'; // , supportsEditableText\nimport {\n getTransformList, resetListMap,\n SVGTransformList as SVGEditTransformList\n} from '../common/svgtransformlist.js';\nimport {\n remapElement,\n init as coordsInit\n} from './coords.js';\nimport {\n recalculateDimensions,\n init as recalculateInit\n} from './recalculate.js';\nimport {\n getSelectorManager,\n Selector,\n init as selectInit\n} from './select.js';\n\nlet $ = jQueryPluginSVG(jQuery);\nconst {\n MoveElementCommand, InsertElementCommand, RemoveElementCommand,\n ChangeElementCommand, BatchCommand, UndoManager, HistoryEventTypes\n} = hstry;\n\nif (!window.console) {\n window.console = {};\n window.console.log = function (str) { /* */ };\n window.console.dir = function (str) { /* */ };\n}\n\nif (window.opera) {\n window.console.log = function (str) { window.opera.postError(str); };\n window.console.dir = function (str) { /* */ };\n}\n\n// Reenable after fixing eslint-plugin-jsdoc to handle\n/**\n* The main SvgCanvas class that manages all SVG-related functions.\n* @memberof module:svgcanvas\n*\n* @borrows module:coords.remapElement as #remapElement\n* @borrows module:recalculate.recalculateDimensions as #recalculateDimensions\n*\n* @borrows module:utilities.cleanupElement as #cleanupElement\n* @borrows module:utilities.getStrokedBBoxDefaultVisible as #getStrokedBBox\n* @borrows module:utilities.getVisibleElements as #getVisibleElements\n* @borrows module:utilities.findDefs as #findDefs\n* @borrows module:utilities.getUrlFromAttr as #getUrlFromAttr\n* @borrows module:utilities.getHref as #getHref\n* @borrows module:utilities.setHref as #setHref\n* @borrows module:utilities.getRotationAngle as #getRotationAngle\n* @borrows module:utilities.getBBox as #getBBox\n* @borrows module:utilities.getElem as #getElem\n* @borrows module:utilities.getRefElem as #getRefElem\n* @borrows module:utilities.assignAttributes as #assignAttributes\n*\n* @borrows module:SVGTransformList.getTransformList as #getTransformList\n* @borrows module:math.matrixMultiply as #matrixMultiply\n* @borrows module:math.hasMatrixTransform as #hasMatrixTransform\n* @borrows module:math.transformListToTransform as #transformListToTransform\n* @borrows module:units.convertToNum as #convertToNum\n* @borrows module:sanitize.sanitizeSvg as #sanitizeSvg\n* @borrows module:path.pathActions.linkControlPoints as #linkControlPoints\n*/\nclass SvgCanvas {\n /**\n * @param {HTMLElement} container - The container HTML element that should hold the SVG root element\n * @param {module:SVGEditor.curConfig} config - An object that contains configuration data\n */\n constructor (container, config) {\n// Alias Namespace constants\n\n// Default configuration options\nconst curConfig = {\n show_outside_canvas: true,\n selectNew: true,\n dimensions: [640, 480]\n};\n\n// Update config with new one if given\nif (config) {\n $.extend(curConfig, config);\n}\n\n// Array with width/height of canvas\nconst {dimensions} = curConfig;\n\nconst canvas = this; // eslint-disable-line consistent-this\n\n// \"document\" element associated with the container (same as window.document using default svg-editor.js)\n// NOTE: This is not actually a SVG document, but an HTML document.\nconst svgdoc = container.ownerDocument;\n\n// This is a container for the document being edited, not the document itself.\n/**\n * @name module:svgcanvas~svgroot\n * @type {SVGSVGElement}\n */\nconst svgroot = svgdoc.importNode(\n text2xml(\n '<svg id=\"svgroot\" xmlns=\"' + NS.SVG + '\" xlinkns=\"' + NS.XLINK + '\" ' +\n 'width=\"' + dimensions[0] + '\" height=\"' + dimensions[1] + '\" x=\"' + dimensions[0] + '\" y=\"' + dimensions[1] + '\" overflow=\"visible\">' +\n '<defs>' +\n '<filter id=\"canvashadow\" filterUnits=\"objectBoundingBox\">' +\n '<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"4\" result=\"blur\"/>' +\n '<feOffset in=\"blur\" dx=\"5\" dy=\"5\" result=\"offsetBlur\"/>' +\n '<feMerge>' +\n '<feMergeNode in=\"offsetBlur\"/>' +\n '<feMergeNode in=\"SourceGraphic\"/>' +\n '</feMerge>' +\n '</filter>' +\n '</defs>' +\n '</svg>'\n ).documentElement,\n true\n);\ncontainer.append(svgroot);\n\n/**\n * The actual element that represents the final output SVG element.\n * @name module:svgcanvas~svgcontent\n * @type {SVGSVGElement}\n */\nlet svgcontent = svgdoc.createElementNS(NS.SVG, 'svg');\n\n/**\n* This function resets the svgcontent element while keeping it in the DOM.\n* @function module:svgcanvas.SvgCanvas#clearSvgContentElement\n* @returns {void}\n*/\nconst clearSvgContentElement = canvas.clearSvgContentElement = function () {\n $(svgcontent).empty();\n\n // TODO: Clear out all other attributes first?\n $(svgcontent).attr({\n id: 'svgcontent',\n width: dimensions[0],\n height: dimensions[1],\n x: dimensions[0],\n y: dimensions[1],\n overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden',\n xmlns: NS.SVG,\n 'xmlns:se': NS.SE,\n 'xmlns:xlink': NS.XLINK\n }).appendTo(svgroot);\n\n // TODO: make this string optional and set by the client\n const comment = svgdoc.createComment(' Created with SVG-edit - https://github.com/SVG-Edit/svgedit');\n svgcontent.append(comment);\n};\nclearSvgContentElement();\n\n// Prefix string for element IDs\nlet idprefix = 'svg_';\n\n/**\n* Changes the ID prefix to the given value.\n* @function module:svgcanvas.SvgCanvas#setIdPrefix\n* @param {string} p - String with the new prefix\n* @returns {void}\n*/\ncanvas.setIdPrefix = function (p) {\n idprefix = p;\n};\n\n/**\n* Current `draw.Drawing` object.\n* @type {module:draw.Drawing}\n* @name module:svgcanvas.SvgCanvas#current_drawing_\n*/\ncanvas.current_drawing_ = new draw.Drawing(svgcontent, idprefix);\n\n/**\n* Returns the current Drawing.\n* @name module:svgcanvas.SvgCanvas#getCurrentDrawing\n* @type {module:draw.DrawCanvasInit#getCurrentDrawing}\n*/\nconst getCurrentDrawing = canvas.getCurrentDrawing = function () {\n return canvas.current_drawing_;\n};\n\n/**\n* Float displaying the current zoom level (1 = 100%, .5 = 50%, etc.).\n* @type {Float}\n*/\nlet currentZoom = 1;\n\n// pointer to current group (for in-group editing)\nlet currentGroup = null;\n\n// Object containing data for the currently selected styles\nconst allProperties = {\n shape: {\n fill: (curConfig.initFill.color === 'none' ? '' : '#') + curConfig.initFill.color,\n fill_paint: null,\n fill_opacity: curConfig.initFill.opacity,\n stroke: '#' + curConfig.initStroke.color,\n stroke_paint: null,\n stroke_opacity: curConfig.initStroke.opacity,\n stroke_width: curConfig.initStroke.width,\n stroke_dasharray: 'none',\n stroke_linejoin: 'miter',\n stroke_linecap: 'butt',\n opacity: curConfig.initOpacity\n }\n};\n\nallProperties.text = $.extend(true, {}, allProperties.shape);\n$.extend(allProperties.text, {\n fill: '#000000',\n stroke_width: curConfig.text && curConfig.text.stroke_width,\n font_size: curConfig.text && curConfig.text.font_size,\n font_family: curConfig.text && curConfig.text.font_family\n});\n\n// Current shape style properties\nconst curShape = allProperties.shape;\n\n// Array with all the currently selected elements\n// default size of 1 until it needs to grow bigger\nlet selectedElements = [];\n\n/**\n* @typedef {PlainObject} module:svgcanvas.SVGAsJSON\n* @property {string} element\n* @property {PlainObject<string, string>} attr\n* @property {module:svgcanvas.SVGAsJSON[]} children\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getContentElem\n* @param {Text|Element} data\n* @returns {module:svgcanvas.SVGAsJSON}\n*/\nconst getJsonFromSvgElement = this.getJsonFromSvgElement = function (data) {\n // Text node\n if (data.nodeType === 3) return data.nodeValue;\n\n const retval = {\n element: data.tagName,\n // namespace: nsMap[data.namespaceURI],\n attr: {},\n children: []\n };\n\n // Iterate attributes\n for (let i = 0, attr; (attr = data.attributes[i]); i++) {\n retval.attr[attr.name] = attr.value;\n }\n\n // Iterate children\n for (let i = 0, node; (node = data.childNodes[i]); i++) {\n retval.children[i] = getJsonFromSvgElement(node);\n }\n\n return retval;\n};\n\n/**\n* This should really be an intersection implementing all rather than a union.\n* @name module:svgcanvas.SvgCanvas#addSVGElementFromJson\n* @type {module:utilities.EditorContext#addSVGElementFromJson|module:path.EditorContext#addSVGElementFromJson}\n*/\nconst addSVGElementFromJson = this.addSVGElementFromJson = function (data) {\n if (typeof data === 'string') return svgdoc.createTextNode(data);\n\n let shape = getElem(data.attr.id);\n // if shape is a path but we need to create a rect/ellipse, then remove the path\n const currentLayer = getCurrentDrawing().getCurrentLayer();\n if (shape && data.element !== shape.tagName) {\n shape.remove();\n shape = null;\n }\n if (!shape) {\n const ns = data.namespace || NS.SVG;\n shape = svgdoc.createElementNS(ns, data.element);\n if (currentLayer) {\n (currentGroup || currentLayer).append(shape);\n }\n }\n if (data.curStyles) {\n assignAttributes(shape, {\n fill: curShape.fill,\n stroke: curShape.stroke,\n 'stroke-width': curShape.stroke_width,\n 'stroke-dasharray': curShape.stroke_dasharray,\n 'stroke-linejoin': curShape.stroke_linejoin,\n 'stroke-linecap': curShape.stroke_linecap,\n 'stroke-opacity': curShape.stroke_opacity,\n 'fill-opacity': curShape.fill_opacity,\n opacity: curShape.opacity / 2,\n style: 'pointer-events:inherit'\n }, 100);\n }\n assignAttributes(shape, data.attr, 100);\n cleanupElement(shape);\n\n // Children\n if (data.children) {\n data.children.forEach((child) => {\n shape.append(addSVGElementFromJson(child));\n });\n }\n\n return shape;\n};\n\ncanvas.getTransformList = getTransformList;\n\ncanvas.matrixMultiply = matrixMultiply;\ncanvas.hasMatrixTransform = hasMatrixTransform;\ncanvas.transformListToTransform = transformListToTransform;\n\n/**\n* @type {module:utilities.EditorContext#getBaseUnit}\n*/\nconst getBaseUnit = () => { return curConfig.baseUnit; };\n\n/**\n* Initialize from units.js.\n* Send in an object implementing the ElementContainer interface (see units.js).\n*/\nunitsInit(\n /**\n * @implements {module:units.ElementContainer}\n */\n {\n getBaseUnit,\n getElement: getElem,\n getHeight () { return svgcontent.getAttribute('height') / currentZoom; },\n getWidth () { return svgcontent.getAttribute('width') / currentZoom; },\n getRoundDigits () { return saveOptions.round_digits; }\n }\n);\n\ncanvas.convertToNum = convertToNum;\n\n/**\n* This should really be an intersection implementing all rather than a union.\n* @type {module:draw.DrawCanvasInit#getSVGContent|module:utilities.EditorContext#getSVGContent}\n*/\nconst getSVGContent = () => { return svgcontent; };\n\n/**\n* Should really be an intersection with all needing to apply rather than a union.\n* @name module:svgcanvas.SvgCanvas#getSelectedElements\n* @type {module:utilities.EditorContext#getSelectedElements|module:draw.DrawCanvasInit#getSelectedElements|module:path.EditorContext#getSelectedElements}\n*/\nconst getSelectedElements = this.getSelectedElems = function () {\n return selectedElements;\n};\n\nconst {pathActions} = pathModule;\n\n/**\n* This should actually be an intersection as all interfaces should be met.\n* @type {module:utilities.EditorContext#getSVGRoot|module:recalculate.EditorContext#getSVGRoot|module:coords.EditorContext#getSVGRoot|module:path.EditorContext#getSVGRoot}\n*/\nconst getSVGRoot = () => svgroot;\n\nutilsInit(\n /**\n * @implements {module:utilities.EditorContext}\n */\n {\n pathActions, // Ok since not modifying\n getSVGContent,\n addSVGElementFromJson,\n getSelectedElements,\n getDOMDocument () { return svgdoc; },\n getDOMContainer () { return container; },\n getSVGRoot,\n // TODO: replace this mostly with a way to get the current drawing.\n getBaseUnit,\n getSnappingStep () { return curConfig.snappingStep; }\n }\n);\n\ncanvas.findDefs = findDefs;\ncanvas.getUrlFromAttr = getUrlFromAttr;\ncanvas.getHref = getHref;\ncanvas.setHref = setHref;\n/* const getBBox = */ canvas.getBBox = utilsGetBBox;\ncanvas.getRotationAngle = getRotationAngle;\ncanvas.getElem = getElem;\ncanvas.getRefElem = getRefElem;\ncanvas.assignAttributes = assignAttributes;\n\nthis.cleanupElement = cleanupElement;\n\n/**\n* This should actually be an intersection not a union as all should apply.\n* @type {module:coords.EditorContext#getGridSnapping|module:path.EditorContext#getGridSnapping}\n*/\nconst getGridSnapping = () => { return curConfig.gridSnapping; };\n\ncoordsInit(\n /**\n * @implements {module:coords.EditorContext}\n */\n {\n getDrawing () { return getCurrentDrawing(); },\n getSVGRoot,\n getGridSnapping\n }\n);\nthis.remapElement = remapElement;\n\nrecalculateInit(\n /**\n * @implements {module:recalculate.EditorContext}\n */\n {\n getSVGRoot,\n getStartTransform () { return startTransform; },\n setStartTransform (transform) { startTransform = transform; }\n }\n);\nthis.recalculateDimensions = recalculateDimensions;\n\n// import from sanitize.js\nconst nsMap = getReverseNS();\ncanvas.sanitizeSvg = sanitizeSvg;\n\n/**\n* @name undoMgr\n* @memberof module:svgcanvas.SvgCanvas#\n* @type {module:history.HistoryEventHandler}\n*/\nconst undoMgr = canvas.undoMgr = new UndoManager({\n /**\n * @param {string} eventType One of the HistoryEvent types\n * @param {module:history.HistoryCommand} cmd Fulfills the HistoryCommand interface\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n handleHistoryEvent (eventType, cmd) {\n const EventTypes = HistoryEventTypes;\n // TODO: handle setBlurOffsets.\n if (eventType === EventTypes.BEFORE_UNAPPLY || eventType === EventTypes.BEFORE_APPLY) {\n canvas.clearSelection();\n } else if (eventType === EventTypes.AFTER_APPLY || eventType === EventTypes.AFTER_UNAPPLY) {\n const elems = cmd.elements();\n canvas.pathActions.clear();\n call('changed', elems);\n const cmdType = cmd.type();\n const isApply = (eventType === EventTypes.AFTER_APPLY);\n if (cmdType === 'MoveElementCommand') {\n const parent = isApply ? cmd.newParent : cmd.oldParent;\n if (parent === svgcontent) {\n draw.identifyLayers();\n }\n } else if (cmdType === 'InsertElementCommand' ||\n cmdType === 'RemoveElementCommand') {\n if (cmd.parent === svgcontent) {\n draw.identifyLayers();\n }\n if (cmdType === 'InsertElementCommand') {\n if (isApply) { restoreRefElems(cmd.elem); }\n } else if (!isApply) {\n restoreRefElems(cmd.elem);\n }\n if (cmd.elem && cmd.elem.tagName === 'use') {\n setUseData(cmd.elem);\n }\n } else if (cmdType === 'ChangeElementCommand') {\n // if we are changing layer names, re-identify all layers\n if (cmd.elem.tagName === 'title' &&\n cmd.elem.parentNode.parentNode === svgcontent\n ) {\n draw.identifyLayers();\n }\n const values = isApply ? cmd.newValues : cmd.oldValues;\n // If stdDeviation was changed, update the blur.\n if (values.stdDeviation) {\n canvas.setBlurOffsets(cmd.elem.parentNode, values.stdDeviation);\n }\n // This is resolved in later versions of webkit, perhaps we should\n // have a featured detection for correct 'use' behavior?\n // ——————————\n // Remove & Re-add hack for Webkit (issue 775)\n // if (cmd.elem.tagName === 'use' && isWebkit()) {\n // const {elem} = cmd;\n // if (!elem.getAttribute('x') && !elem.getAttribute('y')) {\n // const parent = elem.parentNode;\n // const sib = elem.nextSibling;\n // elem.remove();\n // parent.insertBefore(elem, sib);\n // // Ok to replace above with this? `sib.before(elem);`\n // }\n // }\n }\n }\n }\n});\n\n/**\n* This should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas~addCommandToHistory\n* @type {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory}\n*/\nconst addCommandToHistory = function (cmd) {\n canvas.undoMgr.addCommandToHistory(cmd);\n};\n\n/**\n* This should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas.SvgCanvas#getZoom\n* @type {module:path.EditorContext#getCurrentZoom|module:select.SVGFactory#getCurrentZoom}\n*/\nconst getCurrentZoom = this.getZoom = function () { return currentZoom; };\n\n/**\n* This method rounds the incoming value to the nearest value based on the `currentZoom`\n* @name module:svgcanvas.SvgCanvas#round\n* @type {module:path.EditorContext#round}\n*/\nconst round = this.round = function (val) {\n return Number.parseInt(val * currentZoom) / currentZoom;\n};\n\nselectInit(\n curConfig,\n /**\n * Export to select.js.\n * @implements {module:select.SVGFactory}\n */\n {\n createSVGElement (jsonMap) { return canvas.addSVGElementFromJson(jsonMap); },\n svgRoot () { return svgroot; },\n svgContent () { return svgcontent; },\n getCurrentZoom\n }\n);\n/**\n* This object manages selectors for us.\n* @name module:svgcanvas.SvgCanvas#selectorManager\n* @type {module:select.SelectorManager}\n*/\nconst selectorManager = this.selectorManager = getSelectorManager();\n\n/**\n* @name module:svgcanvas.SvgCanvas#getNextId\n* @type {module:path.EditorContext#getNextId}\n*/\nconst getNextId = canvas.getNextId = function () {\n return getCurrentDrawing().getNextId();\n};\n\n/**\n* @name module:svgcanvas.SvgCanvas#getId\n* @type {module:path.EditorContext#getId}\n*/\nconst getId = canvas.getId = function () {\n return getCurrentDrawing().getId();\n};\n\n/**\n* The \"implements\" should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas.SvgCanvas#call\n* @type {module:draw.DrawCanvasInit#call|module:path.EditorContext#call}\n*/\nconst call = function (ev, arg) {\n if (events[ev]) {\n return events[ev](window, arg);\n }\n return undefined;\n};\n\n/**\n* Clears the selection. The 'selected' handler is then optionally called.\n* This should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas.SvgCanvas#clearSelection\n* @type {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection}\n* @fires module:svgcanvas.SvgCanvas#event:selected\n*/\nconst clearSelection = this.clearSelection = function (noCall) {\n selectedElements.forEach((elem) => {\n if (isNullish(elem)) {\n return;\n }\n selectorManager.releaseSelector(elem);\n });\n selectedElements = [];\n\n if (!noCall) { call('selected', selectedElements); }\n};\n\n/**\n* Adds a list of elements to the selection. The 'selected' handler is then called.\n* @name module:svgcanvas.SvgCanvas#addToSelection\n* @type {module:path.EditorContext#addToSelection}\n* @fires module:svgcanvas.SvgCanvas#event:selected\n*/\nconst addToSelection = this.addToSelection = function (elemsToAdd, showGrips) {\n if (!elemsToAdd.length) { return; }\n // find the first null in our selectedElements array\n\n let j = 0;\n while (j < selectedElements.length) {\n if (isNullish(selectedElements[j])) {\n break;\n }\n ++j;\n }\n\n // now add each element consecutively\n let i = elemsToAdd.length;\n while (i--) {\n let elem = elemsToAdd[i];\n if (!elem) { continue; }\n const bbox = utilsGetBBox(elem);\n if (!bbox) { continue; }\n\n if (elem.tagName === 'a' && elem.childNodes.length === 1) {\n // Make \"a\" element's child be the selected element\n elem = elem.firstChild;\n }\n\n // if it's not already there, add it\n if (!selectedElements.includes(elem)) {\n selectedElements[j] = elem;\n\n // only the first selectedBBoxes element is ever used in the codebase these days\n // if (j === 0) selectedBBoxes[0] = utilsGetBBox(elem);\n j++;\n const sel = selectorManager.requestSelector(elem, bbox);\n\n if (selectedElements.length > 1) {\n sel.showGrips(false);\n }\n }\n }\n if (!selectedElements.length) {\n return;\n }\n call('selected', selectedElements);\n\n if (selectedElements.length === 1) {\n selectorManager.requestSelector(selectedElements[0]).showGrips(showGrips);\n }\n\n // make sure the elements are in the correct order\n // See: https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition\n\n selectedElements.sort(function (a, b) {\n if (a && b && a.compareDocumentPosition) {\n return 3 - (b.compareDocumentPosition(a) & 6); // eslint-disable-line no-bitwise\n }\n if (isNullish(a)) {\n return 1;\n }\n return 0;\n });\n\n // Make sure first elements are not null\n while (isNullish(selectedElements[0])) {\n selectedElements.shift(0);\n }\n};\n\n/**\n* @type {module:path.EditorContext#getOpacity}\n*/\nconst getOpacity = function () {\n return curShape.opacity;\n};\n\n/**\n* @name module:svgcanvas.SvgCanvas#getMouseTarget\n* @type {module:path.EditorContext#getMouseTarget}\n*/\nconst getMouseTarget = this.getMouseTarget = function (evt) {\n if (isNullish(evt)) {\n return null;\n }\n let mouseTarget = evt.target;\n\n // if it was a <use>, Opera and WebKit return the SVGElementInstance\n if (mouseTarget.correspondingUseElement) { mouseTarget = mouseTarget.correspondingUseElement; }\n\n // for foreign content, go up until we find the foreignObject\n // WebKit browsers set the mouse target to the svgcanvas div\n if ([NS.MATH, NS.HTML].includes(mouseTarget.namespaceURI) &&\n mouseTarget.id !== 'svgcanvas'\n ) {\n while (mouseTarget.nodeName !== 'foreignObject') {\n mouseTarget = mouseTarget.parentNode;\n if (!mouseTarget) { return svgroot; }\n }\n }\n\n // Get the desired mouseTarget with jQuery selector-fu\n // If it's root-like, select the root\n const currentLayer = getCurrentDrawing().getCurrentLayer();\n if ([svgroot, container, svgcontent, currentLayer].includes(mouseTarget)) {\n return svgroot;\n }\n\n const $target = $(mouseTarget);\n\n // If it's a selection grip, return the grip parent\n if ($target.closest('#selectorParentGroup').length) {\n // While we could instead have just returned mouseTarget,\n // this makes it easier to indentify as being a selector grip\n return selectorManager.selectorParentGroup;\n }\n\n while (mouseTarget.parentNode !== (currentGroup || currentLayer)) {\n mouseTarget = mouseTarget.parentNode;\n }\n\n //\n // // go up until we hit a child of a layer\n // while (mouseTarget.parentNode.parentNode.tagName == 'g') {\n // mouseTarget = mouseTarget.parentNode;\n // }\n // Webkit bubbles the mouse event all the way up to the div, so we\n // set the mouseTarget to the svgroot like the other browsers\n // if (mouseTarget.nodeName.toLowerCase() == 'div') {\n // mouseTarget = svgroot;\n // }\n\n return mouseTarget;\n};\n\n/**\n* @namespace {module:path.pathActions} pathActions\n* @memberof module:svgcanvas.SvgCanvas#\n* @see module:path.pathActions\n*/\ncanvas.pathActions = pathActions;\n/**\n* @type {module:path.EditorContext#resetD}\n*/\nfunction resetD (p) {\n p.setAttribute('d', pathActions.convertPath(p));\n}\npathModule.init(\n /**\n * @implements {module:path.EditorContext}\n */\n {\n selectorManager, // Ok since not changing\n canvas, // Ok since not changing\n call,\n resetD,\n round,\n clearSelection,\n addToSelection,\n addCommandToHistory,\n remapElement,\n addSVGElementFromJson,\n getGridSnapping,\n getOpacity,\n getSelectedElements,\n getContainer () {\n return container;\n },\n setStarted (s) {\n started = s;\n },\n getRubberBox () {\n return rubberBox;\n },\n setRubberBox (rb) {\n rubberBox = rb;\n return rubberBox;\n },\n /**\n * @param {PlainObject} ptsInfo\n * @param {boolean} ptsInfo.closedSubpath\n * @param {SVGCircleElement[]} ptsInfo.grips\n * @fires module:svgcanvas.SvgCanvas#event:pointsAdded\n * @fires module:svgcanvas.SvgCanvas#event:selected\n * @returns {void}\n */\n addPtsToSelection ({closedSubpath, grips}) {\n // TODO: Correct this:\n pathActions.canDeleteNodes = true;\n pathActions.closed_subpath = closedSubpath;\n call('pointsAdded', {closedSubpath, grips});\n call('selected', grips);\n },\n /**\n * @param {PlainObject} changes\n * @param {ChangeElementCommand} changes.cmd\n * @param {SVGPathElement} changes.elem\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n endChanges ({cmd, elem}) {\n addCommandToHistory(cmd);\n call('changed', [elem]);\n },\n getCurrentZoom,\n getId,\n getNextId,\n getMouseTarget,\n getCurrentMode () {\n return currentMode;\n },\n setCurrentMode (cm) {\n currentMode = cm;\n return currentMode;\n },\n getDrawnPath () {\n return drawnPath;\n },\n setDrawnPath (dp) {\n drawnPath = dp;\n return drawnPath;\n },\n getSVGRoot\n }\n);\n\n// Interface strings, usually for title elements\nconst uiStrings = {};\n\nconst visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use';\nconst refAttrs = ['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'];\n\nconst elData = $.data;\n\n// Animation element to change the opacity of any newly created element\nconst opacAni = document.createElementNS(NS.SVG, 'animate');\n$(opacAni).attr({\n attributeName: 'opacity',\n begin: 'indefinite',\n dur: 1,\n fill: 'freeze'\n}).appendTo(svgroot);\n\nconst restoreRefElems = function (elem) {\n // Look for missing reference elements, restore any found\n const attrs = $(elem).attr(refAttrs);\n Object.values(attrs).forEach((val) => {\n if (val && val.startsWith('url(')) {\n const id = getUrlFromAttr(val).substr(1);\n const ref = getElem(id);\n if (!ref) {\n findDefs().append(removedElements[id]);\n delete removedElements[id];\n }\n }\n });\n\n const childs = elem.getElementsByTagName('*');\n\n if (childs.length) {\n for (let i = 0, l = childs.length; i < l; i++) {\n restoreRefElems(childs[i]);\n }\n }\n};\n\n// (function () {\n// TODO For Issue 208: this is a start on a thumbnail\n// const svgthumb = svgdoc.createElementNS(NS.SVG, 'use');\n// svgthumb.setAttribute('width', '100');\n// svgthumb.setAttribute('height', '100');\n// setHref(svgthumb, '#svgcontent');\n// svgroot.append(svgthumb);\n// }());\n\n/**\n * @typedef {PlainObject} module:svgcanvas.SaveOptions\n * @property {boolean} apply\n * @property {\"embed\"} [image]\n * @property {Integer} round_digits\n */\n\n// Object to contain image data for raster images that were found encodable\nconst encodableImages = {},\n\n // Object with save options\n /**\n * @type {module:svgcanvas.SaveOptions}\n */\n saveOptions = {round_digits: 5},\n\n // Object with IDs for imported files, to see if one was already added\n importIds = {},\n\n // Current text style properties\n curText = allProperties.text,\n\n // Object to contain all included extensions\n extensions = {},\n\n // Map of deleted reference elements\n removedElements = {};\n\nlet\n // String with image URL of last loadable image\n lastGoodImgUrl = curConfig.imgPath + 'logo.png',\n\n // Boolean indicating whether or not a draw action has been started\n started = false,\n\n // String with an element's initial transform attribute value\n startTransform = null,\n\n // String indicating the current editor mode\n currentMode = 'select',\n\n // String with the current direction in which an element is being resized\n currentResizeMode = 'none',\n\n // Current general properties\n curProperties = curShape,\n\n // Array with selected elements' Bounding box object\n // selectedBBoxes = new Array(1),\n\n // The DOM element that was just selected\n justSelected = null,\n\n // DOM element for selection rectangle drawn by the user\n rubberBox = null,\n\n // Array of current BBoxes, used in getIntersectionList().\n curBBoxes = [],\n\n // Canvas point for the most recent right click\n lastClickPoint = null;\n\nthis.runExtension = function (name, action, vars) {\n return this.runExtensions(action, vars, false, (n) => n === name);\n};\n/**\n* @typedef {module:svgcanvas.ExtensionMouseDownStatus|module:svgcanvas.ExtensionMouseUpStatus|module:svgcanvas.ExtensionIDsUpdatedStatus|module:locale.ExtensionLocaleData[]|void} module:svgcanvas.ExtensionStatus\n* @tutorial ExtensionDocs\n*/\n/**\n* @callback module:svgcanvas.ExtensionVarBuilder\n* @param {string} name The name of the extension\n* @returns {module:svgcanvas.SvgCanvas#event:ext_addLangData}\n*/\n/**\n* @callback module:svgcanvas.ExtensionNameFilter\n* @param {string} name\n* @returns {boolean}\n*/\n/**\n* @todo Consider: Should this return an array by default, so extension results aren't overwritten?\n* @todo Would be easier to document if passing in object with key of action and vars as value; could then define an interface which tied both together\n* @function module:svgcanvas.SvgCanvas#runExtensions\n* @param {\"mouseDown\"|\"mouseMove\"|\"mouseUp\"|\"zoomChanged\"|\"IDsUpdated\"|\"canvasUpdated\"|\"toolButtonStateUpdate\"|\"selectedChanged\"|\"elementTransition\"|\"elementChanged\"|\"langReady\"|\"langChanged\"|\"addLangData\"|\"onNewDocument\"|\"workareaResized\"} action\n* @param {module:svgcanvas.SvgCanvas#event:ext_mouseDown|module:svgcanvas.SvgCanvas#event:ext_mouseMove|module:svgcanvas.SvgCanvas#event:ext_mouseUp|module:svgcanvas.SvgCanvas#event:ext_zoomChanged|module:svgcanvas.SvgCanvas#event:ext_IDsUpdated|module:svgcanvas.SvgCanvas#event:ext_canvasUpdated|module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate|module:svgcanvas.SvgCanvas#event:ext_selectedChanged|module:svgcanvas.SvgCanvas#event:ext_elementTransition|module:svgcanvas.SvgCanvas#event:ext_elementChanged|module:svgcanvas.SvgCanvas#event:ext_langReady|module:svgcanvas.SvgCanvas#event:ext_langChanged|module:svgcanvas.SvgCanvas#event:ext_addLangData|module:svgcanvas.SvgCanvas#event:ext_onNewDocument|module:svgcanvas.SvgCanvas#event:ext_workareaResized|module:svgcanvas.ExtensionVarBuilder} [vars]\n* @param {boolean} [returnArray]\n* @param {module:svgcanvas.ExtensionNameFilter} nameFilter\n* @returns {GenericArray<module:svgcanvas.ExtensionStatus>|module:svgcanvas.ExtensionStatus|false} See {@tutorial ExtensionDocs} on the ExtensionStatus.\n*/\nconst runExtensions = this.runExtensions = function (action, vars, returnArray, nameFilter) {\n let result = returnArray ? [] : false;\n $.each(extensions, function (name, ext) {\n if (nameFilter && !nameFilter(name)) {\n return;\n }\n if (ext && action in ext) {\n if (typeof vars === 'function') {\n vars = vars(name); // ext, action\n }\n if (returnArray) {\n result.push(ext[action](vars));\n } else {\n result = ext[action](vars);\n }\n }\n });\n return result;\n};\n\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionMouseDownStatus\n* @property {boolean} started Indicates that creating/editing has started\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionMouseUpStatus\n* @property {boolean} keep Indicates if the current element should be kept\n* @property {boolean} started Indicates if editing should still be considered as \"started\"\n* @property {Element} element The element being affected\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionIDsUpdatedStatus\n* @property {string[]} remove Contains string IDs (used by `ext-connector.js`)\n*/\n\n/**\n * @interface module:svgcanvas.ExtensionInitResponse\n * @property {module:SVGEditor.ContextTool[]|PlainObject<string, module:SVGEditor.ContextTool>} [context_tools]\n * @property {module:SVGEditor.Button[]|PlainObject<Integer, module:SVGEditor.Button>} [buttons]\n * @property {string} [svgicons] The location of a local SVG or SVGz file\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#mouseDown\n * @param {module:svgcanvas.SvgCanvas#event:ext_mouseDown} arg\n * @returns {void|module:svgcanvas.ExtensionMouseDownStatus}\n */\n/**\n * @function module:svgcanvas.ExtensionInitResponse#mouseMove\n * @param {module:svgcanvas.SvgCanvas#event:ext_mouseMove} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#mouseUp\n * @param {module:svgcanvas.SvgCanvas#event:ext_mouseUp} arg\n * @returns {module:svgcanvas.ExtensionMouseUpStatus}\n */\n/**\n * @function module:svgcanvas.ExtensionInitResponse#zoomChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_zoomChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#IDsUpdated\n * @param {module:svgcanvas.SvgCanvas#event:ext_IDsUpdated} arg\n * @returns {module:svgcanvas.ExtensionIDsUpdatedStatus}\n */\n/**\n * @function module:svgcanvas.ExtensionInitResponse#canvasUpdated\n * @param {module:svgcanvas.SvgCanvas#event:ext_canvasUpdated} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#toolButtonStateUpdate\n * @param {module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#selectedChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_selectedChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#elementTransition\n * @param {module:svgcanvas.SvgCanvas#event:ext_elementTransition} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#elementChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_elementChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#langReady\n * @param {module:svgcanvas.SvgCanvas#event:ext_langReady} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#langChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_langChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#addLangData\n * @param {module:svgcanvas.SvgCanvas#event:ext_addLangData} arg\n * @returns {Promise<module:locale.ExtensionLocaleData>} Resolves to {@link module:locale.ExtensionLocaleData}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#onNewDocument\n * @param {module:svgcanvas.SvgCanvas#event:ext_onNewDocument} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#workareaResized\n * @param {module:svgcanvas.SvgCanvas#event:ext_workareaResized} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#callback\n * @this module:SVGEditor\n * @param {module:svgcanvas.SvgCanvas#event:ext_callback} arg\n * @returns {void}\n*/\n\n/**\n* @callback module:svgcanvas.ExtensionInitCallback\n* @this module:SVGEditor\n* @param {module:svgcanvas.ExtensionArgumentObject} arg\n* @returns {Promise<module:svgcanvas.ExtensionInitResponse|void>} Resolves to [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse} or `undefined`\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionInitArgs\n* @property {external:jQuery} $\n* @property {module:SVGEditor~ImportLocale} importLocale\n*/\n/**\n* Add an extension to the editor.\n* @function module:svgcanvas.SvgCanvas#addExtension\n* @param {string} name - String with the ID of the extension. Used internally; no need for i18n.\n* @param {module:svgcanvas.ExtensionInitCallback} [extInitFunc] - Function supplied by the extension with its data\n* @param {module:svgcanvas.ExtensionInitArgs} initArgs\n* @fires module:svgcanvas.SvgCanvas#event:extension_added\n* @throws {TypeError|Error} `TypeError` if `extInitFunc` is not a function, `Error`\n* if extension of supplied name already exists\n* @returns {Promise<void>} Resolves to `undefined`\n*/\nthis.addExtension = async function (name, extInitFunc, {$: jq, importLocale}) {\n if (typeof extInitFunc !== 'function') {\n throw new TypeError('Function argument expected for `svgcanvas.addExtension`');\n }\n if (name in extensions) {\n throw new Error('Cannot add extension \"' + name + '\", an extension by that name already exists.');\n }\n // Provide private vars/funcs here. Is there a better way to do this?\n /**\n * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject\n * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot}\n * @property {SVGSVGElement} svgcontent See {@link module:svgcanvas~svgcontent}\n * @property {!(string|Integer)} nonce See {@link module:draw.Drawing#getNonce}\n * @property {module:select.SelectorManager} selectorManager\n * @property {module:SVGEditor~ImportLocale} importLocale\n */\n /**\n * @type {module:svgcanvas.ExtensionArgumentObject}\n * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties\n */\n const argObj = $.extend(canvas.getPrivateMethods(), {\n $: jq,\n importLocale,\n svgroot,\n svgcontent,\n nonce: getCurrentDrawing().getNonce(),\n selectorManager\n });\n const extObj = await extInitFunc(argObj);\n if (extObj) {\n extObj.name = name;\n }\n\n extensions[name] = extObj;\n return call('extension_added', extObj);\n};\n\n/**\n* This method sends back an array or a NodeList full of elements that\n* intersect the multi-select rubber-band-box on the currentLayer only.\n*\n* We brute-force `getIntersectionList` for browsers that do not support it (Firefox).\n*\n* Reference:\n* Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421}.\n* @function module:svgcanvas.SvgCanvas#getIntersectionList\n* @param {SVGRect} rect\n* @returns {Element[]|NodeList} Bbox elements\n*/\nconst getIntersectionList = this.getIntersectionList = function (rect) {\n if (isNullish(rubberBox)) { return null; }\n\n const parent = currentGroup || getCurrentDrawing().getCurrentLayer();\n\n let rubberBBox;\n if (!rect) {\n rubberBBox = rubberBox.getBBox();\n const bb = svgcontent.createSVGRect();\n\n ['x', 'y', 'width', 'height', 'top', 'right', 'bottom', 'left'].forEach((o) => {\n bb[o] = rubberBBox[o] / currentZoom;\n });\n rubberBBox = bb;\n } else {\n rubberBBox = svgcontent.createSVGRect();\n rubberBBox.x = rect.x;\n rubberBBox.y = rect.y;\n rubberBBox.width = rect.width;\n rubberBBox.height = rect.height;\n }\n\n let resultList = null;\n if (!isIE()) {\n if (typeof svgroot.getIntersectionList === 'function') {\n // Offset the bbox of the rubber box by the offset of the svgcontent element.\n rubberBBox.x += Number.parseInt(svgcontent.getAttribute('x'));\n rubberBBox.y += Number.parseInt(svgcontent.getAttribute('y'));\n\n resultList = svgroot.getIntersectionList(rubberBBox, parent);\n }\n }\n\n if (isNullish(resultList) || typeof resultList.item !== 'function') {\n resultList = [];\n\n if (!curBBoxes.length) {\n // Cache all bboxes\n curBBoxes = getVisibleElementsAndBBoxes(parent);\n }\n let i = curBBoxes.length;\n while (i--) {\n if (!rubberBBox.width) { continue; }\n if (rectsIntersect(rubberBBox, curBBoxes[i].bbox)) {\n resultList.push(curBBoxes[i].elem);\n }\n }\n }\n\n // addToSelection expects an array, but it's ok to pass a NodeList\n // because using square-bracket notation is allowed:\n // https://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html\n return resultList;\n};\n\nthis.getStrokedBBox = getStrokedBBoxDefaultVisible;\n\nthis.getVisibleElements = getVisibleElements;\n\n/**\n* @typedef {PlainObject} ElementAndBBox\n* @property {Element} elem - The element\n* @property {module:utilities.BBoxObject} bbox - The element's BBox as retrieved from `getStrokedBBoxDefaultVisible`\n*/\n\n/**\n* Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc).\n* Note that 0-opacity, off-screen etc elements are still considered \"visible\"\n* for this function.\n* @function module:svgcanvas.SvgCanvas#getVisibleElementsAndBBoxes\n* @param {Element} parent - The parent DOM element to search within\n* @returns {ElementAndBBox[]} An array with objects that include:\n*/\nconst getVisibleElementsAndBBoxes = this.getVisibleElementsAndBBoxes = function (parent) {\n if (!parent) {\n parent = $(svgcontent).children(); // Prevent layers from being included\n }\n const contentElems = [];\n $(parent).children().each(function (i, elem) {\n if (elem.getBBox) {\n contentElems.push({elem, bbox: getStrokedBBoxDefaultVisible([elem])});\n }\n });\n return contentElems.reverse();\n};\n\n/**\n* Wrap an SVG element into a group element, mark the group as 'gsvg'.\n* @function module:svgcanvas.SvgCanvas#groupSvgElem\n* @param {Element} elem - SVG element to wrap\n* @returns {void}\n*/\nconst groupSvgElem = this.groupSvgElem = function (elem) {\n const g = document.createElementNS(NS.SVG, 'g');\n elem.replaceWith(g);\n $(g).append(elem).data('gsvg', elem)[0].id = getNextId();\n};\n\n// Set scope for these functions\n\n// Object to contain editor event names and callback functions\nconst events = {};\n\ncanvas.call = call;\n/**\n * Array of what was changed (elements, layers).\n * @event module:svgcanvas.SvgCanvas#event:changed\n * @type {Element[]}\n */\n/**\n * Array of selected elements.\n * @event module:svgcanvas.SvgCanvas#event:selected\n * @type {Element[]}\n */\n/**\n * Array of selected elements.\n * @event module:svgcanvas.SvgCanvas#event:transition\n * @type {Element[]}\n */\n/**\n * The Element is always `SVGGElement`?\n * If not `null`, will be the set current group element.\n * @event module:svgcanvas.SvgCanvas#event:contextset\n * @type {null|Element}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:pointsAdded\n * @type {PlainObject}\n * @property {boolean} closedSubpath\n * @property {SVGCircleElement[]} grips Grips elements\n */\n\n/**\n * @event module:svgcanvas.SvgCanvas#event:zoomed\n * @type {PlainObject}\n * @property {Float} x\n * @property {Float} y\n * @property {Float} width\n * @property {Float} height\n * @property {0.5|2} factor\n * @see module:SVGEditor.BBoxObjectWithFactor\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:updateCanvas\n * @type {PlainObject}\n * @property {false} center\n * @property {module:math.XYObject} newCtr\n */\n/**\n * @typedef {PlainObject} module:svgcanvas.ExtensionInitResponsePlusName\n * @implements {module:svgcanvas.ExtensionInitResponse}\n * @property {string} name The extension's resolved ID (whether explicit or based on file name)\n */\n/**\n * Generalized extension object response of\n * [`init()`]{@link module:svgcanvas.ExtensionInitCallback}\n * along with the name of the extension.\n * @event module:svgcanvas.SvgCanvas#event:extension_added\n * @type {module:svgcanvas.ExtensionInitResponsePlusName|void}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:extensions_added\n * @type {void}\n*/\n/**\n * @typedef {PlainObject} module:svgcanvas.Message\n * @property {any} data The data\n * @property {string} origin The origin\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:message\n * @type {module:svgcanvas.Message}\n */\n/**\n * SVG canvas converted to string.\n * @event module:svgcanvas.SvgCanvas#event:saved\n * @type {string}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:setnonce\n * @type {!(string|Integer)}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:unsetnonce\n * @type {void}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:zoomDone\n * @type {void}\n*/\n/**\n * @event module:svgcanvas.SvgCanvas#event:cleared\n * @type {void}\n*/\n\n/**\n * @event module:svgcanvas.SvgCanvas#event:exported\n * @type {module:svgcanvas.ImageExportedResults}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:exportedPDF\n * @type {module:svgcanvas.PDFExportedResults}\n */\n/**\n * Creating a cover-all class until {@link https://github.com/jsdoc3/jsdoc/issues/1545} may be supported.\n * `undefined` may be returned by {@link module:svgcanvas.SvgCanvas#event:extension_added} if the extension's `init` returns `undefined` It is also the type for the following events \"zoomDone\", \"unsetnonce\", \"cleared\", and \"extensions_added\".\n * @event module:svgcanvas.SvgCanvas#event:GenericCanvasEvent\n * @type {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset|module:svgcanvas.SvgCanvas#event:pointsAdded|module:svgcanvas.SvgCanvas#event:extension_added|module:svgcanvas.SvgCanvas#event:extensions_added|module:svgcanvas.SvgCanvas#event:message|module:svgcanvas.SvgCanvas#event:transition|module:svgcanvas.SvgCanvas#event:zoomed|module:svgcanvas.SvgCanvas#event:updateCanvas|module:svgcanvas.SvgCanvas#event:saved|module:svgcanvas.SvgCanvas#event:exported|module:svgcanvas.SvgCanvas#event:exportedPDF|module:svgcanvas.SvgCanvas#event:setnonce|module:svgcanvas.SvgCanvas#event:unsetnonce|void}\n */\n\n/**\n * The promise return, if present, resolves to `undefined`\n * (`extension_added`, `exported`, `saved`).\n * @typedef {Promise<void>|void} module:svgcanvas.EventHandlerReturn\n*/\n\n/**\n* @callback module:svgcanvas.EventHandler\n* @param {external:Window} win\n* @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg\n* @listens module:svgcanvas.SvgCanvas#event:GenericCanvasEvent\n* @returns {module:svgcanvas.EventHandlerReturn}\n*/\n\n/**\n* Attaches a callback function to an event.\n* @function module:svgcanvas.SvgCanvas#bind\n* @param {\"changed\"|\"contextset\"|\"selected\"|\"pointsAdded\"|\"extension_added\"|\"extensions_added\"|\"message\"|\"transition\"|\"zoomed\"|\"updateCanvas\"|\"zoomDone\"|\"saved\"|\"exported\"|\"exportedPDF\"|\"setnonce\"|\"unsetnonce\"|\"cleared\"} ev - String indicating the name of the event\n* @param {module:svgcanvas.EventHandler} f - The callback function to bind to the event\n* @returns {module:svgcanvas.EventHandler} The previous event\n*/\ncanvas.bind = function (ev, f) {\n const old = events[ev];\n events[ev] = f;\n return old;\n};\n\n/**\n* Runs the SVG Document through the sanitizer and then updates its paths.\n* @function module:svgcanvas.SvgCanvas#prepareSvg\n* @param {XMLDocument} newDoc - The SVG DOM document\n* @returns {void}\n*/\nthis.prepareSvg = function (newDoc) {\n this.sanitizeSvg(newDoc.documentElement);\n\n // convert paths into absolute commands\n const paths = [...newDoc.getElementsByTagNameNS(NS.SVG, 'path')];\n paths.forEach((path) => {\n path.setAttribute('d', pathActions.convertPath(path));\n pathActions.fixEnd(path);\n });\n};\n\n/**\n* Hack for Firefox bugs where text element features aren't updated or get\n* messed up. See issue 136 and issue 137.\n* This function clones the element and re-selects it.\n* @function module:svgcanvas~ffClone\n* @todo Test for this bug on load and add it to \"support\" object instead of\n* browser sniffing\n* @param {Element} elem - The (text) DOM element to clone\n* @returns {Element} Cloned element\n*/\nconst ffClone = function (elem) {\n if (!isGecko()) { return elem; }\n const clone = elem.cloneNode(true);\n elem.before(clone);\n elem.remove();\n selectorManager.releaseSelector(elem);\n selectedElements[0] = clone;\n selectorManager.requestSelector(clone).showGrips(true);\n return clone;\n};\n\n// `this.each` is deprecated, if any extension used this it can be recreated by doing this:\n// * @example $(canvas.getRootElem()).children().each(...)\n// * @function module:svgcanvas.SvgCanvas#each\n// this.each = function (cb) {\n// $(svgroot).children().each(cb);\n// };\n\n/**\n* Removes any old rotations if present, prepends a new rotation at the\n* transformed center.\n* @function module:svgcanvas.SvgCanvas#setRotationAngle\n* @param {string|Float} val - The new rotation angle in degrees\n* @param {boolean} preventUndo - Indicates whether the action should be undoable or not\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setRotationAngle = function (val, preventUndo) {\n // ensure val is the proper type\n val = Number.parseFloat(val);\n const elem = selectedElements[0];\n const oldTransform = elem.getAttribute('transform');\n const bbox = utilsGetBBox(elem);\n const cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2;\n const tlist = getTransformList(elem);\n\n // only remove the real rotational transform if present (i.e. at index=0)\n if (tlist.numberOfItems > 0) {\n const xform = tlist.getItem(0);\n if (xform.type === 4) {\n tlist.removeItem(0);\n }\n }\n // find Rnc and insert it\n if (val !== 0) {\n const center = transformPoint(cx, cy, transformListToTransform(tlist).matrix);\n const Rnc = svgroot.createSVGTransform();\n Rnc.setRotate(val, center.x, center.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(Rnc, 0);\n } else {\n tlist.appendItem(Rnc);\n }\n } else if (tlist.numberOfItems === 0) {\n elem.removeAttribute('transform');\n }\n\n if (!preventUndo) {\n // we need to undo it, then redo it so it can be undo-able! :)\n // TODO: figure out how to make changes to transform list undo-able cross-browser?\n const newTransform = elem.getAttribute('transform');\n elem.setAttribute('transform', oldTransform);\n changeSelectedAttribute('transform', newTransform, selectedElements);\n call('changed', selectedElements);\n }\n // const pointGripContainer = getElem('pathpointgrip_container');\n // if (elem.nodeName === 'path' && pointGripContainer) {\n // pathActions.setPointContainerTransform(elem.getAttribute('transform'));\n // }\n const selector = selectorManager.requestSelector(selectedElements[0]);\n selector.resize();\n Selector.updateGripCursors(val);\n};\n\n/**\n* Runs `recalculateDimensions` on the selected elements,\n* adding the changes to a single batch command.\n* @function module:svgcanvas.SvgCanvas#recalculateAllSelectedDimensions\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nconst recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = function () {\n const text = (currentResizeMode === 'none' ? 'position' : 'size');\n const batchCmd = new BatchCommand(text);\n\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n // if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; }\n const cmd = recalculateDimensions(elem);\n if (cmd) {\n batchCmd.addSubCommand(cmd);\n }\n }\n\n if (!batchCmd.isEmpty()) {\n addCommandToHistory(batchCmd);\n call('changed', selectedElements);\n }\n};\n\n/**\n * Debug tool to easily see the current matrix in the browser's console.\n * @function module:svgcanvas~logMatrix\n * @param {SVGMatrix} m The matrix\n * @returns {void}\n */\nconst logMatrix = function (m) {\n console.log([m.a, m.b, m.c, m.d, m.e, m.f]); // eslint-disable-line no-console\n};\n\n// Root Current Transformation Matrix in user units\nlet rootSctm = null;\n\n/**\n* Group: Selection.\n*/\n\n// TODO: do we need to worry about selectedBBoxes here?\n\n/**\n* Selects only the given elements, shortcut for `clearSelection(); addToSelection()`.\n* @function module:svgcanvas.SvgCanvas#selectOnly\n* @param {Element[]} elems - an array of DOM elements to be selected\n* @param {boolean} showGrips - Indicates whether the resize grips should be shown\n* @returns {void}\n*/\nconst selectOnly = this.selectOnly = function (elems, showGrips) {\n clearSelection(true);\n addToSelection(elems, showGrips);\n};\n\n// TODO: could use slice here to make this faster?\n// TODO: should the 'selected' handler\n\n/**\n* Removes elements from the selection.\n* @function module:svgcanvas.SvgCanvas#removeFromSelection\n* @param {Element[]} elemsToRemove - An array of elements to remove from selection\n* @returns {void}\n*/\n/* const removeFromSelection = */ this.removeFromSelection = function (elemsToRemove) {\n if (isNullish(selectedElements[0])) { return; }\n if (!elemsToRemove.length) { return; }\n\n // find every element and remove it from our array copy\n const newSelectedItems = [],\n len = selectedElements.length;\n for (let i = 0; i < len; ++i) {\n const elem = selectedElements[i];\n if (elem) {\n // keep the item\n if (!elemsToRemove.includes(elem)) {\n newSelectedItems.push(elem);\n } else { // remove the item and its selector\n selectorManager.releaseSelector(elem);\n }\n }\n }\n // the copy becomes the master now\n selectedElements = newSelectedItems;\n};\n\n/**\n* Clears the selection, then adds all elements in the current layer to the selection.\n* @function module:svgcanvas.SvgCanvas#selectAllInCurrentLayer\n* @returns {void}\n*/\nthis.selectAllInCurrentLayer = function () {\n const currentLayer = getCurrentDrawing().getCurrentLayer();\n if (currentLayer) {\n currentMode = 'select';\n selectOnly($(currentGroup || currentLayer).children());\n }\n};\n\nlet drawnPath = null;\n\n// Mouse events\n(function () {\nconst freehand = {\n minx: null,\n miny: null,\n maxx: null,\n maxy: null\n};\nconst THRESHOLD_DIST = 0.8,\n STEP_COUNT = 10;\nlet dAttr = null,\n startX = null,\n startY = null,\n rStartX = null,\n rStartY = null,\n initBbox = {},\n sumDistance = 0,\n controllPoint2 = {x: 0, y: 0},\n controllPoint1 = {x: 0, y: 0},\n start = {x: 0, y: 0},\n end = {x: 0, y: 0},\n bSpline = {x: 0, y: 0},\n nextPos = {x: 0, y: 0},\n parameter,\n nextParameter;\n\nconst getBsplinePoint = function (t) {\n const spline = {x: 0, y: 0},\n p0 = controllPoint2,\n p1 = controllPoint1,\n p2 = start,\n p3 = end,\n S = 1.0 / 6.0,\n t2 = t * t,\n t3 = t2 * t;\n\n const m = [\n [-1, 3, -3, 1],\n [3, -6, 3, 0],\n [-3, 0, 3, 0],\n [1, 4, 1, 0]\n ];\n\n spline.x = S * (\n (p0.x * m[0][0] + p1.x * m[0][1] + p2.x * m[0][2] + p3.x * m[0][3]) * t3 +\n (p0.x * m[1][0] + p1.x * m[1][1] + p2.x * m[1][2] + p3.x * m[1][3]) * t2 +\n (p0.x * m[2][0] + p1.x * m[2][1] + p2.x * m[2][2] + p3.x * m[2][3]) * t +\n (p0.x * m[3][0] + p1.x * m[3][1] + p2.x * m[3][2] + p3.x * m[3][3])\n );\n spline.y = S * (\n (p0.y * m[0][0] + p1.y * m[0][1] + p2.y * m[0][2] + p3.y * m[0][3]) * t3 +\n (p0.y * m[1][0] + p1.y * m[1][1] + p2.y * m[1][2] + p3.y * m[1][3]) * t2 +\n (p0.y * m[2][0] + p1.y * m[2][1] + p2.y * m[2][2] + p3.y * m[2][3]) * t +\n (p0.y * m[3][0] + p1.y * m[3][1] + p2.y * m[3][2] + p3.y * m[3][3])\n );\n\n return {\n x: spline.x,\n y: spline.y\n };\n};\n/**\n * Follows these conditions:\n * - When we are in a create mode, the element is added to the canvas but the\n * action is not recorded until mousing up.\n * - When we are in select mode, select the element, remember the position\n * and do nothing else.\n * @param {MouseEvent} evt\n * @fires module:svgcanvas.SvgCanvas#event:ext_mouseDown\n * @returns {void}\n */\nconst mouseDown = function (evt) {\n if (canvas.spaceKey || evt.button === 1) { return; }\n\n const rightClick = evt.button === 2;\n\n if (evt.altKey) { // duplicate when dragging\n canvas.cloneSelectedElements(0, 0);\n }\n\n rootSctm = $('#svgcontent g')[0].getScreenCTM().inverse();\n\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = pt.x * currentZoom,\n mouseY = pt.y * currentZoom;\n\n evt.preventDefault();\n\n if (rightClick) {\n currentMode = 'select';\n lastClickPoint = pt;\n }\n\n // This would seem to be unnecessary...\n // if (!['select', 'resize'].includes(currentMode)) {\n // setGradient();\n // }\n\n let x = mouseX / currentZoom,\n y = mouseY / currentZoom;\n let mouseTarget = getMouseTarget(evt);\n\n if (mouseTarget.tagName === 'a' && mouseTarget.childNodes.length === 1) {\n mouseTarget = mouseTarget.firstChild;\n }\n\n // realX/y ignores grid-snap value\n const realX = x;\n rStartX = startX = x;\n const realY = y;\n rStartY = startY = y;\n\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n startX = snapToGrid(startX);\n startY = snapToGrid(startY);\n }\n\n // if it is a selector grip, then it must be a single element selected,\n // set the mouseTarget to that and update the mode to rotate/resize\n\n if (mouseTarget === selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) {\n const grip = evt.target;\n const griptype = elData(grip, 'type');\n // rotating\n if (griptype === 'rotate') {\n currentMode = 'rotate';\n // resizing\n } else if (griptype === 'resize') {\n currentMode = 'resize';\n currentResizeMode = elData(grip, 'dir');\n }\n mouseTarget = selectedElements[0];\n }\n\n startTransform = mouseTarget.getAttribute('transform');\n\n const tlist = getTransformList(mouseTarget);\n switch (currentMode) {\n case 'select':\n started = true;\n currentResizeMode = 'none';\n if (rightClick) { started = false; }\n\n if (mouseTarget !== svgroot) {\n // if this element is not yet selected, clear selection and select it\n if (!selectedElements.includes(mouseTarget)) {\n // only clear selection if shift is not pressed (otherwise, add\n // element to selection)\n if (!evt.shiftKey) {\n // No need to do the call here as it will be done on addToSelection\n clearSelection(true);\n }\n addToSelection([mouseTarget]);\n justSelected = mouseTarget;\n pathActions.clear();\n }\n // else if it's a path, go into pathedit mode in mouseup\n\n if (!rightClick) {\n // insert a dummy transform so if the element(s) are moved it will have\n // a transform to use for its translate\n for (const selectedElement of selectedElements) {\n if (isNullish(selectedElement)) { continue; }\n const slist = getTransformList(selectedElement);\n if (slist.numberOfItems) {\n slist.insertItemBefore(svgroot.createSVGTransform(), 0);\n } else {\n slist.appendItem(svgroot.createSVGTransform());\n }\n }\n }\n } else if (!rightClick) {\n clearSelection();\n currentMode = 'multiselect';\n if (isNullish(rubberBox)) {\n rubberBox = selectorManager.getRubberBandBox();\n }\n rStartX *= currentZoom;\n rStartY *= currentZoom;\n // console.log('p',[evt.pageX, evt.pageY]);\n // console.log('c',[evt.clientX, evt.clientY]);\n // console.log('o',[evt.offsetX, evt.offsetY]);\n // console.log('s',[startX, startY]);\n\n assignAttributes(rubberBox, {\n x: rStartX,\n y: rStartY,\n width: 0,\n height: 0,\n display: 'inline'\n }, 100);\n }\n break;\n case 'zoom':\n started = true;\n if (isNullish(rubberBox)) {\n rubberBox = selectorManager.getRubberBandBox();\n }\n assignAttributes(rubberBox, {\n x: realX * currentZoom,\n y: realX * currentZoom,\n width: 0,\n height: 0,\n display: 'inline'\n }, 100);\n break;\n case 'resize': {\n started = true;\n startX = x;\n startY = y;\n\n // Getting the BBox from the selection box, since we know we\n // want to orient around it\n initBbox = utilsGetBBox($('#selectedBox0')[0]);\n const bb = {};\n $.each(initBbox, function (key, val) {\n bb[key] = val / currentZoom;\n });\n initBbox = bb;\n\n // append three dummy transforms to the tlist so that\n // we can translate,scale,translate in mousemove\n const pos = getRotationAngle(mouseTarget) ? 1 : 0;\n\n if (hasMatrixTransform(tlist)) {\n tlist.insertItemBefore(svgroot.createSVGTransform(), pos);\n tlist.insertItemBefore(svgroot.createSVGTransform(), pos);\n tlist.insertItemBefore(svgroot.createSVGTransform(), pos);\n } else {\n tlist.appendItem(svgroot.createSVGTransform());\n tlist.appendItem(svgroot.createSVGTransform());\n tlist.appendItem(svgroot.createSVGTransform());\n\n if (supportsNonScalingStroke()) {\n // Handle crash for newer Chrome and Safari 6 (Mobile and Desktop):\n // https://code.google.com/p/svg-edit/issues/detail?id=904\n // Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625\n // TODO: Remove this workaround once vendor fixes the issue\n const iswebkit = isWebkit();\n\n let delayedStroke;\n if (iswebkit) {\n delayedStroke = function (ele) {\n const stroke_ = ele.getAttribute('stroke');\n ele.removeAttribute('stroke');\n // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker\n if (stroke_ !== null) setTimeout(function () { ele.setAttribute('stroke', stroke_); }, 0);\n };\n }\n mouseTarget.style.vectorEffect = 'non-scaling-stroke';\n if (iswebkit) { delayedStroke(mouseTarget); }\n\n const all = mouseTarget.getElementsByTagName('*'),\n len = all.length;\n for (let i = 0; i < len; i++) {\n if (!all[i].style) { // mathML\n continue;\n }\n all[i].style.vectorEffect = 'non-scaling-stroke';\n if (iswebkit) { delayedStroke(all[i]); }\n }\n }\n }\n break;\n }\n case 'fhellipse':\n case 'fhrect':\n case 'fhpath':\n start.x = realX;\n start.y = realY;\n controllPoint1 = {x: 0, y: 0};\n controllPoint2 = {x: 0, y: 0};\n started = true;\n dAttr = realX + ',' + realY + ' ';\n // Commented out as doing nothing now:\n // strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width;\n addSVGElementFromJson({\n element: 'polyline',\n curStyles: true,\n attr: {\n points: dAttr,\n id: getNextId(),\n fill: 'none',\n opacity: curShape.opacity / 2,\n 'stroke-linecap': 'round',\n style: 'pointer-events:none'\n }\n });\n freehand.minx = realX;\n freehand.maxx = realX;\n freehand.miny = realY;\n freehand.maxy = realY;\n break;\n case 'image': {\n started = true;\n const newImage = addSVGElementFromJson({\n element: 'image',\n attr: {\n x,\n y,\n width: 0,\n height: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2,\n style: 'pointer-events:inherit'\n }\n });\n setHref(newImage, lastGoodImgUrl);\n preventClickDefault(newImage);\n break;\n } case 'square':\n // TODO: once we create the rect, we lose information that this was a square\n // (for resizing purposes this could be important)\n // Fallthrough\n case 'rect':\n started = true;\n startX = x;\n startY = y;\n addSVGElementFromJson({\n element: 'rect',\n curStyles: true,\n attr: {\n x,\n y,\n width: 0,\n height: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2\n }\n });\n break;\n case 'line': {\n started = true;\n const strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width;\n addSVGElementFromJson({\n element: 'line',\n curStyles: true,\n attr: {\n x1: x,\n y1: y,\n x2: x,\n y2: y,\n id: getNextId(),\n stroke: curShape.stroke,\n 'stroke-width': strokeW,\n 'stroke-dasharray': curShape.stroke_dasharray,\n 'stroke-linejoin': curShape.stroke_linejoin,\n 'stroke-linecap': curShape.stroke_linecap,\n 'stroke-opacity': curShape.stroke_opacity,\n fill: 'none',\n opacity: curShape.opacity / 2,\n style: 'pointer-events:none'\n }\n });\n break;\n } case 'circle':\n started = true;\n addSVGElementFromJson({\n element: 'circle',\n curStyles: true,\n attr: {\n cx: x,\n cy: y,\n r: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2\n }\n });\n break;\n case 'ellipse':\n started = true;\n addSVGElementFromJson({\n element: 'ellipse',\n curStyles: true,\n attr: {\n cx: x,\n cy: y,\n rx: 0,\n ry: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2\n }\n });\n break;\n case 'text':\n started = true;\n /* const newText = */ addSVGElementFromJson({\n element: 'text',\n curStyles: true,\n attr: {\n x,\n y,\n id: getNextId(),\n fill: curText.fill,\n 'stroke-width': curText.stroke_width,\n 'font-size': curText.font_size,\n 'font-family': curText.font_family,\n 'text-anchor': 'middle',\n 'xml:space': 'preserve',\n opacity: curShape.opacity\n }\n });\n // newText.textContent = 'text';\n break;\n case 'path':\n // Fall through\n case 'pathedit':\n startX *= currentZoom;\n startY *= currentZoom;\n pathActions.mouseDown(evt, mouseTarget, startX, startY);\n started = true;\n break;\n case 'textedit':\n startX *= currentZoom;\n startY *= currentZoom;\n textActions.mouseDown(evt, mouseTarget, startX, startY);\n started = true;\n break;\n case 'rotate':\n started = true;\n // we are starting an undoable change (a drag-rotation)\n canvas.undoMgr.beginUndoableChange('transform', selectedElements);\n break;\n default:\n // This could occur in an extension\n break;\n }\n\n /**\n * The main (left) mouse button is held down on the canvas area.\n * @event module:svgcanvas.SvgCanvas#event:ext_mouseDown\n * @type {PlainObject}\n * @property {MouseEvent} event The event object\n * @property {Float} start_x x coordinate on canvas\n * @property {Float} start_y y coordinate on canvas\n * @property {Element[]} selectedElements An array of the selected Elements\n */\n const extResult = runExtensions('mouseDown', /** @type {module:svgcanvas.SvgCanvas#event:ext_mouseDown} */ {\n event: evt,\n start_x: startX,\n start_y: startY,\n selectedElements\n }, true);\n\n $.each(extResult, function (i, r) {\n if (r && r.started) {\n started = true;\n }\n });\n};\n\n// in this function we do not record any state changes yet (but we do update\n// any elements that are still being created, moved or resized on the canvas)\n/**\n *\n * @param {MouseEvent} evt\n * @fires module:svgcanvas.SvgCanvas#event:transition\n * @fires module:svgcanvas.SvgCanvas#event:ext_mouseMove\n * @returns {void}\n */\nconst mouseMove = function (evt) {\n if (!started) { return; }\n if (evt.button === 1 || canvas.spaceKey) { return; }\n\n let i, xya, c, cx, cy, dx, dy, len, angle, box,\n selected = selectedElements[0];\n const\n pt = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = pt.x * currentZoom,\n mouseY = pt.y * currentZoom,\n shape = getElem(getId());\n\n let realX = mouseX / currentZoom;\n let x = realX;\n let realY = mouseY / currentZoom;\n let y = realY;\n\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n }\n\n evt.preventDefault();\n let tlist;\n switch (currentMode) {\n case 'select': {\n // we temporarily use a translate on the element(s) being dragged\n // this transform is removed upon mousing up and the element is\n // relocated to the new location\n if (selectedElements[0] !== null) {\n dx = x - startX;\n dy = y - startY;\n\n if (curConfig.gridSnapping) {\n dx = snapToGrid(dx);\n dy = snapToGrid(dy);\n }\n\n /*\n // Commenting out as currently has no effect\n if (evt.shiftKey) {\n xya = snapToAngle(startX, startY, x, y);\n ({x, y} = xya);\n }\n */\n\n if (dx !== 0 || dy !== 0) {\n len = selectedElements.length;\n for (i = 0; i < len; ++i) {\n selected = selectedElements[i];\n if (isNullish(selected)) { break; }\n // if (i === 0) {\n // const box = utilsGetBBox(selected);\n // selectedBBoxes[i].x = box.x + dx;\n // selectedBBoxes[i].y = box.y + dy;\n // }\n\n // update the dummy transform in our transform list\n // to be a translate\n const xform = svgroot.createSVGTransform();\n tlist = getTransformList(selected);\n // Note that if Webkit and there's no ID for this\n // element, the dummy transform may have gotten lost.\n // This results in unexpected behaviour\n\n xform.setTranslate(dx, dy);\n if (tlist.numberOfItems) {\n tlist.replaceItem(xform, 0);\n } else {\n tlist.appendItem(xform);\n }\n\n // update our internal bbox that we're tracking while dragging\n selectorManager.requestSelector(selected).resize();\n }\n\n call('transition', selectedElements);\n }\n }\n break;\n } case 'multiselect': {\n realX *= currentZoom;\n realY *= currentZoom;\n assignAttributes(rubberBox, {\n x: Math.min(rStartX, realX),\n y: Math.min(rStartY, realY),\n width: Math.abs(realX - rStartX),\n height: Math.abs(realY - rStartY)\n }, 100);\n\n // for each selected:\n // - if newList contains selected, do nothing\n // - if newList doesn't contain selected, remove it from selected\n // - for any newList that was not in selectedElements, add it to selected\n const elemsToRemove = selectedElements.slice(), elemsToAdd = [],\n newList = getIntersectionList();\n\n // For every element in the intersection, add if not present in selectedElements.\n len = newList.length;\n for (i = 0; i < len; ++i) {\n const intElem = newList[i];\n // Found an element that was not selected before, so we should add it.\n if (!selectedElements.includes(intElem)) {\n elemsToAdd.push(intElem);\n }\n // Found an element that was already selected, so we shouldn't remove it.\n const foundInd = elemsToRemove.indexOf(intElem);\n if (foundInd !== -1) {\n elemsToRemove.splice(foundInd, 1);\n }\n }\n\n if (elemsToRemove.length > 0) {\n canvas.removeFromSelection(elemsToRemove);\n }\n\n if (elemsToAdd.length > 0) {\n canvas.addToSelection(elemsToAdd);\n }\n\n break;\n } case 'resize': {\n // we track the resize bounding box and translate/scale the selected element\n // while the mouse is down, when mouse goes up, we use this to recalculate\n // the shape's coordinates\n tlist = getTransformList(selected);\n const hasMatrix = hasMatrixTransform(tlist);\n box = hasMatrix ? initBbox : utilsGetBBox(selected);\n let left = box.x,\n top = box.y,\n {width, height} = box;\n dx = (x - startX);\n dy = (y - startY);\n\n if (curConfig.gridSnapping) {\n dx = snapToGrid(dx);\n dy = snapToGrid(dy);\n height = snapToGrid(height);\n width = snapToGrid(width);\n }\n\n // if rotated, adjust the dx,dy values\n angle = getRotationAngle(selected);\n if (angle) {\n const r = Math.sqrt(dx * dx + dy * dy),\n theta = Math.atan2(dy, dx) - angle * Math.PI / 180.0;\n dx = r * Math.cos(theta);\n dy = r * Math.sin(theta);\n }\n\n // if not stretching in y direction, set dy to 0\n // if not stretching in x direction, set dx to 0\n if (!currentResizeMode.includes('n') && !currentResizeMode.includes('s')) {\n dy = 0;\n }\n if (!currentResizeMode.includes('e') && !currentResizeMode.includes('w')) {\n dx = 0;\n }\n\n let // ts = null,\n tx = 0, ty = 0,\n sy = height ? (height + dy) / height : 1,\n sx = width ? (width + dx) / width : 1;\n // if we are dragging on the north side, then adjust the scale factor and ty\n if (currentResizeMode.includes('n')) {\n sy = height ? (height - dy) / height : 1;\n ty = height;\n }\n\n // if we dragging on the east side, then adjust the scale factor and tx\n if (currentResizeMode.includes('w')) {\n sx = width ? (width - dx) / width : 1;\n tx = width;\n }\n\n // update the transform list with translate,scale,translate\n const translateOrigin = svgroot.createSVGTransform(),\n scale = svgroot.createSVGTransform(),\n translateBack = svgroot.createSVGTransform();\n\n if (curConfig.gridSnapping) {\n left = snapToGrid(left);\n tx = snapToGrid(tx);\n top = snapToGrid(top);\n ty = snapToGrid(ty);\n }\n\n translateOrigin.setTranslate(-(left + tx), -(top + ty));\n if (evt.shiftKey) {\n if (sx === 1) {\n sx = sy;\n } else { sy = sx; }\n }\n scale.setScale(sx, sy);\n\n translateBack.setTranslate(left + tx, top + ty);\n if (hasMatrix) {\n const diff = angle ? 1 : 0;\n tlist.replaceItem(translateOrigin, 2 + diff);\n tlist.replaceItem(scale, 1 + diff);\n tlist.replaceItem(translateBack, Number(diff));\n } else {\n const N = tlist.numberOfItems;\n tlist.replaceItem(translateBack, N - 3);\n tlist.replaceItem(scale, N - 2);\n tlist.replaceItem(translateOrigin, N - 1);\n }\n\n selectorManager.requestSelector(selected).resize();\n\n call('transition', selectedElements);\n\n break;\n } case 'zoom': {\n realX *= currentZoom;\n realY *= currentZoom;\n assignAttributes(rubberBox, {\n x: Math.min(rStartX * currentZoom, realX),\n y: Math.min(rStartY * currentZoom, realY),\n width: Math.abs(realX - rStartX * currentZoom),\n height: Math.abs(realY - rStartY * currentZoom)\n }, 100);\n break;\n } case 'text': {\n assignAttributes(shape, {\n x,\n y\n }, 1000);\n break;\n } case 'line': {\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n }\n\n let x2 = x;\n let y2 = y;\n\n if (evt.shiftKey) {\n xya = snapToAngle(startX, startY, x2, y2);\n x2 = xya.x;\n y2 = xya.y;\n }\n\n shape.setAttribute('x2', x2);\n shape.setAttribute('y2', y2);\n break;\n } case 'foreignObject':\n // fall through\n case 'square':\n // fall through\n case 'rect':\n // fall through\n case 'image': {\n const square = (currentMode === 'square') || evt.shiftKey;\n let\n w = Math.abs(x - startX),\n h = Math.abs(y - startY);\n let newX, newY;\n if (square) {\n w = h = Math.max(w, h);\n newX = startX < x ? startX : startX - w;\n newY = startY < y ? startY : startY - h;\n } else {\n newX = Math.min(startX, x);\n newY = Math.min(startY, y);\n }\n\n if (curConfig.gridSnapping) {\n w = snapToGrid(w);\n h = snapToGrid(h);\n newX = snapToGrid(newX);\n newY = snapToGrid(newY);\n }\n\n assignAttributes(shape, {\n width: w,\n height: h,\n x: newX,\n y: newY\n }, 1000);\n\n break;\n } case 'circle': {\n c = $(shape).attr(['cx', 'cy']);\n ({cx, cy} = c);\n let rad = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));\n if (curConfig.gridSnapping) {\n rad = snapToGrid(rad);\n }\n shape.setAttribute('r', rad);\n break;\n } case 'ellipse': {\n c = $(shape).attr(['cx', 'cy']);\n ({cx, cy} = c);\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n cx = snapToGrid(cx);\n y = snapToGrid(y);\n cy = snapToGrid(cy);\n }\n shape.setAttribute('rx', Math.abs(x - cx));\n const ry = Math.abs(evt.shiftKey ? (x - cx) : (y - cy));\n shape.setAttribute('ry', ry);\n break;\n }\n case 'fhellipse':\n case 'fhrect': {\n freehand.minx = Math.min(realX, freehand.minx);\n freehand.maxx = Math.max(realX, freehand.maxx);\n freehand.miny = Math.min(realY, freehand.miny);\n freehand.maxy = Math.max(realY, freehand.maxy);\n }\n // Fallthrough\n case 'fhpath': {\n // dAttr += + realX + ',' + realY + ' ';\n // shape.setAttribute('points', dAttr);\n end.x = realX; end.y = realY;\n if (controllPoint2.x && controllPoint2.y) {\n for (i = 0; i < STEP_COUNT - 1; i++) {\n parameter = i / STEP_COUNT;\n nextParameter = (i + 1) / STEP_COUNT;\n bSpline = getBsplinePoint(nextParameter);\n nextPos = bSpline;\n bSpline = getBsplinePoint(parameter);\n sumDistance += Math.sqrt((nextPos.x - bSpline.x) * (nextPos.x - bSpline.x) + (nextPos.y - bSpline.y) * (nextPos.y - bSpline.y));\n if (sumDistance > THRESHOLD_DIST) {\n sumDistance -= THRESHOLD_DIST;\n\n // Faster than completely re-writing the points attribute.\n const point = svgcontent.createSVGPoint();\n point.x = bSpline.x;\n point.y = bSpline.y;\n shape.points.appendItem(point);\n }\n }\n }\n controllPoint2 = {x: controllPoint1.x, y: controllPoint1.y};\n controllPoint1 = {x: start.x, y: start.y};\n start = {x: end.x, y: end.y};\n break;\n // update path stretch line coordinates\n} case 'path':\n // fall through\n case 'pathedit': {\n x *= currentZoom;\n y *= currentZoom;\n\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n startX = snapToGrid(startX);\n startY = snapToGrid(startY);\n }\n if (evt.shiftKey) {\n const {path} = pathModule;\n let x1, y1;\n if (path) {\n x1 = path.dragging ? path.dragging[0] : startX;\n y1 = path.dragging ? path.dragging[1] : startY;\n } else {\n x1 = startX;\n y1 = startY;\n }\n xya = snapToAngle(x1, y1, x, y);\n ({x, y} = xya);\n }\n\n if (rubberBox && rubberBox.getAttribute('display') !== 'none') {\n realX *= currentZoom;\n realY *= currentZoom;\n assignAttributes(rubberBox, {\n x: Math.min(rStartX * currentZoom, realX),\n y: Math.min(rStartY * currentZoom, realY),\n width: Math.abs(realX - rStartX * currentZoom),\n height: Math.abs(realY - rStartY * currentZoom)\n }, 100);\n }\n pathActions.mouseMove(x, y);\n\n break;\n } case 'textedit': {\n x *= currentZoom;\n y *= currentZoom;\n // if (rubberBox && rubberBox.getAttribute('display') !== 'none') {\n // assignAttributes(rubberBox, {\n // x: Math.min(startX, x),\n // y: Math.min(startY, y),\n // width: Math.abs(x - startX),\n // height: Math.abs(y - startY)\n // }, 100);\n // }\n\n textActions.mouseMove(mouseX, mouseY);\n\n break;\n } case 'rotate': {\n box = utilsGetBBox(selected);\n cx = box.x + box.width / 2;\n cy = box.y + box.height / 2;\n const m = getMatrix(selected),\n center = transformPoint(cx, cy, m);\n cx = center.x;\n cy = center.y;\n angle = ((Math.atan2(cy - y, cx - x) * (180 / Math.PI)) - 90) % 360;\n if (curConfig.gridSnapping) {\n angle = snapToGrid(angle);\n }\n if (evt.shiftKey) { // restrict rotations to nice angles (WRS)\n const snap = 45;\n angle = Math.round(angle / snap) * snap;\n }\n\n canvas.setRotationAngle(angle < -180 ? (360 + angle) : angle, true);\n call('transition', selectedElements);\n break;\n } default:\n break;\n }\n\n /**\n * The mouse has moved on the canvas area.\n * @event module:svgcanvas.SvgCanvas#event:ext_mouseMove\n * @type {PlainObject}\n * @property {MouseEvent} event The event object\n * @property {Float} mouse_x x coordinate on canvas\n * @property {Float} mouse_y y coordinate on canvas\n * @property {Element} selected Refers to the first selected element\n */\n runExtensions('mouseMove', /** @type {module:svgcanvas.SvgCanvas#event:ext_mouseMove} */ {\n event: evt,\n mouse_x: mouseX,\n mouse_y: mouseY,\n selected\n });\n}; // mouseMove()\n\n// - in create mode, the element's opacity is set properly, we create an InsertElementCommand\n// and store it on the Undo stack\n// - in move/resize mode, the element's attributes which were affected by the move/resize are\n// identified, a ChangeElementCommand is created and stored on the stack for those attrs\n// this is done in when we recalculate the selected dimensions()\n/**\n *\n * @param {MouseEvent} evt\n * @fires module:svgcanvas.SvgCanvas#event:zoomed\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @fires module:svgcanvas.SvgCanvas#event:ext_mouseUp\n * @returns {void}\n */\nconst mouseUp = function (evt) {\n if (evt.button === 2) { return; }\n const tempJustSelected = justSelected;\n justSelected = null;\n if (!started) { return; }\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = pt.x * currentZoom,\n mouseY = pt.y * currentZoom,\n x = mouseX / currentZoom,\n y = mouseY / currentZoom;\n\n let element = getElem(getId());\n let keep = false;\n\n const realX = x;\n const realY = y;\n\n // TODO: Make true when in multi-unit mode\n const useUnit = false; // (curConfig.baseUnit !== 'px');\n started = false;\n let attrs, t;\n switch (currentMode) {\n // intentionally fall-through to select here\n case 'resize':\n case 'multiselect':\n if (!isNullish(rubberBox)) {\n rubberBox.setAttribute('display', 'none');\n curBBoxes = [];\n }\n currentMode = 'select';\n // Fallthrough\n case 'select':\n if (!isNullish(selectedElements[0])) {\n // if we only have one selected element\n if (isNullish(selectedElements[1])) {\n // set our current stroke/fill properties to the element's\n const selected = selectedElements[0];\n switch (selected.tagName) {\n case 'g':\n case 'use':\n case 'image':\n case 'foreignObject':\n break;\n default:\n curProperties.fill = selected.getAttribute('fill');\n curProperties.fill_opacity = selected.getAttribute('fill-opacity');\n curProperties.stroke = selected.getAttribute('stroke');\n curProperties.stroke_opacity = selected.getAttribute('stroke-opacity');\n curProperties.stroke_width = selected.getAttribute('stroke-width');\n curProperties.stroke_dasharray = selected.getAttribute('stroke-dasharray');\n curProperties.stroke_linejoin = selected.getAttribute('stroke-linejoin');\n curProperties.stroke_linecap = selected.getAttribute('stroke-linecap');\n }\n\n if (selected.tagName === 'text') {\n curText.font_size = selected.getAttribute('font-size');\n curText.font_family = selected.getAttribute('font-family');\n }\n selectorManager.requestSelector(selected).showGrips(true);\n\n // This shouldn't be necessary as it was done on mouseDown...\n // call('selected', [selected]);\n }\n // always recalculate dimensions to strip off stray identity transforms\n recalculateAllSelectedDimensions();\n // if it was being dragged/resized\n if (realX !== rStartX || realY !== rStartY) {\n const len = selectedElements.length;\n for (let i = 0; i < len; ++i) {\n if (isNullish(selectedElements[i])) { break; }\n if (!selectedElements[i].firstChild) {\n // Not needed for groups (incorrectly resizes elems), possibly not needed at all?\n selectorManager.requestSelector(selectedElements[i]).resize();\n }\n }\n // no change in position/size, so maybe we should move to pathedit\n } else {\n t = evt.target;\n if (selectedElements[0].nodeName === 'path' && isNullish(selectedElements[1])) {\n pathActions.select(selectedElements[0]);\n // if it was a path\n // else, if it was selected and this is a shift-click, remove it from selection\n } else if (evt.shiftKey) {\n if (tempJustSelected !== t) {\n canvas.removeFromSelection([t]);\n }\n }\n } // no change in mouse position\n\n // Remove non-scaling stroke\n if (supportsNonScalingStroke()) {\n const elem = selectedElements[0];\n if (elem) {\n elem.removeAttribute('style');\n walkTree(elem, function (el) {\n el.removeAttribute('style');\n });\n }\n }\n }\n return;\n case 'zoom': {\n if (!isNullish(rubberBox)) {\n rubberBox.setAttribute('display', 'none');\n }\n const factor = evt.shiftKey ? 0.5 : 2;\n call('zoomed', {\n x: Math.min(rStartX, realX),\n y: Math.min(rStartY, realY),\n width: Math.abs(realX - rStartX),\n height: Math.abs(realY - rStartY),\n factor\n });\n return;\n } case 'fhpath': {\n // Check that the path contains at least 2 points; a degenerate one-point path\n // causes problems.\n // Webkit ignores how we set the points attribute with commas and uses space\n // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870\n sumDistance = 0;\n controllPoint2 = {x: 0, y: 0};\n controllPoint1 = {x: 0, y: 0};\n start = {x: 0, y: 0};\n end = {x: 0, y: 0};\n const coords = element.getAttribute('points');\n const commaIndex = coords.indexOf(',');\n if (commaIndex >= 0) {\n keep = coords.includes(',', commaIndex + 1);\n } else {\n keep = coords.includes(' ', coords.indexOf(' ') + 1);\n }\n if (keep) {\n element = pathActions.smoothPolylineIntoPath(element);\n }\n break;\n } case 'line':\n attrs = $(element).attr(['x1', 'x2', 'y1', 'y2']);\n keep = (attrs.x1 !== attrs.x2 || attrs.y1 !== attrs.y2);\n break;\n case 'foreignObject':\n case 'square':\n case 'rect':\n case 'image':\n attrs = $(element).attr(['width', 'height']);\n // Image should be kept regardless of size (use inherit dimensions later)\n keep = (attrs.width || attrs.height) || currentMode === 'image';\n break;\n case 'circle':\n keep = (element.getAttribute('r') !== '0');\n break;\n case 'ellipse':\n attrs = $(element).attr(['rx', 'ry']);\n keep = (attrs.rx || attrs.ry);\n break;\n case 'fhellipse':\n if ((freehand.maxx - freehand.minx) > 0 &&\n (freehand.maxy - freehand.miny) > 0) {\n element = addSVGElementFromJson({\n element: 'ellipse',\n curStyles: true,\n attr: {\n cx: (freehand.minx + freehand.maxx) / 2,\n cy: (freehand.miny + freehand.maxy) / 2,\n rx: (freehand.maxx - freehand.minx) / 2,\n ry: (freehand.maxy - freehand.miny) / 2,\n id: getId()\n }\n });\n call('changed', [element]);\n keep = true;\n }\n break;\n case 'fhrect':\n if ((freehand.maxx - freehand.minx) > 0 &&\n (freehand.maxy - freehand.miny) > 0) {\n element = addSVGElementFromJson({\n element: 'rect',\n curStyles: true,\n attr: {\n x: freehand.minx,\n y: freehand.miny,\n width: (freehand.maxx - freehand.minx),\n height: (freehand.maxy - freehand.miny),\n id: getId()\n }\n });\n call('changed', [element]);\n keep = true;\n }\n break;\n case 'text':\n keep = true;\n selectOnly([element]);\n textActions.start(element);\n break;\n case 'path': {\n // set element to null here so that it is not removed nor finalized\n element = null;\n // continue to be set to true so that mouseMove happens\n started = true;\n\n const res = pathActions.mouseUp(evt, element, mouseX, mouseY);\n ({element} = res);\n ({keep} = res);\n break;\n } case 'pathedit':\n keep = true;\n element = null;\n pathActions.mouseUp(evt);\n break;\n case 'textedit':\n keep = false;\n element = null;\n textActions.mouseUp(evt, mouseX, mouseY);\n break;\n case 'rotate': {\n keep = true;\n element = null;\n currentMode = 'select';\n const batchCmd = canvas.undoMgr.finishUndoableChange();\n if (!batchCmd.isEmpty()) {\n addCommandToHistory(batchCmd);\n }\n // perform recalculation to weed out any stray identity transforms that might get stuck\n recalculateAllSelectedDimensions();\n call('changed', selectedElements);\n break;\n } default:\n // This could occur in an extension\n break;\n }\n\n /**\n * The main (left) mouse button is released (anywhere).\n * @event module:svgcanvas.SvgCanvas#event:ext_mouseUp\n * @type {PlainObject}\n * @property {MouseEvent} event The event object\n * @property {Float} mouse_x x coordinate on canvas\n * @property {Float} mouse_y y coordinate on canvas\n */\n const extResult = runExtensions('mouseUp', /** @type {module:svgcanvas.SvgCanvas#event:ext_mouseUp} */ {\n event: evt,\n mouse_x: mouseX,\n mouse_y: mouseY\n }, true);\n\n $.each(extResult, function (i, r) {\n if (r) {\n keep = r.keep || keep;\n ({element} = r);\n started = r.started || started;\n }\n });\n\n if (!keep && !isNullish(element)) {\n getCurrentDrawing().releaseId(getId());\n element.remove();\n element = null;\n\n t = evt.target;\n\n // if this element is in a group, go up until we reach the top-level group\n // just below the layer groups\n // TODO: once we implement links, we also would have to check for <a> elements\n while (t && t.parentNode && t.parentNode.parentNode && t.parentNode.parentNode.tagName === 'g') {\n t = t.parentNode;\n }\n // if we are not in the middle of creating a path, and we've clicked on some shape,\n // then go to Select mode.\n // WebKit returns <div> when the canvas is clicked, Firefox/Opera return <svg>\n if ((currentMode !== 'path' || !drawnPath) &&\n t && t.parentNode &&\n t.parentNode.id !== 'selectorParentGroup' &&\n t.id !== 'svgcanvas' && t.id !== 'svgroot'\n ) {\n // switch into \"select\" mode if we've clicked on an element\n canvas.setMode('select');\n selectOnly([t], true);\n }\n } else if (!isNullish(element)) {\n /**\n * @name module:svgcanvas.SvgCanvas#addedNew\n * @type {boolean}\n */\n canvas.addedNew = true;\n\n if (useUnit) { convertAttrs(element); }\n\n let aniDur = 0.2;\n let cAni;\n if (opacAni.beginElement && Number.parseFloat(element.getAttribute('opacity')) !== curShape.opacity) {\n cAni = $(opacAni).clone().attr({\n to: curShape.opacity,\n dur: aniDur\n }).appendTo(element);\n try {\n // Fails in FF4 on foreignObject\n cAni[0].beginElement();\n } catch (e) {}\n } else {\n aniDur = 0;\n }\n\n // Ideally this would be done on the endEvent of the animation,\n // but that doesn't seem to be supported in Webkit\n setTimeout(function () {\n if (cAni) { cAni.remove(); }\n element.setAttribute('opacity', curShape.opacity);\n element.setAttribute('style', 'pointer-events:inherit');\n cleanupElement(element);\n if (currentMode === 'path') {\n pathActions.toEditMode(element);\n } else if (curConfig.selectNew) {\n selectOnly([element], true);\n }\n // we create the insert command that is stored on the stack\n // undo means to call cmd.unapply(), redo means to call cmd.apply()\n addCommandToHistory(new InsertElementCommand(element));\n\n call('changed', [element]);\n }, aniDur * 1000);\n }\n\n startTransform = null;\n};\n\nconst dblClick = function (evt) {\n const evtTarget = evt.target;\n const parent = evtTarget.parentNode;\n\n let mouseTarget = getMouseTarget(evt);\n const {tagName} = mouseTarget;\n\n if (tagName === 'text' && currentMode !== 'textedit') {\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm);\n textActions.select(mouseTarget, pt.x, pt.y);\n }\n\n // Do nothing if already in current group\n if (parent === currentGroup) { return; }\n\n if ((tagName === 'g' || tagName === 'a') &&\n getRotationAngle(mouseTarget)\n ) {\n // TODO: Allow method of in-group editing without having to do\n // this (similar to editing rotated paths)\n\n // Ungroup and regroup\n pushGroupProperties(mouseTarget);\n mouseTarget = selectedElements[0];\n clearSelection(true);\n }\n // Reset context\n if (currentGroup) {\n draw.leaveContext();\n }\n\n if ((parent.tagName !== 'g' && parent.tagName !== 'a') ||\n parent === getCurrentDrawing().getCurrentLayer() ||\n mouseTarget === selectorManager.selectorParentGroup\n ) {\n // Escape from in-group edit\n return;\n }\n draw.setContext(mouseTarget);\n};\n\n// prevent links from being followed in the canvas\nconst handleLinkInCanvas = function (e) {\n e.preventDefault();\n return false;\n};\n\n// Added mouseup to the container here.\n// TODO(codedread): Figure out why after the Closure compiler, the window mouseup is ignored.\n$(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp);\n// $(window).mouseup(mouseUp);\n\n// TODO(rafaelcastrocouto): User preference for shift key and zoom factor\n$(container).bind(\n 'mousewheel DOMMouseScroll',\n /**\n * @param {Event} e\n * @fires module:svgcanvas.SvgCanvas#event:updateCanvas\n * @fires module:svgcanvas.SvgCanvas#event:zoomDone\n * @returns {void}\n */\n function (e) {\n if (!e.shiftKey) { return; }\n\n e.preventDefault();\n const evt = e.originalEvent;\n\n rootSctm = $('#svgcontent g')[0].getScreenCTM().inverse();\n\n const workarea = $('#workarea');\n const scrbar = 15;\n const rulerwidth = curConfig.showRulers ? 16 : 0;\n\n // mouse relative to content area in content pixels\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm);\n\n // full work area width in screen pixels\n const editorFullW = workarea.width();\n const editorFullH = workarea.height();\n\n // work area width minus scroll and ruler in screen pixels\n const editorW = editorFullW - scrbar - rulerwidth;\n const editorH = editorFullH - scrbar - rulerwidth;\n\n // work area width in content pixels\n const workareaViewW = editorW * rootSctm.a;\n const workareaViewH = editorH * rootSctm.d;\n\n // content offset from canvas in screen pixels\n const wOffset = workarea.offset();\n const wOffsetLeft = wOffset.left + rulerwidth;\n const wOffsetTop = wOffset.top + rulerwidth;\n\n const delta = (evt.wheelDelta) ? evt.wheelDelta : (evt.detail) ? -evt.detail : 0;\n if (!delta) { return; }\n\n let factor = Math.max(3 / 4, Math.min(4 / 3, (delta)));\n\n let wZoom, hZoom;\n if (factor > 1) {\n wZoom = Math.ceil(editorW / workareaViewW * factor * 100) / 100;\n hZoom = Math.ceil(editorH / workareaViewH * factor * 100) / 100;\n } else {\n wZoom = Math.floor(editorW / workareaViewW * factor * 100) / 100;\n hZoom = Math.floor(editorH / workareaViewH * factor * 100) / 100;\n }\n let zoomlevel = Math.min(wZoom, hZoom);\n zoomlevel = Math.min(10, Math.max(0.01, zoomlevel));\n if (zoomlevel === currentZoom) {\n return;\n }\n factor = zoomlevel / currentZoom;\n\n // top left of workarea in content pixels before zoom\n const topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, rootSctm);\n\n // top left of workarea in content pixels after zoom\n const topLeftNew = {\n x: pt.x - (pt.x - topLeftOld.x) / factor,\n y: pt.y - (pt.y - topLeftOld.y) / factor\n };\n\n // top left of workarea in canvas pixels relative to content after zoom\n const topLeftNewCanvas = {\n x: topLeftNew.x * zoomlevel,\n y: topLeftNew.y * zoomlevel\n };\n\n // new center in canvas pixels\n const newCtr = {\n x: topLeftNewCanvas.x - rulerwidth + editorFullW / 2,\n y: topLeftNewCanvas.y - rulerwidth + editorFullH / 2\n };\n\n canvas.setZoom(zoomlevel);\n $('#zoom').val((zoomlevel * 100).toFixed(1));\n\n call('updateCanvas', {center: false, newCtr});\n call('zoomDone');\n }\n);\n}());\n\n/* eslint-disable jsdoc/require-property */\n/**\n* Group: Text edit functions\n* Functions relating to editing text elements.\n* @namespace {PlainObject} textActions\n* @memberof module:svgcanvas.SvgCanvas#\n*/\nconst textActions = canvas.textActions = (function () {\n/* eslint-enable jsdoc/require-property */\nlet curtext;\nlet textinput;\nlet cursor;\nlet selblock;\nlet blinker;\nlet chardata = [];\nlet textbb; // , transbb;\nlet matrix;\nlet lastX, lastY;\nlet allowDbl;\n\n/**\n *\n * @param {Integer} index\n * @returns {void}\n */\nfunction setCursor (index) {\n const empty = (textinput.value === '');\n $(textinput).focus();\n\n if (!arguments.length) {\n if (empty) {\n index = 0;\n } else {\n if (textinput.selectionEnd !== textinput.selectionStart) { return; }\n index = textinput.selectionEnd;\n }\n }\n\n const charbb = chardata[index];\n if (!empty) {\n textinput.setSelectionRange(index, index);\n }\n cursor = getElem('text_cursor');\n if (!cursor) {\n cursor = document.createElementNS(NS.SVG, 'line');\n assignAttributes(cursor, {\n id: 'text_cursor',\n stroke: '#333',\n 'stroke-width': 1\n });\n cursor = getElem('selectorParentGroup').appendChild(cursor);\n }\n\n if (!blinker) {\n blinker = setInterval(function () {\n const show = (cursor.getAttribute('display') === 'none');\n cursor.setAttribute('display', show ? 'inline' : 'none');\n }, 600);\n }\n\n const startPt = ptToScreen(charbb.x, textbb.y);\n const endPt = ptToScreen(charbb.x, (textbb.y + textbb.height));\n\n assignAttributes(cursor, {\n x1: startPt.x,\n y1: startPt.y,\n x2: endPt.x,\n y2: endPt.y,\n visibility: 'visible',\n display: 'inline'\n });\n\n if (selblock) { selblock.setAttribute('d', ''); }\n}\n\n/**\n *\n * @param {Integer} start\n * @param {Integer} end\n * @param {boolean} skipInput\n * @returns {void}\n */\nfunction setSelection (start, end, skipInput) {\n if (start === end) {\n setCursor(end);\n return;\n }\n\n if (!skipInput) {\n textinput.setSelectionRange(start, end);\n }\n\n selblock = getElem('text_selectblock');\n if (!selblock) {\n selblock = document.createElementNS(NS.SVG, 'path');\n assignAttributes(selblock, {\n id: 'text_selectblock',\n fill: 'green',\n opacity: 0.5,\n style: 'pointer-events:none'\n });\n getElem('selectorParentGroup').append(selblock);\n }\n\n const startbb = chardata[start];\n const endbb = chardata[end];\n\n cursor.setAttribute('visibility', 'hidden');\n\n const tl = ptToScreen(startbb.x, textbb.y),\n tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y),\n bl = ptToScreen(startbb.x, textbb.y + textbb.height),\n br = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y + textbb.height);\n\n const dstr = 'M' + tl.x + ',' + tl.y +\n ' L' + tr.x + ',' + tr.y +\n ' ' + br.x + ',' + br.y +\n ' ' + bl.x + ',' + bl.y + 'z';\n\n assignAttributes(selblock, {\n d: dstr,\n display: 'inline'\n });\n}\n\n/**\n *\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {Integer}\n */\nfunction getIndexFromPoint (mouseX, mouseY) {\n // Position cursor here\n const pt = svgroot.createSVGPoint();\n pt.x = mouseX;\n pt.y = mouseY;\n\n // No content, so return 0\n if (chardata.length === 1) { return 0; }\n // Determine if cursor should be on left or right of character\n let charpos = curtext.getCharNumAtPosition(pt);\n if (charpos < 0) {\n // Out of text range, look at mouse coords\n charpos = chardata.length - 2;\n if (mouseX <= chardata[0].x) {\n charpos = 0;\n }\n } else if (charpos >= chardata.length - 2) {\n charpos = chardata.length - 2;\n }\n const charbb = chardata[charpos];\n const mid = charbb.x + (charbb.width / 2);\n if (mouseX > mid) {\n charpos++;\n }\n return charpos;\n}\n\n/**\n *\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\nfunction setCursorFromPoint (mouseX, mouseY) {\n setCursor(getIndexFromPoint(mouseX, mouseY));\n}\n\n/**\n *\n * @param {Float} x\n * @param {Float} y\n * @param {boolean} apply\n * @returns {void}\n */\nfunction setEndSelectionFromPoint (x, y, apply) {\n const i1 = textinput.selectionStart;\n const i2 = getIndexFromPoint(x, y);\n\n const start = Math.min(i1, i2);\n const end = Math.max(i1, i2);\n setSelection(start, end, !apply);\n}\n\n/**\n *\n * @param {Float} xIn\n * @param {Float} yIn\n * @returns {module:math.XYObject}\n */\nfunction screenToPt (xIn, yIn) {\n const out = {\n x: xIn,\n y: yIn\n };\n\n out.x /= currentZoom;\n out.y /= currentZoom;\n\n if (matrix) {\n const pt = transformPoint(out.x, out.y, matrix.inverse());\n out.x = pt.x;\n out.y = pt.y;\n }\n\n return out;\n}\n\n/**\n *\n * @param {Float} xIn\n * @param {Float} yIn\n * @returns {module:math.XYObject}\n */\nfunction ptToScreen (xIn, yIn) {\n const out = {\n x: xIn,\n y: yIn\n };\n\n if (matrix) {\n const pt = transformPoint(out.x, out.y, matrix);\n out.x = pt.x;\n out.y = pt.y;\n }\n\n out.x *= currentZoom;\n out.y *= currentZoom;\n\n return out;\n}\n\n/*\n// Not currently in use\nfunction hideCursor () {\n if (cursor) {\n cursor.setAttribute('visibility', 'hidden');\n }\n}\n*/\n\n/**\n *\n * @param {Event} evt\n * @returns {void}\n */\nfunction selectAll (evt) {\n setSelection(0, curtext.textContent.length);\n $(this).unbind(evt);\n}\n\n/**\n *\n * @param {Event} evt\n * @returns {void}\n */\nfunction selectWord (evt) {\n if (!allowDbl || !curtext) { return; }\n\n const ept = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = ept.x * currentZoom,\n mouseY = ept.y * currentZoom;\n const pt = screenToPt(mouseX, mouseY);\n\n const index = getIndexFromPoint(pt.x, pt.y);\n const str = curtext.textContent;\n const first = str.substr(0, index).replace(/[a-z\\d]+$/i, '').length;\n const m = str.substr(index).match(/^[a-z\\d]+/i);\n const last = (m ? m[0].length : 0) + index;\n setSelection(first, last);\n\n // Set tripleclick\n $(evt.target).click(selectAll);\n setTimeout(function () {\n $(evt.target).unbind('click', selectAll);\n }, 300);\n}\n\nreturn /** @lends module:svgcanvas.SvgCanvas#textActions */ {\n /**\n * @param {Element} target\n * @param {Float} x\n * @param {Float} y\n * @returns {void}\n */\n select (target, x, y) {\n curtext = target;\n textActions.toEditMode(x, y);\n },\n /**\n * @param {Element} elem\n * @returns {void}\n */\n start (elem) {\n curtext = elem;\n textActions.toEditMode();\n },\n /**\n * @param {external:MouseEvent} evt\n * @param {Element} mouseTarget\n * @param {Float} startX\n * @param {Float} startY\n * @returns {void}\n */\n mouseDown (evt, mouseTarget, startX, startY) {\n const pt = screenToPt(startX, startY);\n\n textinput.focus();\n setCursorFromPoint(pt.x, pt.y);\n lastX = startX;\n lastY = startY;\n\n // TODO: Find way to block native selection\n },\n /**\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\n mouseMove (mouseX, mouseY) {\n const pt = screenToPt(mouseX, mouseY);\n setEndSelectionFromPoint(pt.x, pt.y);\n },\n /**\n * @param {external:MouseEvent} evt\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\n mouseUp (evt, mouseX, mouseY) {\n const pt = screenToPt(mouseX, mouseY);\n\n setEndSelectionFromPoint(pt.x, pt.y, true);\n\n // TODO: Find a way to make this work: Use transformed BBox instead of evt.target\n // if (lastX === mouseX && lastY === mouseY\n // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) {\n // textActions.toSelectMode(true);\n // }\n\n if (\n evt.target !== curtext &&\n mouseX < lastX + 2 &&\n mouseX > lastX - 2 &&\n mouseY < lastY + 2 &&\n mouseY > lastY - 2\n ) {\n textActions.toSelectMode(true);\n }\n },\n /**\n * @function\n * @param {Integer} index\n * @returns {void}\n */\n setCursor,\n /**\n * @param {Float} x\n * @param {Float} y\n * @returns {void}\n */\n toEditMode (x, y) {\n allowDbl = false;\n currentMode = 'textedit';\n selectorManager.requestSelector(curtext).showGrips(false);\n // Make selector group accept clicks\n /* const selector = */ selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used\n // const sel = selector.selectorRect;\n\n textActions.init();\n\n $(curtext).css('cursor', 'text');\n\n // if (supportsEditableText()) {\n // curtext.setAttribute('editable', 'simple');\n // return;\n // }\n\n if (!arguments.length) {\n setCursor();\n } else {\n const pt = screenToPt(x, y);\n setCursorFromPoint(pt.x, pt.y);\n }\n\n setTimeout(function () {\n allowDbl = true;\n }, 300);\n },\n /**\n * @param {boolean|Element} selectElem\n * @fires module:svgcanvas.SvgCanvas#event:selected\n * @returns {void}\n */\n toSelectMode (selectElem) {\n currentMode = 'select';\n clearInterval(blinker);\n blinker = null;\n if (selblock) { $(selblock).attr('display', 'none'); }\n if (cursor) { $(cursor).attr('visibility', 'hidden'); }\n $(curtext).css('cursor', 'move');\n\n if (selectElem) {\n clearSelection();\n $(curtext).css('cursor', 'move');\n\n call('selected', [curtext]);\n addToSelection([curtext], true);\n }\n if (curtext && !curtext.textContent.length) {\n // No content, so delete\n canvas.deleteSelectedElements();\n }\n\n $(textinput).blur();\n\n curtext = false;\n\n // if (supportsEditableText()) {\n // curtext.removeAttribute('editable');\n // }\n },\n /**\n * @param {Element} elem\n * @returns {void}\n */\n setInputElem (elem) {\n textinput = elem;\n // $(textinput).blur(hideCursor);\n },\n /**\n * @returns {void}\n */\n clear () {\n if (currentMode === 'textedit') {\n textActions.toSelectMode();\n }\n },\n /**\n * @param {Element} inputElem Not in use\n * @returns {void}\n */\n init (inputElem) {\n if (!curtext) { return; }\n let i, end;\n // if (supportsEditableText()) {\n // curtext.select();\n // return;\n // }\n\n if (!curtext.parentNode) {\n // Result of the ffClone, need to get correct element\n curtext = selectedElements[0];\n selectorManager.requestSelector(curtext).showGrips(false);\n }\n\n const str = curtext.textContent;\n const len = str.length;\n\n const xform = curtext.getAttribute('transform');\n\n textbb = utilsGetBBox(curtext);\n\n matrix = xform ? getMatrix(curtext) : null;\n\n chardata = [];\n chardata.length = len;\n textinput.focus();\n\n $(curtext).unbind('dblclick', selectWord).dblclick(selectWord);\n\n if (!len) {\n end = {x: textbb.x + (textbb.width / 2), width: 0};\n }\n\n for (i = 0; i < len; i++) {\n const start = curtext.getStartPositionOfChar(i);\n end = curtext.getEndPositionOfChar(i);\n\n if (!supportsGoodTextCharPos()) {\n const offset = canvas.contentW * currentZoom;\n start.x -= offset;\n end.x -= offset;\n\n start.x /= currentZoom;\n end.x /= currentZoom;\n }\n\n // Get a \"bbox\" equivalent for each character. Uses the\n // bbox data of the actual text for y, height purposes\n\n // TODO: Decide if y, width and height are actually necessary\n chardata[i] = {\n x: start.x,\n y: textbb.y, // start.y?\n width: end.x - start.x,\n height: textbb.height\n };\n }\n\n // Add a last bbox for cursor at end of text\n chardata.push({\n x: end.x,\n width: 0\n });\n setSelection(textinput.selectionStart, textinput.selectionEnd, true);\n }\n};\n}());\n\n/**\n* Group: Serialization.\n*/\n\n/**\n* Looks at DOM elements inside the `<defs>` to see if they are referred to,\n* removes them from the DOM if they are not.\n* @function module:svgcanvas.SvgCanvas#removeUnusedDefElems\n* @returns {Integer} The number of elements that were removed\n*/\nconst removeUnusedDefElems = this.removeUnusedDefElems = function () {\n const defs = svgcontent.getElementsByTagNameNS(NS.SVG, 'defs');\n if (!defs || !defs.length) { return 0; }\n\n // if (!defs.firstChild) { return; }\n\n const defelemUses = [];\n let numRemoved = 0;\n const attrs = ['fill', 'stroke', 'filter', 'marker-start', 'marker-mid', 'marker-end'];\n const alen = attrs.length;\n\n const allEls = svgcontent.getElementsByTagNameNS(NS.SVG, '*');\n const allLen = allEls.length;\n\n let i, j;\n for (i = 0; i < allLen; i++) {\n const el = allEls[i];\n for (j = 0; j < alen; j++) {\n const ref = getUrlFromAttr(el.getAttribute(attrs[j]));\n if (ref) {\n defelemUses.push(ref.substr(1));\n }\n }\n\n // gradients can refer to other gradients\n const href = getHref(el);\n if (href && href.startsWith('#')) {\n defelemUses.push(href.substr(1));\n }\n }\n\n const defelems = $(defs).find('linearGradient, radialGradient, filter, marker, svg, symbol');\n i = defelems.length;\n while (i--) {\n const defelem = defelems[i];\n const {id} = defelem;\n if (!defelemUses.includes(id)) {\n // Not found, so remove (but remember)\n removedElements[id] = defelem;\n defelem.remove();\n numRemoved++;\n }\n }\n\n return numRemoved;\n};\n\n/**\n* Main function to set up the SVG content for output.\n* @function module:svgcanvas.SvgCanvas#svgCanvasToString\n* @returns {string} The SVG image for output\n*/\nthis.svgCanvasToString = function () {\n // keep calling it until there are none to remove\n while (removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty\n\n pathActions.clear(true);\n\n // Keep SVG-Edit comment on top\n $.each(svgcontent.childNodes, function (i, node) {\n if (i && node.nodeType === 8 && node.data.includes('Created with')) {\n svgcontent.firstChild.before(node);\n }\n });\n\n // Move out of in-group editing mode\n if (currentGroup) {\n draw.leaveContext();\n selectOnly([currentGroup]);\n }\n\n const nakedSvgs = [];\n\n // Unwrap gsvg if it has no special attributes (only id and style)\n $(svgcontent).find('g:data(gsvg)').each(function () {\n const attrs = this.attributes;\n let len = attrs.length;\n for (let i = 0; i < len; i++) {\n if (attrs[i].nodeName === 'id' || attrs[i].nodeName === 'style') {\n len--;\n }\n }\n // No significant attributes, so ungroup\n if (len <= 0) {\n const svg = this.firstChild;\n nakedSvgs.push(svg);\n $(this).replaceWith(svg);\n }\n });\n const output = this.svgToString(svgcontent, 0);\n\n // Rewrap gsvg\n if (nakedSvgs.length) {\n $(nakedSvgs).each(function () {\n groupSvgElem(this);\n });\n }\n\n return output;\n};\n\n/**\n* Sub function ran on each SVG element to convert it to a string as desired.\n* @function module:svgcanvas.SvgCanvas#svgToString\n* @param {Element} elem - The SVG element to convert\n* @param {Integer} indent - Number of spaces to indent this tag\n* @returns {string} The given element as an SVG tag\n*/\nthis.svgToString = function (elem, indent) {\n const out = [];\n const unit = curConfig.baseUnit;\n const unitRe = new RegExp('^-?[\\\\d\\\\.]+' + unit + '$');\n\n if (elem) {\n cleanupElement(elem);\n const attrs = [...elem.attributes];\n const childs = elem.childNodes;\n attrs.sort((a, b) => {\n return a.name > b.name ? -1 : 1;\n });\n\n for (let i = 0; i < indent; i++) { out.push(' '); }\n out.push('<'); out.push(elem.nodeName);\n if (elem.id === 'svgcontent') {\n // Process root element separately\n const res = getResolution();\n\n const vb = '';\n // TODO: Allow this by dividing all values by current baseVal\n // Note that this also means we should properly deal with this on import\n // if (curConfig.baseUnit !== 'px') {\n // const unit = curConfig.baseUnit;\n // const unitM = getTypeMap()[unit];\n // res.w = shortFloat(res.w / unitM);\n // res.h = shortFloat(res.h / unitM);\n // vb = ' viewBox=\"' + [0, 0, res.w, res.h].join(' ') + '\"';\n // res.w += unit;\n // res.h += unit;\n // }\n\n if (unit !== 'px') {\n res.w = convertUnit(res.w, unit) + unit;\n res.h = convertUnit(res.h, unit) + unit;\n }\n\n out.push(' width=\"' + res.w + '\" height=\"' + res.h + '\"' + vb + ' xmlns=\"' + NS.SVG + '\"');\n\n const nsuris = {};\n\n // Check elements for namespaces, add if found\n $(elem).find('*').andSelf().each(function () {\n // const el = this;\n // for some elements have no attribute\n const uri = this.namespaceURI;\n if (uri && !nsuris[uri] && nsMap[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') {\n nsuris[uri] = true;\n out.push(' xmlns:' + nsMap[uri] + '=\"' + uri + '\"');\n }\n\n $.each(this.attributes, function (i, attr) {\n const u = attr.namespaceURI;\n if (u && !nsuris[u] && nsMap[u] !== 'xmlns' && nsMap[u] !== 'xml') {\n nsuris[u] = true;\n out.push(' xmlns:' + nsMap[u] + '=\"' + u + '\"');\n }\n });\n });\n\n let i = attrs.length;\n const attrNames = ['width', 'height', 'xmlns', 'x', 'y', 'viewBox', 'id', 'overflow'];\n while (i--) {\n const attr = attrs[i];\n const attrVal = toXml(attr.value);\n\n // Namespaces have already been dealt with, so skip\n if (attr.nodeName.startsWith('xmlns:')) { continue; }\n\n // only serialize attributes we don't use internally\n if (attrVal !== '' && !attrNames.includes(attr.localName)) {\n if (!attr.namespaceURI || nsMap[attr.namespaceURI]) {\n out.push(' ');\n out.push(attr.nodeName); out.push('=\"');\n out.push(attrVal); out.push('\"');\n }\n }\n }\n } else {\n // Skip empty defs\n if (elem.nodeName === 'defs' && !elem.firstChild) { return ''; }\n\n const mozAttrs = ['-moz-math-font-style', '_moz-math-font-style'];\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attr = attrs[i];\n let attrVal = toXml(attr.value);\n // remove bogus attributes added by Gecko\n if (mozAttrs.includes(attr.localName)) { continue; }\n if (attrVal === 'null') {\n const styleName = attr.localName.replace(/-[a-z]/g, (s) => s[1].toUpperCase());\n if (Object.prototype.hasOwnProperty.call(elem.style, styleName)) { continue; }\n }\n if (attrVal !== '') {\n if (attrVal.startsWith('pointer-events')) { continue; }\n if (attr.localName === 'class' && attrVal.startsWith('se_')) { continue; }\n out.push(' ');\n if (attr.localName === 'd') { attrVal = pathActions.convertPath(elem, true); }\n if (!isNaN(attrVal)) {\n attrVal = shortFloat(attrVal);\n } else if (unitRe.test(attrVal)) {\n attrVal = shortFloat(attrVal) + unit;\n }\n\n // Embed images when saving\n if (saveOptions.apply &&\n elem.nodeName === 'image' &&\n attr.localName === 'href' &&\n saveOptions.images &&\n saveOptions.images === 'embed'\n ) {\n const img = encodableImages[attrVal];\n if (img) { attrVal = img; }\n }\n\n // map various namespaces to our fixed namespace prefixes\n // (the default xmlns attribute itself does not get a prefix)\n if (!attr.namespaceURI || attr.namespaceURI === NS.SVG || nsMap[attr.namespaceURI]) {\n out.push(attr.nodeName); out.push('=\"');\n out.push(attrVal); out.push('\"');\n }\n }\n }\n }\n\n if (elem.hasChildNodes()) {\n out.push('>');\n indent++;\n let bOneLine = false;\n\n for (let i = 0; i < childs.length; i++) {\n const child = childs.item(i);\n switch (child.nodeType) {\n case 1: // element node\n out.push('\\n');\n out.push(this.svgToString(child, indent));\n break;\n case 3: { // text node\n const str = child.nodeValue.replace(/^\\s+|\\s+$/g, '');\n if (str !== '') {\n bOneLine = true;\n out.push(String(toXml(str)));\n }\n break;\n } case 4: // cdata node\n out.push('\\n');\n out.push(new Array(indent + 1).join(' '));\n out.push('<![CDATA[');\n out.push(child.nodeValue);\n out.push(']]>');\n break;\n case 8: // comment\n out.push('\\n');\n out.push(new Array(indent + 1).join(' '));\n out.push('<!--');\n out.push(child.data);\n out.push('-->');\n break;\n } // switch on node type\n }\n indent--;\n if (!bOneLine) {\n out.push('\\n');\n for (let i = 0; i < indent; i++) { out.push(' '); }\n }\n out.push('</'); out.push(elem.nodeName); out.push('>');\n } else {\n out.push('/>');\n }\n }\n return out.join('');\n}; // end svgToString()\n\n/**\n * Function to run when image data is found.\n * @callback module:svgcanvas.ImageEmbeddedCallback\n * @param {string|false} result Data URL\n * @returns {void}\n */\n/**\n* Converts a given image file to a data URL when possible, then runs a given callback.\n* @function module:svgcanvas.SvgCanvas#embedImage\n* @param {string} src - The path/URL of the image\n* @returns {Promise<string|false>} Resolves to a Data URL (string|false)\n*/\nthis.embedImage = function (src) {\n // Todo: Remove this Promise in favor of making an async/await `Image.load` utility\n return new Promise(function (resolve, reject) { // eslint-disable-line promise/avoid-new\n // load in the image and once it's loaded, get the dimensions\n $(new Image()).load(function (response, status, xhr) {\n if (status === 'error') {\n reject(new Error('Error loading image: ' + xhr.status + ' ' + xhr.statusText));\n return;\n }\n // create a canvas the same size as the raster image\n const cvs = document.createElement('canvas');\n cvs.width = this.width;\n cvs.height = this.height;\n // load the raster image into the canvas\n cvs.getContext('2d').drawImage(this, 0, 0);\n // retrieve the data: URL\n try {\n let urldata = ';svgedit_url=' + encodeURIComponent(src);\n urldata = cvs.toDataURL().replace(';base64', urldata + ';base64');\n encodableImages[src] = urldata;\n } catch (e) {\n encodableImages[src] = false;\n }\n lastGoodImgUrl = src;\n resolve(encodableImages[src]);\n }).attr('src', src);\n });\n};\n\n/**\n* Sets a given URL to be a \"last good image\" URL.\n* @function module:svgcanvas.SvgCanvas#setGoodImage\n* @param {string} val\n* @returns {void}\n*/\nthis.setGoodImage = function (val) {\n lastGoodImgUrl = val;\n};\n\n/**\n* Does nothing by default, handled by optional widget/extension.\n* @function module:svgcanvas.SvgCanvas#open\n* @returns {void}\n*/\nthis.open = function () {\n /* */\n};\n\n/**\n* Serializes the current drawing into SVG XML text and passes it to the 'saved' handler.\n* This function also includes the XML prolog. Clients of the `SvgCanvas` bind their save\n* function to the 'saved' event.\n* @function module:svgcanvas.SvgCanvas#save\n* @param {module:svgcanvas.SaveOptions} opts\n* @fires module:svgcanvas.SvgCanvas#event:saved\n* @returns {void}\n*/\nthis.save = function (opts) {\n // remove the selected outline before serializing\n clearSelection();\n // Update save options if provided\n if (opts) { $.extend(saveOptions, opts); }\n saveOptions.apply = true;\n\n // no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration\n const str = this.svgCanvasToString();\n call('saved', str);\n};\n\n/**\n* @typedef {PlainObject} module:svgcanvas.IssuesAndCodes\n* @property {string[]} issueCodes The locale-independent code names\n* @property {string[]} issues The localized descriptions\n*/\n\n/**\n* Codes only is useful for locale-independent detection.\n* @returns {module:svgcanvas.IssuesAndCodes}\n*/\nfunction getIssues () {\n // remove the selected outline before serializing\n clearSelection();\n\n // Check for known CanVG issues\n const issues = [];\n const issueCodes = [];\n\n // Selector and notice\n const issueList = {\n feGaussianBlur: uiStrings.exportNoBlur,\n foreignObject: uiStrings.exportNoforeignObject,\n '[stroke-dasharray]': uiStrings.exportNoDashArray\n };\n const content = $(svgcontent);\n\n // Add font/text check if Canvas Text API is not implemented\n if (!('font' in $('<canvas>')[0].getContext('2d'))) {\n issueList.text = uiStrings.exportNoText;\n }\n\n $.each(issueList, function (sel, descr) {\n if (content.find(sel).length) {\n issueCodes.push(sel);\n issues.push(descr);\n }\n });\n return {issues, issueCodes};\n}\n\nlet canvg;\n/**\n* @typedef {\"feGaussianBlur\"|\"foreignObject\"|\"[stroke-dasharray]\"|\"text\"} module:svgcanvas.IssueCode\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ImageExportedResults\n* @property {string} datauri Contents as a Data URL\n* @property {string} bloburl May be the empty string\n* @property {string} svg The SVG contents as a string\n* @property {string[]} issues The localization messages of `issueCodes`\n* @property {module:svgcanvas.IssueCode[]} issueCodes CanVG issues found with the SVG\n* @property {\"PNG\"|\"JPEG\"|\"BMP\"|\"WEBP\"|\"ICO\"} type The chosen image type\n* @property {\"image/png\"|\"image/jpeg\"|\"image/bmp\"|\"image/webp\"} mimeType The image MIME type\n* @property {Float} quality A decimal between 0 and 1 (for use with JPEG or WEBP)\n* @property {string} exportWindowName A convenience for passing along a `window.name` to target a window on which the export could be added\n*/\n\n/**\n* Generates a PNG (or JPG, BMP, WEBP) Data URL based on the current image,\n* then calls \"exported\" with an object including the string, image\n* information, and any issues found.\n* @function module:svgcanvas.SvgCanvas#rasterExport\n* @param {\"PNG\"|\"JPEG\"|\"BMP\"|\"WEBP\"|\"ICO\"} [imgType=\"PNG\"]\n* @param {Float} [quality] Between 0 and 1\n* @param {string} [exportWindowName]\n* @param {PlainObject} [opts]\n* @param {boolean} [opts.avoidEvent]\n* @fires module:svgcanvas.SvgCanvas#event:exported\n* @todo Confirm/fix ICO type\n* @returns {Promise<module:svgcanvas.ImageExportedResults>} Resolves to {@link module:svgcanvas.ImageExportedResults}\n*/\nthis.rasterExport = async function (imgType, quality, exportWindowName, opts = {}) {\n const type = imgType === 'ICO' ? 'BMP' : (imgType || 'PNG');\n const mimeType = 'image/' + type.toLowerCase();\n const {issues, issueCodes} = getIssues();\n const svg = this.svgCanvasToString();\n\n if (!canvg) {\n ({canvg} = await importSetGlobal(curConfig.canvgPath + 'canvg.js', {\n global: 'canvg'\n }));\n }\n if (!$('#export_canvas').length) {\n $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');\n }\n const c = $('#export_canvas')[0];\n c.width = canvas.contentW;\n c.height = canvas.contentH;\n\n await canvg(c, svg);\n // Todo: Make async/await utility in place of `toBlob`, so we can remove this constructor\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n const dataURLType = type.toLowerCase();\n const datauri = quality\n ? c.toDataURL('image/' + dataURLType, quality)\n : c.toDataURL('image/' + dataURLType);\n let bloburl;\n /**\n * Called when `bloburl` is available for export.\n * @returns {void}\n */\n function done () {\n const obj = {\n datauri, bloburl, svg, issues, issueCodes, type: imgType,\n mimeType, quality, exportWindowName\n };\n if (!opts.avoidEvent) {\n call('exported', obj);\n }\n resolve(obj);\n }\n if (c.toBlob) {\n c.toBlob((blob) => {\n bloburl = createObjectURL(blob);\n done();\n }, mimeType, quality);\n return;\n }\n bloburl = dataURLToObjectURL(datauri);\n done();\n });\n};\n/**\n * @external jsPDF\n */\n/**\n * @typedef {void|\"save\"|\"arraybuffer\"|\"blob\"|\"datauristring\"|\"dataurlstring\"|\"dataurlnewwindow\"|\"datauri\"|\"dataurl\"} external:jsPDF.OutputType\n * @todo Newer version to add also allows these `outputType` values \"bloburi\"|\"bloburl\" which return strings, so document here and for `outputType` of `module:svgcanvas.PDFExportedResults` below if added\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.PDFExportedResults\n* @property {string} svg The SVG PDF output\n* @property {string|ArrayBuffer|Blob|window} output The output based on the `outputType`;\n* if `undefined`, \"datauristring\", \"dataurlstring\", \"datauri\",\n* or \"dataurl\", will be a string (`undefined` gives a document, while the others\n* build as Data URLs; \"datauri\" and \"dataurl\" change the location of the current page); if\n* \"arraybuffer\", will return `ArrayBuffer`; if \"blob\", returns a `Blob`;\n* if \"dataurlnewwindow\", will change the current page's location and return a string\n* if in Safari and no window object is found; otherwise opens in, and returns, a new `window`\n* object; if \"save\", will have the same return as \"dataurlnewwindow\" if\n* `navigator.getUserMedia` support is found without `URL.createObjectURL` support; otherwise\n* returns `undefined` but attempts to save\n* @property {external:jsPDF.OutputType} outputType\n* @property {string[]} issues The human-readable localization messages of corresponding `issueCodes`\n* @property {module:svgcanvas.IssueCode[]} issueCodes\n* @property {string} exportWindowName\n*/\n\n/**\n* Generates a PDF based on the current image, then calls \"exportedPDF\" with\n* an object including the string, the data URL, and any issues found.\n* @function module:svgcanvas.SvgCanvas#exportPDF\n* @param {string} [exportWindowName] Will also be used for the download file name here\n* @param {external:jsPDF.OutputType} [outputType=\"dataurlstring\"]\n* @fires module:svgcanvas.SvgCanvas#event:exportedPDF\n* @returns {Promise<module:svgcanvas.PDFExportedResults>} Resolves to {@link module:svgcanvas.PDFExportedResults}\n*/\nthis.exportPDF = async function (\n exportWindowName,\n outputType = isChrome() ? 'save' : undefined\n) {\n if (!window.jsPDF) {\n // Todo: Switch to `import()` when widely supported and available (also allow customization of path)\n await importScript([\n // We do not currently have these paths configurable as they are\n // currently global-only, so not Rolled-up\n 'jspdf/underscore-min.js',\n // 'jspdf/jspdf.min.js',\n '../../svgedit-myfix/editor/jspdf/jspdf-1.0.150.debug.js'\n ]);\n\n const modularVersion = !('svgEditor' in window) ||\n !window.svgEditor ||\n window.svgEditor.modules !== false;\n // Todo: Switch to `import()` when widely supported and available (also allow customization of path)\n await importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', {\n type: modularVersion\n ? 'module'\n : 'text/javascript'\n });\n // await importModule('jspdf/jspdf.plugin.svgToPdf.js');\n }\n\n const res = getResolution();\n const orientation = res.w > res.h ? 'landscape' : 'portrait';\n const unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes\n\n // Todo: Give options to use predefined jsPDF formats like \"a4\", etc. from pull-down (with option to keep customizable)\n const doc = jsPDF({\n orientation,\n unit,\n format: [res.w, res.h]\n // , compressPdf: true\n });\n const docTitle = getDocumentTitle();\n doc.setProperties({\n title: docTitle /* ,\n subject: '',\n author: '',\n keywords: '',\n creator: '' */\n });\n const {issues, issueCodes} = getIssues();\n const svg = this.svgCanvasToString();\n doc.addSVG(svg, 0, 0);\n\n // doc.output('save'); // Works to open in a new\n // window; todo: configure this and other export\n // options to optionally work in this manner as\n // opposed to opening a new tab\n outputType = outputType || 'dataurlstring';\n const obj = {svg, issues, issueCodes, exportWindowName, outputType};\n obj.output = doc.output(outputType, outputType === 'save' ? (exportWindowName || 'svg.pdf') : undefined);\n call('exportedPDF', obj);\n return obj;\n};\n\n/**\n* Returns the current drawing as raw SVG XML text.\n* @function module:svgcanvas.SvgCanvas#getSvgString\n* @returns {string} The current drawing as raw SVG XML text.\n*/\nthis.getSvgString = function () {\n saveOptions.apply = false;\n return this.svgCanvasToString();\n};\n\n/**\n* This function determines whether to use a nonce in the prefix, when\n* generating IDs for future documents in SVG-Edit.\n* If you're controlling SVG-Edit externally, and want randomized IDs, call\n* this BEFORE calling `svgCanvas.setSvgString`.\n* @function module:svgcanvas.SvgCanvas#randomizeIds\n* @param {boolean} [enableRandomization] If true, adds a nonce to the prefix. Thus\n* `svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true)`\n* @returns {void}\n*/\nthis.randomizeIds = function (enableRandomization) {\n if (arguments.length > 0 && enableRandomization === false) {\n draw.randomizeIds(false, getCurrentDrawing());\n } else {\n draw.randomizeIds(true, getCurrentDrawing());\n }\n};\n\n/**\n* Ensure each element has a unique ID.\n* @function module:svgcanvas.SvgCanvas#uniquifyElems\n* @param {Element} g - The parent element of the tree to give unique IDs\n* @returns {void}\n*/\nconst uniquifyElems = this.uniquifyElems = function (g) {\n const ids = {};\n // TODO: Handle markers and connectors. These are not yet re-identified properly\n // as their referring elements do not get remapped.\n //\n // <marker id='se_marker_end_svg_7'/>\n // <polyline id='svg_7' se:connector='svg_1 svg_6' marker-end='url(#se_marker_end_svg_7)'/>\n //\n // Problem #1: if svg_1 gets renamed, we do not update the polyline's se:connector attribute\n // Problem #2: if the polyline svg_7 gets renamed, we do not update the marker id nor the polyline's marker-end attribute\n const refElems = ['filter', 'linearGradient', 'pattern', 'radialGradient', 'symbol', 'textPath', 'use'];\n\n walkTree(g, function (n) {\n // if it's an element node\n if (n.nodeType === 1) {\n // and the element has an ID\n if (n.id) {\n // and we haven't tracked this ID yet\n if (!(n.id in ids)) {\n // add this id to our map\n ids[n.id] = {elem: null, attrs: [], hrefs: []};\n }\n ids[n.id].elem = n;\n }\n\n // now search for all attributes on this element that might refer\n // to other elements\n $.each(refAttrs, function (i, attr) {\n const attrnode = n.getAttributeNode(attr);\n if (attrnode) {\n // the incoming file has been sanitized, so we should be able to safely just strip off the leading #\n const url = getUrlFromAttr(attrnode.value),\n refid = url ? url.substr(1) : null;\n if (refid) {\n if (!(refid in ids)) {\n // add this id to our map\n ids[refid] = {elem: null, attrs: [], hrefs: []};\n }\n ids[refid].attrs.push(attrnode);\n }\n }\n });\n\n // check xlink:href now\n const href = getHref(n);\n // TODO: what if an <image> or <a> element refers to an element internally?\n if (href && refElems.includes(n.nodeName)) {\n const refid = href.substr(1);\n if (refid) {\n if (!(refid in ids)) {\n // add this id to our map\n ids[refid] = {elem: null, attrs: [], hrefs: []};\n }\n ids[refid].hrefs.push(n);\n }\n }\n }\n });\n\n // in ids, we now have a map of ids, elements and attributes, let's re-identify\n for (const oldid in ids) {\n if (!oldid) { continue; }\n const {elem} = ids[oldid];\n if (elem) {\n const newid = getNextId();\n\n // assign element its new id\n elem.id = newid;\n\n // remap all url() attributes\n const {attrs} = ids[oldid];\n let j = attrs.length;\n while (j--) {\n const attr = attrs[j];\n attr.ownerElement.setAttribute(attr.name, 'url(#' + newid + ')');\n }\n\n // remap all href attributes\n const hreffers = ids[oldid].hrefs;\n let k = hreffers.length;\n while (k--) {\n const hreffer = hreffers[k];\n setHref(hreffer, '#' + newid);\n }\n }\n }\n};\n\n/**\n* Assigns reference data for each use element.\n* @function module:svgcanvas.SvgCanvas#setUseData\n* @param {Element} parent\n* @returns {void}\n*/\nconst setUseData = this.setUseData = function (parent) {\n let elems = $(parent);\n\n if (parent.tagName !== 'use') {\n elems = elems.find('use');\n }\n\n elems.each(function () {\n const id = getHref(this).substr(1);\n const refElem = getElem(id);\n if (!refElem) { return; }\n $(this).data('ref', refElem);\n if (refElem.tagName === 'symbol' || refElem.tagName === 'svg') {\n $(this).data('symbol', refElem).data('ref', refElem);\n }\n });\n};\n\n/**\n* Converts gradients from userSpaceOnUse to objectBoundingBox.\n* @function module:svgcanvas.SvgCanvas#convertGradients\n* @param {Element} elem\n* @returns {void}\n*/\nconst convertGradients = this.convertGradients = function (elem) {\n let elems = $(elem).find('linearGradient, radialGradient');\n if (!elems.length && isWebkit()) {\n // Bug in webkit prevents regular *Gradient selector search\n elems = $(elem).find('*').filter(function () {\n return (this.tagName.includes('Gradient'));\n });\n }\n\n elems.each(function () {\n const grad = this; // eslint-disable-line consistent-this\n if ($(grad).attr('gradientUnits') === 'userSpaceOnUse') {\n // TODO: Support more than one element with this ref by duplicating parent grad\n const fillStrokeElems = $(svgcontent).find('[fill=\"url(#' + grad.id + ')\"],[stroke=\"url(#' + grad.id + ')\"]');\n if (!fillStrokeElems.length) { return; }\n\n // get object's bounding box\n const bb = utilsGetBBox(fillStrokeElems[0]);\n\n // This will occur if the element is inside a <defs> or a <symbol>,\n // in which we shouldn't need to convert anyway.\n if (!bb) { return; }\n\n if (grad.tagName === 'linearGradient') {\n const gCoords = $(grad).attr(['x1', 'y1', 'x2', 'y2']);\n\n // If has transform, convert\n const tlist = grad.gradientTransform.baseVal;\n if (tlist && tlist.numberOfItems > 0) {\n const m = transformListToTransform(tlist).matrix;\n const pt1 = transformPoint(gCoords.x1, gCoords.y1, m);\n const pt2 = transformPoint(gCoords.x2, gCoords.y2, m);\n\n gCoords.x1 = pt1.x;\n gCoords.y1 = pt1.y;\n gCoords.x2 = pt2.x;\n gCoords.y2 = pt2.y;\n grad.removeAttribute('gradientTransform');\n }\n\n $(grad).attr({\n x1: (gCoords.x1 - bb.x) / bb.width,\n y1: (gCoords.y1 - bb.y) / bb.height,\n x2: (gCoords.x2 - bb.x) / bb.width,\n y2: (gCoords.y2 - bb.y) / bb.height\n });\n grad.removeAttribute('gradientUnits');\n }\n // else {\n // Note: radialGradient elements cannot be easily converted\n // because userSpaceOnUse will keep circular gradients, while\n // objectBoundingBox will x/y scale the gradient according to\n // its bbox.\n //\n // For now we'll do nothing, though we should probably have\n // the gradient be updated as the element is moved, as\n // inkscape/illustrator do.\n //\n // const gCoords = $(grad).attr(['cx', 'cy', 'r']);\n //\n // $(grad).attr({\n // cx: (gCoords.cx - bb.x) / bb.width,\n // cy: (gCoords.cy - bb.y) / bb.height,\n // r: gCoords.r\n // });\n //\n // grad.removeAttribute('gradientUnits');\n // }\n }\n });\n};\n\n/**\n* Converts selected/given `<use>` or child SVG element to a group.\n* @function module:svgcanvas.SvgCanvas#convertToGroup\n* @param {Element} elem\n* @fires module:svgcanvas.SvgCanvas#event:selected\n* @returns {void}\n*/\nconst convertToGroup = this.convertToGroup = function (elem) {\n if (!elem) {\n elem = selectedElements[0];\n }\n const $elem = $(elem);\n const batchCmd = new BatchCommand();\n let ts;\n\n if ($elem.data('gsvg')) {\n // Use the gsvg as the new group\n const svg = elem.firstChild;\n const pt = $(svg).attr(['x', 'y']);\n\n $(elem.firstChild.firstChild).unwrap();\n $(elem).removeData('gsvg');\n\n const tlist = getTransformList(elem);\n const xform = svgroot.createSVGTransform();\n xform.setTranslate(pt.x, pt.y);\n tlist.appendItem(xform);\n recalculateDimensions(elem);\n call('selected', [elem]);\n } else if ($elem.data('symbol')) {\n elem = $elem.data('symbol');\n\n ts = $elem.attr('transform');\n const pos = $elem.attr(['x', 'y']);\n\n const vb = elem.getAttribute('viewBox');\n\n if (vb) {\n const nums = vb.split(' ');\n pos.x -= Number(nums[0]);\n pos.y -= Number(nums[1]);\n }\n\n // Not ideal, but works\n ts += ' translate(' + (pos.x || 0) + ',' + (pos.y || 0) + ')';\n\n const prev = $elem.prev();\n\n // Remove <use> element\n batchCmd.addSubCommand(new RemoveElementCommand($elem[0], $elem[0].nextSibling, $elem[0].parentNode));\n $elem.remove();\n\n // See if other elements reference this symbol\n const hasMore = $(svgcontent).find('use:data(symbol)').length;\n\n const g = svgdoc.createElementNS(NS.SVG, 'g');\n const childs = elem.childNodes;\n\n let i;\n for (i = 0; i < childs.length; i++) {\n g.append(childs[i].cloneNode(true));\n }\n\n // Duplicate the gradients for Gecko, since they weren't included in the <symbol>\n if (isGecko()) {\n const dupeGrads = $(findDefs()).children('linearGradient,radialGradient,pattern').clone();\n $(g).append(dupeGrads);\n }\n\n if (ts) {\n g.setAttribute('transform', ts);\n }\n\n const parent = elem.parentNode;\n\n uniquifyElems(g);\n\n // Put the dupe gradients back into <defs> (after uniquifying them)\n if (isGecko()) {\n $(findDefs()).append($(g).find('linearGradient,radialGradient,pattern'));\n }\n\n // now give the g itself a new id\n g.id = getNextId();\n\n prev.after(g);\n\n if (parent) {\n if (!hasMore) {\n // remove symbol/svg element\n const {nextSibling} = elem;\n elem.remove();\n batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent));\n }\n batchCmd.addSubCommand(new InsertElementCommand(g));\n }\n\n setUseData(g);\n\n if (isGecko()) {\n convertGradients(findDefs());\n } else {\n convertGradients(g);\n }\n\n // recalculate dimensions on the top-level children so that unnecessary transforms\n // are removed\n walkTreePost(g, function (n) {\n try {\n recalculateDimensions(n);\n } catch (e) {\n console.log(e); // eslint-disable-line no-console\n }\n });\n\n // Give ID for any visible element missing one\n $(g).find(visElems).each(function () {\n if (!this.id) { this.id = getNextId(); }\n });\n\n selectOnly([g]);\n\n const cm = pushGroupProperties(g, true);\n if (cm) {\n batchCmd.addSubCommand(cm);\n }\n\n addCommandToHistory(batchCmd);\n } else {\n console.log('Unexpected element to ungroup:', elem); // eslint-disable-line no-console\n }\n};\n\n/**\n* This function sets the current drawing as the input SVG XML.\n* @function module:svgcanvas.SvgCanvas#setSvgString\n* @param {string} xmlString - The SVG as XML text.\n* @param {boolean} [preventUndo=false] - Indicates if we want to do the\n* changes without adding them to the undo stack - e.g. for initializing a\n* drawing on page load.\n* @fires module:svgcanvas.SvgCanvas#event:setnonce\n* @fires module:svgcanvas.SvgCanvas#event:unsetnonce\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} This function returns `false` if the set was\n* unsuccessful, `true` otherwise.\n*/\nthis.setSvgString = function (xmlString, preventUndo) {\n try {\n // convert string into XML document\n const newDoc = text2xml(xmlString);\n if (newDoc.firstElementChild &&\n newDoc.firstElementChild.namespaceURI !== NS.SVG) {\n return false;\n }\n\n this.prepareSvg(newDoc);\n\n const batchCmd = new BatchCommand('Change Source');\n\n // remove old svg document\n const {nextSibling} = svgcontent;\n\n svgcontent.remove();\n const oldzoom = svgcontent;\n batchCmd.addSubCommand(new RemoveElementCommand(oldzoom, nextSibling, svgroot));\n\n // set new svg document\n // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode()\n if (svgdoc.adoptNode) {\n svgcontent = svgdoc.adoptNode(newDoc.documentElement);\n } else {\n svgcontent = svgdoc.importNode(newDoc.documentElement, true);\n }\n\n svgroot.append(svgcontent);\n const content = $(svgcontent);\n\n canvas.current_drawing_ = new draw.Drawing(svgcontent, idprefix);\n\n // retrieve or set the nonce\n const nonce = getCurrentDrawing().getNonce();\n if (nonce) {\n call('setnonce', nonce);\n } else {\n call('unsetnonce');\n }\n\n // change image href vals if possible\n content.find('image').each(function () {\n const image = this; // eslint-disable-line consistent-this\n preventClickDefault(image);\n const val = getHref(this);\n if (val) {\n if (val.startsWith('data:')) {\n // Check if an SVG-edit data URI\n const m = val.match(/svgedit_url=(.*?);/);\n // const m = val.match(/svgedit_url=(?<url>.*?);/);\n if (m) {\n const url = decodeURIComponent(m[1]);\n // const url = decodeURIComponent(m.groups.url);\n $(new Image()).load(function () {\n image.setAttributeNS(NS.XLINK, 'xlink:href', url);\n }).attr('src', url);\n }\n }\n // Add to encodableImages if it loads\n canvas.embedImage(val);\n }\n });\n\n // Wrap child SVGs in group elements\n content.find('svg').each(function () {\n // Skip if it's in a <defs>\n if ($(this).closest('defs').length) { return; }\n\n uniquifyElems(this);\n\n // Check if it already has a gsvg group\n const pa = this.parentNode;\n if (pa.childNodes.length === 1 && pa.nodeName === 'g') {\n $(pa).data('gsvg', this);\n pa.id = pa.id || getNextId();\n } else {\n groupSvgElem(this);\n }\n });\n\n // For Firefox: Put all paint elems in defs\n if (isGecko()) {\n content.find('linearGradient, radialGradient, pattern').appendTo(findDefs());\n }\n\n // Set ref element for <use> elements\n\n // TODO: This should also be done if the object is re-added through \"redo\"\n setUseData(content);\n\n convertGradients(content[0]);\n\n const attrs = {\n id: 'svgcontent',\n overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden'\n };\n\n let percs = false;\n\n // determine proper size\n if (content.attr('viewBox')) {\n const vb = content.attr('viewBox').split(' ');\n attrs.width = vb[2];\n attrs.height = vb[3];\n // handle content that doesn't have a viewBox\n } else {\n $.each(['width', 'height'], function (i, dim) {\n // Set to 100 if not given\n const val = content.attr(dim) || '100%';\n\n if (String(val).substr(-1) === '%') {\n // Use user units if percentage given\n percs = true;\n } else {\n attrs[dim] = convertToNum(dim, val);\n }\n });\n }\n\n // identify layers\n draw.identifyLayers();\n\n // Give ID for any visible layer children missing one\n content.children().find(visElems).each(function () {\n if (!this.id) { this.id = getNextId(); }\n });\n\n // Percentage width/height, so let's base it on visible elements\n if (percs) {\n const bb = getStrokedBBoxDefaultVisible();\n attrs.width = bb.width + bb.x;\n attrs.height = bb.height + bb.y;\n }\n\n // Just in case negative numbers are given or\n // result from the percs calculation\n if (attrs.width <= 0) { attrs.width = 100; }\n if (attrs.height <= 0) { attrs.height = 100; }\n\n content.attr(attrs);\n this.contentW = attrs.width;\n this.contentH = attrs.height;\n\n batchCmd.addSubCommand(new InsertElementCommand(svgcontent));\n // update root to the correct size\n const changes = content.attr(['width', 'height']);\n batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes));\n\n // reset zoom\n currentZoom = 1;\n\n // reset transform lists\n resetListMap();\n clearSelection();\n pathModule.clearData();\n svgroot.append(selectorManager.selectorParentGroup);\n\n if (!preventUndo) addCommandToHistory(batchCmd);\n call('changed', [svgcontent]);\n } catch (e) {\n console.log(e); // eslint-disable-line no-console\n return false;\n }\n\n return true;\n};\n\n/**\n* This function imports the input SVG XML as a `<symbol>` in the `<defs>`, then adds a\n* `<use>` to the current layer.\n* @function module:svgcanvas.SvgCanvas#importSvgString\n* @param {string} xmlString - The SVG as XML text.\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {null|Element} This function returns null if the import was unsuccessful, or the element otherwise.\n* @todo\n* - properly handle if namespace is introduced by imported content (must add to svgcontent\n* and update all prefixes in the imported node)\n* - properly handle recalculating dimensions, `recalculateDimensions()` doesn't handle\n* arbitrary transform lists, but makes some assumptions about how the transform list\n* was obtained\n*/\nthis.importSvgString = function (xmlString) {\n let j, ts, useEl;\n try {\n // Get unique ID\n const uid = encode64(xmlString.length + xmlString).substr(0, 32);\n\n let useExisting = false;\n // Look for symbol and make sure symbol exists in image\n if (importIds[uid]) {\n if ($(importIds[uid].symbol).parents('#svgroot').length) {\n useExisting = true;\n }\n }\n\n const batchCmd = new BatchCommand('Import Image');\n let symbol;\n if (useExisting) {\n ({symbol} = importIds[uid]);\n ts = importIds[uid].xform;\n } else {\n // convert string into XML document\n const newDoc = text2xml(xmlString);\n\n this.prepareSvg(newDoc);\n\n // import new svg document into our document\n let svg;\n // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode()\n if (svgdoc.adoptNode) {\n svg = svgdoc.adoptNode(newDoc.documentElement);\n } else {\n svg = svgdoc.importNode(newDoc.documentElement, true);\n }\n\n uniquifyElems(svg);\n\n const innerw = convertToNum('width', svg.getAttribute('width')),\n innerh = convertToNum('height', svg.getAttribute('height')),\n innervb = svg.getAttribute('viewBox'),\n // if no explicit viewbox, create one out of the width and height\n vb = innervb ? innervb.split(' ') : [0, 0, innerw, innerh];\n for (j = 0; j < 4; ++j) {\n vb[j] = Number(vb[j]);\n }\n\n // TODO: properly handle preserveAspectRatio\n const // canvasw = +svgcontent.getAttribute('width'),\n canvash = Number(svgcontent.getAttribute('height'));\n // imported content should be 1/3 of the canvas on its largest dimension\n\n if (innerh > innerw) {\n ts = 'scale(' + (canvash / 3) / vb[3] + ')';\n } else {\n ts = 'scale(' + (canvash / 3) / vb[2] + ')';\n }\n\n // Hack to make recalculateDimensions understand how to scale\n ts = 'translate(0) ' + ts + ' translate(0)';\n\n symbol = svgdoc.createElementNS(NS.SVG, 'symbol');\n const defs = findDefs();\n\n if (isGecko()) {\n // Move all gradients into root for Firefox, workaround for this bug:\n // https://bugzilla.mozilla.org/show_bug.cgi?id=353575\n // TODO: Make this properly undo-able.\n $(svg).find('linearGradient, radialGradient, pattern').appendTo(defs);\n }\n\n while (svg.firstChild) {\n const first = svg.firstChild;\n symbol.append(first);\n }\n const attrs = svg.attributes;\n for (const attr of attrs) { // Ok for `NamedNodeMap`\n symbol.setAttribute(attr.nodeName, attr.value);\n }\n symbol.id = getNextId();\n\n // Store data\n importIds[uid] = {\n symbol,\n xform: ts\n };\n\n findDefs().append(symbol);\n batchCmd.addSubCommand(new InsertElementCommand(symbol));\n }\n\n useEl = svgdoc.createElementNS(NS.SVG, 'use');\n useEl.id = getNextId();\n setHref(useEl, '#' + symbol.id);\n\n (currentGroup || getCurrentDrawing().getCurrentLayer()).append(useEl);\n batchCmd.addSubCommand(new InsertElementCommand(useEl));\n clearSelection();\n\n useEl.setAttribute('transform', ts);\n recalculateDimensions(useEl);\n $(useEl).data('symbol', symbol).data('ref', symbol);\n addToSelection([useEl]);\n\n // TODO: Find way to add this in a recalculateDimensions-parsable way\n // if (vb[0] !== 0 || vb[1] !== 0) {\n // ts = 'translate(' + (-vb[0]) + ',' + (-vb[1]) + ') ' + ts;\n // }\n addCommandToHistory(batchCmd);\n call('changed', [svgcontent]);\n } catch (e) {\n console.log(e); // eslint-disable-line no-console\n return null;\n }\n\n // we want to return the element so we can automatically select it\n return useEl;\n};\n\n// Could deprecate, but besides external uses, their usage makes clear that\n// canvas is a dependency for all of these\nconst dr = {\n identifyLayers, createLayer, cloneLayer, deleteCurrentLayer,\n setCurrentLayer, renameCurrentLayer, setCurrentLayerPosition,\n setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers,\n leaveContext, setContext\n};\nObject.entries(dr).forEach(([prop, propVal]) => {\n canvas[prop] = propVal;\n});\ndraw.init(\n /**\n * @implements {module:draw.DrawCanvasInit}\n */\n {\n pathActions,\n getCurrentGroup () {\n return currentGroup;\n },\n setCurrentGroup (cg) {\n currentGroup = cg;\n },\n getSelectedElements,\n getSVGContent,\n undoMgr,\n elData,\n getCurrentDrawing,\n clearSelection,\n call,\n addCommandToHistory,\n /**\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n changeSVGContent () {\n call('changed', [svgcontent]);\n }\n }\n);\n\n/**\n* Group: Document functions.\n*/\n\n/**\n* Clears the current document. This is not an undoable action.\n* @function module:svgcanvas.SvgCanvas#clear\n* @fires module:svgcanvas.SvgCanvas#event:cleared\n* @returns {void}\n*/\nthis.clear = function () {\n pathActions.clear();\n\n clearSelection();\n\n // clear the svgcontent node\n canvas.clearSvgContentElement();\n\n // create new document\n canvas.current_drawing_ = new draw.Drawing(svgcontent);\n\n // create empty first layer\n canvas.createLayer('Layer 1');\n\n // clear the undo stack\n canvas.undoMgr.resetUndoStack();\n\n // reset the selector manager\n selectorManager.initGroup();\n\n // reset the rubber band box\n rubberBox = selectorManager.getRubberBandBox();\n\n call('cleared');\n};\n\n// Alias function\nthis.linkControlPoints = pathActions.linkControlPoints;\n\n/**\n* @function module:svgcanvas.SvgCanvas#getContentElem\n* @returns {Element} The content DOM element\n*/\nthis.getContentElem = function () { return svgcontent; };\n\n/**\n* @function module:svgcanvas.SvgCanvas#getRootElem\n* @returns {SVGSVGElement} The root DOM element\n*/\nthis.getRootElem = function () { return svgroot; };\n\n/**\n* @typedef {PlainObject} DimensionsAndZoom\n* @property {Float} w Width\n* @property {Float} h Height\n* @property {Float} zoom Zoom\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getResolution\n* @returns {DimensionsAndZoom} The current dimensions and zoom level in an object\n*/\nconst getResolution = this.getResolution = function () {\n// const vb = svgcontent.getAttribute('viewBox').split(' ');\n// return {w:vb[2], h:vb[3], zoom: currentZoom};\n\n const w = svgcontent.getAttribute('width') / currentZoom;\n const h = svgcontent.getAttribute('height') / currentZoom;\n\n return {\n w,\n h,\n zoom: currentZoom\n };\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getSnapToGrid\n* @returns {boolean} The current snap to grid setting\n*/\nthis.getSnapToGrid = function () { return curConfig.gridSnapping; };\n\n/**\n* @function module:svgcanvas.SvgCanvas#getVersion\n* @returns {string} A string which describes the revision number of SvgCanvas.\n*/\nthis.getVersion = function () {\n return 'svgcanvas.js ($Rev$)';\n};\n\n/**\n* Update interface strings with given values.\n* @function module:svgcanvas.SvgCanvas#setUiStrings\n* @param {module:path.uiStrings} strs - Object with strings (see the [locales API]{@link module:locale.LocaleStrings} and the [tutorial]{@tutorial LocaleDocs})\n* @returns {void}\n*/\nthis.setUiStrings = function (strs) {\n Object.assign(uiStrings, strs.notification);\n $ = jQueryPluginDBox($, strs.common);\n pathModule.setUiStrings(strs);\n};\n\n/**\n* Update configuration options with given values.\n* @function module:svgcanvas.SvgCanvas#setConfig\n* @param {module:SVGEditor.Config} opts - Object with options\n* @returns {void}\n*/\nthis.setConfig = function (opts) {\n Object.assign(curConfig, opts);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getTitle\n* @param {Element} [elem]\n* @returns {string|void} the current group/SVG's title contents or\n* `undefined` if no element is passed nd there are no selected elements.\n*/\nthis.getTitle = function (elem) {\n elem = elem || selectedElements[0];\n if (!elem) { return undefined; }\n elem = $(elem).data('gsvg') || $(elem).data('symbol') || elem;\n const childs = elem.childNodes;\n for (const child of childs) {\n if (child.nodeName === 'title') {\n return child.textContent;\n }\n }\n return '';\n};\n\n/**\n* Sets the group/SVG's title content.\n* @function module:svgcanvas.SvgCanvas#setGroupTitle\n* @param {string} val\n* @todo Combine this with `setDocumentTitle`\n* @returns {void}\n*/\nthis.setGroupTitle = function (val) {\n let elem = selectedElements[0];\n elem = $(elem).data('gsvg') || elem;\n\n const ts = $(elem).children('title');\n\n const batchCmd = new BatchCommand('Set Label');\n\n let title;\n if (!val.length) {\n // Remove title element\n const tsNextSibling = ts.nextSibling;\n batchCmd.addSubCommand(new RemoveElementCommand(ts[0], tsNextSibling, elem));\n ts.remove();\n } else if (ts.length) {\n // Change title contents\n title = ts[0];\n batchCmd.addSubCommand(new ChangeElementCommand(title, {'#text': title.textContent}));\n title.textContent = val;\n } else {\n // Add title element\n title = svgdoc.createElementNS(NS.SVG, 'title');\n title.textContent = val;\n $(elem).prepend(title);\n batchCmd.addSubCommand(new InsertElementCommand(title));\n }\n\n addCommandToHistory(batchCmd);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getDocumentTitle\n* @returns {string|void} The current document title or an empty string if not found\n*/\nconst getDocumentTitle = this.getDocumentTitle = function () {\n return canvas.getTitle(svgcontent);\n};\n\n/**\n* Adds/updates a title element for the document with the given name.\n* This is an undoable action.\n* @function module:svgcanvas.SvgCanvas#setDocumentTitle\n* @param {string} newTitle - String with the new title\n* @returns {void}\n*/\nthis.setDocumentTitle = function (newTitle) {\n const childs = svgcontent.childNodes;\n let docTitle = false, oldTitle = '';\n\n const batchCmd = new BatchCommand('Change Image Title');\n\n for (const child of childs) {\n if (child.nodeName === 'title') {\n docTitle = child;\n oldTitle = docTitle.textContent;\n break;\n }\n }\n if (!docTitle) {\n docTitle = svgdoc.createElementNS(NS.SVG, 'title');\n svgcontent.insertBefore(docTitle, svgcontent.firstChild);\n // svgcontent.firstChild.before(docTitle); // Ok to replace above with this?\n }\n\n if (newTitle.length) {\n docTitle.textContent = newTitle;\n } else {\n // No title given, so element is not necessary\n docTitle.remove();\n }\n batchCmd.addSubCommand(new ChangeElementCommand(docTitle, {'#text': oldTitle}));\n addCommandToHistory(batchCmd);\n};\n\n/**\n* Returns the editor's namespace URL, optionally adding it to the root element.\n* @function module:svgcanvas.SvgCanvas#getEditorNS\n* @param {boolean} [add] - Indicates whether or not to add the namespace value\n* @returns {string} The editor's namespace URL\n*/\nthis.getEditorNS = function (add) {\n if (add) {\n svgcontent.setAttribute('xmlns:se', NS.SE);\n }\n return NS.SE;\n};\n\n/**\n* Changes the document's dimensions to the given size.\n* @function module:svgcanvas.SvgCanvas#setResolution\n* @param {Float|\"fit\"} x - Number with the width of the new dimensions in user units.\n* Can also be the string \"fit\" to indicate \"fit to content\".\n* @param {Float} y - Number with the height of the new dimensions in user units.\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} Indicates if resolution change was successful.\n* It will fail on \"fit to content\" option with no content to fit to.\n*/\nthis.setResolution = function (x, y) {\n const res = getResolution();\n const {w, h} = res;\n let batchCmd;\n\n if (x === 'fit') {\n // Get bounding box\n const bbox = getStrokedBBoxDefaultVisible();\n\n if (bbox) {\n batchCmd = new BatchCommand('Fit Canvas to Content');\n const visEls = getVisibleElements();\n addToSelection(visEls);\n const dx = [], dy = [];\n $.each(visEls, function (i, item) {\n dx.push(bbox.x * -1);\n dy.push(bbox.y * -1);\n });\n\n const cmd = canvas.moveSelectedElements(dx, dy, true);\n batchCmd.addSubCommand(cmd);\n clearSelection();\n\n x = Math.round(bbox.width);\n y = Math.round(bbox.height);\n } else {\n return false;\n }\n }\n if (x !== w || y !== h) {\n if (!batchCmd) {\n batchCmd = new BatchCommand('Change Image Dimensions');\n }\n\n x = convertToNum('width', x);\n y = convertToNum('height', y);\n\n svgcontent.setAttribute('width', x);\n svgcontent.setAttribute('height', y);\n\n this.contentW = x;\n this.contentH = y;\n batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {width: w, height: h}));\n\n svgcontent.setAttribute('viewBox', [0, 0, x / currentZoom, y / currentZoom].join(' '));\n batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {viewBox: ['0 0', w, h].join(' ')}));\n\n addCommandToHistory(batchCmd);\n call('changed', [svgcontent]);\n }\n return true;\n};\n\n/**\n* @typedef {module:jQueryAttr.Attributes} module:svgcanvas.ElementPositionInCanvas\n* @property {Float} x\n* @property {Float} y\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getOffset\n* @returns {module:svgcanvas.ElementPositionInCanvas} An object with `x`, `y` values indicating the svgcontent element's\n* position in the editor's canvas.\n*/\nthis.getOffset = function () {\n return $(svgcontent).attr(['x', 'y']);\n};\n\n/**\n * @typedef {PlainObject} module:svgcanvas.ZoomAndBBox\n * @property {Float} zoom\n * @property {module:utilities.BBoxObject} bbox\n */\n/**\n* Sets the zoom level on the canvas-side based on the given value.\n* @function module:svgcanvas.SvgCanvas#setBBoxZoom\n* @param {\"selection\"|\"canvas\"|\"content\"|\"layer\"|module:SVGEditor.BBoxObjectWithFactor} val - Bounding box object to zoom to or string indicating zoom option. Note: the object value type is defined in `svg-editor.js`\n* @param {Integer} editorW - The editor's workarea box's width\n* @param {Integer} editorH - The editor's workarea box's height\n* @returns {module:svgcanvas.ZoomAndBBox|void}\n*/\nthis.setBBoxZoom = function (val, editorW, editorH) {\n let spacer = 0.85;\n let bb;\n const calcZoom = function (bb) { // eslint-disable-line no-shadow\n if (!bb) { return false; }\n const wZoom = Math.round((editorW / bb.width) * 100 * spacer) / 100;\n const hZoom = Math.round((editorH / bb.height) * 100 * spacer) / 100;\n const zoom = Math.min(wZoom, hZoom);\n canvas.setZoom(zoom);\n return {zoom, bbox: bb};\n };\n\n if (typeof val === 'object') {\n bb = val;\n if (bb.width === 0 || bb.height === 0) {\n const newzoom = bb.zoom ? bb.zoom : currentZoom * bb.factor;\n canvas.setZoom(newzoom);\n return {zoom: currentZoom, bbox: bb};\n }\n return calcZoom(bb);\n }\n\n switch (val) {\n case 'selection': {\n if (!selectedElements[0]) { return undefined; }\n const selectedElems = $.map(selectedElements, function (n) {\n if (n) {\n return n;\n }\n return undefined;\n });\n bb = getStrokedBBoxDefaultVisible(selectedElems);\n break;\n } case 'canvas': {\n const res = getResolution();\n spacer = 0.95;\n bb = {width: res.w, height: res.h, x: 0, y: 0};\n break;\n } case 'content':\n bb = getStrokedBBoxDefaultVisible();\n break;\n case 'layer':\n bb = getStrokedBBoxDefaultVisible(getVisibleElements(getCurrentDrawing().getCurrentLayer()));\n break;\n default:\n return undefined;\n }\n return calcZoom(bb);\n};\n\n/**\n* The zoom level has changed. Supplies the new zoom level as a number (not percentage).\n* @event module:svgcanvas.SvgCanvas#event:ext_zoomChanged\n* @type {Float}\n*/\n/**\n* The bottom panel was updated.\n* @event module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate\n* @type {PlainObject}\n* @property {boolean} nofill Indicates fill is disabled\n* @property {boolean} nostroke Indicates stroke is disabled\n*/\n/**\n* The element selection has changed (elements were added/removed from selection).\n* @event module:svgcanvas.SvgCanvas#event:ext_selectedChanged\n* @type {PlainObject}\n* @property {Element[]} elems Array of the newly selected elements\n* @property {Element|null} selectedElement The single selected element\n* @property {boolean} multiselected Indicates whether one or more elements were selected\n*/\n/**\n* Called when part of element is in process of changing, generally on\n* mousemove actions like rotate, move, etc.\n* @event module:svgcanvas.SvgCanvas#event:ext_elementTransition\n* @type {PlainObject}\n* @property {Element[]} elems Array of transitioning elements\n*/\n/**\n* One or more elements were changed.\n* @event module:svgcanvas.SvgCanvas#event:ext_elementChanged\n* @type {PlainObject}\n* @property {Element[]} elems Array of the affected elements\n*/\n/**\n* Invoked as soon as the locale is ready.\n* @event module:svgcanvas.SvgCanvas#event:ext_langReady\n* @type {PlainObject}\n* @property {string} lang The two-letter language code\n* @property {module:SVGEditor.uiStrings} uiStrings\n* @property {module:SVGEditor~ImportLocale} importLocale\n*/\n/**\n* The language was changed. Two-letter code of the new language.\n* @event module:svgcanvas.SvgCanvas#event:ext_langChanged\n* @type {string}\n*/\n/**\n* Means for an extension to add locale data. The two-letter language code.\n* @event module:svgcanvas.SvgCanvas#event:ext_addLangData\n* @type {PlainObject}\n* @property {string} lang\n* @property {module:SVGEditor~ImportLocale} importLocale\n*/\n/**\n * Called when new image is created.\n * @event module:svgcanvas.SvgCanvas#event:ext_onNewDocument\n * @type {void}\n */\n/**\n * Called when sidepanel is resized or toggled.\n * @event module:svgcanvas.SvgCanvas#event:ext_workareaResized\n * @type {void}\n*/\n/**\n * Called upon addition of the extension, or, if svgicons are set,\n * after the icons are ready when extension SVG icons have loaded.\n * @event module:svgcanvas.SvgCanvas#event:ext_callback\n * @type {void}\n*/\n\n/**\n* Sets the zoom to the given level.\n* @function module:svgcanvas.SvgCanvas#setZoom\n* @param {Float} zoomLevel - Float indicating the zoom level to change to\n* @fires module:svgcanvas.SvgCanvas#event:ext_zoomChanged\n* @returns {void}\n*/\nthis.setZoom = function (zoomLevel) {\n const res = getResolution();\n svgcontent.setAttribute('viewBox', '0 0 ' + res.w / zoomLevel + ' ' + res.h / zoomLevel);\n currentZoom = zoomLevel;\n $.each(selectedElements, function (i, elem) {\n if (!elem) { return; }\n selectorManager.requestSelector(elem).resize();\n });\n pathActions.zoomChange();\n runExtensions('zoomChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_zoomChanged} */ zoomLevel);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getMode\n* @returns {string} The current editor mode string\n*/\nthis.getMode = function () {\n return currentMode;\n};\n\n/**\n* Sets the editor's mode to the given string.\n* @function module:svgcanvas.SvgCanvas#setMode\n* @param {string} name - String with the new mode to change to\n* @returns {void}\n*/\nthis.setMode = function (name) {\n pathActions.clear(true);\n textActions.clear();\n curProperties = (selectedElements[0] && selectedElements[0].nodeName === 'text') ? curText : curShape;\n currentMode = name;\n};\n\n/**\n* Group: Element Styling.\n*/\n\n/**\n* @typedef {PlainObject} module:svgcanvas.PaintOptions\n* @property {\"solidColor\"} type\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getColor\n* @param {string} type\n* @returns {string|module:svgcanvas.PaintOptions|Float|module:jGraduate~Paint} The current fill/stroke option\n*/\nthis.getColor = function (type) {\n return curProperties[type];\n};\n\n/**\n* Change the current stroke/fill color/gradient value.\n* @function module:svgcanvas.SvgCanvas#setColor\n* @param {string} type - String indicating fill or stroke\n* @param {string} val - The value to set the stroke attribute to\n* @param {boolean} preventUndo - Boolean indicating whether or not this should be an undoable option\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setColor = function (type, val, preventUndo) {\n curShape[type] = val;\n curProperties[type + '_paint'] = {type: 'solidColor'};\n const elems = [];\n /**\n *\n * @param {Element} e\n * @returns {void}\n */\n function addNonG (e) {\n if (e.nodeName !== 'g') {\n elems.push(e);\n }\n }\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n if (elem) {\n if (elem.tagName === 'g') {\n walkTree(elem, addNonG);\n } else if (type === 'fill') {\n if (elem.tagName !== 'polyline' && elem.tagName !== 'line') {\n elems.push(elem);\n }\n } else {\n elems.push(elem);\n }\n }\n }\n if (elems.length > 0) {\n if (!preventUndo) {\n changeSelectedAttribute(type, val, elems);\n call('changed', elems);\n } else {\n changeSelectedAttributeNoUndo(type, val, elems);\n }\n }\n};\n\n/**\n* Apply the current gradient to selected element's fill or stroke.\n* @function module:svgcanvas.SvgCanvas#setGradient\n* @param {\"fill\"|\"stroke\"} type - String indicating \"fill\" or \"stroke\" to apply to an element\n* @returns {void}\n*/\nconst setGradient = this.setGradient = function (type) {\n if (!curProperties[type + '_paint'] || curProperties[type + '_paint'].type === 'solidColor') { return; }\n let grad = canvas[type + 'Grad'];\n // find out if there is a duplicate gradient already in the defs\n const duplicateGrad = findDuplicateGradient(grad);\n const defs = findDefs();\n // no duplicate found, so import gradient into defs\n if (!duplicateGrad) {\n // const origGrad = grad;\n grad = defs.appendChild(svgdoc.importNode(grad, true));\n // get next id and set it on the grad\n grad.id = getNextId();\n } else { // use existing gradient\n grad = duplicateGrad;\n }\n canvas.setColor(type, 'url(#' + grad.id + ')');\n};\n\n/**\n* Check if exact gradient already exists.\n* @function module:svgcanvas~findDuplicateGradient\n* @param {SVGGradientElement} grad - The gradient DOM element to compare to others\n* @returns {SVGGradientElement} The existing gradient if found, `null` if not\n*/\nconst findDuplicateGradient = function (grad) {\n const defs = findDefs();\n const existingGrads = $(defs).find('linearGradient, radialGradient');\n let i = existingGrads.length;\n const radAttrs = ['r', 'cx', 'cy', 'fx', 'fy'];\n while (i--) {\n const og = existingGrads[i];\n if (grad.tagName === 'linearGradient') {\n if (grad.getAttribute('x1') !== og.getAttribute('x1') ||\n grad.getAttribute('y1') !== og.getAttribute('y1') ||\n grad.getAttribute('x2') !== og.getAttribute('x2') ||\n grad.getAttribute('y2') !== og.getAttribute('y2')\n ) {\n continue;\n }\n } else {\n const gradAttrs = $(grad).attr(radAttrs);\n const ogAttrs = $(og).attr(radAttrs);\n\n let diff = false;\n $.each(radAttrs, function (j, attr) {\n if (gradAttrs[attr] !== ogAttrs[attr]) { diff = true; }\n });\n\n if (diff) { continue; }\n }\n\n // else could be a duplicate, iterate through stops\n const stops = grad.getElementsByTagNameNS(NS.SVG, 'stop');\n const ostops = og.getElementsByTagNameNS(NS.SVG, 'stop');\n\n if (stops.length !== ostops.length) {\n continue;\n }\n\n let j = stops.length;\n while (j--) {\n const stop = stops[j];\n const ostop = ostops[j];\n\n if (stop.getAttribute('offset') !== ostop.getAttribute('offset') ||\n stop.getAttribute('stop-opacity') !== ostop.getAttribute('stop-opacity') ||\n stop.getAttribute('stop-color') !== ostop.getAttribute('stop-color')) {\n break;\n }\n }\n\n if (j === -1) {\n return og;\n }\n } // for each gradient in defs\n\n return null;\n};\n\n/**\n* Set a color/gradient to a fill/stroke.\n* @function module:svgcanvas.SvgCanvas#setPaint\n* @param {\"fill\"|\"stroke\"} type - String with \"fill\" or \"stroke\"\n* @param {module:jGraduate.jGraduatePaintOptions} paint - The jGraduate paint object to apply\n* @returns {void}\n*/\nthis.setPaint = function (type, paint) {\n // make a copy\n const p = new $.jGraduate.Paint(paint);\n this.setPaintOpacity(type, p.alpha / 100, true);\n\n // now set the current paint object\n curProperties[type + '_paint'] = p;\n switch (p.type) {\n case 'solidColor':\n this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none');\n break;\n case 'linearGradient':\n case 'radialGradient':\n canvas[type + 'Grad'] = p[p.type];\n setGradient(type);\n break;\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#setStrokePaint\n* @param {module:jGraduate~Paint} paint\n* @returns {void}\n*/\nthis.setStrokePaint = function (paint) {\n this.setPaint('stroke', paint);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#setFillPaint\n* @param {module:jGraduate~Paint} paint\n* @returns {void}\n*/\nthis.setFillPaint = function (paint) {\n this.setPaint('fill', paint);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getStrokeWidth\n* @returns {Float|string} The current stroke-width value\n*/\nthis.getStrokeWidth = function () {\n return curProperties.stroke_width;\n};\n\n/**\n* Sets the stroke width for the current selected elements.\n* When attempting to set a line's width to 0, this changes it to 1 instead.\n* @function module:svgcanvas.SvgCanvas#setStrokeWidth\n* @param {Float} val - A Float indicating the new stroke width value\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setStrokeWidth = function (val) {\n if (val === 0 && ['line', 'path'].includes(currentMode)) {\n canvas.setStrokeWidth(1);\n return;\n }\n curProperties.stroke_width = val;\n\n const elems = [];\n /**\n *\n * @param {Element} e\n * @returns {void}\n */\n function addNonG (e) {\n if (e.nodeName !== 'g') {\n elems.push(e);\n }\n }\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n if (elem) {\n if (elem.tagName === 'g') {\n walkTree(elem, addNonG);\n } else {\n elems.push(elem);\n }\n }\n }\n if (elems.length > 0) {\n changeSelectedAttribute('stroke-width', val, elems);\n call('changed', selectedElements);\n }\n};\n\n/**\n* Set the given stroke-related attribute the given value for selected elements.\n* @function module:svgcanvas.SvgCanvas#setStrokeAttr\n* @param {string} attr - String with the attribute name\n* @param {string|Float} val - String or number with the attribute value\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setStrokeAttr = function (attr, val) {\n curShape[attr.replace('-', '_')] = val;\n const elems = [];\n\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n if (elem) {\n if (elem.tagName === 'g') {\n walkTree(elem, function (e) { if (e.nodeName !== 'g') { elems.push(e); } });\n } else {\n elems.push(elem);\n }\n }\n }\n if (elems.length > 0) {\n changeSelectedAttribute(attr, val, elems);\n call('changed', selectedElements);\n }\n};\n\n/**\n* @typedef {PlainObject} module:svgcanvas.StyleOptions\n* @property {string} fill\n* @property {Float} fill_opacity\n* @property {string} stroke\n* @property {Float} stroke_width\n* @property {string} stroke_dasharray\n* @property {string} stroke_linejoin\n* @property {string} stroke_linecap\n* @property {Float} stroke_opacity\n* @property {Float} opacity\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getStyle\n* @returns {module:svgcanvas.StyleOptions} current style options\n*/\nthis.getStyle = function () {\n return curShape;\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getOpacity\n* @returns {Float} the current opacity\n*/\nthis.getOpacity = getOpacity;\n\n/**\n* Sets the given opacity on the current selected elements.\n* @function module:svgcanvas.SvgCanvas#setOpacity\n* @param {string} val\n* @returns {void}\n*/\nthis.setOpacity = function (val) {\n curShape.opacity = val;\n changeSelectedAttribute('opacity', val);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFillOpacity\n* @returns {Float} the current fill opacity\n*/\nthis.getFillOpacity = function () {\n return curShape.fill_opacity;\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getStrokeOpacity\n* @returns {string} the current stroke opacity\n*/\nthis.getStrokeOpacity = function () {\n return curShape.stroke_opacity;\n};\n\n/**\n* Sets the current fill/stroke opacity.\n* @function module:svgcanvas.SvgCanvas#setPaintOpacity\n* @param {string} type - String with \"fill\" or \"stroke\"\n* @param {Float} val - Float with the new opacity value\n* @param {boolean} preventUndo - Indicates whether or not this should be an undoable action\n* @returns {void}\n*/\nthis.setPaintOpacity = function (type, val, preventUndo) {\n curShape[type + '_opacity'] = val;\n if (!preventUndo) {\n changeSelectedAttribute(type + '-opacity', val);\n } else {\n changeSelectedAttributeNoUndo(type + '-opacity', val);\n }\n};\n\n/**\n* Gets the current fill/stroke opacity.\n* @function module:svgcanvas.SvgCanvas#getPaintOpacity\n* @param {\"fill\"|\"stroke\"} type - String with \"fill\" or \"stroke\"\n* @returns {Float} Fill/stroke opacity\n*/\nthis.getPaintOpacity = function (type) {\n return type === 'fill' ? this.getFillOpacity() : this.getStrokeOpacity();\n};\n\n/**\n* Gets the `stdDeviation` blur value of the given element.\n* @function module:svgcanvas.SvgCanvas#getBlur\n* @param {Element} elem - The element to check the blur value for\n* @returns {string} stdDeviation blur attribute value\n*/\nthis.getBlur = function (elem) {\n let val = 0;\n // const elem = selectedElements[0];\n\n if (elem) {\n const filterUrl = elem.getAttribute('filter');\n if (filterUrl) {\n const blur = getElem(elem.id + '_blur');\n if (blur) {\n val = blur.firstChild.getAttribute('stdDeviation');\n }\n }\n }\n return val;\n};\n\n(function () {\nlet curCommand = null;\nlet filter = null;\nlet filterHidden = false;\n\n/**\n* Sets the `stdDeviation` blur value on the selected element without being undoable.\n* @function module:svgcanvas.SvgCanvas#setBlurNoUndo\n* @param {Float} val - The new `stdDeviation` value\n* @returns {void}\n*/\ncanvas.setBlurNoUndo = function (val) {\n if (!filter) {\n canvas.setBlur(val);\n return;\n }\n if (val === 0) {\n // Don't change the StdDev, as that will hide the element.\n // Instead, just remove the value for \"filter\"\n changeSelectedAttributeNoUndo('filter', '');\n filterHidden = true;\n } else {\n const elem = selectedElements[0];\n if (filterHidden) {\n changeSelectedAttributeNoUndo('filter', 'url(#' + elem.id + '_blur)');\n }\n if (isWebkit()) {\n // console.log('e', elem); // eslint-disable-line no-console\n elem.removeAttribute('filter');\n elem.setAttribute('filter', 'url(#' + elem.id + '_blur)');\n }\n changeSelectedAttributeNoUndo('stdDeviation', val, [filter.firstChild]);\n canvas.setBlurOffsets(filter, val);\n }\n};\n\n/**\n *\n * @returns {void}\n */\nfunction finishChange () {\n const bCmd = canvas.undoMgr.finishUndoableChange();\n curCommand.addSubCommand(bCmd);\n addCommandToHistory(curCommand);\n curCommand = null;\n filter = null;\n}\n\n/**\n* Sets the `x`, `y`, `width`, `height` values of the filter element in order to\n* make the blur not be clipped. Removes them if not neeeded.\n* @function module:svgcanvas.SvgCanvas#setBlurOffsets\n* @param {Element} filterElem - The filter DOM element to update\n* @param {Float} stdDev - The standard deviation value on which to base the offset size\n* @returns {void}\n*/\ncanvas.setBlurOffsets = function (filterElem, stdDev) {\n if (stdDev > 3) {\n // TODO: Create algorithm here where size is based on expected blur\n assignAttributes(filterElem, {\n x: '-50%',\n y: '-50%',\n width: '200%',\n height: '200%'\n }, 100);\n // Removing these attributes hides text in Chrome (see Issue 579)\n } else if (!isWebkit()) {\n filterElem.removeAttribute('x');\n filterElem.removeAttribute('y');\n filterElem.removeAttribute('width');\n filterElem.removeAttribute('height');\n }\n};\n\n/**\n* Adds/updates the blur filter to the selected element.\n* @function module:svgcanvas.SvgCanvas#setBlur\n* @param {Float} val - Float with the new `stdDeviation` blur value\n* @param {boolean} complete - Whether or not the action should be completed (to add to the undo manager)\n* @returns {void}\n*/\ncanvas.setBlur = function (val, complete) {\n if (curCommand) {\n finishChange();\n return;\n }\n\n // Looks for associated blur, creates one if not found\n const elem = selectedElements[0];\n const elemId = elem.id;\n filter = getElem(elemId + '_blur');\n\n val -= 0;\n\n const batchCmd = new BatchCommand();\n\n // Blur found!\n if (filter) {\n if (val === 0) {\n filter = null;\n }\n } else {\n // Not found, so create\n const newblur = addSVGElementFromJson({element: 'feGaussianBlur',\n attr: {\n in: 'SourceGraphic',\n stdDeviation: val\n }\n });\n\n filter = addSVGElementFromJson({element: 'filter',\n attr: {\n id: elemId + '_blur'\n }\n });\n\n filter.append(newblur);\n findDefs().append(filter);\n\n batchCmd.addSubCommand(new InsertElementCommand(filter));\n }\n\n const changes = {filter: elem.getAttribute('filter')};\n\n if (val === 0) {\n elem.removeAttribute('filter');\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n return;\n }\n\n changeSelectedAttribute('filter', 'url(#' + elemId + '_blur)');\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n canvas.setBlurOffsets(filter, val);\n\n curCommand = batchCmd;\n canvas.undoMgr.beginUndoableChange('stdDeviation', [filter ? filter.firstChild : null]);\n if (complete) {\n canvas.setBlurNoUndo(val);\n finishChange();\n }\n};\n}());\n\n/**\n* Check whether selected element is bold or not.\n* @function module:svgcanvas.SvgCanvas#getBold\n* @returns {boolean} Indicates whether or not element is bold\n*/\nthis.getBold = function () {\n // should only have one element selected\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n return (selected.getAttribute('font-weight') === 'bold');\n }\n return false;\n};\n\n/**\n* Make the selected element bold or normal.\n* @function module:svgcanvas.SvgCanvas#setBold\n* @param {boolean} b - Indicates bold (`true`) or normal (`false`)\n* @returns {void}\n*/\nthis.setBold = function (b) {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n changeSelectedAttribute('font-weight', b ? 'bold' : 'normal');\n }\n if (!selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* Check whether selected element is in italics or not.\n* @function module:svgcanvas.SvgCanvas#getItalic\n* @returns {boolean} Indicates whether or not element is italic\n*/\nthis.getItalic = function () {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n return (selected.getAttribute('font-style') === 'italic');\n }\n return false;\n};\n\n/**\n* Make the selected element italic or normal.\n* @function module:svgcanvas.SvgCanvas#setItalic\n* @param {boolean} i - Indicates italic (`true`) or normal (`false`)\n* @returns {void}\n*/\nthis.setItalic = function (i) {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n changeSelectedAttribute('font-style', i ? 'italic' : 'normal');\n }\n if (!selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFontFamily\n* @returns {string} The current font family\n*/\nthis.getFontFamily = function () {\n return curText.font_family;\n};\n\n/**\n* Set the new font family.\n* @function module:svgcanvas.SvgCanvas#setFontFamily\n* @param {string} val - String with the new font family\n* @returns {void}\n*/\nthis.setFontFamily = function (val) {\n curText.font_family = val;\n changeSelectedAttribute('font-family', val);\n if (selectedElements[0] && !selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* Set the new font color.\n* @function module:svgcanvas.SvgCanvas#setFontColor\n* @param {string} val - String with the new font color\n* @returns {void}\n*/\nthis.setFontColor = function (val) {\n curText.fill = val;\n changeSelectedAttribute('fill', val);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFontColor\n* @returns {string} The current font color\n*/\nthis.getFontColor = function () {\n return curText.fill;\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFontSize\n* @returns {Float} The current font size\n*/\nthis.getFontSize = function () {\n return curText.font_size;\n};\n\n/**\n* Applies the given font size to the selected element.\n* @function module:svgcanvas.SvgCanvas#setFontSize\n* @param {Float} val - Float with the new font size\n* @returns {void}\n*/\nthis.setFontSize = function (val) {\n curText.font_size = val;\n changeSelectedAttribute('font-size', val);\n if (!selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getText\n* @returns {string} The current text (`textContent`) of the selected element\n*/\nthis.getText = function () {\n const selected = selectedElements[0];\n if (isNullish(selected)) { return ''; }\n return selected.textContent;\n};\n\n/**\n* Updates the text element with the given string.\n* @function module:svgcanvas.SvgCanvas#setTextContent\n* @param {string} val - String with the new text\n* @returns {void}\n*/\nthis.setTextContent = function (val) {\n changeSelectedAttribute('#text', val);\n textActions.init(val);\n textActions.setCursor();\n};\n\n/**\n* Sets the new image URL for the selected image element. Updates its size if\n* a new URL is given.\n* @function module:svgcanvas.SvgCanvas#setImageURL\n* @param {string} val - String with the image URL/path\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setImageURL = function (val) {\n const elem = selectedElements[0];\n if (!elem) { return; }\n\n const attrs = $(elem).attr(['width', 'height']);\n const setsize = (!attrs.width || !attrs.height);\n\n const curHref = getHref(elem);\n\n // Do nothing if no URL change or size change\n if (curHref === val && !setsize) {\n return;\n }\n\n const batchCmd = new BatchCommand('Change Image URL');\n\n setHref(elem, val);\n batchCmd.addSubCommand(new ChangeElementCommand(elem, {\n '#href': curHref\n }));\n\n $(new Image()).load(function () {\n const changes = $(elem).attr(['width', 'height']);\n\n $(elem).attr({\n width: this.width,\n height: this.height\n });\n\n selectorManager.requestSelector(elem).resize();\n\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n addCommandToHistory(batchCmd);\n call('changed', [elem]);\n }).attr('src', val);\n};\n\n/**\n* Sets the new link URL for the selected anchor element.\n* @function module:svgcanvas.SvgCanvas#setLinkURL\n* @param {string} val - String with the link URL/path\n* @returns {void}\n*/\nthis.setLinkURL = function (val) {\n let elem = selectedElements[0];\n if (!elem) { return; }\n if (elem.tagName !== 'a') {\n // See if parent is an anchor\n const parentsA = $(elem).parents('a');\n if (parentsA.length) {\n elem = parentsA[0];\n } else {\n return;\n }\n }\n\n const curHref = getHref(elem);\n\n if (curHref === val) { return; }\n\n const batchCmd = new BatchCommand('Change Link URL');\n\n setHref(elem, val);\n batchCmd.addSubCommand(new ChangeElementCommand(elem, {\n '#href': curHref\n }));\n\n addCommandToHistory(batchCmd);\n};\n\n/**\n* Sets the `rx` and `ry` values to the selected `rect` element\n* to change its corner radius.\n* @function module:svgcanvas.SvgCanvas#setRectRadius\n* @param {string|Float} val - The new radius\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setRectRadius = function (val) {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'rect') {\n const r = selected.getAttribute('rx');\n if (r !== String(val)) {\n selected.setAttribute('rx', val);\n selected.setAttribute('ry', val);\n addCommandToHistory(new ChangeElementCommand(selected, {rx: r, ry: r}, 'Radius'));\n call('changed', [selected]);\n }\n }\n};\n\n/**\n* Wraps the selected element(s) in an anchor element or converts group to one.\n* @function module:svgcanvas.SvgCanvas#makeHyperlink\n* @param {string} url\n* @returns {void}\n*/\nthis.makeHyperlink = function (url) {\n canvas.groupSelectedElements('a', url);\n\n // TODO: If element is a single \"g\", convert to \"a\"\n // if (selectedElements.length > 1 && selectedElements[1]) {\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#removeHyperlink\n* @returns {void}\n*/\nthis.removeHyperlink = function () {\n canvas.ungroupSelectedElement();\n};\n\n/**\n* Group: Element manipulation.\n*/\n\n/**\n* Sets the new segment type to the selected segment(s).\n* @function module:svgcanvas.SvgCanvas#setSegType\n* @param {Integer} newType - New segment type. See {@link https://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSeg} for list\n* @returns {void}\n*/\nthis.setSegType = function (newType) {\n pathActions.setSegType(newType);\n};\n\n/**\n* Convert selected element to a path, or get the BBox of an element-as-path.\n* @function module:svgcanvas.SvgCanvas#convertToPath\n* @todo (codedread): Remove the getBBox argument and split this function into two.\n* @param {Element} elem - The DOM element to be converted\n* @param {boolean} getBBox - Boolean on whether or not to only return the path's BBox\n* @returns {void|DOMRect|false|SVGPathElement|null} If the getBBox flag is true, the resulting path's bounding box object.\n* Otherwise the resulting path element is returned.\n*/\nthis.convertToPath = function (elem, getBBox) {\n if (isNullish(elem)) {\n const elems = selectedElements;\n $.each(elems, function (i, el) {\n if (el) { canvas.convertToPath(el); }\n });\n return undefined;\n }\n if (getBBox) {\n return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);\n }\n // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem?\n // TODO: If convertToPath is called with one elem, curShape and elem are probably the same; but calling with multiple is a bug or cool feature.\n const attrs = {\n fill: curShape.fill,\n 'fill-opacity': curShape.fill_opacity,\n stroke: curShape.stroke,\n 'stroke-width': curShape.stroke_width,\n 'stroke-dasharray': curShape.stroke_dasharray,\n 'stroke-linejoin': curShape.stroke_linejoin,\n 'stroke-linecap': curShape.stroke_linecap,\n 'stroke-opacity': curShape.stroke_opacity,\n opacity: curShape.opacity,\n visibility: 'hidden'\n };\n return convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory);\n};\n\n/**\n* This function makes the changes to the elements. It does not add the change\n* to the history stack.\n* @param {string} attr - Attribute name\n* @param {string|Float} newValue - String or number with the new attribute value\n* @param {Element[]} elems - The DOM elements to apply the change to\n* @returns {void}\n*/\nconst changeSelectedAttributeNoUndo = function (attr, newValue, elems) {\n if (currentMode === 'pathedit') {\n // Editing node\n pathActions.moveNode(attr, newValue);\n }\n elems = elems || selectedElements;\n let i = elems.length;\n const noXYElems = ['g', 'polyline', 'path'];\n // const goodGAttrs = ['transform', 'opacity', 'filter'];\n\n while (i--) {\n let elem = elems[i];\n if (isNullish(elem)) { continue; }\n\n // Set x,y vals on elements that don't have them\n if ((attr === 'x' || attr === 'y') && noXYElems.includes(elem.tagName)) {\n const bbox = getStrokedBBoxDefaultVisible([elem]);\n const diffX = attr === 'x' ? newValue - bbox.x : 0;\n const diffY = attr === 'y' ? newValue - bbox.y : 0;\n canvas.moveSelectedElements(diffX * currentZoom, diffY * currentZoom, true);\n continue;\n }\n\n // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky\n // TODO: Missing statement body\n // if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {}\n let oldval = attr === '#text' ? elem.textContent : elem.getAttribute(attr);\n if (isNullish(oldval)) { oldval = ''; }\n if (oldval !== String(newValue)) {\n if (attr === '#text') {\n // const oldW = utilsGetBBox(elem).width;\n elem.textContent = newValue;\n\n // FF bug occurs on on rotated elements\n if ((/rotate/).test(elem.getAttribute('transform'))) {\n elem = ffClone(elem);\n }\n // Hoped to solve the issue of moving text with text-anchor=\"start\",\n // but this doesn't actually fix it. Hopefully on the right track, though. -Fyrd\n // const box = getBBox(elem), left = box.x, top = box.y, {width, height} = box,\n // dx = width - oldW, dy = 0;\n // const angle = getRotationAngle(elem, true);\n // if (angle) {\n // const r = Math.sqrt(dx * dx + dy * dy);\n // const theta = Math.atan2(dy, dx) - angle;\n // dx = r * Math.cos(theta);\n // dy = r * Math.sin(theta);\n //\n // elem.setAttribute('x', elem.getAttribute('x') - dx);\n // elem.setAttribute('y', elem.getAttribute('y') - dy);\n // }\n } else if (attr === '#href') {\n setHref(elem, newValue);\n } else { elem.setAttribute(attr, newValue); }\n\n // Go into \"select\" mode for text changes\n // NOTE: Important that this happens AFTER elem.setAttribute() or else attributes like\n // font-size can get reset to their old value, ultimately by svgEditor.updateContextPanel(),\n // after calling textActions.toSelectMode() below\n if (currentMode === 'textedit' && attr !== '#text' && elem.textContent.length) {\n textActions.toSelectMode(elem);\n }\n\n // if (i === 0) {\n // selectedBBoxes[0] = utilsGetBBox(elem);\n // }\n\n // Use the Firefox ffClone hack for text elements with gradients or\n // where other text attributes are changed.\n if (isGecko() && elem.nodeName === 'text' && (/rotate/).test(elem.getAttribute('transform'))) {\n if (String(newValue).startsWith('url') || (['font-size', 'font-family', 'x', 'y'].includes(attr) && elem.textContent)) {\n elem = ffClone(elem);\n }\n }\n // Timeout needed for Opera & Firefox\n // codedread: it is now possible for this function to be called with elements\n // that are not in the selectedElements array, we need to only request a\n // selector if the element is in that array\n if (selectedElements.includes(elem)) {\n setTimeout(function () {\n // Due to element replacement, this element may no longer\n // be part of the DOM\n if (!elem.parentNode) { return; }\n selectorManager.requestSelector(elem).resize();\n }, 0);\n }\n // if this element was rotated, and we changed the position of this element\n // we need to update the rotational transform attribute\n const angle = getRotationAngle(elem);\n if (angle !== 0 && attr !== 'transform') {\n const tlist = getTransformList(elem);\n let n = tlist.numberOfItems;\n while (n--) {\n const xform = tlist.getItem(n);\n if (xform.type === 4) {\n // remove old rotate\n tlist.removeItem(n);\n\n const box = utilsGetBBox(elem);\n const center = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix);\n const cx = center.x,\n cy = center.y;\n const newrot = svgroot.createSVGTransform();\n newrot.setRotate(angle, cx, cy);\n tlist.insertItemBefore(newrot, n);\n break;\n }\n }\n }\n } // if oldValue != newValue\n } // for each elem\n};\n\n/**\n* Change the given/selected element and add the original value to the history stack.\n* If you want to change all `selectedElements`, ignore the `elems` argument.\n* If you want to change only a subset of `selectedElements`, then send the\n* subset to this function in the `elems` argument.\n* @function module:svgcanvas.SvgCanvas#changeSelectedAttribute\n* @param {string} attr - String with the attribute name\n* @param {string|Float} val - String or number with the new attribute value\n* @param {Element[]} elems - The DOM elements to apply the change to\n* @returns {void}\n*/\nconst changeSelectedAttribute = this.changeSelectedAttribute = function (attr, val, elems) {\n elems = elems || selectedElements;\n canvas.undoMgr.beginUndoableChange(attr, elems);\n // const i = elems.length;\n\n changeSelectedAttributeNoUndo(attr, val, elems);\n\n const batchCmd = canvas.undoMgr.finishUndoableChange();\n if (!batchCmd.isEmpty()) {\n addCommandToHistory(batchCmd);\n }\n};\n\n/**\n* Removes all selected elements from the DOM and adds the change to the\n* history stack.\n* @function module:svgcanvas.SvgCanvas#deleteSelectedElements\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.deleteSelectedElements = function () {\n const batchCmd = new BatchCommand('Delete Elements');\n const len = selectedElements.length;\n const selectedCopy = []; // selectedElements is being deleted\n\n for (let i = 0; i < len; ++i) {\n const selected = selectedElements[i];\n if (isNullish(selected)) { break; }\n\n let parent = selected.parentNode;\n let t = selected;\n\n // this will unselect the element and remove the selectedOutline\n selectorManager.releaseSelector(t);\n\n // Remove the path if present.\n pathModule.removePath_(t.id);\n\n // Get the parent if it's a single-child anchor\n if (parent.tagName === 'a' && parent.childNodes.length === 1) {\n t = parent;\n parent = parent.parentNode;\n }\n\n const {nextSibling} = t;\n t.remove();\n const elem = t;\n selectedCopy.push(selected); // for the copy\n batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent));\n }\n selectedElements = [];\n\n if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); }\n call('changed', selectedCopy);\n clearSelection();\n};\n\n/**\n* Removes all selected elements from the DOM and adds the change to the\n* history stack. Remembers removed elements on the clipboard.\n* @function module:svgcanvas.SvgCanvas#cutSelectedElements\n* @returns {void}\n*/\nthis.cutSelectedElements = function () {\n canvas.copySelectedElements();\n canvas.deleteSelectedElements();\n};\n\nconst CLIPBOARD_ID = 'svgedit_clipboard';\n\n/**\n* Flash the clipboard data momentarily on localStorage so all tabs can see.\n* @returns {void}\n*/\nfunction flashStorage () {\n const data = sessionStorage.getItem(CLIPBOARD_ID);\n localStorage.setItem(CLIPBOARD_ID, data);\n setTimeout(function () {\n localStorage.removeItem(CLIPBOARD_ID);\n }, 1);\n}\n\n/**\n* Transfers sessionStorage from one tab to another.\n* @param {!Event} ev Storage event.\n* @returns {void}\n*/\nfunction storageChange (ev) {\n if (!ev.newValue) return; // This is a call from removeItem.\n if (ev.key === CLIPBOARD_ID + '_startup') {\n // Another tab asked for our sessionStorage.\n localStorage.removeItem(CLIPBOARD_ID + '_startup');\n flashStorage();\n } else if (ev.key === CLIPBOARD_ID) {\n // Another tab sent data.\n sessionStorage.setItem(CLIPBOARD_ID, ev.newValue);\n }\n}\n\n// Listen for changes to localStorage.\nwindow.addEventListener('storage', storageChange, false);\n// Ask other tabs for sessionStorage (this is ONLY to trigger event).\nlocalStorage.setItem(CLIPBOARD_ID + '_startup', Math.random());\n\n/**\n* Remembers the current selected elements on the clipboard.\n* @function module:svgcanvas.SvgCanvas#copySelectedElements\n* @returns {void}\n*/\nthis.copySelectedElements = function () {\n const data =\n JSON.stringify(selectedElements.map((x) => getJsonFromSvgElement(x)));\n // Use sessionStorage for the clipboard data.\n sessionStorage.setItem(CLIPBOARD_ID, data);\n flashStorage();\n\n const menu = $('#cmenu_canvas');\n // Context menu might not exist (it is provided by editor.js).\n if (menu.enableContextMenuItems) {\n menu.enableContextMenuItems('#paste,#paste_in_place');\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#pasteElements\n* @param {\"in_place\"|\"point\"|void} type\n* @param {Integer|void} x Expected if type is \"point\"\n* @param {Integer|void} y Expected if type is \"point\"\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @fires module:svgcanvas.SvgCanvas#event:ext_IDsUpdated\n* @returns {void}\n*/\nthis.pasteElements = function (type, x, y) {\n let clipb = JSON.parse(sessionStorage.getItem(CLIPBOARD_ID));\n if (!clipb) return;\n let len = clipb.length;\n if (!len) return;\n\n const pasted = [];\n const batchCmd = new BatchCommand('Paste elements');\n // const drawing = getCurrentDrawing();\n /**\n * @typedef {PlainObject<string, string>} module:svgcanvas.ChangedIDs\n */\n /**\n * @type {module:svgcanvas.ChangedIDs}\n */\n const changedIDs = {};\n\n // Recursively replace IDs and record the changes\n /**\n *\n * @param {module:svgcanvas.SVGAsJSON} elem\n * @returns {void}\n */\n function checkIDs (elem) {\n if (elem.attr && elem.attr.id) {\n changedIDs[elem.attr.id] = getNextId();\n elem.attr.id = changedIDs[elem.attr.id];\n }\n if (elem.children) elem.children.forEach(checkIDs);\n }\n clipb.forEach(checkIDs);\n\n // Give extensions like the connector extension a chance to reflect new IDs and remove invalid elements\n /**\n * Triggered when `pasteElements` is called from a paste action (context menu or key).\n * @event module:svgcanvas.SvgCanvas#event:ext_IDsUpdated\n * @type {PlainObject}\n * @property {module:svgcanvas.SVGAsJSON[]} elems\n * @property {module:svgcanvas.ChangedIDs} changes Maps past ID (on attribute) to current ID\n */\n runExtensions(\n 'IDsUpdated',\n /** @type {module:svgcanvas.SvgCanvas#event:ext_IDsUpdated} */\n {elems: clipb, changes: changedIDs},\n true\n ).forEach(function (extChanges) {\n if (!extChanges || !('remove' in extChanges)) return;\n\n extChanges.remove.forEach(function (removeID) {\n clipb = clipb.filter(function (clipBoardItem) {\n return clipBoardItem.attr.id !== removeID;\n });\n });\n });\n\n // Move elements to lastClickPoint\n while (len--) {\n const elem = clipb[len];\n if (!elem) { continue; }\n\n const copy = addSVGElementFromJson(elem);\n pasted.push(copy);\n batchCmd.addSubCommand(new InsertElementCommand(copy));\n\n restoreRefElems(copy);\n }\n\n selectOnly(pasted);\n\n if (type !== 'in_place') {\n let ctrX, ctrY;\n\n if (!type) {\n ctrX = lastClickPoint.x;\n ctrY = lastClickPoint.y;\n } else if (type === 'point') {\n ctrX = x;\n ctrY = y;\n }\n\n const bbox = getStrokedBBoxDefaultVisible(pasted);\n const cx = ctrX - (bbox.x + bbox.width / 2),\n cy = ctrY - (bbox.y + bbox.height / 2),\n dx = [],\n dy = [];\n\n $.each(pasted, function (i, item) {\n dx.push(cx);\n dy.push(cy);\n });\n\n const cmd = canvas.moveSelectedElements(dx, dy, false);\n if (cmd) batchCmd.addSubCommand(cmd);\n }\n\n addCommandToHistory(batchCmd);\n call('changed', pasted);\n};\n\n/**\n* Wraps all the selected elements in a group (`g`) element.\n* @function module:svgcanvas.SvgCanvas#groupSelectedElements\n* @param {\"a\"|\"g\"} [type=\"g\"] - type of element to group into, defaults to `<g>`\n* @param {string} [urlArg]\n* @returns {void}\n*/\nthis.groupSelectedElements = function (type, urlArg) {\n if (!type) { type = 'g'; }\n let cmdStr = '';\n let url;\n\n switch (type) {\n case 'a': {\n cmdStr = 'Make hyperlink';\n url = urlArg || '';\n break;\n } default: {\n type = 'g';\n cmdStr = 'Group Elements';\n break;\n }\n }\n\n const batchCmd = new BatchCommand(cmdStr);\n\n // create and insert the group element\n const g = addSVGElementFromJson({\n element: type,\n attr: {\n id: getNextId()\n }\n });\n if (type === 'a') {\n setHref(g, url);\n }\n batchCmd.addSubCommand(new InsertElementCommand(g));\n\n // now move all children into the group\n let i = selectedElements.length;\n while (i--) {\n let elem = selectedElements[i];\n if (isNullish(elem)) { continue; }\n\n if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) {\n elem = elem.parentNode;\n }\n\n const oldNextSibling = elem.nextSibling;\n const oldParent = elem.parentNode;\n g.append(elem);\n batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));\n }\n if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); }\n\n // update selection\n selectOnly([g], true);\n};\n\n/**\n* Pushes all appropriate parent group properties down to its children, then\n* removes them from the group.\n* @function module:svgcanvas.SvgCanvas#pushGroupProperties\n* @param {SVGAElement|SVGGElement} g\n* @param {boolean} undoable\n* @returns {BatchCommand|void}\n*/\nconst pushGroupProperties = this.pushGroupProperties = function (g, undoable) {\n const children = g.childNodes;\n const len = children.length;\n const xform = g.getAttribute('transform');\n\n const glist = getTransformList(g);\n const m = transformListToTransform(glist).matrix;\n\n const batchCmd = new BatchCommand('Push group properties');\n\n // TODO: get all fill/stroke properties from the group that we are about to destroy\n // \"fill\", \"fill-opacity\", \"fill-rule\", \"stroke\", \"stroke-dasharray\", \"stroke-dashoffset\",\n // \"stroke-linecap\", \"stroke-linejoin\", \"stroke-miterlimit\", \"stroke-opacity\",\n // \"stroke-width\"\n // and then for each child, if they do not have the attribute (or the value is 'inherit')\n // then set the child's attribute\n\n const gangle = getRotationAngle(g);\n\n const gattrs = $(g).attr(['filter', 'opacity']);\n let gfilter, gblur, changes;\n const drawing = getCurrentDrawing();\n\n for (let i = 0; i < len; i++) {\n const elem = children[i];\n\n if (elem.nodeType !== 1) { continue; }\n\n if (gattrs.opacity !== null && gattrs.opacity !== 1) {\n // const c_opac = elem.getAttribute('opacity') || 1;\n const newOpac = Math.round((elem.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100;\n changeSelectedAttribute('opacity', newOpac, [elem]);\n }\n\n if (gattrs.filter) {\n let cblur = this.getBlur(elem);\n const origCblur = cblur;\n if (!gblur) { gblur = this.getBlur(g); }\n if (cblur) {\n // Is this formula correct?\n cblur = Number(gblur) + Number(cblur);\n } else if (cblur === 0) {\n cblur = gblur;\n }\n\n // If child has no current filter, get group's filter or clone it.\n if (!origCblur) {\n // Set group's filter to use first child's ID\n if (!gfilter) {\n gfilter = getRefElem(gattrs.filter);\n } else {\n // Clone the group's filter\n gfilter = drawing.copyElem(gfilter);\n findDefs().append(gfilter);\n }\n } else {\n gfilter = getRefElem(elem.getAttribute('filter'));\n }\n\n // Change this in future for different filters\n const suffix = (gfilter.firstChild.tagName === 'feGaussianBlur') ? 'blur' : 'filter';\n gfilter.id = elem.id + '_' + suffix;\n changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [elem]);\n\n // Update blur value\n if (cblur) {\n changeSelectedAttribute('stdDeviation', cblur, [gfilter.firstChild]);\n canvas.setBlurOffsets(gfilter, cblur);\n }\n }\n\n let chtlist = getTransformList(elem);\n\n // Don't process gradient transforms\n if (elem.tagName.includes('Gradient')) { chtlist = null; }\n\n // Hopefully not a problem to add this. Necessary for elements like <desc/>\n if (!chtlist) { continue; }\n\n // Apparently <defs> can get get a transformlist, but we don't want it to have one!\n if (elem.tagName === 'defs') { continue; }\n\n if (glist.numberOfItems) {\n // TODO: if the group's transform is just a rotate, we can always transfer the\n // rotate() down to the children (collapsing consecutive rotates and factoring\n // out any translates)\n if (gangle && glist.numberOfItems === 1) {\n // [Rg] [Rc] [Mc]\n // we want [Tr] [Rc2] [Mc] where:\n // - [Rc2] is at the child's current center but has the\n // sum of the group and child's rotation angles\n // - [Tr] is the equivalent translation that this child\n // undergoes if the group wasn't there\n\n // [Tr] = [Rg] [Rc] [Rc2_inv]\n\n // get group's rotation matrix (Rg)\n const rgm = glist.getItem(0).matrix;\n\n // get child's rotation matrix (Rc)\n let rcm = svgroot.createSVGMatrix();\n const cangle = getRotationAngle(elem);\n if (cangle) {\n rcm = chtlist.getItem(0).matrix;\n }\n\n // get child's old center of rotation\n const cbox = utilsGetBBox(elem);\n const ceqm = transformListToTransform(chtlist).matrix;\n const coldc = transformPoint(cbox.x + cbox.width / 2, cbox.y + cbox.height / 2, ceqm);\n\n // sum group and child's angles\n const sangle = gangle + cangle;\n\n // get child's rotation at the old center (Rc2_inv)\n const r2 = svgroot.createSVGTransform();\n r2.setRotate(sangle, coldc.x, coldc.y);\n\n // calculate equivalent translate\n const trm = matrixMultiply(rgm, rcm, r2.matrix.inverse());\n\n // set up tlist\n if (cangle) {\n chtlist.removeItem(0);\n }\n\n if (sangle) {\n if (chtlist.numberOfItems) {\n chtlist.insertItemBefore(r2, 0);\n } else {\n chtlist.appendItem(r2);\n }\n }\n\n if (trm.e || trm.f) {\n const tr = svgroot.createSVGTransform();\n tr.setTranslate(trm.e, trm.f);\n if (chtlist.numberOfItems) {\n chtlist.insertItemBefore(tr, 0);\n } else {\n chtlist.appendItem(tr);\n }\n }\n } else { // more complicated than just a rotate\n // transfer the group's transform down to each child and then\n // call recalculateDimensions()\n const oldxform = elem.getAttribute('transform');\n changes = {};\n changes.transform = oldxform || '';\n\n const newxform = svgroot.createSVGTransform();\n\n // [ gm ] [ chm ] = [ chm ] [ gm' ]\n // [ gm' ] = [ chmInv ] [ gm ] [ chm ]\n const chm = transformListToTransform(chtlist).matrix,\n chmInv = chm.inverse();\n const gm = matrixMultiply(chmInv, m, chm);\n newxform.setMatrix(gm);\n chtlist.appendItem(newxform);\n }\n const cmd = recalculateDimensions(elem);\n if (cmd) { batchCmd.addSubCommand(cmd); }\n }\n }\n\n // remove transform and make it undo-able\n if (xform) {\n changes = {};\n changes.transform = xform;\n g.setAttribute('transform', '');\n g.removeAttribute('transform');\n batchCmd.addSubCommand(new ChangeElementCommand(g, changes));\n }\n\n if (undoable && !batchCmd.isEmpty()) {\n return batchCmd;\n }\n return undefined;\n};\n\n/**\n* Unwraps all the elements in a selected group (`g`) element. This requires\n* significant recalculations to apply group's transforms, etc. to its children.\n* @function module:svgcanvas.SvgCanvas#ungroupSelectedElement\n* @returns {void}\n*/\nthis.ungroupSelectedElement = function () {\n let g = selectedElements[0];\n if (!g) {\n return;\n }\n if ($(g).data('gsvg') || $(g).data('symbol')) {\n // Is svg, so actually convert to group\n convertToGroup(g);\n return;\n }\n if (g.tagName === 'use') {\n // Somehow doesn't have data set, so retrieve\n const symbol = getElem(getHref(g).substr(1));\n $(g).data('symbol', symbol).data('ref', symbol);\n convertToGroup(g);\n return;\n }\n const parentsA = $(g).parents('a');\n if (parentsA.length) {\n g = parentsA[0];\n }\n\n // Look for parent \"a\"\n if (g.tagName === 'g' || g.tagName === 'a') {\n const batchCmd = new BatchCommand('Ungroup Elements');\n const cmd = pushGroupProperties(g, true);\n if (cmd) { batchCmd.addSubCommand(cmd); }\n\n const parent = g.parentNode;\n const anchor = g.nextSibling;\n const children = new Array(g.childNodes.length);\n\n let i = 0;\n while (g.firstChild) {\n const elem = g.firstChild;\n const oldNextSibling = elem.nextSibling;\n const oldParent = elem.parentNode;\n\n // Remove child title elements\n if (elem.tagName === 'title') {\n const {nextSibling} = elem;\n batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, oldParent));\n elem.remove();\n continue;\n }\n\n if (anchor) {\n anchor.before(elem);\n } else {\n g.after(elem);\n }\n children[i++] = elem;\n batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));\n }\n\n // remove the group from the selection\n clearSelection();\n\n // delete the group element (but make undo-able)\n const gNextSibling = g.nextSibling;\n g.remove();\n batchCmd.addSubCommand(new RemoveElementCommand(g, gNextSibling, parent));\n\n if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); }\n\n // update selection\n addToSelection(children);\n }\n};\n\n/**\n* Repositions the selected element to the bottom in the DOM to appear on top of\n* other elements.\n* @function module:svgcanvas.SvgCanvas#moveToTopSelectedElement\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.moveToTopSelectedElement = function () {\n const [selected] = selectedElements;\n if (!isNullish(selected)) {\n let t = selected;\n const oldParent = t.parentNode;\n const oldNextSibling = t.nextSibling;\n t = t.parentNode.appendChild(t);\n // If the element actually moved position, add the command and fire the changed\n // event handler.\n if (oldNextSibling !== t.nextSibling) {\n addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'top'));\n call('changed', [t]);\n }\n }\n};\n\n/**\n* Repositions the selected element to the top in the DOM to appear under\n* other elements.\n* @function module:svgcanvas.SvgCanvas#moveToBottomSelectedElement\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.moveToBottomSelectedElement = function () {\n const [selected] = selectedElements;\n if (!isNullish(selected)) {\n let t = selected;\n const oldParent = t.parentNode;\n const oldNextSibling = t.nextSibling;\n let {firstChild} = t.parentNode;\n if (firstChild.tagName === 'title') {\n firstChild = firstChild.nextSibling;\n }\n // This can probably be removed, as the defs should not ever apppear\n // inside a layer group\n if (firstChild.tagName === 'defs') {\n firstChild = firstChild.nextSibling;\n }\n t = t.parentNode.insertBefore(t, firstChild);\n // If the element actually moved position, add the command and fire the changed\n // event handler.\n if (oldNextSibling !== t.nextSibling) {\n addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'bottom'));\n call('changed', [t]);\n }\n }\n};\n\n/**\n* Moves the select element up or down the stack, based on the visibly\n* intersecting elements.\n* @function module:svgcanvas.SvgCanvas#moveUpDownSelected\n* @param {\"Up\"|\"Down\"} dir - String that's either 'Up' or 'Down'\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.moveUpDownSelected = function (dir) {\n const selected = selectedElements[0];\n if (!selected) { return; }\n\n curBBoxes = [];\n let closest, foundCur;\n // jQuery sorts this list\n const list = $(getIntersectionList(getStrokedBBoxDefaultVisible([selected]))).toArray();\n if (dir === 'Down') { list.reverse(); }\n\n $.each(list, function () {\n if (!foundCur) {\n if (this === selected) {\n foundCur = true;\n }\n return true;\n }\n closest = this; // eslint-disable-line consistent-this\n return false;\n });\n if (!closest) { return; }\n\n const t = selected;\n const oldParent = t.parentNode;\n const oldNextSibling = t.nextSibling;\n $(closest)[dir === 'Down' ? 'before' : 'after'](t);\n // If the element actually moved position, add the command and fire the changed\n // event handler.\n if (oldNextSibling !== t.nextSibling) {\n addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'Move ' + dir));\n call('changed', [t]);\n }\n};\n\n/**\n* Moves selected elements on the X/Y axis.\n* @function module:svgcanvas.SvgCanvas#moveSelectedElements\n* @param {Float} dx - Float with the distance to move on the x-axis\n* @param {Float} dy - Float with the distance to move on the y-axis\n* @param {boolean} undoable - Boolean indicating whether or not the action should be undoable\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {BatchCommand|void} Batch command for the move\n*/\nthis.moveSelectedElements = function (dx, dy, undoable) {\n // if undoable is not sent, default to true\n // if single values, scale them to the zoom\n if (dx.constructor !== Array) {\n dx /= currentZoom;\n dy /= currentZoom;\n }\n undoable = undoable || true;\n const batchCmd = new BatchCommand('position');\n let i = selectedElements.length;\n while (i--) {\n const selected = selectedElements[i];\n if (!isNullish(selected)) {\n // if (i === 0) {\n // selectedBBoxes[0] = utilsGetBBox(selected);\n // }\n // const b = {};\n // for (const j in selectedBBoxes[i]) b[j] = selectedBBoxes[i][j];\n // selectedBBoxes[i] = b;\n\n const xform = svgroot.createSVGTransform();\n const tlist = getTransformList(selected);\n\n // dx and dy could be arrays\n if (dx.constructor === Array) {\n // if (i === 0) {\n // selectedBBoxes[0].x += dx[0];\n // selectedBBoxes[0].y += dy[0];\n // }\n xform.setTranslate(dx[i], dy[i]);\n } else {\n // if (i === 0) {\n // selectedBBoxes[0].x += dx;\n // selectedBBoxes[0].y += dy;\n // }\n xform.setTranslate(dx, dy);\n }\n\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(xform, 0);\n } else {\n tlist.appendItem(xform);\n }\n\n const cmd = recalculateDimensions(selected);\n if (cmd) {\n batchCmd.addSubCommand(cmd);\n }\n\n selectorManager.requestSelector(selected).resize();\n }\n }\n if (!batchCmd.isEmpty()) {\n if (undoable) {\n addCommandToHistory(batchCmd);\n }\n call('changed', selectedElements);\n return batchCmd;\n }\n return undefined;\n};\n\n/**\n* Create deep DOM copies (clones) of all selected elements and move them slightly\n* from their originals.\n* @function module:svgcanvas.SvgCanvas#cloneSelectedElements\n* @param {Float} x Float with the distance to move on the x-axis\n* @param {Float} y Float with the distance to move on the y-axis\n* @returns {void}\n*/\nthis.cloneSelectedElements = function (x, y) {\n let i, elem;\n const batchCmd = new BatchCommand('Clone Elements');\n // find all the elements selected (stop at first null)\n const len = selectedElements.length;\n /**\n * Sorts an array numerically and ascending.\n * @param {Element} a\n * @param {Element} b\n * @returns {Integer}\n */\n function sortfunction (a, b) {\n return ($(b).index() - $(a).index());\n }\n selectedElements.sort(sortfunction);\n for (i = 0; i < len; ++i) {\n elem = selectedElements[i];\n if (isNullish(elem)) { break; }\n }\n // use slice to quickly get the subset of elements we need\n const copiedElements = selectedElements.slice(0, i);\n this.clearSelection(true);\n // note that we loop in the reverse way because of the way elements are added\n // to the selectedElements array (top-first)\n const drawing = getCurrentDrawing();\n i = copiedElements.length;\n while (i--) {\n // clone each element and replace it within copiedElements\n elem = copiedElements[i] = drawing.copyElem(copiedElements[i]);\n (currentGroup || drawing.getCurrentLayer()).append(elem);\n batchCmd.addSubCommand(new InsertElementCommand(elem));\n }\n\n if (!batchCmd.isEmpty()) {\n addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding\n this.moveSelectedElements(x, y, false);\n addCommandToHistory(batchCmd);\n }\n};\n\n/**\n* Aligns selected elements.\n* @function module:svgcanvas.SvgCanvas#alignSelectedElements\n* @param {string} type - String with single character indicating the alignment type\n* @param {\"selected\"|\"largest\"|\"smallest\"|\"page\"} relativeTo\n* @returns {void}\n*/\nthis.alignSelectedElements = function (type, relativeTo) {\n const bboxes = []; // angles = [];\n const len = selectedElements.length;\n if (!len) { return; }\n let minx = Number.MAX_VALUE, maxx = Number.MIN_VALUE,\n miny = Number.MAX_VALUE, maxy = Number.MIN_VALUE;\n let curwidth = Number.MIN_VALUE, curheight = Number.MIN_VALUE;\n for (let i = 0; i < len; ++i) {\n if (isNullish(selectedElements[i])) { break; }\n const elem = selectedElements[i];\n bboxes[i] = getStrokedBBoxDefaultVisible([elem]);\n\n // now bbox is axis-aligned and handles rotation\n switch (relativeTo) {\n case 'smallest':\n if (((type === 'l' || type === 'c' || type === 'r') &&\n (curwidth === Number.MIN_VALUE || curwidth > bboxes[i].width)) ||\n ((type === 't' || type === 'm' || type === 'b') &&\n (curheight === Number.MIN_VALUE || curheight > bboxes[i].height))\n ) {\n minx = bboxes[i].x;\n miny = bboxes[i].y;\n maxx = bboxes[i].x + bboxes[i].width;\n maxy = bboxes[i].y + bboxes[i].height;\n curwidth = bboxes[i].width;\n curheight = bboxes[i].height;\n }\n break;\n case 'largest':\n if (((type === 'l' || type === 'c' || type === 'r') &&\n (curwidth === Number.MIN_VALUE || curwidth < bboxes[i].width)) ||\n ((type === 't' || type === 'm' || type === 'b') &&\n (curheight === Number.MIN_VALUE || curheight < bboxes[i].height))\n ) {\n minx = bboxes[i].x;\n miny = bboxes[i].y;\n maxx = bboxes[i].x + bboxes[i].width;\n maxy = bboxes[i].y + bboxes[i].height;\n curwidth = bboxes[i].width;\n curheight = bboxes[i].height;\n }\n break;\n default: // 'selected'\n if (bboxes[i].x < minx) { minx = bboxes[i].x; }\n if (bboxes[i].y < miny) { miny = bboxes[i].y; }\n if (bboxes[i].x + bboxes[i].width > maxx) { maxx = bboxes[i].x + bboxes[i].width; }\n if (bboxes[i].y + bboxes[i].height > maxy) { maxy = bboxes[i].y + bboxes[i].height; }\n break;\n }\n } // loop for each element to find the bbox and adjust min/max\n\n if (relativeTo === 'page') {\n minx = 0;\n miny = 0;\n maxx = canvas.contentW;\n maxy = canvas.contentH;\n }\n\n const dx = new Array(len);\n const dy = new Array(len);\n for (let i = 0; i < len; ++i) {\n if (isNullish(selectedElements[i])) { break; }\n // const elem = selectedElements[i];\n const bbox = bboxes[i];\n dx[i] = 0;\n dy[i] = 0;\n switch (type) {\n case 'l': // left (horizontal)\n dx[i] = minx - bbox.x;\n break;\n case 'c': // center (horizontal)\n dx[i] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2);\n break;\n case 'r': // right (horizontal)\n dx[i] = maxx - (bbox.x + bbox.width);\n break;\n case 't': // top (vertical)\n dy[i] = miny - bbox.y;\n break;\n case 'm': // middle (vertical)\n dy[i] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2);\n break;\n case 'b': // bottom (vertical)\n dy[i] = maxy - (bbox.y + bbox.height);\n break;\n }\n }\n this.moveSelectedElements(dx, dy);\n};\n\n/**\n* Group: Additional editor tools.\n*/\n\n/**\n* @name module:svgcanvas.SvgCanvas#contentW\n* @type {Float}\n*/\nthis.contentW = getResolution().w;\n/**\n* @name module:svgcanvas.SvgCanvas#contentH\n* @type {Float}\n*/\nthis.contentH = getResolution().h;\n\n/**\n* @typedef {PlainObject} module:svgcanvas.CanvasInfo\n* @property {Float} x - The canvas' new x coordinate\n* @property {Float} y - The canvas' new y coordinate\n* @property {string} oldX - The canvas' old x coordinate\n* @property {string} oldY - The canvas' old y coordinate\n* @property {Float} d_x - The x position difference\n* @property {Float} d_y - The y position difference\n*/\n\n/**\n* Updates the editor canvas width/height/position after a zoom has occurred.\n* @function module:svgcanvas.SvgCanvas#updateCanvas\n* @param {Float} w - Float with the new width\n* @param {Float} h - Float with the new height\n* @fires module:svgcanvas.SvgCanvas#event:ext_canvasUpdated\n* @returns {module:svgcanvas.CanvasInfo}\n*/\nthis.updateCanvas = function (w, h) {\n svgroot.setAttribute('width', w);\n svgroot.setAttribute('height', h);\n const bg = $('#canvasBackground')[0];\n const oldX = svgcontent.getAttribute('x');\n const oldY = svgcontent.getAttribute('y');\n const x = ((w - this.contentW * currentZoom) / 2);\n const y = ((h - this.contentH * currentZoom) / 2);\n\n assignAttributes(svgcontent, {\n width: this.contentW * currentZoom,\n height: this.contentH * currentZoom,\n x,\n y,\n viewBox: '0 0 ' + this.contentW + ' ' + this.contentH\n });\n\n assignAttributes(bg, {\n width: svgcontent.getAttribute('width'),\n height: svgcontent.getAttribute('height'),\n x,\n y\n });\n\n const bgImg = getElem('background_image');\n if (bgImg) {\n assignAttributes(bgImg, {\n width: '100%',\n height: '100%'\n });\n }\n\n selectorManager.selectorParentGroup.setAttribute('transform', 'translate(' + x + ',' + y + ')');\n\n /**\n * Invoked upon updates to the canvas.\n * @event module:svgcanvas.SvgCanvas#event:ext_canvasUpdated\n * @type {PlainObject}\n * @property {Integer} new_x\n * @property {Integer} new_y\n * @property {string} old_x (Of Integer)\n * @property {string} old_y (Of Integer)\n * @property {Integer} d_x\n * @property {Integer} d_y\n */\n runExtensions(\n 'canvasUpdated',\n /**\n * @type {module:svgcanvas.SvgCanvas#event:ext_canvasUpdated}\n */\n {new_x: x, new_y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY}\n );\n return {x, y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY};\n};\n\n/**\n* Set the background of the editor (NOT the actual document).\n* @function module:svgcanvas.SvgCanvas#setBackground\n* @param {string} color - String with fill color to apply\n* @param {string} url - URL or path to image to use\n* @returns {void}\n*/\nthis.setBackground = function (color, url) {\n const bg = getElem('canvasBackground');\n const border = $(bg).find('rect')[0];\n let bgImg = getElem('background_image');\n let bgPattern = getElem('background_pattern');\n border.setAttribute('fill', color === 'chessboard' ? '#fff' : color);\n if (color === 'chessboard') {\n if (!bgPattern) {\n bgPattern = svgdoc.createElementNS(NS.SVG, 'foreignObject');\n assignAttributes(bgPattern, {\n id: 'background_pattern',\n width: '100%',\n height: '100%',\n preserveAspectRatio: 'xMinYMin',\n style: 'pointer-events:none'\n });\n const div = document.createElement('div');\n assignAttributes(div, {\n style: 'pointer-events:none;width:100%;height:100%;background-image:url(data:image/gif;base64,R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7);'\n });\n bgPattern.appendChild(div);\n bg.append(bgPattern);\n }\n } else if (bgPattern) {\n bgPattern.remove();\n }\n if (url) {\n if (!bgImg) {\n bgImg = svgdoc.createElementNS(NS.SVG, 'image');\n assignAttributes(bgImg, {\n id: 'background_image',\n width: '100%',\n height: '100%',\n preserveAspectRatio: 'xMinYMin',\n style: 'pointer-events:none'\n });\n }\n setHref(bgImg, url);\n bg.append(bgImg);\n } else if (bgImg) {\n bgImg.remove();\n }\n};\n\n/**\n* Select the next/previous element within the current layer.\n* @function module:svgcanvas.SvgCanvas#cycleElement\n* @param {boolean} next - true = next and false = previous element\n* @fires module:svgcanvas.SvgCanvas#event:selected\n* @returns {void}\n*/\nthis.cycleElement = function (next) {\n let num;\n const curElem = selectedElements[0];\n let elem = false;\n const allElems = getVisibleElements(currentGroup || getCurrentDrawing().getCurrentLayer());\n if (!allElems.length) { return; }\n if (isNullish(curElem)) {\n num = next ? allElems.length - 1 : 0;\n elem = allElems[num];\n } else {\n let i = allElems.length;\n while (i--) {\n if (allElems[i] === curElem) {\n num = next ? i - 1 : i + 1;\n if (num >= allElems.length) {\n num = 0;\n } else if (num < 0) {\n num = allElems.length - 1;\n }\n elem = allElems[num];\n break;\n }\n }\n }\n selectOnly([elem], true);\n call('selected', selectedElements);\n};\n\nthis.clear();\n\n/**\n* @interface module:svgcanvas.PrivateMethods\n* @type {PlainObject}\n* @property {module:svgcanvas~addCommandToHistory} addCommandToHistory\n* @property {module:history.HistoryCommand} BatchCommand\n* @property {module:history.HistoryCommand} ChangeElementCommand\n* @property {module:utilities.decode64} decode64\n* @property {module:utilities.dropXMLInternalSubset} dropXMLInternalSubset\n* @property {module:utilities.encode64} encode64\n* @property {module:svgcanvas~ffClone} ffClone\n* @property {module:svgcanvas~findDuplicateGradient} findDuplicateGradient\n* @property {module:utilities.getPathBBox} getPathBBox\n* @property {module:units.getTypeMap} getTypeMap\n* @property {module:draw.identifyLayers} identifyLayers\n* @property {module:history.HistoryCommand} InsertElementCommand\n* @property {module:browser.isChrome} isChrome\n* @property {module:math.isIdentity} isIdentity\n* @property {module:browser.isIE} isIE\n* @property {module:svgcanvas~logMatrix} logMatrix\n* @property {module:history.HistoryCommand} MoveElementCommand\n* @property {module:namespaces.NS} NS\n* @property {module:utilities.preventClickDefault} preventClickDefault\n* @property {module:history.HistoryCommand} RemoveElementCommand\n* @property {module:SVGTransformList.SVGEditTransformList} SVGEditTransformList\n* @property {module:utilities.text2xml} text2xml\n* @property {module:math.transformBox} transformBox\n* @property {module:math.transformPoint} transformPoint\n* @property {module:utilities.walkTree} walkTree\n*/\n/**\n* @deprecated getPrivateMethods\n* Since all methods are/should be public somehow, this function should be removed;\n* we might require `import` in place of this in the future once ES6 Modules\n* widespread\n\n* Being able to access private methods publicly seems wrong somehow,\n* but currently appears to be the best way to allow testing and provide\n* access to them to plugins.\n* @function module:svgcanvas.SvgCanvas#getPrivateMethods\n* @returns {module:svgcanvas.PrivateMethods}\n*/\nthis.getPrivateMethods = function () {\n const obj = {\n addCommandToHistory,\n BatchCommand,\n ChangeElementCommand,\n decode64,\n dropXMLInternalSubset,\n encode64,\n ffClone,\n findDefs,\n findDuplicateGradient,\n getElem,\n getPathBBox,\n getTypeMap,\n getUrlFromAttr,\n identifyLayers: draw.identifyLayers,\n InsertElementCommand,\n isChrome,\n isIdentity,\n isIE,\n logMatrix,\n MoveElementCommand,\n NS,\n preventClickDefault,\n RemoveElementCommand,\n SVGEditTransformList,\n text2xml,\n transformBox,\n transformPoint,\n walkTree\n };\n return obj;\n};\n } // End constructor\n} // End class\n\nexport default SvgCanvas;\n","/**\n * @module jQueryPluginDBox\n */\n/**\n* @param {external:jQuery} $\n* @param {PlainObject} [strings]\n* @param {PlainObject} [strings.ok]\n* @param {PlainObject} [strings.cancel]\n* @returns {external:jQuery}\n*/\nexport default function jQueryPluginDBox ($, strings = {ok: 'Ok', cancel: 'Cancel'}) {\n // This sets up alternative dialog boxes. They mostly work the same way as\n // their UI counterparts, expect instead of returning the result, a callback\n // needs to be included that returns the result as its first parameter.\n // In the future we may want to add additional types of dialog boxes, since\n // they should be easy to handle this way.\n $('#dialog_container').draggable({\n cancel: '#dialog_content, #dialog_buttons *',\n containment: 'window'\n }).css('position', 'absolute');\n\n const box = $('#dialog_box'),\n btnHolder = $('#dialog_buttons'),\n dialogContent = $('#dialog_content');\n\n /**\n * @typedef {PlainObject} module:jQueryPluginDBox.PromiseResultObject\n * @property {string|true} response\n * @property {boolean} checked\n */\n\n /**\n * Resolves to `false` (if cancelled), for prompts and selects\n * without checkboxes, it resolves to the value of the form control. For other\n * types without checkboxes, it resolves to `true`. For checkboxes, it resolves\n * to an object with the `response` key containing the same value as the previous\n * mentioned (string or `true`) and a `checked` (boolean) property.\n * @typedef {Promise<boolean|string|module:jQueryPluginDBox.PromiseResultObject>} module:jQueryPluginDBox.ResultPromise\n */\n /**\n * @typedef {PlainObject} module:jQueryPluginDBox.SelectOption\n * @property {string} text\n * @property {string} value\n */\n /**\n * @typedef {PlainObject} module:jQueryPluginDBox.CheckboxInfo\n * @property {string} label Label for the checkbox\n * @property {string} value Value of the checkbox\n * @property {string} tooltip Tooltip on the checkbox label\n * @property {boolean} checked Whether the checkbox is checked by default\n */\n /**\n * Triggered upon a change of value for the select pull-down.\n * @callback module:jQueryPluginDBox.SelectChangeListener\n * @returns {void}\n */\n /**\n * Creates a dialog of the specified type with a given message\n * and any defaults and type-specific metadata. Returns a `Promise`\n * which resolves differently depending on whether the dialog\n * was cancelled or okayed (with the response and any checked state).\n * @param {\"alert\"|\"prompt\"|\"select\"|\"process\"} type\n * @param {string} msg\n * @param {string} [defaultVal]\n * @param {module:jQueryPluginDBox.SelectOption[]} [opts]\n * @param {module:jQueryPluginDBox.SelectChangeListener} [changeListener]\n * @param {module:jQueryPluginDBox.CheckboxInfo} [checkbox]\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n function dbox (type, msg, defaultVal, opts, changeListener, checkbox) {\n dialogContent.html('<p>' + msg.replace(/\\n/g, '</p><p>') + '</p>')\n .toggleClass('prompt', (type === 'prompt'));\n btnHolder.empty();\n\n const ok = $('<input type=\"button\" data-ok=\"\" value=\"' + strings.ok + '\">').appendTo(btnHolder);\n\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n if (type !== 'alert') {\n $('<input type=\"button\" value=\"' + strings.cancel + '\">')\n .appendTo(btnHolder)\n .click(function () {\n box.hide();\n resolve(false);\n });\n }\n\n let ctrl, chkbx;\n if (type === 'prompt') {\n ctrl = $('<input type=\"text\">').prependTo(btnHolder);\n ctrl.val(defaultVal || '');\n ctrl.bind('keydown', 'return', function () { ok.click(); });\n } else if (type === 'select') {\n const div = $('<div style=\"text-align:center;\">');\n ctrl = $(`<select aria-label=\"${msg}\">`).appendTo(div);\n if (checkbox) {\n const label = $('<label>').text(checkbox.label);\n chkbx = $('<input type=\"checkbox\">').appendTo(label);\n chkbx.val(checkbox.value);\n if (checkbox.tooltip) {\n label.attr('title', checkbox.tooltip);\n }\n chkbx.prop('checked', Boolean(checkbox.checked));\n div.append($('<div>').append(label));\n }\n $.each(opts || [], function (opt, val) {\n if (typeof val === 'object') {\n ctrl.append($('<option>').val(val.value).html(val.text));\n } else {\n ctrl.append($('<option>').html(val));\n }\n });\n dialogContent.append(div);\n if (defaultVal) {\n ctrl.val(defaultVal);\n }\n if (changeListener) {\n ctrl.bind('change', 'return', changeListener);\n }\n ctrl.bind('keydown', 'return', function () { ok.click(); });\n } else if (type === 'process') {\n ok.hide();\n }\n\n box.show();\n\n ok.click(function () {\n box.hide();\n const response = (type === 'prompt' || type === 'select') ? ctrl.val() : true;\n if (chkbx) {\n resolve({response, checked: chkbx.prop('checked')});\n return;\n }\n resolve(response);\n }).focus();\n\n if (type === 'prompt' || type === 'select') {\n ctrl.focus();\n }\n });\n }\n\n /**\n * @param {string} msg Message to alert\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.alert = function (msg) {\n return dbox('alert', msg);\n };\n /**\n * @param {string} msg Message for which to ask confirmation\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.confirm = function (msg) {\n return dbox('confirm', msg);\n };\n /**\n * @param {string} msg Message to indicate upon cancelable indicator\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.process_cancel = function (msg) {\n return dbox('process', msg);\n };\n /**\n * @param {string} msg Message to accompany the prompt\n * @param {string} [defaultText=''] The default text to show for the prompt\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.prompt = function (msg, defaultText = '') {\n return dbox('prompt', msg, defaultText);\n };\n $.select = function (msg, opts, changeListener, txt, checkbox) {\n return dbox('select', msg, txt, opts, changeListener, checkbox);\n };\n return $;\n}\n"],"names":["jQueryPluginSVG","$","proxied","fn","attr","key","value","len","this","length","call","i","elem","namespaceURI","undefined","setAttribute","Array","isArray","obj","j","aname","getAttribute","isNaN","name","val","Object","entries","window","SVGPathSeg","constructor","type","typeAsLetter","owningPathSegList","pathSegType","pathSegTypeAsLetter","_owningPathSegList","_segmentChanged","segmentChanged","prototype","classname","PATHSEG_UNKNOWN","PATHSEG_CLOSEPATH","PATHSEG_MOVETO_ABS","PATHSEG_MOVETO_REL","PATHSEG_LINETO_ABS","PATHSEG_LINETO_REL","PATHSEG_CURVETO_CUBIC_ABS","PATHSEG_CURVETO_CUBIC_REL","PATHSEG_CURVETO_QUADRATIC_ABS","PATHSEG_CURVETO_QUADRATIC_REL","PATHSEG_ARC_ABS","PATHSEG_ARC_REL","PATHSEG_LINETO_HORIZONTAL_ABS","PATHSEG_LINETO_HORIZONTAL_REL","PATHSEG_LINETO_VERTICAL_ABS","PATHSEG_LINETO_VERTICAL_REL","PATHSEG_CURVETO_CUBIC_SMOOTH_ABS","PATHSEG_CURVETO_CUBIC_SMOOTH_REL","PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS","PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL","SVGPathSegClosePath","toString","_asPathString","clone","SVGPathSegMovetoAbs","x","y","_x","_y","defineProperties","get","set","enumerable","SVGPathSegMovetoRel","SVGPathSegLinetoAbs","SVGPathSegLinetoRel","SVGPathSegCurvetoCubicAbs","x1","y1","x2","y2","_x1","_y1","_x2","_y2","SVGPathSegCurvetoCubicRel","SVGPathSegCurvetoQuadraticAbs","SVGPathSegCurvetoQuadraticRel","SVGPathSegArcAbs","r1","r2","angle","largeArcFlag","sweepFlag","_r1","_r2","_angle","_largeArcFlag","_sweepFlag","SVGPathSegArcRel","SVGPathSegLinetoHorizontalAbs","defineProperty","SVGPathSegLinetoHorizontalRel","SVGPathSegLinetoVerticalAbs","SVGPathSegLinetoVerticalRel","SVGPathSegCurvetoCubicSmoothAbs","SVGPathSegCurvetoCubicSmoothRel","SVGPathSegCurvetoQuadraticSmoothAbs","SVGPathSegCurvetoQuadraticSmoothRel","SVGPathElement","createSVGPathSegClosePath","createSVGPathSegMovetoAbs","createSVGPathSegMovetoRel","createSVGPathSegLinetoAbs","createSVGPathSegLinetoRel","createSVGPathSegCurvetoCubicAbs","createSVGPathSegCurvetoCubicRel","createSVGPathSegCurvetoQuadraticAbs","createSVGPathSegCurvetoQuadraticRel","createSVGPathSegArcAbs","createSVGPathSegArcRel","createSVGPathSegLinetoHorizontalAbs","createSVGPathSegLinetoHorizontalRel","createSVGPathSegLinetoVerticalAbs","createSVGPathSegLinetoVerticalRel","createSVGPathSegCurvetoCubicSmoothAbs","createSVGPathSegCurvetoCubicSmoothRel","createSVGPathSegCurvetoQuadraticSmoothAbs","createSVGPathSegCurvetoQuadraticSmoothRel","getPathSegAtLength","distance","isFinite","Error","measurementElement","document","createElementNS","lastPathSegment","pathSegList","numberOfItems","removeItem","getTotalLength","SVGPathSegList","pathElement","_pathElement","_list","_parsePath","_mutationObserverConfig","attributes","attributeFilter","_pathElementMutationObserver","MutationObserver","_updateListFromPathMutations","bind","observe","_checkPathSynchronizedToList","takeRecords","mutationRecords","hasPathMutations","forEach","record","attributeName","_writeListToPath","disconnect","_pathSegArrayAsString","pathSeg","clear","initialize","newItem","_checkValidIndex","index","getItem","insertItemBefore","splice","replaceItem","item","appendItem","push","string","builder","appendSegment","source","_string","_currentIndex","_endIndex","_previousCommand","_skipOptionalSpaces","_isCurrentSpace","character","_skipOptionalSpacesOrDelimiter","charAt","hasMoreData","peekSegmentType","lookahead","_pathSegTypeFromChar","_nextCommandHelper","previousCommand","initialCommandIsMoveTo","command","_parseNumber","exponent","integer","frac","decimal","sign","expsign","startIndex","startIntPartIndex","scanIntPartIndex","multiplier","number","_parseArcFlag","flag","flagChar","parseSegment","points","arcAngle","arcLarge","arcSweep","pathSegArray","first","_pathSegList","normalizedPathSegList","animatedPathSegList","animatedNormalizedPathSegList","NS","HTML","MATH","SE","SVG","XLINK","XML","XMLNS","getReverseNS","reverseNS","URI","toLowerCase","jQuery","userAgent","Boolean","createSVGRect","navigator","svg","isOpera_","opera","isWebkit_","includes","isGecko_","isIE_","isChrome_","isTouch_","supportsSelectors_","querySelector","supportsXpath_","evaluate","supportsPathReplaceItem_","path","seglist","seg","err","supportsPathInsertItemBefore_","supportsGoodTextCharPos_","svgroot","svgcontent","documentElement","append","text","textContent","getStartPositionOfChar","remove","supportsPathBBox_","bbox","getBBox","height","supportsHVLineContainerBBox_","path2","g","width","supportsNonScalingStroke_","rect","retValue","cloneNode","alert","style","vectorEffect","supportsNativeSVGTransformLists_","rxform","transform","baseVal","t1","createSVGTransform","isSVGTransform","o","setMatrix","matrix","a","b","c","d","e","f","isWebkit","isGecko","isIE","isChrome","supportsNonScalingStroke","transformToString","xform","m","join","cx","cy","K","listMap_","SVGTransformList","_elem","_xforms","_update","tstr","_init","str","re","match","replace","bits","split","valBits","valArr","letters","mtx","createSVGMatrix","values","Number","parseFloat","fname","toUpperCase","slice","_removeFromOtherLists","some","tl","code","newxforms","removeElementFromListMap","id","getTransformList","t","gradientTransform","patternTransform","transformPoint","isIdentity","matrixMultiply","args","reduceRight","prev","m1","multiply","Math","abs","hasMatrixTransform","tlist","num","transformBox","l","w","h","tr","bl","br","minx","min","maxx","max","miny","aabox","transformListToTransform","isNullish","createSVGTransformFromMatrix","parseInt","temp","mtom","getMatrix","snapToAngle","snap","PI","dx","dy","atan2","dist","sqrt","snapangle","round","cos","sin","rectsIntersect","KEYSTR","visElemsArr","editorContext_","domdoc_","domcontainer_","svgroot_","dropXMLInternalSubset","toXml","encode64","input","encodeUTF8","btoa","output","floor","p","chr1","charCodeAt","chr2","chr3","enc1","enc2","enc3","enc4","decode64","atob","decodeUTF8","indexOf","String","fromCharCode","argString","decodeURIComponent","escape","unescape","encodeURIComponent","createObjectURL","blob","URL","text2xml","Blob","sXML","out","dXML","DOMParser","ActiveXObject","async","loadXML","parseFromString","e2","walkTree","cbFn","nodeType","childNodes","getUrlFromAttr","attrVal","startsWith","substring","getHref","getAttributeNS","setHref","setAttributeNS","findDefs","svgElement","getSVGContent","defs","getElementsByTagNameNS","ownerDocument","firstChild","insertBefore","nextSibling","getPathBBox","tot","bounds","start","P0","getCalc","P1","P2","P3","calc","b2ac","t2","apply","groupBBFix","selected","ref","data","ret","copy","matched","children","filter","find","issue","each","bb","elems","getStrokedBBox","geSelectedElements","elname","nodeName","extent","getExtentOfChar","getComputedTextLength","fo","closest","bboxToObj","getPathDFromSegments","pathSegments","singleChar","pts","getPathDFromElement","rx","ry","tagName","r","getExtraAttributesForConvertToPath","attrs","getBBoxOfElementAsPath","addSVGElementFromJson","pathActions","element","eltrans","parentNode","before","resetOrientation","getBBoxWithTransform","getRotationAngleFromTransformList","hasMatrixXForm","goodBb","hasAMatrixTransform","angleModulo90","bBoxCanBeOptimizedOverNativeGetBBox","getStrokeOffsetForBBox","sw","fullBb","maxX","maxY","minX","minY","offset","curBb","getVisibleElements","parentElement","contentElems","reverse","getStrokedBBoxDefaultVisible","toRad","N","getRotationAngle","getSelectedElements","getRefElem","getElem","substr","singleNodeValue","assignAttributes","suspendLength","unitCheck","ns","removeAttributeNS","removeAttribute","setUnitAttr","cleanupElement","defaults","opacity","stroke","snapToGrid","unit","getBaseUnit","stepSize","getSnappingStep","getTypeMap","preventClickDefault","img","click","preventDefault","wAttrs","hAttrs","elementContainer_","typeMap_","shortFloat","digits","getRoundDigits","toFixed","convertUnit","convertToNum","getWidth","getHeight","HistoryEventTypes","BEFORE_APPLY","AFTER_APPLY","BEFORE_UNAPPLY","AFTER_UNAPPLY","Command","getText","handler","applyFunction","handleHistoryEvent","unapply","unapplyFunction","elements","MoveElementCommand","oldNextSibling","oldParent","newNextSibling","newParent","InsertElementCommand","parent","RemoveElementCommand","console","error","ChangeElementCommand","newValues","oldValues","bChangedTransform","rotate","BatchCommand","stack","stackItem","assert","cmd","thisElems","addSubCommand","isEmpty","historyEventHandler","handler_","undoStackPointer","undoStack","undoChangeStackPointer","undoableChangeStack","resetUndoStack","getUndoStackSize","getRedoStackSize","getNextUndoCommandText","getNextRedoCommandText","undo","redo","addCommandToHistory","beginUndoableChange","attrName","finishUndoableChange","changeset","batchCmd","changes","segData","uiStrings","setUiStrings","strs","assign","ui","pathFuncs","linkControlPts","pathData","setLinkControlPoints","lcp","init","editorContext","s","newseg","list","arr","curSeg","ptObjToArr","segItem","map","prop","getGripPt","altPt","pth","currentZoom","getCurrentZoom","getPointFromGrip","pt","imatrix","addPointGrip","pointGripContainer","getGripContainer","pointGrip","atts","display","fill","cursor","pathNodeTooltip","appendChild","dblclick","setSegType","addCtrlGrip","pathCtrlPtTooltip","getCtrlLine","ctrlLine","getPointGrip","update","getControlPoints","cpt","segItems","segs","gpt","replacePathSeg","segList","getSegSelector","segLine","point","smoothControlPoints","ct1","ct2","nct1","getSVGRoot","createSVGPoint","nct2","anglea","angleb","angleBetween","angleDiff","newAnglea","newAngleb","Segment","ctrlpts","ptgrip","segsel","showCtrlPts","hasOwnProperty","selectCtrls","show","select","addGrip","full","move","curPts","next","nextPts","mate","itm","setLinked","anum","moveCtrl","setType","newType","Path","selected_pts","first_seg","segment","startI","nextSeg","prevSeg","startSeg","eachSeg","addSeg","newX","newY","p0x","p1x","p2x","p01x","p12x","p0y","p1y","p2y","p01y","p12y","deleteSeg","removePtFromSelection","pos","clearSelection","storeD","last_d","selectPt","movePts","dragctrl","selPt","cur","curX","curY","prevX","prevY","olditem","old","diffX","diffY","endChanges","ctrlNum","addPtsToSelection","inverse","resetD","indexes","sort","grips","closedSubpath","subpathIsClosed","clsd","getPath_","removePath_","newcx","newcy","oldcx","oldcy","getRotVals","theta","recalcRotatedPath","currentPath","oldbox","oldbbox","box","rvals","cVals1","cVals2","Rnc","setRotate","clearData","reorientGrads","utilsGetBBox","grad","pt1","pt2","gCoords","newgrad","getNextId","pathMap","convertPath","toRel","curx","cury","lastM","letter","pathDSegment","morePoints","lastPoint","pnt","newPoint","firstCtrl","subpath","hasMoved","mouseDown","evt","mouseTarget","startX","startY","curPt","getCurrentMode","target","cur_pt","dragging","shiftKey","parts","rubberBox","getRubberBox","setRubberBox","selectorManager","getRubberBandBox","mouseX","mouseY","stretchy","getGridSnapping","keep","drawnPath","getDrawnPath","FUZZ","clickOnPoint","px","py","getId","newpath","sSeg","absX","absY","endseg","setDrawnPath","setStarted","remapElement","newD","origD","toEditMode","contains","getContainer","getMouseTarget","last","lastx","lasty","xya","dAttr","curStyles","getOpacity","mouseMove","mpt","rbb","ptBb","sel","pointGrip1","pointGrip2","ptX","ptY","altX","altY","lastX","lastY","mouseUp","lastPt","toSelectMode","setCurrentMode","selPath","addToSelection","addSubPath","on","reorient","n","zoomChange","getNodePoint","linkControlPoints","linkPoints","clonePathNode","selPts","nums","opencloseSubPath","openPt","startItem","closer","zSeg","deletePathNode","canDeleteNodes","cleanup","remItems","count","nprev","prevType","canvas","deleteSelectedElements","cp","smoothPolylineIntoPath","curpos","prevCtlPt","end","newpts","prevArr","v","moveNode","newValue","diff","fixEnd","Layer","group","svgElem","name_","group_","svgdoc","layerTitle","after","classes","CLASS_NAME","CLASS_REGEX","test","addLayerClass","getName","getGroup","activate","deactivate","setVisible","visible","expected","isVisible","setOpacity","appendChildren","child","getTitleElement","setName","hrService","previousName","title","empty","changeElement","removeGroup","RegExp","HistoryRecordingService","undoManager","undoManager_","currentBatchCommand_","batchCommandStack_","startBatchCommand","endBatchCommand","batchCommand","pop","addCommand_","moveElement","insertElement","removeElement","NO_HISTORY","copyElem","el","newEl","localName","fixedD","nodeValue","visElems","RandomizeModes","randIds","disabledElems","historyRecordingService","canvas_","undoMgr","findLayerNameInGroup","querySelectorAll","getNewLayerName","existingLayerNames","Drawing","optIdPrefix","svgElem_","obj_num","idPrefix","releasedNums","all_layers","layer_map","current_layer","nonce_","setNonce","random","getElem_","getSvgElem","getNonce","clearNonce","oldObjNum","restoreOldObjNum","releaseId","front","getNumLayers","hasLayer","getLayerName","getCurrentLayer","getLayerByName","layer","getCurrentLayerName","setCurrentLayerName","finalName","oldName","setCurrentLayerPosition","newpos","layerCount","oldpos","currentGroup","refGroup","identifyLayers","setCurrentLayer","mergeLayer","prevGroup","layerNextSibling","mergeAllLayers","deleteCurrentLayer","oldLayerGroup","numchildren","orphans","layernames","childgroups","createLayer","keys","cloneLayer","getLayerVisibility","layerName","setLayerVisibility","bVisible","getLayerOpacity","setLayerOpacity","that","utilCopyElem","randomizeIds","enableRandomization","currentDrawing","leaveContext","getCurrentDrawing","newLayer","currentLayer","result","renameCurrentLayer","newName","drawing","newPos","prevVisibility","oldDisplay","moveSelectedToLayer","selElems","oldLayer","changeSVGContent","orig","elData","setCurrentGroup","setContext","parentsUntil","andSelf","siblings","opac","getCurrentGroup","REVERSE_NS","svgWhiteList_","circle","clipPath","desc","ellipse","feGaussianBlur","feMorphology","foreignObject","image","line","linearGradient","marker","mask","metadata","pattern","polygon","polyline","radialGradient","stop","switch","symbol","textPath","tspan","use","annotation","maction","math","menclose","merror","mfrac","mi","mmultiscripts","mn","mo","mover","mpadded","mphantom","mprescripts","mroot","mrow","mspace","msqrt","mstyle","msub","msubsup","msup","mtable","mtd","mtext","mtr","munder","munderover","none","semantics","svgWhiteListNS_","elt","attNS","att","sanitizeSvg","node","doc","allowedAttrs","allowedAttrsNS","seAttrs","attrLocalName","attrNsURI","props","styleAttrName","trim","styleAttrVal","href","hasChildNodes","addScriptAtts","script","importSetGlobal","url","global","glob","returnDefault","svgEditor","modules","importScript","importModule","Promise","all","u","resolve","reject","vector","createElement","scriptOnError","destructor","scriptOnLoad","removeEventListener","revokeObjectURL","src","defer","addEventListener","loader","toAbsoluteURL","head","remap","scalew","scaleh","doSnapping","finishUp","getDrawing","elName","chlist","mt","existing","tNew","tbox","gsvg","pstr","firstseg","currentpt","dstr","context_","updateClipPath","tx","ty","cpXform","newxlate","setTranslate","recalculateDimensions","k","noi","mxs","mNew","oldcenter","newcenter","initial","extend","getStartTransform","gangle","rm","firstM","oldStartTransform","operation","tm","sm","tmn","childTlist","setStartTransform","e2t","t2n","s2","translateOrigin","scale","translateBack","setScale","T_M","mInv","M2","clipPathsDone","uses","useElem","usexlate","newRot","em","e2m","avg","roldt","rold","rnew","rnewInv","extrat","paint","gtlist","gmatrix","mStr","oldxlate","meq","meqInv","tspanChanges","svgFactory_","config_","selectorManager_","gripRadius","Selector","selectedElement","locked","selectorGroup","createSVGElement","selectorRect","gripCoords","nw","ne","se","reset","resize","showGrips","bShow","selectorGripsGroup","hasGrips","updateGripCursors","selectedBox","mgr","selectedGrips","selectorGrips","strokedBbox","nbox","nbax","nbay","nbaw","nbah","rot","svgRoot","rotm","maxy","dir","coords","rotateGripConnector","rotateGrip","dirArr","steps","shift","gripElement","SelectorManager","selectorParentGroup","rubberBandBox","selectors","selectorMap","initGroup","grip","imgPath","dimensions","canvasbg","overflow","svgContent","requestSelector","releaseSelector","log","UndoManager","hstry","postError","container","config","curConfig","show_outside_canvas","selectNew","importNode","clearSvgContentElement","xmlns","appendTo","comment","createComment","idprefix","setIdPrefix","current_drawing_","draw","allProperties","shape","initFill","color","fill_paint","fill_opacity","initStroke","stroke_paint","stroke_opacity","stroke_width","stroke_dasharray","stroke_linejoin","stroke_linecap","initOpacity","font_size","font_family","curShape","selectedElements","getJsonFromSvgElement","retval","createTextNode","namespace","baseUnit","elementContainer","body","inch","ex","in","cm","mm","pc","unitsInit","getElement","saveOptions","round_digits","getSelectedElems","pathModule","getDOMDocument","getDOMContainer","snappingStep","gridSnapping","coordsInit","recalculateInit","startTransform","nsMap","eventType","EventTypes","cmdType","isApply","restoreRefElems","setUseData","stdDeviation","setBlurOffsets","getZoom","svgFactory","selectInit","jsonMap","ev","arg","events","noCall","elemsToAdd","compareDocumentPosition","correspondingUseElement","started","rb","closed_subpath","currentMode","dp","refAttrs","opacAni","begin","dur","removedElements","childs","getElementsByTagName","encodableImages","importIds","curText","extensions","lastGoodImgUrl","currentResizeMode","curProperties","justSelected","curBBoxes","lastClickPoint","runExtension","action","vars","runExtensions","returnArray","nameFilter","ext","addExtension","extInitFunc","jq","importLocale","TypeError","argObj","getPrivateMethods","nonce","extObj","getIntersectionList","rubberBBox","resultList","getVisibleElementsAndBBoxes","groupSvgElem","replaceWith","prepareSvg","newDoc","ffClone","setRotationAngle","preventUndo","oldTransform","center","newTransform","changeSelectedAttribute","recalculateAllSelectedDimensions","logMatrix","rootSctm","selectOnly","removeFromSelection","elemsToRemove","newSelectedItems","selectAllInCurrentLayer","freehand","parameter","nextParameter","rStartX","rStartY","initBbox","sumDistance","controllPoint2","controllPoint1","bSpline","nextPos","getBsplinePoint","spline","p0","p1","p2","p3","t3","mousedown","spaceKey","button","rightClick","altKey","cloneSelectedElements","getScreenCTM","pageX","pageY","realX","realY","griptype","slist","iswebkit","delayedStroke","ele","stroke_","setTimeout","newImage","strokeW","textActions","extResult","event","start_x","start_y","mousemove","newList","intElem","foundInd","hasMatrix","left","top","sy","sx","square","rad","STEP_COUNT","mouse_x","mouse_y","pushGroupProperties","mouseup","tempJustSelected","factor","commaIndex","res","addedNew","cAni","aniDur","beginElement","to","setMode","originalEvent","workarea","rulerwidth","showRulers","editorFullW","editorFullH","editorW","editorH","workareaViewW","workareaViewH","wOffset","wOffsetLeft","wOffsetTop","delta","wheelDelta","detail","wZoom","hZoom","ceil","zoomlevel","topLeftOld","newCtr","setZoom","curtext","textinput","selblock","blinker","textbb","allowDbl","chardata","setCursor","focus","arguments","selectionEnd","selectionStart","charbb","setSelectionRange","setInterval","startPt","ptToScreen","endPt","visibility","setSelection","skipInput","startbb","endbb","getIndexFromPoint","charpos","getCharNumAtPosition","setCursorFromPoint","setEndSelectionFromPoint","i1","i2","screenToPt","xIn","yIn","selectAll","unbind","selectWord","ept","css","selectElem","clearInterval","blur","setInputElem","inputElem","getEndPositionOfChar","contentW","removeUnusedDefElems","defelemUses","numRemoved","alen","allEls","allLen","defelems","defelem","getIssues","issues","issueCodes","issueList","exportNoBlur","exportNoforeignObject","exportNoDashArray","content","getContext","exportNoText","descr","canvg","svgCanvasToString","nakedSvgs","svgToString","indent","unitRe","getResolution","vb","nsuris","uri","attrNames","mozAttrs","styleName","images","bOneLine","embedImage","Image","load","response","status","xhr","statusText","cvs","drawImage","urldata","toDataURL","setGoodImage","open","save","opts","rasterExport","imgType","quality","exportWindowName","mimeType","canvgPath","hide","contentH","dataURLType","datauri","bloburl","done","avoidEvent","toBlob","dataurl","Uint8Array","mime","bstr","u8arr","dataURLToObjectURL","exportPDF","outputType","jsPDF","modularVersion","jspdfPath","orientation","format","docTitle","getDocumentTitle","setProperties","addSVG","getSvgString","uniquifyElems","ids","refElems","hrefs","attrnode","getAttributeNode","refid","oldid","newid","ownerElement","hreffers","hreffer","refElem","convertGradients","fillStrokeElems","convertToGroup","$elem","ts","unwrap","removeData","hasMore","dupeGrads","walkTreePost","setSvgString","xmlString","firstElementChild","oldzoom","adoptNode","pa","percs","dim","importSvgString","useEl","uid","useExisting","parents","innerw","innerh","innervb","canvash","dr","propVal","cg","getContentElem","getRootElem","zoom","getSnapToGrid","getVersion","notification","strings","ok","cancel","draggable","containment","btnHolder","dialogContent","dbox","msg","defaultVal","changeListener","checkbox","html","toggleClass","ctrl","chkbx","prependTo","div","label","tooltip","checked","opt","confirm","process_cancel","prompt","defaultText","txt","jQueryPluginDBox","common","setConfig","getTitle","setGroupTitle","prepend","tsNextSibling","setDocumentTitle","newTitle","oldTitle","getEditorNS","add","setResolution","visEls","moveSelectedElements","viewBox","getOffset","setBBoxZoom","spacer","calcZoom","newzoom","selectedElems","zoomLevel","getMode","getColor","setColor","addNonG","changeSelectedAttributeNoUndo","setGradient","duplicateGrad","findDuplicateGradient","existingGrads","radAttrs","og","gradAttrs","ogAttrs","stops","ostops","ostop","setPaint","jGraduate","Paint","setPaintOpacity","alpha","solidColor","setStrokePaint","setFillPaint","getStrokeWidth","setStrokeWidth","setStrokeAttr","getStyle","getFillOpacity","getStrokeOpacity","getPaintOpacity","getBlur","curCommand","filterHidden","finishChange","bCmd","setBlurNoUndo","setBlur","filterElem","stdDev","complete","elemId","newblur","getBold","setBold","getItalic","setItalic","getFontFamily","setFontFamily","setFontColor","getFontColor","getFontSize","setFontSize","setTextContent","setImageURL","setsize","curHref","setLinkURL","parentsA","setRectRadius","makeHyperlink","groupSelectedElements","removeHyperlink","ungroupSelectedElement","convertToPath","noXYElems","oldval","newrot","selectedCopy","cutSelectedElements","copySelectedElements","CLIPBOARD_ID","flashStorage","sessionStorage","localStorage","setItem","JSON","stringify","menu","enableContextMenuItems","pasteElements","clipb","parse","pasted","changedIDs","checkIDs","extChanges","removeID","clipBoardItem","ctrX","ctrY","urlArg","cmdStr","undoable","glist","gattrs","gfilter","gblur","newOpac","cblur","origCblur","suffix","chtlist","rgm","rcm","cangle","cbox","ceqm","coldc","sangle","trm","oldxform","newxform","chm","chmInv","gm","anchor","gNextSibling","moveToTopSelectedElement","moveToBottomSelectedElement","moveUpDownSelected","foundCur","toArray","copiedElements","alignSelectedElements","relativeTo","bboxes","MAX_VALUE","MIN_VALUE","curwidth","curheight","updateCanvas","bg","oldX","oldY","bgImg","new_x","new_y","old_x","old_y","d_x","d_y","setBackground","border","bgPattern","preserveAspectRatio","cycleElement","curElem","allElems","SVGEditTransformList"],"mappings":"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"}