Merge pull request #628 from SVG-Edit/fix-transformation-issues
This commit is contained in:
@@ -1,14 +1,10 @@
|
|||||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
import { NS } from '../../../instrumented/common/namespaces.js';
|
||||||
import * as transformlist from '../../../instrumented/svgcanvas/svgtransformlist.js';
|
|
||||||
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
||||||
import * as hstory from '../../../instrumented/svgcanvas/history.js';
|
import * as hstory from '../../../instrumented/svgcanvas/history.js';
|
||||||
|
|
||||||
describe('history', function () {
|
describe('history', function () {
|
||||||
// TODO(codedread): Write tests for handling history events.
|
// TODO(codedread): Write tests for handling history events.
|
||||||
|
|
||||||
// Mocked out methods.
|
|
||||||
transformlist.changeRemoveElementFromListMap(() => { /* empty fn */ });
|
|
||||||
|
|
||||||
utilities.mock({
|
utilities.mock({
|
||||||
getHref () { return '#foo'; },
|
getHref () { return '#foo'; },
|
||||||
setHref () { /* empty fn */ },
|
setHref () { /* empty fn */ },
|
||||||
|
|||||||
@@ -1,330 +0,0 @@
|
|||||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
|
||||||
import * as transformlist from '../../../instrumented/svgcanvas/svgtransformlist.js';
|
|
||||||
import { disableSupportsNativeTransformLists } from '../../../instrumented/common/browser.js';
|
|
||||||
|
|
||||||
import almostEqualsPlugin from '../../support/assert-almostEquals.js';
|
|
||||||
import expectOutOfBoundsExceptionPlugin from '../../support/assert-expectOutOfBoundsException.js';
|
|
||||||
|
|
||||||
chai.use(almostEqualsPlugin);
|
|
||||||
chai.use(expectOutOfBoundsExceptionPlugin);
|
|
||||||
|
|
||||||
describe('svgtransformlist', function () {
|
|
||||||
disableSupportsNativeTransformLists();
|
|
||||||
|
|
||||||
let svgroot; let svgcontent; let rect; let circle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up tests, adding elements.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.textContent = '';
|
|
||||||
svgroot = document.createElement('div');
|
|
||||||
svgroot.id = 'svgroot';
|
|
||||||
svgroot.style.visibility = 'hidden';
|
|
||||||
document.body.append(svgroot);
|
|
||||||
|
|
||||||
svgcontent = document.createElementNS(NS.SVG, 'svg');
|
|
||||||
svgroot.append(svgcontent);
|
|
||||||
rect = document.createElementNS(NS.SVG, 'rect');
|
|
||||||
svgcontent.append(rect);
|
|
||||||
rect.id = 'r';
|
|
||||||
circle = document.createElementNS(NS.SVG, 'circle');
|
|
||||||
svgcontent.append(circle);
|
|
||||||
circle.id = 'c';
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tear down tests, emptying SVG root, and resetting list map.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
afterEach(() => {
|
|
||||||
transformlist.resetListMap();
|
|
||||||
while (svgroot.hasChildNodes()) {
|
|
||||||
svgroot.firstChild.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test svgedit.transformlist package', function () {
|
|
||||||
assert.ok(transformlist);
|
|
||||||
assert.ok(transformlist.getTransformList);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test svgedit.transformlist.getTransformList() function', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
const cxform = transformlist.getTransformList(circle);
|
|
||||||
|
|
||||||
assert.ok(rxform);
|
|
||||||
assert.ok(cxform);
|
|
||||||
assert.equal(typeof rxform, typeof {});
|
|
||||||
assert.equal(typeof cxform, typeof {});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.numberOfItems property', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
|
|
||||||
assert.equal(typeof rxform.numberOfItems, typeof 0);
|
|
||||||
assert.equal(rxform.numberOfItems, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.initialize()', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
const cxform = transformlist.getTransformList(circle);
|
|
||||||
|
|
||||||
const t = svgcontent.createSVGTransform();
|
|
||||||
assert.ok(t);
|
|
||||||
assert.ok(rxform.initialize);
|
|
||||||
assert.equal(typeof rxform.initialize, typeof function () { /* empty fn */ });
|
|
||||||
rxform.initialize(t);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
assert.equal(cxform.numberOfItems, 0);
|
|
||||||
|
|
||||||
// If a transform was already in a transform list, this should
|
|
||||||
// remove it from its old list and add it to this list.
|
|
||||||
cxform.initialize(t);
|
|
||||||
// This also fails in Firefox native.
|
|
||||||
// assert.equal(rxform.numberOfItems, 0, 'Did not remove transform from list before initializing another transformlist');
|
|
||||||
assert.equal(cxform.numberOfItems, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.appendItem() and getItem()', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
const cxform = transformlist.getTransformList(circle);
|
|
||||||
|
|
||||||
const t1 = svgcontent.createSVGTransform();
|
|
||||||
const t2 = svgcontent.createSVGTransform();
|
|
||||||
const t3 = svgcontent.createSVGTransform();
|
|
||||||
|
|
||||||
assert.ok(rxform.appendItem);
|
|
||||||
assert.ok(rxform.getItem);
|
|
||||||
assert.equal(typeof rxform.appendItem, typeof function () { /* empty fn */ });
|
|
||||||
assert.equal(typeof rxform.getItem, typeof function () { /* empty fn */ });
|
|
||||||
|
|
||||||
rxform.appendItem(t1);
|
|
||||||
rxform.appendItem(t2);
|
|
||||||
rxform.appendItem(t3);
|
|
||||||
|
|
||||||
assert.equal(rxform.numberOfItems, 3);
|
|
||||||
const rxf = rxform.getItem(0);
|
|
||||||
assert.equal(rxf, t1);
|
|
||||||
assert.equal(rxform.getItem(1), t2);
|
|
||||||
assert.equal(rxform.getItem(2), t3);
|
|
||||||
|
|
||||||
assert.expectOutOfBoundsException(rxform, 'getItem', -1);
|
|
||||||
assert.expectOutOfBoundsException(rxform, 'getItem', 3);
|
|
||||||
cxform.appendItem(t1);
|
|
||||||
// These also fail in Firefox native.
|
|
||||||
// assert.equal(rxform.numberOfItems, 2, 'Did not remove a transform from a list before appending it to a new transformlist');
|
|
||||||
// assert.equal(rxform.getItem(0), t2, 'Found the wrong transform in a transformlist');
|
|
||||||
// assert.equal(rxform.getItem(1), t3, 'Found the wrong transform in a transformlist');
|
|
||||||
|
|
||||||
assert.equal(cxform.numberOfItems, 1);
|
|
||||||
assert.equal(cxform.getItem(0), t1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.removeItem()', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
|
|
||||||
const t1 = svgcontent.createSVGTransform();
|
|
||||||
const t2 = svgcontent.createSVGTransform();
|
|
||||||
assert.ok(rxform.removeItem);
|
|
||||||
assert.equal(typeof rxform.removeItem, typeof function () { /* empty fn */ });
|
|
||||||
rxform.appendItem(t1);
|
|
||||||
rxform.appendItem(t2);
|
|
||||||
|
|
||||||
const removedTransform = rxform.removeItem(0);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
assert.equal(removedTransform, t1);
|
|
||||||
assert.equal(rxform.getItem(0), t2);
|
|
||||||
|
|
||||||
assert.expectOutOfBoundsException(rxform, 'removeItem', -1);
|
|
||||||
assert.expectOutOfBoundsException(rxform, 'removeItem', 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.replaceItem()', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
const cxform = transformlist.getTransformList(circle);
|
|
||||||
|
|
||||||
assert.ok(rxform.replaceItem);
|
|
||||||
assert.equal(typeof rxform.replaceItem, typeof function () { /* empty fn */ });
|
|
||||||
|
|
||||||
const t1 = svgcontent.createSVGTransform();
|
|
||||||
const t2 = svgcontent.createSVGTransform();
|
|
||||||
const t3 = svgcontent.createSVGTransform();
|
|
||||||
|
|
||||||
rxform.appendItem(t1);
|
|
||||||
rxform.appendItem(t2);
|
|
||||||
cxform.appendItem(t3);
|
|
||||||
|
|
||||||
const newItem = rxform.replaceItem(t3, 0);
|
|
||||||
assert.equal(rxform.numberOfItems, 2);
|
|
||||||
assert.equal(newItem, t3);
|
|
||||||
assert.equal(rxform.getItem(0), t3);
|
|
||||||
assert.equal(rxform.getItem(1), t2);
|
|
||||||
// Fails in Firefox native
|
|
||||||
// assert.equal(cxform.numberOfItems, 0);
|
|
||||||
|
|
||||||
// test replaceItem within a list
|
|
||||||
rxform.appendItem(t1);
|
|
||||||
rxform.replaceItem(t1, 0);
|
|
||||||
// Fails in Firefox native
|
|
||||||
// assert.equal(rxform.numberOfItems, 2);
|
|
||||||
assert.equal(rxform.getItem(0), t1);
|
|
||||||
assert.equal(rxform.getItem(1), t2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.insertItemBefore()', function () {
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
const cxform = transformlist.getTransformList(circle);
|
|
||||||
|
|
||||||
assert.ok(rxform.insertItemBefore);
|
|
||||||
assert.equal(typeof rxform.insertItemBefore, typeof function () { /* empty fn */ });
|
|
||||||
|
|
||||||
const t1 = svgcontent.createSVGTransform();
|
|
||||||
const t2 = svgcontent.createSVGTransform();
|
|
||||||
const t3 = svgcontent.createSVGTransform();
|
|
||||||
|
|
||||||
rxform.appendItem(t1);
|
|
||||||
rxform.appendItem(t2);
|
|
||||||
cxform.appendItem(t3);
|
|
||||||
|
|
||||||
const newItem = rxform.insertItemBefore(t3, 0);
|
|
||||||
assert.equal(rxform.numberOfItems, 3);
|
|
||||||
assert.equal(newItem, t3);
|
|
||||||
assert.equal(rxform.getItem(0), t3);
|
|
||||||
assert.equal(rxform.getItem(1), t1);
|
|
||||||
assert.equal(rxform.getItem(2), t2);
|
|
||||||
// Fails in Firefox native
|
|
||||||
// assert.equal(cxform.numberOfItems, 0);
|
|
||||||
|
|
||||||
rxform.insertItemBefore(t2, 1);
|
|
||||||
// Fails in Firefox native (they make copies of the transforms)
|
|
||||||
// assert.equal(rxform.numberOfItems, 3);
|
|
||||||
assert.equal(rxform.getItem(0), t3);
|
|
||||||
assert.equal(rxform.getItem(1), t2);
|
|
||||||
assert.equal(rxform.getItem(2), t1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.init() for translate(200,100)', function () {
|
|
||||||
rect.setAttribute('transform', 'translate(200,100)');
|
|
||||||
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
|
|
||||||
const translate = rxform.getItem(0);
|
|
||||||
assert.equal(translate.type, 2);
|
|
||||||
|
|
||||||
const m = translate.matrix;
|
|
||||||
assert.equal(m.a, 1);
|
|
||||||
assert.equal(m.b, 0);
|
|
||||||
assert.equal(m.c, 0);
|
|
||||||
assert.equal(m.d, 1);
|
|
||||||
assert.equal(m.e, 200);
|
|
||||||
assert.equal(m.f, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.init() for scale(4)', function () {
|
|
||||||
rect.setAttribute('transform', 'scale(4)');
|
|
||||||
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
|
|
||||||
const scale = rxform.getItem(0);
|
|
||||||
assert.equal(scale.type, 3);
|
|
||||||
|
|
||||||
const m = scale.matrix;
|
|
||||||
assert.equal(m.a, 4);
|
|
||||||
assert.equal(m.b, 0);
|
|
||||||
assert.equal(m.c, 0);
|
|
||||||
assert.equal(m.d, 4);
|
|
||||||
assert.equal(m.e, 0);
|
|
||||||
assert.equal(m.f, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.init() for scale(4,3)', function () {
|
|
||||||
rect.setAttribute('transform', 'scale(4,3)');
|
|
||||||
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
|
|
||||||
const scale = rxform.getItem(0);
|
|
||||||
assert.equal(scale.type, 3);
|
|
||||||
|
|
||||||
const m = scale.matrix;
|
|
||||||
assert.equal(m.a, 4);
|
|
||||||
assert.equal(m.b, 0);
|
|
||||||
assert.equal(m.c, 0);
|
|
||||||
assert.equal(m.d, 3);
|
|
||||||
assert.equal(m.e, 0);
|
|
||||||
assert.equal(m.f, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.init() for rotate(45)', function () {
|
|
||||||
rect.setAttribute('transform', 'rotate(45)');
|
|
||||||
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
|
|
||||||
const rotate = rxform.getItem(0);
|
|
||||||
assert.equal(rotate.type, 4);
|
|
||||||
assert.equal(rotate.angle, 45);
|
|
||||||
|
|
||||||
const m = rotate.matrix;
|
|
||||||
assert.almostEquals(1 / Math.sqrt(2), m.a);
|
|
||||||
assert.almostEquals(1 / Math.sqrt(2), m.b);
|
|
||||||
assert.almostEquals(-1 / Math.sqrt(2), m.c);
|
|
||||||
assert.almostEquals(1 / Math.sqrt(2), m.d);
|
|
||||||
assert.equal(m.e, 0);
|
|
||||||
assert.equal(m.f, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.init() for rotate(45, 100, 200)', function () {
|
|
||||||
rect.setAttribute('transform', 'rotate(45, 100, 200)');
|
|
||||||
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
|
|
||||||
const rotate = rxform.getItem(0);
|
|
||||||
assert.equal(rotate.type, 4);
|
|
||||||
assert.equal(rotate.angle, 45);
|
|
||||||
|
|
||||||
const m = rotate.matrix;
|
|
||||||
assert.almostEquals(m.a, 1 / Math.sqrt(2));
|
|
||||||
assert.almostEquals(m.b, 1 / Math.sqrt(2));
|
|
||||||
assert.almostEquals(m.c, -1 / Math.sqrt(2));
|
|
||||||
assert.almostEquals(m.d, 1 / Math.sqrt(2));
|
|
||||||
|
|
||||||
const r = svgcontent.createSVGMatrix();
|
|
||||||
r.a = 1 / Math.sqrt(2); r.b = 1 / Math.sqrt(2);
|
|
||||||
r.c = -1 / Math.sqrt(2); r.d = 1 / Math.sqrt(2);
|
|
||||||
|
|
||||||
const t = svgcontent.createSVGMatrix();
|
|
||||||
t.e = -100; t.f = -200;
|
|
||||||
|
|
||||||
const t_ = svgcontent.createSVGMatrix();
|
|
||||||
t_.e = 100; t_.f = 200;
|
|
||||||
|
|
||||||
const result = t_.multiply(r).multiply(t);
|
|
||||||
|
|
||||||
assert.almostEquals(m.e, result.e);
|
|
||||||
assert.almostEquals(m.f, result.f);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test SVGTransformList.init() for matrix(1, 2, 3, 4, 5, 6)', function () {
|
|
||||||
rect.setAttribute('transform', 'matrix(1,2,3,4,5,6)');
|
|
||||||
|
|
||||||
const rxform = transformlist.getTransformList(rect);
|
|
||||||
assert.equal(rxform.numberOfItems, 1);
|
|
||||||
|
|
||||||
const mt = rxform.getItem(0);
|
|
||||||
assert.equal(mt.type, 1);
|
|
||||||
|
|
||||||
const m = mt.matrix;
|
|
||||||
assert.equal(m.a, 1);
|
|
||||||
assert.equal(m.b, 2);
|
|
||||||
assert.equal(m.c, 3);
|
|
||||||
assert.equal(m.d, 4);
|
|
||||||
assert.equal(m.e, 5);
|
|
||||||
assert.equal(m.f, 6);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -3,7 +3,6 @@ import 'pathseg';
|
|||||||
|
|
||||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
import { NS } from '../../../instrumented/common/namespaces.js';
|
||||||
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
||||||
import * as transformlist from '../../../instrumented/svgcanvas/svgtransformlist.js';
|
|
||||||
import * as math from '../../../instrumented/svgcanvas/math.js';
|
import * as math from '../../../instrumented/svgcanvas/math.js';
|
||||||
import * as path from '../../../instrumented/svgcanvas/path.js';
|
import * as path from '../../../instrumented/svgcanvas/path.js';
|
||||||
import setAssertionMethods from '../../support/assert-close.js';
|
import setAssertionMethods from '../../support/assert-close.js';
|
||||||
@@ -39,7 +38,7 @@ describe('utilities bbox', function () {
|
|||||||
const mockPathActions = {
|
const mockPathActions = {
|
||||||
resetOrientation (pth) {
|
resetOrientation (pth) {
|
||||||
if (utilities.isNullish(pth) || pth.nodeName !== 'path') { return false; }
|
if (utilities.isNullish(pth) || pth.nodeName !== 'path') { return false; }
|
||||||
const tlist = transformlist.getTransformList(pth);
|
const tlist = pth.transform.baseVal;
|
||||||
const m = math.transformListToTransform(tlist).matrix;
|
const m = math.transformListToTransform(tlist).matrix;
|
||||||
tlist.clear();
|
tlist.clear();
|
||||||
pth.removeAttribute('transform');
|
pth.removeAttribute('transform');
|
||||||
@@ -84,8 +83,6 @@ describe('utilities bbox', function () {
|
|||||||
});
|
});
|
||||||
sandbox.append(svgroot);
|
sandbox.append(svgroot);
|
||||||
|
|
||||||
// We're reusing ID's so we need to do this for transforms.
|
|
||||||
transformlist.resetListMap();
|
|
||||||
path.init(null);
|
path.init(null);
|
||||||
mockaddSVGElementFromJsonCallCount = 0;
|
mockaddSVGElementFromJsonCallCount = 0;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import 'pathseg';
|
|||||||
|
|
||||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
import { NS } from '../../../instrumented/common/namespaces.js';
|
||||||
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
||||||
import * as transformlist from '../../../instrumented/svgcanvas/svgtransformlist.js';
|
|
||||||
import * as math from '../../../instrumented/svgcanvas/math.js';
|
import * as math from '../../../instrumented/svgcanvas/math.js';
|
||||||
|
|
||||||
describe('utilities performance', function () {
|
describe('utilities performance', function () {
|
||||||
@@ -118,7 +117,7 @@ describe('utilities performance', function () {
|
|||||||
const mockPathActions = {
|
const mockPathActions = {
|
||||||
resetOrientation (path) {
|
resetOrientation (path) {
|
||||||
if (utilities.isNullish(path) || path.nodeName !== 'path') { return false; }
|
if (utilities.isNullish(path) || path.nodeName !== 'path') { return false; }
|
||||||
const tlist = transformlist.getTransformList(path);
|
const tlist = path.transform.baseVal;
|
||||||
const m = math.transformListToTransform(tlist).matrix;
|
const m = math.transformListToTransform(tlist).matrix;
|
||||||
tlist.clear();
|
tlist.clear();
|
||||||
path.removeAttribute('transform');
|
path.removeAttribute('transform');
|
||||||
|
|||||||
@@ -113,17 +113,6 @@ describe('utilities', function () {
|
|||||||
assert.equal(toXml('\'<&>"'), ''<&>"');
|
assert.equal(toXml('\'<&>"'), ''<&>"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Test svgedit.utilities.fromXml() function', function () {
|
|
||||||
const { fromXml } = utilities;
|
|
||||||
|
|
||||||
assert.equal(fromXml('a'), 'a');
|
|
||||||
assert.equal(fromXml('ABC_'), 'ABC_');
|
|
||||||
assert.equal(fromXml('PB&J'), 'PB&J');
|
|
||||||
assert.equal(fromXml('2 < 5'), '2 < 5');
|
|
||||||
assert.equal(fromXml('5 > 2'), '5 > 2');
|
|
||||||
assert.equal(fromXml('<&>'), '<&>');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test svgedit.utilities.encode64() function', function () {
|
it('Test svgedit.utilities.encode64() function', function () {
|
||||||
const { encode64 } = utilities;
|
const { encode64 } = utilities;
|
||||||
|
|
||||||
|
|||||||
518
package-lock.json
generated
518
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -79,7 +79,7 @@
|
|||||||
"@babel/polyfill": "7.12.1",
|
"@babel/polyfill": "7.12.1",
|
||||||
"browser-fs-access": "^0.20.4",
|
"browser-fs-access": "^0.20.4",
|
||||||
"canvg": "3.0.7",
|
"canvg": "3.0.7",
|
||||||
"core-js": "3.16.2",
|
"core-js": "3.16.3",
|
||||||
"elix": "15.0.0",
|
"elix": "15.0.0",
|
||||||
"html2canvas": "1.3.2",
|
"html2canvas": "1.3.2",
|
||||||
"i18next": "20.4.0",
|
"i18next": "20.4.0",
|
||||||
@@ -103,14 +103,14 @@
|
|||||||
"@rollup/plugin-node-resolve": "13.0.4",
|
"@rollup/plugin-node-resolve": "13.0.4",
|
||||||
"@rollup/plugin-replace": "3.0.0",
|
"@rollup/plugin-replace": "3.0.0",
|
||||||
"@rollup/plugin-url": "6.1.0",
|
"@rollup/plugin-url": "6.1.0",
|
||||||
"@web/dev-server": "0.1.21",
|
"@web/dev-server": "0.1.22",
|
||||||
"@web/dev-server-rollup": "0.3.9",
|
"@web/dev-server-rollup": "0.3.9",
|
||||||
"axe-core": "4.3.2",
|
"axe-core": "4.3.3",
|
||||||
"babel-plugin-transform-object-rest-spread": "7.0.0-beta.3",
|
"babel-plugin-transform-object-rest-spread": "7.0.0-beta.3",
|
||||||
"copyfiles": "2.4.1",
|
"copyfiles": "2.4.1",
|
||||||
"core-js-bundle": "3.16.2",
|
"core-js-bundle": "3.16.3",
|
||||||
"cp-cli": "2.0.0",
|
"cp-cli": "2.0.0",
|
||||||
"cypress": "8.3.0",
|
"cypress": "8.3.1",
|
||||||
"cypress-axe": "0.13.0",
|
"cypress-axe": "0.13.0",
|
||||||
"cypress-multi-reporters": "1.5.0",
|
"cypress-multi-reporters": "1.5.0",
|
||||||
"cypress-plugin-snapshots": "1.4.4",
|
"cypress-plugin-snapshots": "1.4.4",
|
||||||
@@ -120,12 +120,12 @@
|
|||||||
"eslint-plugin-chai-expect": "2.2.0",
|
"eslint-plugin-chai-expect": "2.2.0",
|
||||||
"eslint-plugin-chai-expect-keywords": "2.1.0",
|
"eslint-plugin-chai-expect-keywords": "2.1.0",
|
||||||
"eslint-plugin-chai-friendly": "0.7.2",
|
"eslint-plugin-chai-friendly": "0.7.2",
|
||||||
"eslint-plugin-compat": "3.12.0",
|
"eslint-plugin-compat": "3.13.0",
|
||||||
"eslint-plugin-cypress": "2.11.3",
|
"eslint-plugin-cypress": "2.11.3",
|
||||||
"eslint-plugin-eslint-comments": "3.2.0",
|
"eslint-plugin-eslint-comments": "3.2.0",
|
||||||
"eslint-plugin-html": "6.1.2",
|
"eslint-plugin-html": "6.1.2",
|
||||||
"eslint-plugin-import": "2.24.0",
|
"eslint-plugin-import": "2.24.2",
|
||||||
"eslint-plugin-jsdoc": "36.0.7",
|
"eslint-plugin-jsdoc": "36.0.8",
|
||||||
"eslint-plugin-markdown": "2.2.0",
|
"eslint-plugin-markdown": "2.2.0",
|
||||||
"eslint-plugin-no-unsanitized": "3.1.5",
|
"eslint-plugin-no-unsanitized": "3.1.5",
|
||||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
"remark-cli": "10.0.0",
|
"remark-cli": "10.0.0",
|
||||||
"remark-lint-ordered-list-marker-value": "3.0.1",
|
"remark-lint-ordered-list-marker-value": "3.0.1",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"rollup": "2.56.2",
|
"rollup": "2.56.3",
|
||||||
"rollup-plugin-copy": "3.4.0",
|
"rollup-plugin-copy": "3.4.0",
|
||||||
"rollup-plugin-filesize": "9.1.1",
|
"rollup-plugin-filesize": "9.1.1",
|
||||||
"rollup-plugin-node-polyfills": "0.2.1",
|
"rollup-plugin-node-polyfills": "0.2.1",
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import 'pathseg';
|
|||||||
import { NS } from './namespaces.js';
|
import { NS } from './namespaces.js';
|
||||||
|
|
||||||
const { userAgent } = navigator;
|
const { userAgent } = navigator;
|
||||||
const svg = document.createElementNS(NS.SVG, 'svg');
|
|
||||||
|
|
||||||
// Note: Browser sniffing should only be used if no other detection method is possible
|
// Note: Browser sniffing should only be used if no other detection method is possible
|
||||||
const isWebkit_ = userAgent.includes('AppleWebKit');
|
const isWebkit_ = userAgent.includes('AppleWebKit');
|
||||||
@@ -99,26 +98,6 @@ const supportsNonScalingStroke_ = (function () {
|
|||||||
return rect.style.vectorEffect === 'non-scaling-stroke';
|
return rect.style.vectorEffect === 'non-scaling-stroke';
|
||||||
}());
|
}());
|
||||||
|
|
||||||
let supportsNativeSVGTransformLists_ = (function () {
|
|
||||||
const rect = document.createElementNS(NS.SVG, 'rect');
|
|
||||||
const rxform = rect.transform.baseVal;
|
|
||||||
const t1 = svg.createSVGTransform();
|
|
||||||
rxform.appendItem(t1);
|
|
||||||
const r1 = rxform.getItem(0);
|
|
||||||
const 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
|
// Public API
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -184,17 +163,3 @@ export const supportsGoodTextCharPos = () => supportsGoodTextCharPos_;
|
|||||||
*/
|
*/
|
||||||
export const supportsNonScalingStroke = () => supportsNonScalingStroke_;
|
export const supportsNonScalingStroke = () => supportsNonScalingStroke_;
|
||||||
|
|
||||||
/**
|
|
||||||
* @function module:browser.supportsNativeTransformLists
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export const supportsNativeTransformLists = () => supportsNativeSVGTransformLists_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set `supportsNativeSVGTransformLists_` to `false` (for unit testing).
|
|
||||||
* @function module:browser.disableSupportsNativeTransformLists
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
export const disableSupportsNativeTransformLists = () => {
|
|
||||||
supportsNativeSVGTransformLists_ = false;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -224,14 +224,12 @@ export const convertAttrs = function (element) {
|
|||||||
const attrs = attrsToConvert[elName];
|
const attrs = attrsToConvert[elName];
|
||||||
if (!attrs) { return; }
|
if (!attrs) { return; }
|
||||||
|
|
||||||
const len = attrs.length;
|
attrs.forEach( (attr) => {
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
const attr = attrs[i];
|
|
||||||
const cur = element.getAttribute(attr);
|
const cur = element.getAttribute(attr);
|
||||||
if (cur && !isNaN(cur)) {
|
if (cur && !isNaN(cur)) {
|
||||||
element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
|
element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -136,11 +136,7 @@ export default {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Should only occur in FF which formats points attr as "n,n n,n", so just split
|
// Should only occur in FF which formats points attr as "n,n n,n", so just split
|
||||||
const ptArr = elem.getAttribute('points').split(' ');
|
const ptArr = elem.getAttribute('points').split(' ');
|
||||||
for (let i = 0; i < ptArr.length; i++) {
|
ptArr[pos] = x + ',' + y;
|
||||||
if (i === pos) {
|
|
||||||
ptArr[i] = x + ',' + y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elem.setAttribute('points', ptArr.join(' '));
|
elem.setAttribute('points', ptArr.join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +204,7 @@ export default {
|
|||||||
let addThis;
|
let addThis;
|
||||||
// Grab the ends
|
// Grab the ends
|
||||||
const parts = [];
|
const parts = [];
|
||||||
[ 'start', 'end' ].forEach(function (pos, i) {
|
[ 'start', 'end' ].forEach( (pos, i) => {
|
||||||
const key = 'c_' + pos;
|
const key = 'c_' + pos;
|
||||||
let part = dataStorage.get(ethis, key);
|
let part = dataStorage.get(ethis, key);
|
||||||
if (part === null || part === undefined) { // Does this ever return nullish values?
|
if (part === null || part === undefined) { // Does this ever return nullish values?
|
||||||
@@ -460,7 +456,7 @@ export default {
|
|||||||
if (elem && dataStorage.has(elem, 'c_start')) {
|
if (elem && dataStorage.has(elem, 'c_start')) {
|
||||||
// Remove the "translate" transform given to move
|
// Remove the "translate" transform given to move
|
||||||
svgCanvas.removeFromSelection([ elem ]);
|
svgCanvas.removeFromSelection([ elem ]);
|
||||||
svgCanvas.getTransformList(elem).clear();
|
elem.transform.baseVal.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (connections.length) {
|
if (connections.length) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default {
|
|||||||
$id("sidepanel_content").insertAdjacentHTML( 'beforeend', propsWindowHtml );
|
$id("sidepanel_content").insertAdjacentHTML( 'beforeend', propsWindowHtml );
|
||||||
|
|
||||||
// Define dynamic animation of the view box.
|
// Define dynamic animation of the view box.
|
||||||
const updateViewBox = function () {
|
const updateViewBox = () => {
|
||||||
const { workarea } = svgEditor;
|
const { workarea } = svgEditor;
|
||||||
const portHeight = parseFloat(getComputedStyle(workarea, null).height.replace("px", ""));
|
const portHeight = parseFloat(getComputedStyle(workarea, null).height.replace("px", ""));
|
||||||
const portWidth = parseFloat(getComputedStyle(workarea, null).width.replace("px", ""));
|
const portWidth = parseFloat(getComputedStyle(workarea, null).width.replace("px", ""));
|
||||||
|
|||||||
@@ -94,8 +94,6 @@ export default {
|
|||||||
|
|
||||||
canv.recalculateDimensions(curShape);
|
canv.recalculateDimensions(curShape);
|
||||||
|
|
||||||
canv.getTransformList(curShape);
|
|
||||||
|
|
||||||
lastBBox = curShape.getBBox();
|
lastBBox = curShape.getBBox();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -112,7 +110,7 @@ export default {
|
|||||||
const x = opts.mouse_x / zoom;
|
const x = opts.mouse_x / zoom;
|
||||||
const y = opts.mouse_y / zoom;
|
const y = opts.mouse_y / zoom;
|
||||||
|
|
||||||
const tlist = canv.getTransformList(curShape);
|
const tlist = curShape.transform.baseVal;
|
||||||
const box = curShape.getBBox();
|
const box = curShape.getBBox();
|
||||||
const left = box.x; const top = box.y;
|
const left = box.x; const top = box.y;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
transformPoint, transformListToTransform, matrixMultiply, transformBox
|
transformPoint, transformListToTransform, matrixMultiply, transformBox
|
||||||
} from './math.js';
|
} from './math.js';
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
|
|
||||||
// this is how we map paths to our preferred relative segment types
|
// this is how we map paths to our preferred relative segment types
|
||||||
const pathMap = [
|
const pathMap = [
|
||||||
@@ -51,11 +50,11 @@ export const init = function (editorContext) {
|
|||||||
* @type {module:path.EditorContext#remapElement}
|
* @type {module:path.EditorContext#remapElement}
|
||||||
*/
|
*/
|
||||||
export const remapElement = function (selected, changes, m) {
|
export const remapElement = function (selected, changes, m) {
|
||||||
const remap = function (x, y) { return transformPoint(x, y, m); };
|
const remap = (x, y) => transformPoint(x, y, m);
|
||||||
const scalew = function (w) { return m.a * w; };
|
const scalew = (w) => m.a * w;
|
||||||
const scaleh = function (h) { return m.d * h; };
|
const scaleh = (h) => m.d * h;
|
||||||
const doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg';
|
const doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg';
|
||||||
const finishUp = function () {
|
const finishUp = () => {
|
||||||
if (doSnapping) {
|
if (doSnapping) {
|
||||||
Object.entries(changes).forEach(([ o, value ]) => {
|
Object.entries(changes).forEach(([ o, value ]) => {
|
||||||
changes[o] = snapToGrid(value);
|
changes[o] = snapToGrid(value);
|
||||||
@@ -65,8 +64,7 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
};
|
};
|
||||||
const box = getBBox(selected);
|
const box = getBBox(selected);
|
||||||
|
|
||||||
for (let i = 0; i < 2; i++) {
|
[ 'fill', 'stroke' ].forEach( (type) => {
|
||||||
const type = i === 0 ? 'fill' : 'stroke';
|
|
||||||
const attrVal = selected.getAttribute(type);
|
const attrVal = selected.getAttribute(type);
|
||||||
if (attrVal && attrVal.startsWith('url(') && (m.a < 0 || m.d < 0)) {
|
if (attrVal && attrVal.startsWith('url(') && (m.a < 0 || m.d < 0)) {
|
||||||
const grad = getRefElem(attrVal);
|
const grad = getRefElem(attrVal);
|
||||||
@@ -90,7 +88,7 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
findDefs().append(newgrad);
|
findDefs().append(newgrad);
|
||||||
selected.setAttribute(type, 'url(#' + newgrad.id + ')');
|
selected.setAttribute(type, 'url(#' + newgrad.id + ')');
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
const elName = selected.tagName;
|
const elName = selected.tagName;
|
||||||
if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') {
|
if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') {
|
||||||
@@ -104,7 +102,7 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
changes.y = Number.parseFloat(changes.y) + tNew.f;
|
changes.y = Number.parseFloat(changes.y) + tNew.f;
|
||||||
} else {
|
} else {
|
||||||
// we just absorb all matrices into the element and don't do any remapping
|
// we just absorb all matrices into the element and don't do any remapping
|
||||||
const chlist = getTransformList(selected);
|
const chlist = selected.transform.baseVal;
|
||||||
const mt = editorContext_.getSVGRoot().createSVGTransform();
|
const mt = editorContext_.getSVGRoot().createSVGTransform();
|
||||||
mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));
|
mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));
|
||||||
chlist.clear();
|
chlist.clear();
|
||||||
@@ -121,7 +119,7 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
// Allow images to be inverted (give them matrix when flipped)
|
// Allow images to be inverted (give them matrix when flipped)
|
||||||
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
||||||
// Convert to matrix
|
// Convert to matrix
|
||||||
const chlist = getTransformList(selected);
|
const chlist = selected.transform.baseVal;
|
||||||
const mt = editorContext_.getSVGRoot().createSVGTransform();
|
const mt = editorContext_.getSVGRoot().createSVGTransform();
|
||||||
mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));
|
mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));
|
||||||
chlist.clear();
|
chlist.clear();
|
||||||
@@ -181,20 +179,17 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
break;
|
break;
|
||||||
} case 'polyline':
|
} case 'polyline':
|
||||||
case 'polygon': {
|
case 'polygon': {
|
||||||
const len = changes.points.length;
|
changes.points.forEach( (pt) => {
|
||||||
for (let i = 0; i < len; ++i) {
|
|
||||||
const pt = changes.points[i];
|
|
||||||
const { x, y } = remap(pt.x, pt.y);
|
const { x, y } = remap(pt.x, pt.y);
|
||||||
changes.points[i].x = x;
|
pt.x = x;
|
||||||
changes.points[i].y = y;
|
pt.y = y;
|
||||||
}
|
});
|
||||||
|
|
||||||
// const len = changes.points.length;
|
// const len = changes.points.length;
|
||||||
let pstr = '';
|
let pstr = '';
|
||||||
for (let i = 0; i < len; ++i) {
|
changes.points.forEach( (pt) => {
|
||||||
const pt = changes.points[i];
|
|
||||||
pstr += pt.x + ',' + pt.y + ' ';
|
pstr += pt.x + ',' + pt.y + ' ';
|
||||||
}
|
});
|
||||||
selected.setAttribute('points', pstr);
|
selected.setAttribute('points', pstr);
|
||||||
break;
|
break;
|
||||||
} case 'path': {
|
} case 'path': {
|
||||||
@@ -221,9 +216,12 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
|
|
||||||
len = changes.d.length;
|
len = changes.d.length;
|
||||||
const firstseg = changes.d[0];
|
const firstseg = changes.d[0];
|
||||||
const currentpt = remap(firstseg.x, firstseg.y);
|
let currentpt;
|
||||||
changes.d[0].x = currentpt.x;
|
if (len > 0) {
|
||||||
changes.d[0].y = currentpt.y;
|
currentpt = remap(firstseg.x, firstseg.y);
|
||||||
|
changes.d[0].x = currentpt.x;
|
||||||
|
changes.d[0].y = currentpt.y;
|
||||||
|
}
|
||||||
for (let i = 1; i < len; ++i) {
|
for (let i = 1; i < len; ++i) {
|
||||||
const seg = changes.d[i];
|
const seg = changes.d[i];
|
||||||
const { type } = seg;
|
const { type } = seg;
|
||||||
@@ -256,9 +254,7 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
} // for each segment
|
} // for each segment
|
||||||
|
|
||||||
let dstr = '';
|
let dstr = '';
|
||||||
len = changes.d.length;
|
changes.d.forEach( (seg) => {
|
||||||
for (let i = 0; i < len; ++i) {
|
|
||||||
const seg = changes.d[i];
|
|
||||||
const { type } = seg;
|
const { type } = seg;
|
||||||
dstr += pathMap[type];
|
dstr += pathMap[type];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -297,7 +293,7 @@ export const remapElement = function (selected, changes, m) {
|
|||||||
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
selected.setAttribute('d', dstr);
|
selected.setAttribute('d', dstr);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
transformPoint, hasMatrixTransform, getMatrix, snapToAngle
|
transformPoint, hasMatrixTransform, getMatrix, snapToAngle
|
||||||
} from './math.js';
|
} from './math.js';
|
||||||
import {
|
|
||||||
getTransformList
|
|
||||||
} from './svgtransformlist.js';
|
|
||||||
import { supportsNonScalingStroke } from '../common/browser.js';
|
import { supportsNonScalingStroke } from '../common/browser.js';
|
||||||
import * as draw from './draw.js';
|
import * as draw from './draw.js';
|
||||||
import * as pathModule from './path.js';
|
import * as pathModule from './path.js';
|
||||||
@@ -144,7 +141,7 @@ export const mouseMoveEvent = function (evt) {
|
|||||||
// update the dummy transform in our transform list
|
// update the dummy transform in our transform list
|
||||||
// to be a translate
|
// to be a translate
|
||||||
const xform = svgRoot.createSVGTransform();
|
const xform = svgRoot.createSVGTransform();
|
||||||
tlist = getTransformList(selected);
|
tlist = selected.transform?.baseVal;
|
||||||
// Note that if Webkit and there's no ID for this
|
// Note that if Webkit and there's no ID for this
|
||||||
// element, the dummy transform may have gotten lost.
|
// element, the dummy transform may have gotten lost.
|
||||||
// This results in unexpected behaviour
|
// This results in unexpected behaviour
|
||||||
@@ -209,7 +206,7 @@ export const mouseMoveEvent = function (evt) {
|
|||||||
// we track the resize bounding box and translate/scale the selected element
|
// we track the resize bounding box and translate/scale the selected element
|
||||||
// while the mouse is down, when mouse goes up, we use this to recalculate
|
// while the mouse is down, when mouse goes up, we use this to recalculate
|
||||||
// the shape's coordinates
|
// the shape's coordinates
|
||||||
tlist = getTransformList(selected);
|
tlist = selected.transform.baseVal;
|
||||||
const hasMatrix = hasMatrixTransform(tlist);
|
const hasMatrix = hasMatrixTransform(tlist);
|
||||||
box = hasMatrix ? eventContext_.getInitBbox() : utilsGetBBox(selected);
|
box = hasMatrix ? eventContext_.getInitBbox() : utilsGetBBox(selected);
|
||||||
let left = box.x;
|
let left = box.x;
|
||||||
@@ -1019,7 +1016,7 @@ export const mouseDownEvent = function (evt) {
|
|||||||
|
|
||||||
eventContext_.setStartTransform(mouseTarget.getAttribute('transform'));
|
eventContext_.setStartTransform(mouseTarget.getAttribute('transform'));
|
||||||
|
|
||||||
const tlist = getTransformList(mouseTarget);
|
const tlist = mouseTarget.transform.baseVal;
|
||||||
switch (eventContext_.getCurrentMode()) {
|
switch (eventContext_.getCurrentMode()) {
|
||||||
case 'select':
|
case 'select':
|
||||||
eventContext_.setStarted(true);
|
eventContext_.setStarted(true);
|
||||||
@@ -1046,7 +1043,7 @@ export const mouseDownEvent = function (evt) {
|
|||||||
// a transform to use for its translate
|
// a transform to use for its translate
|
||||||
for (const selectedElement of selectedElements()) {
|
for (const selectedElement of selectedElements()) {
|
||||||
if (isNullish(selectedElement)) { continue; }
|
if (isNullish(selectedElement)) { continue; }
|
||||||
const slist = getTransformList(selectedElement);
|
const slist = selectedElement.transform?.baseVal;
|
||||||
if (slist.numberOfItems) {
|
if (slist.numberOfItems) {
|
||||||
slist.insertItemBefore(svgRoot.createSVGTransform(), 0);
|
slist.insertItemBefore(svgRoot.createSVGTransform(), 0);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { getHref, setHref, getRotationAngle, isNullish } from './utilities.js';
|
import { getHref, setHref, getRotationAngle, isNullish } from './utilities.js';
|
||||||
import { removeElementFromListMap } from './svgtransformlist.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group: Undo/Redo history management.
|
* Group: Undo/Redo history management.
|
||||||
@@ -215,6 +214,7 @@ export class InsertElementCommand extends Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* History command for an element removed from the DOM.
|
* History command for an element removed from the DOM.
|
||||||
* @implements {module:history.HistoryCommand}
|
* @implements {module:history.HistoryCommand}
|
||||||
@@ -232,9 +232,6 @@ export class RemoveElementCommand extends Command {
|
|||||||
this.text = text || ('Delete ' + elem.tagName);
|
this.text = text || ('Delete ' + elem.tagName);
|
||||||
this.nextSibling = oldNextSibling;
|
this.nextSibling = oldNextSibling;
|
||||||
this.parent = oldParent;
|
this.parent = oldParent;
|
||||||
|
|
||||||
// special hack for webkit: remove this element's entry in the svgTransformLists map
|
|
||||||
removeElementFromListMap(elem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,7 +242,6 @@ export class RemoveElementCommand extends Command {
|
|||||||
*/
|
*/
|
||||||
apply (handler) {
|
apply (handler) {
|
||||||
super.apply(handler, () => {
|
super.apply(handler, () => {
|
||||||
removeElementFromListMap(this.elem);
|
|
||||||
this.parent = this.elem.parentNode;
|
this.parent = this.elem.parentNode;
|
||||||
this.elem.remove();
|
this.elem.remove();
|
||||||
});
|
});
|
||||||
@@ -259,7 +255,6 @@ export class RemoveElementCommand extends Command {
|
|||||||
*/
|
*/
|
||||||
unapply (handler) {
|
unapply (handler) {
|
||||||
super.unapply(handler, () => {
|
super.unapply(handler, () => {
|
||||||
removeElementFromListMap(this.elem);
|
|
||||||
if (isNullish(this.nextSibling) && window.console) {
|
if (isNullish(this.nextSibling) && window.console) {
|
||||||
console.error('Reference element was lost');
|
console.error('Reference element was lost');
|
||||||
}
|
}
|
||||||
@@ -385,8 +380,6 @@ export class ChangeElementCommand extends Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove transformlist to prevent confusion that causes bugs like 575.
|
|
||||||
removeElementFromListMap(this.elem);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { NS } from '../common/namespaces.js';
|
import { NS } from '../common/namespaces.js';
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const NEAR_ZERO = 1e-14;
|
const NEAR_ZERO = 1e-14;
|
||||||
@@ -178,7 +177,7 @@ export const transformListToTransform = function (tlist, min, max) {
|
|||||||
* @returns {SVGMatrix} The matrix object associated with the element's transformlist
|
* @returns {SVGMatrix} The matrix object associated with the element's transformlist
|
||||||
*/
|
*/
|
||||||
export const getMatrix = function (elem) {
|
export const getMatrix = function (elem) {
|
||||||
const tlist = getTransformList(elem);
|
const tlist = elem.transform.baseVal;
|
||||||
return transformListToTransform(tlist).matrix;
|
return transformListToTransform(tlist).matrix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
import { NS } from '../common/namespaces.js';
|
import { NS } from '../common/namespaces.js';
|
||||||
import { shortFloat } from '../common/units.js';
|
import { shortFloat } from '../common/units.js';
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
import { ChangeElementCommand, BatchCommand } from './history.js';
|
import { ChangeElementCommand, BatchCommand } from './history.js';
|
||||||
import {
|
import {
|
||||||
transformPoint, snapToAngle, rectsIntersect,
|
transformPoint, snapToAngle, rectsIntersect,
|
||||||
@@ -879,7 +878,7 @@ export const pathActionsMethod = (function () {
|
|||||||
*/
|
*/
|
||||||
resetOrientation (pth) {
|
resetOrientation (pth) {
|
||||||
if (isNullish(pth) || pth.nodeName !== 'path') { return false; }
|
if (isNullish(pth) || pth.nodeName !== 'path') { return false; }
|
||||||
const tlist = getTransformList(pth);
|
const tlist = pth.transform.baseVal;
|
||||||
const m = transformListToTransform(tlist).matrix;
|
const m = transformListToTransform(tlist).matrix;
|
||||||
tlist.clear();
|
tlist.clear();
|
||||||
pth.removeAttribute('transform');
|
pth.removeAttribute('transform');
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
* @copyright 2011 Alexis Deveria, 2011 Jeff Schiller
|
* @copyright 2011 Alexis Deveria, 2011 Jeff Schiller
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
import { shortFloat } from '../common/units.js';
|
import { shortFloat } from '../common/units.js';
|
||||||
import { transformPoint } from './math.js';
|
import { transformPoint } from './math.js';
|
||||||
import {
|
import {
|
||||||
@@ -526,7 +525,7 @@ export const recalcRotatedPath = function () {
|
|||||||
|
|
||||||
// now we must set the new transform to be rotated around the new center
|
// now we must set the new transform to be rotated around the new center
|
||||||
const Rnc = editorContext_.getSVGRoot().createSVGTransform();
|
const Rnc = editorContext_.getSVGRoot().createSVGTransform();
|
||||||
const tlist = getTransformList(currentPath);
|
const tlist = currentPath.transform.baseVal;
|
||||||
Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);
|
Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);
|
||||||
tlist.replaceItem(Rnc, 0);
|
tlist.replaceItem(Rnc, 0);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
import { NS } from '../common/namespaces.js';
|
import { NS } from '../common/namespaces.js';
|
||||||
import { convertToNum } from '../common/units.js';
|
import { convertToNum } from '../common/units.js';
|
||||||
import { isWebkit } from '../common/browser.js';
|
import { isWebkit } from '../common/browser.js';
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
import { getRotationAngle, getHref, getBBox, getRefElem, isNullish } from './utilities.js';
|
import { getRotationAngle, getHref, getBBox, getRefElem, isNullish } from './utilities.js';
|
||||||
import { BatchCommand, ChangeElementCommand } from './history.js';
|
import { BatchCommand, ChangeElementCommand } from './history.js';
|
||||||
import { remapElement } from './coords.js';
|
import { remapElement } from './coords.js';
|
||||||
@@ -57,7 +56,7 @@ export const init = function (editorContext) {
|
|||||||
*/
|
*/
|
||||||
export const updateClipPath = function (attr, tx, ty) {
|
export const updateClipPath = function (attr, tx, ty) {
|
||||||
const path = getRefElem(attr).firstChild;
|
const path = getRefElem(attr).firstChild;
|
||||||
const cpXform = getTransformList(path);
|
const cpXform = path.transform.baseVal;
|
||||||
const newxlate = context_.getSVGRoot().createSVGTransform();
|
const newxlate = context_.getSVGRoot().createSVGTransform();
|
||||||
newxlate.setTranslate(tx, ty);
|
newxlate.setTranslate(tx, ty);
|
||||||
|
|
||||||
@@ -74,17 +73,10 @@ export const updateClipPath = function (attr, tx, ty) {
|
|||||||
* @returns {Command} Undo command object with the resulting change
|
* @returns {Command} Undo command object with the resulting change
|
||||||
*/
|
*/
|
||||||
export const recalculateDimensions = function (selected) {
|
export const recalculateDimensions = function (selected) {
|
||||||
if (isNullish(selected)) { return null; }
|
if (!selected) return null;
|
||||||
|
|
||||||
// Firefox Issue - 1081
|
|
||||||
if (selected.nodeName === 'svg' && navigator.userAgent.includes('Firefox/20')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const svgroot = context_.getSVGRoot();
|
const svgroot = context_.getSVGRoot();
|
||||||
const dataStorage = context_.getDataStorage();
|
const dataStorage = context_.getDataStorage();
|
||||||
const tlist = getTransformList(selected);
|
const tlist = selected.transform?.baseVal;
|
||||||
|
|
||||||
// remove any unnecessary transforms
|
// remove any unnecessary transforms
|
||||||
if (tlist && tlist.numberOfItems > 0) {
|
if (tlist && tlist.numberOfItems > 0) {
|
||||||
let k = tlist.numberOfItems;
|
let k = tlist.numberOfItems;
|
||||||
@@ -307,7 +299,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
tx = 0;
|
tx = 0;
|
||||||
ty = 0;
|
ty = 0;
|
||||||
if (child.nodeType === 1) {
|
if (child.nodeType === 1) {
|
||||||
const childTlist = getTransformList(child);
|
const childTlist = child.transform.baseVal;
|
||||||
|
|
||||||
// some children might not have a transform (<metadata>, <defs>, etc)
|
// some children might not have a transform (<metadata>, <defs>, etc)
|
||||||
if (!childTlist) { continue; }
|
if (!childTlist) { continue; }
|
||||||
@@ -387,7 +379,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
// if (href == getHref(useElem)) {
|
// if (href == getHref(useElem)) {
|
||||||
// const usexlate = svgroot.createSVGTransform();
|
// const usexlate = svgroot.createSVGTransform();
|
||||||
// usexlate.setTranslate(-tx,-ty);
|
// usexlate.setTranslate(-tx,-ty);
|
||||||
// getTransformList(useElem).insertItemBefore(usexlate,0);
|
// useElem.transform.baseVal.insertItemBefore(usexlate,0);
|
||||||
// batchCmd.addSubCommand( recalculateDimensions(useElem) );
|
// batchCmd.addSubCommand( recalculateDimensions(useElem) );
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
@@ -441,7 +433,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
oldStartTransform = context_.getStartTransform();
|
oldStartTransform = context_.getStartTransform();
|
||||||
context_.setStartTransform(child.getAttribute('transform'));
|
context_.setStartTransform(child.getAttribute('transform'));
|
||||||
|
|
||||||
const childTlist = getTransformList(child);
|
const childTlist = child.transform?.baseVal;
|
||||||
// some children might not have a transform (<metadata>, <defs>, etc)
|
// some children might not have a transform (<metadata>, <defs>, etc)
|
||||||
if (childTlist) {
|
if (childTlist) {
|
||||||
const newxlate = svgroot.createSVGTransform();
|
const newxlate = svgroot.createSVGTransform();
|
||||||
@@ -463,7 +455,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
if (href === getHref(useElem)) {
|
if (href === getHref(useElem)) {
|
||||||
const usexlate = svgroot.createSVGTransform();
|
const usexlate = svgroot.createSVGTransform();
|
||||||
usexlate.setTranslate(-tx, -ty);
|
usexlate.setTranslate(-tx, -ty);
|
||||||
getTransformList(useElem).insertItemBefore(usexlate, 0);
|
useElem.transform.baseVal.insertItemBefore(usexlate, 0);
|
||||||
batchCmd.addSubCommand(recalculateDimensions(useElem));
|
batchCmd.addSubCommand(recalculateDimensions(useElem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -485,7 +477,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
if (child.nodeType === 1) {
|
if (child.nodeType === 1) {
|
||||||
oldStartTransform = context_.getStartTransform();
|
oldStartTransform = context_.getStartTransform();
|
||||||
context_.setStartTransform(child.getAttribute('transform'));
|
context_.setStartTransform(child.getAttribute('transform'));
|
||||||
const childTlist = getTransformList(child);
|
const childTlist = child.transform?.baseVal;
|
||||||
|
|
||||||
if (!childTlist) { continue; }
|
if (!childTlist) { continue; }
|
||||||
|
|
||||||
@@ -566,7 +558,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
if (child.nodeType === 1) {
|
if (child.nodeType === 1) {
|
||||||
oldStartTransform = context_.getStartTransform();
|
oldStartTransform = context_.getStartTransform();
|
||||||
context_.setStartTransform(child.getAttribute('transform'));
|
context_.setStartTransform(child.getAttribute('transform'));
|
||||||
const childTlist = getTransformList(child);
|
const childTlist = child.transform?.baseVal;
|
||||||
const newxlate = svgroot.createSVGTransform();
|
const newxlate = svgroot.createSVGTransform();
|
||||||
newxlate.setTranslate(tx, ty);
|
newxlate.setTranslate(tx, ty);
|
||||||
if (childTlist.numberOfItems) {
|
if (childTlist.numberOfItems) {
|
||||||
@@ -649,7 +641,7 @@ export const recalculateDimensions = function (selected) {
|
|||||||
if (attrVal === 'userSpaceOnUse') {
|
if (attrVal === 'userSpaceOnUse') {
|
||||||
// Update the userSpaceOnUse element
|
// Update the userSpaceOnUse element
|
||||||
m = transformListToTransform(tlist).matrix;
|
m = transformListToTransform(tlist).matrix;
|
||||||
const gtlist = getTransformList(paint);
|
const gtlist = paint.transform.baseVal;
|
||||||
const gmatrix = transformListToTransform(gtlist).matrix;
|
const gmatrix = transformListToTransform(gtlist).matrix;
|
||||||
m = matrixMultiply(m, gmatrix);
|
m = matrixMultiply(m, gmatrix);
|
||||||
const mStr = 'matrix(' + [ m.a, m.b, m.c, m.d, m.e, m.f ].join(',') + ')';
|
const mStr = 'matrix(' + [ m.a, m.b, m.c, m.d, m.e, m.f ].join(',') + ')';
|
||||||
|
|||||||
@@ -19,54 +19,55 @@ const REVERSE_NS = getReverseNS();
|
|||||||
* @type {PlainObject}
|
* @type {PlainObject}
|
||||||
*/
|
*/
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
|
const svgGenericWhiteList = [ 'class', 'id', 'display', 'transform' ];
|
||||||
const svgWhiteList_ = {
|
const svgWhiteList_ = {
|
||||||
// SVG Elements
|
// SVG Elements
|
||||||
a: [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title' ],
|
a: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'xlink:href', 'xlink:title' ],
|
||||||
circle: [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
circle: [ 'clip-path', 'clip-rule', 'cx', 'cy', 'enable-background', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage' ],
|
||||||
clipPath: [ 'class', 'clipPathUnits', 'id' ],
|
clipPath: [ 'clipPathUnits', 'id' ],
|
||||||
defs: [ 'id' ],
|
defs: [],
|
||||||
style: [ 'id', 'type' ],
|
style: [ 'type' ],
|
||||||
desc: [],
|
desc: [],
|
||||||
ellipse: [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
ellipse: [ 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage' ],
|
||||||
feBlend: [ 'in', 'in2' ],
|
feBlend: [ 'in', 'in2' ],
|
||||||
feColorMatrix: [ 'in', 'type', 'value', 'result', 'values', 'id' ],
|
feColorMatrix: [ 'in', 'type', 'value', 'result', 'values' ],
|
||||||
feComposite: [ 'in', 'id', 'operator', 'result', 'in2' ],
|
feComposite: [ 'in', 'operator', 'result', 'in2' ],
|
||||||
feFlood: [ 'flood-color', 'in', 'id', 'result', 'flood-opacity' ],
|
feFlood: [ 'flood-color', 'in', 'result', 'flood-opacity' ],
|
||||||
feGaussianBlur: [ 'class', 'color-interpolation-filters', 'id', 'in', 'requiredFeatures', 'stdDeviation', 'result' ],
|
feGaussianBlur: [ 'color-interpolation-filters', 'in', 'requiredFeatures', 'stdDeviation', 'result' ],
|
||||||
feMerge: [],
|
feMerge: [],
|
||||||
feMergeNode: [ 'in' ],
|
feMergeNode: [ 'in' ],
|
||||||
feMorphology: [ 'class', 'in', 'operator', 'radius' ],
|
feMorphology: [ 'in', 'operator', 'radius' ],
|
||||||
feOffset: [ 'dx', 'id', 'in', 'dy', 'result' ],
|
feOffset: [ 'dx', 'in', 'dy', 'result' ],
|
||||||
filter: [ 'class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'style', 'width', 'x', 'xlink:href', 'y' ],
|
filter: [ 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'primitiveUnits', 'requiredFeatures', 'style', 'width', 'x', 'xlink:href', 'y' ],
|
||||||
foreignObject: [ 'class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y' ],
|
foreignObject: [ 'font-size', 'height', 'opacity', 'requiredFeatures', 'style', 'width', 'x', 'y' ],
|
||||||
g: [ 'class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor' ],
|
g: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor' ],
|
||||||
image: [ 'class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y' ],
|
image: [ 'clip-path', 'clip-rule', 'filter', 'height', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'width', 'x', 'xlink:href', 'xlink:title', 'y' ],
|
||||||
line: [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2' ],
|
line: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'x1', 'x2', 'y1', 'y2' ],
|
||||||
linearGradient: [ 'class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2' ],
|
linearGradient: [ 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2' ],
|
||||||
marker: [ 'id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox' ],
|
marker: [ 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox' ],
|
||||||
mask: [ 'class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y' ],
|
mask: [ 'height', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y' ],
|
||||||
metadata: [ 'class', 'id' ],
|
metadata: [ 'id' ],
|
||||||
path: [ 'class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
path: [ 'clip-path', 'clip-rule', 'd', 'enable-background', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage' ],
|
||||||
pattern: [ 'class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y' ],
|
pattern: [ 'height', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y' ],
|
||||||
polygon: [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'sides', 'shape', 'edge', 'point', 'starRadiusMultiplier', 'r', 'radialshift' ],
|
polygon: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'sides', 'shape', 'edge', 'point', 'starRadiusMultiplier', 'r', 'radialshift' ],
|
||||||
polyline: [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'se:connector' ],
|
polyline: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'se:connector' ],
|
||||||
radialGradient: [ 'class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href' ],
|
radialGradient: [ 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href' ],
|
||||||
rect: [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y' ],
|
rect: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'width', 'x', 'y' ],
|
||||||
stop: [ 'class', 'id', 'offset', 'requiredFeatures', 'stop-opacity', 'style', 'systemLanguage', 'stop-color', 'gradientUnits', 'gradientTransform' ],
|
stop: [ 'offset', 'requiredFeatures', 'stop-opacity', 'style', 'systemLanguage', 'stop-color', 'gradientUnits', 'gradientTransform' ],
|
||||||
svg: [ 'class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'version', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'xmlns:oi', 'oi:animations', 'y', 'stroke-linejoin', 'fill-rule', 'aria-label', 'stroke-width', 'fill-rule' ],
|
svg: [ 'clip-path', 'clip-rule', 'enable-background', 'filter', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'version', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'xmlns:oi', 'oi:animations', 'y', 'stroke-linejoin', 'fill-rule', 'aria-label', 'stroke-width', 'fill-rule', 'xml:space' ],
|
||||||
switch: [ 'class', 'id', 'requiredFeatures', 'systemLanguage' ],
|
switch: [ 'requiredFeatures', 'systemLanguage' ],
|
||||||
symbol: [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'overflow', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox', 'width', 'height' ],
|
symbol: [ 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'opacity', 'overflow', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'viewBox', 'width', 'height' ],
|
||||||
text: [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y' ],
|
text: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'x', 'xml:space', 'y' ],
|
||||||
textPath: [ 'class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href' ],
|
textPath: [ 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'xlink:href' ],
|
||||||
title: [],
|
title: [],
|
||||||
tspan: [ 'class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y' ],
|
tspan: [ 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'x', 'xml:space', 'y' ],
|
||||||
use: [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y' ],
|
use: [ 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'width', 'x', 'xlink:href', 'y', 'overflow' ],
|
||||||
|
|
||||||
// MathML Elements
|
// MathML Elements
|
||||||
annotation: [ 'encoding' ],
|
annotation: [ 'encoding' ],
|
||||||
'annotation-xml': [ 'encoding' ],
|
'annotation-xml': [ 'encoding' ],
|
||||||
maction: [ 'actiontype', 'other', 'selection' ],
|
maction: [ 'actiontype', 'other', 'selection' ],
|
||||||
math: [ 'class', 'id', 'display', 'xmlns' ],
|
math: [ 'xmlns' ],
|
||||||
menclose: [ 'notation' ],
|
menclose: [ 'notation' ],
|
||||||
merror: [],
|
merror: [],
|
||||||
mfrac: [ 'linethickness' ],
|
mfrac: [ 'linethickness' ],
|
||||||
@@ -96,10 +97,11 @@ const svgWhiteList_ = {
|
|||||||
semantics: []
|
semantics: []
|
||||||
};
|
};
|
||||||
/* eslint-enable max-len */
|
/* eslint-enable max-len */
|
||||||
|
// add generic attributes to all elements of the whitelist
|
||||||
|
Object.keys(svgWhiteList_).forEach((element) => svgWhiteList_[element] = [ ...svgWhiteList_[element], ...svgGenericWhiteList ]);
|
||||||
// Produce a Namespace-aware version of svgWhitelist
|
// Produce a Namespace-aware version of svgWhitelist
|
||||||
const svgWhiteListNS_ = {};
|
const svgWhiteListNS_ = {};
|
||||||
Object.entries(svgWhiteList_).forEach(function ([ elt, atts ]) {
|
Object.entries(svgWhiteList_).forEach(([ elt, atts ]) => {
|
||||||
const attNS = {};
|
const attNS = {};
|
||||||
Object.entries(atts).forEach(function ([ _i, att ]) {
|
Object.entries(atts).forEach(function ([ _i, att ]) {
|
||||||
if (att.includes(':')) {
|
if (att.includes(':')) {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import { isTouch, isWebkit } from '../common/browser.js'; // , isOpera
|
import { isTouch, isWebkit } from '../common/browser.js'; // , isOpera
|
||||||
import { getRotationAngle, getBBox, getStrokedBBox, isNullish } from './utilities.js';
|
import { getRotationAngle, getBBox, getStrokedBBox, isNullish } from './utilities.js';
|
||||||
import { transformListToTransform, transformBox, transformPoint } from './math.js';
|
import { transformListToTransform, transformBox, transformPoint } from './math.js';
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
|
|
||||||
let svgFactory_;
|
let svgFactory_;
|
||||||
let config_;
|
let config_;
|
||||||
@@ -124,7 +123,7 @@ export class Selector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loop and transform our bounding box until we reach our first rotation
|
// loop and transform our bounding box until we reach our first rotation
|
||||||
const tlist = getTransformList(selected);
|
const tlist = selected.transform.baseVal;
|
||||||
const m = transformListToTransform(tlist).matrix;
|
const m = transformListToTransform(tlist).matrix;
|
||||||
|
|
||||||
// This should probably be handled somewhere else, but for now
|
// This should probably be handled somewhere else, but for now
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
transformPoint, matrixMultiply, transformListToTransform
|
transformPoint, matrixMultiply, transformListToTransform
|
||||||
} from './math.js';
|
} from './math.js';
|
||||||
import {
|
|
||||||
getTransformList
|
|
||||||
} from './svgtransformlist.js';
|
|
||||||
import {
|
import {
|
||||||
recalculateDimensions
|
recalculateDimensions
|
||||||
} from './recalculate.js';
|
} from './recalculate.js';
|
||||||
@@ -171,7 +168,7 @@ export const moveSelectedElements = function (dx, dy, undoable = true) {
|
|||||||
const selected = selectedElements[i];
|
const selected = selectedElements[i];
|
||||||
if (!isNullish(selected)) {
|
if (!isNullish(selected)) {
|
||||||
const xform = elementContext_.getSVGRoot().createSVGTransform();
|
const xform = elementContext_.getSVGRoot().createSVGTransform();
|
||||||
const tlist = getTransformList(selected);
|
const tlist = selected.transform?.baseVal;
|
||||||
|
|
||||||
// dx and dy could be arrays
|
// dx and dy could be arrays
|
||||||
if (Array.isArray(dx)) {
|
if (Array.isArray(dx)) {
|
||||||
@@ -503,7 +500,7 @@ export const pushGroupProperty = function (g, undoable) {
|
|||||||
const len = children.length;
|
const len = children.length;
|
||||||
const xform = g.getAttribute('transform');
|
const xform = g.getAttribute('transform');
|
||||||
|
|
||||||
const glist = getTransformList(g);
|
const glist = g.transform.baseVal;
|
||||||
const m = transformListToTransform(glist).matrix;
|
const m = transformListToTransform(glist).matrix;
|
||||||
|
|
||||||
const batchCmd = new BatchCommand('Push group properties');
|
const batchCmd = new BatchCommand('Push group properties');
|
||||||
@@ -576,7 +573,7 @@ export const pushGroupProperty = function (g, undoable) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let chtlist = getTransformList(elem);
|
let chtlist = elem.transform?.baseVal;
|
||||||
|
|
||||||
// Don't process gradient transforms
|
// Don't process gradient transforms
|
||||||
if (elem.tagName.includes('Gradient')) { chtlist = null; }
|
if (elem.tagName.includes('Gradient')) { chtlist = null; }
|
||||||
@@ -717,7 +714,7 @@ export const convertToGroup = function (elem) {
|
|||||||
}
|
}
|
||||||
dataStorage.remove(elem, 'gsvg');
|
dataStorage.remove(elem, 'gsvg');
|
||||||
|
|
||||||
const tlist = getTransformList(elem);
|
const tlist = elem.transform.baseVal;
|
||||||
const xform = elementContext_.getSVGRoot().createSVGTransform();
|
const xform = elementContext_.getSVGRoot().createSVGTransform();
|
||||||
xform.setTranslate(pt.x, pt.y);
|
xform.setTranslate(pt.x, pt.y);
|
||||||
tlist.appendItem(xform);
|
tlist.appendItem(xform);
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ import {
|
|||||||
isNullish, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible
|
isNullish, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible
|
||||||
} from './utilities.js';
|
} from './utilities.js';
|
||||||
import { transformPoint, transformListToTransform, rectsIntersect } from './math.js';
|
import { transformPoint, transformListToTransform, rectsIntersect } from './math.js';
|
||||||
import {
|
|
||||||
getTransformList
|
|
||||||
} from './svgtransformlist.js';
|
|
||||||
import * as hstry from './history.js';
|
import * as hstry from './history.js';
|
||||||
import { getClosest } from '../editor/components/jgraduate/Util.js';
|
import { getClosest } from '../editor/components/jgraduate/Util.js';
|
||||||
|
|
||||||
@@ -164,7 +161,7 @@ export const getMouseTargetMethod = function (evt) {
|
|||||||
return svgCanvas.selectorManager.selectorParentGroup;
|
return svgCanvas.selectorManager.selectorParentGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!mouseTarget.parentNode?.isSameNode(selectionContext_.getCurrentGroup() || currentLayer)) {
|
while (!mouseTarget?.parentNode?.isSameNode(selectionContext_.getCurrentGroup() || currentLayer)) {
|
||||||
mouseTarget = mouseTarget.parentNode;
|
mouseTarget = mouseTarget.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +350,7 @@ export const setRotationAngle = function (val, preventUndo) {
|
|||||||
const oldTransform = elem.getAttribute('transform');
|
const oldTransform = elem.getAttribute('transform');
|
||||||
const bbox = utilsGetBBox(elem);
|
const bbox = utilsGetBBox(elem);
|
||||||
const cx = bbox.x + bbox.width / 2; const cy = bbox.y + bbox.height / 2;
|
const cx = bbox.x + bbox.width / 2; const cy = bbox.y + bbox.height / 2;
|
||||||
const tlist = getTransformList(elem);
|
const tlist = elem.transform.baseVal;
|
||||||
|
|
||||||
// only remove the real rotational transform if present (i.e. at index=0)
|
// only remove the real rotational transform if present (i.e. at index=0)
|
||||||
if (tlist.numberOfItems > 0) {
|
if (tlist.numberOfItems > 0) {
|
||||||
@@ -411,7 +408,6 @@ export const recalculateAllSelectedDimensions = function () {
|
|||||||
let i = selectedElements().length;
|
let i = selectedElements().length;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
const elem = selectedElements()[i];
|
const elem = selectedElements()[i];
|
||||||
// if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; }
|
|
||||||
const cmd = svgCanvas.recalculateDimensions(elem);
|
const cmd = svgCanvas.recalculateDimensions(elem);
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
batchCmd.addSubCommand(cmd);
|
batchCmd.addSubCommand(cmd);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
transformPoint, transformListToTransform
|
transformPoint, transformListToTransform
|
||||||
} from './math.js';
|
} from './math.js';
|
||||||
import { resetListMap } from './svgtransformlist.js';
|
|
||||||
import {
|
import {
|
||||||
convertUnit, shortFloat, convertToNum
|
convertUnit, shortFloat, convertToNum
|
||||||
} from '../common/units.js';
|
} from '../common/units.js';
|
||||||
@@ -491,8 +490,6 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||||||
// reset zoom
|
// reset zoom
|
||||||
svgContext_.setCurrentZoom(1);
|
svgContext_.setCurrentZoom(1);
|
||||||
|
|
||||||
// reset transform lists
|
|
||||||
resetListMap();
|
|
||||||
svgCanvas.clearSelection();
|
svgCanvas.clearSelection();
|
||||||
pathModule.clearData();
|
pathModule.clearData();
|
||||||
svgContext_.getSVGRoot().append(svgCanvas.selectorManager.selectorParentGroup);
|
svgContext_.getSVGRoot().append(svgCanvas.selectorManager.selectorParentGroup);
|
||||||
|
|||||||
@@ -87,9 +87,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
isChrome, isWebkit
|
isChrome, isWebkit
|
||||||
} from '../common/browser.js'; // , supportsEditableText
|
} from '../common/browser.js'; // , supportsEditableText
|
||||||
import {
|
|
||||||
getTransformList, SVGTransformList as SVGEditTransformList
|
|
||||||
} from './svgtransformlist.js';
|
|
||||||
import {
|
import {
|
||||||
remapElement,
|
remapElement,
|
||||||
init as coordsInit
|
init as coordsInit
|
||||||
@@ -151,7 +148,6 @@ if (window.opera) {
|
|||||||
* @borrows module:utilities.getRefElem as #getRefElem
|
* @borrows module:utilities.getRefElem as #getRefElem
|
||||||
* @borrows module:utilities.assignAttributes as #assignAttributes
|
* @borrows module:utilities.assignAttributes as #assignAttributes
|
||||||
*
|
*
|
||||||
* @borrows module:SVGTransformList.getTransformList as #getTransformList
|
|
||||||
* @borrows module:math.matrixMultiply as #matrixMultiply
|
* @borrows module:math.matrixMultiply as #matrixMultiply
|
||||||
* @borrows module:math.hasMatrixTransform as #hasMatrixTransform
|
* @borrows module:math.hasMatrixTransform as #hasMatrixTransform
|
||||||
* @borrows module:math.transformListToTransform as #transformListToTransform
|
* @borrows module:math.transformListToTransform as #transformListToTransform
|
||||||
@@ -372,7 +368,6 @@ class SvgCanvas {
|
|||||||
*/
|
*/
|
||||||
const addSVGElementFromJson = this.addSVGElementFromJson = addSVGElementsFromJson;
|
const addSVGElementFromJson = this.addSVGElementFromJson = addSVGElementsFromJson;
|
||||||
|
|
||||||
canvas.getTransformList = getTransformList;
|
|
||||||
canvas.matrixMultiply = matrixMultiply;
|
canvas.matrixMultiply = matrixMultiply;
|
||||||
canvas.hasMatrixTransform = hasMatrixTransform;
|
canvas.hasMatrixTransform = hasMatrixTransform;
|
||||||
canvas.transformListToTransform = transformListToTransform;
|
canvas.transformListToTransform = transformListToTransform;
|
||||||
@@ -2756,7 +2751,6 @@ class SvgCanvas {
|
|||||||
NS,
|
NS,
|
||||||
preventClickDefault,
|
preventClickDefault,
|
||||||
RemoveElementCommand,
|
RemoveElementCommand,
|
||||||
SVGEditTransformList,
|
|
||||||
text2xml,
|
text2xml,
|
||||||
transformBox,
|
transformBox,
|
||||||
transformPoint,
|
transformPoint,
|
||||||
|
|||||||
@@ -1,393 +0,0 @@
|
|||||||
/**
|
|
||||||
* Partial polyfill of `SVGTransformList`
|
|
||||||
* @module SVGTransformList
|
|
||||||
*
|
|
||||||
* @license MIT
|
|
||||||
*
|
|
||||||
* @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { NS } from '../common/namespaces.js';
|
|
||||||
import { supportsNativeTransformLists } from '../common/browser.js';
|
|
||||||
|
|
||||||
const svgroot = document.createElementNS(NS.SVG, 'svg');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to convert `SVGTransform` to a string.
|
|
||||||
* @param {SVGTransform} xform
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function transformToString (xform) {
|
|
||||||
const m = xform.matrix;
|
|
||||||
let 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
|
|
||||||
text = (m.a === m.d) ? `scale(${m.a})` : `scale(${m.a},${m.d})`;
|
|
||||||
break;
|
|
||||||
case 4: { // ROTATE
|
|
||||||
let cx = 0;
|
|
||||||
let cy = 0;
|
|
||||||
// this prevents divide by zero
|
|
||||||
if (xform.angle !== 0) {
|
|
||||||
const 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.
|
|
||||||
*/
|
|
||||||
let 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}
|
|
||||||
*/
|
|
||||||
export class SVGTransformList {
|
|
||||||
/**
|
|
||||||
* @param {Element} elem
|
|
||||||
* @returns {SVGTransformList}
|
|
||||||
*/
|
|
||||||
constructor (elem) {
|
|
||||||
this._elem = elem || null;
|
|
||||||
this._xforms = [];
|
|
||||||
// TODO: how do we capture the undo-ability in the changed transform list?
|
|
||||||
this._update = function () {
|
|
||||||
let tstr = '';
|
|
||||||
// /* const concatMatrix = */ svgroot.createSVGMatrix();
|
|
||||||
for (let i = 0; i < this.numberOfItems; ++i) {
|
|
||||||
const xform = this._list.getItem(i);
|
|
||||||
tstr += transformToString(xform) + ' ';
|
|
||||||
}
|
|
||||||
this._elem.setAttribute('transform', tstr);
|
|
||||||
};
|
|
||||||
this._list = this;
|
|
||||||
this._init = function () {
|
|
||||||
// Transform attribute parser
|
|
||||||
let str = this._elem.getAttribute('transform');
|
|
||||||
if (!str) { return; }
|
|
||||||
|
|
||||||
// TODO: Add skew support in future
|
|
||||||
const re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
|
|
||||||
// const re = /\s*(?<xform>(?:scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
|
|
||||||
let m = true;
|
|
||||||
while (m) {
|
|
||||||
m = str.match(re);
|
|
||||||
str = str.replace(re, '');
|
|
||||||
if (m && m[1]) {
|
|
||||||
const x = m[1];
|
|
||||||
const bits = x.split(/\s*\(/);
|
|
||||||
const name = bits[0];
|
|
||||||
const valBits = bits[1].match(/\s*(.*?)\s*\)/);
|
|
||||||
valBits[1] = valBits[1].replace(/(\d)-/g, '$1 -');
|
|
||||||
const valArr = valBits[1].split(/[, ]+/);
|
|
||||||
const letters = 'abcdef'.split('');
|
|
||||||
/*
|
|
||||||
if (m && m.groups.xform) {
|
|
||||||
const x = m.groups.xform;
|
|
||||||
const [name, bits] = x.split(/\s*\(/);
|
|
||||||
const valBits = bits.match(/\s*(?<nonWhitespace>.*?)\s*\)/);
|
|
||||||
valBits.groups.nonWhitespace = valBits.groups.nonWhitespace.replace(
|
|
||||||
/(?<digit>\d)-/g, '$<digit> -'
|
|
||||||
);
|
|
||||||
const valArr = valBits.groups.nonWhitespace.split(/[, ]+/);
|
|
||||||
const letters = [...'abcdef'];
|
|
||||||
*/
|
|
||||||
const mtx = svgroot.createSVGMatrix();
|
|
||||||
Object.values(valArr).forEach(function (item, i) {
|
|
||||||
valArr[i] = Number.parseFloat(item);
|
|
||||||
if (name === 'matrix') {
|
|
||||||
mtx[letters[i]] = valArr[i];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const xform = svgroot.createSVGTransform();
|
|
||||||
const fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
|
|
||||||
const 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](...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((tl) => {
|
|
||||||
for (let 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}
|
|
||||||
*/
|
|
||||||
clear () {
|
|
||||||
this.numberOfItems = 0;
|
|
||||||
this._xforms = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {SVGTransform} newItem
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
initialize (newItem) {
|
|
||||||
this.numberOfItems = 1;
|
|
||||||
this._removeFromOtherLists(newItem);
|
|
||||||
this._xforms = [ newItem ];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Integer} index unsigned long
|
|
||||||
* @throws {Error}
|
|
||||||
* @returns {SVGTransform}
|
|
||||||
*/
|
|
||||||
getItem (index) {
|
|
||||||
if (index < this.numberOfItems && index >= 0) {
|
|
||||||
return this._xforms[index];
|
|
||||||
}
|
|
||||||
const err = new Error('DOMException with code=INDEX_SIZE_ERR');
|
|
||||||
err.code = 1;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {SVGTransform} newItem
|
|
||||||
* @param {Integer} index unsigned long
|
|
||||||
* @returns {SVGTransform}
|
|
||||||
*/
|
|
||||||
insertItemBefore (newItem, index) {
|
|
||||||
let retValue = null;
|
|
||||||
if (index >= 0) {
|
|
||||||
if (index < this.numberOfItems) {
|
|
||||||
this._removeFromOtherLists(newItem);
|
|
||||||
const newxforms = new Array(this.numberOfItems + 1);
|
|
||||||
// TODO: use array copying and slicing
|
|
||||||
let i;
|
|
||||||
for (i = 0; i < index; ++i) {
|
|
||||||
newxforms[i] = this._xforms[i];
|
|
||||||
}
|
|
||||||
newxforms[i] = newItem;
|
|
||||||
for (let 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}
|
|
||||||
*/
|
|
||||||
replaceItem (newItem, index) {
|
|
||||||
let 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}
|
|
||||||
*/
|
|
||||||
removeItem (index) {
|
|
||||||
if (index < this.numberOfItems && index >= 0) {
|
|
||||||
const retValue = this._xforms[index];
|
|
||||||
const newxforms = new Array(this.numberOfItems - 1);
|
|
||||||
let i;
|
|
||||||
for (i = 0; i < index; ++i) {
|
|
||||||
newxforms[i] = this._xforms[i];
|
|
||||||
}
|
|
||||||
for (let j = i; j < this.numberOfItems - 1; ++j, ++i) {
|
|
||||||
newxforms[j] = this._xforms[i + 1];
|
|
||||||
}
|
|
||||||
this.numberOfItems--;
|
|
||||||
this._xforms = newxforms;
|
|
||||||
this._list._update();
|
|
||||||
return retValue;
|
|
||||||
}
|
|
||||||
const err = new Error('DOMException with code=INDEX_SIZE_ERR');
|
|
||||||
err.code = 1;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {SVGTransform} newItem
|
|
||||||
* @returns {SVGTransform}
|
|
||||||
*/
|
|
||||||
appendItem (newItem) {
|
|
||||||
this._removeFromOtherLists(newItem);
|
|
||||||
this._xforms.push(newItem);
|
|
||||||
this.numberOfItems++;
|
|
||||||
this._list._update();
|
|
||||||
return newItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function module:SVGTransformList.resetListMap
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
export const resetListMap = function () {
|
|
||||||
listMap_ = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes transforms of the given element from the map.
|
|
||||||
* @function module:SVGTransformList.removeElementFromListMap
|
|
||||||
* @param {Element} elem - a DOM Element
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
export let removeElementFromListMap = function (elem) {
|
|
||||||
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}
|
|
||||||
*/
|
|
||||||
export const getTransformList = function (elem) {
|
|
||||||
if (!supportsNativeTransformLists()) {
|
|
||||||
const id = elem.id || 'temp';
|
|
||||||
let 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @callback module:SVGTransformList.removeElementFromListMap
|
|
||||||
* @param {Element} elem
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Replace `removeElementFromListMap` for unit-testing.
|
|
||||||
* @function module:SVGTransformList.changeRemoveElementFromListMap
|
|
||||||
* @param {module:SVGTransformList.removeElementFromListMap} cb Passed a single argument `elem`
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const changeRemoveElementFromListMap = function (cb) {
|
|
||||||
removeElementFromListMap = cb;
|
|
||||||
};
|
|
||||||
@@ -15,9 +15,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
transformPoint, transformListToTransform
|
transformPoint, transformListToTransform
|
||||||
} from './math.js';
|
} from './math.js';
|
||||||
import {
|
|
||||||
getTransformList
|
|
||||||
} from './svgtransformlist.js';
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
UndoManager, HistoryEventTypes
|
UndoManager, HistoryEventTypes
|
||||||
@@ -84,20 +81,6 @@ export const getUndoManager = function () {
|
|||||||
if (values.stdDeviation) {
|
if (values.stdDeviation) {
|
||||||
undoContext_.getCanvas().setBlurOffsets(cmd.elem.parentNode, values.stdDeviation);
|
undoContext_.getCanvas().setBlurOffsets(cmd.elem.parentNode, values.stdDeviation);
|
||||||
}
|
}
|
||||||
// This is resolved in later versions of webkit, perhaps we should
|
|
||||||
// have a featured detection for correct 'use' behavior?
|
|
||||||
// ——————————
|
|
||||||
// Remove & Re-add hack for Webkit (issue 775)
|
|
||||||
// if (cmd.elem.tagName === 'use' && isWebkit()) {
|
|
||||||
// const {elem} = cmd;
|
|
||||||
// if (!elem.getAttribute('x') && !elem.getAttribute('y')) {
|
|
||||||
// const parent = elem.parentNode;
|
|
||||||
// const sib = elem.nextSibling;
|
|
||||||
// elem.remove();
|
|
||||||
// parent.insertBefore(elem, sib);
|
|
||||||
// // Ok to replace above with this? `sib.before(elem);`
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (cmd.elem.tagName === 'text'){
|
if (cmd.elem.tagName === 'text'){
|
||||||
const [ dx, dy ] = [ cmd.newValues.x - cmd.oldValues.x,
|
const [ dx, dy ] = [ cmd.newValues.x - cmd.oldValues.x,
|
||||||
cmd.newValues.y - cmd.oldValues.y ];
|
cmd.newValues.y - cmd.oldValues.y ];
|
||||||
@@ -251,7 +234,7 @@ export const changeSelectedAttributeNoUndoMethod = function (attr, newValue, ele
|
|||||||
// we need to update the rotational transform attribute
|
// we need to update the rotational transform attribute
|
||||||
const angle = getRotationAngle(elem);
|
const angle = getRotationAngle(elem);
|
||||||
if (angle !== 0 && attr !== 'transform') {
|
if (angle !== 0 && attr !== 'transform') {
|
||||||
const tlist = getTransformList(elem);
|
const tlist = elem.transform?.baseVal;
|
||||||
let n = tlist.numberOfItems;
|
let n = tlist.numberOfItems;
|
||||||
while (n--) {
|
while (n--) {
|
||||||
const xform = tlist.getItem(n);
|
const xform = tlist.getItem(n);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { NS } from '../common/namespaces.js';
|
import { NS } from '../common/namespaces.js';
|
||||||
import { getTransformList } from './svgtransformlist.js';
|
|
||||||
import { setUnitAttr, getTypeMap } from '../common/units.js';
|
import { setUnitAttr, getTypeMap } from '../common/units.js';
|
||||||
import {
|
import {
|
||||||
hasMatrixTransform, transformListToTransform, transformBox
|
hasMatrixTransform, transformListToTransform, transformBox
|
||||||
@@ -122,20 +121,6 @@ export const toXml = function (str) {
|
|||||||
.replace(/'/g, '''); // Note: `'` is XML only
|
.replace(/'/g, '''); // Note: `'` is XML only
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts XML entities in a string to single characters.
|
|
||||||
* @function module:utilities.fromXml
|
|
||||||
* @example `&` becomes `&`
|
|
||||||
* @param {string} str - The string to be converted
|
|
||||||
* @returns {string} The converted string
|
|
||||||
*/
|
|
||||||
export function fromXml(str) {
|
|
||||||
const p = document.createElement('p');
|
|
||||||
// eslint-disable-next-line no-unsanitized/property
|
|
||||||
p.innerHTML = str;
|
|
||||||
return p.textContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This code was written by Tyler Akins and has been placed in the
|
// This code was written by Tyler Akins and has been placed in the
|
||||||
// public domain. It would be nice if you left this header intact.
|
// public domain. It would be nice if you left this header intact.
|
||||||
// Base64 code from Tyler Akins -- http://rumkin.com
|
// Base64 code from Tyler Akins -- http://rumkin.com
|
||||||
@@ -921,7 +906,7 @@ export const convertToPath = function (
|
|||||||
|
|
||||||
// Reorient if it has a matrix
|
// Reorient if it has a matrix
|
||||||
if (eltrans) {
|
if (eltrans) {
|
||||||
const tlist = getTransformList(path);
|
const tlist = path.transform.baseVal;
|
||||||
if (hasMatrixTransform(tlist)) {
|
if (hasMatrixTransform(tlist)) {
|
||||||
pathActions.resetOrientation(path);
|
pathActions.resetOrientation(path);
|
||||||
}
|
}
|
||||||
@@ -992,7 +977,7 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tlist = getTransformList(elem);
|
const tlist = elem.transform.baseVal;
|
||||||
const angle = getRotationAngleFromTransformList(tlist);
|
const angle = getRotationAngleFromTransformList(tlist);
|
||||||
const hasMatrixXForm = hasMatrixTransform(tlist);
|
const hasMatrixXForm = hasMatrixTransform(tlist);
|
||||||
|
|
||||||
@@ -1127,7 +1112,7 @@ export const getStrokedBBox = function (elems, addSVGElementFromJson, pathAction
|
|||||||
export const getVisibleElements = function (parentElement) {
|
export const getVisibleElements = function (parentElement) {
|
||||||
if (!parentElement) {
|
if (!parentElement) {
|
||||||
const svgcontent = editorContext_.getSVGContent();
|
const svgcontent = editorContext_.getSVGContent();
|
||||||
parentElement = svgcontent.children; // Prevent layers from being included
|
parentElement = svgcontent.children[0]; // Prevent layers from being included
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentElems = [];
|
const contentElems = [];
|
||||||
@@ -1162,10 +1147,9 @@ export const getStrokedBBoxDefaultVisible = function (elems) {
|
|||||||
* @param {boolean} toRad - When true returns the value in radians rather than degrees
|
* @param {boolean} toRad - When true returns the value in radians rather than degrees
|
||||||
* @returns {Float} The angle in degrees or radians
|
* @returns {Float} The angle in degrees or radians
|
||||||
*/
|
*/
|
||||||
export const getRotationAngleFromTransformList = function (tlist, toRad) {
|
export const getRotationAngleFromTransformList = (tlist, toRad) => {
|
||||||
if (!tlist) { return 0; } // <svg> elements have no tlist
|
if (!tlist) { return 0; } // <svg> element have no tlist
|
||||||
const N = tlist.numberOfItems;
|
for (let i = 0; i < tlist.numberOfItems; ++i) {
|
||||||
for (let i = 0; i < N; ++i) {
|
|
||||||
const xform = tlist.getItem(i);
|
const xform = tlist.getItem(i);
|
||||||
if (xform.type === 4) {
|
if (xform.type === 4) {
|
||||||
return toRad ? xform.angle * Math.PI / 180.0 : xform.angle;
|
return toRad ? xform.angle * Math.PI / 180.0 : xform.angle;
|
||||||
@@ -1184,7 +1168,7 @@ export const getRotationAngleFromTransformList = function (tlist, toRad) {
|
|||||||
export let getRotationAngle = function (elem, toRad) {
|
export let getRotationAngle = function (elem, toRad) {
|
||||||
const selected = elem || editorContext_.getSelectedElements()[0];
|
const selected = elem || editorContext_.getSelectedElements()[0];
|
||||||
// find the rotation transform (if any) and set it
|
// find the rotation transform (if any) and set it
|
||||||
const tlist = getTransformList(selected);
|
const tlist = selected.transform?.baseVal;
|
||||||
return getRotationAngleFromTransformList(tlist, toRad);
|
return getRotationAngleFromTransformList(tlist, toRad);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user