fixtransforms branch: Fixed issues 348, 349 and 350. Made multiplyMatrix() accept any amount of matrices as parameters. Improved BBox calculation on rotated groups
git-svn-id: http://svg-edit.googlecode.com/svn/branches/fixtransforms@1002 eee81c28-f429-11dd-99c0-75d572ba1dddmaster
parent
fecc1da764
commit
ed45a7b2fa
|
@ -88,10 +88,10 @@ function SvgCanvas(c)
|
||||||
{
|
{
|
||||||
|
|
||||||
var toXml = function(str) {
|
var toXml = function(str) {
|
||||||
return str.replace("&", "&").replace("<", "<").replace(">",">");
|
return $('<p/>').text(str).html();
|
||||||
};
|
};
|
||||||
var fromXml = function(str) {
|
var fromXml = function(str) {
|
||||||
return str.replace(">", ">").replace("<", "<").replace("&", "&");
|
return $('<p/>').html(str).text();
|
||||||
};
|
};
|
||||||
|
|
||||||
var pathFuncsStrs = ['Moveto','Lineto','CurvetoCubic','CurvetoQuadratic','Arc','LinetoHorizontal','LinetoVertical','CurvetoCubicSmooth','CurvetoQuadraticSmooth']
|
var pathFuncsStrs = ['Moveto','Lineto','CurvetoCubic','CurvetoQuadratic','Arc','LinetoHorizontal','LinetoVertical','CurvetoCubicSmooth','CurvetoQuadraticSmooth']
|
||||||
|
@ -1441,7 +1441,7 @@ function BatchCommand(text) {
|
||||||
var tm = tlist.getItem(N-3).matrix;
|
var tm = tlist.getItem(N-3).matrix;
|
||||||
var sm = tlist.getItem(N-2).matrix;
|
var sm = tlist.getItem(N-2).matrix;
|
||||||
var tmn = tlist.getItem(N-1).matrix;
|
var tmn = tlist.getItem(N-1).matrix;
|
||||||
var em = matrixMultiply(tm, matrixMultiply(sm, tmn));
|
var em = matrixMultiply(tm, sm, tmn);
|
||||||
|
|
||||||
var children = selected.childNodes;
|
var children = selected.childNodes;
|
||||||
var c = children.length;
|
var c = children.length;
|
||||||
|
@ -1461,7 +1461,7 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// [E][M] = [M][E2]
|
// [E][M] = [M][E2]
|
||||||
// [E2] = [M_inv][E][M]
|
// [E2] = [M_inv][E][M]
|
||||||
var e2 = matrixMultiply(m.inverse(), matrixMultiply(em, m));
|
var e2 = matrixMultiply(m.inverse(), em, m);
|
||||||
|
|
||||||
// this does not appear to work, something wrong with my logic here
|
// this does not appear to work, something wrong with my logic here
|
||||||
var e2t = svgroot.createSVGTransform();
|
var e2t = svgroot.createSVGTransform();
|
||||||
|
@ -1486,7 +1486,7 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// [T][S][-T][M] = [T][S][M][-T2]
|
// [T][S][-T][M] = [T][S][M][-T2]
|
||||||
// [-T2] = [M_inv][-T][M]
|
// [-T2] = [M_inv][-T][M]
|
||||||
var t2n = matrixMultiply(m.inverse(), matrixMultiply(tmn,m));
|
var t2n = matrixMultiply(m.inverse(), tmn, m);
|
||||||
// [T2] is always negative translation of [-T2]
|
// [T2] is always negative translation of [-T2]
|
||||||
var t2 = svgroot.createSVGMatrix();
|
var t2 = svgroot.createSVGMatrix();
|
||||||
t2.e = -t2n.e;
|
t2.e = -t2n.e;
|
||||||
|
@ -1494,13 +1494,7 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// [T][S][-T][M] = [M][T2][S2][-T2]
|
// [T][S][-T][M] = [M][T2][S2][-T2]
|
||||||
// [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv]
|
// [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv]
|
||||||
var s2 = matrixMultiply(
|
var s2 = matrixMultiply(t2.inverse(), m.inverse(), tm, sm, tmn, m, t2n.inverse());
|
||||||
t2.inverse(), matrixMultiply(
|
|
||||||
m.inverse(), matrixMultiply(
|
|
||||||
tm, matrixMultiply(
|
|
||||||
sm, matrixMultiply(
|
|
||||||
tmn, matrixMultiply(
|
|
||||||
m, t2n.inverse()) ) ) ) ) );
|
|
||||||
|
|
||||||
var translateOrigin = svgroot.createSVGTransform(),
|
var translateOrigin = svgroot.createSVGTransform(),
|
||||||
scale = svgroot.createSVGTransform(),
|
scale = svgroot.createSVGTransform(),
|
||||||
|
@ -1597,7 +1591,7 @@ function BatchCommand(text) {
|
||||||
var tail = transformListToTransform(tlist, n+1, tlist.numberOfItems-1).matrix,
|
var tail = transformListToTransform(tlist, n+1, tlist.numberOfItems-1).matrix,
|
||||||
tail_inv = tail.inverse();
|
tail_inv = tail.inverse();
|
||||||
// multiply (B_inv * A * B)
|
// multiply (B_inv * A * B)
|
||||||
m = matrixMultiply(tail_inv, matrixMultiply(xform.matrix,tail));
|
m = matrixMultiply(tail_inv, xform.matrix, tail);
|
||||||
|
|
||||||
var remap = null, scalew = null, scaleh = null;
|
var remap = null, scalew = null, scaleh = null;
|
||||||
switch (xform.type) {
|
switch (xform.type) {
|
||||||
|
@ -1913,6 +1907,8 @@ function BatchCommand(text) {
|
||||||
selectedElements.sort(function(a,b) {
|
selectedElements.sort(function(a,b) {
|
||||||
if(a && b && a.compareDocumentPosition) {
|
if(a && b && a.compareDocumentPosition) {
|
||||||
return 3 - (b.compareDocumentPosition(a) & 6);
|
return 3 - (b.compareDocumentPosition(a) & 6);
|
||||||
|
} else if(a == null) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1998,40 +1994,51 @@ function BatchCommand(text) {
|
||||||
// of the resulting matrix, we have to do it with translate/rotate/scale
|
// of the resulting matrix, we have to do it with translate/rotate/scale
|
||||||
// TODO: Actually all browsers seem to allow setting of a-f in a SVGMatrix without
|
// TODO: Actually all browsers seem to allow setting of a-f in a SVGMatrix without
|
||||||
// throwing an exception - perhaps an update was issued in SVG 1.1 2e?
|
// throwing an exception - perhaps an update was issued in SVG 1.1 2e?
|
||||||
var matrixMultiply = function(m1, m2) {
|
var matrixMultiply = function() {
|
||||||
var a = m1.a*m2.a + m1.c*m2.b,
|
var multi2 = function(m1, m2) {
|
||||||
b = m1.b*m2.a + m1.d*m2.b,
|
var a = m1.a*m2.a + m1.c*m2.b,
|
||||||
c = m1.a*m2.c + m1.c*m2.d,
|
b = m1.b*m2.a + m1.d*m2.b,
|
||||||
d = m1.b*m2.c + m1.d*m2.d,
|
c = m1.a*m2.c + m1.c*m2.d,
|
||||||
e = m1.a*m2.e + m1.c*m2.f + m1.e,
|
d = m1.b*m2.c + m1.d*m2.d,
|
||||||
f = m1.b*m2.e + m1.d*m2.f + m1.f;
|
e = m1.a*m2.e + m1.c*m2.f + m1.e,
|
||||||
|
f = m1.b*m2.e + m1.d*m2.f + m1.f;
|
||||||
// now construct a matrix by analyzing a,b,c,d,e,f and trying to
|
|
||||||
// translate, rotate, and scale the thing into place
|
// now construct a matrix by analyzing a,b,c,d,e,f and trying to
|
||||||
var m = svgroot.createSVGMatrix();
|
// translate, rotate, and scale the thing into place
|
||||||
var sx = 1, sy = 1, angle = 0;
|
var m = svgroot.createSVGMatrix();
|
||||||
|
var sx = 1, sy = 1, angle = 0;
|
||||||
// translate
|
|
||||||
m = m.translate(e,f);
|
// translate
|
||||||
|
m = m.translate(e,f);
|
||||||
// see if there was a rotation
|
|
||||||
var rad = Math.atan2(b,a);
|
// see if there was a rotation
|
||||||
if (rad != 0 && rad != Math.PI && rad != -Math.PI) {
|
var rad = Math.atan2(b,a);
|
||||||
m = m.rotate(180.0 * rad / Math.PI);
|
if (rad != 0 && rad != Math.PI && rad != -Math.PI) {
|
||||||
sx = b / Math.sin(rad);
|
m = m.rotate(180.0 * rad / Math.PI);
|
||||||
sy = -c / Math.sin(rad);
|
sx = b / Math.sin(rad);
|
||||||
}
|
sy = -c / Math.sin(rad);
|
||||||
else {
|
}
|
||||||
sx = a / Math.cos(rad);
|
else {
|
||||||
sy = d / Math.cos(rad);
|
sx = a / Math.cos(rad);
|
||||||
|
sy = d / Math.cos(rad);
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale
|
||||||
|
if (sx != 1 || sy != 1) {
|
||||||
|
m = m.scaleNonUniform(sx,sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle skews?
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale
|
var args = arguments, i = args.length, m = args[i-1];
|
||||||
if (sx != 1 || sy != 1) {
|
|
||||||
m = m.scaleNonUniform(sx,sy);
|
while(i-- > 1) {
|
||||||
|
var m1 = args[i-1];
|
||||||
|
m = multi2(m1, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle skews?
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5472,7 +5479,7 @@ function BatchCommand(text) {
|
||||||
if (oldval == null) oldval = "";
|
if (oldval == null) oldval = "";
|
||||||
if (oldval !== newValue) {
|
if (oldval !== newValue) {
|
||||||
if (attr == "#text") {
|
if (attr == "#text") {
|
||||||
var old_w = elem.getBBox().width;
|
var old_w = canvas.getBBox(elem).width;
|
||||||
elem.textContent = newValue;
|
elem.textContent = newValue;
|
||||||
elem = canvas.quickClone(elem);
|
elem = canvas.quickClone(elem);
|
||||||
|
|
||||||
|
@ -5667,7 +5674,7 @@ function BatchCommand(text) {
|
||||||
// [ gm' ] = [ chm_inv ] [ gm ] [ chm ]
|
// [ gm' ] = [ chm_inv ] [ gm ] [ chm ]
|
||||||
var chm = transformListToTransform(chtlist).matrix,
|
var chm = transformListToTransform(chtlist).matrix,
|
||||||
chm_inv = chm.inverse();
|
chm_inv = chm.inverse();
|
||||||
var gm = matrixMultiply( chm_inv, matrixMultiply( m, chm ) );
|
var gm = matrixMultiply( chm_inv, m, chm );
|
||||||
newxform.setMatrix(gm);
|
newxform.setMatrix(gm);
|
||||||
chtlist.appendItem(newxform);
|
chtlist.appendItem(newxform);
|
||||||
|
|
||||||
|
@ -5779,45 +5786,46 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// Make sure the expected BBox is returned if the element is a group
|
// Make sure the expected BBox is returned if the element is a group
|
||||||
var getCheckedBBox = function(elem) {
|
var getCheckedBBox = function(elem) {
|
||||||
if(elem.tagName == 'g') {
|
try {
|
||||||
return canvas.getStrokedBBox($(elem).children());
|
// TODO: Fix issue with rotated groups. Currently they work
|
||||||
} else {
|
// fine in FF, but not in other browsers (same problem mentioned
|
||||||
try {
|
// in Issue 339 comment #2).
|
||||||
var bb = elem.getBBox();
|
|
||||||
var angle = canvas.getRotationAngle(elem);
|
var bb = elem.getBBox();
|
||||||
if (angle && angle % 90) {
|
var angle = canvas.getRotationAngle(elem);
|
||||||
// Accurate way to get BBox of rotated element in Firefox:
|
if (angle && angle % 90) {
|
||||||
// Put element in group and get its BBox
|
// Accurate way to get BBox of rotated element in Firefox:
|
||||||
|
// Put element in group and get its BBox
|
||||||
var good_bb = false;
|
|
||||||
|
var good_bb = false;
|
||||||
// Get the BBox from the raw path for these elements
|
|
||||||
var elemNames = ['ellipse','path','line','polyline','polygon'];
|
// Get the BBox from the raw path for these elements
|
||||||
if($.inArray(elem.tagName, elemNames) != -1) {
|
var elemNames = ['ellipse','path','line','polyline','polygon'];
|
||||||
|
if($.inArray(elem.tagName, elemNames) != -1) {
|
||||||
|
bb = good_bb = canvas.convertToPath(elem, true, angle);
|
||||||
|
} else if(elem.tagName == 'rect') {
|
||||||
|
// Look for radius
|
||||||
|
var rx = elem.getAttribute('rx');
|
||||||
|
var ry = elem.getAttribute('ry');
|
||||||
|
if(rx || ry) {
|
||||||
bb = good_bb = canvas.convertToPath(elem, true, angle);
|
bb = good_bb = canvas.convertToPath(elem, true, angle);
|
||||||
} else if(elem.tagName == 'rect') {
|
|
||||||
// Look for radius
|
|
||||||
var rx = elem.getAttribute('rx');
|
|
||||||
var ry = elem.getAttribute('ry');
|
|
||||||
if(rx || ry) {
|
|
||||||
bb = good_bb = canvas.convertToPath(elem, true, angle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(!good_bb) {
|
|
||||||
var g = document.createElementNS(svgns, "g");
|
if(!good_bb) {
|
||||||
var parent = elem.parentNode;
|
var g = document.createElementNS(svgns, "g");
|
||||||
parent.replaceChild(g, elem);
|
var parent = elem.parentNode;
|
||||||
g.appendChild(elem);
|
parent.replaceChild(g, elem);
|
||||||
bb = g.getBBox();
|
g.appendChild(elem);
|
||||||
parent.insertBefore(elem,g);
|
bb = g.getBBox();
|
||||||
parent.removeChild(g);
|
parent.insertBefore(elem,g);
|
||||||
}
|
parent.removeChild(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Old method: Works by giving the rotated BBox,
|
// Old method: Works by giving the rotated BBox,
|
||||||
// this is (unfortunately) what Opera and Safari do
|
// this is (unfortunately) what Opera and Safari do
|
||||||
// natively when getting the BBox of the parent group
|
// natively when getting the BBox of the parent group
|
||||||
// var angle = angle * Math.PI / 180.0;
|
// var angle = angle * Math.PI / 180.0;
|
||||||
// var rminx = Number.MAX_VALUE, rminy = Number.MAX_VALUE,
|
// var rminx = Number.MAX_VALUE, rminy = Number.MAX_VALUE,
|
||||||
// rmaxx = Number.MIN_VALUE, rmaxy = Number.MIN_VALUE;
|
// rmaxx = Number.MIN_VALUE, rmaxy = Number.MIN_VALUE;
|
||||||
|
@ -5847,11 +5855,11 @@ function BatchCommand(text) {
|
||||||
// bb.y = rminy;
|
// bb.y = rminy;
|
||||||
// bb.width = rmaxx - rminx;
|
// bb.width = rmaxx - rminx;
|
||||||
// bb.height = rmaxy - rminy;
|
// bb.height = rmaxy - rminy;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bb;
|
return bb;
|
||||||
} catch(e) { return null; }
|
} catch(e) { return null; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var full_bb;
|
var full_bb;
|
||||||
$.each(elems, function() {
|
$.each(elems, function() {
|
||||||
|
|
Loading…
Reference in New Issue