Merge branch 'master' of https://github.com/SVG-Edit/svgedit into issues/631
commit
a29a82e921
|
@ -67,7 +67,7 @@ exports[`use all parts of svg-edit > check tool_path_change_node_xy #0`] = `
|
|||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
d="M75,75L150,100L125,200L75,75z"
|
||||
d="M 75 75 L 150 100 L 125 200 L 75 75 z"
|
||||
id="svg_1"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
|
@ -94,7 +94,7 @@ exports[`use all parts of svg-edit > check tool_path_change_seg_type #0`] = `
|
|||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
d="M75,75L150,100L125,200C235.33333,330.33333 91.66667,116.66667 75,75z"
|
||||
d="M 75 75 L 150 100 L 125 200 C 235.33333333333331 330.33333333333337 91.66666666666667 116.66666666666666 75 75 z"
|
||||
id="svg_1"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
|
@ -121,7 +121,7 @@ exports[`use all parts of svg-edit > check tool_path_change_clone_node #0`] = `
|
|||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
d="M201,246L150,100L125,200C180.16666,265.16666 297.83333,415.33333 273.625,373C249.41667,330.66667 209.33334,266.83334 201,246z"
|
||||
d="M 201 246 L 150 100 L 125 200 C 180.16666666666666 265.1666666666667 297.8333333333333 415.33333333333337 273.625 373 C 249.41666666666669 330.66666666666663 209.33333333333334 266.8333333333333 201 246 z"
|
||||
id="svg_1"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
|
@ -148,7 +148,7 @@ exports[`use all parts of svg-edit > check tool_path_openclose #0`] = `
|
|||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
d="M201,246L150,100L125,200C180.16666,265.16666 297.83333,415.33333 273.625,373C249.41667,330.66667 209.33334,266.83334 201,246z"
|
||||
d="M 201 246 L 150 100 L 125 200 C 180.16666666666666 265.1666666666667 297.8333333333333 415.33333333333337 273.625 373 C 249.41666666666669 330.66666666666663 209.33333333333334 266.8333333333333 201 246 z"
|
||||
id="svg_1"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
|
|
|
@ -182,9 +182,7 @@ describe('use various parts of svg-edit', function () {
|
|||
});
|
||||
it('check tool_text_change_font_family', function () {
|
||||
cy.get('#svg_1').click({ force: true });
|
||||
cy.get('#tool_font_family').shadow().find('elix-dropdown-list').eq(0).invoke('attr', 'opened', 'opened');
|
||||
cy.get('#tool_font_family').find('se-list-item').eq(6).shadow().find('elix-option').eq(0)
|
||||
.click({ force: true });
|
||||
cy.get('#tool_font_family').shadow().find('select').select("Serif");
|
||||
cy.get('#svgcontent').toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -56,7 +56,7 @@ describe('use all parts of svg-edit', function () {
|
|||
it('check tool_path_change_seg_type', function () {
|
||||
cy.get('#svg_1').click({ force: true });
|
||||
cy.get('#svg_1').dblclick({ force: true });
|
||||
cy.get('#seg_type').select('6').should('have.value', '6');
|
||||
cy.get('#seg_type').shadow().find('select').select('6').should('have.value', '6');
|
||||
cy.get('#ctrlpointgrip_3c1')
|
||||
.trigger('mousedown', { force: true })
|
||||
.trigger('mousemove', 130, 175, { force: true })
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'pathseg';
|
||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
||||
import * as draw from '../../../instrumented/svgcanvas/draw.js';
|
||||
import * as units from '../../../instrumented/common/units.js';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-disable max-len */
|
||||
import * as browser from '../../../instrumented/common/browser.js';
|
||||
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
||||
|
||||
|
@ -161,19 +160,6 @@ describe('utilities', function () {
|
|||
assert.equal(utilities.getUrlFromAttr('url("#foo")'), '#foo');
|
||||
});
|
||||
|
||||
it('Test getPathBBox', function () {
|
||||
if (browser.supportsPathBBox()) {
|
||||
return;
|
||||
}
|
||||
const doc = utilities.text2xml('<svg></svg>');
|
||||
const path = doc.createElementNS(NS.SVG, 'path');
|
||||
path.setAttribute('d', 'm0,0l5,0l0,5l-5,0l0,-5z');
|
||||
const bb = utilities.getPathBBox(path);
|
||||
assert.equal(typeof bb, 'object', 'BBox returned object');
|
||||
assert.ok(bb.x && !isNaN(bb.x));
|
||||
assert.ok(bb.y && !isNaN(bb.y));
|
||||
});
|
||||
|
||||
it('Test getPathDFromSegments', function () {
|
||||
const { getPathDFromSegments } = utilities;
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
* @copyright 2010 Jeff Schiller, 2010 Alexis Deveria
|
||||
*/
|
||||
|
||||
import 'pathseg';
|
||||
|
||||
import { NS } from './namespaces.js';
|
||||
|
||||
const { userAgent } = navigator;
|
||||
|
@ -19,31 +17,6 @@ const isChrome_ = userAgent.includes('Chrome/');
|
|||
const isMac_ = userAgent.includes('Macintosh');
|
||||
const isTouch_ = 'ontouchstart' in window;
|
||||
|
||||
// segList functions (for FF1.5 and 2.0)
|
||||
const supportsPathReplaceItem_ = (function () {
|
||||
const path = document.createElementNS(NS.SVG, 'path');
|
||||
path.setAttribute('d', 'M0,0 10,10');
|
||||
const seglist = path.pathSegList;
|
||||
const seg = path.createSVGPathSegLinetoAbs(5, 5);
|
||||
try {
|
||||
seglist.replaceItem(seg, 1);
|
||||
return true;
|
||||
}catch (err) {/* empty */}
|
||||
return false;
|
||||
}());
|
||||
|
||||
const supportsPathInsertItemBefore_ = (function () {
|
||||
const path = document.createElementNS(NS.SVG, 'path');
|
||||
path.setAttribute('d', 'M0,0 10,10');
|
||||
const seglist = path.pathSegList;
|
||||
const seg = path.createSVGPathSegLinetoAbs(5, 5);
|
||||
try {
|
||||
seglist.insertItemBefore(seg, 1);
|
||||
return true;
|
||||
}catch (err) {/* empty */}
|
||||
return false;
|
||||
}());
|
||||
|
||||
// text character positioning (for IE9 and now Chrome)
|
||||
const supportsGoodTextCharPos_ = (function () {
|
||||
const svgroot = document.createElementNS(NS.SVG, 'svg');
|
||||
|
@ -64,17 +37,6 @@ const supportsGoodTextCharPos_ = (function () {
|
|||
}
|
||||
}());
|
||||
|
||||
const supportsPathBBox_ = (function () {
|
||||
const svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||
document.documentElement.append(svgcontent);
|
||||
const path = document.createElementNS(NS.SVG, 'path');
|
||||
path.setAttribute('d', 'M0,0 C0,0 10,10 10,0');
|
||||
svgcontent.append(path);
|
||||
const bbox = path.getBBox();
|
||||
svgcontent.remove();
|
||||
return (bbox.height > 4 && bbox.height < 5);
|
||||
}());
|
||||
|
||||
// Support for correct bbox sizing on groups with horizontal/vertical lines
|
||||
const supportsHVLineContainerBBox_ = (function () {
|
||||
const svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||
|
@ -127,24 +89,6 @@ export const isMac = () => isMac_;
|
|||
*/
|
||||
export const isTouch = () => isTouch_;
|
||||
|
||||
/**
|
||||
* @function module:browser.supportsPathReplaceItem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const supportsPathReplaceItem = () => supportsPathReplaceItem_;
|
||||
|
||||
/**
|
||||
* @function module:browser.supportsPathInsertItemBefore
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const supportsPathInsertItemBefore = () => supportsPathInsertItemBefore_;
|
||||
|
||||
/**
|
||||
* @function module:browser.supportsPathBBox
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const supportsPathBBox = () => supportsPathBBox_;
|
||||
|
||||
/**
|
||||
* @function module:browser.supportsHVLineContainerBBox
|
||||
* @returns {boolean}
|
||||
|
|
|
@ -122,7 +122,7 @@ export default class ConfigObj {
|
|||
text: {
|
||||
stroke_width: 0,
|
||||
font_size: 24,
|
||||
font_family: 'serif'
|
||||
font_family: 'Serif'
|
||||
},
|
||||
initOpacity: 1,
|
||||
initTool: 'select',
|
||||
|
|
|
@ -365,7 +365,8 @@ class Editor extends EditorStartup {
|
|||
const { workarea } = this;
|
||||
const cnvs = $id("svgcanvas");
|
||||
|
||||
let w = parseFloat(getComputedStyle(workarea, null).width.replace("px", "")); let h = parseFloat(getComputedStyle(workarea, null).height.replace("px", ""));
|
||||
let w = parseFloat(getComputedStyle(workarea, null).width.replace("px", ""));
|
||||
let h = parseFloat(getComputedStyle(workarea, null).height.replace("px", ""));
|
||||
const wOrig = w; const hOrig = h;
|
||||
const oldCtr = {
|
||||
x: workarea.scrollLeft + wOrig / 2,
|
||||
|
|
|
@ -249,7 +249,7 @@ class EditorStartup {
|
|||
});
|
||||
|
||||
$id('seg_type').addEventListener('change', (evt) => {
|
||||
this.svgCanvas.setSegType(evt.currentTarget.value);
|
||||
this.svgCanvas.setSegType(evt.detail.value);
|
||||
});
|
||||
|
||||
const addListenerMulti = (element, eventNames, listener)=> {
|
||||
|
|
|
@ -120,7 +120,6 @@ class MainMenu {
|
|||
this.editor.configObj.curConfig.snappingStep = gridsnappingstep;
|
||||
this.editor.configObj.curConfig.gridColor = gridcolor;
|
||||
this.editor.configObj.curConfig.showRulers = showrulers;
|
||||
$id('rulers').style.display = (this.editor.configObj.curConfig.showRulers) ? 'block' : 'none';
|
||||
if (this.editor.configObj.curConfig.showRulers) {
|
||||
this.editor.rulers.updateRulers();
|
||||
}
|
||||
|
@ -288,7 +287,7 @@ class MainMenu {
|
|||
<se-menu-item id="tool_editor_homepage" label="tools.editor_homepage" src="logo.svg"></se-menu-item>
|
||||
</se-menu>
|
||||
`;
|
||||
$id('tools_top').prepend(template.content.cloneNode(true));
|
||||
this.editor.$svgEditor.append(template.content.cloneNode(true));
|
||||
|
||||
// register action to main menu entries
|
||||
/**
|
||||
|
|
|
@ -10,3 +10,5 @@ import './seMenuItem.js';
|
|||
import './seList.js';
|
||||
import './seListItem.js';
|
||||
import './seColorPicker.js';
|
||||
import './seSelect';
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ template.innerHTML = `
|
|||
{
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin: 2px 1px 4px;
|
||||
margin: 4px 1px 4px;
|
||||
padding: 3px;
|
||||
background-color: var(--icon-bg-color);
|
||||
cursor: pointer;
|
||||
|
|
|
@ -24,6 +24,7 @@ template.innerHTML = `
|
|||
elix-input {
|
||||
background-color: var(--input-color);
|
||||
border-radius: 3px;
|
||||
height: 24px;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
|
|
|
@ -12,7 +12,11 @@ elix-dropdown-list:hover {
|
|||
background-color: var(--icon-bg-color-hover);
|
||||
}
|
||||
|
||||
::part(popup-toggle) {
|
||||
elix-dropdown-list::part(value) {
|
||||
background-color: var(--main-bg-color);
|
||||
}
|
||||
|
||||
elix-dropdown-list::part(popup-toggle) {
|
||||
display: none;
|
||||
}
|
||||
::slotted(*) {
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
const template = document.createElement('template');
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
select {
|
||||
margin-top: 8px;
|
||||
background-color: var(--input-color);
|
||||
appearance: none;
|
||||
outline: none;
|
||||
padding: 3px;
|
||||
}
|
||||
label {
|
||||
margin-left: 2px;
|
||||
}
|
||||
::slotted(*) {
|
||||
padding:0;
|
||||
width:100%;
|
||||
}
|
||||
</style>
|
||||
<label>Label</label>
|
||||
<select>
|
||||
</select>
|
||||
|
||||
`;
|
||||
/**
|
||||
* @class SeList
|
||||
*/
|
||||
export class SeSelect extends HTMLElement {
|
||||
/**
|
||||
* @function constructor
|
||||
*/
|
||||
constructor () {
|
||||
super();
|
||||
// create the shadowDom and insert the template
|
||||
this._shadowRoot = this.attachShadow({ mode: 'open' });
|
||||
this._shadowRoot.append(template.content.cloneNode(true));
|
||||
this.$select = this._shadowRoot.querySelector('select');
|
||||
this.$label = this._shadowRoot.querySelector('label');
|
||||
}
|
||||
/**
|
||||
* @function observedAttributes
|
||||
* @returns {any} observed
|
||||
*/
|
||||
static get observedAttributes () {
|
||||
return [ 'label', 'width', 'height', 'options', 'values' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @function attributeChangedCallback
|
||||
* @param {string} name
|
||||
* @param {string} oldValue
|
||||
* @param {string} newValue
|
||||
* @returns {void}
|
||||
*/
|
||||
attributeChangedCallback (name, oldValue, newValue) {
|
||||
let options;
|
||||
if (oldValue === newValue) return;
|
||||
switch (name) {
|
||||
case 'label':
|
||||
this.$label.textContent = newValue;
|
||||
break;
|
||||
case 'height':
|
||||
this.$select.style.height = newValue;
|
||||
break;
|
||||
case 'width':
|
||||
this.$select.style.width = newValue;
|
||||
break;
|
||||
case 'options':
|
||||
options = newValue.split(',');
|
||||
options.forEach((option) => {
|
||||
const optionNode = document.createElement("OPTION");
|
||||
const text = document.createTextNode(option);
|
||||
optionNode.appendChild(text);
|
||||
this.$select.appendChild(optionNode);
|
||||
});
|
||||
break;
|
||||
case 'values':
|
||||
options = newValue.split(' ');
|
||||
options.forEach((option, index) => {
|
||||
this.$select.children[index].setAttribute('value', option);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`unknown attribute: ${name}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @function get
|
||||
* @returns {any}
|
||||
*/
|
||||
get label () {
|
||||
return this.getAttribute('label');
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set label (value) {
|
||||
this.setAttribute('label', value);
|
||||
}
|
||||
/**
|
||||
* @function get
|
||||
* @returns {any}
|
||||
*/
|
||||
get width () {
|
||||
return this.getAttribute('width');
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set width (value) {
|
||||
this.setAttribute('width', value);
|
||||
}
|
||||
/**
|
||||
* @function get
|
||||
* @returns {any}
|
||||
*/
|
||||
get height () {
|
||||
return this.getAttribute('height');
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set height (value) {
|
||||
this.setAttribute('height', value);
|
||||
}
|
||||
/**
|
||||
* @function get
|
||||
* @returns {any}
|
||||
*/
|
||||
get value () {
|
||||
return this.$select.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function set
|
||||
* @returns {void}
|
||||
*/
|
||||
set value (value) {
|
||||
this.$select.value = value;
|
||||
}
|
||||
/**
|
||||
* @function connectedCallback
|
||||
* @returns {void}
|
||||
*/
|
||||
connectedCallback () {
|
||||
const currentObj = this;
|
||||
this.$select.addEventListener('change', () => {
|
||||
const value = this.$select.value;
|
||||
const closeEvent = new CustomEvent('change', { detail: { value } });
|
||||
currentObj.dispatchEvent(closeEvent);
|
||||
currentObj.value = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Register
|
||||
customElements.define('se-select', SeSelect);
|
|
@ -15,6 +15,7 @@ template.innerHTML = `
|
|||
img {
|
||||
position: relative;
|
||||
right: -4px;
|
||||
top: 2px;
|
||||
}
|
||||
span {
|
||||
bottom: -0.5em;
|
||||
|
|
|
@ -48,8 +48,7 @@ Array.prototype.forEach.call(atags, function (aEle) {
|
|||
post({ href, data });
|
||||
return data;
|
||||
})
|
||||
// eslint-disable-next-line no-console
|
||||
.catch( (error) => console.log(error));
|
||||
.catch( (error) => console.error(error));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -81,14 +81,6 @@ export default {
|
|||
}
|
||||
});
|
||||
|
||||
/*
|
||||
// Make sure shape uses absolute values
|
||||
if ((/[a-z]/).test(currentD)) {
|
||||
currentD = curLib.data[curShapeId] = canv.pathActions.convertPath(curShape);
|
||||
curShape.setAttribute('d', currentD);
|
||||
canv.pathActions.fixEnd(curShape);
|
||||
}
|
||||
*/
|
||||
curShape.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(0.005) translate(' + -x + ',' + -y + ')');
|
||||
|
||||
canv.recalculateDimensions(curShape);
|
||||
|
|
|
@ -185,13 +185,10 @@ class BottomPanel {
|
|||
<se-colorpicker id="stroke_color" src="stroke.svg" label="properties.stroke_color" type="stroke">
|
||||
</se-colorpicker>
|
||||
<se-spin-input id="stroke_width" min=0 max=99 step=1 title="properties.stroke_width" label=""></se-spin-input>
|
||||
<se-list id="stroke_style" title="properties.stroke_style" label="" width="22px" height="22px">
|
||||
<se-list-item value="none" option="—"></se-list-item>
|
||||
<se-list-item value="2,2" option="..."></se-list-item>
|
||||
<se-list-item value="5,5" option="- -"></se-list-item>
|
||||
<se-list-item value="5,2,2,2" option="- ."></se-list-item>
|
||||
<se-list-item value="5,2,2,2,2,2" option="- .."></se-list-item>
|
||||
</se-list>
|
||||
<se-select id="stroke_style" title="${i18next.t('properties.stroke_style')}" label="" width="22px" height="22px"
|
||||
options="—,...,- -,- .,- .."
|
||||
values="none 2,2 5,5 5,2,2,2 5,2,2,2,2,2">
|
||||
</se-select>
|
||||
<se-list id="stroke_linejoin" title="properties.linejoin_miter" label="" width="22px" height="22px">
|
||||
<se-list-item id="linejoin_miter" value="miter" src="linejoin_miter.svg" title="properties.linejoin_miter" img-height="22px"></se-list-item>
|
||||
<se-list-item id="linejoin_round" value="round" src="linejoin_round.svg" title="properties.linejoin_round" img-height="22px"></se-list-item>
|
||||
|
|
|
@ -11,7 +11,7 @@ class LayersPanel {
|
|||
* @param {PlainObject} editor
|
||||
*/
|
||||
constructor(editor) {
|
||||
this.updateContextPanel = editor.topPanel.updateContextPanel;
|
||||
this.updateContextPanel = editor.topPanel.updateContextPanel.bind(editor.topPanel);
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
|
|
|
@ -784,8 +784,7 @@ class TopPanel {
|
|||
editor.svgCanvas.setMode('select');
|
||||
editor.svgCanvas.selectOnly(editor.svgCanvas.getSelectedElems(), true);
|
||||
}, (error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("error =", error);
|
||||
console.error("error =", error);
|
||||
seAlert(editor.i18next.t('tools.no_embed'));
|
||||
editor.svgCanvas.deleteSelectedElements();
|
||||
});
|
||||
|
@ -895,12 +894,13 @@ class TopPanel {
|
|||
<se-button id="tool_align_top" title="tools.align_top" src="align_top.svg"></se-button>
|
||||
<se-button id="tool_align_middle" title="tools.align_middle" src="align_middle.svg"></se-button>
|
||||
<se-button id="tool_align_bottom" title="tools.align_bottom" src="align_bottom.svg"></se-button>
|
||||
<se-list id="tool_align_relative" label="tools.relativeTo">
|
||||
<se-list-item id="selected_objects" value="selected" option="tools.selected_objects"></se-list-item>
|
||||
<se-list-item id="largest_object" value="largest" option="tools.largest_object"></se-list-item>
|
||||
<se-list-item id="smallest_object" value="smallest" option="tools.smallest_object"></se-list-item>
|
||||
<se-list-item id="page" value="page" option="tools.page"></se-list-item>
|
||||
</se-list>
|
||||
<se-select id="tool_align_relative" label="relative to:"
|
||||
options="${i18next.t('tools.selected_objects')},
|
||||
${i18next.t('tools.largest_object')},
|
||||
${i18next.t('tools.smallest_object')},
|
||||
${i18next.t('tools.page')}"
|
||||
values="selected largest smallest page"></se-list-item>
|
||||
</se-select>
|
||||
</div> <!-- multiselected_panel -->
|
||||
<div class="rect_panel">
|
||||
<se-spin-input id="rect_width" data-attr="width" size="4" label="properties.w_label" title="properties.rect_width"></se-spin-input>
|
||||
|
@ -938,16 +938,18 @@ class TopPanel {
|
|||
<div class="text_panel">
|
||||
<se-button id="tool_bold" title="properties.bold" src="bold.svg" shortcut="B"></se-button>
|
||||
<se-button id="tool_italic" title="properties.italic" src="italic.svg" shortcut="I"></se-button>
|
||||
<se-list id="tool_font_family" label="properties.font_family_label">
|
||||
<se-list-item value="Serif" style="font-family:serif;" option="properties.serif"></se-list-item>
|
||||
<se-list-item value="Sans-serif" style="font-family:sans-serif;" option="properties.sans_serif"></se-list-item>
|
||||
<se-list-item value="Cursive" style="font-family:cursive;" option="properties.cursive"></se-list-item>
|
||||
<se-list-item value="Fantasy" style="font-family:fantasy;" option="properties.fantasy"></se-list-item>
|
||||
<se-list-item value="Monospace" style="font-family:monospace;" option="properties.monospace"></se-list-item>
|
||||
<se-list-item value="Courier" style="font-family:courier;" option="properties.courier"></se-list-item>
|
||||
<se-list-item value="Helvetica" style="font-family:helvetica;" option="properties.helvetica"></se-list-item>
|
||||
<se-list-item value="Times" style="font-family:times;" option="properties.times"></se-list-item>
|
||||
</se-list>
|
||||
<se-select id="tool_font_family" label="Font:"
|
||||
options="${i18next.t('properties.serif')},
|
||||
${i18next.t('properties.sans_serif')},
|
||||
${i18next.t('properties.cursive')},
|
||||
${i18next.t('properties.fantasy')},
|
||||
${i18next.t('properties.monospace')},
|
||||
${i18next.t('properties.courier')},
|
||||
${i18next.t('properties.helvetica')},
|
||||
${i18next.t('properties.times')}"
|
||||
values="Serif Sans-serif Cursive Fantasy Monospace Courier Helvetica Times"
|
||||
>
|
||||
</select>
|
||||
<se-spin-input size="2" id="font_size" min=1 max=1000 step=1 title="properties.font_size" src="fontsize.svg"></se-spin-input>
|
||||
</div>
|
||||
<div class="text_panel">
|
||||
|
@ -980,10 +982,7 @@ class TopPanel {
|
|||
<div class="tool_sep"></div>
|
||||
<se-spin-input id="path_node_x" data-attr="x" size="4" title="properties.node_x" label="properties.x_label"></se-spin-input>
|
||||
<se-spin-input id="path_node_y" data-attr="y" size="4" title="properties.node_y" label="properties.y_label"></se-spin-input>
|
||||
<select id="seg_type" title="${i18next.t('tools.seg_type')}">
|
||||
<option id="straight_segments" selected="selected" value="4">${i18next.t('properties.straight_segments')}</option>
|
||||
<option id="curve_segments" value="6">${i18next.t('properties.curve_segments')}</option>
|
||||
</select>
|
||||
<se-select id="seg_type" title="${i18next.t('tools.seg_type')}" label="" options="${i18next.t('properties.straight_segments')}, ${i18next.t('properties.curve_segments')}" values="4 6"></se-select>
|
||||
<se-button id="tool_node_clone" title="tools.node_clone" src="tool_node_clone.svg"></se-button>
|
||||
<se-button id="tool_node_delete" title="tools.node_delete" src="tool_node_delete.svg"></se-button>
|
||||
<se-button id="tool_openclose_path" title="tools.openclose_path" src="tool_openclose_path.svg"></se-button>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
:root {
|
||||
--main-bg-color: #72797A;
|
||||
--text-color: #000000;
|
||||
--text-color: #ffffff;
|
||||
--border-color: #808080;
|
||||
--canvas-bg-color: #B2B2B2;
|
||||
--link-color: #19c;
|
||||
|
@ -18,12 +18,12 @@
|
|||
.svg_editor {
|
||||
display: grid;
|
||||
grid-template-rows: auto 15px 1fr 40px;
|
||||
grid-template-columns: 34px 15px 1fr 15px;
|
||||
grid-template-columns: 34px 15px 50px 1fr 15px;
|
||||
grid-template-areas:
|
||||
"top top top top"
|
||||
"left corner rulerX side"
|
||||
"left rulerY workarea side"
|
||||
"left bottom bottom bottom";
|
||||
"main main main top top"
|
||||
"left corner rulerX rulerX side"
|
||||
"left rulerY workarea workarea side"
|
||||
"left bottom bottom bottom bottom";
|
||||
font-size: 8pt;
|
||||
background: var(--main-bg-color);
|
||||
font-family: Verdana, Helvetica, Arial;
|
||||
|
@ -33,18 +33,18 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.svg_editor.open {
|
||||
grid-template-columns: 34px 15px 1fr 150px;
|
||||
}
|
||||
|
||||
/* on smaller screen, allow 2 lines for the toolbar */
|
||||
|
||||
@media screen and (max-width:1250px) {
|
||||
.svg_editor {
|
||||
grid-template-rows: minmax(80px, auto) 15px 1fr 40px;
|
||||
}
|
||||
}
|
||||
|
||||
/* class to open the right panel */
|
||||
.svg_editor.open {
|
||||
grid-template-columns: 34px 15px 50px 1fr 150px;
|
||||
}
|
||||
|
||||
#svgroot {
|
||||
user-select: none;
|
||||
position: absolute;
|
||||
|
@ -186,6 +186,7 @@ hr {
|
|||
—————————————————————————————*/
|
||||
|
||||
#main_button {
|
||||
grid-area: main;
|
||||
color: #fff;
|
||||
border-radius: 3px;
|
||||
padding-block: 2px;
|
||||
|
@ -299,8 +300,7 @@ hr {
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
/* leave space for the main menu */
|
||||
position: relative;
|
||||
align-items: flex-start;
|
||||
background-color: var(--main-bg-color);
|
||||
}
|
||||
|
||||
|
@ -325,10 +325,15 @@ hr {
|
|||
width: 3px;
|
||||
}
|
||||
|
||||
#tools_bottom se-list {
|
||||
#tools_bottom se-list, #tools_bottom se-select {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#zoom {
|
||||
color: var(--text-color);
|
||||
background-color: var(--main-bg-color);
|
||||
border: none;
|
||||
}
|
||||
|
||||
/*—————————————————————————————*/
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ export const setBlurNoUndo = function (val) {
|
|||
blurContext_.changeSelectedAttributeNoUndoMethod('filter', 'url(#' + elem.id + '_blur)');
|
||||
}
|
||||
if (blurContext_.isWebkit()) {
|
||||
// console.log('e', elem);
|
||||
elem.removeAttribute('filter');
|
||||
elem.setAttribute('filter', 'url(#' + elem.id + '_blur)');
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { isWebkit } from '../common/browser.js';
|
||||
import { convertPath } from './path.js';
|
||||
import { preventClickDefault } from './utilities.js';
|
||||
|
||||
/**
|
||||
|
@ -19,13 +17,6 @@ export const copyElem = function (el, getNextId) {
|
|||
newEl.removeAttribute('id');
|
||||
newEl.id = getNextId();
|
||||
|
||||
// Opera's "d" value needs to be reset for Opera/Win/non-EN
|
||||
// Also needed for webkit (else does not keep curved segments on clone)
|
||||
if (isWebkit() && el.nodeName === 'path') {
|
||||
const fixedD = convertPath(el);
|
||||
newEl.setAttribute('d', fixedD);
|
||||
}
|
||||
|
||||
// now create copies of all children
|
||||
el.childNodes.forEach(function(child){
|
||||
switch (child.nodeType) {
|
||||
|
|
|
@ -17,9 +17,6 @@ import {
|
|||
assignAttributes, getElem, getRotationAngle, snapToGrid, isNullish,
|
||||
getBBox as utilsGetBBox
|
||||
} from './utilities.js';
|
||||
import {
|
||||
isWebkit
|
||||
} from '../common/browser.js';
|
||||
|
||||
let pathActionsContext_ = null;
|
||||
let editorContext_ = null;
|
||||
|
@ -61,22 +58,24 @@ export const convertPath = function (pth, toRel) {
|
|||
let x2 = seg.x2 || 0;
|
||||
let y2 = seg.y2 || 0;
|
||||
|
||||
const type = seg.pathSegType;
|
||||
const pathMap = pathActionsContext_.getPathMap();
|
||||
let letter = pathMap[type][toRel ? 'toLowerCase' : 'toUpperCase']();
|
||||
// const type = seg.pathSegType;
|
||||
// const pathMap = pathActionsContext_.getPathMap();
|
||||
// let letter = pathMap[type][toRel ? 'toLowerCase' : 'toUpperCase']();
|
||||
let letter = seg.pathSegTypeAsLetter;
|
||||
|
||||
switch (type) {
|
||||
case 1: // z,Z closepath (Z/z)
|
||||
switch (letter) {
|
||||
case 'z': // z,Z closepath (Z/z)
|
||||
case 'Z':
|
||||
d += 'z';
|
||||
if (lastM && !toRel) {
|
||||
curx = lastM[0];
|
||||
cury = lastM[1];
|
||||
}
|
||||
break;
|
||||
case 12: // absolute horizontal line (H)
|
||||
case 'H': // absolute horizontal line (H)
|
||||
x -= curx;
|
||||
// Fallthrough
|
||||
case 13: // relative horizontal line (h)
|
||||
case 'h': // relative horizontal line (h)
|
||||
if (toRel) {
|
||||
y = 0;
|
||||
curx += x;
|
||||
|
@ -90,10 +89,10 @@ export const convertPath = function (pth, toRel) {
|
|||
// Convert to "line" for easier editing
|
||||
d += pathDSegment(letter, [ [ x, y ] ]);
|
||||
break;
|
||||
case 14: // absolute vertical line (V)
|
||||
case 'V': // absolute vertical line (V)
|
||||
y -= cury;
|
||||
// Fallthrough
|
||||
case 15: // relative vertical line (v)
|
||||
case 'v': // relative vertical line (v)
|
||||
if (toRel) {
|
||||
x = 0;
|
||||
cury += y;
|
||||
|
@ -107,71 +106,81 @@ export const convertPath = function (pth, toRel) {
|
|||
// Convert to "line" for easier editing
|
||||
d += pathDSegment(letter, [ [ x, y ] ]);
|
||||
break;
|
||||
case 2: // absolute move (M)
|
||||
case 4: // absolute line (L)
|
||||
case 18: // absolute smooth quad (T)
|
||||
case 10: // absolute elliptical arc (A)
|
||||
case 'M': // absolute move (M)
|
||||
case 'L': // absolute line (L)
|
||||
case 'T': // absolute smooth quad (T)
|
||||
x -= curx;
|
||||
y -= cury;
|
||||
// Fallthrough
|
||||
case 5: // relative line (l)
|
||||
case 3: // relative move (m)
|
||||
case 19: // relative smooth quad (t)
|
||||
case 'l': // relative line (l)
|
||||
case 'm': // relative move (m)
|
||||
case 't': // relative smooth quad (t)
|
||||
if (toRel) {
|
||||
curx += x;
|
||||
cury += y;
|
||||
letter = letter.toLowerCase();
|
||||
} else {
|
||||
x += curx;
|
||||
y += cury;
|
||||
curx = x;
|
||||
cury = y;
|
||||
letter = letter.toUpperCase();
|
||||
}
|
||||
if (type === 2 || type === 3) { lastM = [ curx, cury ]; }
|
||||
if (letter === 'm' || letter === 'M') { lastM = [ curx, cury ]; }
|
||||
|
||||
d += pathDSegment(letter, [ [ x, y ] ]);
|
||||
break;
|
||||
case 6: // absolute cubic (C)
|
||||
case 'C': // absolute cubic (C)
|
||||
x -= curx; x1 -= curx; x2 -= curx;
|
||||
y -= cury; y1 -= cury; y2 -= cury;
|
||||
// Fallthrough
|
||||
case 7: // relative cubic (c)
|
||||
case 'c': // relative cubic (c)
|
||||
if (toRel) {
|
||||
curx += x;
|
||||
cury += y;
|
||||
letter = 'c';
|
||||
} else {
|
||||
x += curx; x1 += curx; x2 += curx;
|
||||
y += cury; y1 += cury; y2 += cury;
|
||||
curx = x;
|
||||
cury = y;
|
||||
letter = 'C';
|
||||
}
|
||||
d += pathDSegment(letter, [ [ x1, y1 ], [ x2, y2 ], [ x, y ] ]);
|
||||
break;
|
||||
case 8: // absolute quad (Q)
|
||||
case 'Q': // absolute quad (Q)
|
||||
x -= curx; x1 -= curx;
|
||||
y -= cury; y1 -= cury;
|
||||
// Fallthrough
|
||||
case 9: // relative quad (q)
|
||||
case 'q': // relative quad (q)
|
||||
if (toRel) {
|
||||
curx += x;
|
||||
cury += y;
|
||||
letter = 'q';
|
||||
} else {
|
||||
x += curx; x1 += curx;
|
||||
y += cury; y1 += cury;
|
||||
curx = x;
|
||||
cury = y;
|
||||
letter = 'Q';
|
||||
}
|
||||
d += pathDSegment(letter, [ [ x1, y1 ], [ x, y ] ]);
|
||||
break;
|
||||
// Fallthrough
|
||||
case 11: // relative elliptical arc (a)
|
||||
case 'A':
|
||||
x -= curx;
|
||||
y -= cury;
|
||||
// fallthrough
|
||||
case 'a': // relative elliptical arc (a)
|
||||
if (toRel) {
|
||||
curx += x;
|
||||
cury += y;
|
||||
letter = 'a';
|
||||
} else {
|
||||
x += curx;
|
||||
y += cury;
|
||||
curx = x;
|
||||
cury = y;
|
||||
letter = 'A';
|
||||
}
|
||||
d += pathDSegment(letter, [ [ seg.r1, seg.r2 ] ], [
|
||||
seg.angle,
|
||||
|
@ -179,19 +188,21 @@ export const convertPath = function (pth, toRel) {
|
|||
(seg.sweepFlag ? 1 : 0)
|
||||
], [ x, y ]);
|
||||
break;
|
||||
case 16: // absolute smooth cubic (S)
|
||||
case 'S': // absolute smooth cubic (S)
|
||||
x -= curx; x2 -= curx;
|
||||
y -= cury; y2 -= cury;
|
||||
// Fallthrough
|
||||
case 17: // relative smooth cubic (s)
|
||||
case 's': // relative smooth cubic (s)
|
||||
if (toRel) {
|
||||
curx += x;
|
||||
cury += y;
|
||||
letter = 's';
|
||||
} else {
|
||||
x += curx; x2 += curx;
|
||||
y += cury; y2 += cury;
|
||||
curx = x;
|
||||
cury = y;
|
||||
letter = 'S';
|
||||
}
|
||||
d += pathDSegment(letter, [ [ x2, y2 ], [ x, y ] ]);
|
||||
break;
|
||||
|
@ -446,7 +457,6 @@ export const pathActionsMethod = (function () {
|
|||
if (path.matrix) {
|
||||
pathActionsContext_.recalcRotatedPath();
|
||||
}
|
||||
init();
|
||||
pathActionsMethod.toEditMode(path.elem);
|
||||
path.selectPt();
|
||||
return false;
|
||||
|
@ -758,6 +768,7 @@ export const pathActionsMethod = (function () {
|
|||
path = pathActionsContext_.getPath_(element);
|
||||
editorContext_.setCurrentMode('pathedit');
|
||||
editorContext_.clearSelection();
|
||||
path.setPathContext();
|
||||
path.show(true).update();
|
||||
path.oldbbox = utilsGetBBox(path.elem);
|
||||
subpath = false;
|
||||
|
@ -771,6 +782,7 @@ export const pathActionsMethod = (function () {
|
|||
editorContext_ = pathActionsContext_.getEditorContext();
|
||||
const selPath = (elem === path.elem);
|
||||
editorContext_.setCurrentMode('select');
|
||||
path.setPathContext();
|
||||
path.show(false);
|
||||
currentPath = false;
|
||||
editorContext_.clearSelection();
|
||||
|
@ -862,7 +874,7 @@ export const pathActionsMethod = (function () {
|
|||
const pathpointgripContainer = getElem('pathpointgrip_container');
|
||||
const elements = pathpointgripContainer.querySelectorAll('*');
|
||||
Array.prototype.forEach.call(elements, function(el){
|
||||
el.style.display = 'none';
|
||||
el.setAttribute('display', 'none');
|
||||
});
|
||||
firstCtrl = null;
|
||||
editorContext_.setDrawnPath(null);
|
||||
|
@ -1026,8 +1038,8 @@ export const pathActionsMethod = (function () {
|
|||
list.appendItem(newseg);
|
||||
list.appendItem(closer);
|
||||
} else {
|
||||
pathActionsContext_.insertItemBefore(elem, closer, openPt);
|
||||
pathActionsContext_.insertItemBefore(elem, newseg, openPt);
|
||||
list.insertItemBefore(closer, openPt);
|
||||
list.insertItemBefore(newseg, openPt);
|
||||
}
|
||||
|
||||
path.init().selectPt(openPt + 1);
|
||||
|
@ -1073,7 +1085,7 @@ export const pathActionsMethod = (function () {
|
|||
let num = (index - lastM) - 1;
|
||||
|
||||
while (num--) {
|
||||
pathActionsContext_.insertItemBefore(elem, list.getItem(lastM), zSeg);
|
||||
list.insertItemBefore(list.getItem(lastM), zSeg);
|
||||
}
|
||||
|
||||
const pt = list.getItem(lastM);
|
||||
|
@ -1178,7 +1190,7 @@ export const pathActionsMethod = (function () {
|
|||
* @returns {void}
|
||||
*/
|
||||
setSegType (v) {
|
||||
path.setSegType(v);
|
||||
path?.setSegType(v);
|
||||
},
|
||||
/**
|
||||
* @param {string} attr
|
||||
|
@ -1212,24 +1224,22 @@ export const pathActionsMethod = (function () {
|
|||
let lastM;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const item = segList.getItem(i);
|
||||
if (item.pathSegType === 2) {
|
||||
if (item.pathSegType === 2) { // 2 => M segment type (move to)
|
||||
lastM = item;
|
||||
}
|
||||
|
||||
if (item.pathSegType === 1) {
|
||||
if (item.pathSegType === 1) { // 1 => Z segment type (close path)
|
||||
const prev = segList.getItem(i - 1);
|
||||
if (prev.x !== lastM.x || prev.y !== lastM.y) {
|
||||
// Add an L segment here
|
||||
const newseg = elem.createSVGPathSegLinetoAbs(lastM.x, lastM.y);
|
||||
pathActionsContext_.insertItemBefore(elem, newseg, i);
|
||||
segList.insertItemBefore(newseg, i);
|
||||
// Can this be done better?
|
||||
pathActionsMethod.fixEnd(elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
editorContext_ = pathActionsContext_.getEditorContext();
|
||||
if (isWebkit()) { editorContext_.resetD(elem); }
|
||||
},
|
||||
// Can't seem to use `@borrows` here, so using `@see`
|
||||
/**
|
||||
|
|
|
@ -15,9 +15,6 @@ import {
|
|||
assignAttributes, getRotationAngle, isNullish,
|
||||
getElem
|
||||
} from './utilities.js';
|
||||
import {
|
||||
supportsPathInsertItemBefore, supportsPathReplaceItem, isWebkit
|
||||
} from '../common/browser.js';
|
||||
|
||||
let pathMethodsContext_ = null;
|
||||
let editorContext_ = null;
|
||||
|
@ -31,35 +28,6 @@ export const init = function (pathMethodsContext) {
|
|||
pathMethodsContext_ = pathMethodsContext;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function module:path.insertItemBefore
|
||||
* @param {Element} elem
|
||||
* @param {Segment} newseg
|
||||
* @param {Integer} index
|
||||
* @returns {void}
|
||||
*/
|
||||
export const insertItemBeforeMethod = function (elem, newseg, index) {
|
||||
// Support insertItemBefore on paths for FF2
|
||||
const list = elem.pathSegList;
|
||||
|
||||
if (supportsPathInsertItemBefore()) {
|
||||
list.insertItemBefore(newseg, index);
|
||||
return;
|
||||
}
|
||||
const len = list.numberOfItems;
|
||||
const arr = [];
|
||||
for (let i = 0; i < len; i++) {
|
||||
const curSeg = list.getItem(i);
|
||||
arr.push(curSeg);
|
||||
}
|
||||
list.clear();
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (i === index) { // index + 1
|
||||
list.appendItem(newseg);
|
||||
}
|
||||
list.appendItem(arr[i]);
|
||||
}
|
||||
};
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* @function module:path.ptObjToArr
|
||||
|
@ -324,25 +292,7 @@ export const replacePathSegMethod = function (type, index, pts, elem) {
|
|||
const func = 'createSVGPathSeg' + pathFuncs[type];
|
||||
const seg = pth[func](...pts);
|
||||
|
||||
if (supportsPathReplaceItem()) {
|
||||
pth.pathSegList.replaceItem(seg, index);
|
||||
} else {
|
||||
const segList = pth.pathSegList;
|
||||
const len = segList.numberOfItems;
|
||||
const arr = [];
|
||||
for (let i = 0; i < len; i++) {
|
||||
const curSeg = segList.getItem(i);
|
||||
arr.push(curSeg);
|
||||
}
|
||||
segList.clear();
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (i === index) {
|
||||
segList.appendItem(seg);
|
||||
} else {
|
||||
segList.appendItem(arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
pth.pathSegList.replaceItem(seg, index);
|
||||
};
|
||||
/**
|
||||
* @function module:path.getSegSelector
|
||||
|
@ -629,6 +579,10 @@ export class Path {
|
|||
this.init();
|
||||
}
|
||||
|
||||
setPathContext() {
|
||||
pathMethodsContext_.setPathObj(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset path data.
|
||||
* @returns {module:path.Path}
|
||||
|
@ -640,7 +594,7 @@ export class Path {
|
|||
const pointGripContainer = getGripContainerMethod();
|
||||
const elements = pointGripContainer.querySelectorAll('*');
|
||||
Array.prototype.forEach.call(elements, function(el){
|
||||
el.style.display = 'none';
|
||||
el.setAttribute('display', 'none');
|
||||
});
|
||||
|
||||
const segList = this.elem.pathSegList;
|
||||
|
@ -771,8 +725,8 @@ export class Path {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
insertItemBeforeMethod(this.elem, newseg, index);
|
||||
const list = this.elem.pathSegList;
|
||||
list.insertItemBefore(newseg, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1001,7 +955,6 @@ export class Path {
|
|||
* @returns {void}
|
||||
*/
|
||||
endChanges (text) {
|
||||
if (isWebkit()) { editorContext_.resetD(this.elem); }
|
||||
const cmd = new ChangeElementCommand(this.elem, { d: this.last_d }, text);
|
||||
editorContext_.endChanges({ cmd, elem: this.elem });
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
getBBox as utilsGetBBox
|
||||
} from './utilities.js';
|
||||
import {
|
||||
init as pathMethodInit, insertItemBeforeMethod, ptObjToArrMethod, getGripPtMethod,
|
||||
init as pathMethodInit, ptObjToArrMethod, getGripPtMethod,
|
||||
getPointFromGripMethod, addPointGripMethod, getGripContainerMethod, addCtrlGripMethod,
|
||||
getCtrlLineMethod, getPointGripMethod, getControlPointsMethod, replacePathSegMethod,
|
||||
getSegSelectorMethod, Path
|
||||
|
@ -103,11 +103,6 @@ let editorContext_ = null;
|
|||
* If the event is "changed", an array of `Element`s is passed; if "selected", a single-item array of `Element` is passed.
|
||||
* @returns {void}
|
||||
*/
|
||||
/**
|
||||
* @function module:path.EditorContext#resetD
|
||||
* @param {SVGPathElement} p
|
||||
* @returns {void}
|
||||
*/
|
||||
/**
|
||||
* Note: This doesn't round to an integer necessarily.
|
||||
* @function module:path.EditorContext#round
|
||||
|
@ -263,14 +258,6 @@ pathMethodInit(
|
|||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @function module:path.insertItemBefore
|
||||
* @param {Element} elem
|
||||
* @param {Segment} newseg
|
||||
* @param {Integer} index
|
||||
* @returns {void}
|
||||
*/
|
||||
export const insertItemBefore = insertItemBeforeMethod;
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* @function module:path.ptObjToArr
|
||||
|
@ -801,7 +788,6 @@ pathActionsInit(
|
|||
addCtrlGrip,
|
||||
getCtrlLine,
|
||||
replacePathSeg,
|
||||
insertItemBefore,
|
||||
getPointFromGrip,
|
||||
getGripPt,
|
||||
getPath_,
|
||||
|
|
|
@ -324,12 +324,14 @@ export const groupSvgElem = function (elem) {
|
|||
* @returns {void}
|
||||
*/
|
||||
export const prepareSvg = function (newDoc) {
|
||||
|
||||
svgCanvas.sanitizeSvg(newDoc.documentElement);
|
||||
|
||||
// convert paths into absolute commands
|
||||
const paths = [ ...newDoc.getElementsByTagNameNS(NS.SVG, 'path') ];
|
||||
paths.forEach((path) => {
|
||||
path.setAttribute('d', svgCanvas.pathActions.convertPath(path));
|
||||
const convertedPath = svgCanvas.pathActions.convertPath(path);
|
||||
path.setAttribute('d', convertedPath);
|
||||
svgCanvas.pathActions.fixEnd(path);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
import { Canvg as canvg } from 'canvg';
|
||||
import 'pathseg';
|
||||
import 'pathseg'; // SVGPathSeg Polyfill (see https://github.com/progers/pathseg)
|
||||
|
||||
import * as pathModule from './path.js';
|
||||
import * as hstry from './history.js';
|
||||
|
@ -668,16 +668,6 @@ class SvgCanvas {
|
|||
* @see module:path.pathActions
|
||||
*/
|
||||
canvas.pathActions = pathActions;
|
||||
/**
|
||||
* @type {module:path.EditorContext#resetD}
|
||||
*/
|
||||
function resetD(p) {
|
||||
if (typeof pathActions.convertPath === 'function') {
|
||||
p.setAttribute('d', pathActions.convertPath(p));
|
||||
} else if (typeof pathActions.convertPaths === 'function') {
|
||||
p.setAttribute('d', pathActions.convertPaths(p));
|
||||
}
|
||||
}
|
||||
pathModule.init(
|
||||
/**
|
||||
* @implements {module:path.EditorContext}
|
||||
|
@ -686,7 +676,6 @@ class SvgCanvas {
|
|||
selectorManager, // Ok since not changing
|
||||
canvas, // Ok since not changing
|
||||
call,
|
||||
resetD,
|
||||
round,
|
||||
clearSelection,
|
||||
addToSelection,
|
||||
|
|
|
@ -12,13 +12,10 @@ import {
|
|||
hasMatrixTransform, transformListToTransform, transformBox
|
||||
} from './math.js';
|
||||
import {
|
||||
isWebkit, supportsHVLineContainerBBox, supportsPathBBox
|
||||
isWebkit, supportsHVLineContainerBBox
|
||||
} from '../common/browser.js';
|
||||
import { getClosest, mergeDeep } from '../editor/components/jgraduate/Util.js';
|
||||
|
||||
// String used to encode base64.
|
||||
const KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
|
||||
// Much faster than running getBBox() every time
|
||||
const visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use,clipPath';
|
||||
const visElemsArr = visElems.split(',');
|
||||
|
@ -137,41 +134,7 @@ export const toXml = function (str) {
|
|||
export 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
|
||||
}
|
||||
const output = new Array(Math.floor((input.length + 2) / 3) * 4);
|
||||
|
||||
let i = 0;
|
||||
let p = 0;
|
||||
do {
|
||||
const chr1 = input.charCodeAt(i++);
|
||||
const chr2 = input.charCodeAt(i++);
|
||||
const chr3 = input.charCodeAt(i++);
|
||||
|
||||
/* eslint-disable no-bitwise */
|
||||
const enc1 = chr1 >> 2;
|
||||
const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
|
||||
let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
let 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('');
|
||||
return window.btoa(input); // Use native if available
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,38 +144,7 @@ export function encode64(input) {
|
|||
* @returns {string} Decoded output
|
||||
*/
|
||||
export 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, '');
|
||||
|
||||
let output = '';
|
||||
let i = 0;
|
||||
|
||||
do {
|
||||
const enc1 = KEYSTR.indexOf(input.charAt(i++));
|
||||
const enc2 = KEYSTR.indexOf(input.charAt(i++));
|
||||
const enc3 = KEYSTR.indexOf(input.charAt(i++));
|
||||
const enc4 = KEYSTR.indexOf(input.charAt(i++));
|
||||
|
||||
/* eslint-disable no-bitwise */
|
||||
const chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
const 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);
|
||||
return decodeUTF8(window.atob(input));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -315,17 +247,13 @@ export const text2xml = function (sXML) {
|
|||
|
||||
let out; let dXML;
|
||||
try {
|
||||
dXML = (window.DOMParser) ? new DOMParser() : new window.ActiveXObject('Microsoft.XMLDOM');
|
||||
dXML = new DOMParser();
|
||||
dXML.async = false;
|
||||
} catch (e) {
|
||||
throw new Error('XML Parser could not be instantiated');
|
||||
}
|
||||
try {
|
||||
if (dXML.loadXML) {
|
||||
out = (dXML.loadXML(sXML)) ? dXML : false;
|
||||
} else {
|
||||
out = dXML.parseFromString(sXML, 'text/xml');
|
||||
}
|
||||
out = dXML.parseFromString(sXML, 'text/xml');
|
||||
} catch (e2) { throw new Error('Error parsing XML string'); }
|
||||
return out;
|
||||
};
|
||||
|
@ -618,9 +546,7 @@ export const getBBox = function (elem) {
|
|||
}
|
||||
break;
|
||||
case 'path':
|
||||
if (!supportsPathBBox()) {
|
||||
ret = getPathBBox(selected);
|
||||
} else if (selected.getBBox) {
|
||||
if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
|
@ -1049,7 +975,7 @@ export const getStrokedBBox = function (elems, addSVGElementFromJson, pathAction
|
|||
});
|
||||
|
||||
// This shouldn't ever happen...
|
||||
if (fullBb === undefined) { return null; }
|
||||
if (!fullBb) { return null; }
|
||||
|
||||
// fullBb doesn't include the stoke, so this does no good!
|
||||
// if (elems.length == 1) return fullBb;
|
||||
|
|
Loading…
Reference in New Issue