mirror of
https://github.com/scratchfoundation/scratchjr.git
synced 2024-12-01 11:27:16 -05:00
Transform.js module
This commit is contained in:
parent
535e61f628
commit
53ac780598
1 changed files with 483 additions and 477 deletions
|
@ -1,504 +1,510 @@
|
||||||
var Transform = function () {};
|
|
||||||
|
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
// SVG Transforms
|
// SVG Transforms
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
|
|
||||||
Transform.getList = function (elem) {
|
import SVGTools from './SVGTools';
|
||||||
if (elem == undefined) {
|
import SVG2Canvas from './SVG2Canvas';
|
||||||
return null;
|
import Paint from './Paint';
|
||||||
}
|
import Vector from '../geom/Vector';
|
||||||
if (elem.transform) {
|
import {gn, DEGTOR} from '../utils/lib';
|
||||||
return elem.transform.baseVal;
|
|
||||||
} else if (elem.gradientTransform) {
|
|
||||||
return elem.gradientTransform.baseVal;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.extract = function (elem, n) {
|
export default class Transform {
|
||||||
var tl = Transform.getList(elem);
|
static getList (elem) {
|
||||||
for (var i = 0; i < tl.numberOfItems; ++i) {
|
if (elem == undefined) {
|
||||||
if (tl.getItem(i).type == n) {
|
|
||||||
return tl.getItem(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Paint.root.createSVGTransform();
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getIndex = function (elem, n) {
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
for (var i = 0; i < tl.numberOfItems; ++i) {
|
|
||||||
if (tl.getItem(i).type == n) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.point = function (x, y, m) {
|
|
||||||
return Transform.newPoint(x, y).matrixTransform(m);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.newPoint = function (x, y) {
|
|
||||||
var pt = Paint.root.createSVGPoint();
|
|
||||||
pt.x = x;
|
|
||||||
pt.y = y;
|
|
||||||
return pt;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
// Element translation
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
Transform.translateTo = function (elem, xform) {
|
|
||||||
if (elem == undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var pname = elem.tagName;
|
|
||||||
// console.log ("translateTo", elem.id, elem.tagName, xform.matrix);
|
|
||||||
switch (pname) {
|
|
||||||
case 'g':
|
|
||||||
for (var i = 0; i < elem.childElementCount; i++) {
|
|
||||||
if (Transform.getList(elem.childNodes[i]) != null) {
|
|
||||||
Transform.translateTo(elem.childNodes[i], xform, Transform.getScaleMatrix(elem.childNodes[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'ellipse':
|
|
||||||
case 'circle':
|
|
||||||
var center = Transform.point(elem.getAttribute('cx'), elem.getAttribute('cy'), xform.matrix);
|
|
||||||
elem.setAttributeNS(null, 'cx', center.x);
|
|
||||||
elem.setAttributeNS(null, 'cy', center.y);
|
|
||||||
break;
|
|
||||||
case 'line':
|
|
||||||
Transform.line(elem, xform.matrix);
|
|
||||||
break;
|
|
||||||
case 'path':
|
|
||||||
Transform.applyToCmds(elem, xform.matrix);
|
|
||||||
break;
|
|
||||||
case 'clipPath':
|
|
||||||
Transform.translateTo(elem.childNodes[0], xform);
|
|
||||||
break;
|
|
||||||
case 'image':
|
|
||||||
case 'rect':
|
|
||||||
var corner = Transform.point(Number(elem.getAttribute('x')), Number(elem.getAttribute('y')), xform.matrix);
|
|
||||||
elem.setAttributeNS(null, 'x', corner.x);
|
|
||||||
elem.setAttributeNS(null, 'y', corner.y);
|
|
||||||
break;
|
|
||||||
case 'polygon':
|
|
||||||
case 'polyline':
|
|
||||||
var points = elem.points;
|
|
||||||
var delta = {
|
|
||||||
x: xform.matrix.e,
|
|
||||||
y: xform.matrix.f
|
|
||||||
};
|
|
||||||
for (var j = 0; j < points.numberOfItems; j++) {
|
|
||||||
var p = Vector.sum(points.getItem(j), delta);
|
|
||||||
points.getItem(j).x = p.x;
|
|
||||||
points.getItem(j).y = p.y;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Transform.updateAll(elem);
|
|
||||||
Transform.updateRotationCenter(elem);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.updateRotationCenter = function (elem) {
|
|
||||||
if (Transform.getRotationAngle(elem) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var angle = Transform.getRotationAngle(elem);
|
|
||||||
var rot = Transform.extract(elem, 4);
|
|
||||||
var mtx = Transform.getCombinedMatrices(elem); // skips rotation matrices
|
|
||||||
var center = SVGTools.getBoxCenter(elem);
|
|
||||||
center = Transform.point(center.x, center.y, mtx);
|
|
||||||
rot.setRotate(angle, center.x, center.y);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.line = function (elem, mtx) {
|
|
||||||
var pt = Paint.root.createSVGPoint();
|
|
||||||
pt.x = Number(elem.getAttribute('x1'));
|
|
||||||
pt.y = Number(elem.getAttribute('y1'));
|
|
||||||
pt = pt.matrixTransform(mtx);
|
|
||||||
elem.setAttribute('x1', pt.x);
|
|
||||||
elem.setAttribute('y1', pt.y);
|
|
||||||
pt.x = Number(elem.getAttribute('x2'));
|
|
||||||
pt.y = Number(elem.getAttribute('y2'));
|
|
||||||
pt = pt.matrixTransform(mtx);
|
|
||||||
elem.setAttribute('x2', pt.x);
|
|
||||||
elem.setAttribute('y2', pt.y);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.eleminateTranslates = function (elem) {
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
for (var i = 0; i < tl.numberOfItems; ++i) {
|
|
||||||
if (tl.getItem(i).type == 2) {
|
|
||||||
var trnsf = tl.getItem(i);
|
|
||||||
tl.removeItem(i);
|
|
||||||
if (elem.nodeName == 'image') {
|
|
||||||
var clip = gn('clip_' + elem.id);
|
|
||||||
if (clip) {
|
|
||||||
Transform.translateTo(clip.childNodes[0], trnsf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Transform.translateTo(elem, trnsf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.eliminateAll = function (spr) {
|
|
||||||
var tl = Transform.getList(spr);
|
|
||||||
if (tl && tl.numberOfItems > 0) {
|
|
||||||
var k = tl.numberOfItems;
|
|
||||||
while (k--) {
|
|
||||||
tl.removeItem(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tl;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.combineAll = function (elem) {
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
if (tl == null) {
|
|
||||||
return Paint.root.createSVGMatrix();
|
|
||||||
}
|
|
||||||
var n = tl.numberOfItems;
|
|
||||||
var m = Paint.root.createSVGMatrix();
|
|
||||||
for (var i = 0; i < n; i++) {
|
|
||||||
var mtom = tl.getItem(i);
|
|
||||||
m = m.multiply(mtom.matrix);
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.appendForMove = function (elem, t) {
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
if (tl == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tl.numberOfItems == 0) {
|
|
||||||
tl.appendItem(t);
|
|
||||||
} else {
|
|
||||||
tl.insertItemBefore(t, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getTranslateTransform = function () {
|
|
||||||
var res = Paint.root.createSVGTransform();
|
|
||||||
res.setTranslate(0, 0);
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.applyRotation = function (elem, angle) {
|
|
||||||
var rot = Paint.root.createSVGTransform();
|
|
||||||
var box = SVGTools.getBox(elem);
|
|
||||||
var cx = box.x + box.width / 2;
|
|
||||||
var cy = box.y + box.height / 2;
|
|
||||||
rot.setRotate(angle, cx, cy);
|
|
||||||
Transform.getList(elem).appendItem(rot);
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////
|
|
||||||
// SVG Transforms
|
|
||||||
//////////////////////////////////
|
|
||||||
|
|
||||||
Transform.getRotationAngle = function (elem, to_rad) {
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
if (!tl) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var num = tl.numberOfItems;
|
|
||||||
for (var i = 0; i < num; ++i) {
|
|
||||||
var xform = tl.getItem(i);
|
|
||||||
if (xform.type == 4) {
|
|
||||||
return to_rad ? xform.angle * DEGTOR : xform.angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getRotation = function (elem) {
|
|
||||||
//console.log ("Transform.getRotation", elem);
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
var num = tl.numberOfItems;
|
|
||||||
for (var i = 0; i < num; ++i) {
|
|
||||||
var xform = tl.getItem(i);
|
|
||||||
if (xform.type == 4) {
|
|
||||||
return xform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var rot = Paint.root.createSVGTransform();
|
|
||||||
var center = SVGTools.getBoxCenter(elem);
|
|
||||||
rot.setRotate(0, center.x, center.y);
|
|
||||||
|
|
||||||
if (tl.numberOfItems == 0) {
|
|
||||||
Transform.getList(elem).appendItem(rot);
|
|
||||||
} else {
|
|
||||||
Transform.getList(elem).insertItemBefore(rot, 0);
|
|
||||||
}
|
|
||||||
return rot;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getValid = function (elem) {
|
|
||||||
if (!elem) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var tl = Transform.getList(elem);
|
|
||||||
if (!tl) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (tl && tl.numberOfItems > 0) {
|
|
||||||
var k = tl.numberOfItems;
|
|
||||||
while (k--) {
|
|
||||||
var xform = tl.getItem(k);
|
|
||||||
if (xform.type == 0) {
|
|
||||||
tl.removeItem(k);
|
|
||||||
}
|
|
||||||
if (xform.matrix.isIdentity()) {
|
|
||||||
tl.removeItem(k);
|
|
||||||
} else if (xform.type == 4) { // remove zero-degree rotations
|
|
||||||
if (xform.angle == 0) {
|
|
||||||
tl.removeItem(k);
|
|
||||||
}
|
|
||||||
if (xform.angle == 360) {
|
|
||||||
tl.removeItem(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tl.numberOfItems == 1 && Transform.getRotationAngle(elem)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
if (elem.transform) {
|
||||||
// if this element had no transforms, we are done
|
return elem.transform.baseVal;
|
||||||
if (tl.numberOfItems == 0) {
|
} else if (elem.gradientTransform) {
|
||||||
if (elem.getAttribute('transform')) {
|
return elem.gradientTransform.baseVal;
|
||||||
elem.removeAttribute('transform');
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return tl;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getCombinedMatrices = function (elem) {
|
static extract (elem, n) {
|
||||||
var tl = Transform.getList(elem);
|
var tl = Transform.getList(elem);
|
||||||
if (tl == null) {
|
for (var i = 0; i < tl.numberOfItems; ++i) {
|
||||||
return Paint.root.createSVGMatrix();
|
if (tl.getItem(i).type == n) {
|
||||||
|
return tl.getItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Paint.root.createSVGTransform();
|
||||||
}
|
}
|
||||||
var n = tl.numberOfItems;
|
|
||||||
var m = Paint.root.createSVGMatrix();
|
static getIndex (elem, n) {
|
||||||
for (var i = 0; i < n; i++) {
|
var tl = Transform.getList(elem);
|
||||||
var mtom = tl.getItem(i);
|
for (var i = 0; i < tl.numberOfItems; ++i) {
|
||||||
if (mtom.type == 4) {
|
if (tl.getItem(i).type == n) {
|
||||||
continue; // skip rotation transform
|
return i;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static point (x, y, m) {
|
||||||
|
return Transform.newPoint(x, y).matrixTransform(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static newPoint (x, y) {
|
||||||
|
var pt = Paint.root.createSVGPoint();
|
||||||
|
pt.x = x;
|
||||||
|
pt.y = y;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// Element translation
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
static translateTo (elem, xform) {
|
||||||
|
if (elem == undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pname = elem.tagName;
|
||||||
|
// console.log ("translateTo", elem.id, elem.tagName, xform.matrix);
|
||||||
|
switch (pname) {
|
||||||
|
case 'g':
|
||||||
|
for (var i = 0; i < elem.childElementCount; i++) {
|
||||||
|
if (Transform.getList(elem.childNodes[i]) != null) {
|
||||||
|
Transform.translateTo(elem.childNodes[i], xform, Transform.getScaleMatrix(elem.childNodes[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'ellipse':
|
||||||
|
case 'circle':
|
||||||
|
var center = Transform.point(elem.getAttribute('cx'), elem.getAttribute('cy'), xform.matrix);
|
||||||
|
elem.setAttributeNS(null, 'cx', center.x);
|
||||||
|
elem.setAttributeNS(null, 'cy', center.y);
|
||||||
|
break;
|
||||||
|
case 'line':
|
||||||
|
Transform.line(elem, xform.matrix);
|
||||||
|
break;
|
||||||
|
case 'path':
|
||||||
|
Transform.applyToCmds(elem, xform.matrix);
|
||||||
|
break;
|
||||||
|
case 'clipPath':
|
||||||
|
Transform.translateTo(elem.childNodes[0], xform);
|
||||||
|
break;
|
||||||
|
case 'image':
|
||||||
|
case 'rect':
|
||||||
|
var corner = Transform.point(Number(elem.getAttribute('x')), Number(elem.getAttribute('y')), xform.matrix);
|
||||||
|
elem.setAttributeNS(null, 'x', corner.x);
|
||||||
|
elem.setAttributeNS(null, 'y', corner.y);
|
||||||
|
break;
|
||||||
|
case 'polygon':
|
||||||
|
case 'polyline':
|
||||||
|
var points = elem.points;
|
||||||
|
var delta = {
|
||||||
|
x: xform.matrix.e,
|
||||||
|
y: xform.matrix.f
|
||||||
|
};
|
||||||
|
for (var j = 0; j < points.numberOfItems; j++) {
|
||||||
|
var p = Vector.sum(points.getItem(j), delta);
|
||||||
|
points.getItem(j).x = p.x;
|
||||||
|
points.getItem(j).y = p.y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Transform.updateAll(elem);
|
||||||
|
Transform.updateRotationCenter(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static updateRotationCenter (elem) {
|
||||||
|
if (Transform.getRotationAngle(elem) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var angle = Transform.getRotationAngle(elem);
|
||||||
|
var rot = Transform.extract(elem, 4);
|
||||||
|
var mtx = Transform.getCombinedMatrices(elem); // skips rotation matrices
|
||||||
|
var center = SVGTools.getBoxCenter(elem);
|
||||||
|
center = Transform.point(center.x, center.y, mtx);
|
||||||
|
rot.setRotate(angle, center.x, center.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static line (elem, mtx) {
|
||||||
|
var pt = Paint.root.createSVGPoint();
|
||||||
|
pt.x = Number(elem.getAttribute('x1'));
|
||||||
|
pt.y = Number(elem.getAttribute('y1'));
|
||||||
|
pt = pt.matrixTransform(mtx);
|
||||||
|
elem.setAttribute('x1', pt.x);
|
||||||
|
elem.setAttribute('y1', pt.y);
|
||||||
|
pt.x = Number(elem.getAttribute('x2'));
|
||||||
|
pt.y = Number(elem.getAttribute('y2'));
|
||||||
|
pt = pt.matrixTransform(mtx);
|
||||||
|
elem.setAttribute('x2', pt.x);
|
||||||
|
elem.setAttribute('y2', pt.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static eleminateTranslates (elem) {
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
for (var i = 0; i < tl.numberOfItems; ++i) {
|
||||||
|
if (tl.getItem(i).type == 2) {
|
||||||
|
var trnsf = tl.getItem(i);
|
||||||
|
tl.removeItem(i);
|
||||||
|
if (elem.nodeName == 'image') {
|
||||||
|
var clip = gn('clip_' + elem.id);
|
||||||
|
if (clip) {
|
||||||
|
Transform.translateTo(clip.childNodes[0], trnsf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Transform.translateTo(elem, trnsf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static eliminateAll (spr) {
|
||||||
|
var tl = Transform.getList(spr);
|
||||||
|
if (tl && tl.numberOfItems > 0) {
|
||||||
|
var k = tl.numberOfItems;
|
||||||
|
while (k--) {
|
||||||
|
tl.removeItem(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static combineAll (elem) {
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
if (tl == null) {
|
||||||
|
return Paint.root.createSVGMatrix();
|
||||||
|
}
|
||||||
|
var n = tl.numberOfItems;
|
||||||
|
var m = Paint.root.createSVGMatrix();
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
var mtom = tl.getItem(i);
|
||||||
m = m.multiply(mtom.matrix);
|
m = m.multiply(mtom.matrix);
|
||||||
}
|
}
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.hasScaleMatrix = function (elem) {
|
static appendForMove (elem, t) {
|
||||||
var tl = Transform.getList(elem);
|
var tl = Transform.getList(elem);
|
||||||
if (tl == null) {
|
if (tl == null) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
for (var i = 0; i < tl.numberOfItems; ++i) {
|
if (tl.numberOfItems == 0) {
|
||||||
if (tl.getItem(i).type == 3) {
|
tl.appendItem(t);
|
||||||
return true;
|
} else {
|
||||||
|
tl.insertItemBefore(t, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getScaleMatrix = function (e) {
|
static getTranslateTransform () {
|
||||||
var tl = Transform.getList(e);
|
var res = Paint.root.createSVGTransform();
|
||||||
var scaleIndex = Transform.getIndex(e, 3);
|
res.setTranslate(0, 0);
|
||||||
if (scaleIndex != null) {
|
return res;
|
||||||
return tl.getItem(scaleIndex).matrix;
|
|
||||||
}
|
}
|
||||||
return Paint.root.createSVGMatrix();
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.updateAll = function (elem) {
|
static applyRotation (elem, angle) {
|
||||||
var newtl = Transform.getList(elem);
|
var rot = Paint.root.createSVGTransform();
|
||||||
if (newtl && newtl.numberOfItems == 0) {
|
var box = SVGTools.getBox(elem);
|
||||||
elem.removeAttribute('transform');
|
var cx = box.x + box.width / 2;
|
||||||
|
var cy = box.y + box.height / 2;
|
||||||
|
rot.setRotate(angle, cx, cy);
|
||||||
|
Transform.getList(elem).appendItem(rot);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
Transform.applyMatrix = function (elem, matrix) {
|
//////////////////////////////////
|
||||||
var m = Paint.root.createSVGTransform();
|
// SVG Transforms
|
||||||
m.setMatrix(matrix);
|
//////////////////////////////////
|
||||||
Transform.getList(elem).appendItem(m);
|
|
||||||
};
|
static getRotationAngle (elem, to_rad) {
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
if (!tl) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
var num = tl.numberOfItems;
|
||||||
|
for (var i = 0; i < num; ++i) {
|
||||||
|
var xform = tl.getItem(i);
|
||||||
|
if (xform.type == 4) {
|
||||||
|
return to_rad ? xform.angle * DEGTOR : xform.angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getRotation (elem) {
|
||||||
|
//console.log ("Transform.getRotation", elem);
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
var num = tl.numberOfItems;
|
||||||
|
for (var i = 0; i < num; ++i) {
|
||||||
|
var xform = tl.getItem(i);
|
||||||
|
if (xform.type == 4) {
|
||||||
|
return xform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var rot = Paint.root.createSVGTransform();
|
||||||
|
var center = SVGTools.getBoxCenter(elem);
|
||||||
|
rot.setRotate(0, center.x, center.y);
|
||||||
|
|
||||||
|
if (tl.numberOfItems == 0) {
|
||||||
|
Transform.getList(elem).appendItem(rot);
|
||||||
|
} else {
|
||||||
|
Transform.getList(elem).insertItemBefore(rot, 0);
|
||||||
|
}
|
||||||
|
return rot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getValid (elem) {
|
||||||
|
if (!elem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
if (!tl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (tl && tl.numberOfItems > 0) {
|
||||||
|
var k = tl.numberOfItems;
|
||||||
|
while (k--) {
|
||||||
|
var xform = tl.getItem(k);
|
||||||
|
if (xform.type == 0) {
|
||||||
|
tl.removeItem(k);
|
||||||
|
}
|
||||||
|
if (xform.matrix.isIdentity()) {
|
||||||
|
tl.removeItem(k);
|
||||||
|
} else if (xform.type == 4) { // remove zero-degree rotations
|
||||||
|
if (xform.angle == 0) {
|
||||||
|
tl.removeItem(k);
|
||||||
|
}
|
||||||
|
if (xform.angle == 360) {
|
||||||
|
tl.removeItem(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tl.numberOfItems == 1 && Transform.getRotationAngle(elem)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if this element had no transforms, we are done
|
||||||
|
if (tl.numberOfItems == 0) {
|
||||||
|
if (elem.getAttribute('transform')) {
|
||||||
|
elem.removeAttribute('transform');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getCombinedMatrices (elem) {
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
if (tl == null) {
|
||||||
|
return Paint.root.createSVGMatrix();
|
||||||
|
}
|
||||||
|
var n = tl.numberOfItems;
|
||||||
|
var m = Paint.root.createSVGMatrix();
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
var mtom = tl.getItem(i);
|
||||||
|
if (mtom.type == 4) {
|
||||||
|
continue; // skip rotation transform
|
||||||
|
} else {
|
||||||
|
m = m.multiply(mtom.matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hasScaleMatrix (elem) {
|
||||||
|
var tl = Transform.getList(elem);
|
||||||
|
if (tl == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < tl.numberOfItems; ++i) {
|
||||||
|
if (tl.getItem(i).type == 3) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getScaleMatrix (e) {
|
||||||
|
var tl = Transform.getList(e);
|
||||||
|
var scaleIndex = Transform.getIndex(e, 3);
|
||||||
|
if (scaleIndex != null) {
|
||||||
|
return tl.getItem(scaleIndex).matrix;
|
||||||
|
}
|
||||||
|
return Paint.root.createSVGMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
static updateAll (elem) {
|
||||||
|
var newtl = Transform.getList(elem);
|
||||||
|
if (newtl && newtl.numberOfItems == 0) {
|
||||||
|
elem.removeAttribute('transform');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static applyMatrix (elem, matrix) {
|
||||||
|
var m = Paint.root.createSVGTransform();
|
||||||
|
m.setMatrix(matrix);
|
||||||
|
Transform.getList(elem).appendItem(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Paths data structure
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static applyToCmds (shape, mtx) {
|
||||||
|
var d = shape.getAttribute('d');
|
||||||
|
var list = SVG2Canvas.getCommandList(d);
|
||||||
|
var plist = [];
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var j = 0; j < list.length; j++) {
|
||||||
|
var cmd = list[j];
|
||||||
|
cmd = Transform.getModifiedCmd(cmd, mtx);
|
||||||
|
plist.push(cmd);
|
||||||
|
}
|
||||||
|
var path = SVG2Canvas.arrayToString(plist);
|
||||||
|
shape.setAttribute('d', path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getModifiedCmd (cmd, mtx) {
|
||||||
|
var pt = Transform.newPoint(0, 0);
|
||||||
|
if (cmd.length < 2) {
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
if (cmd.length < 3) {
|
||||||
|
if (cmd[0].toLowerCase() == 'h') {
|
||||||
|
pt.x = cmd[1];
|
||||||
|
cmd[1] = pt.matrixTransform(mtx).x;
|
||||||
|
} else {
|
||||||
|
pt.y = cmd[1];
|
||||||
|
cmd[1] = pt.matrixTransform(mtx).y;
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
for (var i = 1; i < cmd.length; i += 2) {
|
||||||
|
pt.x = cmd[i];
|
||||||
|
pt.y = cmd[i + 1];
|
||||||
|
pt = pt.matrixTransform(mtx);
|
||||||
|
cmd[i] = pt.x;
|
||||||
|
cmd[i + 1] = pt.y;
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// Element Rotation
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
|
||||||
|
static rotateFromPoint (erot, node) {
|
||||||
|
var pname = node.tagName;
|
||||||
|
var rot = Transform.getRotation(node);
|
||||||
|
var c, p, delta, mtx, cx, cy;
|
||||||
|
switch (pname) {
|
||||||
|
case 'g':
|
||||||
|
for (var i = 0; i < node.childElementCount; i++) {
|
||||||
|
Transform.rotateFromPoint(erot, node.childNodes[i]);
|
||||||
|
}
|
||||||
|
if (node.getAttribute('transform')) {
|
||||||
|
node.removeAttribute('transform');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'clipPath':
|
||||||
|
// it is done in the image processing
|
||||||
|
break;
|
||||||
|
case 'image':
|
||||||
|
case 'rect':
|
||||||
|
c = SVGTools.getBoxCenter(node);
|
||||||
|
p = Transform.point(c.x, c.y, erot.matrix);
|
||||||
|
delta = Vector.diff(p, c);
|
||||||
|
mtx = Paint.root.createSVGMatrix();
|
||||||
|
mtx.e = delta.x;
|
||||||
|
mtx.f = delta.y;
|
||||||
|
var pt = Paint.root.createSVGPoint();
|
||||||
|
pt.x = Number(node.getAttribute('x'));
|
||||||
|
pt.y = Number(node.getAttribute('y'));
|
||||||
|
pt = pt.matrixTransform(mtx);
|
||||||
|
var imgdelta = Vector.diff({
|
||||||
|
x: pt.x,
|
||||||
|
y: pt.y
|
||||||
|
}, {
|
||||||
|
x: node.getAttribute('x'),
|
||||||
|
y: node.getAttribute('y')
|
||||||
|
});
|
||||||
|
node.setAttribute('x', pt.x);
|
||||||
|
node.setAttribute('y', pt.y);
|
||||||
|
if ((pname == 'image') && (Vector.len(imgdelta) > 0)) {
|
||||||
|
var clip = gn('pathmask_' + node.id);
|
||||||
|
if (clip) {
|
||||||
|
if (clip.getAttribute('transform')) {
|
||||||
|
clip.removeAttribute('transform');
|
||||||
|
}
|
||||||
|
var cmtx = Paint.root.createSVGMatrix();
|
||||||
|
cmtx.e = imgdelta.x;
|
||||||
|
cmtx.f = imgdelta.y;
|
||||||
|
Transform.applyToCmds(clip, cmtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'circle':
|
||||||
|
case 'ellipse':
|
||||||
|
cx = Number(node.getAttribute('cx'));
|
||||||
|
cy = Number(node.getAttribute('cy'));
|
||||||
|
p = Transform.point(cx, cy, erot.matrix);
|
||||||
|
var attr = {
|
||||||
|
'cx': p.x,
|
||||||
|
'cy': p.y
|
||||||
|
};
|
||||||
|
for (var val in attr) {
|
||||||
|
node.setAttributeNS(null, val, Math.round(attr[val] * 100) / 100);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'line':
|
||||||
|
c = SVGTools.getBoxCenter(node);
|
||||||
|
p = Transform.point(c.x, c.y, erot.matrix);
|
||||||
|
delta = Vector.diff(p, c);
|
||||||
|
mtx = Paint.root.createSVGMatrix();
|
||||||
|
mtx.e = delta.x;
|
||||||
|
mtx.f = delta.y;
|
||||||
|
Transform.line(node, mtx);
|
||||||
|
break;
|
||||||
|
case 'path':
|
||||||
|
c = SVGTools.getBoxCenter(node);
|
||||||
|
p = Transform.point(c.x, c.y, erot.matrix);
|
||||||
|
delta = Vector.diff(p, c);
|
||||||
|
mtx = Paint.root.createSVGMatrix();
|
||||||
|
mtx.e = delta.x;
|
||||||
|
mtx.f = delta.y;
|
||||||
|
Transform.applyToCmds(node, mtx);
|
||||||
|
break;
|
||||||
|
case 'polygon':
|
||||||
|
case 'polyline':
|
||||||
|
c = SVGTools.getBoxCenter(node);
|
||||||
|
p = Transform.point(c.x, c.y, erot.matrix);
|
||||||
|
delta = Vector.diff(p, c);
|
||||||
|
mtx = Paint.root.createSVGMatrix();
|
||||||
|
mtx.e = delta.x;
|
||||||
|
mtx.f = delta.y;
|
||||||
|
var points = node.points;
|
||||||
|
for (var j = 0; j < points.numberOfItems; j++) {
|
||||||
|
p = Transform.point(points.getItem(j).x, points.getItem(j).y, mtx);
|
||||||
|
points.getItem(j).x = p.x;
|
||||||
|
points.getItem(j).y = p.y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pname == 'g') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pname == 'clipPath') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rot = Transform.getRotation(node);
|
||||||
|
var box = SVGTools.getBox(node);
|
||||||
|
cx = box.x + box.width / 2;
|
||||||
|
cy = box.y + box.height / 2;
|
||||||
|
rot.setRotate(erot.angle + rot.angle, cx, cy);
|
||||||
|
Transform.updateRotationCenter(node);
|
||||||
|
if (pname == 'path') {
|
||||||
|
Transform.applyToCmds(node, Transform.combineAll(node));
|
||||||
|
Transform.eliminateAll(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SVGMatrix.prototype.isIdentity = function () {
|
SVGMatrix.prototype.isIdentity = function () {
|
||||||
return (this.a == 1 && this.b == 0 && this.c == 0 && this.d == 1 && this.e == 0 && this.f == 0);
|
return (this.a == 1 && this.b == 0 && this.c == 0 && this.d == 1 && this.e == 0 && this.f == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Paths data structure
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Transform.applyToCmds = function (shape, mtx) {
|
|
||||||
var d = shape.getAttribute('d');
|
|
||||||
var list = SVG2Canvas.getCommandList(d);
|
|
||||||
var plist = [];
|
|
||||||
if (!list) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var j = 0; j < list.length; j++) {
|
|
||||||
var cmd = list[j];
|
|
||||||
cmd = Transform.getModifiedCmd(cmd, mtx);
|
|
||||||
plist.push(cmd);
|
|
||||||
}
|
|
||||||
var path = SVG2Canvas.arrayToString(plist);
|
|
||||||
shape.setAttribute('d', path);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.getModifiedCmd = function (cmd, mtx) {
|
|
||||||
var pt = Transform.newPoint(0, 0);
|
|
||||||
if (cmd.length < 2) {
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
if (cmd.length < 3) {
|
|
||||||
if (cmd[0].toLowerCase() == 'h') {
|
|
||||||
pt.x = cmd[1];
|
|
||||||
cmd[1] = pt.matrixTransform(mtx).x;
|
|
||||||
} else {
|
|
||||||
pt.y = cmd[1];
|
|
||||||
cmd[1] = pt.matrixTransform(mtx).y;
|
|
||||||
}
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
for (var i = 1; i < cmd.length; i += 2) {
|
|
||||||
pt.x = cmd[i];
|
|
||||||
pt.y = cmd[i + 1];
|
|
||||||
pt = pt.matrixTransform(mtx);
|
|
||||||
cmd[i] = pt.x;
|
|
||||||
cmd[i + 1] = pt.y;
|
|
||||||
}
|
|
||||||
return cmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
|
||||||
// Element Rotation
|
|
||||||
///////////////////////////////////////////////
|
|
||||||
|
|
||||||
Transform.rotateFromPoint = function (erot, node) {
|
|
||||||
var pname = node.tagName;
|
|
||||||
var rot = Transform.getRotation(node);
|
|
||||||
var c, p, delta, mtx, cx, cy;
|
|
||||||
switch (pname) {
|
|
||||||
case 'g':
|
|
||||||
for (var i = 0; i < node.childElementCount; i++) {
|
|
||||||
Transform.rotateFromPoint(erot, node.childNodes[i]);
|
|
||||||
}
|
|
||||||
if (node.getAttribute('transform')) {
|
|
||||||
node.removeAttribute('transform');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'clipPath':
|
|
||||||
// it is done in the image processing
|
|
||||||
break;
|
|
||||||
case 'image':
|
|
||||||
case 'rect':
|
|
||||||
c = SVGTools.getBoxCenter(node);
|
|
||||||
p = Transform.point(c.x, c.y, erot.matrix);
|
|
||||||
delta = Vector.diff(p, c);
|
|
||||||
mtx = Paint.root.createSVGMatrix();
|
|
||||||
mtx.e = delta.x;
|
|
||||||
mtx.f = delta.y;
|
|
||||||
var pt = Paint.root.createSVGPoint();
|
|
||||||
pt.x = Number(node.getAttribute('x'));
|
|
||||||
pt.y = Number(node.getAttribute('y'));
|
|
||||||
pt = pt.matrixTransform(mtx);
|
|
||||||
var imgdelta = Vector.diff({
|
|
||||||
x: pt.x,
|
|
||||||
y: pt.y
|
|
||||||
}, {
|
|
||||||
x: node.getAttribute('x'),
|
|
||||||
y: node.getAttribute('y')
|
|
||||||
});
|
|
||||||
node.setAttribute('x', pt.x);
|
|
||||||
node.setAttribute('y', pt.y);
|
|
||||||
if ((pname == 'image') && (Vector.len(imgdelta) > 0)) {
|
|
||||||
var clip = gn('pathmask_' + node.id);
|
|
||||||
if (clip) {
|
|
||||||
if (clip.getAttribute('transform')) {
|
|
||||||
clip.removeAttribute('transform');
|
|
||||||
}
|
|
||||||
var cmtx = Paint.root.createSVGMatrix();
|
|
||||||
cmtx.e = imgdelta.x;
|
|
||||||
cmtx.f = imgdelta.y;
|
|
||||||
Transform.applyToCmds(clip, cmtx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'circle':
|
|
||||||
case 'ellipse':
|
|
||||||
cx = Number(node.getAttribute('cx'));
|
|
||||||
cy = Number(node.getAttribute('cy'));
|
|
||||||
p = Transform.point(cx, cy, erot.matrix);
|
|
||||||
var attr = {
|
|
||||||
'cx': p.x,
|
|
||||||
'cy': p.y
|
|
||||||
};
|
|
||||||
for (var val in attr) {
|
|
||||||
node.setAttributeNS(null, val, Math.round(attr[val] * 100) / 100);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'line':
|
|
||||||
c = SVGTools.getBoxCenter(node);
|
|
||||||
p = Transform.point(c.x, c.y, erot.matrix);
|
|
||||||
delta = Vector.diff(p, c);
|
|
||||||
mtx = Paint.root.createSVGMatrix();
|
|
||||||
mtx.e = delta.x;
|
|
||||||
mtx.f = delta.y;
|
|
||||||
Transform.line(node, mtx);
|
|
||||||
break;
|
|
||||||
case 'path':
|
|
||||||
c = SVGTools.getBoxCenter(node);
|
|
||||||
p = Transform.point(c.x, c.y, erot.matrix);
|
|
||||||
delta = Vector.diff(p, c);
|
|
||||||
mtx = Paint.root.createSVGMatrix();
|
|
||||||
mtx.e = delta.x;
|
|
||||||
mtx.f = delta.y;
|
|
||||||
Transform.applyToCmds(node, mtx);
|
|
||||||
break;
|
|
||||||
case 'polygon':
|
|
||||||
case 'polyline':
|
|
||||||
c = SVGTools.getBoxCenter(node);
|
|
||||||
p = Transform.point(c.x, c.y, erot.matrix);
|
|
||||||
delta = Vector.diff(p, c);
|
|
||||||
mtx = Paint.root.createSVGMatrix();
|
|
||||||
mtx.e = delta.x;
|
|
||||||
mtx.f = delta.y;
|
|
||||||
var points = node.points;
|
|
||||||
for (var j = 0; j < points.numberOfItems; j++) {
|
|
||||||
p = Transform.point(points.getItem(j).x, points.getItem(j).y, mtx);
|
|
||||||
points.getItem(j).x = p.x;
|
|
||||||
points.getItem(j).y = p.y;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (pname == 'g') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pname == 'clipPath') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rot = Transform.getRotation(node);
|
|
||||||
var box = SVGTools.getBox(node);
|
|
||||||
cx = box.x + box.width / 2;
|
|
||||||
cy = box.y + box.height / 2;
|
|
||||||
rot.setRotate(erot.angle + rot.angle, cx, cy);
|
|
||||||
Transform.updateRotationCenter(node);
|
|
||||||
if (pname == 'path') {
|
|
||||||
Transform.applyToCmds(node, Transform.combineAll(node));
|
|
||||||
Transform.eliminateAll(node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in a new issue