fixtransforms branch: Another attempt to fix transforms on groups/ungrouped elements - mostly broken, still a work-in-progress
git-svn-id: http://svg-edit.googlecode.com/svn/branches/fixtransforms@993 eee81c28-f429-11dd-99c0-75d572ba1dddmaster
parent
dba61fb803
commit
464b1580bf
|
@ -11,6 +11,12 @@
|
||||||
/*
|
/*
|
||||||
TODOs for TransformList:
|
TODOs for TransformList:
|
||||||
|
|
||||||
|
* When ungrouping, always end up with a single [M]
|
||||||
|
* When rotating, always end up with [Rc][M]
|
||||||
|
* When scaling a group, [Rc][M]
|
||||||
|
* When scaling a shape, [Rc]
|
||||||
|
* When moving, always end up with a single [M]
|
||||||
|
|
||||||
* Fix Opera's centering of rotated, resized groups
|
* Fix Opera's centering of rotated, resized groups
|
||||||
* Fix resizing of rotated already-resized groups (scales incorrect with mouse)
|
* Fix resizing of rotated already-resized groups (scales incorrect with mouse)
|
||||||
* Ensure ungrouping works (Issue 204)
|
* Ensure ungrouping works (Issue 204)
|
||||||
|
@ -1417,118 +1423,38 @@ function BatchCommand(text) {
|
||||||
// save the start transform value too
|
// save the start transform value too
|
||||||
initial["transform"] = start_transform ? start_transform : "";
|
initial["transform"] = start_transform ? start_transform : "";
|
||||||
|
|
||||||
// reduce the transform list here...
|
|
||||||
|
|
||||||
// if it's a group, we have special processing to flatten transforms
|
// if it's a group, we have special processing to flatten transforms
|
||||||
if (selected.tagName == "g") {
|
if (selected.tagName == "g") {
|
||||||
|
|
||||||
var angle = 0;
|
|
||||||
var sx = 1, sy = 1;
|
|
||||||
var tx = 0, ty = 0;
|
var tx = 0, ty = 0;
|
||||||
var oldcx = 0, oldcy = 0, newcx = 0, newcy = 0;
|
|
||||||
var opType = 0;
|
|
||||||
|
|
||||||
/*
|
// if we have a translate as the first transform, let's push it down to the children
|
||||||
The current concatenated matrix will be of the form:
|
var xform = tlist.getItem(0);
|
||||||
|
if (xform.type == 2 && (tlist.numberOfItems < 3 || tlist.getItem(1).type != 3)) {
|
||||||
[ T ] [ R,oldc ] [ S ] [ T,s ] [ S,new ] [ - T,s ]
|
var m = xform.matrix;
|
||||||
|
tx = m.e;
|
||||||
which can be simply represented as:
|
ty = m.f;
|
||||||
|
tlist.removeItem(0);
|
||||||
| x' | | a c e | | x |
|
|
||||||
| y' | = | b d f | * | y |
|
|
||||||
| 1 | | 0 0 1 | | 1 |
|
|
||||||
|
|
||||||
where: a = A*cos(r), c = -C*sin(r)
|
|
||||||
b = A*sin(r), d = C*cos(r)
|
|
||||||
e,f are the translation required to recenter and properly scale it.
|
|
||||||
A is the total x scale factor
|
|
||||||
C is the total y scale factor
|
|
||||||
|
|
||||||
We always want to reduce the new transformation matrix to:
|
|
||||||
|
|
||||||
[ R,newc ] [ S ]
|
|
||||||
|
|
||||||
which will be of the form:
|
|
||||||
|
|
||||||
| x' | | a c g | | x + tx |
|
|
||||||
| y' | = | b d h | * | y + ty |
|
|
||||||
| 1 | | 0 0 1 | | 1 |
|
|
||||||
|
|
||||||
where: tx,ty are appropriate translations on the children so that the effect
|
|
||||||
is identical to the original concatenated matrix above
|
|
||||||
g,h are translations to recenter the rotation.
|
|
||||||
|
|
||||||
We can get a, b, c, d, e, f from the actual tlist matrix.
|
|
||||||
We can calculate g,h from the new bounding box.
|
|
||||||
|
|
||||||
Thus, we solve for tx,ty and we get:
|
|
||||||
|
|
||||||
tx = ( (e-g)*cos(r) + (f-h)*sin(r) ) / A
|
|
||||||
ty = ( -(e-g)*sin(r) + (e-g)*cos(r) ) / C
|
|
||||||
*/
|
|
||||||
|
|
||||||
// First, we quickly extract the factors:
|
|
||||||
var N = tlist.numberOfItems;
|
|
||||||
var i = N;
|
|
||||||
while (i--) {
|
|
||||||
var xform = tlist.getItem(i);
|
|
||||||
if (xform.type == 3) {
|
|
||||||
// extract scale factors
|
|
||||||
var sobj = transformToObj(xform);
|
|
||||||
sx *= sobj.sx;
|
|
||||||
sy *= sobj.sy;
|
|
||||||
}
|
|
||||||
else if (xform.type == 4) {
|
|
||||||
var robj = transformToObj(xform);
|
|
||||||
// extract angle and old center
|
|
||||||
angle = robj.angle;
|
|
||||||
oldcx = robj.cx;
|
|
||||||
oldcy = robj.cy;
|
|
||||||
newcx = oldcx;
|
|
||||||
newcy = oldcy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now find the new transformed bbox so we can determine what the
|
// if we have any other transforms, collapse them all down to a matrix
|
||||||
// new center of rotation should be
|
var m = transformListToTransform(tlist).matrix;
|
||||||
var origm = transformListToTransform(tlist).matrix;
|
if (tlist.numberOfItems > 0) {
|
||||||
if (angle != 0) {
|
var newxform = svgroot.createSVGTransform();
|
||||||
var box = canvas.getBBox(selected);
|
newxform.setMatrix(m);
|
||||||
var topleft = transformPoint(box.x,box.y,origm);
|
tlist.clear();
|
||||||
var botright = transformPoint(box.x+box.width,box.y+box.height,origm);
|
tlist.appendItem(newxform);
|
||||||
newcx = topleft.x + (botright.x-topleft.x)/2;
|
|
||||||
newcy = topleft.y + (botright.y-topleft.y)/2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now get e,f and calculate g,h
|
|
||||||
var e = origm.e,
|
|
||||||
f = origm.f;
|
|
||||||
var rad = angle * Math.PI / 180;
|
|
||||||
var g = newcx * (1 - Math.cos(rad)) + newcy * Math.sin(rad);
|
|
||||||
h = newcy * (1 - Math.cos(rad)) - newcx * Math.sin(rad);
|
|
||||||
|
|
||||||
// now actually calculate the new scale factors
|
|
||||||
var tx = ( (e-g)*Math.cos(rad) + (f-h)*Math.sin(rad) ) / sx,
|
|
||||||
ty = ( -(e-g)*Math.sin(rad) + (f-h)*Math.cos(rad) ) / sy;
|
|
||||||
|
|
||||||
// now we can remove all transforms from the list and create our new transforms
|
|
||||||
tlist.clear();
|
|
||||||
|
|
||||||
if (angle) {
|
|
||||||
var rot = svgroot.createSVGTransform();
|
|
||||||
rot.setRotate(angle,newcx,newcy);
|
|
||||||
tlist.appendItem(rot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sx != 1 || sy != 1) {
|
|
||||||
var scale = svgroot.createSVGTransform();
|
|
||||||
scale.setScale(sx,sy);
|
|
||||||
tlist.appendItem(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
// force the accumulated translation down to the children
|
|
||||||
if (tx != 0 || ty != 0) {
|
if (tx != 0 || ty != 0) {
|
||||||
|
var a = m.a, b = m.b, c = m.c, d = m.d;
|
||||||
|
// is it possible for (bc - ad) to equal zero?
|
||||||
|
var denom = b*c - a*d;
|
||||||
|
var ntx = (c*ty - d*tx) / denom,
|
||||||
|
nty = (b*tx - a*ty) / denom;
|
||||||
|
tx = ntx;
|
||||||
|
ty = nty;
|
||||||
|
|
||||||
|
// now push this transform down to the children
|
||||||
// FIXME: unfortunately recalculateDimensions depends on this global variable
|
// FIXME: unfortunately recalculateDimensions depends on this global variable
|
||||||
var old_start_transform = start_transform;
|
var old_start_transform = start_transform;
|
||||||
start_transform = null;
|
start_transform = null;
|
||||||
|
@ -1556,28 +1482,32 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// This pass loop in reverse order and removes any translates or scales.
|
// This pass loop in reverse order and removes any translates or scales.
|
||||||
// Once we hit our first rotate(), we will only remove translates.
|
// Once we hit our first rotate(), we will only remove translates.
|
||||||
var bRemoveTransform = true;
|
|
||||||
n = tlist.numberOfItems;
|
n = tlist.numberOfItems;
|
||||||
|
var m = svgroot.createSVGMatrix(); // identity
|
||||||
while (n--) {
|
while (n--) {
|
||||||
// once we reach an unmoveable transform, we can stop
|
|
||||||
var xform = tlist.getItem(n);
|
var xform = tlist.getItem(n);
|
||||||
var m = xform.matrix;
|
// get the matrix of all transformations to the right of this transform
|
||||||
// if translate...
|
// and its inverse (B and B_inv)
|
||||||
|
var tail = transformListToTransform(tlist, n+1, tlist.numberOfItems-1).matrix,
|
||||||
|
tail_inv = tail.inverse();
|
||||||
|
// multiply (B_inv * A * B)
|
||||||
|
m = matrixMultiply(tail_inv, matrixMultiply(xform.matrix,tail));
|
||||||
|
|
||||||
var remap = null, scalew = null, scaleh = null;
|
var remap = null, scalew = null, scaleh = null;
|
||||||
switch (xform.type) {
|
switch (xform.type) {
|
||||||
|
case 1: // MATRIX - continue
|
||||||
|
continue;
|
||||||
case 2: // TRANSLATE - always remove
|
case 2: // TRANSLATE - always remove
|
||||||
remap = function(x,y) { return transformPoint(x,y,m); };
|
remap = function(x,y) { return transformPoint(x,y,m); };
|
||||||
scalew = function(w) { return w; }
|
scalew = function(w) { return w; }
|
||||||
scaleh = function(h) { return h; }
|
scaleh = function(h) { return h; }
|
||||||
break;
|
break;
|
||||||
case 3: // SCALE - only remove if we haven't hit a rotate
|
case 3: // SCALE - always remove
|
||||||
if (!bRemoveTransform) continue;
|
|
||||||
remap = function(x,y) { return transformPoint(x,y,m); };
|
remap = function(x,y) { return transformPoint(x,y,m); };
|
||||||
scalew = function(w) { return m.a * w; }
|
scalew = function(w) { return m.a * w; }
|
||||||
scaleh = function(h) { return m.d * h; }
|
scaleh = function(h) { return m.d * h; }
|
||||||
break;
|
break;
|
||||||
case 4: // ROTATE - only re-center if we haven't previously hit a rotate
|
case 4: // ROTATE
|
||||||
if (!bRemoveTransform) continue;
|
|
||||||
// if the new center of the shape has moved, then
|
// if the new center of the shape has moved, then
|
||||||
// re-center the rotation, and determine the movement
|
// re-center the rotation, and determine the movement
|
||||||
// offset required to keep the shape in the same place
|
// offset required to keep the shape in the same place
|
||||||
|
@ -1600,8 +1530,6 @@ function BatchCommand(text) {
|
||||||
};
|
};
|
||||||
scalew = function(w) { return w; }
|
scalew = function(w) { return w; }
|
||||||
scaleh = function(h) { return h; }
|
scaleh = function(h) { return h; }
|
||||||
// this latches to false once we hit our first rotate transform
|
|
||||||
bRemoveTransform = false;
|
|
||||||
var newrot = svgroot.createSVGTransform();
|
var newrot = svgroot.createSVGTransform();
|
||||||
newrot.setRotate(xform.angle, cx, cy);
|
newrot.setRotate(xform.angle, cx, cy);
|
||||||
tlist.replaceItem(newrot, n);
|
tlist.replaceItem(newrot, n);
|
||||||
|
@ -1610,6 +1538,7 @@ function BatchCommand(text) {
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remap) continue;
|
if (!remap) continue;
|
||||||
|
|
||||||
newcenter = remap(box.x+box.width/2, box.y+box.height/2);
|
newcenter = remap(box.x+box.width/2, box.y+box.height/2);
|
||||||
|
@ -1706,23 +1635,10 @@ function BatchCommand(text) {
|
||||||
break;
|
break;
|
||||||
} // switch on element type to get initial values
|
} // switch on element type to get initial values
|
||||||
|
|
||||||
// we have eliminated the transform, so remove it from the list
|
// if it wasn't a rotate, we have eliminated the transform, so remove it
|
||||||
if (bRemoveTransform) {
|
if (xform.type != 4) {
|
||||||
tlist.removeItem(n);
|
tlist.removeItem(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now loop through the other transforms and adjust accordingly
|
|
||||||
for ( var j = n; j < tlist.numberOfItems; ++j) {
|
|
||||||
var changed_xform = tlist.getItem(j);
|
|
||||||
switch (changed_xform.type) {
|
|
||||||
// TODO: TRANSLATE, SCALE?
|
|
||||||
case 4: // rotate
|
|
||||||
var newrot = svgroot.createSVGTransform();
|
|
||||||
newrot.setRotate(changed_xform.angle, newcenter.x, newcenter.y);
|
|
||||||
tlist.replaceItem(newrot, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // looping for each transform
|
} // looping for each transform
|
||||||
} // a non-group
|
} // a non-group
|
||||||
|
|
||||||
|
@ -2010,13 +1926,21 @@ function BatchCommand(text) {
|
||||||
// This returns a single matrix Transform for a given Transform List
|
// This returns a single matrix Transform for a given Transform List
|
||||||
// (this is the equivalent of SVGTransformList.consolidate() but unlike
|
// (this is the equivalent of SVGTransformList.consolidate() but unlike
|
||||||
// that method, this one does not modify the actual SVGTransformList)
|
// that method, this one does not modify the actual SVGTransformList)
|
||||||
|
// This function is very liberal with its min,max arguments
|
||||||
var transformListToTransform = function(tlist, min, max) {
|
var transformListToTransform = function(tlist, min, max) {
|
||||||
if (min > max) { throw "min>max"; }
|
|
||||||
var min = min || 0;
|
var min = min || 0;
|
||||||
var max = max || tlist.numberOfItems;
|
var max = max || (tlist.numberOfItems-1);
|
||||||
|
min = parseInt(min);
|
||||||
|
max = parseInt(max);
|
||||||
|
if (min > max) { var temp = max; max = min; min = temp; }
|
||||||
|
|
||||||
var m = svgroot.createSVGMatrix();
|
var m = svgroot.createSVGMatrix();
|
||||||
for (var i = min; i < max; ++i) {
|
for (var i = min; i <= max; ++i) {
|
||||||
m = matrixMultiply(m, tlist.getItem(i).matrix);
|
// if our indices are out of range, just use a harmless identity matrix
|
||||||
|
var mtom = (i >= 0 && i < tlist.numberOfItems ?
|
||||||
|
tlist.getItem(i).matrix :
|
||||||
|
svgroot.createSVGMatrix());
|
||||||
|
m = matrixMultiply(m, mtom);
|
||||||
}
|
}
|
||||||
return svgroot.createSVGTransformFromMatrix(m);
|
return svgroot.createSVGTransformFromMatrix(m);
|
||||||
};
|
};
|
||||||
|
@ -2395,6 +2319,8 @@ function BatchCommand(text) {
|
||||||
break;
|
break;
|
||||||
case "rotate":
|
case "rotate":
|
||||||
started = true;
|
started = true;
|
||||||
|
// append a dummy transform that will be used as the rotate
|
||||||
|
tlist.appendItem(svgroot.createSVGTransform());
|
||||||
// we are starting an undoable change (a drag-rotation)
|
// we are starting an undoable change (a drag-rotation)
|
||||||
canvas.beginUndoableChange("transform", selectedElements);
|
canvas.beginUndoableChange("transform", selectedElements);
|
||||||
break;
|
break;
|
||||||
|
@ -5125,21 +5051,31 @@ function BatchCommand(text) {
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: do we need to sum up all rotation angles?
|
// we get the rotation angle in the tlist
|
||||||
this.getRotationAngle = function(elem, to_rad) {
|
this.getRotationAngle = function(elem, to_rad) {
|
||||||
var selected = elem || selectedElements[0];
|
var selected = elem || selectedElements[0];
|
||||||
// find the rotation transform (if any) and set it
|
// find the rotation transform (if any) and set it
|
||||||
var tlist = canvas.getTransformList(selected);
|
var tlist = canvas.getTransformList(selected);
|
||||||
var t = tlist.numberOfItems;
|
var t = tlist.numberOfItems;
|
||||||
|
var sangle = 0;
|
||||||
while (t--) {
|
while (t--) {
|
||||||
var xform = tlist.getItem(t);
|
var xform = tlist.getItem(t);
|
||||||
|
// rotation transform
|
||||||
if (xform.type == 4) {
|
if (xform.type == 4) {
|
||||||
return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle;
|
sangle += tlist.getItem(t).angle;
|
||||||
}
|
}
|
||||||
|
// matrix transform
|
||||||
|
// else if (xform.type == 1) {
|
||||||
|
// var m = xform.matrix;
|
||||||
|
// sangle += Math.atan2(m.b,m.a) * 180.0 / Math.PI;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
return 0;
|
return to_rad ? sangle * Math.PI / 180.0 : sangle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// this should:
|
||||||
|
// - remove any old rotations if present
|
||||||
|
// - prepend a new rotation at the transformed center
|
||||||
this.setRotationAngle = function(val,preventUndo) {
|
this.setRotationAngle = function(val,preventUndo) {
|
||||||
// ensure val is the proper type
|
// ensure val is the proper type
|
||||||
val = parseFloat(val);
|
val = parseFloat(val);
|
||||||
|
@ -5148,24 +5084,22 @@ function BatchCommand(text) {
|
||||||
var bbox = elem.getBBox();
|
var bbox = elem.getBBox();
|
||||||
var cx = round(bbox.x+bbox.width/2), cy = round(bbox.y+bbox.height/2);
|
var cx = round(bbox.x+bbox.width/2), cy = round(bbox.y+bbox.height/2);
|
||||||
var tlist = canvas.getTransformList(elem);
|
var tlist = canvas.getTransformList(elem);
|
||||||
var rotIndex = 0;
|
|
||||||
// find the index of the rotation transform
|
// remove the rotation transform
|
||||||
var n = tlist.numberOfItems;
|
var n = tlist.numberOfItems;
|
||||||
while (n--) {
|
while (n--) {
|
||||||
var xform = tlist.getItem(n);
|
if (tlist.getItem(n).type == 4) {
|
||||||
if (xform.type == 4) {
|
|
||||||
rotIndex = n;
|
|
||||||
// TODO: get the rotational center here?
|
|
||||||
tlist.removeItem(n);
|
tlist.removeItem(n);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we are not rotated yet, insert a dummy xform
|
|
||||||
var m = transformListToTransform(tlist).matrix;
|
// find R_nc and insert it
|
||||||
var center = transformPoint(cx,cy,m);
|
var center = transformPoint(cx,cy,transformListToTransform(tlist).matrix);
|
||||||
var newrot = svgroot.createSVGTransform();
|
var R_nc = svgroot.createSVGTransform();
|
||||||
newrot.setRotate(val, center.x, center.y);
|
R_nc.setRotate(val, center.x, center.y);
|
||||||
tlist.insertItemBefore(newrot, rotIndex);
|
|
||||||
|
tlist.insertItemBefore(R_nc,0);
|
||||||
|
|
||||||
if (!preventUndo) {
|
if (!preventUndo) {
|
||||||
// we need to undo it, then redo it so it can be undo-able! :)
|
// we need to undo it, then redo it so it can be undo-able! :)
|
||||||
// TODO: figure out how to make changes to transform list undo-able cross-browser?
|
// TODO: figure out how to make changes to transform list undo-able cross-browser?
|
||||||
|
@ -5564,8 +5498,6 @@ function BatchCommand(text) {
|
||||||
canvas.addToSelection([g], true);
|
canvas.addToSelection([g], true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: when transferring group's rotational transform to the children, must deal
|
|
||||||
// with children who are already rotated within the group (Issue 204)
|
|
||||||
this.ungroupSelectedElement = function() {
|
this.ungroupSelectedElement = function() {
|
||||||
var g = selectedElements[0];
|
var g = selectedElements[0];
|
||||||
if (g.tagName == "g") {
|
if (g.tagName == "g") {
|
||||||
|
@ -5574,6 +5506,7 @@ function BatchCommand(text) {
|
||||||
var anchor = g.previousSibling;
|
var anchor = g.previousSibling;
|
||||||
var children = new Array(g.childNodes.length);
|
var children = new Array(g.childNodes.length);
|
||||||
var xform = g.getAttribute("transform");
|
var xform = g.getAttribute("transform");
|
||||||
|
// get consolidated matrix
|
||||||
var m = transformListToTransform(canvas.getTransformList(g)).matrix;
|
var m = transformListToTransform(canvas.getTransformList(g)).matrix;
|
||||||
|
|
||||||
// TODO: get all fill/stroke properties from the group that we are about to destroy
|
// TODO: get all fill/stroke properties from the group that we are about to destroy
|
||||||
|
@ -5585,43 +5518,25 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// TODO: get the group's opacity and propagate it down to the children (multiply it
|
// TODO: get the group's opacity and propagate it down to the children (multiply it
|
||||||
// by the child's opacity (or 1.0)
|
// by the child's opacity (or 1.0)
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var gbox = g.getBBox(),
|
|
||||||
gx = gbox.x + gbox.width/2,
|
|
||||||
gy = gbox.y + gbox.height/2;
|
|
||||||
var gangle = canvas.getRotationAngle(g, true);
|
|
||||||
while (g.firstChild) {
|
while (g.firstChild) {
|
||||||
var elem = g.firstChild;
|
var elem = g.firstChild;
|
||||||
var oldNextSibling = elem.nextSibling;
|
var oldNextSibling = elem.nextSibling;
|
||||||
var oldParent = elem.parentNode;
|
var oldParent = elem.parentNode;
|
||||||
children[i++] = elem = parent.insertBefore(elem, anchor);
|
children[i++] = elem = parent.insertBefore(elem, anchor);
|
||||||
batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
|
batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
|
||||||
|
|
||||||
|
// transfer the group's transform down to each child and then
|
||||||
|
// call recalculateDimensions()
|
||||||
if (xform) {
|
if (xform) {
|
||||||
var childBox = elem.getBBox();
|
var oldxform = elem.getAttribute("transform");
|
||||||
var cx = childBox.x + childBox.width/2,
|
|
||||||
cy = childBox.y + childBox.height/2,
|
|
||||||
dx = cx - gx,
|
|
||||||
dy = cy - gy,
|
|
||||||
r = Math.sqrt(dx*dx + dy*dy);
|
|
||||||
var tangle = gangle + Math.atan2(dy,dx);
|
|
||||||
var newcx = r * Math.cos(tangle) + gx,
|
|
||||||
newcy = r * Math.sin(tangle) + gy;
|
|
||||||
childBox.x += (newcx - cx);
|
|
||||||
childBox.y += (newcy - cy);
|
|
||||||
// now we add the angle that the element was rotated by
|
|
||||||
// if it's non-zero, we need to set the new transform
|
|
||||||
// otherwise, we clear it
|
|
||||||
var angle = gangle + canvas.getRotationAngle(elem, true);
|
|
||||||
var changes = {};
|
var changes = {};
|
||||||
changes["transform"] = elem.getAttribute("transform");
|
changes["transform"] = oldxform ? oldxform : "";
|
||||||
if (angle != 0) {
|
|
||||||
elem.setAttribute("transform", "rotate(" + (angle*180.0)/Math.PI + " " + cx + "," + cy + ")");
|
var newxform = svgroot.createSVGTransform();
|
||||||
}
|
var chtlist = canvas.getTransformList(elem);
|
||||||
else {
|
newxform.setMatrix(matrixMultiply(m,transformListToTransform(chtlist).matrix.inverse()));
|
||||||
elem.setAttribute("transform", "");
|
chtlist.insertItemBefore(newxform,0);
|
||||||
}
|
|
||||||
batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));
|
|
||||||
batchCmd.addSubCommand(recalculateDimensions(elem));
|
batchCmd.addSubCommand(recalculateDimensions(elem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue