Fix SVG-Edit code for rotating objects

A little math goes a long way ...

Also pick up some updates from SVG-Edit trunk.
This commit is contained in:
Jacques Distler 2010-02-10 15:41:47 -06:00
parent 1d8318cfd2
commit 9047e5d460
3 changed files with 76 additions and 40 deletions

View file

@ -1,4 +1,4 @@
body { body {
background: #E8E8E8; background: #E8E8E8;
} }
@ -722,6 +722,11 @@ span.zoom_tool {
z-index: 20001; z-index: 20001;
} }
#svg_docprops .error {
border: 1px solid red;
padding: 3px;
}
#svg_docprops #resolution { #svg_docprops #resolution {
max-width: 14em; max-width: 14em;
} }

View file

@ -1513,7 +1513,6 @@ function svg_edit_setup() {
$('#image_save_opts input').val([curPrefs.img_save]); $('#image_save_opts input').val([curPrefs.img_save]);
// update resolution option with actual resolution // update resolution option with actual resolution
// TODO: what if SVG source is changed?
var res = svgCanvas.getResolution(); var res = svgCanvas.getResolution();
$('#canvas_width').val(res.w); $('#canvas_width').val(res.w);
$('#canvas_height').val(res.h); $('#canvas_height').val(res.h);
@ -1580,12 +1579,26 @@ function svg_edit_setup() {
svgCanvas.setImageTitle(new_title); svgCanvas.setImageTitle(new_title);
// update resolution // update resolution
var x = parseInt($('#canvas_width').val()); var width = $('#canvas_width'), w = width.val();
var y = parseInt($('#canvas_height').val()); var height = $('#canvas_height'), h = height.val();
if(isNaN(x) || isNaN(y)) {
x ='fit'; if(w != "fit" && !svgCanvas.isValidUnit('width', w)) {
$.alert(uiStrings.invalidAttrValGiven);
width.parent().addClass('error');
return false;
} }
if(!svgCanvas.setResolution(x,y)) {
width.parent().removeClass('error');
if(h != "fit" && !svgCanvas.isValidUnit('height', h)) {
$.alert(uiStrings.invalidAttrValGiven);
height.parent().addClass('error');
return false;
}
height.parent().removeClass('error');
if(!svgCanvas.setResolution(w, h)) {
$.alert(uiStrings.noContentToFitTo); $.alert(uiStrings.noContentToFitTo);
return false; return false;
} }
@ -2705,7 +2718,7 @@ function svg_edit_setup() {
updateCanvas(true); updateCanvas(true);
}); });
// var revnums = "svg-editor.js ($Rev: 1367 $) "; // var revnums = "svg-editor.js ($Rev: 1372 $) ";
// revnums += svgCanvas.getVersion(); // revnums += svgCanvas.getVersion();
// $('#copyright')[0].setAttribute("title", revnums); // $('#copyright')[0].setAttribute("title", revnums);
return svgCanvas; return svgCanvas;

View file

@ -87,8 +87,6 @@ function SvgCanvas(container)
var isOpera = !!window.opera, var isOpera = !!window.opera,
isWebkit = navigator.userAgent.indexOf("AppleWebKit") != -1, isWebkit = navigator.userAgent.indexOf("AppleWebKit") != -1,
support = {}, support = {},
htmlns = "http://www.w3.org/1999/xhtml",
mathns = "http://www.w3.org/1998/Math/MathML",
// this defines which elements and attributes that we support // this defines which elements and attributes that we support
svgWhiteList = { svgWhiteList = {
@ -671,8 +669,10 @@ function BatchCommand(text) {
'height': 480, 'height': 480,
'x': 0, 'x': 0,
'y': 0, 'y': 0,
'overflow': 'visible',
'style': 'pointer-events:none' 'style': 'pointer-events:none'
}); });
var rect = svgdoc.createElementNS(svgns, "rect"); var rect = svgdoc.createElementNS(svgns, "rect");
assignAttributes(rect, { assignAttributes(rect, {
'width': '100%', 'width': '100%',
@ -684,6 +684,7 @@ function BatchCommand(text) {
'fill': '#FFF', 'fill': '#FFF',
'style': 'pointer-events:none' 'style': 'pointer-events:none'
}); });
if (!window.opera) rect.setAttribute('filter', 'url(#canvashadow)');
canvasbg.appendChild(rect); canvasbg.appendChild(rect);
svgroot.insertBefore(canvasbg, svgcontent); svgroot.insertBefore(canvasbg, svgcontent);
}; };
@ -917,17 +918,25 @@ function BatchCommand(text) {
xlinkns = "http://www.w3.org/1999/xlink", xlinkns = "http://www.w3.org/1999/xlink",
xmlns = "http://www.w3.org/XML/1998/namespace", xmlns = "http://www.w3.org/XML/1998/namespace",
se_ns = "http://svg-edit.googlecode.com", se_ns = "http://svg-edit.googlecode.com",
htmlns = "http://www.w3.org/1999/xhtml",
mathns = "http://www.w3.org/1998/Math/MathML",
idprefix = "svg_", idprefix = "svg_",
svgdoc = container.ownerDocument, svgdoc = container.ownerDocument,
svgroot = svgdoc.createElementNS(svgns, "svg"); svgroot = svgdoc.importNode(Utils.text2xml('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
'width="640" height="480" x="640" y="480" overflow="visible">' +
'<defs>' +
'<filter id="canvashadow" filterUnits="objectBoundingBox">' +
'<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>'+
'<feOffset in="blur" dx="5" dy="5" result="offsetBlur"/>'+
'<feMerge>'+
'<feMergeNode in="offsetBlur"/>'+
'<feMergeNode in="SourceGraphic"/>'+
'</feMerge>'+
'</filter>'+
'</defs>'+
'</svg>').documentElement, true);
$(svgroot).attr({ $(svgroot).appendTo(container);
width: 640,
height: 480,
id: "svgroot",
xmlns: svgns,
"xmlns:xlink": xlinkns
}).appendTo(container);
var svgcontent = svgdoc.createElementNS(svgns, "svg"); var svgcontent = svgdoc.createElementNS(svgns, "svg");
$(svgcontent).attr({ $(svgcontent).attr({
@ -1985,15 +1994,20 @@ function BatchCommand(text) {
// temporarily strip off the rotate and save the old center // temporarily strip off the rotate and save the old center
var gangle = canvas.getRotationAngle(selected); var gangle = canvas.getRotationAngle(selected);
if (gangle) { if (gangle) {
var a = gangle * Math.PI / 180;
if ( Math.abs(a) > (1.0e-10) ) {
var s = Math.sin(a)/(1 - Math.cos(a));
} else {
// FIXME: This blows up if the angle is exactly 0!
var s = 2/a;
}
for (var i = 0; i < tlist.numberOfItems; ++i) { for (var i = 0; i < tlist.numberOfItems; ++i) {
var xform = tlist.getItem(i); var xform = tlist.getItem(i);
if (xform.type == 4) { if (xform.type == 4) {
// extract old center through mystical arts // extract old center through mystical arts
var rm = xform.matrix; var rm = xform.matrix;
var a = gangle * Math.PI / 180; oldcenter.y = (s*rm.e + rm.f)/2;
// FIXME: This blows up if the angle is exactly 0 or 180 degrees! oldcenter.x = (rm.e - s*rm.f)/2;
oldcenter.y = 0.5 * (Math.sin(a)*rm.e + (1-Math.cos(a))*rm.f) / (1 - Math.cos(a));
oldcenter.x = ((1 - Math.cos(a)) * oldcenter.y - rm.f) / Math.sin(a);
tlist.removeItem(i); tlist.removeItem(i);
break; break;
} }
@ -5528,32 +5542,33 @@ function BatchCommand(text) {
canvas.fixOperaXML(svgcontent, newDoc.documentElement); canvas.fixOperaXML(svgcontent, newDoc.documentElement);
} }
svgcontent.id= 'svgcontent'; var content = $(svgcontent);
// determine proper size // determine proper size
var w, h; var w, h;
if (svgcontent.getAttribute("viewBox")) { if (content.attr("viewBox")) {
var vb = svgcontent.getAttribute("viewBox").split(' '); var vb = content.attr("viewBox").split(' ');
w = vb[2]; w = vb[2];
h = vb[3]; h = vb[3];
} }
// handle old content that doesn't have a viewBox // handle content that doesn't have a viewBox
else { else {
w = svgcontent.getAttribute("width"); var dims = content.attr(["width", "height"]);
h = svgcontent.getAttribute("height"); w = convertToNum('width', dims.width);
h = convertToNum('height', dims.height);
// svgcontent.setAttribute("viewBox", ["0", "0", w, h].join(" ")); // svgcontent.setAttribute("viewBox", ["0", "0", w, h].join(" "));
} }
svgcontent.setAttribute('width', w); content.attr({
svgcontent.setAttribute('height', h); id: 'svgcontent',
svgcontent.setAttribute('overflow', 'visible'); width: w,
height: h,
overflow: 'visible'
});
batchCmd.addSubCommand(new InsertElementCommand(svgcontent)); batchCmd.addSubCommand(new InsertElementCommand(svgcontent));
// update root to the correct size // update root to the correct size
var changes = {}; var changes = content.attr(["width", "height"]);
changes['width'] = svgcontent.getAttribute('width');
changes['height'] = svgcontent.getAttribute('height');
// svgroot.setAttribute('width', w);
// svgroot.setAttribute('height', h);
batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes)); batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes));
// reset zoom // reset zoom
@ -6104,6 +6119,9 @@ function BatchCommand(text) {
if(!batchCmd) { if(!batchCmd) {
batchCmd = new BatchCommand("Change Image Dimensions"); batchCmd = new BatchCommand("Change Image Dimensions");
} }
x = convertToNum('width', x);
y = convertToNum('height', y);
svgcontent.setAttribute('width', x); svgcontent.setAttribute('width', x);
svgcontent.setAttribute('height', y); svgcontent.setAttribute('height', y);
batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {"width":w, "height":h})); batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {"width":w, "height":h}));
@ -7631,7 +7649,7 @@ function BatchCommand(text) {
// Function: getVersion // Function: getVersion
// Returns a string which describes the revision number of SvgCanvas. // Returns a string which describes the revision number of SvgCanvas.
this.getVersion = function() { this.getVersion = function() {
return "svgcanvas.js ($Rev: 1369 $)"; return "svgcanvas.js ($Rev: 1375 $)";
}; };
this.setUiStrings = function(strs) { this.setUiStrings = function(strs) {