').append(btn.title);
+ }
+ } else if (btn.list) {
+ // Add button to list
+ button.addClass('push_button');
+ $$c('#' + btn.list + '_opts').append(button);
+
+ if (btn.isDefault) {
+ $$c('#cur_' + btn.list).append(button.children().clone());
+
+ var _svgicon = btn.svgicon || btn.id;
+
+ placementObj['#cur_' + btn.list] = _svgicon;
+ }
+ } else if (btn.includeWith) {
+ // Add to flyout menu / make flyout menu
+ var opts = btn.includeWith; // opts.button, default, position
+
+ refBtn = $$c(opts.button);
+ flyoutHolder = refBtn.parent(); // Create a flyout menu if there isn't one already
+
+ var _tlsId;
+
+ if (!refBtn.parent().hasClass('tools_flyout')) {
+ // Create flyout placeholder
+ _tlsId = refBtn[0].id.replace('tool_', 'tools_');
+ showBtn = refBtn.clone().attr('id', _tlsId + '_show').append($$c('
', {
+ "class": 'flyout_arrow_horiz'
+ }));
+ refBtn.before(showBtn); // Create a flyout div
+
+ flyoutHolder = makeFlyoutHolder(_tlsId, refBtn);
+ }
+
+ refData = Actions.getButtonData(opts.button);
+
+ if (opts.isDefault) {
+ placementObj['#' + _tlsId + '_show'] = btn.id;
+ } // TODO: Find way to set the current icon using the iconloader if this is not default
+ // Include data for extension button as well as ref button
+
+
+ var curH = holders['#' + flyoutHolder[0].id] = [{
+ sel: '#' + id,
+ fn: btn.events.click,
+ icon: btn.id,
+ key: btn.key,
+ isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault)
+ }, refData]; // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
+
+ var pos = 'position' in opts ? opts.position : 'last';
+ var len = flyoutHolder.children().length; // Add at given position or end
+
+ if (!isNaN(pos) && pos >= 0 && pos < len) {
+ flyoutHolder.children().eq(pos).before(button);
+ } else {
+ flyoutHolder.append(button);
+ curH.reverse();
+ }
+ }
+
+ if (!svgicons) {
+ button.append(icon);
+ }
+
+ if (!btn.list) {
+ // Add given events to button
+ $$c.each(btn.events, function (name, func) {
+ if (name === 'click' && btn.type === 'mode') {
+ // `touch.js` changes `touchstart` to `mousedown`,
+ // so we must map extension click events as well
+ if (isTouch() && name === 'click') {
+ name = 'mousedown';
+ }
+
+ if (btn.includeWith) {
+ button.bind(name, func);
+ } else {
+ button.bind(name, function () {
+ if (toolButtonClick(button)) {
+ func();
+ }
+ });
+ }
+
+ if (btn.key) {
+ $$c(document).bind('keydown', btn.key, func);
+
+ if (btn.title) {
+ button.attr('title', btn.title + ' [' + btn.key + ']');
+ }
+ }
+ } else {
+ button.bind(name, func);
+ }
+ });
+ }
+
+ setupFlyouts(holders);
+ });
+ $$c.each(btnSelects, function () {
+ addAltDropDown(this.elem, this.list, this.callback, {
+ seticon: true
+ });
+ });
+
+ if (!svgicons) {
+ _context5.next = 24;
+ break;
+ }
+
+ return _context5.abrupt("return", new Promise(function (resolve, reject) {
+ // eslint-disable-line promise/avoid-new
+ $$c.svgIcons(svgicons, {
+ w: 24,
+ h: 24,
+ id_match: false,
+ no_img: !isWebkit(),
+ fallback: fallbackObj,
+ placement: placementObj,
+ callback: function callback(icons) {
+ // Non-ideal hack to make the icon match the current size
+ // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
+ if (editor.pref('iconsize') !== 'm') {
+ prepResize();
+ }
+
+ runCallback();
+ resolve();
+ }
+ });
+ }));
+
+ case 24:
+ return _context5.abrupt("return", runCallback());
+
+ case 25:
+ case "end":
+ return _context5.stop();
+ }
+ }
+ }, _callee5);
+ }));
+
+ return function extAdded(_x3, _x4) {
+ return _ref11.apply(this, arguments);
+ };
+ }();
+ /**
+ * @param {string} color
+ * @param {Float} opac
+ * @param {string} type
+ * @returns {module:jGraduate~Paint}
+ */
+
+
+ var getPaint = function getPaint(color, opac, type) {
+ // update the editor's fill paint
+ var opts = {
+ alpha: opac
+ };
+
+ if (color.startsWith('url(#')) {
+ var refElem = svgCanvas.getRefElem(color);
+
+ if (refElem) {
+ refElem = refElem.cloneNode(true);
+ } else {
+ refElem = $$c('#' + type + '_color defs *')[0];
+ }
+
+ opts[refElem.tagName] = refElem;
+ } else if (color.startsWith('#')) {
+ opts.solidColor = color.substr(1);
+ } else {
+ opts.solidColor = 'none';
+ }
+
+ return new $$c.jGraduate.Paint(opts);
+ }; // $('#text').focus(function () { textBeingEntered = true; });
+ // $('#text').blur(function () { textBeingEntered = false; });
+ // bind the selected event to our function that handles updates to the UI
+
+
+ svgCanvas.bind('selected', selectedChanged);
+ svgCanvas.bind('transition', elementTransition);
+ svgCanvas.bind('changed', elementChanged);
+ svgCanvas.bind('saved', saveHandler);
+ svgCanvas.bind('exported', exportHandler);
+ svgCanvas.bind('exportedPDF', function (win, data) {
+ if (!data.output) {
+ // Ignore Chrome
+ return;
+ }
+
+ var exportWindowName = data.exportWindowName;
+
+ if (exportWindowName) {
+ exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one
+ }
+
+ if (!exportWindow || exportWindow.closed) {
+ /* await */
+ $$c.alert(uiStrings$1.notification.popupWindowBlocked);
+ return;
+ }
+
+ exportWindow.location.href = data.output;
+ });
+ svgCanvas.bind('zoomed', zoomChanged);
+ svgCanvas.bind('zoomDone', zoomDone);
+ svgCanvas.bind('updateCanvas',
+ /**
+ * @param {external:Window} win
+ * @param {PlainObject} centerInfo
+ * @param {false} centerInfo.center
+ * @param {module:math.XYObject} centerInfo.newCtr
+ * @listens module:svgcanvas.SvgCanvas#event:updateCanvas
+ * @returns {void}
+ */
+ function (win, _ref12) {
+ var center = _ref12.center,
+ newCtr = _ref12.newCtr;
+ updateCanvas(center, newCtr);
+ });
+ svgCanvas.bind('contextset', contextChanged);
+ svgCanvas.bind('extension_added', extAdded);
+ svgCanvas.textActions.setInputElem($$c('#text')[0]);
+ var str = '
';
+ $$c.each(palette, function (i, item) {
+ str += '
';
+ });
+ $$c('#palette').append(str); // Set up editor background functionality
+
+ var colorBlocks = ['#FFF', '#888', '#000', 'chessboard'];
+ str = '';
+ $$c.each(colorBlocks, function (i, e) {
+ if (e === 'chessboard') {
+ str += '
';
+ } else {
+ str += '
';
+ }
+ });
+ $$c('#bg_blocks').append(str);
+ var blocks = $$c('#bg_blocks div');
+ var curBg = 'cur_background';
+ blocks.each(function () {
+ var blk = $$c(this);
+ blk.click(function () {
+ blocks.removeClass(curBg);
+ $$c(this).addClass(curBg);
+ });
+ });
+ setBackground(editor.pref('bkgd_color'), editor.pref('bkgd_url'));
+ $$c('#image_save_opts input').val([editor.pref('img_save')]);
+ /**
+ * @type {module:jQuerySpinButton.ValueCallback}
+ */
+
+ var changeRectRadius = function changeRectRadius(ctl) {
+ svgCanvas.setRectRadius(ctl.value);
+ };
+ /**
+ * @type {module:jQuerySpinButton.ValueCallback}
+ */
+
+
+ var changeFontSize = function changeFontSize(ctl) {
+ svgCanvas.setFontSize(ctl.value);
+ };
+ /**
+ * @type {module:jQuerySpinButton.ValueCallback}
+ */
+
+
+ var changeStrokeWidth = function changeStrokeWidth(ctl) {
+ var val = ctl.value;
+
+ if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) {
+ val = ctl.value = 1;
+ }
+
+ svgCanvas.setStrokeWidth(val);
+ };
+ /**
+ * @type {module:jQuerySpinButton.ValueCallback}
+ */
+
+
+ var changeRotationAngle = function changeRotationAngle(ctl) {
+ svgCanvas.setRotationAngle(ctl.value);
+ $$c('#tool_reorient').toggleClass('disabled', Number.parseInt(ctl.value) === 0);
+ };
+ /**
+ * @param {external:jQuery.fn.SpinButton} ctl Spin Button
+ * @param {string} [val=ctl.value]
+ * @returns {void}
+ */
+
+
+ var changeOpacity = function changeOpacity(ctl, val) {
+ if (isNullish(val)) {
+ val = ctl.value;
+ }
+
+ $$c('#group_opacity').val(val);
+
+ if (!ctl || !ctl.handle) {
+ $$c('#opac_slider').slider('option', 'value', val);
+ }
+
+ svgCanvas.setOpacity(val / 100);
+ };
+ /**
+ * @param {external:jQuery.fn.SpinButton} ctl Spin Button
+ * @param {string} [val=ctl.value]
+ * @param {boolean} noUndo
+ * @returns {void}
+ */
+
+
+ var changeBlur = function changeBlur(ctl, val, noUndo) {
+ if (isNullish(val)) {
+ val = ctl.value;
+ }
+
+ $$c('#blur').val(val);
+ var complete = false;
+
+ if (!ctl || !ctl.handle) {
+ $$c('#blur_slider').slider('option', 'value', val);
+ complete = true;
+ }
+
+ if (noUndo) {
+ svgCanvas.setBlurNoUndo(val);
+ } else {
+ svgCanvas.setBlur(val, complete);
+ }
+ };
+
+ $$c('#stroke_style').change(function () {
+ svgCanvas.setStrokeAttr('stroke-dasharray', $$c(this).val());
+ operaRepaint();
+ });
+ $$c('#stroke_linejoin').change(function () {
+ svgCanvas.setStrokeAttr('stroke-linejoin', $$c(this).val());
+ operaRepaint();
+ }); // Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
+
+ $$c('select').change(function () {
+ $$c(this).blur();
+ }); // fired when user wants to move elements to another layer
+
+ var promptMoveLayerOnce = false;
+ $$c('#selLayerNames').change( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6() {
+ var destLayer, confirmStr, moveToLayer, ok;
+ return regeneratorRuntime.wrap(function _callee6$(_context6) {
+ while (1) {
+ switch (_context6.prev = _context6.next) {
+ case 0:
+ destLayer = this.options[this.selectedIndex].value;
+ confirmStr = uiStrings$1.notification.QmoveElemsToLayer.replace('%s', destLayer);
+ /**
+ * @param {boolean} ok
+ * @returns {void}
+ */
+
+ moveToLayer = function moveToLayer(ok) {
+ if (!ok) {
+ return;
+ }
+
+ promptMoveLayerOnce = true;
+ svgCanvas.moveSelectedToLayer(destLayer);
+ svgCanvas.clearSelection();
+ populateLayers();
+ };
+
+ if (!destLayer) {
+ _context6.next = 14;
+ break;
+ }
+
+ if (!promptMoveLayerOnce) {
+ _context6.next = 8;
+ break;
+ }
+
+ moveToLayer(true);
+ _context6.next = 14;
+ break;
+
+ case 8:
+ _context6.next = 10;
+ return $$c.confirm(confirmStr);
+
+ case 10:
+ ok = _context6.sent;
+
+ if (ok) {
+ _context6.next = 13;
+ break;
+ }
+
+ return _context6.abrupt("return");
+
+ case 13:
+ moveToLayer(true);
+
+ case 14:
+ case "end":
+ return _context6.stop();
+ }
+ }
+ }, _callee6, this);
+ })));
+ $$c('#font_family').change(function () {
+ svgCanvas.setFontFamily(this.value);
+ });
+ $$c('#seg_type').change(function () {
+ svgCanvas.setSegType($$c(this).val());
+ });
+ $$c('#text').bind('keyup input', function () {
+ svgCanvas.setTextContent(this.value);
+ });
+ $$c('#image_url').change(function () {
+ setImageURL(this.value);
+ });
+ $$c('#link_url').change(function () {
+ if (this.value.length) {
+ svgCanvas.setLinkURL(this.value);
+ } else {
+ svgCanvas.removeHyperlink();
+ }
+ });
+ $$c('#g_title').change(function () {
+ svgCanvas.setGroupTitle(this.value);
+ });
+ $$c('.attr_changer').change(function () {
+ var attr = this.getAttribute('data-attr');
+ var val = this.value;
+ var valid = isValidUnit(attr, val, selectedElement);
+
+ if (!valid) {
+ this.value = selectedElement.getAttribute(attr);
+ /* await */
+
+ $$c.alert(uiStrings$1.notification.invalidAttrValGiven);
+ return false;
+ }
+
+ if (attr !== 'id' && attr !== 'class') {
+ if (isNaN(val)) {
+ val = svgCanvas.convertToNum(attr, val);
+ } else if (curConfig.baseUnit !== 'px') {
+ // Convert unitless value to one with given unit
+ var unitData = getTypeMap();
+
+ if (selectedElement[attr] || svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') {
+ val *= unitData[curConfig.baseUnit];
+ }
+ }
+ } // if the user is changing the id, then de-select the element first
+ // change the ID, then re-select it with the new ID
+
+
+ if (attr === 'id') {
+ var elem = selectedElement;
+ svgCanvas.clearSelection();
+ elem.id = val;
+ svgCanvas.addToSelection([elem], true);
+ } else {
+ svgCanvas.changeSelectedAttribute(attr, val);
+ }
+
+ this.blur();
+ return true;
+ }); // Prevent selection of elements when shift-clicking
+
+ $$c('#palette').mouseover(function () {
+ var inp = $$c('
');
+ $$c(this).append(inp);
+ inp.focus().remove();
+ });
+ $$c('.palette_item').mousedown(function (evt) {
+ // shift key or right click for stroke
+ var picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill';
+ var color = $$c(this).data('rgb');
+ var paint; // Webkit-based browsers returned 'initial' here for no stroke
+
+ if (color === 'none' || color === 'transparent' || color === 'initial') {
+ color = 'none';
+ paint = new $$c.jGraduate.Paint();
+ } else {
+ paint = new $$c.jGraduate.Paint({
+ alpha: 100,
+ solidColor: color.substr(1)
+ });
+ }
+
+ paintBox[picker].setPaint(paint);
+ svgCanvas.setColor(picker, color);
+
+ if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) {
+ svgCanvas.setPaintOpacity(picker, 1.0);
+ }
+
+ updateToolButtonState();
+ }).bind('contextmenu', function (e) {
+ e.preventDefault();
+ });
+ $$c('#toggle_stroke_tools').on('click', function () {
+ $$c('#tools_bottom').toggleClass('expanded');
+ });
+
+ (function () {
+ var wArea = workarea[0];
+ var lastX = null,
+ lastY = null,
+ panning = false,
+ keypan = false;
+ $$c('#svgcanvas').bind('mousemove mouseup', function (evt) {
+ if (panning === false) {
+ return true;
+ }
+
+ wArea.scrollLeft -= evt.clientX - lastX;
+ wArea.scrollTop -= evt.clientY - lastY;
+ lastX = evt.clientX;
+ lastY = evt.clientY;
+
+ if (evt.type === 'mouseup') {
+ panning = false;
+ }
+
+ return false;
+ }).mousedown(function (evt) {
+ if (evt.button === 1 || keypan === true) {
+ panning = true;
+ lastX = evt.clientX;
+ lastY = evt.clientY;
+ return false;
+ }
+
+ return true;
+ });
+ $$c(window).mouseup(function () {
+ panning = false;
+ });
+ $$c(document).bind('keydown', 'space', function (evt) {
+ svgCanvas.spaceKey = keypan = true;
+ evt.preventDefault();
+ }).bind('keyup', 'space', function (evt) {
+ evt.preventDefault();
+ svgCanvas.spaceKey = keypan = false;
+ }).bind('keydown', 'shift', function (evt) {
+ if (svgCanvas.getMode() === 'zoom') {
+ workarea.css('cursor', zoomOutIcon);
+ }
+ }).bind('keyup', 'shift', function (evt) {
+ if (svgCanvas.getMode() === 'zoom') {
+ workarea.css('cursor', zoomInIcon);
+ }
+ });
+ /**
+ * @function module:SVGEditor.setPanning
+ * @param {boolean} active
+ * @returns {void}
+ */
+
+ editor.setPanning = function (active) {
+ svgCanvas.spaceKey = keypan = active;
+ };
+ })();
+
+ (function () {
+ var button = $$c('#main_icon');
+ var overlay = $$c('#main_icon span');
+ var list = $$c('#main_menu');
+ var onButton = false;
+ var height = 0;
+ var jsHover = true;
+ var setClick = false;
+ /*
+ // Currently unused
+ const hideMenu = function () {
+ list.fadeOut(200);
+ };
+ */
+
+ $$c(window).mouseup(function (evt) {
+ if (!onButton) {
+ button.removeClass('buttondown'); // do not hide if it was the file input as that input needs to be visible
+ // for its change event to fire
+
+ if (evt.target.tagName !== 'INPUT') {
+ list.fadeOut(200);
+ } else if (!setClick) {
+ setClick = true;
+ $$c(evt.target).click(function () {
+ list.css('margin-left', '-9999px').show();
+ });
+ }
+ }
+
+ onButton = false;
+ }).mousedown(function (evt) {
+ // $('.contextMenu').hide();
+ var islib = $$c(evt.target).closest('div.tools_flyout, .contextMenu').length;
+
+ if (!islib) {
+ $$c('.tools_flyout:visible,.contextMenu').fadeOut(250);
+ }
+ });
+ overlay.bind('mousedown', function () {
+ if (!button.hasClass('buttondown')) {
+ // Margin must be reset in case it was changed before;
+ list.css('margin-left', 0).show();
+
+ if (!height) {
+ height = list.height();
+ } // Using custom animation as slideDown has annoying 'bounce effect'
+
+
+ list.css('height', 0).animate({
+ height: height
+ }, 200);
+ onButton = true;
+ } else {
+ list.fadeOut(200);
+ }
+
+ button.toggleClass('buttondown buttonup');
+ }).hover(function () {
+ onButton = true;
+ }).mouseout(function () {
+ onButton = false;
+ });
+ var listItems = $$c('#main_menu li'); // Check if JS method of hovering needs to be used (Webkit bug)
+
+ listItems.mouseover(function () {
+ jsHover = $$c(this).css('background-color') === 'rgba(0, 0, 0, 0)';
+ listItems.unbind('mouseover');
+
+ if (jsHover) {
+ listItems.mouseover(function () {
+ this.style.backgroundColor = '#FFC';
+ }).mouseout(function () {
+ this.style.backgroundColor = 'transparent';
+ return true;
+ });
+ }
+ });
+ })(); // Made public for UI customization.
+ // TODO: Group UI functions into a public editor.ui interface.
+
+ /**
+ * See {@link http://api.jquery.com/bind/#bind-eventType-eventData-handler}.
+ * @callback module:SVGEditor.DropDownCallback
+ * @param {external:jQuery.Event} ev See {@link http://api.jquery.com/Types/#Event}
+ * @listens external:jQuery.Event
+ * @returns {void|boolean} Calls `preventDefault()` and `stopPropagation()`
+ */
+
+ /**
+ * @function module:SVGEditor.addDropDown
+ * @param {Element|string} elem DOM Element or selector
+ * @param {module:SVGEditor.DropDownCallback} callback Mouseup callback
+ * @param {boolean} dropUp
+ * @returns {void}
+ */
+
+
+ editor.addDropDown = function (elem, callback, dropUp) {
+ if (!$$c(elem).length) {
+ return;
+ } // Quit if called on non-existent element
+
+
+ var button = $$c(elem).find('button');
+ var list = $$c(elem).find('ul').attr('id', $$c(elem)[0].id + '-list');
+
+ if (dropUp) {
+ $$c(elem).addClass('dropup');
+ } else {
+ // Move list to place where it can overflow container
+ $$c('#option_lists').append(list);
+ }
+
+ list.find('li').bind('mouseup', callback);
+ var onButton = false;
+ $$c(window).mouseup(function (evt) {
+ if (!onButton) {
+ button.removeClass('down');
+ list.hide();
+ }
+
+ onButton = false;
+ });
+ button.bind('mousedown', function () {
+ if (!button.hasClass('down')) {
+ if (!dropUp) {
+ var pos = $$c(elem).position();
+ list.css({
+ top: pos.top + 24,
+ left: pos.left - 10
+ });
+ }
+
+ list.show();
+ onButton = true;
+ } else {
+ list.hide();
+ }
+
+ button.toggleClass('down');
+ }).hover(function () {
+ onButton = true;
+ }).mouseout(function () {
+ onButton = false;
+ });
+ };
+
+ editor.addDropDown('#font_family_dropdown', function () {
+ $$c('#font_family').val($$c(this).text()).change();
+ });
+ editor.addDropDown('#opacity_dropdown', function () {
+ if ($$c(this).find('div').length) {
+ return;
+ }
+
+ var perc = Number.parseInt($$c(this).text().split('%')[0]);
+ changeOpacity(false, perc);
+ }, true); // For slider usage, see: http://jqueryui.com/demos/slider/
+
+ $$c('#opac_slider').slider({
+ start: function start() {
+ $$c('#opacity_dropdown li:not(.special)').hide();
+ },
+ stop: function stop() {
+ $$c('#opacity_dropdown li').show();
+ $$c(window).mouseup();
+ },
+ slide: function slide(evt, ui) {
+ changeOpacity(ui);
+ }
+ });
+ editor.addDropDown('#blur_dropdown', $$c.noop);
+ var slideStart = false;
+ $$c('#blur_slider').slider({
+ max: 10,
+ step: 0.1,
+ stop: function stop(evt, ui) {
+ slideStart = false;
+ changeBlur(ui);
+ $$c('#blur_dropdown li').show();
+ $$c(window).mouseup();
+ },
+ start: function start() {
+ slideStart = true;
+ },
+ slide: function slide(evt, ui) {
+ changeBlur(ui, null, slideStart);
+ }
+ });
+ editor.addDropDown('#zoom_dropdown', function () {
+ var item = $$c(this);
+ var val = item.data('val');
+
+ if (val) {
+ zoomChanged(window, val);
+ } else {
+ changeZoom({
+ value: Number.parseFloat(item.text())
+ });
+ }
+ }, true);
+ addAltDropDown('#stroke_linecap', '#linecap_opts', function () {
+ setStrokeOpt(this, true);
+ }, {
+ dropUp: true
+ });
+ addAltDropDown('#stroke_linejoin', '#linejoin_opts', function () {
+ setStrokeOpt(this, true);
+ }, {
+ dropUp: true
+ });
+ addAltDropDown('#tool_position', '#position_opts', function () {
+ var letter = this.id.replace('tool_pos', '').charAt(0);
+ svgCanvas.alignSelectedElements(letter, 'page');
+ }, {
+ multiclick: true
+ });
+ /*
+ When a flyout icon is selected
+ (if flyout) {
+ - Change the icon
+ - Make pressing the button run its stuff
+ }
+ - Run its stuff
+ When its shortcut key is pressed
+ - If not current in list, do as above
+ , else:
+ - Just run its stuff
+ */
+ // Unfocus text input when workarea is mousedowned.
+
+ (function () {
+ var inp;
+ /**
+ *
+ * @returns {void}
+ */
+
+ var unfocus = function unfocus() {
+ $$c(inp).blur();
+ };
+
+ $$c('#svg_editor').find('button, select, input:not(#text)').focus(function () {
+ inp = this;
+ uiContext = 'toolbars';
+ workarea.mousedown(unfocus);
+ }).blur(function () {
+ uiContext = 'canvas';
+ workarea.unbind('mousedown', unfocus); // Go back to selecting text if in textedit mode
+
+ if (svgCanvas.getMode() === 'textedit') {
+ $$c('#text').focus();
+ }
+ });
+ })();
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickFHPath = function clickFHPath() {
+ if (toolButtonClick('#tool_fhpath')) {
+ svgCanvas.setMode('fhpath');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickLine = function clickLine() {
+ if (toolButtonClick('#tool_line')) {
+ svgCanvas.setMode('line');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickSquare = function clickSquare() {
+ if (toolButtonClick('#tool_square')) {
+ svgCanvas.setMode('square');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickRect = function clickRect() {
+ if (toolButtonClick('#tool_rect')) {
+ svgCanvas.setMode('rect');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickFHRect = function clickFHRect() {
+ if (toolButtonClick('#tool_fhrect')) {
+ svgCanvas.setMode('fhrect');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickCircle = function clickCircle() {
+ if (toolButtonClick('#tool_circle')) {
+ svgCanvas.setMode('circle');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickEllipse = function clickEllipse() {
+ if (toolButtonClick('#tool_ellipse')) {
+ svgCanvas.setMode('ellipse');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickFHEllipse = function clickFHEllipse() {
+ if (toolButtonClick('#tool_fhellipse')) {
+ svgCanvas.setMode('fhellipse');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickImage = function clickImage() {
+ if (toolButtonClick('#tool_image')) {
+ svgCanvas.setMode('image');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickZoom = function clickZoom() {
+ if (toolButtonClick('#tool_zoom')) {
+ svgCanvas.setMode('zoom');
+ workarea.css('cursor', zoomInIcon);
+ }
+ };
+ /**
+ * @param {Float} multiplier
+ * @returns {void}
+ */
+
+
+ var zoomImage = function zoomImage(multiplier) {
+ var res = svgCanvas.getResolution();
+ multiplier = multiplier ? res.zoom * multiplier : 1; // setResolution(res.w * multiplier, res.h * multiplier, true);
+
+ $$c('#zoom').val(multiplier * 100);
+ svgCanvas.setZoom(multiplier);
+ zoomDone();
+ updateCanvas(true);
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var dblclickZoom = function dblclickZoom() {
+ if (toolButtonClick('#tool_zoom')) {
+ zoomImage();
+ setSelectMode();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickText = function clickText() {
+ if (toolButtonClick('#tool_text')) {
+ svgCanvas.setMode('text');
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickPath = function clickPath() {
+ if (toolButtonClick('#tool_path')) {
+ svgCanvas.setMode('path');
+ }
+ };
+ /**
+ * Delete is a contextual tool that only appears in the ribbon if
+ * an element has been selected.
+ * @returns {void}
+ */
+
+
+ var deleteSelected = function deleteSelected() {
+ if (!isNullish(selectedElement) || multiselected) {
+ svgCanvas.deleteSelectedElements();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var cutSelected = function cutSelected() {
+ if (!isNullish(selectedElement) || multiselected) {
+ svgCanvas.cutSelectedElements();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var copySelected = function copySelected() {
+ if (!isNullish(selectedElement) || multiselected) {
+ svgCanvas.copySelectedElements();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var pasteInCenter = function pasteInCenter() {
+ var zoom = svgCanvas.getZoom();
+ var x = (workarea[0].scrollLeft + workarea.width() / 2) / zoom - svgCanvas.contentW;
+ var y = (workarea[0].scrollTop + workarea.height() / 2) / zoom - svgCanvas.contentH;
+ svgCanvas.pasteElements('point', x, y);
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var moveToTopSelected = function moveToTopSelected() {
+ if (!isNullish(selectedElement)) {
+ svgCanvas.moveToTopSelectedElement();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var moveToBottomSelected = function moveToBottomSelected() {
+ if (!isNullish(selectedElement)) {
+ svgCanvas.moveToBottomSelectedElement();
+ }
+ };
+ /**
+ * @param {"Up"|"Down"} dir
+ * @returns {void}
+ */
+
+
+ var moveUpDownSelected = function moveUpDownSelected(dir) {
+ if (!isNullish(selectedElement)) {
+ svgCanvas.moveUpDownSelected(dir);
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var convertToPath = function convertToPath() {
+ if (!isNullish(selectedElement)) {
+ svgCanvas.convertToPath();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var reorientPath = function reorientPath() {
+ if (!isNullish(selectedElement)) {
+ path.reorient();
+ }
+ };
+ /**
+ *
+ * @returns {Promise
} Resolves to `undefined`
+ */
+
+
+ var makeHyperlink = /*#__PURE__*/function () {
+ var _ref14 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() {
+ var url;
+ return regeneratorRuntime.wrap(function _callee7$(_context7) {
+ while (1) {
+ switch (_context7.prev = _context7.next) {
+ case 0:
+ if (!(!isNullish(selectedElement) || multiselected)) {
+ _context7.next = 5;
+ break;
+ }
+
+ _context7.next = 3;
+ return $$c.prompt(uiStrings$1.notification.enterNewLinkURL, 'http://');
+
+ case 3:
+ url = _context7.sent;
+
+ if (url) {
+ svgCanvas.makeHyperlink(url);
+ }
+
+ case 5:
+ case "end":
+ return _context7.stop();
+ }
+ }
+ }, _callee7);
+ }));
+
+ return function makeHyperlink() {
+ return _ref14.apply(this, arguments);
+ };
+ }();
+ /**
+ * @param {Float} dx
+ * @param {Float} dy
+ * @returns {void}
+ */
+
+
+ var moveSelected = function moveSelected(dx, dy) {
+ if (!isNullish(selectedElement) || multiselected) {
+ if (curConfig.gridSnapping) {
+ // Use grid snap value regardless of zoom level
+ var multi = svgCanvas.getZoom() * curConfig.snappingStep;
+ dx *= multi;
+ dy *= multi;
+ }
+
+ svgCanvas.moveSelectedElements(dx, dy);
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var linkControlPoints = function linkControlPoints() {
+ $$c('#tool_node_link').toggleClass('push_button_pressed tool_button');
+ var linked = $$c('#tool_node_link').hasClass('push_button_pressed');
+ path.linkControlPoints(linked);
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clonePathNode = function clonePathNode() {
+ if (path.getNodePoint()) {
+ path.clonePathNode();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var deletePathNode = function deletePathNode() {
+ if (path.getNodePoint()) {
+ path.deletePathNode();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var addSubPath = function addSubPath() {
+ var button = $$c('#tool_add_subpath');
+ var sp = !button.hasClass('push_button_pressed');
+ button.toggleClass('push_button_pressed tool_button');
+ path.addSubPath(sp);
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var opencloseSubPath = function opencloseSubPath() {
+ path.opencloseSubPath();
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var selectNext = function selectNext() {
+ svgCanvas.cycleElement(1);
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var selectPrev = function selectPrev() {
+ svgCanvas.cycleElement(0);
+ };
+ /**
+ * @param {0|1} cw
+ * @param {Integer} step
+ * @returns {void}
+ */
+
+
+ var rotateSelected = function rotateSelected(cw, step) {
+ if (isNullish(selectedElement) || multiselected) {
+ return;
+ }
+
+ if (!cw) {
+ step *= -1;
+ }
+
+ var angle = Number.parseFloat($$c('#angle').val()) + step;
+ svgCanvas.setRotationAngle(angle);
+ updateContextPanel();
+ };
+ /**
+ * @fires module:svgcanvas.SvgCanvas#event:ext_onNewDocument
+ * @returns {Promise} Resolves to `undefined`
+ */
+
+
+ var clickClear = /*#__PURE__*/function () {
+ var _ref15 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8() {
+ var _curConfig$dimensions, x, y, ok;
+
+ return regeneratorRuntime.wrap(function _callee8$(_context8) {
+ while (1) {
+ switch (_context8.prev = _context8.next) {
+ case 0:
+ _curConfig$dimensions = _slicedToArray(curConfig.dimensions, 2), x = _curConfig$dimensions[0], y = _curConfig$dimensions[1];
+ _context8.next = 3;
+ return $$c.confirm(uiStrings$1.notification.QwantToClear);
+
+ case 3:
+ ok = _context8.sent;
+
+ if (ok) {
+ _context8.next = 6;
+ break;
+ }
+
+ return _context8.abrupt("return");
+
+ case 6:
+ setSelectMode();
+ svgCanvas.clear();
+ svgCanvas.setResolution(x, y);
+ updateCanvas(true);
+ zoomImage();
+ populateLayers();
+ updateContextPanel();
+ prepPaints();
+ svgCanvas.runExtensions('onNewDocument');
+
+ case 15:
+ case "end":
+ return _context8.stop();
+ }
+ }
+ }, _callee8);
+ }));
+
+ return function clickClear() {
+ return _ref15.apply(this, arguments);
+ };
+ }();
+ /**
+ *
+ * @returns {false}
+ */
+
+
+ var clickBold = function clickBold() {
+ svgCanvas.setBold(!svgCanvas.getBold());
+ updateContextPanel();
+ return false;
+ };
+ /**
+ *
+ * @returns {false}
+ */
+
+
+ var clickItalic = function clickItalic() {
+ svgCanvas.setItalic(!svgCanvas.getItalic());
+ updateContextPanel();
+ return false;
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickSave = function clickSave() {
+ // In the future, more options can be provided here
+ var saveOpts = {
+ images: editor.pref('img_save'),
+ round_digits: 6
+ };
+ svgCanvas.save(saveOpts);
+ };
+
+ var loadingURL;
+ /**
+ *
+ * @returns {Promise} Resolves to `undefined`
+ */
+
+ var clickExport = /*#__PURE__*/function () {
+ var _ref16 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9() {
+ var imgType, exportWindowName, openExportWindow, chrome, quality;
+ return regeneratorRuntime.wrap(function _callee9$(_context9) {
+ while (1) {
+ switch (_context9.prev = _context9.next) {
+ case 0:
+ openExportWindow = function _openExportWindow() {
+ var loadingImage = uiStrings$1.notification.loadingImage;
+
+ if (curConfig.exportWindowType === 'new') {
+ editor.exportWindowCt++;
+ }
+
+ exportWindowName = curConfig.canvasName + editor.exportWindowCt;
+ var popHTML, popURL;
+
+ if (loadingURL) {
+ popURL = loadingURL;
+ } else {
+ popHTML = "\n \n \n ".concat(loadingImage, "\n \n ").concat(loadingImage, "
\n ");
+
+ if (typeof URL !== 'undefined' && URL.createObjectURL) {
+ var blob = new Blob([popHTML], {
+ type: 'text/html'
+ });
+ popURL = URL.createObjectURL(blob);
+ } else {
+ popURL = 'data:text/html;base64;charset=utf-8,' + encode64(popHTML);
+ }
+
+ loadingURL = popURL;
+ }
+
+ exportWindow = window.open(popURL, exportWindowName);
+ };
+
+ _context9.next = 3;
+ return $$c.select('Select an image type for export: ', [// See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support
+ // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG'
+ 'PNG', 'JPEG', 'BMP', 'WEBP', 'PDF'], function () {
+ var sel = $$c(this);
+
+ if (sel.val() === 'JPEG' || sel.val() === 'WEBP') {
+ if (!$$c('#image-slider').length) {
+ $$c("")).appendTo(sel.parent());
+ }
+ } else {
+ $$c('#image-slider').parent().remove();
+ }
+ });
+
+ case 3:
+ imgType = _context9.sent;
+
+ if (imgType) {
+ _context9.next = 6;
+ break;
+ }
+
+ return _context9.abrupt("return");
+
+ case 6:
+ chrome = isChrome();
+
+ if (!(imgType === 'PDF')) {
+ _context9.next = 12;
+ break;
+ }
+
+ if (!customExportPDF && !chrome) {
+ openExportWindow();
+ }
+
+ svgCanvas.exportPDF(exportWindowName);
+ _context9.next = 16;
+ break;
+
+ case 12:
+ if (!customExportImage) {
+ openExportWindow();
+ }
+
+ quality = Number.parseInt($$c('#image-slider').val()) / 100;
+ /* const results = */
+
+ _context9.next = 16;
+ return svgCanvas.rasterExport(imgType, quality, exportWindowName);
+
+ case 16:
+ case "end":
+ return _context9.stop();
+ }
+ }
+ }, _callee9);
+ }));
+
+ return function clickExport() {
+ return _ref16.apply(this, arguments);
+ };
+ }();
+ /**
+ * By default, svgCanvas.open() is a no-op. It is up to an extension
+ * mechanism (opera widget, etc.) to call `setCustomHandlers()` which
+ * will make it do something.
+ * @returns {void}
+ */
+
+
+ var clickOpen = function clickOpen() {
+ svgCanvas.open();
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickImport = function clickImport() {
+ /* */
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickUndo = function clickUndo() {
+ if (undoMgr.getUndoStackSize() > 0) {
+ undoMgr.undo();
+ populateLayers();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickRedo = function clickRedo() {
+ if (undoMgr.getRedoStackSize() > 0) {
+ undoMgr.redo();
+ populateLayers();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickGroup = function clickGroup() {
+ // group
+ if (multiselected) {
+ svgCanvas.groupSelectedElements(); // ungroup
+ } else if (selectedElement) {
+ svgCanvas.ungroupSelectedElement();
+ }
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickClone = function clickClone() {
+ svgCanvas.cloneSelectedElements(20, 20);
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickAlign = function clickAlign() {
+ var letter = this.id.replace('tool_align', '').charAt(0);
+ svgCanvas.alignSelectedElements(letter, $$c('#align_relative_to').val());
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var clickWireframe = function clickWireframe() {
+ $$c('#tool_wireframe').toggleClass('push_button_pressed tool_button');
+ workarea.toggleClass('wireframe');
+
+ if (supportsNonSS) {
+ return;
+ }
+
+ var wfRules = $$c('#wireframe_rules');
+
+ if (!wfRules.length) {
+ /* wfRules = */
+ $$c('').appendTo('head');
+ } else {
+ wfRules.empty();
+ }
+
+ updateWireFrame();
+ };
+
+ $$c('#svg_docprops_container, #svg_prefs_container').draggable({
+ cancel: 'button,fieldset',
+ containment: 'window'
+ }).css('position', 'absolute');
+ var docprops = false;
+ var preferences = false;
+ /**
+ *
+ * @returns {void}
+ */
+
+ var showDocProperties = function showDocProperties() {
+ if (docprops) {
+ return;
+ }
+
+ docprops = true; // This selects the correct radio button by using the array notation
+
+ $$c('#image_save_opts input').val([editor.pref('img_save')]); // update resolution option with actual resolution
+
+ var res = svgCanvas.getResolution();
+
+ if (curConfig.baseUnit !== 'px') {
+ res.w = convertUnit(res.w) + curConfig.baseUnit;
+ res.h = convertUnit(res.h) + curConfig.baseUnit;
+ }
+
+ $$c('#canvas_width').val(res.w);
+ $$c('#canvas_height').val(res.h);
+ $$c('#canvas_title').val(svgCanvas.getDocumentTitle());
+ $$c('#svg_docprops').show();
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var showPreferences = function showPreferences() {
+ if (preferences) {
+ return;
+ }
+
+ preferences = true;
+ $$c('#main_menu').hide(); // Update background color with current one
+
+ var canvasBg = curPrefs.bkgd_color;
+ var url = editor.pref('bkgd_url');
+ blocks.each(function () {
+ var blk = $$c(this);
+ var isBg = blk.data('bgcolor') === canvasBg;
+ blk.toggleClass(curBg, isBg);
+ });
+
+ if (!canvasBg) {
+ blocks.eq(0).addClass(curBg);
+ }
+
+ if (url) {
+ $$c('#canvas_bg_url').val(url);
+ }
+
+ $$c('#grid_snapping_on').prop('checked', curConfig.gridSnapping);
+ $$c('#grid_snapping_step').attr('value', curConfig.snappingStep);
+ $$c('#grid_color').attr('value', curConfig.gridColor);
+ $$c('#svg_prefs').show();
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var openHomePage = function openHomePage() {
+ window.open(homePage, '_blank');
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var hideSourceEditor = function hideSourceEditor() {
+ $$c('#svg_source_editor').hide();
+ editingsource = false;
+ $$c('#svg_source_textarea').blur();
+ };
+ /**
+ *
+ * @returns {Promise} Resolves to `undefined`
+ */
+
+
+ var saveSourceEditor = /*#__PURE__*/function () {
+ var _ref17 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10() {
+ var saveChanges, ok;
+ return regeneratorRuntime.wrap(function _callee10$(_context10) {
+ while (1) {
+ switch (_context10.prev = _context10.next) {
+ case 0:
+ if (editingsource) {
+ _context10.next = 2;
+ break;
+ }
+
+ return _context10.abrupt("return");
+
+ case 2:
+ saveChanges = function saveChanges() {
+ svgCanvas.clearSelection();
+ hideSourceEditor();
+ zoomImage();
+ populateLayers();
+ updateTitle();
+ prepPaints();
+ };
+
+ if (svgCanvas.setSvgString($$c('#svg_source_textarea').val())) {
+ _context10.next = 11;
+ break;
+ }
+
+ _context10.next = 6;
+ return $$c.confirm(uiStrings$1.notification.QerrorsRevertToSource);
+
+ case 6:
+ ok = _context10.sent;
+
+ if (ok) {
+ _context10.next = 9;
+ break;
+ }
+
+ return _context10.abrupt("return");
+
+ case 9:
+ saveChanges();
+ return _context10.abrupt("return");
+
+ case 11:
+ saveChanges();
+ setSelectMode();
+
+ case 13:
+ case "end":
+ return _context10.stop();
+ }
+ }
+ }, _callee10);
+ }));
+
+ return function saveSourceEditor() {
+ return _ref17.apply(this, arguments);
+ };
+ }();
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var hideDocProperties = function hideDocProperties() {
+ $$c('#svg_docprops').hide();
+ $$c('#canvas_width,#canvas_height').removeAttr('disabled');
+ $$c('#resolution')[0].selectedIndex = 0;
+ $$c('#image_save_opts input').val([editor.pref('img_save')]);
+ docprops = false;
+ };
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ var hidePreferences = function hidePreferences() {
+ $$c('#svg_prefs').hide();
+ preferences = false;
+ };
+ /**
+ *
+ * @returns {boolean} Whether there were problems saving the document properties
+ */
+
+
+ var saveDocProperties = function saveDocProperties() {
+ // set title
+ var newTitle = $$c('#canvas_title').val();
+ updateTitle(newTitle);
+ svgCanvas.setDocumentTitle(newTitle); // update resolution
+
+ var width = $$c('#canvas_width'),
+ w = width.val();
+ var height = $$c('#canvas_height'),
+ h = height.val();
+
+ if (w !== 'fit' && !isValidUnit('width', w)) {
+ width.parent().addClass('error');
+ /* await */
+
+ $$c.alert(uiStrings$1.notification.invalidAttrValGiven);
+ return false;
+ }
+
+ width.parent().removeClass('error');
+
+ if (h !== 'fit' && !isValidUnit('height', h)) {
+ height.parent().addClass('error');
+ /* await */
+
+ $$c.alert(uiStrings$1.notification.invalidAttrValGiven);
+ return false;
+ }
+
+ height.parent().removeClass('error');
+
+ if (!svgCanvas.setResolution(w, h)) {
+ /* await */
+ $$c.alert(uiStrings$1.notification.noContentToFitTo);
+ return false;
+ } // Set image save option
+
+
+ editor.pref('img_save', $$c('#image_save_opts :checked').val());
+ updateCanvas();
+ hideDocProperties();
+ return true;
+ };
+ /**
+ * Save user preferences based on current values in the UI.
+ * @function module:SVGEditor.savePreferences
+ * @returns {Promise}
+ */
+
+
+ var savePreferences = editor.savePreferences = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11() {
+ var color, lang, _yield$editor$putLoca2, langParam, langData;
+
+ return regeneratorRuntime.wrap(function _callee11$(_context11) {
+ while (1) {
+ switch (_context11.prev = _context11.next) {
+ case 0:
+ // Set background
+ color = $$c('#bg_blocks div.cur_background').data('bgcolor') || '#FFF';
+ setBackground(color, $$c('#canvas_bg_url').val()); // set language
+
+ lang = $$c('#lang_select').val();
+
+ if (!(lang && lang !== editor.pref('lang'))) {
+ _context11.next = 11;
+ break;
+ }
+
+ _context11.next = 6;
+ return editor.putLocale(lang, goodLangs, curConfig);
+
+ case 6:
+ _yield$editor$putLoca2 = _context11.sent;
+ langParam = _yield$editor$putLoca2.langParam;
+ langData = _yield$editor$putLoca2.langData;
+ _context11.next = 11;
+ return setLang(langParam, langData);
+
+ case 11:
+ // set icon size
+ setIconSize($$c('#iconsize').val()); // set grid setting
+
+ curConfig.gridSnapping = $$c('#grid_snapping_on')[0].checked;
+ curConfig.snappingStep = $$c('#grid_snapping_step').val();
+ curConfig.gridColor = $$c('#grid_color').val();
+ curConfig.showRulers = $$c('#show_rulers')[0].checked;
+ $$c('#rulers').toggle(curConfig.showRulers);
+
+ if (curConfig.showRulers) {
+ updateRulers();
+ }
+
+ curConfig.baseUnit = $$c('#base_unit').val();
+ svgCanvas.setConfig(curConfig);
+ updateCanvas();
+ hidePreferences();
+
+ case 22:
+ case "end":
+ return _context11.stop();
+ }
+ }
+ }, _callee11);
+ }));
+
+ var resetScrollPos = $$c.noop;
+ /**
+ *
+ * @returns {Promise} Resolves to `undefined`
+ */
+
+ var cancelOverlays = /*#__PURE__*/function () {
+ var _ref19 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12() {
+ var ok;
+ return regeneratorRuntime.wrap(function _callee12$(_context12) {
+ while (1) {
+ switch (_context12.prev = _context12.next) {
+ case 0:
+ $$c('#dialog_box').hide();
+
+ if (!(!editingsource && !docprops && !preferences)) {
+ _context12.next = 4;
+ break;
+ }
+
+ if (curContext) {
+ svgCanvas.leaveContext();
+ }
+
+ return _context12.abrupt("return");
+
+ case 4:
+ if (!editingsource) {
+ _context12.next = 15;
+ break;
+ }
+
+ if (!(origSource !== $$c('#svg_source_textarea').val())) {
+ _context12.next = 12;
+ break;
+ }
+
+ _context12.next = 8;
+ return $$c.confirm(uiStrings$1.notification.QignoreSourceChanges);
+
+ case 8:
+ ok = _context12.sent;
+
+ if (ok) {
+ hideSourceEditor();
+ }
+
+ _context12.next = 13;
+ break;
+
+ case 12:
+ hideSourceEditor();
+
+ case 13:
+ _context12.next = 16;
+ break;
+
+ case 15:
+ if (docprops) {
+ hideDocProperties();
+ } else if (preferences) {
+ hidePreferences();
+ }
+
+ case 16:
+ resetScrollPos();
+
+ case 17:
+ case "end":
+ return _context12.stop();
+ }
+ }
+ }, _callee12);
+ }));
+
+ return function cancelOverlays() {
+ return _ref19.apply(this, arguments);
+ };
+ }();
+
+ var winWh = {
+ width: $$c(window).width(),
+ height: $$c(window).height()
+ }; // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)
+
+ if (isIE()) {
+ resetScrollPos = function resetScrollPos() {
+ if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) {
+ workarea[0].scrollLeft = curScrollPos.left;
+ workarea[0].scrollTop = curScrollPos.top;
+ }
+ };
+
+ curScrollPos = {
+ left: workarea[0].scrollLeft,
+ top: workarea[0].scrollTop
+ };
+ $$c(window).resize(resetScrollPos);
+ editor.ready(function () {
+ // TODO: Find better way to detect when to do this to minimize
+ // flickering effect
+ return new Promise(function (resolve, reject) {
+ // eslint-disable-line promise/avoid-new
+ setTimeout(function () {
+ resetScrollPos();
+ resolve();
+ }, 500);
+ });
+ });
+ workarea.scroll(function () {
+ curScrollPos = {
+ left: workarea[0].scrollLeft,
+ top: workarea[0].scrollTop
+ };
+ });
+ }
+
+ $$c(window).resize(function (evt) {
+ $$c.each(winWh, function (type, val) {
+ var curval = $$c(window)[type]();
+ workarea[0]['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;
+ winWh[type] = curval;
+ });
+ setFlyoutPositions();
+ });
+ workarea.scroll(function () {
+ // TODO: jQuery's scrollLeft/Top() wouldn't require a null check
+ if ($$c('#ruler_x').length) {
+ $$c('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft;
+ }
+
+ if ($$c('#ruler_y').length) {
+ $$c('#ruler_y')[0].scrollTop = workarea[0].scrollTop;
+ }
+ });
+ $$c('#url_notice').click(function () {
+ /* await */
+ $$c.alert(this.title);
+ });
+ $$c('#change_image_url').click(promptImgURL); // added these event handlers for all the push buttons so they
+ // behave more like buttons being pressed-in and not images
+
+ (function () {
+ var toolnames = ['clear', 'open', 'save', 'source', 'delete', 'delete_multi', 'paste', 'clone', 'clone_multi', 'move_top', 'move_bottom'];
+ var curClass = 'tool_button_current';
+ var allTools = '';
+ $$c.each(toolnames, function (i, item) {
+ allTools += (i ? ',' : '') + '#tool_' + item;
+ });
+ $$c(allTools).mousedown(function () {
+ $$c(this).addClass(curClass);
+ }).bind('mousedown mouseout', function () {
+ $$c(this).removeClass(curClass);
+ });
+ $$c('#tool_undo, #tool_redo').mousedown(function () {
+ if (!$$c(this).hasClass('disabled')) {
+ $$c(this).addClass(curClass);
+ }
+ }).bind('mousedown mouseout', function () {
+ $$c(this).removeClass(curClass);
+ });
+ })(); // switch modifier key in tooltips if mac
+ // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta
+ // in Opera and Chrome
+
+
+ if (isMac() && !window.opera) {
+ var shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone'];
+ var _i = shortcutButtons.length;
+
+ while (_i--) {
+ var button = document.getElementById(shortcutButtons[_i]);
+
+ if (button) {
+ var title = button.title;
+ var index = title.indexOf('Ctrl+');
+ button.title = [title.substr(0, index), 'Cmd+', title.substr(index + 5)].join('');
+ }
+ }
+ }
+ /**
+ * @param {external:jQuery} elem
+ * @todo Go back to the color boxes having white background-color and then setting
+ * background-image to none.png (otherwise partially transparent gradients look weird)
+ * @returns {void}
+ */
+
+
+ var colorPicker = function colorPicker(elem) {
+ var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill'; // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
+
+ var title = picker === 'stroke' ? uiStrings$1.ui.pick_stroke_paint_opacity : uiStrings$1.ui.pick_fill_paint_opacity; // let wasNone = false; // Currently unused
+
+ var pos = elem.offset();
+ var paint = paintBox[picker].paint;
+ $$c('#color_picker').draggable({
+ cancel: '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker',
+ containment: 'window'
+ }).css(curConfig.colorPickerCSS || {
+ left: pos.left - 140,
+ bottom: 40
+ }).jGraduate({
+ paint: paint,
+ window: {
+ pickerTitle: title
+ },
+ images: {
+ clientPath: curConfig.jGraduatePath
+ },
+ newstop: 'inverse'
+ }, function (p) {
+ paint = new $$c.jGraduate.Paint(p);
+ paintBox[picker].setPaint(paint);
+ svgCanvas.setPaint(picker, paint);
+ $$c('#color_picker').hide();
+ }, function () {
+ $$c('#color_picker').hide();
+ });
+ };
+ /**
+ * Paint box class.
+ */
+
+
+ var PaintBox = /*#__PURE__*/function () {
+ /**
+ * @param {string|Element|external:jQuery} container
+ * @param {"fill"} type
+ */
+ function PaintBox(container, type) {
+ _classCallCheck(this, PaintBox);
+
+ var cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke']; // set up gradients to be used for the buttons
+
+ var svgdocbox = new DOMParser().parseFromString(""), 'text/xml');
+ var docElem = svgdocbox.documentElement;
+ docElem = $$c(container)[0].appendChild(document.importNode(docElem, true));
+ docElem.setAttribute('width', 16.5);
+ this.rect = docElem.firstElementChild;
+ this.defs = docElem.getElementsByTagName('defs')[0];
+ this.grad = this.defs.firstElementChild;
+ this.paint = new $$c.jGraduate.Paint({
+ solidColor: cur.color
+ });
+ this.type = type;
+ }
+ /**
+ * @param {module:jGraduate~Paint} paint
+ * @param {boolean} apply
+ * @returns {void}
+ */
+
+
+ _createClass(PaintBox, [{
+ key: "setPaint",
+ value: function setPaint(paint, apply) {
+ this.paint = paint;
+ var ptype = paint.type;
+ var opac = paint.alpha / 100;
+ var fillAttr = 'none';
+
+ switch (ptype) {
+ case 'solidColor':
+ fillAttr = paint[ptype] !== 'none' ? '#' + paint[ptype] : paint[ptype];
+ break;
+
+ case 'linearGradient':
+ case 'radialGradient':
+ {
+ this.grad.remove();
+ this.grad = this.defs.appendChild(paint[ptype]);
+ var id = this.grad.id = 'gradbox_' + this.type;
+ fillAttr = 'url(#' + id + ')';
+ break;
+ }
+ }
+
+ this.rect.setAttribute('fill', fillAttr);
+ this.rect.setAttribute('opacity', opac);
+
+ if (apply) {
+ svgCanvas.setColor(this.type, this._paintColor, true);
+ svgCanvas.setPaintOpacity(this.type, this._paintOpacity, true);
+ }
+ }
+ /**
+ * @param {boolean} apply
+ * @returns {void}
+ */
+
+ }, {
+ key: "update",
+ value: function update(apply) {
+ if (!selectedElement) {
+ return;
+ }
+
+ var type = this.type;
+
+ switch (selectedElement.tagName) {
+ case 'use':
+ case 'image':
+ case 'foreignObject':
+ // These elements don't have fill or stroke, so don't change
+ // the current value
+ return;
+
+ case 'g':
+ case 'a':
+ {
+ var childs = selectedElement.getElementsByTagName('*');
+ var gPaint = null;
+
+ for (var _i2 = 0, len = childs.length; _i2 < len; _i2++) {
+ var elem = childs[_i2];
+ var p = elem.getAttribute(type);
+
+ if (_i2 === 0) {
+ gPaint = p;
+ } else if (gPaint !== p) {
+ gPaint = null;
+ break;
+ }
+ }
+
+ if (gPaint === null) {
+ // No common color, don't update anything
+ this._paintColor = null;
+ return;
+ }
+
+ this._paintColor = gPaint;
+ this._paintOpacity = 1;
+ break;
+ }
+
+ default:
+ {
+ this._paintOpacity = Number.parseFloat(selectedElement.getAttribute(type + '-opacity'));
+
+ if (Number.isNaN(this._paintOpacity)) {
+ this._paintOpacity = 1.0;
+ }
+
+ var defColor = type === 'fill' ? 'black' : 'none';
+ this._paintColor = selectedElement.getAttribute(type) || defColor;
+ }
+ }
+
+ if (apply) {
+ svgCanvas.setColor(type, this._paintColor, true);
+ svgCanvas.setPaintOpacity(type, this._paintOpacity, true);
+ }
+
+ this._paintOpacity *= 100;
+ var paint = getPaint(this._paintColor, this._paintOpacity, type); // update the rect inside #fill_color/#stroke_color
+
+ this.setPaint(paint);
+ }
+ /**
+ * @returns {void}
+ */
+
+ }, {
+ key: "prep",
+ value: function prep() {
+ var ptype = this.paint.type;
+
+ switch (ptype) {
+ case 'linearGradient':
+ case 'radialGradient':
+ {
+ var paint = new $$c.jGraduate.Paint({
+ copy: this.paint
+ });
+ svgCanvas.setPaint(this.type, paint);
+ break;
+ }
+ }
+ }
+ }]);
+
+ return PaintBox;
+ }();
+
+ PaintBox.ctr = 0;
+ paintBox.fill = new PaintBox('#fill_color', 'fill');
+ paintBox.stroke = new PaintBox('#stroke_color', 'stroke');
+ $$c('#stroke_width').val(curConfig.initStroke.width);
+ $$c('#group_opacity').val(curConfig.initOpacity * 100); // Use this SVG elem to test vectorEffect support
+
+ var testEl = paintBox.fill.rect.cloneNode(false);
+ testEl.setAttribute('style', 'vector-effect:non-scaling-stroke');
+ var supportsNonSS = testEl.style.vectorEffect === 'non-scaling-stroke';
+ testEl.removeAttribute('style');
+ var svgdocbox = paintBox.fill.rect.ownerDocument; // Use this to test support for blur element. Seems to work to test support in Webkit
+
+ var blurTest = svgdocbox.createElementNS(NS.SVG, 'feGaussianBlur');
+
+ if (blurTest.stdDeviationX === undefined) {
+ $$c('#tool_blur').hide();
+ }
+
+ $$c(blurTest).remove(); // Test for zoom icon support
+
+ (function () {
+ var pre = '-' + uaPrefix.toLowerCase() + '-zoom-';
+ var zoom = pre + 'in';
+ workarea.css('cursor', zoom);
+
+ if (workarea.css('cursor') === zoom) {
+ zoomInIcon = zoom;
+ zoomOutIcon = pre + 'out';
+ }
+
+ workarea.css('cursor', 'auto');
+ })(); // Test for embedImage support (use timeout to not interfere with page load)
+
+
+ setTimeout(function () {
+ svgCanvas.embedImage('images/logo.png', function (datauri) {
+ if (!datauri) {
+ // Disable option
+ $$c('#image_save_opts [value=embed]').attr('disabled', 'disabled');
+ $$c('#image_save_opts input').val(['ref']);
+ editor.pref('img_save', 'ref');
+ $$c('#image_opt_embed').css('color', '#666').attr('title', uiStrings$1.notification.featNotSupported);
+ }
+ });
+ }, 1000);
+ $$c('#fill_color, #tool_fill .icon_label').click(function () {
+ colorPicker($$c('#fill_color'));
+ updateToolButtonState();
+ });
+ $$c('#stroke_color, #tool_stroke .icon_label').click(function () {
+ colorPicker($$c('#stroke_color'));
+ updateToolButtonState();
+ });
+ $$c('#group_opacityLabel').click(function () {
+ $$c('#opacity_dropdown button').mousedown();
+ $$c(window).mouseup();
+ });
+ $$c('#zoomLabel').click(function () {
+ $$c('#zoom_dropdown button').mousedown();
+ $$c(window).mouseup();
+ });
+ $$c('#tool_move_top').mousedown(function (evt) {
+ $$c('#tools_stacking').show();
+ evt.preventDefault();
+ });
+ $$c('.layer_button').mousedown(function () {
+ $$c(this).addClass('layer_buttonpressed');
+ }).mouseout(function () {
+ $$c(this).removeClass('layer_buttonpressed');
+ }).mouseup(function () {
+ $$c(this).removeClass('layer_buttonpressed');
+ });
+ $$c('.push_button').mousedown(function () {
+ if (!$$c(this).hasClass('disabled')) {
+ $$c(this).addClass('push_button_pressed').removeClass('push_button');
+ }
+ }).mouseout(function () {
+ $$c(this).removeClass('push_button_pressed').addClass('push_button');
+ }).mouseup(function () {
+ $$c(this).removeClass('push_button_pressed').addClass('push_button');
+ }); // ask for a layer name
+
+ $$c('#layer_new').click( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee13() {
+ var uniqName, i, newName;
+ return regeneratorRuntime.wrap(function _callee13$(_context13) {
+ while (1) {
+ switch (_context13.prev = _context13.next) {
+ case 0:
+ i = svgCanvas.getCurrentDrawing().getNumLayers();
+
+ do {
+ uniqName = uiStrings$1.layers.layer + ' ' + ++i;
+ } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName));
+
+ _context13.next = 4;
+ return $$c.prompt(uiStrings$1.notification.enterUniqueLayerName, uniqName);
+
+ case 4:
+ newName = _context13.sent;
+
+ if (newName) {
+ _context13.next = 7;
+ break;
+ }
+
+ return _context13.abrupt("return");
+
+ case 7:
+ if (!svgCanvas.getCurrentDrawing().hasLayer(newName)) {
+ _context13.next = 10;
+ break;
+ }
+
+ /* await */
+ $$c.alert(uiStrings$1.notification.dupeLayerName);
+ return _context13.abrupt("return");
+
+ case 10:
+ svgCanvas.createLayer(newName);
+ updateContextPanel();
+ populateLayers();
+
+ case 13:
+ case "end":
+ return _context13.stop();
+ }
+ }
+ }, _callee13);
+ })));
+ /**
+ *
+ * @returns {void}
+ */
+
+ function deleteLayer() {
+ if (svgCanvas.deleteCurrentLayer()) {
+ updateContextPanel();
+ populateLayers(); // This matches what SvgCanvas does
+ // TODO: make this behavior less brittle (svg-editor should get which
+ // layer is selected from the canvas and then select that one in the UI)
+
+ $$c('#layerlist tr.layer').removeClass('layersel');
+ $$c('#layerlist tr.layer:first').addClass('layersel');
+ }
+ }
+ /**
+ *
+ * @returns {Promise}
+ */
+
+
+ function cloneLayer() {
+ return _cloneLayer.apply(this, arguments);
+ }
+ /**
+ *
+ * @returns {void}
+ */
+
+
+ function _cloneLayer() {
+ _cloneLayer = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee19() {
+ var name, newName;
+ return regeneratorRuntime.wrap(function _callee19$(_context19) {
+ while (1) {
+ switch (_context19.prev = _context19.next) {
+ case 0:
+ name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy';
+ _context19.next = 3;
+ return $$c.prompt(uiStrings$1.notification.enterUniqueLayerName, name);
+
+ case 3:
+ newName = _context19.sent;
+
+ if (newName) {
+ _context19.next = 6;
+ break;
+ }
+
+ return _context19.abrupt("return");
+
+ case 6:
+ if (!svgCanvas.getCurrentDrawing().hasLayer(newName)) {
+ _context19.next = 9;
+ break;
+ }
+
+ /* await */
+ $$c.alert(uiStrings$1.notification.dupeLayerName);
+ return _context19.abrupt("return");
+
+ case 9:
+ svgCanvas.cloneLayer(newName);
+ updateContextPanel();
+ populateLayers();
+
+ case 12:
+ case "end":
+ return _context19.stop();
+ }
+ }
+ }, _callee19);
+ }));
+ return _cloneLayer.apply(this, arguments);
+ }
+
+ function mergeLayer() {
+ if ($$c('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) {
+ return;
+ }
+
+ svgCanvas.mergeLayer();
+ updateContextPanel();
+ populateLayers();
+ }
+ /**
+ * @param {Integer} pos
+ * @returns {void}
+ */
+
+
+ function moveLayer(pos) {
+ var total = svgCanvas.getCurrentDrawing().getNumLayers();
+ var curIndex = $$c('#layerlist tr.layersel').index();
+
+ if (curIndex > 0 || curIndex < total - 1) {
+ curIndex += pos;
+ svgCanvas.setCurrentLayerPosition(total - curIndex - 1);
+ populateLayers();
+ }
+ }
+
+ $$c('#layer_delete').click(deleteLayer);
+ $$c('#layer_up').click(function () {
+ moveLayer(-1);
+ });
+ $$c('#layer_down').click(function () {
+ moveLayer(1);
+ });
+ $$c('#layer_rename').click( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee14() {
+ var oldName, newName;
+ return regeneratorRuntime.wrap(function _callee14$(_context14) {
+ while (1) {
+ switch (_context14.prev = _context14.next) {
+ case 0:
+ // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
+ oldName = $$c('#layerlist tr.layersel td.layername').text();
+ _context14.next = 3;
+ return $$c.prompt(uiStrings$1.notification.enterNewLayerName, '');
+
+ case 3:
+ newName = _context14.sent;
+
+ if (newName) {
+ _context14.next = 6;
+ break;
+ }
+
+ return _context14.abrupt("return");
+
+ case 6:
+ if (!(oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName))) {
+ _context14.next = 9;
+ break;
+ }
+
+ /* await */
+ $$c.alert(uiStrings$1.notification.layerHasThatName);
+ return _context14.abrupt("return");
+
+ case 9:
+ svgCanvas.renameCurrentLayer(newName);
+ populateLayers();
+
+ case 11:
+ case "end":
+ return _context14.stop();
+ }
+ }
+ }, _callee14);
+ })));
+ var SIDEPANEL_MAXWIDTH = 300;
+ var SIDEPANEL_OPENWIDTH = 150;
+ var sidedrag = -1,
+ sidedragging = false,
+ allowmove = false;
+ /**
+ * @param {Float} delta
+ * @fires module:svgcanvas.SvgCanvas#event:ext_workareaResized
+ * @returns {void}
+ */
+
+ var changeSidePanelWidth = function changeSidePanelWidth(delta) {
+ var rulerX = $$c('#ruler_x');
+ $$c('#sidepanels').width('+=' + delta);
+ $$c('#layerpanel').width('+=' + delta);
+ rulerX.css('right', Number.parseInt(rulerX.css('right')) + delta);
+ workarea.css('right', Number.parseInt(workarea.css('right')) + delta);
+ svgCanvas.runExtensions('workareaResized');
+ };
+ /**
+ * @param {Event} evt
+ * @returns {void}
+ */
+
+
+ var resizeSidePanel = function resizeSidePanel(evt) {
+ if (!allowmove) {
+ return;
+ }
+
+ if (sidedrag === -1) {
+ return;
+ }
+
+ sidedragging = true;
+ var deltaX = sidedrag - evt.pageX;
+ var sideWidth = $$c('#sidepanels').width();
+
+ if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) {
+ deltaX = SIDEPANEL_MAXWIDTH - sideWidth; // sideWidth = SIDEPANEL_MAXWIDTH;
+ } else if (sideWidth + deltaX < 2) {
+ deltaX = 2 - sideWidth; // sideWidth = 2;
+ }
+
+ if (deltaX === 0) {
+ return;
+ }
+
+ sidedrag -= deltaX;
+ changeSidePanelWidth(deltaX);
+ };
+ /**
+ * If width is non-zero, then fully close it; otherwise fully open it.
+ * @param {boolean} close Forces the side panel closed
+ * @returns {void}
+ */
+
+
+ var toggleSidePanel = function toggleSidePanel(close) {
+ var dpr = window.devicePixelRatio || 1;
+ var w = $$c('#sidepanels').width();
+ var isOpened = (dpr < 1 ? w : w / dpr) > 2;
+ var zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH;
+ var deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w;
+ changeSidePanelWidth(deltaX);
+ };
+
+ $$c('#sidepanel_handle').mousedown(function (evt) {
+ sidedrag = evt.pageX;
+ $$c(window).mousemove(resizeSidePanel);
+ allowmove = false; // Silly hack for Chrome, which always runs mousemove right after mousedown
+
+ setTimeout(function () {
+ allowmove = true;
+ }, 20);
+ }).mouseup(function (evt) {
+ if (!sidedragging) {
+ toggleSidePanel();
+ }
+
+ sidedrag = -1;
+ sidedragging = false;
+ });
+ $$c(window).mouseup(function () {
+ sidedrag = -1;
+ sidedragging = false;
+ $$c('#svg_editor').unbind('mousemove', resizeSidePanel);
+ });
+ populateLayers(); // function changeResolution (x,y) {
+ // const {zoom} = svgCanvas.getResolution();
+ // setResolution(x * zoom, y * zoom);
+ // }
+
+ var centerCanvas = function centerCanvas() {
+ // this centers the canvas vertically in the workarea (horizontal handled in CSS)
+ workarea.css('line-height', workarea.height() + 'px');
+ };
+
+ $$c(window).bind('load resize', centerCanvas);
+ /**
+ * @type {module:jQuerySpinButton.StepCallback}
+ */
+
+ function stepFontSize(elem, step) {
+ var origVal = Number(elem.value);
+ var sugVal = origVal + step;
+ var increasing = sugVal >= origVal;
+
+ if (step === 0) {
+ return origVal;
+ }
+
+ if (origVal >= 24) {
+ if (increasing) {
+ return Math.round(origVal * 1.1);
+ }
+
+ return Math.round(origVal / 1.1);
+ }
+
+ if (origVal <= 1) {
+ if (increasing) {
+ return origVal * 2;
+ }
+
+ return origVal / 2;
+ }
+
+ return sugVal;
+ }
+ /**
+ * @type {module:jQuerySpinButton.StepCallback}
+ */
+
+
+ function stepZoom(elem, step) {
+ var origVal = Number(elem.value);
+
+ if (origVal === 0) {
+ return 100;
+ }
+
+ var sugVal = origVal + step;
+
+ if (step === 0) {
+ return origVal;
+ }
+
+ if (origVal >= 100) {
+ return sugVal;
+ }
+
+ if (sugVal >= origVal) {
+ return origVal * 2;
+ }
+
+ return origVal / 2;
+ } // function setResolution (w, h, center) {
+ // updateCanvas();
+ // // w -= 0; h -= 0;
+ // // $('#svgcanvas').css({width: w, height: h});
+ // // $('#canvas_width').val(w);
+ // // $('#canvas_height').val(h);
+ // //
+ // // if (center) {
+ // // const wArea = workarea;
+ // // const scrollY = h/2 - wArea.height()/2;
+ // // const scrollX = w/2 - wArea.width()/2;
+ // // wArea[0].scrollTop = scrollY;
+ // // wArea[0].scrollLeft = scrollX;
+ // // }
+ // }
+
+
+ $$c('#resolution').change(function () {
+ var wh = $$c('#canvas_width,#canvas_height');
+
+ if (!this.selectedIndex) {
+ if ($$c('#canvas_width').val() === 'fit') {
+ wh.removeAttr('disabled').val(100);
+ }
+ } else if (this.value === 'content') {
+ wh.val('fit').attr('disabled', 'disabled');
+ } else {
+ var dims = this.value.split('x');
+ $$c('#canvas_width').val(dims[0]);
+ $$c('#canvas_height').val(dims[1]);
+ wh.removeAttr('disabled');
+ }
+ }); // Prevent browser from erroneously repopulating fields
+
+ $$c('input,select').attr('autocomplete', 'off');
+ var dialogSelectors = ['#tool_source_cancel', '#tool_docprops_cancel', '#tool_prefs_cancel', '.overlay'];
+ /* eslint-disable jsdoc/require-property */
+
+ /**
+ * Associate all button actions as well as non-button keyboard shortcuts.
+ * @namespace {PlainObject} module:SVGEditor~Actions
+ */
+
+ var Actions = function () {
+ /* eslint-enable jsdoc/require-property */
+
+ /**
+ * @typedef {PlainObject} module:SVGEditor.ToolButton
+ * @property {string} sel The CSS selector for the tool
+ * @property {external:jQuery.Function} fn A handler to be attached to the `evt`
+ * @property {string} evt The event for which the `fn` listener will be added
+ * @property {module:SVGEditor.Key} [key] [key, preventDefault, NoDisableInInput]
+ * @property {string} [parent] Selector
+ * @property {boolean} [hidekey] Whether to show key value in title
+ * @property {string} [icon] The button ID
+ * @property {boolean} isDefault For flyout holders
+ */
+
+ /**
+ *
+ * @name module:SVGEditor~ToolButtons
+ * @type {module:SVGEditor.ToolButton[]}
+ */
+ var toolButtons = [{
+ sel: '#tool_select',
+ fn: clickSelect,
+ evt: 'click',
+ key: ['V', true]
+ }, {
+ sel: '#tool_fhpath',
+ fn: clickFHPath,
+ evt: 'click',
+ key: ['Q', true]
+ }, {
+ sel: '#tool_line',
+ fn: clickLine,
+ evt: 'click',
+ key: ['L', true],
+ parent: '#tools_line',
+ prepend: true
+ }, {
+ sel: '#tool_rect',
+ fn: clickRect,
+ evt: 'mouseup',
+ key: ['R', true],
+ parent: '#tools_rect',
+ icon: 'rect'
+ }, {
+ sel: '#tool_square',
+ fn: clickSquare,
+ evt: 'mouseup',
+ parent: '#tools_rect',
+ icon: 'square'
+ }, {
+ sel: '#tool_fhrect',
+ fn: clickFHRect,
+ evt: 'mouseup',
+ parent: '#tools_rect',
+ icon: 'fh_rect'
+ }, {
+ sel: '#tool_ellipse',
+ fn: clickEllipse,
+ evt: 'mouseup',
+ key: ['E', true],
+ parent: '#tools_ellipse',
+ icon: 'ellipse'
+ }, {
+ sel: '#tool_circle',
+ fn: clickCircle,
+ evt: 'mouseup',
+ parent: '#tools_ellipse',
+ icon: 'circle'
+ }, {
+ sel: '#tool_fhellipse',
+ fn: clickFHEllipse,
+ evt: 'mouseup',
+ parent: '#tools_ellipse',
+ icon: 'fh_ellipse'
+ }, {
+ sel: '#tool_path',
+ fn: clickPath,
+ evt: 'click',
+ key: ['P', true]
+ }, {
+ sel: '#tool_text',
+ fn: clickText,
+ evt: 'click',
+ key: ['T', true]
+ }, {
+ sel: '#tool_image',
+ fn: clickImage,
+ evt: 'mouseup'
+ }, {
+ sel: '#tool_zoom',
+ fn: clickZoom,
+ evt: 'mouseup',
+ key: ['Z', true]
+ }, {
+ sel: '#tool_clear',
+ fn: clickClear,
+ evt: 'mouseup',
+ key: ['N', true]
+ }, {
+ sel: '#tool_save',
+ fn: function fn() {
+ if (editingsource) {
+ saveSourceEditor();
+ } else {
+ clickSave();
+ }
+ },
+ evt: 'mouseup',
+ key: ['S', true]
+ }, {
+ sel: '#tool_export',
+ fn: clickExport,
+ evt: 'mouseup'
+ }, {
+ sel: '#tool_open',
+ fn: clickOpen,
+ evt: 'mouseup',
+ key: ['O', true]
+ }, {
+ sel: '#tool_import',
+ fn: clickImport,
+ evt: 'mouseup'
+ }, {
+ sel: '#tool_source',
+ fn: showSourceEditor,
+ evt: 'click',
+ key: ['U', true]
+ }, {
+ sel: '#tool_wireframe',
+ fn: clickWireframe,
+ evt: 'click',
+ key: ['F', true]
+ }, {
+ key: ['esc', false, false],
+ fn: function fn() {
+ if (dialogSelectors.every(function (sel) {
+ return $$c(sel + ':hidden').length;
+ })) {
+ svgCanvas.clearSelection();
+ }
+ },
+ hidekey: true
+ }, {
+ sel: dialogSelectors.join(','),
+ fn: cancelOverlays,
+ evt: 'click',
+ key: ['esc', false, false],
+ hidekey: true
+ }, {
+ sel: '#tool_source_save',
+ fn: saveSourceEditor,
+ evt: 'click'
+ }, {
+ sel: '#tool_docprops_save',
+ fn: saveDocProperties,
+ evt: 'click'
+ }, {
+ sel: '#tool_docprops',
+ fn: showDocProperties,
+ evt: 'click'
+ }, {
+ sel: '#tool_prefs_save',
+ fn: savePreferences,
+ evt: 'click'
+ }, {
+ sel: '#tool_editor_prefs',
+ fn: showPreferences,
+ evt: 'click'
+ }, {
+ sel: '#tool_editor_homepage',
+ fn: openHomePage,
+ evt: 'click'
+ }, {
+ sel: '#tool_open',
+ fn: function fn() {
+ window.dispatchEvent(new CustomEvent('openImage'));
+ },
+ evt: 'click'
+ }, {
+ sel: '#tool_import',
+ fn: function fn() {
+ window.dispatchEvent(new CustomEvent('importImage'));
+ },
+ evt: 'click'
+ }, {
+ sel: '#tool_delete,#tool_delete_multi',
+ fn: deleteSelected,
+ evt: 'click',
+ key: ['del/backspace', true]
+ }, {
+ sel: '#tool_reorient',
+ fn: reorientPath,
+ evt: 'click'
+ }, {
+ sel: '#tool_node_link',
+ fn: linkControlPoints,
+ evt: 'click'
+ }, {
+ sel: '#tool_node_clone',
+ fn: clonePathNode,
+ evt: 'click'
+ }, {
+ sel: '#tool_node_delete',
+ fn: deletePathNode,
+ evt: 'click'
+ }, {
+ sel: '#tool_openclose_path',
+ fn: opencloseSubPath,
+ evt: 'click'
+ }, {
+ sel: '#tool_add_subpath',
+ fn: addSubPath,
+ evt: 'click'
+ }, {
+ sel: '#tool_move_top',
+ fn: moveToTopSelected,
+ evt: 'click',
+ key: 'ctrl+shift+]'
+ }, {
+ sel: '#tool_move_bottom',
+ fn: moveToBottomSelected,
+ evt: 'click',
+ key: 'ctrl+shift+['
+ }, {
+ sel: '#tool_topath',
+ fn: convertToPath,
+ evt: 'click'
+ }, {
+ sel: '#tool_make_link,#tool_make_link_multi',
+ fn: makeHyperlink,
+ evt: 'click'
+ }, {
+ sel: '#tool_undo',
+ fn: clickUndo,
+ evt: 'click'
+ }, {
+ sel: '#tool_redo',
+ fn: clickRedo,
+ evt: 'click'
+ }, {
+ sel: '#tool_clone,#tool_clone_multi',
+ fn: clickClone,
+ evt: 'click',
+ key: ['D', true]
+ }, {
+ sel: '#tool_group_elements',
+ fn: clickGroup,
+ evt: 'click',
+ key: ['G', true]
+ }, {
+ sel: '#tool_ungroup',
+ fn: clickGroup,
+ evt: 'click'
+ }, {
+ sel: '#tool_unlink_use',
+ fn: clickGroup,
+ evt: 'click'
+ }, {
+ sel: '[id^=tool_align]',
+ fn: clickAlign,
+ evt: 'click'
+ }, // these two lines are required to make Opera work properly with the flyout mechanism
+ // {sel: '#tools_rect_show', fn: clickRect, evt: 'click'},
+ // {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'},
+ {
+ sel: '#tool_bold',
+ fn: clickBold,
+ evt: 'mousedown'
+ }, {
+ sel: '#tool_italic',
+ fn: clickItalic,
+ evt: 'mousedown'
+ }, {
+ sel: '#sidepanel_handle',
+ fn: toggleSidePanel,
+ key: ['X']
+ }, {
+ sel: '#copy_save_done',
+ fn: cancelOverlays,
+ evt: 'click'
+ }, // Shortcuts not associated with buttons
+ {
+ key: 'ctrl+left',
+ fn: function fn() {
+ rotateSelected(0, 1);
+ }
+ }, {
+ key: 'ctrl+right',
+ fn: function fn() {
+ rotateSelected(1, 1);
+ }
+ }, {
+ key: 'ctrl+shift+left',
+ fn: function fn() {
+ rotateSelected(0, 5);
+ }
+ }, {
+ key: 'ctrl+shift+right',
+ fn: function fn() {
+ rotateSelected(1, 5);
+ }
+ }, {
+ key: 'shift+O',
+ fn: selectPrev
+ }, {
+ key: 'shift+P',
+ fn: selectNext
+ }, {
+ key: [modKey + 'up', true],
+ fn: function fn() {
+ zoomImage(2);
+ }
+ }, {
+ key: [modKey + 'down', true],
+ fn: function fn() {
+ zoomImage(0.5);
+ }
+ }, {
+ key: [modKey + ']', true],
+ fn: function fn() {
+ moveUpDownSelected('Up');
+ }
+ }, {
+ key: [modKey + '[', true],
+ fn: function fn() {
+ moveUpDownSelected('Down');
+ }
+ }, {
+ key: ['up', true],
+ fn: function fn() {
+ moveSelected(0, -1);
+ }
+ }, {
+ key: ['down', true],
+ fn: function fn() {
+ moveSelected(0, 1);
+ }
+ }, {
+ key: ['left', true],
+ fn: function fn() {
+ moveSelected(-1, 0);
+ }
+ }, {
+ key: ['right', true],
+ fn: function fn() {
+ moveSelected(1, 0);
+ }
+ }, {
+ key: 'shift+up',
+ fn: function fn() {
+ moveSelected(0, -10);
+ }
+ }, {
+ key: 'shift+down',
+ fn: function fn() {
+ moveSelected(0, 10);
+ }
+ }, {
+ key: 'shift+left',
+ fn: function fn() {
+ moveSelected(-10, 0);
+ }
+ }, {
+ key: 'shift+right',
+ fn: function fn() {
+ moveSelected(10, 0);
+ }
+ }, {
+ key: ['alt+up', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(0, -1);
+ }
+ }, {
+ key: ['alt+down', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(0, 1);
+ }
+ }, {
+ key: ['alt+left', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(-1, 0);
+ }
+ }, {
+ key: ['alt+right', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(1, 0);
+ }
+ }, {
+ key: ['alt+shift+up', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(0, -10);
+ }
+ }, {
+ key: ['alt+shift+down', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(0, 10);
+ }
+ }, {
+ key: ['alt+shift+left', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(-10, 0);
+ }
+ }, {
+ key: ['alt+shift+right', true],
+ fn: function fn() {
+ svgCanvas.cloneSelectedElements(10, 0);
+ }
+ }, {
+ key: 'a',
+ fn: function fn() {
+ svgCanvas.selectAllInCurrentLayer();
+ }
+ }, {
+ key: modKey + 'a',
+ fn: function fn() {
+ svgCanvas.selectAllInCurrentLayer();
+ }
+ }, // Standard shortcuts
+ {
+ key: modKey + 'z',
+ fn: clickUndo
+ }, {
+ key: modKey + 'shift+z',
+ fn: clickRedo
+ }, {
+ key: modKey + 'y',
+ fn: clickRedo
+ }, {
+ key: modKey + 'x',
+ fn: cutSelected
+ }, {
+ key: modKey + 'c',
+ fn: copySelected
+ }, {
+ key: modKey + 'v',
+ fn: pasteInCenter
+ }]; // Tooltips not directly associated with a single function
+
+ var keyAssocs = {
+ '4/Shift+4': '#tools_rect_show',
+ '5/Shift+5': '#tools_ellipse_show'
+ };
+ return {
+ /** @lends module:SVGEditor~Actions */
+
+ /**
+ * @returns {void}
+ */
+ setAll: function setAll() {
+ var flyouts = {};
+ var keyHandler = {}; // will contain the action for each pressed key
+
+ toolButtons.forEach(function (opts) {
+ // Bind function to button
+ var btn;
+
+ if (opts.sel) {
+ btn = $q$1(opts.sel);
+
+ if (btn === null) {
+ return true;
+ } // Skip if markup does not exist
+
+
+ if (opts.evt) {
+ // `touch.js` changes `touchstart` to `mousedown`,
+ // so we must map tool button click events as well
+ if (isTouch() && opts.evt === 'click') {
+ opts.evt = 'mousedown';
+ }
+
+ btn.addEventListener(opts.evt, opts.fn);
+ } // Add to parent flyout menu, if able to be displayed
+
+
+ if (opts.parent && $$c(opts.parent + '_show').length) {
+ var fH = $$c(opts.parent);
+
+ if (!fH.length) {
+ fH = makeFlyoutHolder(opts.parent.substr(1));
+ }
+
+ if (opts.prepend) {
+ btn.style.margin = 'initial';
+ }
+
+ fH[opts.prepend ? 'prepend' : 'append'](btn);
+
+ if (!Array.isArray(flyouts[opts.parent])) {
+ flyouts[opts.parent] = [];
+ }
+
+ flyouts[opts.parent].push(opts);
+ }
+ } // Bind function to shortcut key
+
+
+ if (opts.key) {
+ // Set shortcut based on options
+ var keyval = opts.key;
+ var pd = false;
+
+ if (Array.isArray(opts.key)) {
+ keyval = opts.key[0];
+
+ if (opts.key.length > 1) {
+ pd = opts.key[1];
+ }
+ }
+
+ keyval = String(keyval);
+ var fn = opts.fn;
+ keyval.split('/').forEach(function (key) {
+ keyHandler[key] = {
+ fn: fn,
+ pd: pd
+ };
+ }); // Put shortcut in title
+
+ if (opts.sel && !opts.hidekey && btn.title) {
+ var newTitle = "".concat(btn.title.split('[')[0], " (").concat(keyval, ")");
+ keyAssocs[keyval] = opts.sel; // Disregard for menu items
+
+ if (btn.closest('#main_menu') === null) {
+ btn.title = newTitle;
+ }
+ }
+ }
+
+ return true;
+ }); // register the keydown event
+
+ document.addEventListener('keydown', function (e) {
+ // only track keyboard shortcuts for the body containing the SVG-Editor
+ if (e.target.nodeName !== 'BODY') return; // normalize key
+
+ var key = "".concat(e.metaKey ? 'meta+' : '').concat(e.ctrlKey ? 'ctrl+' : '').concat(e.key.toLowerCase()); // return if no shortcut defined for this key
+
+ if (!keyHandler[key]) return; // launch associated handler and preventDefault if necessary
+
+ keyHandler[key].fn();
+
+ if (keyHandler[key].pd) {
+ e.preventDefault();
+ }
+ }); // Setup flyouts
+
+ setupFlyouts(flyouts); // Misc additional actions
+ // Make 'return' keypress trigger the change event
+
+ $$c('.attr_changer, #image_url').bind('keydown', 'return', function (evt) {
+ $$c(this).change();
+ evt.preventDefault();
+ });
+ $$c(window).bind('keydown', 'tab', function (e) {
+ if (uiContext === 'canvas') {
+ e.preventDefault();
+ selectNext();
+ }
+ }).bind('keydown', 'shift+tab', function (e) {
+ if (uiContext === 'canvas') {
+ e.preventDefault();
+ selectPrev();
+ }
+ });
+ $$c('#tool_zoom').dblclick(dblclickZoom);
+ },
+
+ /**
+ * @returns {void}
+ */
+ setTitles: function setTitles() {
+ $$c.each(keyAssocs, function (keyval, sel) {
+ var menu = $$c(sel).parents('#main_menu').length;
+ $$c(sel).each(function () {
+ var t;
+
+ if (menu) {
+ t = $$c(this).text().split(' [')[0];
+ } else {
+ t = this.title.split(' [')[0];
+ }
+
+ var keyStr = ''; // Shift+Up
+
+ $$c.each(keyval.split('/'), function (i, key) {
+ var modBits = key.split('+');
+ var mod = '';
+
+ if (modBits.length > 1) {
+ mod = modBits[0] + '+';
+ key = modBits[1];
+ }
+
+ keyStr += (i ? '/' : '') + mod + (uiStrings$1['key_' + key] || key);
+ });
+
+ if (menu) {
+ this.lastChild.textContent = t + ' [' + keyStr + ']';
+ } else {
+ this.title = t + ' [' + keyStr + ']';
+ }
+ });
+ });
+ },
+
+ /**
+ * @param {string} sel Selector to match
+ * @returns {module:SVGEditor.ToolButton}
+ */
+ getButtonData: function getButtonData(sel) {
+ return Object.values(toolButtons).find(function (btn) {
+ return btn.sel === sel;
+ });
+ }
+ };
+ }(); // Select given tool
+
+
+ editor.ready(function () {
+ var tool;
+ var itool = curConfig.initTool,
+ container = $$c('#tools_left, #svg_editor .tools_flyout'),
+ preTool = container.find('#tool_' + itool),
+ regTool = container.find('#' + itool);
+
+ if (preTool.length) {
+ tool = preTool;
+ } else if (regTool.length) {
+ tool = regTool;
+ } else {
+ tool = $$c('#tool_select');
+ }
+
+ tool.click().mouseup();
+
+ if (curConfig.wireframe) {
+ $$c('#tool_wireframe').click();
+ }
+
+ if (curConfig.showlayers) {
+ toggleSidePanel();
+ }
+
+ $$c('#rulers').toggle(Boolean(curConfig.showRulers));
+
+ if (curConfig.showRulers) {
+ $$c('#show_rulers')[0].checked = true;
+ }
+
+ if (curConfig.baseUnit) {
+ $$c('#base_unit').val(curConfig.baseUnit);
+ }
+
+ if (curConfig.gridSnapping) {
+ $$c('#grid_snapping_on')[0].checked = true;
+ }
+
+ if (curConfig.snappingStep) {
+ $$c('#grid_snapping_step').val(curConfig.snappingStep);
+ }
+
+ if (curConfig.gridColor) {
+ $$c('#grid_color').val(curConfig.gridColor);
+ }
+ }); // init SpinButtons
+
+ $$c('#rect_rx').SpinButton({
+ min: 0,
+ max: 1000,
+ stateObj: stateObj,
+ callback: changeRectRadius
+ });
+ $$c('#stroke_width').SpinButton({
+ min: 0,
+ max: 99,
+ smallStep: 0.1,
+ stateObj: stateObj,
+ callback: changeStrokeWidth
+ });
+ $$c('#angle').SpinButton({
+ min: -180,
+ max: 180,
+ step: 5,
+ stateObj: stateObj,
+ callback: changeRotationAngle
+ });
+ $$c('#font_size').SpinButton({
+ min: 0.001,
+ stepfunc: stepFontSize,
+ stateObj: stateObj,
+ callback: changeFontSize
+ });
+ $$c('#group_opacity').SpinButton({
+ min: 0,
+ max: 100,
+ step: 5,
+ stateObj: stateObj,
+ callback: changeOpacity
+ });
+ $$c('#blur').SpinButton({
+ min: 0,
+ max: 10,
+ step: 0.1,
+ stateObj: stateObj,
+ callback: changeBlur
+ });
+ $$c('#zoom').SpinButton({
+ min: 0.001,
+ max: 10000,
+ step: 50,
+ stepfunc: stepZoom,
+ stateObj: stateObj,
+ callback: changeZoom // Set default zoom
+
+ }).val(svgCanvas.getZoom() * 100);
+ $$c('#workarea').contextMenu({
+ menu: 'cmenu_canvas',
+ inSpeed: 0
+ }, function (action, el, pos) {
+ switch (action) {
+ case 'delete':
+ deleteSelected();
+ break;
+
+ case 'cut':
+ cutSelected();
+ break;
+
+ case 'copy':
+ copySelected();
+ break;
+
+ case 'paste':
+ svgCanvas.pasteElements();
+ break;
+
+ case 'paste_in_place':
+ svgCanvas.pasteElements('in_place');
+ break;
+
+ case 'group':
+ case 'group_elements':
+ svgCanvas.groupSelectedElements();
+ break;
+
+ case 'ungroup':
+ svgCanvas.ungroupSelectedElement();
+ break;
+
+ case 'move_front':
+ moveToTopSelected();
+ break;
+
+ case 'move_up':
+ moveUpDownSelected('Up');
+ break;
+
+ case 'move_down':
+ moveUpDownSelected('Down');
+ break;
+
+ case 'move_back':
+ moveToBottomSelected();
+ break;
+
+ default:
+ if (hasCustomHandler(action)) {
+ getCustomHandler(action).call();
+ }
+
+ break;
+ }
+ });
+ /**
+ * Implements {@see module:jQueryContextMenu.jQueryContextMenuListener}.
+ * @param {"dupe"|"delete"|"merge_down"|"merge_all"} action
+ * @param {external:jQuery} el
+ * @param {{x: Float, y: Float, docX: Float, docY: Float}} pos
+ * @returns {void}
+ */
+
+ var lmenuFunc = function lmenuFunc(action, el, pos) {
+ switch (action) {
+ case 'dupe':
+ /* await */
+ cloneLayer();
+ break;
+
+ case 'delete':
+ deleteLayer();
+ break;
+
+ case 'merge_down':
+ mergeLayer();
+ break;
+
+ case 'merge_all':
+ svgCanvas.mergeAllLayers();
+ updateContextPanel();
+ populateLayers();
+ break;
+ }
+ };
+
+ $$c('#layerlist').contextMenu({
+ menu: 'cmenu_layers',
+ inSpeed: 0
+ }, lmenuFunc);
+ $$c('#layer_moreopts').contextMenu({
+ menu: 'cmenu_layers',
+ inSpeed: 0,
+ allowLeft: true
+ }, lmenuFunc);
+ $$c('.contextMenu li').mousedown(function (ev) {
+ ev.preventDefault();
+ });
+ $$c('#cmenu_canvas li').disableContextMenu();
+ canvMenu.enableContextMenuItems('#delete,#cut,#copy');
+ /**
+ * @returns {void}
+ */
+
+ function enableOrDisableClipboard() {
+ var svgeditClipboard;
+
+ try {
+ svgeditClipboard = localStorage.getItem('svgedit_clipboard');
+ } catch (err) {}
+
+ canvMenu[(svgeditClipboard ? 'en' : 'dis') + 'ableContextMenuItems']('#paste,#paste_in_place');
+ }
+
+ enableOrDisableClipboard();
+ window.addEventListener('storage', function (e) {
+ if (e.key !== 'svgedit_clipboard') {
+ return;
+ }
+
+ enableOrDisableClipboard();
+ });
+ window.addEventListener('beforeunload', function (e) {
+ // Suppress warning if page is empty
+ if (undoMgr.getUndoStackSize() === 0) {
+ editor.showSaveWarning = false;
+ } // showSaveWarning is set to 'false' when the page is saved.
+
+
+ if (!curConfig.no_save_warning && editor.showSaveWarning) {
+ // Browser already asks question about closing the page
+ e.returnValue = uiStrings$1.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
+
+ return uiStrings$1.notification.unsavedChanges;
+ }
+
+ return true;
+ });
+ /**
+ * Expose the `uiStrings`.
+ * @function module:SVGEditor.canvas.getUIStrings
+ * @returns {module:SVGEditor.uiStrings}
+ */
+
+ editor.canvas.getUIStrings = function () {
+ return uiStrings$1;
+ };
+ /**
+ * @function module:SVGEditor.openPrep
+ * @returns {boolean|Promise} Resolves to boolean indicating `true` if there were no changes
+ * and `false` after the user confirms.
+ */
+
+
+ editor.openPrep = function () {
+ $$c('#main_menu').hide();
+
+ if (undoMgr.getUndoStackSize() === 0) {
+ return true;
+ }
+
+ return $$c.confirm(uiStrings$1.notification.QwantToOpen);
+ };
+ /**
+ *
+ * @param {Event} e
+ * @returns {void}
+ */
+
+
+ function onDragEnter(e) {
+ e.stopPropagation();
+ e.preventDefault(); // and indicator should be displayed here, such as "drop files here"
+ }
+ /**
+ *
+ * @param {Event} e
+ * @returns {void}
+ */
+
+
+ function onDragOver(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ /**
+ *
+ * @param {Event} e
+ * @returns {void}
+ */
+
+
+ function onDragLeave(e) {
+ e.stopPropagation();
+ e.preventDefault(); // hypothetical indicator should be removed here
+ } // Use HTML5 File API: http://www.w3.org/TR/FileAPI/
+ // if browser has HTML5 File API support, then we will show the open menu item
+ // and provide a file input to click. When that change event fires, it will
+ // get the text contents of the file and send it to the canvas
+
+
+ if (window.FileReader) {
+ /**
+ * @param {Event} e
+ * @returns {void}
+ */
+ var importImage = function importImage(e) {
+ $$c.process_cancel(uiStrings$1.notification.loadingImage);
+ e.stopPropagation();
+ e.preventDefault();
+ $$c('#workarea').removeAttr('style');
+ $$c('#main_menu').hide();
+ var file = e.type === 'drop' ? e.dataTransfer.files[0] : this.files[0];
+
+ if (!file) {
+ $$c('#dialog_box').hide();
+ return;
+ }
+ /* if (file.type === 'application/pdf') { // Todo: Handle PDF imports
+ }
+ else */
+
+
+ if (!file.type.includes('image')) {
+ return;
+ } // Detected an image
+ // svg handling
+
+
+ var reader;
+
+ if (file.type.includes('svg')) {
+ reader = new FileReader();
+
+ reader.onloadend = function (ev) {
+ var newElement = svgCanvas.importSvgString(ev.target.result, true);
+ svgCanvas.ungroupSelectedElement();
+ svgCanvas.ungroupSelectedElement();
+ svgCanvas.groupSelectedElements();
+ svgCanvas.alignSelectedElements('m', 'page');
+ svgCanvas.alignSelectedElements('c', 'page'); // highlight imported element, otherwise we get strange empty selectbox
+
+ svgCanvas.selectOnly([newElement]);
+ $$c('#dialog_box').hide();
+ };
+
+ reader.readAsText(file);
+ } else {
+ // bitmap handling
+ reader = new FileReader();
+
+ reader.onloadend = function (_ref22) {
+ var result = _ref22.target.result;
+
+ /**
+ * Insert the new image until we know its dimensions.
+ * @param {Float} width
+ * @param {Float} height
+ * @returns {void}
+ */
+ var insertNewImage = function insertNewImage(width, height) {
+ var newImage = svgCanvas.addSVGElementFromJson({
+ element: 'image',
+ attr: {
+ x: 0,
+ y: 0,
+ width: width,
+ height: height,
+ id: svgCanvas.getNextId(),
+ style: 'pointer-events:inherit'
+ }
+ });
+ svgCanvas.setHref(newImage, result);
+ svgCanvas.selectOnly([newImage]);
+ svgCanvas.alignSelectedElements('m', 'page');
+ svgCanvas.alignSelectedElements('c', 'page');
+ updateContextPanel();
+ $$c('#dialog_box').hide();
+ }; // create dummy img so we know the default dimensions
+
+
+ var imgWidth = 100;
+ var imgHeight = 100;
+ var img = new Image();
+ img.style.opacity = 0;
+ img.addEventListener('load', function () {
+ imgWidth = img.offsetWidth || img.naturalWidth || img.width;
+ imgHeight = img.offsetHeight || img.naturalHeight || img.height;
+ insertNewImage(imgWidth, imgHeight);
+ });
+ img.src = result;
+ };
+
+ reader.readAsDataURL(file);
+ }
+ };
+
+ workarea[0].addEventListener('dragenter', onDragEnter);
+ workarea[0].addEventListener('dragover', onDragOver);
+ workarea[0].addEventListener('dragleave', onDragLeave);
+ workarea[0].addEventListener('drop', importImage);
+ var open = $$c('').change( /*#__PURE__*/function () {
+ var _ref23 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee16(e) {
+ var ok, reader;
+ return regeneratorRuntime.wrap(function _callee16$(_context16) {
+ while (1) {
+ switch (_context16.prev = _context16.next) {
+ case 0:
+ _context16.next = 2;
+ return editor.openPrep();
+
+ case 2:
+ ok = _context16.sent;
+
+ if (ok) {
+ _context16.next = 5;
+ break;
+ }
+
+ return _context16.abrupt("return");
+
+ case 5:
+ svgCanvas.clear();
+
+ if (this.files.length === 1) {
+ $$c.process_cancel(uiStrings$1.notification.loadingImage);
+ reader = new FileReader();
+
+ reader.onloadend = /*#__PURE__*/function () {
+ var _ref25 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee15(_ref24) {
+ var target;
+ return regeneratorRuntime.wrap(function _callee15$(_context15) {
+ while (1) {
+ switch (_context15.prev = _context15.next) {
+ case 0:
+ target = _ref24.target;
+ _context15.next = 3;
+ return loadSvgString(target.result);
+
+ case 3:
+ updateCanvas();
+
+ case 4:
+ case "end":
+ return _context15.stop();
+ }
+ }
+ }, _callee15);
+ }));
+
+ return function (_x6) {
+ return _ref25.apply(this, arguments);
+ };
+ }();
+
+ reader.readAsText(this.files[0]);
+ }
+
+ case 7:
+ case "end":
+ return _context16.stop();
+ }
+ }
+ }, _callee16, this);
+ }));
+
+ return function (_x5) {
+ return _ref23.apply(this, arguments);
+ };
+ }());
+ $$c('#tool_open').show();
+ $$c(window).on('openImage', function () {
+ return open.click();
+ });
+ var imgImport = $$c('').change(importImage);
+ $$c('#tool_import').show();
+ $$c(window).on('importImage', function () {
+ return imgImport.click();
+ });
+ }
+
+ updateCanvas(true); // const revnums = 'svg-editor.js ($Rev$) ';
+ // revnums += svgCanvas.getVersion();
+ // $('#copyright')[0].setAttribute('title', revnums);
+
+ var loadedExtensionNames = [];
+ /**
+ * @function module:SVGEditor.setLang
+ * @param {string} lang The language code
+ * @param {module:locale.LocaleStrings} allStrings See {@tutorial LocaleDocs}
+ * @fires module:svgcanvas.SvgCanvas#event:ext_langReady
+ * @fires module:svgcanvas.SvgCanvas#event:ext_langChanged
+ * @returns {Promise} A Promise which resolves to `undefined`
+ */
+
+ var setLang = editor.setLang = /*#__PURE__*/function () {
+ var _ref26 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee17(lang, allStrings) {
+ var oldLayerName, renameLayer, elems;
+ return regeneratorRuntime.wrap(function _callee17$(_context17) {
+ while (1) {
+ switch (_context17.prev = _context17.next) {
+ case 0:
+ editor.langChanged = true;
+ editor.pref('lang', lang);
+ $$c('#lang_select').val(lang);
+
+ if (allStrings) {
+ _context17.next = 5;
+ break;
+ }
+
+ return _context17.abrupt("return");
+
+ case 5:
+ // Todo: Remove `allStrings.lang` property in locale in
+ // favor of just `lang`?
+ document.documentElement.lang = allStrings.lang; // lang;
+ // Todo: Add proper RTL Support!
+ // Todo: Use RTL detection instead and take out of locales?
+ // document.documentElement.dir = allStrings.dir;
+
+ $$c.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused
+ // $.extend will only replace the given strings
+
+ oldLayerName = $$c('#layerlist tr.layersel td.layername').text();
+ renameLayer = oldLayerName === uiStrings$1.common.layer + ' 1';
+ svgCanvas.setUiStrings(allStrings);
+ Actions.setTitles();
+
+ if (renameLayer) {
+ svgCanvas.renameCurrentLayer(uiStrings$1.common.layer + ' 1');
+ populateLayers();
+ } // In case extensions loaded before the locale, now we execute a callback on them
+
+
+ if (!extsPreLang.length) {
+ _context17.next = 18;
+ break;
+ }
+
+ _context17.next = 15;
+ return Promise.all(extsPreLang.map(function (ext) {
+ loadedExtensionNames.push(ext.name);
+ return ext.langReady({
+ lang: lang,
+ uiStrings: uiStrings$1,
+ importLocale: getImportLocale({
+ defaultLang: lang,
+ defaultName: ext.name
+ })
+ });
+ }));
+
+ case 15:
+ extsPreLang.length = 0;
+ _context17.next = 19;
+ break;
+
+ case 18:
+ loadedExtensionNames.forEach(function (loadedExtensionName) {
+ svgCanvas.runExtension(loadedExtensionName, 'langReady',
+ /** @type {module:svgcanvas.SvgCanvas#event:ext_langReady} */
+ {
+ lang: lang,
+ uiStrings: uiStrings$1,
+ importLocale: getImportLocale({
+ defaultLang: lang,
+ defaultName: loadedExtensionName
+ })
+ });
+ });
+
+ case 19:
+ svgCanvas.runExtensions('langChanged',
+ /** @type {module:svgcanvas.SvgCanvas#event:ext_langChanged} */
+ lang); // Update flyout tooltips
+
+ setFlyoutTitles(); // Copy title for certain tool elements
+
+ elems = {
+ '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block',
+ '#fill_color': '#tool_fill label, #tool_fill .color_block',
+ '#linejoin_miter': '#cur_linejoin',
+ '#linecap_butt': '#cur_linecap'
+ };
+ $$c.each(elems, function (source, dest) {
+ $$c(dest).attr('title', $$c(source)[0].title);
+ }); // Copy alignment titles
+
+ $$c('#multiselected_panel div[id^=tool_align]').each(function () {
+ $$c('#tool_pos' + this.id.substr(10))[0].title = this.title;
+ });
+
+ case 24:
+ case "end":
+ return _context17.stop();
+ }
+ }
+ }, _callee17);
+ }));
+
+ return function (_x7, _x8) {
+ return _ref26.apply(this, arguments);
+ };
+ }();
+
+ init$7(
+ /**
+ * @implements {module:locale.LocaleEditorInit}
+ */
+ {
+ /**
+ * Gets an array of results from extensions with a `addLangData` method,
+ * returning an object with a `data` property set to its locales (to be
+ * merged with regular locales).
+ * @param {string} langParam
+ * @fires module:svgcanvas.SvgCanvas#event:ext_addLangData
+ * @todo Can we forego this in favor of `langReady` (or forego `langReady`)?
+ * @returns {module:locale.AddLangExtensionLocaleData[]}
+ */
+ addLangData: function addLangData(langParam) {
+ return svgCanvas.runExtensions('addLangData',
+ /**
+ * @function
+ * @type {module:svgcanvas.ExtensionVarBuilder}
+ * @param {string} name
+ * @returns {module:svgcanvas.SvgCanvas#event:ext_addLangData}
+ */
+ function (name) {
+ // We pass in a function as we don't know the extension name here when defining this `addLangData` method
+ return {
+ lang: langParam,
+ importLocale: getImportLocale({
+ defaultLang: langParam,
+ defaultName: name
+ })
+ };
+ }, true);
+ },
+ curConfig: curConfig
+ }); // Load extensions
+ // Bit of a hack to run extensions in local Opera/IE9
+
+ if (document.location.protocol === 'file:') {
+ setTimeout(extAndLocaleFunc, 100);
+ } else {
+ // Returns a promise (if we wanted to fire 'extensions-loaded' event,
+ // potentially useful to hide interface as some extension locales
+ // are only available after this)
+ extAndLocaleFunc();
+ }
+ };
+ /**
+ * @callback module:SVGEditor.ReadyCallback
+ * @returns {Promise|void}
+ */
+
+ /**
+ * Queues a callback to be invoked when the editor is ready (or
+ * to be invoked immediately if it is already ready--i.e.,
+ * if `runCallbacks` has been run).
+ * @function module:SVGEditor.ready
+ * @param {module:SVGEditor.ReadyCallback} cb Callback to be queued to invoke
+ * @returns {Promise} Resolves when all callbacks, including the supplied have resolved
+ */
+
+
+ editor.ready = function (cb) {
+ // eslint-disable-line promise/prefer-await-to-callbacks
+ return new Promise(function (resolve, reject) {
+ // eslint-disable-line promise/avoid-new
+ if (isReady) {
+ resolve(cb()); // eslint-disable-line node/callback-return, promise/prefer-await-to-callbacks
+
+ return;
+ }
+
+ callbacks.push([cb, resolve, reject]);
+ });
+ };
+ /**
+ * Invokes the callbacks previous set by `svgEditor.ready`
+ * @function module:SVGEditor.runCallbacks
+ * @returns {Promise} Resolves to `undefined` if all callbacks succeeded and rejects otherwise
+ */
+
+
+ editor.runCallbacks = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee20() {
+ return regeneratorRuntime.wrap(function _callee20$(_context20) {
+ while (1) {
+ switch (_context20.prev = _context20.next) {
+ case 0:
+ _context20.prev = 0;
+ _context20.next = 3;
+ return Promise.all(callbacks.map(function (_ref29) {
+ var _ref30 = _slicedToArray(_ref29, 1),
+ cb = _ref30[0];
+
+ return cb(); // eslint-disable-line promise/prefer-await-to-callbacks
+ }));
+
+ case 3:
+ _context20.next = 9;
+ break;
+
+ case 5:
+ _context20.prev = 5;
+ _context20.t0 = _context20["catch"](0);
+ callbacks.forEach(function (_ref31) {
+ var _ref32 = _slicedToArray(_ref31, 3),
+ reject = _ref32[2];
+
+ reject();
+ });
+ throw _context20.t0;
+
+ case 9:
+ callbacks.forEach(function (_ref33) {
+ var _ref34 = _slicedToArray(_ref33, 2),
+ resolve = _ref34[1];
+
+ resolve();
+ });
+ isReady = true;
+
+ case 11:
+ case "end":
+ return _context20.stop();
+ }
+ }
+ }, _callee20, null, [[0, 5]]);
+ }));
+ /**
+ * @function module:SVGEditor.loadFromString
+ * @param {string} str The SVG string to load
+ * @param {PlainObject} [opts={}]
+ * @param {boolean} [opts.noAlert=false] Option to avoid alert to user and instead get rejected promise
+ * @returns {Promise}
+ */
+
+ editor.loadFromString = function (str) {
+ var _ref35 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+ noAlert = _ref35.noAlert;
+
+ return editor.ready( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee21() {
+ return regeneratorRuntime.wrap(function _callee21$(_context21) {
+ while (1) {
+ switch (_context21.prev = _context21.next) {
+ case 0:
+ _context21.prev = 0;
+ _context21.next = 3;
+ return loadSvgString(str, {
+ noAlert: noAlert
+ });
+
+ case 3:
+ _context21.next = 9;
+ break;
+
+ case 5:
+ _context21.prev = 5;
+ _context21.t0 = _context21["catch"](0);
+
+ if (!noAlert) {
+ _context21.next = 9;
+ break;
+ }
+
+ throw _context21.t0;
+
+ case 9:
+ case "end":
+ return _context21.stop();
+ }
+ }
+ }, _callee21, null, [[0, 5]]);
+ })));
+ };
+ /**
+ * Not presently in use.
+ * @function module:SVGEditor.disableUI
+ * @param {PlainObject} featList
+ * @returns {void}
+ */
+
+
+ editor.disableUI = function (featList) {// $(function () {
+ // $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove();
+ // $('#tools_top').css('left', 5);
+ // });
+ };
+ /**
+ * @callback module:SVGEditor.URLLoadCallback
+ * @param {boolean} success
+ * @returns {void}
+ */
+
+ /**
+ * @function module:SVGEditor.loadFromURL
+ * @param {string} url URL from which to load an SVG string via Ajax
+ * @param {PlainObject} [opts={}] May contain properties: `cache`, `callback`
+ * @param {boolean} [opts.cache]
+ * @param {boolean} [opts.noAlert]
+ * @returns {Promise} Resolves to `undefined` or rejects upon bad loading of
+ * the SVG (or upon failure to parse the loaded string) when `noAlert` is
+ * enabled
+ */
+
+
+ editor.loadFromURL = function (url) {
+ var _ref37 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+ cache = _ref37.cache,
+ noAlert = _ref37.noAlert;
+
+ return editor.ready(function () {
+ return new Promise(function (resolve, reject) {
+ // eslint-disable-line promise/avoid-new
+ $$c.ajax({
+ url: url,
+ dataType: 'text',
+ cache: Boolean(cache),
+ beforeSend: function beforeSend() {
+ $$c.process_cancel(uiStrings$1.notification.loadingImage);
+ },
+ success: function success(str) {
+ resolve(loadSvgString(str, {
+ noAlert: noAlert
+ }));
+ },
+ error: function error(xhr, stat, err) {
+ if (xhr.status !== 404 && xhr.responseText) {
+ resolve(loadSvgString(xhr.responseText, {
+ noAlert: noAlert
+ }));
+ return;
+ }
+
+ if (noAlert) {
+ reject(new Error('URLLoadFail'));
+ return;
+ }
+
+ $$c.alert(uiStrings$1.notification.URLLoadFail + ': \n' + err);
+ resolve();
+ },
+ complete: function complete() {
+ $$c('#dialog_box').hide();
+ }
+ });
+ });
+ });
+ };
+ /**
+ * @function module:SVGEditor.loadFromDataURI
+ * @param {string} str The Data URI to base64-decode (if relevant) and load
+ * @param {PlainObject} [opts={}]
+ * @param {boolean} [opts.noAlert]
+ * @returns {Promise} Resolves to `undefined` and rejects if loading SVG string fails and `noAlert` is enabled
+ */
+
+
+ editor.loadFromDataURI = function (str) {
+ var _ref38 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+ noAlert = _ref38.noAlert;
+
+ return editor.ready(function () {
+ var base64 = false;
+ var pre = str.match(/^data:image\/svg\+xml;base64,/);
+
+ if (pre) {
+ base64 = true;
+ } else {
+ pre = str.match(/^data:image\/svg\+xml(?:;|;utf8)?,/);
+ }
+
+ if (pre) {
+ pre = pre[0];
+ }
+
+ var src = str.slice(pre.length);
+ return loadSvgString(base64 ? decode64(src) : decodeURIComponent(src), {
+ noAlert: noAlert
+ });
+ });
+ };
+ /**
+ * @function module:SVGEditor.addExtension
+ * @param {string} name Used internally; no need for i18n.
+ * @param {module:svgcanvas.ExtensionInitCallback} init Config to be invoked on this module
+ * @param {module:svgcanvas.ExtensionInitArgs} initArgs
+ * @throws {Error} If called too early
+ * @returns {Promise} Resolves to `undefined`
+ */
+
+
+ editor.addExtension = function (name, init, initArgs) {
+ // Note that we don't want this on editor.ready since some extensions
+ // may want to run before then (like server_opensave).
+ // $(function () {
+ if (!svgCanvas) {
+ throw new Error('Extension added too early');
+ }
+
+ return svgCanvas.addExtension.call(this, name, init, initArgs); // });
+ }; // Defer injection to wait out initial menu processing. This probably goes
+ // away once all context menu behavior is brought to context menu.
+
+
+ editor.ready(function () {
+ injectExtendedContextMenuItemsIntoDom();
+ });
+ var extensionsAdded = false;
+ var messageQueue = [];
+ /**
+ * @param {PlainObject} info
+ * @param {any} info.data
+ * @param {string} info.origin
+ * @fires module:svgcanvas.SvgCanvas#event:message
+ * @returns {void}
+ */
+
+ var messageListener = function messageListener(_ref39) {
+ var data = _ref39.data,
+ origin = _ref39.origin;
+ // eslint-disable-line no-shadow
+ // console.log('data, origin, extensionsAdded', data, origin, extensionsAdded);
+ var messageObj = {
+ data: data,
+ origin: origin
+ };
+
+ if (!extensionsAdded) {
+ messageQueue.push(messageObj);
+ } else {
+ // Extensions can handle messages at this stage with their own
+ // canvas `message` listeners
+ svgCanvas.call('message', messageObj);
+ }
+ };
+
+ window.addEventListener('message', messageListener); // Run init once DOM is loaded
+ // jQuery(editor.init);
+
+ _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee22() {
+ return regeneratorRuntime.wrap(function _callee22$(_context22) {
+ while (1) {
+ switch (_context22.prev = _context22.next) {
+ case 0:
+ _context22.prev = 0;
+ _context22.next = 3;
+ return Promise.resolve();
+
+ case 3:
+ editor.init();
+ _context22.next = 9;
+ break;
+
+ case 6:
+ _context22.prev = 6;
+ _context22.t0 = _context22["catch"](0);
+ console.error(_context22.t0); // eslint-disable-line no-console
+
+ case 9:
+ case "end":
+ return _context22.stop();
+ }
+ }
+ }, _callee22, null, [[0, 6]]);
+ }))();
+
+ // TO BUILD AN IIFE VERSION OF THIS FILE (AS CAN WORK ON OLDER BROWSERS),
+
+ editor.setConfig({
+ /* To override the ability for URLs to set URL-based SVG content,
+ uncomment the following: */
+ // preventURLContentLoading: true,
+
+ /* To override the ability for URLs to set other configuration (including
+ extension config), uncomment the following: */
+ // preventAllURLConfig: true,
+
+ /* To override the ability for URLs to set their own extensions, uncomment the
+ following (note that if `setConfig()` is used in extension code, it will still
+ be additive to extensions, however): */
+ // lockExtensions: true,
+ });
+ editor.setConfig({
+ /*
+ Provide default values here which differ from that of the editor but
+ which the URL can override
+ */
+ }, {
+ allowInitialUserOverride: true
+ }); // EXTENSION CONFIG
+
+ editor.setConfig({
+ extensions: [// 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js',
+ // 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js',
+ // 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js',
+ // 'ext-storage.js'
+ ],
+ // noDefaultExtensions can only be meaningfully used in
+ // `svgedit-config-es.js` or in the URL
+ noDefaultExtensions: false
+ }); // OTHER CONFIG
+
+ editor.setConfig({// canvasName: 'default',
+ // canvas_expansion: 3,
+ // initFill: {
+ // color: 'FF0000', // solid red
+ // opacity: 1
+ // },
+ // initStroke: {
+ // width: 5,
+ // color: '000000', // solid black
+ // opacity: 1
+ // },
+ // initOpacity: 1,
+ // colorPickerCSS: null,
+ // initTool: 'select',
+ // exportWindowType: 'new', // 'same'
+ // wireframe: false,
+ // showlayers: false,
+ // no_save_warning: false,
+ // PATH CONFIGURATION
+ // imgPath: 'images/',
+ // langPath: 'locale/',
+ // extPath: 'extensions/',
+ // jGraduatePath: 'jgraduate/images/',
+
+ /*
+ Uncomment the following to allow at least same domain (embedded) access,
+ including `file:///` access.
+ Setting as `['*']` would allow any domain to access but would be unsafe to
+ data privacy and integrity.
+ */
+ // May be 'null' (as a string) when used as a `file:///` URL
+ // allowedOrigins: [location.origin || 'null'],
+ // DOCUMENT PROPERTIES
+ // dimensions: [640, 480],
+ // EDITOR OPTIONS
+ // gridSnapping: false,
+ // gridColor: '#000',
+ // baseUnit: 'px',
+ // snappingStep: 10,
+ // showRulers: true,
+ // EXTENSION-RELATED (GRID)
+ // showGrid: false, // Set by ext-grid.js
+ // EXTENSION-RELATED (STORAGE)
+ // Some interaction with `ext-storage.js`; prevent even the loading of
+ // previously saved local storage
+ // noStorageOnLoad: false,
+ // Some interaction with `ext-storage.js`; strongly discouraged from
+ // modification as it bypasses user privacy by preventing them from
+ // choosing whether to keep local storage or not
+ // forceStorage: false,
+ // Used by `ext-storage.js`; empty any prior storage if the user
+ // declines to store
+ // emptyStorageOnDecline: true,
+ }); // PREF CHANGES
+
+ /*
+ setConfig() can also be used to set preferences in addition to
+ configuration (see defaultPrefs in svg-editor.js for a list of
+ possible settings), but at least if you are using ext-storage.js
+ to store preferences, it will probably be better to let your
+ users control these.
+ As with configuration, one may use allowInitialUserOverride, but
+ in the case of preferences, any previously stored preferences
+ will also thereby be enabled to override this setting (and at a
+ higher priority than any URL preference setting overrides).
+ Failing to use allowInitialUserOverride will ensure preferences
+ are hard-coded here regardless of URL or prior user storage setting.
+ */
+
+ editor.setConfig({// Set dynamically within locale.js if not previously set
+ // lang: '',
+ // Will default to 's' if the window height is smaller than the minimum
+ // height and 'm' otherwise
+ // iconsize: '',
+
+ /**
+ * When showing the preferences dialog, svg-editor.js currently relies
+ * on `curPrefs` instead of `svgEditor.pref`, so allowing an override for
+ * `bkgd_color` means that this value won't have priority over block
+ * auto-detection as far as determining which color shows initially
+ * in the preferences dialog (though it can be changed and saved).
+ */
+ // bkgd_color: '#FFF',
+ // bkgd_url: '',
+ // img_save: 'embed',
+ // Only shows in UI as far as alert notices
+ // save_notice_done: false,
+ // export_notice_done: false
+ });
+ editor.setConfig({// Indicate pref settings here if you wish to allow user storage or URL
+ // settings to be able to override your default preferences (unless
+ // other config options have already explicitly prevented one or the
+ // other)
+ }, {
+ allowInitialUserOverride: true
+ });
+
+}());
diff --git a/dist/editor/index-umd.html b/dist/editor/index-umd.html
new file mode 100644
index 00000000..890419cf
--- /dev/null
+++ b/dist/editor/index-umd.html
@@ -0,0 +1,783 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SVG-edit
+
+
+
+
+
+
+
+
+
+
Layers
+
+
+
Move elements to:
+
+
+
L a y e r s
+
+
+
+
+
+
+
+ -
+
+ New Image (N)
+
+ -
+
+ Open SVG
+
+ -
+
+ Import Image
+
+ -
+
+ Save Image (S)
+
+ -
+
+ Export
+
+ -
+
+ Document Properties (D)
+
+ -
+
+ Editor Preferences
+
+ -
+
+ SVG-Edit Home Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Copy the contents of this box into a text editor,
+ then save the file with a .svg extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/editor/index-umd.js b/dist/editor/index-umd.js
new file mode 100644
index 00000000..6a850263
--- /dev/null
+++ b/dist/editor/index-umd.js
@@ -0,0 +1,36386 @@
+(function (factory) {
+ typeof define === 'function' && define.amd ? define(factory) :
+ factory();
+}((function () { 'use strict';
+
+ function _typeof(obj) {
+ "@babel/helpers - typeof";
+
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+ _typeof = function (obj) {
+ return typeof obj;
+ };
+ } else {
+ _typeof = function (obj) {
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+ };
+ }
+
+ return _typeof(obj);
+ }
+
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
+ try {
+ var info = gen[key](arg);
+ var value = info.value;
+ } catch (error) {
+ reject(error);
+ return;
+ }
+
+ if (info.done) {
+ resolve(value);
+ } else {
+ Promise.resolve(value).then(_next, _throw);
+ }
+ }
+
+ function _asyncToGenerator(fn) {
+ return function () {
+ var self = this,
+ args = arguments;
+ return new Promise(function (resolve, reject) {
+ var gen = fn.apply(self, args);
+
+ function _next(value) {
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
+ }
+
+ function _throw(err) {
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
+ }
+
+ _next(undefined);
+ });
+ };
+ }
+
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ }
+
+ function _defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) _defineProperties(Constructor, staticProps);
+ return Constructor;
+ }
+
+ function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value: value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+
+ return obj;
+ }
+
+ function ownKeys(object, enumerableOnly) {
+ var keys = Object.keys(object);
+
+ if (Object.getOwnPropertySymbols) {
+ var symbols = Object.getOwnPropertySymbols(object);
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+ });
+ keys.push.apply(keys, symbols);
+ }
+
+ return keys;
+ }
+
+ function _objectSpread2(target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i] != null ? arguments[i] : {};
+
+ if (i % 2) {
+ ownKeys(Object(source), true).forEach(function (key) {
+ _defineProperty(target, key, source[key]);
+ });
+ } else if (Object.getOwnPropertyDescriptors) {
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
+ } else {
+ ownKeys(Object(source)).forEach(function (key) {
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
+ });
+ }
+ }
+
+ return target;
+ }
+
+ function _inherits(subClass, superClass) {
+ if (typeof superClass !== "function" && superClass !== null) {
+ throw new TypeError("Super expression must either be null or a function");
+ }
+
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ writable: true,
+ configurable: true
+ }
+ });
+ if (superClass) _setPrototypeOf(subClass, superClass);
+ }
+
+ function _getPrototypeOf(o) {
+ _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+ return o.__proto__ || Object.getPrototypeOf(o);
+ };
+ return _getPrototypeOf(o);
+ }
+
+ function _setPrototypeOf(o, p) {
+ _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+ o.__proto__ = p;
+ return o;
+ };
+
+ return _setPrototypeOf(o, p);
+ }
+
+ function _isNativeReflectConstruct() {
+ if (typeof Reflect === "undefined" || !Reflect.construct) return false;
+ if (Reflect.construct.sham) return false;
+ if (typeof Proxy === "function") return true;
+
+ try {
+ Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ function _assertThisInitialized(self) {
+ if (self === void 0) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }
+
+ return self;
+ }
+
+ function _possibleConstructorReturn(self, call) {
+ if (call && (typeof call === "object" || typeof call === "function")) {
+ return call;
+ }
+
+ return _assertThisInitialized(self);
+ }
+
+ function _createSuper(Derived) {
+ var hasNativeReflectConstruct = _isNativeReflectConstruct();
+
+ return function _createSuperInternal() {
+ var Super = _getPrototypeOf(Derived),
+ result;
+
+ if (hasNativeReflectConstruct) {
+ var NewTarget = _getPrototypeOf(this).constructor;
+
+ result = Reflect.construct(Super, arguments, NewTarget);
+ } else {
+ result = Super.apply(this, arguments);
+ }
+
+ return _possibleConstructorReturn(this, result);
+ };
+ }
+
+ function _superPropBase(object, property) {
+ while (!Object.prototype.hasOwnProperty.call(object, property)) {
+ object = _getPrototypeOf(object);
+ if (object === null) break;
+ }
+
+ return object;
+ }
+
+ function _get(target, property, receiver) {
+ if (typeof Reflect !== "undefined" && Reflect.get) {
+ _get = Reflect.get;
+ } else {
+ _get = function _get(target, property, receiver) {
+ var base = _superPropBase(target, property);
+
+ if (!base) return;
+ var desc = Object.getOwnPropertyDescriptor(base, property);
+
+ if (desc.get) {
+ return desc.get.call(receiver);
+ }
+
+ return desc.value;
+ };
+ }
+
+ return _get(target, property, receiver || target);
+ }
+
+ function _slicedToArray(arr, i) {
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
+ }
+
+ function _toConsumableArray(arr) {
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
+ }
+
+ function _arrayWithoutHoles(arr) {
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
+ }
+
+ function _arrayWithHoles(arr) {
+ if (Array.isArray(arr)) return arr;
+ }
+
+ function _iterableToArray(iter) {
+ if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
+ }
+
+ function _iterableToArrayLimit(arr, i) {
+ if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
+ var _arr = [];
+ var _n = true;
+ var _d = false;
+ var _e = undefined;
+
+ try {
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
+ _arr.push(_s.value);
+
+ if (i && _arr.length === i) break;
+ }
+ } catch (err) {
+ _d = true;
+ _e = err;
+ } finally {
+ try {
+ if (!_n && _i["return"] != null) _i["return"]();
+ } finally {
+ if (_d) throw _e;
+ }
+ }
+
+ return _arr;
+ }
+
+ function _unsupportedIterableToArray(o, minLen) {
+ if (!o) return;
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
+ var n = Object.prototype.toString.call(o).slice(8, -1);
+ if (n === "Object" && o.constructor) n = o.constructor.name;
+ if (n === "Map" || n === "Set") return Array.from(o);
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
+ }
+
+ function _arrayLikeToArray(arr, len) {
+ if (len == null || len > arr.length) len = arr.length;
+
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
+
+ return arr2;
+ }
+
+ function _nonIterableSpread() {
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+ }
+
+ function _nonIterableRest() {
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+ }
+
+ function _createForOfIteratorHelper(o, allowArrayLike) {
+ var it;
+
+ if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
+ if (it) o = it;
+ var i = 0;
+
+ var F = function () {};
+
+ return {
+ s: F,
+ n: function () {
+ if (i >= o.length) return {
+ done: true
+ };
+ return {
+ done: false,
+ value: o[i++]
+ };
+ },
+ e: function (e) {
+ throw e;
+ },
+ f: F
+ };
+ }
+
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+ }
+
+ var normalCompletion = true,
+ didErr = false,
+ err;
+ return {
+ s: function () {
+ it = o[Symbol.iterator]();
+ },
+ n: function () {
+ var step = it.next();
+ normalCompletion = step.done;
+ return step;
+ },
+ e: function (e) {
+ didErr = true;
+ err = e;
+ },
+ f: function () {
+ try {
+ if (!normalCompletion && it.return != null) it.return();
+ } finally {
+ if (didErr) throw err;
+ }
+ }
+ };
+ }
+
+ // http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
+
+ /**
+ *
+ * @param {Event} ev
+ * @returns {void}
+ */
+ function touchHandler(ev) {
+ var changedTouches = ev.changedTouches,
+ first = changedTouches[0];
+ var type = '';
+
+ switch (ev.type) {
+ case 'touchstart':
+ type = 'mousedown';
+ break;
+
+ case 'touchmove':
+ type = 'mousemove';
+ break;
+
+ case 'touchend':
+ type = 'mouseup';
+ break;
+
+ default:
+ return;
+ }
+
+ var screenX = first.screenX,
+ screenY = first.screenY,
+ clientX = first.clientX,
+ clientY = first.clientY; // eslint-disable-line no-shadow
+
+ var simulatedEvent = new MouseEvent(type, {
+ // Event interface
+ bubbles: true,
+ cancelable: true,
+ // UIEvent interface
+ view: window,
+ detail: 1,
+ // click count
+ // MouseEvent interface (customized)
+ screenX: screenX,
+ screenY: screenY,
+ clientX: clientX,
+ clientY: clientY,
+ // MouseEvent interface (defaults) - these could be removed
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false,
+ button: 0,
+ // main button (usually left)
+ relatedTarget: null
+ });
+
+ if (changedTouches.length < 2) {
+ first.target.dispatchEvent(simulatedEvent);
+ ev.preventDefault();
+ }
+ }
+
+ document.addEventListener('touchstart', touchHandler, true);
+ document.addEventListener('touchmove', touchHandler, true);
+ document.addEventListener('touchend', touchHandler, true);
+ document.addEventListener('touchcancel', touchHandler, true);
+
+ /**
+ * Namespaces or tools therefor.
+ * @module namespaces
+ * @license MIT
+ */
+
+ /**
+ * Common namepaces constants in alpha order.
+ * @enum {string}
+ * @type {PlainObject}
+ * @memberof module:namespaces
+ */
+ var NS = {
+ HTML: 'http://www.w3.org/1999/xhtml',
+ MATH: 'http://www.w3.org/1998/Math/MathML',
+ SE: 'http://svg-edit.googlecode.com',
+ SVG: 'http://www.w3.org/2000/svg',
+ XLINK: 'http://www.w3.org/1999/xlink',
+ XML: 'http://www.w3.org/XML/1998/namespace',
+ XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved
+
+ };
+ /**
+ * @function module:namespaces.getReverseNS
+ * @returns {string} The NS with key values switched and lowercase
+ */
+
+ var getReverseNS = function getReverseNS() {
+ var reverseNS = {};
+ Object.entries(NS).forEach(function (_ref) {
+ var _ref2 = _slicedToArray(_ref, 2),
+ name = _ref2[0],
+ URI = _ref2[1];
+
+ reverseNS[URI] = name.toLowerCase();
+ });
+ return reverseNS;
+ };
+
+ /* eslint-disable import/unambiguous, max-len */
+
+ /* globals SVGPathSeg, SVGPathSegMovetoRel, SVGPathSegMovetoAbs,
+ SVGPathSegMovetoRel, SVGPathSegLinetoRel, SVGPathSegLinetoAbs,
+ SVGPathSegLinetoHorizontalRel, SVGPathSegLinetoHorizontalAbs,
+ SVGPathSegLinetoVerticalRel, SVGPathSegLinetoVerticalAbs,
+ SVGPathSegClosePath, SVGPathSegCurvetoCubicRel,
+ SVGPathSegCurvetoCubicAbs, SVGPathSegCurvetoCubicSmoothRel,
+ SVGPathSegCurvetoCubicSmoothAbs, SVGPathSegCurvetoQuadraticRel,
+ SVGPathSegCurvetoQuadraticAbs, SVGPathSegCurvetoQuadraticSmoothRel,
+ SVGPathSegCurvetoQuadraticSmoothAbs, SVGPathSegArcRel, SVGPathSegArcAbs */
+
+ /**
+ * SVGPathSeg API polyfill
+ * https://github.com/progers/pathseg
+ *
+ * This is a drop-in replacement for the `SVGPathSeg` and `SVGPathSegList` APIs
+ * that were removed from SVG2 ({@link https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html}),
+ * including the latest spec changes which were implemented in Firefox 43 and
+ * Chrome 46.
+ */
+
+ /* eslint-disable no-shadow, class-methods-use-this, jsdoc/require-jsdoc */
+ // Linting: We avoid `no-shadow` as ESLint thinks these are still available globals
+ // Linting: We avoid `class-methods-use-this` as this is a polyfill that must
+ // follow the conventions
+ (function () {
+ if (!('SVGPathSeg' in window)) {
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
+ var _SVGPathSeg = /*#__PURE__*/function () {
+ function _SVGPathSeg(type, typeAsLetter, owningPathSegList) {
+ _classCallCheck(this, _SVGPathSeg);
+
+ this.pathSegType = type;
+ this.pathSegTypeAsLetter = typeAsLetter;
+ this._owningPathSegList = owningPathSegList;
+ } // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
+
+
+ _createClass(_SVGPathSeg, [{
+ key: "_segmentChanged",
+ value: function _segmentChanged() {
+ if (this._owningPathSegList) {
+ this._owningPathSegList.segmentChanged(this);
+ }
+ }
+ }]);
+
+ return _SVGPathSeg;
+ }();
+
+ _SVGPathSeg.prototype.classname = 'SVGPathSeg';
+ _SVGPathSeg.PATHSEG_UNKNOWN = 0;
+ _SVGPathSeg.PATHSEG_CLOSEPATH = 1;
+ _SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
+ _SVGPathSeg.PATHSEG_MOVETO_REL = 3;
+ _SVGPathSeg.PATHSEG_LINETO_ABS = 4;
+ _SVGPathSeg.PATHSEG_LINETO_REL = 5;
+ _SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
+ _SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
+ _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
+ _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
+ _SVGPathSeg.PATHSEG_ARC_ABS = 10;
+ _SVGPathSeg.PATHSEG_ARC_REL = 11;
+ _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
+ _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
+ _SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
+ _SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
+ _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
+ _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
+ _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
+ _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
+
+ var _SVGPathSegClosePath = /*#__PURE__*/function (_SVGPathSeg2) {
+ _inherits(_SVGPathSegClosePath, _SVGPathSeg2);
+
+ var _super = _createSuper(_SVGPathSegClosePath);
+
+ function _SVGPathSegClosePath(owningPathSegList) {
+ _classCallCheck(this, _SVGPathSegClosePath);
+
+ return _super.call(this, _SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList);
+ }
+
+ _createClass(_SVGPathSegClosePath, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegClosePath]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegClosePath(undefined);
+ }
+ }]);
+
+ return _SVGPathSegClosePath;
+ }(_SVGPathSeg);
+
+ var _SVGPathSegMovetoAbs = /*#__PURE__*/function (_SVGPathSeg3) {
+ _inherits(_SVGPathSegMovetoAbs, _SVGPathSeg3);
+
+ var _super2 = _createSuper(_SVGPathSegMovetoAbs);
+
+ function _SVGPathSegMovetoAbs(owningPathSegList, x, y) {
+ var _this;
+
+ _classCallCheck(this, _SVGPathSegMovetoAbs);
+
+ _this = _super2.call(this, _SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList);
+ _this._x = x;
+ _this._y = y;
+ return _this;
+ }
+
+ _createClass(_SVGPathSegMovetoAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegMovetoAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegMovetoAbs(undefined, this._x, this._y);
+ }
+ }]);
+
+ return _SVGPathSegMovetoAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegMovetoAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegMovetoRel = /*#__PURE__*/function (_SVGPathSeg4) {
+ _inherits(_SVGPathSegMovetoRel, _SVGPathSeg4);
+
+ var _super3 = _createSuper(_SVGPathSegMovetoRel);
+
+ function _SVGPathSegMovetoRel(owningPathSegList, x, y) {
+ var _this2;
+
+ _classCallCheck(this, _SVGPathSegMovetoRel);
+
+ _this2 = _super3.call(this, _SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList);
+ _this2._x = x;
+ _this2._y = y;
+ return _this2;
+ }
+
+ _createClass(_SVGPathSegMovetoRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegMovetoRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegMovetoRel(undefined, this._x, this._y);
+ }
+ }]);
+
+ return _SVGPathSegMovetoRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegMovetoRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegLinetoAbs = /*#__PURE__*/function (_SVGPathSeg5) {
+ _inherits(_SVGPathSegLinetoAbs, _SVGPathSeg5);
+
+ var _super4 = _createSuper(_SVGPathSegLinetoAbs);
+
+ function _SVGPathSegLinetoAbs(owningPathSegList, x, y) {
+ var _this3;
+
+ _classCallCheck(this, _SVGPathSegLinetoAbs);
+
+ _this3 = _super4.call(this, _SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList);
+ _this3._x = x;
+ _this3._y = y;
+ return _this3;
+ }
+
+ _createClass(_SVGPathSegLinetoAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegLinetoAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegLinetoAbs(undefined, this._x, this._y);
+ }
+ }]);
+
+ return _SVGPathSegLinetoAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegLinetoAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegLinetoRel = /*#__PURE__*/function (_SVGPathSeg6) {
+ _inherits(_SVGPathSegLinetoRel, _SVGPathSeg6);
+
+ var _super5 = _createSuper(_SVGPathSegLinetoRel);
+
+ function _SVGPathSegLinetoRel(owningPathSegList, x, y) {
+ var _this4;
+
+ _classCallCheck(this, _SVGPathSegLinetoRel);
+
+ _this4 = _super5.call(this, _SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList);
+ _this4._x = x;
+ _this4._y = y;
+ return _this4;
+ }
+
+ _createClass(_SVGPathSegLinetoRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegLinetoRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegLinetoRel(undefined, this._x, this._y);
+ }
+ }]);
+
+ return _SVGPathSegLinetoRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegLinetoRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoCubicAbs = /*#__PURE__*/function (_SVGPathSeg7) {
+ _inherits(_SVGPathSegCurvetoCubicAbs, _SVGPathSeg7);
+
+ var _super6 = _createSuper(_SVGPathSegCurvetoCubicAbs);
+
+ function _SVGPathSegCurvetoCubicAbs(owningPathSegList, x, y, x1, y1, x2, y2) {
+ var _this5;
+
+ _classCallCheck(this, _SVGPathSegCurvetoCubicAbs);
+
+ _this5 = _super6.call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList);
+ _this5._x = x;
+ _this5._y = y;
+ _this5._x1 = x1;
+ _this5._y1 = y1;
+ _this5._x2 = x2;
+ _this5._y2 = y2;
+ return _this5;
+ }
+
+ _createClass(_SVGPathSegCurvetoCubicAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoCubicAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoCubicAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoCubicAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x1: {
+ get: function get() {
+ return this._x1;
+ },
+ set: function set(x1) {
+ this._x1 = x1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y1: {
+ get: function get() {
+ return this._y1;
+ },
+ set: function set(y1) {
+ this._y1 = y1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x2: {
+ get: function get() {
+ return this._x2;
+ },
+ set: function set(x2) {
+ this._x2 = x2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y2: {
+ get: function get() {
+ return this._y2;
+ },
+ set: function set(y2) {
+ this._y2 = y2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoCubicRel = /*#__PURE__*/function (_SVGPathSeg8) {
+ _inherits(_SVGPathSegCurvetoCubicRel, _SVGPathSeg8);
+
+ var _super7 = _createSuper(_SVGPathSegCurvetoCubicRel);
+
+ function _SVGPathSegCurvetoCubicRel(owningPathSegList, x, y, x1, y1, x2, y2) {
+ var _this6;
+
+ _classCallCheck(this, _SVGPathSegCurvetoCubicRel);
+
+ _this6 = _super7.call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList);
+ _this6._x = x;
+ _this6._y = y;
+ _this6._x1 = x1;
+ _this6._y1 = y1;
+ _this6._x2 = x2;
+ _this6._y2 = y2;
+ return _this6;
+ }
+
+ _createClass(_SVGPathSegCurvetoCubicRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoCubicRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoCubicRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoCubicRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x1: {
+ get: function get() {
+ return this._x1;
+ },
+ set: function set(x1) {
+ this._x1 = x1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y1: {
+ get: function get() {
+ return this._y1;
+ },
+ set: function set(y1) {
+ this._y1 = y1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x2: {
+ get: function get() {
+ return this._x2;
+ },
+ set: function set(x2) {
+ this._x2 = x2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y2: {
+ get: function get() {
+ return this._y2;
+ },
+ set: function set(y2) {
+ this._y2 = y2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoQuadraticAbs = /*#__PURE__*/function (_SVGPathSeg9) {
+ _inherits(_SVGPathSegCurvetoQuadraticAbs, _SVGPathSeg9);
+
+ var _super8 = _createSuper(_SVGPathSegCurvetoQuadraticAbs);
+
+ function _SVGPathSegCurvetoQuadraticAbs(owningPathSegList, x, y, x1, y1) {
+ var _this7;
+
+ _classCallCheck(this, _SVGPathSegCurvetoQuadraticAbs);
+
+ _this7 = _super8.call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList);
+ _this7._x = x;
+ _this7._y = y;
+ _this7._x1 = x1;
+ _this7._y1 = y1;
+ return _this7;
+ }
+
+ _createClass(_SVGPathSegCurvetoQuadraticAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoQuadraticAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoQuadraticAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoQuadraticAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x1: {
+ get: function get() {
+ return this._x1;
+ },
+ set: function set(x1) {
+ this._x1 = x1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y1: {
+ get: function get() {
+ return this._y1;
+ },
+ set: function set(y1) {
+ this._y1 = y1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoQuadraticRel = /*#__PURE__*/function (_SVGPathSeg10) {
+ _inherits(_SVGPathSegCurvetoQuadraticRel, _SVGPathSeg10);
+
+ var _super9 = _createSuper(_SVGPathSegCurvetoQuadraticRel);
+
+ function _SVGPathSegCurvetoQuadraticRel(owningPathSegList, x, y, x1, y1) {
+ var _this8;
+
+ _classCallCheck(this, _SVGPathSegCurvetoQuadraticRel);
+
+ _this8 = _super9.call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList);
+ _this8._x = x;
+ _this8._y = y;
+ _this8._x1 = x1;
+ _this8._y1 = y1;
+ return _this8;
+ }
+
+ _createClass(_SVGPathSegCurvetoQuadraticRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoQuadraticRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoQuadraticRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoQuadraticRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x1: {
+ get: function get() {
+ return this._x1;
+ },
+ set: function set(x1) {
+ this._x1 = x1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y1: {
+ get: function get() {
+ return this._y1;
+ },
+ set: function set(y1) {
+ this._y1 = y1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegArcAbs = /*#__PURE__*/function (_SVGPathSeg11) {
+ _inherits(_SVGPathSegArcAbs, _SVGPathSeg11);
+
+ var _super10 = _createSuper(_SVGPathSegArcAbs);
+
+ function _SVGPathSegArcAbs(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ var _this9;
+
+ _classCallCheck(this, _SVGPathSegArcAbs);
+
+ _this9 = _super10.call(this, _SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList);
+ _this9._x = x;
+ _this9._y = y;
+ _this9._r1 = r1;
+ _this9._r2 = r2;
+ _this9._angle = angle;
+ _this9._largeArcFlag = largeArcFlag;
+ _this9._sweepFlag = sweepFlag;
+ return _this9;
+ }
+
+ _createClass(_SVGPathSegArcAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegArcAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
+ }
+ }]);
+
+ return _SVGPathSegArcAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegArcAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ r1: {
+ get: function get() {
+ return this._r1;
+ },
+ set: function set(r1) {
+ this._r1 = r1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ r2: {
+ get: function get() {
+ return this._r2;
+ },
+ set: function set(r2) {
+ this._r2 = r2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ angle: {
+ get: function get() {
+ return this._angle;
+ },
+ set: function set(angle) {
+ this._angle = angle;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ largeArcFlag: {
+ get: function get() {
+ return this._largeArcFlag;
+ },
+ set: function set(largeArcFlag) {
+ this._largeArcFlag = largeArcFlag;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ sweepFlag: {
+ get: function get() {
+ return this._sweepFlag;
+ },
+ set: function set(sweepFlag) {
+ this._sweepFlag = sweepFlag;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegArcRel = /*#__PURE__*/function (_SVGPathSeg12) {
+ _inherits(_SVGPathSegArcRel, _SVGPathSeg12);
+
+ var _super11 = _createSuper(_SVGPathSegArcRel);
+
+ function _SVGPathSegArcRel(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ var _this10;
+
+ _classCallCheck(this, _SVGPathSegArcRel);
+
+ _this10 = _super11.call(this, _SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList);
+ _this10._x = x;
+ _this10._y = y;
+ _this10._r1 = r1;
+ _this10._r2 = r2;
+ _this10._angle = angle;
+ _this10._largeArcFlag = largeArcFlag;
+ _this10._sweepFlag = sweepFlag;
+ return _this10;
+ }
+
+ _createClass(_SVGPathSegArcRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegArcRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
+ }
+ }]);
+
+ return _SVGPathSegArcRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegArcRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ r1: {
+ get: function get() {
+ return this._r1;
+ },
+ set: function set(r1) {
+ this._r1 = r1;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ r2: {
+ get: function get() {
+ return this._r2;
+ },
+ set: function set(r2) {
+ this._r2 = r2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ angle: {
+ get: function get() {
+ return this._angle;
+ },
+ set: function set(angle) {
+ this._angle = angle;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ largeArcFlag: {
+ get: function get() {
+ return this._largeArcFlag;
+ },
+ set: function set(largeArcFlag) {
+ this._largeArcFlag = largeArcFlag;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ sweepFlag: {
+ get: function get() {
+ return this._sweepFlag;
+ },
+ set: function set(sweepFlag) {
+ this._sweepFlag = sweepFlag;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegLinetoHorizontalAbs = /*#__PURE__*/function (_SVGPathSeg13) {
+ _inherits(_SVGPathSegLinetoHorizontalAbs, _SVGPathSeg13);
+
+ var _super12 = _createSuper(_SVGPathSegLinetoHorizontalAbs);
+
+ function _SVGPathSegLinetoHorizontalAbs(owningPathSegList, x) {
+ var _this11;
+
+ _classCallCheck(this, _SVGPathSegLinetoHorizontalAbs);
+
+ _this11 = _super12.call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList);
+ _this11._x = x;
+ return _this11;
+ }
+
+ _createClass(_SVGPathSegLinetoHorizontalAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegLinetoHorizontalAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegLinetoHorizontalAbs(undefined, this._x);
+ }
+ }]);
+
+ return _SVGPathSegLinetoHorizontalAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperty(_SVGPathSegLinetoHorizontalAbs.prototype, 'x', {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ });
+
+ var _SVGPathSegLinetoHorizontalRel = /*#__PURE__*/function (_SVGPathSeg14) {
+ _inherits(_SVGPathSegLinetoHorizontalRel, _SVGPathSeg14);
+
+ var _super13 = _createSuper(_SVGPathSegLinetoHorizontalRel);
+
+ function _SVGPathSegLinetoHorizontalRel(owningPathSegList, x) {
+ var _this12;
+
+ _classCallCheck(this, _SVGPathSegLinetoHorizontalRel);
+
+ _this12 = _super13.call(this, _SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList);
+ _this12._x = x;
+ return _this12;
+ }
+
+ _createClass(_SVGPathSegLinetoHorizontalRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegLinetoHorizontalRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegLinetoHorizontalRel(undefined, this._x);
+ }
+ }]);
+
+ return _SVGPathSegLinetoHorizontalRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperty(_SVGPathSegLinetoHorizontalRel.prototype, 'x', {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ });
+
+ var _SVGPathSegLinetoVerticalAbs = /*#__PURE__*/function (_SVGPathSeg15) {
+ _inherits(_SVGPathSegLinetoVerticalAbs, _SVGPathSeg15);
+
+ var _super14 = _createSuper(_SVGPathSegLinetoVerticalAbs);
+
+ function _SVGPathSegLinetoVerticalAbs(owningPathSegList, y) {
+ var _this13;
+
+ _classCallCheck(this, _SVGPathSegLinetoVerticalAbs);
+
+ _this13 = _super14.call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList);
+ _this13._y = y;
+ return _this13;
+ }
+
+ _createClass(_SVGPathSegLinetoVerticalAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegLinetoVerticalAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegLinetoVerticalAbs(undefined, this._y);
+ }
+ }]);
+
+ return _SVGPathSegLinetoVerticalAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperty(_SVGPathSegLinetoVerticalAbs.prototype, 'y', {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ });
+
+ var _SVGPathSegLinetoVerticalRel = /*#__PURE__*/function (_SVGPathSeg16) {
+ _inherits(_SVGPathSegLinetoVerticalRel, _SVGPathSeg16);
+
+ var _super15 = _createSuper(_SVGPathSegLinetoVerticalRel);
+
+ function _SVGPathSegLinetoVerticalRel(owningPathSegList, y) {
+ var _this14;
+
+ _classCallCheck(this, _SVGPathSegLinetoVerticalRel);
+
+ _this14 = _super15.call(this, _SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList);
+ _this14._y = y;
+ return _this14;
+ }
+
+ _createClass(_SVGPathSegLinetoVerticalRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegLinetoVerticalRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegLinetoVerticalRel(undefined, this._y);
+ }
+ }]);
+
+ return _SVGPathSegLinetoVerticalRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperty(_SVGPathSegLinetoVerticalRel.prototype, 'y', {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ });
+
+ var _SVGPathSegCurvetoCubicSmoothAbs = /*#__PURE__*/function (_SVGPathSeg17) {
+ _inherits(_SVGPathSegCurvetoCubicSmoothAbs, _SVGPathSeg17);
+
+ var _super16 = _createSuper(_SVGPathSegCurvetoCubicSmoothAbs);
+
+ function _SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, x, y, x2, y2) {
+ var _this15;
+
+ _classCallCheck(this, _SVGPathSegCurvetoCubicSmoothAbs);
+
+ _this15 = _super16.call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList);
+ _this15._x = x;
+ _this15._y = y;
+ _this15._x2 = x2;
+ _this15._y2 = y2;
+ return _this15;
+ }
+
+ _createClass(_SVGPathSegCurvetoCubicSmoothAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoCubicSmoothAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoCubicSmoothAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoCubicSmoothAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x2: {
+ get: function get() {
+ return this._x2;
+ },
+ set: function set(x2) {
+ this._x2 = x2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y2: {
+ get: function get() {
+ return this._y2;
+ },
+ set: function set(y2) {
+ this._y2 = y2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoCubicSmoothRel = /*#__PURE__*/function (_SVGPathSeg18) {
+ _inherits(_SVGPathSegCurvetoCubicSmoothRel, _SVGPathSeg18);
+
+ var _super17 = _createSuper(_SVGPathSegCurvetoCubicSmoothRel);
+
+ function _SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, x, y, x2, y2) {
+ var _this16;
+
+ _classCallCheck(this, _SVGPathSegCurvetoCubicSmoothRel);
+
+ _this16 = _super17.call(this, _SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList);
+ _this16._x = x;
+ _this16._y = y;
+ _this16._x2 = x2;
+ _this16._y2 = y2;
+ return _this16;
+ }
+
+ _createClass(_SVGPathSegCurvetoCubicSmoothRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoCubicSmoothRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoCubicSmoothRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoCubicSmoothRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ x2: {
+ get: function get() {
+ return this._x2;
+ },
+ set: function set(x2) {
+ this._x2 = x2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y2: {
+ get: function get() {
+ return this._y2;
+ },
+ set: function set(y2) {
+ this._y2 = y2;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoQuadraticSmoothAbs = /*#__PURE__*/function (_SVGPathSeg19) {
+ _inherits(_SVGPathSegCurvetoQuadraticSmoothAbs, _SVGPathSeg19);
+
+ var _super18 = _createSuper(_SVGPathSegCurvetoQuadraticSmoothAbs);
+
+ function _SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, x, y) {
+ var _this17;
+
+ _classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothAbs);
+
+ _this17 = _super18.call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList);
+ _this17._x = x;
+ _this17._y = y;
+ return _this17;
+ }
+
+ _createClass(_SVGPathSegCurvetoQuadraticSmoothAbs, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoQuadraticSmoothAbs]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoQuadraticSmoothAbs;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoQuadraticSmoothAbs.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ });
+
+ var _SVGPathSegCurvetoQuadraticSmoothRel = /*#__PURE__*/function (_SVGPathSeg20) {
+ _inherits(_SVGPathSegCurvetoQuadraticSmoothRel, _SVGPathSeg20);
+
+ var _super19 = _createSuper(_SVGPathSegCurvetoQuadraticSmoothRel);
+
+ function _SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, x, y) {
+ var _this18;
+
+ _classCallCheck(this, _SVGPathSegCurvetoQuadraticSmoothRel);
+
+ _this18 = _super19.call(this, _SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList);
+ _this18._x = x;
+ _this18._y = y;
+ return _this18;
+ }
+
+ _createClass(_SVGPathSegCurvetoQuadraticSmoothRel, [{
+ key: "toString",
+ value: function toString() {
+ return '[object SVGPathSegCurvetoQuadraticSmoothRel]';
+ }
+ }, {
+ key: "_asPathString",
+ value: function _asPathString() {
+ return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+ }
+ }, {
+ key: "clone",
+ value: function clone() {
+ return new _SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y);
+ }
+ }]);
+
+ return _SVGPathSegCurvetoQuadraticSmoothRel;
+ }(_SVGPathSeg);
+
+ Object.defineProperties(_SVGPathSegCurvetoQuadraticSmoothRel.prototype, {
+ x: {
+ get: function get() {
+ return this._x;
+ },
+ set: function set(x) {
+ this._x = x;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ },
+ y: {
+ get: function get() {
+ return this._y;
+ },
+ set: function set(y) {
+ this._y = y;
+
+ this._segmentChanged();
+ },
+ enumerable: true
+ }
+ }); // Add createSVGPathSeg* functions to SVGPathElement.
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement.
+
+ SVGPathElement.prototype.createSVGPathSegClosePath = function () {
+ return new _SVGPathSegClosePath(undefined);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) {
+ return new _SVGPathSegMovetoAbs(undefined, x, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) {
+ return new _SVGPathSegMovetoRel(undefined, x, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) {
+ return new _SVGPathSegLinetoAbs(undefined, x, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) {
+ return new _SVGPathSegLinetoRel(undefined, x, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) {
+ return new _SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) {
+ return new _SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) {
+ return new _SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) {
+ return new _SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ return new _SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ return new _SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) {
+ return new _SVGPathSegLinetoHorizontalAbs(undefined, x);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) {
+ return new _SVGPathSegLinetoHorizontalRel(undefined, x);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) {
+ return new _SVGPathSegLinetoVerticalAbs(undefined, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) {
+ return new _SVGPathSegLinetoVerticalRel(undefined, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) {
+ return new _SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) {
+ return new _SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) {
+ return new _SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y);
+ };
+
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) {
+ return new _SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y);
+ };
+
+ if (!('getPathSegAtLength' in SVGPathElement.prototype)) {
+ // Add getPathSegAtLength to SVGPathElement.
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
+ // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
+ SVGPathElement.prototype.getPathSegAtLength = function (distance) {
+ if (distance === undefined || !isFinite(distance)) {
+ throw new Error('Invalid arguments.');
+ }
+
+ var measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+ measurementElement.setAttribute('d', this.getAttribute('d'));
+ var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1; // If the path is empty, return 0.
+
+ if (lastPathSegment <= 0) {
+ return 0;
+ }
+
+ do {
+ measurementElement.pathSegList.removeItem(lastPathSegment);
+
+ if (distance > measurementElement.getTotalLength()) {
+ break;
+ }
+
+ lastPathSegment--;
+ } while (lastPathSegment > 0);
+
+ return lastPathSegment;
+ };
+ }
+
+ window.SVGPathSeg = _SVGPathSeg;
+ window.SVGPathSegClosePath = _SVGPathSegClosePath;
+ window.SVGPathSegMovetoAbs = _SVGPathSegMovetoAbs;
+ window.SVGPathSegMovetoRel = _SVGPathSegMovetoRel;
+ window.SVGPathSegLinetoAbs = _SVGPathSegLinetoAbs;
+ window.SVGPathSegLinetoRel = _SVGPathSegLinetoRel;
+ window.SVGPathSegCurvetoCubicAbs = _SVGPathSegCurvetoCubicAbs;
+ window.SVGPathSegCurvetoCubicRel = _SVGPathSegCurvetoCubicRel;
+ window.SVGPathSegCurvetoQuadraticAbs = _SVGPathSegCurvetoQuadraticAbs;
+ window.SVGPathSegCurvetoQuadraticRel = _SVGPathSegCurvetoQuadraticRel;
+ window.SVGPathSegArcAbs = _SVGPathSegArcAbs;
+ window.SVGPathSegArcRel = _SVGPathSegArcRel;
+ window.SVGPathSegLinetoHorizontalAbs = _SVGPathSegLinetoHorizontalAbs;
+ window.SVGPathSegLinetoHorizontalRel = _SVGPathSegLinetoHorizontalRel;
+ window.SVGPathSegLinetoVerticalAbs = _SVGPathSegLinetoVerticalAbs;
+ window.SVGPathSegLinetoVerticalRel = _SVGPathSegLinetoVerticalRel;
+ window.SVGPathSegCurvetoCubicSmoothAbs = _SVGPathSegCurvetoCubicSmoothAbs;
+ window.SVGPathSegCurvetoCubicSmoothRel = _SVGPathSegCurvetoCubicSmoothRel;
+ window.SVGPathSegCurvetoQuadraticSmoothAbs = _SVGPathSegCurvetoQuadraticSmoothAbs;
+ window.SVGPathSegCurvetoQuadraticSmoothRel = _SVGPathSegCurvetoQuadraticSmoothRel;
+ } // Checking for SVGPathSegList in window checks for the case of an implementation without the
+ // SVGPathSegList API.
+ // The second check for appendItem is specific to Firefox 59+ which removed only parts of the
+ // SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API
+ // so the polyfill data (i.e., _list) is used throughout.
+
+
+ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.prototype)) {
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
+ var SVGPathSegList = /*#__PURE__*/function () {
+ function SVGPathSegList(pathElement) {
+ _classCallCheck(this, SVGPathSegList);
+
+ this._pathElement = pathElement;
+ this._list = this._parsePath(this._pathElement.getAttribute('d')); // Use a MutationObserver to catch changes to the path's "d" attribute.
+
+ this._mutationObserverConfig = {
+ attributes: true,
+ attributeFilter: ['d']
+ };
+ this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
+
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+ } // Process any pending mutations to the path element and update the list as needed.
+ // This should be the first call of all public functions and is needed because
+ // MutationObservers are not synchronous so we can have pending asynchronous mutations.
+
+
+ _createClass(SVGPathSegList, [{
+ key: "_checkPathSynchronizedToList",
+ value: function _checkPathSynchronizedToList() {
+ this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
+ }
+ }, {
+ key: "_updateListFromPathMutations",
+ value: function _updateListFromPathMutations(mutationRecords) {
+ if (!this._pathElement) {
+ return;
+ }
+
+ var hasPathMutations = false;
+ mutationRecords.forEach(function (record) {
+ if (record.attributeName === 'd') {
+ hasPathMutations = true;
+ }
+ });
+
+ if (hasPathMutations) {
+ this._list = this._parsePath(this._pathElement.getAttribute('d'));
+ }
+ } // Serialize the list and update the path's 'd' attribute.
+
+ }, {
+ key: "_writeListToPath",
+ value: function _writeListToPath() {
+ this._pathElementMutationObserver.disconnect();
+
+ this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list));
+
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+ } // When a path segment changes the list needs to be synchronized back to the path element.
+
+ }, {
+ key: "segmentChanged",
+ value: function segmentChanged(pathSeg) {
+ this._writeListToPath();
+ }
+ }, {
+ key: "clear",
+ value: function clear() {
+ this._checkPathSynchronizedToList();
+
+ this._list.forEach(function (pathSeg) {
+ pathSeg._owningPathSegList = null;
+ });
+
+ this._list = [];
+
+ this._writeListToPath();
+ }
+ }, {
+ key: "initialize",
+ value: function initialize(newItem) {
+ this._checkPathSynchronizedToList();
+
+ this._list = [newItem];
+ newItem._owningPathSegList = this;
+
+ this._writeListToPath();
+
+ return newItem;
+ }
+ }, {
+ key: "_checkValidIndex",
+ value: function _checkValidIndex(index) {
+ if (isNaN(index) || index < 0 || index >= this.numberOfItems) {
+ throw new Error('INDEX_SIZE_ERR');
+ }
+ }
+ }, {
+ key: "getItem",
+ value: function getItem(index) {
+ this._checkPathSynchronizedToList();
+
+ this._checkValidIndex(index);
+
+ return this._list[index];
+ }
+ }, {
+ key: "insertItemBefore",
+ value: function insertItemBefore(newItem, index) {
+ this._checkPathSynchronizedToList(); // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+
+
+ if (index > this.numberOfItems) {
+ index = this.numberOfItems;
+ }
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+
+ this._list.splice(index, 0, newItem);
+
+ newItem._owningPathSegList = this;
+
+ this._writeListToPath();
+
+ return newItem;
+ }
+ }, {
+ key: "replaceItem",
+ value: function replaceItem(newItem, index) {
+ this._checkPathSynchronizedToList();
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+
+ this._checkValidIndex(index);
+
+ this._list[index] = newItem;
+ newItem._owningPathSegList = this;
+
+ this._writeListToPath();
+
+ return newItem;
+ }
+ }, {
+ key: "removeItem",
+ value: function removeItem(index) {
+ this._checkPathSynchronizedToList();
+
+ this._checkValidIndex(index);
+
+ var item = this._list[index];
+
+ this._list.splice(index, 1);
+
+ this._writeListToPath();
+
+ return item;
+ }
+ }, {
+ key: "appendItem",
+ value: function appendItem(newItem) {
+ this._checkPathSynchronizedToList();
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+
+ this._list.push(newItem);
+
+ newItem._owningPathSegList = this; // TODO: Optimize this to just append to the existing attribute.
+
+ this._writeListToPath();
+
+ return newItem;
+ } // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
+
+ }, {
+ key: "_parsePath",
+ value: function _parsePath(string) {
+ if (!string || !string.length) {
+ return [];
+ }
+
+ var owningPathSegList = this;
+
+ var Builder = /*#__PURE__*/function () {
+ function Builder() {
+ _classCallCheck(this, Builder);
+
+ this.pathSegList = [];
+ }
+
+ _createClass(Builder, [{
+ key: "appendSegment",
+ value: function appendSegment(pathSeg) {
+ this.pathSegList.push(pathSeg);
+ }
+ }]);
+
+ return Builder;
+ }();
+
+ var Source = /*#__PURE__*/function () {
+ function Source(string) {
+ _classCallCheck(this, Source);
+
+ this._string = string;
+ this._currentIndex = 0;
+ this._endIndex = this._string.length;
+ this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN;
+
+ this._skipOptionalSpaces();
+ }
+
+ _createClass(Source, [{
+ key: "_isCurrentSpace",
+ value: function _isCurrentSpace() {
+ var character = this._string[this._currentIndex];
+ return character <= ' ' && (character === ' ' || character === '\n' || character === '\t' || character === '\r' || character === '\f');
+ }
+ }, {
+ key: "_skipOptionalSpaces",
+ value: function _skipOptionalSpaces() {
+ while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {
+ this._currentIndex++;
+ }
+
+ return this._currentIndex < this._endIndex;
+ }
+ }, {
+ key: "_skipOptionalSpacesOrDelimiter",
+ value: function _skipOptionalSpacesOrDelimiter() {
+ if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) !== ',') {
+ return false;
+ }
+
+ if (this._skipOptionalSpaces()) {
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === ',') {
+ this._currentIndex++;
+
+ this._skipOptionalSpaces();
+ }
+ }
+
+ return this._currentIndex < this._endIndex;
+ }
+ }, {
+ key: "hasMoreData",
+ value: function hasMoreData() {
+ return this._currentIndex < this._endIndex;
+ }
+ }, {
+ key: "peekSegmentType",
+ value: function peekSegmentType() {
+ var lookahead = this._string[this._currentIndex];
+ return this._pathSegTypeFromChar(lookahead);
+ }
+ }, {
+ key: "_pathSegTypeFromChar",
+ value: function _pathSegTypeFromChar(lookahead) {
+ switch (lookahead) {
+ case 'Z':
+ case 'z':
+ return SVGPathSeg.PATHSEG_CLOSEPATH;
+
+ case 'M':
+ return SVGPathSeg.PATHSEG_MOVETO_ABS;
+
+ case 'm':
+ return SVGPathSeg.PATHSEG_MOVETO_REL;
+
+ case 'L':
+ return SVGPathSeg.PATHSEG_LINETO_ABS;
+
+ case 'l':
+ return SVGPathSeg.PATHSEG_LINETO_REL;
+
+ case 'C':
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
+
+ case 'c':
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
+
+ case 'Q':
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
+
+ case 'q':
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
+
+ case 'A':
+ return SVGPathSeg.PATHSEG_ARC_ABS;
+
+ case 'a':
+ return SVGPathSeg.PATHSEG_ARC_REL;
+
+ case 'H':
+ return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
+
+ case 'h':
+ return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
+
+ case 'V':
+ return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
+
+ case 'v':
+ return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
+
+ case 'S':
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
+
+ case 's':
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
+
+ case 'T':
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
+
+ case 't':
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
+
+ default:
+ return SVGPathSeg.PATHSEG_UNKNOWN;
+ }
+ }
+ }, {
+ key: "_nextCommandHelper",
+ value: function _nextCommandHelper(lookahead, previousCommand) {
+ // Check for remaining coordinates in the current command.
+ if ((lookahead === '+' || lookahead === '-' || lookahead === '.' || lookahead >= '0' && lookahead <= '9') && previousCommand !== SVGPathSeg.PATHSEG_CLOSEPATH) {
+ if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_ABS) {
+ return SVGPathSeg.PATHSEG_LINETO_ABS;
+ }
+
+ if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_REL) {
+ return SVGPathSeg.PATHSEG_LINETO_REL;
+ }
+
+ return previousCommand;
+ }
+
+ return SVGPathSeg.PATHSEG_UNKNOWN;
+ }
+ }, {
+ key: "initialCommandIsMoveTo",
+ value: function initialCommandIsMoveTo() {
+ // If the path is empty it is still valid, so return true.
+ if (!this.hasMoreData()) {
+ return true;
+ }
+
+ var command = this.peekSegmentType(); // Path must start with moveTo.
+
+ return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL;
+ } // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
+
+ }, {
+ key: "_parseNumber",
+ value: function _parseNumber() {
+ var exponent = 0;
+ var integer = 0;
+ var frac = 1;
+ var decimal = 0;
+ var sign = 1;
+ var expsign = 1;
+ var startIndex = this._currentIndex;
+
+ this._skipOptionalSpaces(); // Read the sign.
+
+
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '+') {
+ this._currentIndex++;
+ } else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '-') {
+ this._currentIndex++;
+ sign = -1;
+ }
+
+ if (this._currentIndex === this._endIndex || (this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') && this._string.charAt(this._currentIndex) !== '.') {
+ // The first character of a number must be one of [0-9+-.].
+ return undefined;
+ } // Read the integer part, build right-to-left.
+
+
+ var startIntPartIndex = this._currentIndex;
+
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {
+ this._currentIndex++; // Advance to first non-digit.
+ }
+
+ if (this._currentIndex !== startIntPartIndex) {
+ var scanIntPartIndex = this._currentIndex - 1;
+ var multiplier = 1;
+
+ while (scanIntPartIndex >= startIntPartIndex) {
+ integer += multiplier * (this._string.charAt(scanIntPartIndex--) - '0');
+ multiplier *= 10;
+ }
+ } // Read the decimals.
+
+
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '.') {
+ this._currentIndex++; // There must be a least one digit following the .
+
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') {
+ return undefined;
+ }
+
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {
+ frac *= 10;
+ decimal += (this._string.charAt(this._currentIndex) - '0') / frac;
+ this._currentIndex += 1;
+ }
+ } // Read the exponent part.
+
+
+ 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') {
+ this._currentIndex++; // Read the sign of the exponent.
+
+ if (this._string.charAt(this._currentIndex) === '+') {
+ this._currentIndex++;
+ } else if (this._string.charAt(this._currentIndex) === '-') {
+ this._currentIndex++;
+ expsign = -1;
+ } // There must be an exponent.
+
+
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') {
+ return undefined;
+ }
+
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {
+ exponent *= 10;
+ exponent += this._string.charAt(this._currentIndex) - '0';
+ this._currentIndex++;
+ }
+ }
+
+ var number = integer + decimal;
+ number *= sign;
+
+ if (exponent) {
+ number *= Math.pow(10, expsign * exponent);
+ }
+
+ if (startIndex === this._currentIndex) {
+ return undefined;
+ }
+
+ this._skipOptionalSpacesOrDelimiter();
+
+ return number;
+ }
+ }, {
+ key: "_parseArcFlag",
+ value: function _parseArcFlag() {
+ if (this._currentIndex >= this._endIndex) {
+ return undefined;
+ }
+
+ var flag = false;
+
+ var flagChar = this._string.charAt(this._currentIndex++);
+
+ if (flagChar === '0') {
+ flag = false;
+ } else if (flagChar === '1') {
+ flag = true;
+ } else {
+ return undefined;
+ }
+
+ this._skipOptionalSpacesOrDelimiter();
+
+ return flag;
+ }
+ }, {
+ key: "parseSegment",
+ value: function parseSegment() {
+ var lookahead = this._string[this._currentIndex];
+
+ var command = this._pathSegTypeFromChar(lookahead);
+
+ if (command === SVGPathSeg.PATHSEG_UNKNOWN) {
+ // Possibly an implicit command. Not allowed if this is the first command.
+ if (this._previousCommand === SVGPathSeg.PATHSEG_UNKNOWN) {
+ return null;
+ }
+
+ command = this._nextCommandHelper(lookahead, this._previousCommand);
+
+ if (command === SVGPathSeg.PATHSEG_UNKNOWN) {
+ return null;
+ }
+ } else {
+ this._currentIndex++;
+ }
+
+ this._previousCommand = command;
+
+ switch (command) {
+ case SVGPathSeg.PATHSEG_MOVETO_REL:
+ return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_MOVETO_ABS:
+ return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_LINETO_REL:
+ return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_LINETO_ABS:
+ return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
+ return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
+ return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
+ return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
+ return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_CLOSEPATH:
+ this._skipOptionalSpaces();
+
+ return new SVGPathSegClosePath(owningPathSegList);
+
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
+ {
+ var points = {
+ x1: this._parseNumber(),
+ y1: this._parseNumber(),
+ x2: this._parseNumber(),
+ y2: this._parseNumber(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+ }
+
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
+ {
+ var _points = {
+ x1: this._parseNumber(),
+ y1: this._parseNumber(),
+ x2: this._parseNumber(),
+ y2: this._parseNumber(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegCurvetoCubicAbs(owningPathSegList, _points.x, _points.y, _points.x1, _points.y1, _points.x2, _points.y2);
+ }
+
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+ {
+ var _points2 = {
+ x2: this._parseNumber(),
+ y2: this._parseNumber(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, _points2.x, _points2.y, _points2.x2, _points2.y2);
+ }
+
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+ {
+ var _points3 = {
+ x2: this._parseNumber(),
+ y2: this._parseNumber(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, _points3.x, _points3.y, _points3.x2, _points3.y2);
+ }
+
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
+ {
+ var _points4 = {
+ x1: this._parseNumber(),
+ y1: this._parseNumber(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, _points4.x, _points4.y, _points4.x1, _points4.y1);
+ }
+
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
+ {
+ var _points5 = {
+ x1: this._parseNumber(),
+ y1: this._parseNumber(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, _points5.x, _points5.y, _points5.x1, _points5.y1);
+ }
+
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+ return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+ return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+
+ case SVGPathSeg.PATHSEG_ARC_REL:
+ {
+ var _points6 = {
+ x1: this._parseNumber(),
+ y1: this._parseNumber(),
+ arcAngle: this._parseNumber(),
+ arcLarge: this._parseArcFlag(),
+ arcSweep: this._parseArcFlag(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegArcRel(owningPathSegList, _points6.x, _points6.y, _points6.x1, _points6.y1, _points6.arcAngle, _points6.arcLarge, _points6.arcSweep);
+ }
+
+ case SVGPathSeg.PATHSEG_ARC_ABS:
+ {
+ var _points7 = {
+ x1: this._parseNumber(),
+ y1: this._parseNumber(),
+ arcAngle: this._parseNumber(),
+ arcLarge: this._parseArcFlag(),
+ arcSweep: this._parseArcFlag(),
+ x: this._parseNumber(),
+ y: this._parseNumber()
+ };
+ return new SVGPathSegArcAbs(owningPathSegList, _points7.x, _points7.y, _points7.x1, _points7.y1, _points7.arcAngle, _points7.arcLarge, _points7.arcSweep);
+ }
+
+ default:
+ throw new Error('Unknown path seg type.');
+ }
+ }
+ }]);
+
+ return Source;
+ }();
+
+ var builder = new Builder();
+ var source = new Source(string);
+
+ if (!source.initialCommandIsMoveTo()) {
+ return [];
+ }
+
+ while (source.hasMoreData()) {
+ var pathSeg = source.parseSegment();
+
+ if (!pathSeg) {
+ return [];
+ }
+
+ builder.appendSegment(pathSeg);
+ }
+
+ return builder.pathSegList;
+ } // STATIC
+
+ }], [{
+ key: "_pathSegArrayAsString",
+ value: function _pathSegArrayAsString(pathSegArray) {
+ var string = '';
+ var first = true;
+ pathSegArray.forEach(function (pathSeg) {
+ if (first) {
+ first = false;
+ string += pathSeg._asPathString();
+ } else {
+ string += ' ' + pathSeg._asPathString();
+ }
+ });
+ return string;
+ }
+ }]);
+
+ return SVGPathSegList;
+ }();
+
+ SVGPathSegList.prototype.classname = 'SVGPathSegList';
+ Object.defineProperty(SVGPathSegList.prototype, 'numberOfItems', {
+ get: function get() {
+ this._checkPathSynchronizedToList();
+
+ return this._list.length;
+ },
+ enumerable: true
+ }); // Add the pathSegList accessors to SVGPathElement.
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
+
+ Object.defineProperties(SVGPathElement.prototype, {
+ pathSegList: {
+ get: function get() {
+ if (!this._pathSegList) {
+ this._pathSegList = new SVGPathSegList(this);
+ }
+
+ return this._pathSegList;
+ },
+ enumerable: true
+ },
+ // TODO: The following are not implemented and simply return SVGPathElement.pathSegList.
+ normalizedPathSegList: {
+ get: function get() {
+ return this.pathSegList;
+ },
+ enumerable: true
+ },
+ animatedPathSegList: {
+ get: function get() {
+ return this.pathSegList;
+ },
+ enumerable: true
+ },
+ animatedNormalizedPathSegList: {
+ get: function get() {
+ return this.pathSegList;
+ },
+ enumerable: true
+ }
+ });
+ window.SVGPathSegList = SVGPathSegList;
+ }
+ })();
+
+ var $ = jQuery;
+
+ var supportsSVG_ = function () {
+ return Boolean(document.createElementNS && document.createElementNS(NS.SVG, 'svg').createSVGRect);
+ }();
+ var _navigator = navigator,
+ userAgent = _navigator.userAgent;
+ var svg = document.createElementNS(NS.SVG, 'svg'); // Note: Browser sniffing should only be used if no other detection method is possible
+
+ var isOpera_ = Boolean(window.opera);
+ var isWebkit_ = userAgent.includes('AppleWebKit');
+ var isGecko_ = userAgent.includes('Gecko/');
+ var isIE_ = userAgent.includes('MSIE');
+ var isChrome_ = userAgent.includes('Chrome/');
+ var isWindows_ = userAgent.includes('Windows');
+ var isMac_ = userAgent.includes('Macintosh');
+ var isTouch_ = ('ontouchstart' in window);
+
+ var supportsSelectors_ = function () {
+ return Boolean(svg.querySelector);
+ }();
+
+ var supportsXpath_ = function () {
+ return Boolean(document.evaluate);
+ }(); // segList functions (for FF1.5 and 2.0)
+
+
+ var supportsPathReplaceItem_ = function () {
+ var path = document.createElementNS(NS.SVG, 'path');
+ path.setAttribute('d', 'M0,0 10,10');
+ var seglist = path.pathSegList;
+ var seg = path.createSVGPathSegLinetoAbs(5, 5);
+
+ try {
+ seglist.replaceItem(seg, 1);
+ return true;
+ } catch (err) {}
+
+ return false;
+ }();
+
+ var supportsPathInsertItemBefore_ = function () {
+ var path = document.createElementNS(NS.SVG, 'path');
+ path.setAttribute('d', 'M0,0 10,10');
+ var seglist = path.pathSegList;
+ var seg = path.createSVGPathSegLinetoAbs(5, 5);
+
+ try {
+ seglist.insertItemBefore(seg, 1);
+ return true;
+ } catch (err) {}
+
+ return false;
+ }(); // text character positioning (for IE9 and now Chrome)
+
+
+ var supportsGoodTextCharPos_ = function () {
+ var svgroot = document.createElementNS(NS.SVG, 'svg');
+ var svgcontent = document.createElementNS(NS.SVG, 'svg');
+ document.documentElement.append(svgroot);
+ svgcontent.setAttribute('x', 5);
+ svgroot.append(svgcontent);
+ var text = document.createElementNS(NS.SVG, 'text');
+ text.textContent = 'a';
+ svgcontent.append(text);
+
+ try {
+ // Chrome now fails here
+ var pos = text.getStartPositionOfChar(0).x;
+ return pos === 0;
+ } catch (err) {
+ return false;
+ } finally {
+ svgroot.remove();
+ }
+ }();
+
+ var supportsPathBBox_ = function () {
+ var svgcontent = document.createElementNS(NS.SVG, 'svg');
+ document.documentElement.append(svgcontent);
+ var path = document.createElementNS(NS.SVG, 'path');
+ path.setAttribute('d', 'M0,0 C0,0 10,10 10,0');
+ svgcontent.append(path);
+ var bbox = path.getBBox();
+ svgcontent.remove();
+ return bbox.height > 4 && bbox.height < 5;
+ }(); // Support for correct bbox sizing on groups with horizontal/vertical lines
+
+
+ var supportsHVLineContainerBBox_ = function () {
+ var svgcontent = document.createElementNS(NS.SVG, 'svg');
+ document.documentElement.append(svgcontent);
+ var path = document.createElementNS(NS.SVG, 'path');
+ path.setAttribute('d', 'M0,0 10,0');
+ var path2 = document.createElementNS(NS.SVG, 'path');
+ path2.setAttribute('d', 'M5,0 15,0');
+ var g = document.createElementNS(NS.SVG, 'g');
+ g.append(path, path2);
+ svgcontent.append(g);
+ var bbox = g.getBBox();
+ svgcontent.remove(); // Webkit gives 0, FF gives 10, Opera (correctly) gives 15
+
+ return bbox.width === 15;
+ }();
+
+ var supportsGoodDecimals_ = function () {
+ // Correct decimals on clone attributes (Opera < 10.5/win/non-en)
+ var rect = document.createElementNS(NS.SVG, 'rect');
+ rect.setAttribute('x', 0.1);
+ var crect = rect.cloneNode(false);
+ var retValue = !crect.getAttribute('x').includes(',');
+
+ if (!retValue) {
+ // Todo: i18nize or remove
+ $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' + 'Please upgrade to the latest version in which the problems have been fixed.');
+ }
+
+ return retValue;
+ }();
+
+ var supportsNonScalingStroke_ = function () {
+ var rect = document.createElementNS(NS.SVG, 'rect');
+ rect.setAttribute('style', 'vector-effect:non-scaling-stroke');
+ return rect.style.vectorEffect === 'non-scaling-stroke';
+ }();
+
+ var supportsNativeSVGTransformLists_ = function () {
+ var rect = document.createElementNS(NS.SVG, 'rect');
+ var rxform = rect.transform.baseVal;
+ var t1 = svg.createSVGTransform();
+ rxform.appendItem(t1);
+ var r1 = rxform.getItem(0);
+
+ var isSVGTransform = function isSVGTransform(o) {
+ // https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform
+ return o && _typeof(o) === 'object' && typeof o.setMatrix === 'function' && 'angle' in o;
+ };
+
+ return isSVGTransform(r1) && isSVGTransform(t1) && r1.type === t1.type && r1.angle === t1.angle && r1.matrix.a === t1.matrix.a && r1.matrix.b === t1.matrix.b && r1.matrix.c === t1.matrix.c && r1.matrix.d === t1.matrix.d && r1.matrix.e === t1.matrix.e && r1.matrix.f === t1.matrix.f;
+ }(); // Public API
+
+ /**
+ * @function module:browser.isOpera
+ * @returns {boolean}
+ */
+
+
+ var isOpera = function isOpera() {
+ return isOpera_;
+ };
+ /**
+ * @function module:browser.isWebkit
+ * @returns {boolean}
+ */
+
+ var isWebkit = function isWebkit() {
+ return isWebkit_;
+ };
+ /**
+ * @function module:browser.isGecko
+ * @returns {boolean}
+ */
+
+ var isGecko = function isGecko() {
+ return isGecko_;
+ };
+ /**
+ * @function module:browser.isIE
+ * @returns {boolean}
+ */
+
+ var isIE = function isIE() {
+ return isIE_;
+ };
+ /**
+ * @function module:browser.isChrome
+ * @returns {boolean}
+ */
+
+ var isChrome = function isChrome() {
+ return isChrome_;
+ };
+ /**
+ * @function module:browser.isMac
+ * @returns {boolean}
+ */
+
+ var isMac = function isMac() {
+ return isMac_;
+ };
+ /**
+ * @function module:browser.isTouch
+ * @returns {boolean}
+ */
+
+ var isTouch = function isTouch() {
+ return isTouch_;
+ };
+ /**
+ * @function module:browser.supportsSelectors
+ * @returns {boolean}
+ */
+
+ var supportsSelectors = function supportsSelectors() {
+ return supportsSelectors_;
+ };
+ /**
+ * @function module:browser.supportsXpath
+ * @returns {boolean}
+ */
+
+ var supportsXpath = function supportsXpath() {
+ return supportsXpath_;
+ };
+ /**
+ * @function module:browser.supportsPathReplaceItem
+ * @returns {boolean}
+ */
+
+ var supportsPathReplaceItem = function supportsPathReplaceItem() {
+ return supportsPathReplaceItem_;
+ };
+ /**
+ * @function module:browser.supportsPathInsertItemBefore
+ * @returns {boolean}
+ */
+
+ var supportsPathInsertItemBefore = function supportsPathInsertItemBefore() {
+ return supportsPathInsertItemBefore_;
+ };
+ /**
+ * @function module:browser.supportsPathBBox
+ * @returns {boolean}
+ */
+
+ var supportsPathBBox = function supportsPathBBox() {
+ return supportsPathBBox_;
+ };
+ /**
+ * @function module:browser.supportsHVLineContainerBBox
+ * @returns {boolean}
+ */
+
+ var supportsHVLineContainerBBox = function supportsHVLineContainerBBox() {
+ return supportsHVLineContainerBBox_;
+ };
+ /**
+ * @function module:browser.supportsGoodTextCharPos
+ * @returns {boolean}
+ */
+
+ var supportsGoodTextCharPos = function supportsGoodTextCharPos() {
+ return supportsGoodTextCharPos_;
+ };
+ /**
+ * @function module:browser.supportsNonScalingStroke
+ * @returns {boolean}
+ */
+
+ var supportsNonScalingStroke = function supportsNonScalingStroke() {
+ return supportsNonScalingStroke_;
+ };
+ /**
+ * @function module:browser.supportsNativeTransformLists
+ * @returns {boolean}
+ */
+
+ var supportsNativeTransformLists = function supportsNativeTransformLists() {
+ return supportsNativeSVGTransformLists_;
+ };
+
+ /**
+ * A jQuery module to work with SVG attributes.
+ * @module jQueryAttr
+ * @license MIT
+ */
+
+ /**
+ * This fixes `$(...).attr()` to work as expected with SVG elements.
+ * Does not currently use `*AttributeNS()` since we rarely need that.
+ * Adds {@link external:jQuery.fn.attr}.
+ * See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()`.
+ *
+ * Additional functionality:
+ * - When getting attributes, a string that's a number is returned as type number.
+ * - If an array is supplied as the first parameter, multiple values are returned
+ * as an object with values for each given attribute.
+ * @function module:jQueryAttr.jQueryAttr
+ * @param {external:jQuery} $ The jQuery object to which to add the plug-in
+ * @returns {external:jQuery}
+ */
+ function jQueryPluginSVG($) {
+ var proxied = $.fn.attr,
+ svgns = 'http://www.w3.org/2000/svg';
+ /**
+ * @typedef {PlainObject} module:jQueryAttr.Attributes
+ */
+
+ /**
+ * @function external:jQuery.fn.attr
+ * @param {string|string[]|PlainObject} key
+ * @param {string} value
+ * @returns {external:jQuery|module:jQueryAttr.Attributes}
+ */
+
+ $.fn.attr = function (key, value) {
+ var len = this.length;
+
+ if (!len) {
+ return proxied.call(this, key, value);
+ }
+
+ for (var i = 0; i < len; ++i) {
+ var elem = this[i]; // set/get SVG attribute
+
+ if (elem.namespaceURI === svgns) {
+ // Setting attribute
+ if (value !== undefined) {
+ elem.setAttribute(key, value);
+ } else if (Array.isArray(key)) {
+ // Getting attributes from array
+ var obj = {};
+ var j = key.length;
+
+ while (j--) {
+ var aname = key[j];
+ var attr = elem.getAttribute(aname); // This returns a number when appropriate
+
+ if (attr || attr === '0') {
+ attr = isNaN(attr) ? attr : attr - 0;
+ }
+
+ obj[aname] = attr;
+ }
+
+ return obj;
+ }
+
+ if (_typeof(key) === 'object') {
+ // Setting attributes from object
+ for (var _i = 0, _Object$entries = Object.entries(key); _i < _Object$entries.length; _i++) {
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
+ name = _Object$entries$_i[0],
+ val = _Object$entries$_i[1];
+
+ elem.setAttribute(name, val);
+ } // Getting attribute
+
+ } else {
+ var _attr = elem.getAttribute(key);
+
+ if (_attr || _attr === '0') {
+ _attr = isNaN(_attr) ? _attr : _attr - 0;
+ }
+
+ return _attr;
+ }
+ } else {
+ return proxied.call(this, key, value);
+ }
+ }
+
+ return this;
+ };
+
+ return $;
+ }
+
+ var svgroot = document.createElementNS(NS.SVG, 'svg');
+ /**
+ * Helper function to convert `SVGTransform` to a string.
+ * @param {SVGTransform} xform
+ * @returns {string}
+ */
+
+ function transformToString(xform) {
+ var m = xform.matrix;
+ var text = '';
+
+ switch (xform.type) {
+ case 1:
+ // MATRIX
+ text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';
+ break;
+
+ case 2:
+ // TRANSLATE
+ text = 'translate(' + m.e + ',' + m.f + ')';
+ break;
+
+ case 3:
+ // SCALE
+ if (m.a === m.d) {
+ text = 'scale(' + m.a + ')';
+ } else {
+ text = 'scale(' + m.a + ',' + m.d + ')';
+ }
+
+ break;
+
+ case 4:
+ {
+ // ROTATE
+ var cx = 0;
+ var cy = 0; // this prevents divide by zero
+
+ if (xform.angle !== 0) {
+ var K = 1 - m.a;
+ cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);
+ cx = (m.e - m.b * cy) / K;
+ }
+
+ text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';
+ break;
+ }
+ }
+
+ return text;
+ }
+ /**
+ * Map of SVGTransformList objects.
+ */
+
+
+ var listMap_ = {};
+ /**
+ * @interface module:SVGTransformList.SVGEditTransformList
+ * @property {Integer} numberOfItems unsigned long
+ */
+
+ /**
+ * @function module:SVGTransformList.SVGEditTransformList#clear
+ * @returns {void}
+ */
+
+ /**
+ * @function module:SVGTransformList.SVGEditTransformList#initialize
+ * @param {SVGTransform} newItem
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * DOES NOT THROW DOMException, INDEX_SIZE_ERR.
+ * @function module:SVGTransformList.SVGEditTransformList#getItem
+ * @param {Integer} index unsigned long
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * DOES NOT THROW DOMException, INDEX_SIZE_ERR.
+ * @function module:SVGTransformList.SVGEditTransformList#insertItemBefore
+ * @param {SVGTransform} newItem
+ * @param {Integer} index unsigned long
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * DOES NOT THROW DOMException, INDEX_SIZE_ERR.
+ * @function module:SVGTransformList.SVGEditTransformList#replaceItem
+ * @param {SVGTransform} newItem
+ * @param {Integer} index unsigned long
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * DOES NOT THROW DOMException, INDEX_SIZE_ERR.
+ * @function module:SVGTransformList.SVGEditTransformList#removeItem
+ * @param {Integer} index unsigned long
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * @function module:SVGTransformList.SVGEditTransformList#appendItem
+ * @param {SVGTransform} newItem
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * NOT IMPLEMENTED.
+ * @ignore
+ * @function module:SVGTransformList.SVGEditTransformList#createSVGTransformFromMatrix
+ * @param {SVGMatrix} matrix
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * NOT IMPLEMENTED.
+ * @ignore
+ * @function module:SVGTransformList.SVGEditTransformList#consolidate
+ * @returns {SVGTransform}
+ */
+
+ /**
+ * SVGTransformList implementation for Webkit.
+ * These methods do not currently raise any exceptions.
+ * These methods also do not check that transforms are being inserted. This is basically
+ * implementing as much of SVGTransformList that we need to get the job done.
+ * @implements {module:SVGTransformList.SVGEditTransformList}
+ */
+
+ var SVGTransformList = /*#__PURE__*/function () {
+ // eslint-disable-line no-shadow
+
+ /**
+ * @param {Element} elem
+ * @returns {SVGTransformList}
+ */
+ function SVGTransformList(elem) {
+ _classCallCheck(this, SVGTransformList);
+
+ this._elem = elem || null;
+ this._xforms = []; // TODO: how do we capture the undo-ability in the changed transform list?
+
+ this._update = function () {
+ var tstr = ''; // /* const concatMatrix = */ svgroot.createSVGMatrix();
+
+ for (var i = 0; i < this.numberOfItems; ++i) {
+ var xform = this._list.getItem(i);
+
+ tstr += transformToString(xform) + ' ';
+ }
+
+ this._elem.setAttribute('transform', tstr);
+ };
+
+ this._list = this;
+
+ this._init = function () {
+ var _this = this;
+
+ // Transform attribute parser
+ var str = this._elem.getAttribute('transform');
+
+ if (!str) {
+ return;
+ } // TODO: Add skew support in future
+
+
+ var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/; // const re = /\s*(?(?:scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
+
+ var m = true;
+
+ while (m) {
+ m = str.match(re);
+ str = str.replace(re, '');
+
+ if (m && m[1]) {
+ (function () {
+ var x = m[1];
+ var bits = x.split(/\s*\(/);
+ var name = bits[0];
+ var valBits = bits[1].match(/\s*(.*?)\s*\)/);
+ valBits[1] = valBits[1].replace(/(\d)-/g, '$1 -');
+ var valArr = valBits[1].split(/[, ]+/);
+ var letters = 'abcdef'.split('');
+ /*
+ if (m && m.groups.xform) {
+ const x = m.groups.xform;
+ const [name, bits] = x.split(/\s*\(/);
+ const valBits = bits.match(/\s*(?.*?)\s*\)/);
+ valBits.groups.nonWhitespace = valBits.groups.nonWhitespace.replace(
+ /(?\d)-/g, '$ -'
+ );
+ const valArr = valBits.groups.nonWhitespace.split(/[, ]+/);
+ const letters = [...'abcdef'];
+ */
+
+ var mtx = svgroot.createSVGMatrix();
+ Object.values(valArr).forEach(function (item, i) {
+ valArr[i] = Number.parseFloat(item);
+
+ if (name === 'matrix') {
+ mtx[letters[i]] = valArr[i];
+ }
+ });
+ var xform = svgroot.createSVGTransform();
+ var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
+ var values = name === 'matrix' ? [mtx] : valArr;
+
+ if (name === 'scale' && values.length === 1) {
+ values.push(values[0]);
+ } else if (name === 'translate' && values.length === 1) {
+ values.push(0);
+ } else if (name === 'rotate' && values.length === 1) {
+ values.push(0, 0);
+ }
+
+ xform[fname].apply(xform, _toConsumableArray(values));
+
+ _this._list.appendItem(xform);
+ })();
+ }
+ }
+ };
+
+ this._removeFromOtherLists = function (item) {
+ if (item) {
+ // Check if this transform is already in a transformlist, and
+ // remove it if so.
+ Object.values(listMap_).some(function (tl) {
+ for (var i = 0, len = tl._xforms.length; i < len; ++i) {
+ if (tl._xforms[i] === item) {
+ tl.removeItem(i);
+ return true;
+ }
+ }
+
+ return false;
+ });
+ }
+ };
+
+ this.numberOfItems = 0;
+ }
+ /**
+ * @returns {void}
+ */
+
+
+ _createClass(SVGTransformList, [{
+ key: "clear",
+ value: function clear() {
+ this.numberOfItems = 0;
+ this._xforms = [];
+ }
+ /**
+ * @param {SVGTransform} newItem
+ * @returns {void}
+ */
+
+ }, {
+ key: "initialize",
+ value: function initialize(newItem) {
+ this.numberOfItems = 1;
+
+ this._removeFromOtherLists(newItem);
+
+ this._xforms = [newItem];
+ }
+ /**
+ * @param {Integer} index unsigned long
+ * @throws {Error}
+ * @returns {SVGTransform}
+ */
+
+ }, {
+ key: "getItem",
+ value: function getItem(index) {
+ if (index < this.numberOfItems && index >= 0) {
+ return this._xforms[index];
+ }
+
+ var err = new Error('DOMException with code=INDEX_SIZE_ERR');
+ err.code = 1;
+ throw err;
+ }
+ /**
+ * @param {SVGTransform} newItem
+ * @param {Integer} index unsigned long
+ * @returns {SVGTransform}
+ */
+
+ }, {
+ key: "insertItemBefore",
+ value: function insertItemBefore(newItem, index) {
+ var retValue = null;
+
+ if (index >= 0) {
+ if (index < this.numberOfItems) {
+ this._removeFromOtherLists(newItem);
+
+ var newxforms = new Array(this.numberOfItems + 1); // TODO: use array copying and slicing
+
+ var i;
+
+ for (i = 0; i < index; ++i) {
+ newxforms[i] = this._xforms[i];
+ }
+
+ newxforms[i] = newItem;
+
+ for (var j = i + 1; i < this.numberOfItems; ++j, ++i) {
+ newxforms[j] = this._xforms[i];
+ }
+
+ this.numberOfItems++;
+ this._xforms = newxforms;
+ retValue = newItem;
+
+ this._list._update();
+ } else {
+ retValue = this._list.appendItem(newItem);
+ }
+ }
+
+ return retValue;
+ }
+ /**
+ * @param {SVGTransform} newItem
+ * @param {Integer} index unsigned long
+ * @returns {SVGTransform}
+ */
+
+ }, {
+ key: "replaceItem",
+ value: function replaceItem(newItem, index) {
+ var retValue = null;
+
+ if (index < this.numberOfItems && index >= 0) {
+ this._removeFromOtherLists(newItem);
+
+ this._xforms[index] = newItem;
+ retValue = newItem;
+
+ this._list._update();
+ }
+
+ return retValue;
+ }
+ /**
+ * @param {Integer} index unsigned long
+ * @throws {Error}
+ * @returns {SVGTransform}
+ */
+
+ }, {
+ key: "removeItem",
+ value: function removeItem(index) {
+ if (index < this.numberOfItems && index >= 0) {
+ var retValue = this._xforms[index];
+ var newxforms = new Array(this.numberOfItems - 1);
+ var i;
+
+ for (i = 0; i < index; ++i) {
+ newxforms[i] = this._xforms[i];
+ }
+
+ for (var j = i; j < this.numberOfItems - 1; ++j, ++i) {
+ newxforms[j] = this._xforms[i + 1];
+ }
+
+ this.numberOfItems--;
+ this._xforms = newxforms;
+
+ this._list._update();
+
+ return retValue;
+ }
+
+ var err = new Error('DOMException with code=INDEX_SIZE_ERR');
+ err.code = 1;
+ throw err;
+ }
+ /**
+ * @param {SVGTransform} newItem
+ * @returns {SVGTransform}
+ */
+
+ }, {
+ key: "appendItem",
+ value: function appendItem(newItem) {
+ this._removeFromOtherLists(newItem);
+
+ this._xforms.push(newItem);
+
+ this.numberOfItems++;
+
+ this._list._update();
+
+ return newItem;
+ }
+ }]);
+
+ return SVGTransformList;
+ }();
+ /**
+ * @function module:SVGTransformList.resetListMap
+ * @returns {void}
+ */
+
+ var resetListMap = function resetListMap() {
+ listMap_ = {};
+ };
+ /**
+ * Removes transforms of the given element from the map.
+ * @function module:SVGTransformList.removeElementFromListMap
+ * @param {Element} elem - a DOM Element
+ * @returns {void}
+ */
+
+ var removeElementFromListMap = function removeElementFromListMap(elem) {
+ // eslint-disable-line import/no-mutable-exports
+ if (elem.id && listMap_[elem.id]) {
+ delete listMap_[elem.id];
+ }
+ };
+ /**
+ * Returns an object that behaves like a `SVGTransformList` for the given DOM element.
+ * @function module:SVGTransformList.getTransformList
+ * @param {Element} elem - DOM element to get a transformlist from
+ * @todo The polyfill should have `SVGAnimatedTransformList` and this should use it
+ * @returns {SVGAnimatedTransformList|SVGTransformList}
+ */
+
+ var getTransformList = function getTransformList(elem) {
+ if (!supportsNativeTransformLists()) {
+ var id = elem.id || 'temp';
+ var t = listMap_[id];
+
+ if (!t || id === 'temp') {
+ listMap_[id] = new SVGTransformList(elem);
+
+ listMap_[id]._init();
+
+ t = listMap_[id];
+ }
+
+ return t;
+ }
+
+ if (elem.transform) {
+ return elem.transform.baseVal;
+ }
+
+ if (elem.gradientTransform) {
+ return elem.gradientTransform.baseVal;
+ }
+
+ if (elem.patternTransform) {
+ return elem.patternTransform.baseVal;
+ }
+
+ return null;
+ };
+
+ /**
+ * Tools for working with units.
+ * @module units
+ * @license MIT
+ *
+ * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
+ */
+ var wAttrs = ['x', 'x1', 'cx', 'rx', 'width'];
+ var hAttrs = ['y', 'y1', 'cy', 'ry', 'height'];
+ var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs); // unused
+
+ /*
+ const unitNumMap = {
+ '%': 2,
+ em: 3,
+ ex: 4,
+ px: 5,
+ cm: 6,
+ mm: 7,
+ in: 8,
+ pt: 9,
+ pc: 10
+ };
+ */
+ // Container of elements.
+
+ var elementContainer_; // Stores mapping of unit type to user coordinates.
+
+ var typeMap_ = {};
+ /**
+ * @interface module:units.ElementContainer
+ */
+
+ /**
+ * @function module:units.ElementContainer#getBaseUnit
+ * @returns {string} The base unit type of the container ('em')
+ */
+
+ /**
+ * @function module:units.ElementContainer#getElement
+ * @returns {?Element} An element in the container given an id
+ */
+
+ /**
+ * @function module:units.ElementContainer#getHeight
+ * @returns {Float} The container's height
+ */
+
+ /**
+ * @function module:units.ElementContainer#getWidth
+ * @returns {Float} The container's width
+ */
+
+ /**
+ * @function module:units.ElementContainer#getRoundDigits
+ * @returns {Integer} The number of digits number should be rounded to
+ */
+
+ /* eslint-disable jsdoc/valid-types */
+
+ /**
+ * @typedef {PlainObject} module:units.TypeMap
+ * @property {Float} em
+ * @property {Float} ex
+ * @property {Float} in
+ * @property {Float} cm
+ * @property {Float} mm
+ * @property {Float} pt
+ * @property {Float} pc
+ * @property {Integer} px
+ * @property {0} %
+ */
+
+ /* eslint-enable jsdoc/valid-types */
+
+ /**
+ * Initializes this module.
+ *
+ * @function module:units.init
+ * @param {module:units.ElementContainer} elementContainer - An object implementing the ElementContainer interface.
+ * @returns {void}
+ */
+
+ var init = function init(elementContainer) {
+ elementContainer_ = elementContainer; // Get correct em/ex values by creating a temporary SVG.
+
+ var svg = document.createElementNS(NS.SVG, 'svg');
+ document.body.append(svg);
+ var rect = document.createElementNS(NS.SVG, 'rect');
+ rect.setAttribute('width', '1em');
+ rect.setAttribute('height', '1ex');
+ rect.setAttribute('x', '1in');
+ svg.append(rect);
+ var bb = rect.getBBox();
+ svg.remove();
+ var inch = bb.x;
+ typeMap_ = {
+ em: bb.width,
+ ex: bb.height,
+ "in": inch,
+ cm: inch / 2.54,
+ mm: inch / 25.4,
+ pt: inch / 72,
+ pc: inch / 6,
+ px: 1,
+ '%': 0
+ };
+ };
+ /**
+ * Group: Unit conversion functions.
+ */
+
+ /**
+ * @function module:units.getTypeMap
+ * @returns {module:units.TypeMap} The unit object with values for each unit
+ */
+
+ var getTypeMap = function getTypeMap() {
+ return typeMap_;
+ };
+ /**
+ * @typedef {GenericArray} module:units.CompareNumbers
+ * @property {Integer} length 2
+ * @property {Float} 0
+ * @property {Float} 1
+ */
+
+ /**
+ * Rounds a given value to a float with number of digits defined in
+ * `round_digits` of `saveOptions`
+ *
+ * @function module:units.shortFloat
+ * @param {string|Float|module:units.CompareNumbers} val - The value (or Array of two numbers) to be rounded
+ * @returns {Float|string} If a string/number was given, returns a Float. If an array, return a string
+ * with comma-separated floats
+ */
+
+ var shortFloat = function shortFloat(val) {
+ var digits = elementContainer_.getRoundDigits();
+
+ if (!isNaN(val)) {
+ return Number(Number(val).toFixed(digits));
+ }
+
+ if (Array.isArray(val)) {
+ return shortFloat(val[0]) + ',' + shortFloat(val[1]);
+ }
+
+ return Number.parseFloat(val).toFixed(digits) - 0;
+ };
+ /**
+ * Converts the number to given unit or baseUnit.
+ * @function module:units.convertUnit
+ * @param {string|Float} val
+ * @param {"em"|"ex"|"in"|"cm"|"mm"|"pt"|"pc"|"px"|"%"} [unit]
+ * @returns {Float}
+ */
+
+ var convertUnit = function convertUnit(val, unit) {
+ unit = unit || elementContainer_.getBaseUnit(); // baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
+ // const val = baseVal.valueInSpecifiedUnits;
+ // baseVal.convertToSpecifiedUnits(1);
+
+ return shortFloat(val / typeMap_[unit]);
+ };
+ /**
+ * Sets an element's attribute based on the unit in its current value.
+ *
+ * @function module:units.setUnitAttr
+ * @param {Element} elem - DOM element to be changed
+ * @param {string} attr - Name of the attribute associated with the value
+ * @param {string} val - Attribute value to convert
+ * @returns {void}
+ */
+
+ var setUnitAttr = function setUnitAttr(elem, attr, val) {
+ // if (!isNaN(val)) {
+ // New value is a number, so check currently used unit
+ // const oldVal = elem.getAttribute(attr);
+ // Enable this for alternate mode
+ // if (oldVal !== null && (isNaN(oldVal) || elementContainer_.getBaseUnit() !== 'px')) {
+ // // Old value was a number, so get unit, then convert
+ // let unit;
+ // if (oldVal.substr(-1) === '%') {
+ // const res = getResolution();
+ // unit = '%';
+ // val *= 100;
+ // if (wAttrs.includes(attr)) {
+ // val = val / res.w;
+ // } else if (hAttrs.includes(attr)) {
+ // val = val / res.h;
+ // } else {
+ // return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);
+ // }
+ // } else {
+ // if (elementContainer_.getBaseUnit() !== 'px') {
+ // unit = elementContainer_.getBaseUnit();
+ // } else {
+ // unit = oldVal.substr(-2);
+ // }
+ // val = val / typeMap_[unit];
+ // }
+ //
+ // val += unit;
+ // }
+ // }
+ elem.setAttribute(attr, val);
+ };
+ /**
+ * Converts given values to numbers. Attributes must be supplied in
+ * case a percentage is given.
+ *
+ * @function module:units.convertToNum
+ * @param {string} attr - Name of the attribute associated with the value
+ * @param {string} val - Attribute value to convert
+ * @returns {Float} The converted number
+ */
+
+ var convertToNum = function convertToNum(attr, val) {
+ // Return a number if that's what it already is
+ if (!isNaN(val)) {
+ return val - 0;
+ }
+
+ if (val.substr(-1) === '%') {
+ // Deal with percentage, depends on attribute
+ var _num = val.substr(0, val.length - 1) / 100;
+
+ var width = elementContainer_.getWidth();
+ var height = elementContainer_.getHeight();
+
+ if (wAttrs.includes(attr)) {
+ return _num * width;
+ }
+
+ if (hAttrs.includes(attr)) {
+ return _num * height;
+ }
+
+ return _num * Math.sqrt(width * width + height * height) / Math.sqrt(2);
+ }
+
+ var unit = val.substr(-2);
+ var num = val.substr(0, val.length - 2); // Note that this multiplication turns the string into a number
+
+ return num * typeMap_[unit];
+ };
+ /**
+ * Check if an attribute's value is in a valid format.
+ * @function module:units.isValidUnit
+ * @param {string} attr - The name of the attribute associated with the value
+ * @param {string} val - The attribute value to check
+ * @param {Element} selectedElement
+ * @returns {boolean} Whether the unit is valid
+ */
+
+ var isValidUnit = function isValidUnit(attr, val, selectedElement) {
+ if (unitAttrs.includes(attr)) {
+ // True if it's just a number
+ if (!isNaN(val)) {
+ return true;
+ } // Not a number, check if it has a valid unit
+
+
+ val = val.toLowerCase();
+ return Object.keys(typeMap_).some(function (unit) {
+ var re = new RegExp('^-?[\\d\\.]+' + unit + '$');
+ return re.test(val);
+ });
+ }
+
+ if (attr === 'id') {
+ // if we're trying to change the id, make sure it's not already present in the doc
+ // and the id value is valid.
+ var result = false; // because getElem() can throw an exception in the case of an invalid id
+ // (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName)
+ // we wrap it in an exception and only return true if the ID was valid and
+ // not already present
+
+ try {
+ var elem = elementContainer_.getElement(val);
+ result = !elem || elem === selectedElement;
+ } catch (e) {}
+
+ return result;
+ }
+
+ return true;
+ };
+
+ /**
+ * Mathematical utilities.
+ * @module math
+ * @license MIT
+ *
+ * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
+ */
+
+ var NEAR_ZERO = 1e-14; // Throw away SVGSVGElement used for creating matrices/transforms.
+
+ var svg$1 = document.createElementNS(NS.SVG, 'svg');
+ /**
+ * A (hopefully) quicker function to transform a point by a matrix
+ * (this function avoids any DOM calls and just does the math).
+ * @function module:math.transformPoint
+ * @param {Float} x - Float representing the x coordinate
+ * @param {Float} y - Float representing the y coordinate
+ * @param {SVGMatrix} m - Matrix object to transform the point with
+ * @returns {module:math.XYObject} An x, y object representing the transformed point
+ */
+
+ var transformPoint = function transformPoint(x, y, m) {
+ return {
+ x: m.a * x + m.c * y + m.e,
+ y: m.b * x + m.d * y + m.f
+ };
+ };
+ /**
+ * Helper function to check if the matrix performs no actual transform
+ * (i.e. exists for identity purposes).
+ * @function module:math.isIdentity
+ * @param {SVGMatrix} m - The matrix object to check
+ * @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0
+ */
+
+ var isIdentity = function isIdentity(m) {
+ return m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0;
+ };
+ /**
+ * This function tries to return a `SVGMatrix` that is the multiplication `m1 * m2`.
+ * We also round to zero when it's near zero.
+ * @function module:math.matrixMultiply
+ * @param {...SVGMatrix} args - Matrix objects to multiply
+ * @returns {SVGMatrix} The matrix object resulting from the calculation
+ */
+
+ var matrixMultiply = function matrixMultiply() {
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var m = args.reduceRight(function (prev, m1) {
+ return m1.multiply(prev);
+ });
+
+ if (Math.abs(m.a) < NEAR_ZERO) {
+ m.a = 0;
+ }
+
+ if (Math.abs(m.b) < NEAR_ZERO) {
+ m.b = 0;
+ }
+
+ if (Math.abs(m.c) < NEAR_ZERO) {
+ m.c = 0;
+ }
+
+ if (Math.abs(m.d) < NEAR_ZERO) {
+ m.d = 0;
+ }
+
+ if (Math.abs(m.e) < NEAR_ZERO) {
+ m.e = 0;
+ }
+
+ if (Math.abs(m.f) < NEAR_ZERO) {
+ m.f = 0;
+ }
+
+ return m;
+ };
+ /**
+ * See if the given transformlist includes a non-indentity matrix transform.
+ * @function module:math.hasMatrixTransform
+ * @param {SVGTransformList} [tlist] - The transformlist to check
+ * @returns {boolean} Whether or not a matrix transform was found
+ */
+
+ var hasMatrixTransform = function hasMatrixTransform(tlist) {
+ if (!tlist) {
+ return false;
+ }
+
+ var num = tlist.numberOfItems;
+
+ while (num--) {
+ var xform = tlist.getItem(num);
+
+ if (xform.type === 1 && !isIdentity(xform.matrix)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+ /**
+ * @typedef {PlainObject} module:math.TransformedBox An object with the following values
+ * @property {module:math.XYObject} tl - The top left coordinate
+ * @property {module:math.XYObject} tr - The top right coordinate
+ * @property {module:math.XYObject} bl - The bottom left coordinate
+ * @property {module:math.XYObject} br - The bottom right coordinate
+ * @property {PlainObject} aabox - Object with the following values:
+ * @property {Float} aabox.x - Float with the axis-aligned x coordinate
+ * @property {Float} aabox.y - Float with the axis-aligned y coordinate
+ * @property {Float} aabox.width - Float with the axis-aligned width coordinate
+ * @property {Float} aabox.height - Float with the axis-aligned height coordinate
+ */
+
+ /**
+ * Transforms a rectangle based on the given matrix.
+ * @function module:math.transformBox
+ * @param {Float} l - Float with the box's left coordinate
+ * @param {Float} t - Float with the box's top coordinate
+ * @param {Float} w - Float with the box width
+ * @param {Float} h - Float with the box height
+ * @param {SVGMatrix} m - Matrix object to transform the box by
+ * @returns {module:math.TransformedBox}
+ */
+
+ var transformBox = function transformBox(l, t, w, h, m) {
+ var tl = transformPoint(l, t, m),
+ tr = transformPoint(l + w, t, m),
+ bl = transformPoint(l, t + h, m),
+ br = transformPoint(l + w, t + h, m),
+ minx = Math.min(tl.x, tr.x, bl.x, br.x),
+ maxx = Math.max(tl.x, tr.x, bl.x, br.x),
+ miny = Math.min(tl.y, tr.y, bl.y, br.y),
+ maxy = Math.max(tl.y, tr.y, bl.y, br.y);
+ return {
+ tl: tl,
+ tr: tr,
+ bl: bl,
+ br: br,
+ aabox: {
+ x: minx,
+ y: miny,
+ width: maxx - minx,
+ height: maxy - miny
+ }
+ };
+ };
+ /**
+ * This returns a single matrix Transform for a given Transform List
+ * (this is the equivalent of `SVGTransformList.consolidate()` but unlike
+ * that method, this one does not modify the actual `SVGTransformList`).
+ * This function is very liberal with its `min`, `max` arguments.
+ * @function module:math.transformListToTransform
+ * @param {SVGTransformList} tlist - The transformlist object
+ * @param {Integer} [min=0] - Optional integer indicating start transform position
+ * @param {Integer} [max] - Optional integer indicating end transform position;
+ * defaults to one less than the tlist's `numberOfItems`
+ * @returns {SVGTransform} A single matrix transform object
+ */
+
+ var transformListToTransform = function transformListToTransform(tlist, min, max) {
+ if (!tlist) {
+ // Or should tlist = null have been prevented before this?
+ return svg$1.createSVGTransformFromMatrix(svg$1.createSVGMatrix());
+ }
+
+ min = min || 0;
+ max = max || tlist.numberOfItems - 1;
+ min = Number.parseInt(min);
+ max = Number.parseInt(max);
+
+ if (min > max) {
+ var temp = max;
+ max = min;
+ min = temp;
+ }
+
+ var m = svg$1.createSVGMatrix();
+
+ for (var i = min; i <= max; ++i) {
+ // if our indices are out of range, just use a harmless identity matrix
+ var mtom = i >= 0 && i < tlist.numberOfItems ? tlist.getItem(i).matrix : svg$1.createSVGMatrix();
+ m = matrixMultiply(m, mtom);
+ }
+
+ return svg$1.createSVGTransformFromMatrix(m);
+ };
+ /**
+ * Get the matrix object for a given element.
+ * @function module:math.getMatrix
+ * @param {Element} elem - The DOM element to check
+ * @returns {SVGMatrix} The matrix object associated with the element's transformlist
+ */
+
+ var getMatrix = function getMatrix(elem) {
+ var tlist = getTransformList(elem);
+ return transformListToTransform(tlist).matrix;
+ };
+ /**
+ * Returns a 45 degree angle coordinate associated with the two given
+ * coordinates.
+ * @function module:math.snapToAngle
+ * @param {Integer} x1 - First coordinate's x value
+ * @param {Integer} y1 - First coordinate's y value
+ * @param {Integer} x2 - Second coordinate's x value
+ * @param {Integer} y2 - Second coordinate's y value
+ * @returns {module:math.AngleCoord45}
+ */
+
+ var snapToAngle = function snapToAngle(x1, y1, x2, y2) {
+ var snap = Math.PI / 4; // 45 degrees
+
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+ var angle = Math.atan2(dy, dx);
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var snapangle = Math.round(angle / snap) * snap;
+ return {
+ x: x1 + dist * Math.cos(snapangle),
+ y: y1 + dist * Math.sin(snapangle),
+ a: snapangle
+ };
+ };
+ /**
+ * Check if two rectangles (BBoxes objects) intersect each other.
+ * @function module:math.rectsIntersect
+ * @param {SVGRect} r1 - The first BBox-like object
+ * @param {SVGRect} r2 - The second BBox-like object
+ * @returns {boolean} True if rectangles intersect
+ */
+
+ var rectsIntersect = function rectsIntersect(r1, r2) {
+ return r2.x < r1.x + r1.width && r2.x + r2.width > r1.x && r2.y < r1.y + r1.height && r2.y + r2.height > r1.y;
+ };
+
+ var $$1 = jQueryPluginSVG(jQuery); // String used to encode base64.
+
+ var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; // Much faster than running getBBox() every time
+
+ var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use,clipPath';
+ var visElemsArr = visElems.split(','); // const hidElems = 'defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath';
+
+ var editorContext_ = null;
+ var domdoc_ = null;
+ var domcontainer_ = null;
+ var svgroot_ = null;
+ /**
+ * Object with the following keys/values.
+ * @typedef {PlainObject} module:utilities.SVGElementJSON
+ * @property {string} element - Tag name of the SVG element to create
+ * @property {PlainObject} 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.
+ * @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first
+ * @property {module:utilities.SVGElementJSON[]} [children] - Data objects to be added recursively as children
+ * @property {string} [namespace="http://www.w3.org/2000/svg"] - Indicate a (non-SVG) namespace
+ */
+
+ /**
+ * An object that creates SVG elements for the canvas.
+ *
+ * @interface module:utilities.EditorContext
+ * @property {module:path.pathActions} pathActions
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getSVGContent
+ * @returns {SVGSVGElement}
+ */
+
+ /**
+ * Create a new SVG element based on the given object keys/values and add it
+ * to the current layer.
+ * The element will be run through `cleanupElement` before being returned.
+ * @function module:utilities.EditorContext#addSVGElementFromJson
+ * @param {module:utilities.SVGElementJSON} data
+ * @returns {Element} The new element
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getSelectedElements
+ * @returns {Element[]} the array with selected DOM elements
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getDOMDocument
+ * @returns {HTMLDocument}
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getDOMContainer
+ * @returns {HTMLElement}
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getSVGRoot
+ * @returns {SVGSVGElement}
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getBaseUnit
+ * @returns {string}
+ */
+
+ /**
+ * @function module:utilities.EditorContext#getSnappingStep
+ * @returns {Float|string}
+ */
+
+ /**
+ * @function module:utilities.init
+ * @param {module:utilities.EditorContext} editorContext
+ * @returns {void}
+ */
+
+ var init$1 = function init(editorContext) {
+ editorContext_ = editorContext;
+ domdoc_ = editorContext.getDOMDocument();
+ domcontainer_ = editorContext.getDOMContainer();
+ svgroot_ = editorContext.getSVGRoot();
+ };
+ /**
+ * Used to prevent the [Billion laughs attack]{@link https://en.wikipedia.org/wiki/Billion_laughs_attack}.
+ * @function module:utilities.dropXMLInternalSubset
+ * @param {string} str String to be processed
+ * @returns {string} The string with entity declarations in the internal subset removed
+ * @todo This might be needed in other places `parseFromString` is used even without LGTM flagging
+ */
+
+ var dropXMLInternalSubset = function dropXMLInternalSubset(str) {
+ return str.replace(/()/, '$1$2'); // return str.replace(/(?\?\]>)/, '$$');
+ };
+ /**
+ * Converts characters in a string to XML-friendly entities.
+ * @function module:utilities.toXml
+ * @example `&` becomes `&`
+ * @param {string} str - The string to be converted
+ * @returns {string} The converted string
+ */
+
+ var toXml = function toXml(str) {
+ // ' is ok in XML, but not HTML
+ // > does not normally need escaping, though it can if within a CDATA expression (and preceded by "]]")
+ return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); // Note: `'` is XML only
+ };
+ // public domain. It would be nice if you left this header intact.
+ // Base64 code from Tyler Akins -- http://rumkin.com
+ // schiller: Removed string concatenation in favour of Array.join() optimization,
+ // also precalculate the size of the array needed.
+
+ /**
+ * Converts a string to base64.
+ * @function module:utilities.encode64
+ * @param {string} input
+ * @returns {string} Base64 output
+ */
+
+ function encode64(input) {
+ // base64 strings are 4/3 larger than the original string
+ input = encodeUTF8(input); // convert non-ASCII characters
+ // input = convertToXMLReferences(input);
+
+ if (window.btoa) {
+ return window.btoa(input); // Use native if available
+ }
+
+ var output = new Array(Math.floor((input.length + 2) / 3) * 4);
+ var i = 0,
+ p = 0;
+
+ do {
+ var chr1 = input.charCodeAt(i++);
+ var chr2 = input.charCodeAt(i++);
+ var chr3 = input.charCodeAt(i++);
+ /* eslint-disable no-bitwise */
+
+ var enc1 = chr1 >> 2;
+ var enc2 = (chr1 & 3) << 4 | chr2 >> 4;
+ var enc3 = (chr2 & 15) << 2 | chr3 >> 6;
+ var enc4 = chr3 & 63;
+ /* eslint-enable no-bitwise */
+
+ if (Number.isNaN(chr2)) {
+ enc3 = 64;
+ enc4 = 64;
+ } else if (Number.isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output[p++] = KEYSTR.charAt(enc1);
+ output[p++] = KEYSTR.charAt(enc2);
+ output[p++] = KEYSTR.charAt(enc3);
+ output[p++] = KEYSTR.charAt(enc4);
+ } while (i < input.length);
+
+ return output.join('');
+ }
+ /**
+ * Converts a string from base64.
+ * @function module:utilities.decode64
+ * @param {string} input Base64-encoded input
+ * @returns {string} Decoded output
+ */
+
+ function decode64(input) {
+ if (window.atob) {
+ return decodeUTF8(window.atob(input));
+ } // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+
+
+ input = input.replace(/[^A-Za-z\d+/=]/g, '');
+ var output = '';
+ var i = 0;
+
+ do {
+ var enc1 = KEYSTR.indexOf(input.charAt(i++));
+ var enc2 = KEYSTR.indexOf(input.charAt(i++));
+ var enc3 = KEYSTR.indexOf(input.charAt(i++));
+ var enc4 = KEYSTR.indexOf(input.charAt(i++));
+ /* eslint-disable no-bitwise */
+
+ var chr1 = enc1 << 2 | enc2 >> 4;
+ var chr2 = (enc2 & 15) << 4 | enc3 >> 2;
+ var chr3 = (enc3 & 3) << 6 | enc4;
+ /* eslint-enable no-bitwise */
+
+ output += String.fromCharCode(chr1);
+
+ if (enc3 !== 64) {
+ output += String.fromCharCode(chr2);
+ }
+
+ if (enc4 !== 64) {
+ output += String.fromCharCode(chr3);
+ }
+ } while (i < input.length);
+
+ return decodeUTF8(output);
+ }
+ /**
+ * @function module:utilities.decodeUTF8
+ * @param {string} argString
+ * @returns {string}
+ */
+
+ function decodeUTF8(argString) {
+ return decodeURIComponent(escape(argString));
+ } // codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded
+
+ /**
+ * @function module:utilities.encodeUTF8
+ * @param {string} argString
+ * @returns {string}
+ */
+
+ var encodeUTF8 = function encodeUTF8(argString) {
+ return unescape(encodeURIComponent(argString));
+ };
+ /**
+ * Convert dataURL to object URL.
+ * @function module:utilities.dataURLToObjectURL
+ * @param {string} dataurl
+ * @returns {string} object URL or empty string
+ */
+
+ var dataURLToObjectURL = function dataURLToObjectURL(dataurl) {
+ if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) {
+ return '';
+ }
+
+ var arr = dataurl.split(','),
+ mime = arr[0].match(/:(.*?);/)[1],
+ bstr = atob(arr[1]);
+ /*
+ const [prefix, suffix] = dataurl.split(','),
+ {groups: {mime}} = prefix.match(/:(?.*?);/),
+ bstr = atob(suffix);
+ */
+
+ var n = bstr.length;
+ var u8arr = new Uint8Array(n);
+
+ while (n--) {
+ u8arr[n] = bstr.charCodeAt(n);
+ }
+
+ var blob = new Blob([u8arr], {
+ type: mime
+ });
+ return URL.createObjectURL(blob);
+ };
+ /**
+ * Get object URL for a blob object.
+ * @function module:utilities.createObjectURL
+ * @param {Blob} blob A Blob object or File object
+ * @returns {string} object URL or empty string
+ */
+
+ var createObjectURL = function createObjectURL(blob) {
+ if (!blob || typeof URL === 'undefined' || !URL.createObjectURL) {
+ return '';
+ }
+
+ return URL.createObjectURL(blob);
+ };
+ /**
+ * @property {string} blankPageObjectURL
+ */
+
+ var blankPageObjectURL = function () {
+ if (typeof Blob === 'undefined') {
+ return '';
+ }
+
+ var blob = new Blob(['SVG-edit '], {
+ type: 'text/html'
+ });
+ return createObjectURL(blob);
+ }();
+ /**
+ * Cross-browser compatible method of converting a string to an XML tree.
+ * Found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f}.
+ * @function module:utilities.text2xml
+ * @param {string} sXML
+ * @throws {Error}
+ * @returns {XMLDocument}
+ */
+
+ var text2xml = function text2xml(sXML) {
+ if (sXML.includes('`
+ * - ``
+ * - ``
+ * @function module:utilities.getUrlFromAttr
+ * @param {string} attrVal The attribute value as a string
+ * @returns {string} String with just the URL, like "someFile.svg#foo"
+ */
+
+ var getUrlFromAttr = function getUrlFromAttr(attrVal) {
+ if (attrVal) {
+ // url('#somegrad')
+ if (attrVal.startsWith('url("')) {
+ return attrVal.substring(5, attrVal.indexOf('"', 6));
+ } // url('#somegrad')
+
+
+ if (attrVal.startsWith("url('")) {
+ return attrVal.substring(5, attrVal.indexOf("'", 6));
+ }
+
+ if (attrVal.startsWith('url(')) {
+ return attrVal.substring(4, attrVal.indexOf(')'));
+ }
+ }
+
+ return null;
+ };
+ /**
+ * @function module:utilities.getHref
+ * @param {Element} elem
+ * @returns {string} The given element's `xlink:href` value
+ */
+
+ var getHref = function getHref(elem) {
+ // eslint-disable-line import/no-mutable-exports
+ return elem.getAttributeNS(NS.XLINK, 'href');
+ };
+ /**
+ * Sets the given element's `xlink:href` value.
+ * @function module:utilities.setHref
+ * @param {Element} elem
+ * @param {string} val
+ * @returns {void}
+ */
+
+ var setHref = function setHref(elem, val) {
+ // eslint-disable-line import/no-mutable-exports
+ elem.setAttributeNS(NS.XLINK, 'xlink:href', val);
+ };
+ /**
+ * @function module:utilities.findDefs
+ * @returns {SVGDefsElement} The document's `` element, creating it first if necessary
+ */
+
+ var findDefs = function findDefs() {
+ var svgElement = editorContext_.getSVGContent();
+ var defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs');
+
+ if (defs.length > 0) {
+ defs = defs[0];
+ } else {
+ defs = svgElement.ownerDocument.createElementNS(NS.SVG, 'defs');
+
+ if (svgElement.firstChild) {
+ // first child is a comment, so call nextSibling
+ svgElement.insertBefore(defs, svgElement.firstChild.nextSibling); // svgElement.firstChild.nextSibling.before(defs); // Not safe
+ } else {
+ svgElement.append(defs);
+ }
+ }
+
+ return defs;
+ }; // TODO(codedread): Consider moving the next to functions to bbox.js
+
+ /**
+ * Get correct BBox for a path in Webkit.
+ * Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html}.
+ * @function module:utilities.getPathBBox
+ * @param {SVGPathElement} path - The path DOM element to get the BBox for
+ * @returns {module:utilities.BBoxObject} A BBox-like object
+ */
+
+ var getPathBBox = function getPathBBox(path) {
+ var seglist = path.pathSegList;
+ var tot = seglist.numberOfItems;
+ var bounds = [[], []];
+ var start = seglist.getItem(0);
+ var P0 = [start.x, start.y];
+
+ var getCalc = function getCalc(j, P1, P2, P3) {
+ return function (t) {
+ return 1 - Math.pow(t, 3) * P0[j] + 3 * 1 - Math.pow(t, 2) * t * P1[j] + 3 * (1 - t) * Math.pow(t, 2) * P2[j] + Math.pow(t, 3) * P3[j];
+ };
+ };
+
+ for (var i = 0; i < tot; i++) {
+ var seg = seglist.getItem(i);
+
+ if (seg.x === undefined) {
+ continue;
+ } // Add actual points to limits
+
+
+ bounds[0].push(P0[0]);
+ bounds[1].push(P0[1]);
+
+ if (seg.x1) {
+ var P1 = [seg.x1, seg.y1],
+ P2 = [seg.x2, seg.y2],
+ P3 = [seg.x, seg.y];
+
+ for (var j = 0; j < 2; j++) {
+ var calc = getCalc(j, P1, P2, P3);
+ var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];
+ var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];
+ var c = 3 * P1[j] - 3 * P0[j];
+
+ if (a === 0) {
+ if (b === 0) {
+ continue;
+ }
+
+ var t = -c / b;
+
+ if (t > 0 && t < 1) {
+ bounds[j].push(calc(t));
+ }
+
+ continue;
+ }
+
+ var b2ac = Math.pow(b, 2) - 4 * c * a;
+
+ if (b2ac < 0) {
+ continue;
+ }
+
+ var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
+
+ if (t1 > 0 && t1 < 1) {
+ bounds[j].push(calc(t1));
+ }
+
+ var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
+
+ if (t2 > 0 && t2 < 1) {
+ bounds[j].push(calc(t2));
+ }
+ }
+
+ P0 = P3;
+ } else {
+ bounds[0].push(seg.x);
+ bounds[1].push(seg.y);
+ }
+ }
+
+ var x = Math.min.apply(null, bounds[0]);
+ var w = Math.max.apply(null, bounds[0]) - x;
+ var y = Math.min.apply(null, bounds[1]);
+ var h = Math.max.apply(null, bounds[1]) - y;
+ return {
+ x: x,
+ y: y,
+ width: w,
+ height: h
+ };
+ };
+ /**
+ * Get the given/selected element's bounding box object, checking for
+ * horizontal/vertical lines (see issue 717)
+ * Note that performance is currently terrible, so some way to improve would
+ * be great.
+ * @param {Element} selected - Container or `