Sync with latest SVG-Edit
This commit is contained in:
parent
3fbff19997
commit
a1654f1e99
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg width="205.5" xmlns="http://www.w3.org/2000/svg" height="255.87">
|
<svg width="100" xmlns="http://www.w3.org/2000/svg" height="100" viewBox="0 0 205.5 255.87">
|
||||||
<g display="inline">
|
<g display="inline">
|
||||||
<title>Layer 1</title>
|
<title>Layer 1</title>
|
||||||
<path id="svg_1" d="m10.671,231.42c89.543,56.086,188.11-10.029,193.33-94.559-1.7286-101.53-92.171-150.4-160.16-128.01,35.129,15.844,73.4,62.729,73.871,88.013-3.4428,7.5157-5.8714,16.373,1.5286,18.844-2,12.857-18.486,33.571-21.043,40.643-2.5571,7.0714,2.2143,9.8443,5.4429,10.357,0.2,6.0586-4.4429,8.3572-5.3572,12.156-7.9,3.13-8.4714,9.9872-7.3286,14.844-19.714,18.571-20.571,27.143-80.286,37.714z" stroke="#000" stroke-width="5" fill="#f6c700"/>
|
<path id="svg_1" d="m10.671,231.42c89.543,56.086,188.11-10.029,193.33-94.559-1.7286-101.53-92.171-150.4-160.16-128.01,35.129,15.844,73.4,62.729,73.871,88.013-3.4428,7.5157-5.8714,16.373,1.5286,18.844-2,12.857-18.486,33.571-21.043,40.643-2.5571,7.0714,2.2143,9.8443,5.4429,10.357,0.2,6.0586-4.4429,8.3572-5.3572,12.156-7.9,3.13-8.4714,9.9872-7.3286,14.844-19.714,18.571-20.571,27.143-80.286,37.714z" stroke="#000" stroke-width="5" fill="#f6c700"/>
|
||||||
|
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100">
|
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100">
|
||||||
<path stroke-linejoin="round" d="M36.536,32.822c12.699-31.856,13.17-31.734,26.356-1.061,34.15,2.198,39.388,9.622,6.513,23.932,19.821,46.047-0.792,28.383-19.842,13.178-22.358,25.013-29.541,22.639-18.782-12.118-7.282-8.501-45.095-18.741,5.755-23.931z" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-miterlimit="4" stroke-width="5" fill="#FF0"/>
|
<path id="svg_1" stroke-linejoin="round" d="M36.536,32.822c12.699-31.856,13.17-31.734,26.356-1.061,34.15,2.198,39.388,9.622,6.513,23.932,19.821,46.047-0.792,28.383-19.842,13.178-22.358,25.013-29.541,22.639-18.782-12.118-7.282-8.501-45.095-18.741,5.755-23.931z" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-miterlimit="4" stroke-width="5" fill="#FF0"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 489 B After Width: | Height: | Size: 500 B |
|
@ -1460,7 +1460,6 @@ function svg_edit_setup() {
|
||||||
svgCanvas.open();
|
svgCanvas.open();
|
||||||
};
|
};
|
||||||
var clickImport = function(){
|
var clickImport = function(){
|
||||||
svgCanvas.import();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var clickUndo = function(){
|
var clickUndo = function(){
|
||||||
|
@ -2780,7 +2779,7 @@ function svg_edit_setup() {
|
||||||
updateCanvas(true);
|
updateCanvas(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// var revnums = "svg-editor.js ($Rev: 1421 $) ";
|
// var revnums = "svg-editor.js ($Rev: 1423 $) ";
|
||||||
// revnums += svgCanvas.getVersion();
|
// revnums += svgCanvas.getVersion();
|
||||||
// $('#copyright')[0].setAttribute("title", revnums);
|
// $('#copyright')[0].setAttribute("title", revnums);
|
||||||
return svgCanvas;
|
return svgCanvas;
|
||||||
|
|
|
@ -1393,7 +1393,7 @@ function BatchCommand(text) {
|
||||||
}
|
}
|
||||||
// if the element has attributes pointing to a non-local reference,
|
// if the element has attributes pointing to a non-local reference,
|
||||||
// need to remove the attribute
|
// need to remove the attribute
|
||||||
$.each(["clip-path", "fill", "marker-end", "marker-mid", "marker-start", "mask", "stroke"],function(i,attr) {
|
$.each(["clip-path", "fill", "filter", "marker-end", "marker-mid", "marker-start", "mask", "stroke"],function(i,attr) {
|
||||||
var val = node.getAttribute(attr);
|
var val = node.getAttribute(attr);
|
||||||
if (val) {
|
if (val) {
|
||||||
val = getUrlFromAttr(val);
|
val = getUrlFromAttr(val);
|
||||||
|
@ -2164,6 +2164,8 @@ function BatchCommand(text) {
|
||||||
start_transform = child.getAttribute("transform");
|
start_transform = child.getAttribute("transform");
|
||||||
|
|
||||||
var childTlist = canvas.getTransformList(child);
|
var childTlist = canvas.getTransformList(child);
|
||||||
|
// some children might not have a transform (<metadata>, <defs>, etc)
|
||||||
|
if (childTlist) {
|
||||||
var newxlate = svgroot.createSVGTransform();
|
var newxlate = svgroot.createSVGTransform();
|
||||||
newxlate.setTranslate(tx,ty);
|
newxlate.setTranslate(tx,ty);
|
||||||
childTlist.insertItemBefore(newxlate, 0);
|
childTlist.insertItemBefore(newxlate, 0);
|
||||||
|
@ -2171,6 +2173,7 @@ function BatchCommand(text) {
|
||||||
start_transform = old_start_transform;
|
start_transform = old_start_transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
start_transform = old_start_transform;
|
start_transform = old_start_transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2263,6 +2266,7 @@ function BatchCommand(text) {
|
||||||
}
|
}
|
||||||
// else, it's a non-group
|
// else, it's a non-group
|
||||||
else {
|
else {
|
||||||
|
// FIXME: box might be null for some elements (<metadata> etc), need to handle this
|
||||||
var box = canvas.getBBox(selected),
|
var box = canvas.getBBox(selected),
|
||||||
oldcenter = {x: box.x+box.width/2, y: box.y+box.height/2},
|
oldcenter = {x: box.x+box.width/2, y: box.y+box.height/2},
|
||||||
newcenter = transformPoint(box.x+box.width/2, box.y+box.height/2,
|
newcenter = transformPoint(box.x+box.width/2, box.y+box.height/2,
|
||||||
|
@ -2706,7 +2710,6 @@ function BatchCommand(text) {
|
||||||
}
|
}
|
||||||
tobj.text = "rotate(" + xform.angle + " " + tobj.cx*z + "," + tobj.cy*z + ")";
|
tobj.text = "rotate(" + xform.angle + " " + tobj.cx*z + "," + tobj.cy*z + ")";
|
||||||
break;
|
break;
|
||||||
// TODO: matrix, skewX, skewY
|
|
||||||
}
|
}
|
||||||
return tobj;
|
return tobj;
|
||||||
};
|
};
|
||||||
|
@ -4484,7 +4487,7 @@ function BatchCommand(text) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make sure current_path isn't null at this point
|
// Make sure current_path isn't null at this point
|
||||||
if(!current_path) return;
|
if(!current_path) return;
|
||||||
|
|
||||||
current_path_oldd = getD();
|
current_path_oldd = getD();
|
||||||
|
@ -5023,7 +5026,7 @@ function BatchCommand(text) {
|
||||||
current_path_pts.splice(pt*2 + 2, 0, abs_x, abs_y);
|
current_path_pts.splice(pt*2 + 2, 0, abs_x, abs_y);
|
||||||
|
|
||||||
// TODO: This should select the new path points but breaks
|
// TODO: This should select the new path points but breaks
|
||||||
// when doing several times seleting many nodes
|
// when doing several times selecting many nodes
|
||||||
nums.push(pt + i);
|
nums.push(pt + i);
|
||||||
nums.push(pt + i + 1);
|
nums.push(pt + i + 1);
|
||||||
}
|
}
|
||||||
|
@ -5525,9 +5528,6 @@ function BatchCommand(text) {
|
||||||
this.open = function() {
|
this.open = function() {
|
||||||
// Nothing by default, handled by optional widget/extension
|
// Nothing by default, handled by optional widget/extension
|
||||||
};
|
};
|
||||||
this.import = function() {
|
|
||||||
// Nothing by default, handled by optional widget/extension
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function: save
|
// Function: save
|
||||||
// Serializes the current drawing into SVG XML text and returns it to the 'saved' handler.
|
// Serializes the current drawing into SVG XML text and returns it to the 'saved' handler.
|
||||||
|
@ -5548,6 +5548,7 @@ function BatchCommand(text) {
|
||||||
call("saved", str);
|
call("saved", str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Walks the tree and executes the callback on each element in a top-down fashion
|
||||||
var walkTree = function(elem, cbFn){
|
var walkTree = function(elem, cbFn){
|
||||||
if (elem && elem.nodeType == 1) {
|
if (elem && elem.nodeType == 1) {
|
||||||
cbFn(elem);
|
cbFn(elem);
|
||||||
|
@ -5557,6 +5558,16 @@ function BatchCommand(text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// Walks the tree and executes the callback on each element in a depth-first fashion
|
||||||
|
var walkTreePost = function(elem, cbFn) {
|
||||||
|
if (elem && elem.nodeType == 1) {
|
||||||
|
var i = elem.childNodes.length;
|
||||||
|
while (i--) {
|
||||||
|
walkTree(elem.childNodes.item(i), cbFn);
|
||||||
|
}
|
||||||
|
cbFn(elem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Function: getSvgString
|
// Function: getSvgString
|
||||||
// Returns the current drawing as raw SVG XML text.
|
// Returns the current drawing as raw SVG XML text.
|
||||||
|
@ -5617,17 +5628,7 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// recalculate dimensions on the top-level children so that unnecessary transforms
|
// recalculate dimensions on the top-level children so that unnecessary transforms
|
||||||
// are removed
|
// are removed
|
||||||
var deepdive = function(node) {
|
walkTreePost(svgcontent, function(n){try{recalculateDimensions(n)}catch(e){console.log(e)}});
|
||||||
if (node.nodeType == 1) {
|
|
||||||
var children = node.childNodes;
|
|
||||||
var i = children.length;
|
|
||||||
while (i--) { deepdive(children.item(i)); }
|
|
||||||
try {
|
|
||||||
recalculateDimensions(node);
|
|
||||||
} catch(e) { console.log(e); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deepdive(svgcontent);
|
|
||||||
|
|
||||||
var content = $(svgcontent);
|
var content = $(svgcontent);
|
||||||
|
|
||||||
|
@ -5693,8 +5694,8 @@ function BatchCommand(text) {
|
||||||
// Returns:
|
// Returns:
|
||||||
// This function returns false if the import was unsuccessful, true otherwise.
|
// This function returns false if the import was unsuccessful, true otherwise.
|
||||||
|
|
||||||
|
// TODO: import should happen in top-left of current zoomed viewport
|
||||||
// TODO: create a new layer for the imported SVG
|
// TODO: create a new layer for the imported SVG
|
||||||
// TODO: properly size the new group
|
|
||||||
this.importSvgString = function(xmlString) {
|
this.importSvgString = function(xmlString) {
|
||||||
try {
|
try {
|
||||||
// convert string into XML document
|
// convert string into XML document
|
||||||
|
@ -5708,9 +5709,120 @@ function BatchCommand(text) {
|
||||||
var importedNode = svgdoc.importNode(newDoc.documentElement, true);
|
var importedNode = svgdoc.importNode(newDoc.documentElement, true);
|
||||||
|
|
||||||
if (current_layer) {
|
if (current_layer) {
|
||||||
|
// TODO: properly handle if width/height are not specified or if in percentages
|
||||||
|
// TODO: properly handle if width/height are in units (px, etc)
|
||||||
|
var innerw = importedNode.getAttribute("width"),
|
||||||
|
innerh = importedNode.getAttribute("height"),
|
||||||
|
innervb = importedNode.getAttribute("viewBox"),
|
||||||
|
// if no explicit viewbox, create one out of the width and height
|
||||||
|
vb = innervb ? innervb.split(" ") : [0,0,innerw,innerh];
|
||||||
|
for (var j = 0; j < 4; ++j)
|
||||||
|
vb[j] = Number(vb[j]);
|
||||||
|
|
||||||
|
// TODO: properly handle preserveAspectRatio
|
||||||
|
var canvasw = Number(svgcontent.getAttribute("width")),
|
||||||
|
canvash = Number(svgcontent.getAttribute("height"));
|
||||||
|
// imported content should be 1/3 of the canvas on its largest dimension
|
||||||
|
if (innerh > innerw) {
|
||||||
|
var ts = "scale(" + (canvash/3)/vb[3] + ")";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var ts = "scale(" + (canvash/3)/vb[2] + ")";
|
||||||
|
}
|
||||||
|
if (vb[0] != 0 || vb[1] != 0)
|
||||||
|
ts = "translate(" + (-vb[0]) + "," + (-vb[1]) + ") " + ts;
|
||||||
|
|
||||||
// add all children of the imported <svg> to the <g> we create
|
// add all children of the imported <svg> to the <g> we create
|
||||||
var g = svgdoc.createElementNS(svgns, "g");
|
var g = svgdoc.createElementNS(svgns, "g");
|
||||||
while (importedNode.hasChildNodes()) { g.appendChild(importedNode.firstChild); }
|
while (importedNode.hasChildNodes())
|
||||||
|
g.appendChild(importedNode.firstChild);
|
||||||
|
if (ts)
|
||||||
|
g.setAttribute("transform", ts);
|
||||||
|
|
||||||
|
// now ensure each element has a unique ID
|
||||||
|
var ids = {};
|
||||||
|
walkTree(g, function(n) {
|
||||||
|
// if it's an element node
|
||||||
|
if (n.nodeType == 1) {
|
||||||
|
// and the element has an ID
|
||||||
|
if (n.id) {
|
||||||
|
// and we haven't tracked this ID yet
|
||||||
|
if (!(n.id in ids)) {
|
||||||
|
// add this id to our map
|
||||||
|
ids[n.id] = {elem:null, attrs:[], hrefs:[]};
|
||||||
|
}
|
||||||
|
ids[n.id]["elem"] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now search for all attributes on this element that might refer
|
||||||
|
// to other elements
|
||||||
|
$.each(["clip-path", "fill", "filter", "marker-end", "marker-mid", "marker-start", "mask", "stroke"],function(i,attr) {
|
||||||
|
var attrnode = n.getAttributeNode(attr);
|
||||||
|
if (attrnode) {
|
||||||
|
// the incoming file has been sanitized, so we should be able to safely just strip off the leading #
|
||||||
|
var url = getUrlFromAttr(attrnode.value),
|
||||||
|
refid = url ? url.substr(1) : null;
|
||||||
|
if (refid) {
|
||||||
|
if (!(refid in ids)) {
|
||||||
|
// add this id to our map
|
||||||
|
ids[refid] = {elem:null, attrs:[], hrefs:[]};
|
||||||
|
}
|
||||||
|
ids[refid]["attrs"].push(attrnode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// check xlink:href now
|
||||||
|
var href = n.getAttributeNS(xlinkns,"href");
|
||||||
|
// TODO: what if an <image> or <a> element refers to an element internally?
|
||||||
|
if(href &&
|
||||||
|
$.inArray(n.nodeName, ["filter", "linearGradient", "pattern",
|
||||||
|
"radialGradient", "textPath", "use"]) != -1)
|
||||||
|
{
|
||||||
|
var refid = href.substr(1);
|
||||||
|
if (!(refid in ids)) {
|
||||||
|
// add this id to our map
|
||||||
|
ids[refid] = {elem:null, attrs:[], hrefs:[]};
|
||||||
|
}
|
||||||
|
ids[refid]["hrefs"].push(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// in ids, we now have a map of ids, elements and attributes, let's re-identify
|
||||||
|
for (var oldid in ids) {
|
||||||
|
var elem = ids[oldid]["elem"];
|
||||||
|
if (elem) {
|
||||||
|
var newid = getNextId();
|
||||||
|
// manually increment obj_num because our cloned elements are not in the DOM yet
|
||||||
|
obj_num++;
|
||||||
|
|
||||||
|
// assign element its new id
|
||||||
|
elem.id = newid;
|
||||||
|
|
||||||
|
// remap all url() attributes
|
||||||
|
var attrs = ids[oldid]["attrs"];
|
||||||
|
var j = attrs.length;
|
||||||
|
while (j--) {
|
||||||
|
var attr = attrs[j];
|
||||||
|
attr.ownerElement.setAttribute(attr.name, "url(#" + newid + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// remap all href attributes
|
||||||
|
var hreffers = ids[oldid]["hrefs"];
|
||||||
|
var k = hreffers.length;
|
||||||
|
while (k--) {
|
||||||
|
var hreffer = hreffers[k];
|
||||||
|
hreffer.setAttributeNS(xlinkns, "xlink:href", "#"+newid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now give the g itself a new id
|
||||||
|
g.id = getNextId();
|
||||||
|
// manually increment obj_num because our cloned elements are not in the DOM yet
|
||||||
|
obj_num++;
|
||||||
|
|
||||||
current_layer.appendChild(g);
|
current_layer.appendChild(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5740,54 +5852,13 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
// recalculate dimensions on the top-level children so that unnecessary transforms
|
// recalculate dimensions on the top-level children so that unnecessary transforms
|
||||||
// are removed
|
// are removed
|
||||||
var deepdive = function(node) {
|
walkTreePost(importedNode, function(n){try{recalculateDimensions(n)}catch(e){console.log(e)}});
|
||||||
if (node.nodeType == 1) {
|
|
||||||
var children = node.childNodes;
|
|
||||||
var i = children.length;
|
|
||||||
while (i--) { deepdive(children.item(i)); }
|
|
||||||
try {
|
|
||||||
recalculateDimensions(node);
|
|
||||||
} catch(e) { console.log(e); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deepdive(importedNode);
|
|
||||||
|
|
||||||
// var content = $(svgcontent);
|
|
||||||
|
|
||||||
// var attrs = {
|
|
||||||
// id: 'svgcontent',
|
|
||||||
// overflow: 'visible'
|
|
||||||
// };
|
|
||||||
|
|
||||||
// determine proper size
|
|
||||||
// if (content.attr("viewBox")) {
|
|
||||||
// var vb = content.attr("viewBox").split(' ');
|
|
||||||
// attrs.width = vb[2];
|
|
||||||
// attrs.height = vb[3];
|
|
||||||
// }
|
|
||||||
// // handle content that doesn't have a viewBox
|
|
||||||
// else {
|
|
||||||
// $.each(['width', 'height'], function(i, dim) {
|
|
||||||
// // Set to 100 if not given
|
|
||||||
// var val = content.attr(dim) || 100;
|
|
||||||
//
|
|
||||||
// if((val+'').substr(-1) === "%") {
|
|
||||||
// // Use user units if percentage given
|
|
||||||
// attrs[dim] = parseInt(val);
|
|
||||||
// } else {
|
|
||||||
// attrs[dim] = convertToNum(dim, val);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// content.attr(attrs);
|
|
||||||
batchCmd.addSubCommand(new InsertElementCommand(svgcontent));
|
batchCmd.addSubCommand(new InsertElementCommand(svgcontent));
|
||||||
// update root to the correct size
|
|
||||||
// var changes = content.attr(["width", "height"]);
|
|
||||||
// batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes));
|
|
||||||
|
|
||||||
// reset zoom
|
// reset zoom - TODO: why?
|
||||||
current_zoom = 1;
|
// current_zoom = 1;
|
||||||
|
|
||||||
// identify layers
|
// identify layers
|
||||||
// identifyLayers();
|
// identifyLayers();
|
||||||
|
@ -6734,12 +6805,12 @@ function BatchCommand(text) {
|
||||||
ret = getPathBBox(selected);
|
ret = getPathBBox(selected);
|
||||||
} else if(elem.nodeName == 'use' && !isWebkit) {
|
} else if(elem.nodeName == 'use' && !isWebkit) {
|
||||||
ret = selected.getBBox();
|
ret = selected.getBBox();
|
||||||
ret.x += parseFloat(selected.getAttribute('x'));
|
ret.x += parseFloat(selected.getAttribute('x')||0);
|
||||||
ret.y += parseFloat(selected.getAttribute('y'));
|
ret.y += parseFloat(selected.getAttribute('y')||0);
|
||||||
} else if(elem.nodeName == 'foreignObject') {
|
} else if(elem.nodeName == 'foreignObject') {
|
||||||
ret = selected.getBBox();
|
ret = selected.getBBox();
|
||||||
ret.x += parseFloat(selected.getAttribute('x'));
|
ret.x += parseFloat(selected.getAttribute('x')||0);
|
||||||
ret.y += parseFloat(selected.getAttribute('y'));
|
ret.y += parseFloat(selected.getAttribute('y')||0);
|
||||||
} else {
|
} else {
|
||||||
try { ret = selected.getBBox(); }
|
try { ret = selected.getBBox(); }
|
||||||
catch(e) {
|
catch(e) {
|
||||||
|
@ -7474,9 +7545,6 @@ function BatchCommand(text) {
|
||||||
if(!elems) elems = canvas.getVisibleElements();
|
if(!elems) elems = canvas.getVisibleElements();
|
||||||
if(!elems.length) return false;
|
if(!elems.length) return false;
|
||||||
// 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
|
||||||
// FIXME: doesn't this mean that every time we call getStrokedBBox() that we are
|
|
||||||
// re-creating the getCheckedBBox() function? shouldn't we make this a function
|
|
||||||
// at the 'canvas' level
|
|
||||||
var getCheckedBBox = function(elem) {
|
var getCheckedBBox = function(elem) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -7588,11 +7656,12 @@ function BatchCommand(text) {
|
||||||
var bboxes = [];
|
var bboxes = [];
|
||||||
$.each(elems, function(i, elem) {
|
$.each(elems, function(i, elem) {
|
||||||
var cur_bb = getCheckedBBox(elem);
|
var cur_bb = getCheckedBBox(elem);
|
||||||
if(!cur_bb) return;
|
if(cur_bb) {
|
||||||
var offset = getOffset(elem);
|
var offset = getOffset(elem);
|
||||||
min_x = Math.min(min_x, cur_bb.x - offset);
|
min_x = Math.min(min_x, cur_bb.x - offset);
|
||||||
min_y = Math.min(min_y, cur_bb.y - offset);
|
min_y = Math.min(min_y, cur_bb.y - offset);
|
||||||
bboxes.push(cur_bb);
|
bboxes.push(cur_bb);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
full_bb.x = min_x;
|
full_bb.x = min_x;
|
||||||
|
@ -7600,7 +7669,8 @@ function BatchCommand(text) {
|
||||||
|
|
||||||
$.each(elems, function(i, elem) {
|
$.each(elems, function(i, elem) {
|
||||||
var cur_bb = bboxes[i];
|
var cur_bb = bboxes[i];
|
||||||
if (cur_bb) {
|
// ensure that elem is really an element node
|
||||||
|
if (cur_bb && elem.nodeType == 1) {
|
||||||
var offset = getOffset(elem);
|
var offset = getOffset(elem);
|
||||||
max_x = Math.max(max_x, cur_bb.x + cur_bb.width + offset);
|
max_x = Math.max(max_x, cur_bb.x + cur_bb.width + offset);
|
||||||
max_y = Math.max(max_y, cur_bb.y + cur_bb.height + offset);
|
max_y = Math.max(max_y, cur_bb.y + cur_bb.height + offset);
|
||||||
|
@ -7881,7 +7951,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: 1422 $)";
|
return "svgcanvas.js ($Rev: 1427 $)";
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setUiStrings = function(strs) {
|
this.setUiStrings = function(strs) {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
test("Test existence of SvgCanvas object", function() {
|
test("Test existence of SvgCanvas object", function() {
|
||||||
expect(1);
|
expect(1);
|
||||||
equals(typeof {}, typeof svgCanvas);
|
equal(typeof {}, typeof svgCanvas);
|
||||||
});
|
});
|
||||||
|
|
||||||
module("Path Module");
|
module("Path Module");
|
||||||
|
@ -58,21 +58,21 @@
|
||||||
seglist = p1.pathSegList,
|
seglist = p1.pathSegList,
|
||||||
curseg = null;
|
curseg = null;
|
||||||
|
|
||||||
equals(p1.nodeName, "path", "Expected 'path', got");
|
equal(p1.nodeName, "path", "Expected 'path', got");
|
||||||
|
|
||||||
equals(seglist.numberOfItems, 3, "Number of segments before conversion");
|
equal(seglist.numberOfItems, 3, "Number of segments before conversion");
|
||||||
|
|
||||||
// verify segments before conversion
|
// verify segments before conversion
|
||||||
curseg = seglist.getItem(0);
|
curseg = seglist.getItem(0);
|
||||||
equals(curseg.pathSegTypeAsLetter, "M", "Before conversion, segment #1 type");
|
equal(curseg.pathSegTypeAsLetter, "M", "Before conversion, segment #1 type");
|
||||||
curseg = seglist.getItem(1);
|
curseg = seglist.getItem(1);
|
||||||
equals(curseg.pathSegTypeAsLetter, "L", "Before conversion, segment #2 type");
|
equal(curseg.pathSegTypeAsLetter, "L", "Before conversion, segment #2 type");
|
||||||
curseg = seglist.getItem(2);
|
curseg = seglist.getItem(2);
|
||||||
equals(curseg.pathSegType, 1, "Before conversion, segment #3 type");
|
equal(curseg.pathSegType, 1, "Before conversion, segment #3 type");
|
||||||
|
|
||||||
// convert and verify segments
|
// convert and verify segments
|
||||||
var d = convert(p1, true);
|
var d = convert(p1, true);
|
||||||
equals(d, "m100,100l100,0z", "Converted path to relative string");
|
equal(d, "m100,100l100,0z", "Converted path to relative string");
|
||||||
|
|
||||||
// TODO: see why this isn't working in SVG-edit
|
// TODO: see why this isn't working in SVG-edit
|
||||||
d = convert(p2, true);
|
d = convert(p2, true);
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
tr_2 = svgroot.createSVGMatrix().translate(-90,0),
|
tr_2 = svgroot.createSVGMatrix().translate(-90,0),
|
||||||
tr_3 = svgroot.createSVGMatrix().translate(-10,-50),
|
tr_3 = svgroot.createSVGMatrix().translate(-10,-50),
|
||||||
I = svgCanvas.matrixMultiply(tr_1,tr_2,tr_3);
|
I = svgCanvas.matrixMultiply(tr_1,tr_2,tr_3);
|
||||||
equals(true, isIdentity(I),
|
equal(isIdentity(I), true,
|
||||||
"Expected identity matrix when translating there and back, got " + matrixString(I));
|
"Expected identity matrix when translating there and back, got " + matrixString(I));
|
||||||
|
|
||||||
// rotate there and back
|
// rotate there and back
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
rot_back = svgroot.createSVGMatrix().rotate(-90); // TODO: set this to -50
|
rot_back = svgroot.createSVGMatrix().rotate(-90); // TODO: set this to -50
|
||||||
rot_back_more = svgroot.createSVGMatrix().rotate(0); // TODO: set this to -40
|
rot_back_more = svgroot.createSVGMatrix().rotate(0); // TODO: set this to -40
|
||||||
I = svgCanvas.matrixMultiply(rot_there, rot_back, rot_back_more);
|
I = svgCanvas.matrixMultiply(rot_there, rot_back, rot_back_more);
|
||||||
equals(true, isIdentity(I),
|
equal(isIdentity(I), true,
|
||||||
"Expected identity matrix when rotating there and back, got " + matrixString(I));
|
"Expected identity matrix when rotating there and back, got " + matrixString(I));
|
||||||
|
|
||||||
// scale up and down
|
// scale up and down
|
||||||
|
@ -109,15 +109,15 @@
|
||||||
scale_down = svgroot.createSVGMatrix().scaleNonUniform(0.25,1);
|
scale_down = svgroot.createSVGMatrix().scaleNonUniform(0.25,1);
|
||||||
scale_down_more = svgroot.createSVGMatrix().scaleNonUniform(1,0.25);
|
scale_down_more = svgroot.createSVGMatrix().scaleNonUniform(1,0.25);
|
||||||
I = svgCanvas.matrixMultiply(scale_up, scale_down, scale_down_more);
|
I = svgCanvas.matrixMultiply(scale_up, scale_down, scale_down_more);
|
||||||
equals(true, isIdentity(I),
|
equal(isIdentity(I), true,
|
||||||
"Expected identity matrix when scaling up and down, got " + matrixString(I));
|
"Expected identity matrix when scaling up and down, got " + matrixString(I));
|
||||||
|
|
||||||
// test multiplication with its inverse
|
// test multiplication with its inverse
|
||||||
I = svgCanvas.matrixMultiply(rot_there, rot_there.inverse());
|
I = svgCanvas.matrixMultiply(rot_there, rot_there.inverse());
|
||||||
equals(true, isIdentity(I),
|
equal(isIdentity(I), true,
|
||||||
"Expected identity matrix when multiplying a matrix by its inverse, got " + matrixString(I));
|
"Expected identity matrix when multiplying a matrix by its inverse, got " + matrixString(I));
|
||||||
I = svgCanvas.matrixMultiply(rot_there.inverse(), rot_there);
|
I = svgCanvas.matrixMultiply(rot_there.inverse(), rot_there);
|
||||||
equals(true, isIdentity(I),
|
equal(isIdentity(I), true,
|
||||||
"Expected identity matrix when multiplying a matrix by its inverse, got " + matrixString(I));
|
"Expected identity matrix when multiplying a matrix by its inverse, got " + matrixString(I));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -137,18 +137,18 @@
|
||||||
fu = document.getElementById("foreign-use"),
|
fu = document.getElementById("foreign-use"),
|
||||||
nfu = document.getElementById("no-use");
|
nfu = document.getElementById("no-use");
|
||||||
|
|
||||||
equals((u && u.nodeName == "use"), true, "Did not import <use> element");
|
equal((u && u.nodeName == "use"), true, "Did not import <use> element");
|
||||||
equals(fu, null, "Removed <use> element that had a foreign href");
|
equal(fu, null, "Removed <use> element that had a foreign href");
|
||||||
equals(nfu, null, "Removed <use> element that had no href");
|
equal(nfu, null, "Removed <use> element that had no href");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Test getUrlFromAttr", function() {
|
test("Test getUrlFromAttr", function() {
|
||||||
expect(4);
|
expect(4);
|
||||||
|
|
||||||
equals(svgCanvas.getUrlFromAttr("url(#foo)"), "#foo");
|
equal(svgCanvas.getUrlFromAttr("url(#foo)"), "#foo");
|
||||||
equals(svgCanvas.getUrlFromAttr("url(somefile.svg#foo)"), "somefile.svg#foo");
|
equal(svgCanvas.getUrlFromAttr("url(somefile.svg#foo)"), "somefile.svg#foo");
|
||||||
equals(svgCanvas.getUrlFromAttr("url('#foo')"), "#foo");
|
equal(svgCanvas.getUrlFromAttr("url('#foo')"), "#foo");
|
||||||
equals(svgCanvas.getUrlFromAttr('url("#foo")'), "#foo");
|
equal(svgCanvas.getUrlFromAttr('url("#foo")'), "#foo");
|
||||||
});
|
});
|
||||||
|
|
||||||
// This test shows that an element with an invalid attribute is still parsed in properly
|
// This test shows that an element with an invalid attribute is still parsed in properly
|
||||||
|
@ -162,8 +162,8 @@
|
||||||
|
|
||||||
var t = document.getElementById("the-text");
|
var t = document.getElementById("the-text");
|
||||||
|
|
||||||
equals(true, (t && t.nodeName == "text"), "Did not import <text> element");
|
equal(true, (t && t.nodeName == "text"), "Did not import <text> element");
|
||||||
equals(null, t.getAttribute("d"), "Imported a <text> with a d attribute");
|
equal(null, t.getAttribute("d"), "Imported a <text> with a d attribute");
|
||||||
});
|
});
|
||||||
|
|
||||||
// This test makes sure import/export properly handles namespaced attributes
|
// This test makes sure import/export properly handles namespaced attributes
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
'</svg>');
|
'</svg>');
|
||||||
var attrVal = document.getElementById('se_test_elem').getAttributeNS("http://svg-edit.googlecode.com", "foo");
|
var attrVal = document.getElementById('se_test_elem').getAttributeNS("http://svg-edit.googlecode.com", "foo");
|
||||||
|
|
||||||
equals(attrVal === "bar", true, "Preserved namespaced attribute on import");
|
equal(attrVal === "bar", true, "Preserved namespaced attribute on import");
|
||||||
|
|
||||||
var output = svgCanvas.getSvgString();
|
var output = svgCanvas.getSvgString();
|
||||||
var has_xlink = output.indexOf('xmlns:xlink="http://www.w3.org/1999/xlink"') !== -1;
|
var has_xlink = output.indexOf('xmlns:xlink="http://www.w3.org/1999/xlink"') !== -1;
|
||||||
|
@ -183,10 +183,10 @@
|
||||||
var has_foo = output.indexOf('xmlns:foo=') !== -1;
|
var has_foo = output.indexOf('xmlns:foo=') !== -1;
|
||||||
var has_attr = output.indexOf('se:foo="bar"') !== -1;
|
var has_attr = output.indexOf('se:foo="bar"') !== -1;
|
||||||
|
|
||||||
equals(has_attr, true, "Preserved namespaced attribute on export");
|
equal(has_attr, true, "Preserved namespaced attribute on export");
|
||||||
equals(has_xlink, true, "Included xlink: xmlns");
|
equal(has_xlink, true, "Included xlink: xmlns");
|
||||||
equals(has_se, true, "Included se: xmlns");
|
equal(has_se, true, "Included se: xmlns");
|
||||||
equals(has_foo, false, "Did not include foo: xmlns");
|
equal(has_foo, false, "Did not include foo: xmlns");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Test import math elements inside a foreignObject", function() {
|
test("Test import math elements inside a foreignObject", function() {
|
||||||
|
@ -205,20 +205,86 @@
|
||||||
// see Bug https://bugs.webkit.org/show_bug.cgi?id=35042
|
// see Bug https://bugs.webkit.org/show_bug.cgi?id=35042
|
||||||
var math = fo.firstChild;
|
var math = fo.firstChild;
|
||||||
|
|
||||||
equals(!!math, true, "Math element exists");
|
equal(!!math, true, "Math element exists");
|
||||||
equals(math.nodeName, 'math', "Math element has the proper nodeName");
|
equal(math.nodeName, 'math', "Math element has the proper nodeName");
|
||||||
equals(math.getAttribute('id'), 'm', "Math element has an id");
|
equal(math.getAttribute('id'), 'm', "Math element has an id");
|
||||||
equals(math.namespaceURI, "http://www.w3.org/1998/Math/MathML", "Preserved MathML namespace");
|
equal(math.namespaceURI, "http://www.w3.org/1998/Math/MathML", "Preserved MathML namespace");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Test XML entities in attribute", function() {
|
test("Test escaping XML entities", function() {
|
||||||
expect(3);
|
expect(3);
|
||||||
|
|
||||||
equals(svgCanvas.getPrivateMethods().toXml("<"), "<", "Escaped < properly");
|
equal(svgCanvas.getPrivateMethods().toXml("<"), "<", "Escaped < properly");
|
||||||
equals(svgCanvas.getPrivateMethods().toXml(">"), ">", "Escaped > properly");
|
equal(svgCanvas.getPrivateMethods().toXml(">"), ">", "Escaped > properly");
|
||||||
equals(svgCanvas.getPrivateMethods().toXml("&"), "&", "Escaped & properly");
|
equal(svgCanvas.getPrivateMethods().toXml("&"), "&", "Escaped & properly");
|
||||||
// TODO: what about " and ' ?
|
// TODO: what about " and ' ?
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Test importing SVG into existing drawing", function() {
|
||||||
|
expect(3);
|
||||||
|
|
||||||
|
var doc = svgCanvas.setSvgString('<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">'+
|
||||||
|
'<g><title>Layer 1</title>'+
|
||||||
|
'<circle cx="200" cy="200" r="50" fill="blue"/>'+
|
||||||
|
'<ellipse cx="300" cy="100" rx="40" ry="30" fill="green"/>'+
|
||||||
|
'</g>'+
|
||||||
|
'</svg>');
|
||||||
|
|
||||||
|
svgCanvas.importSvgString('<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">'+
|
||||||
|
'<circle cx="50" cy="50" r="40" fill="yellow"/>'+
|
||||||
|
'<rect width="20" height="20" fill="blue"/>'+
|
||||||
|
'</svg>');
|
||||||
|
|
||||||
|
var svgcontent = document.getElementById("svgcontent"),
|
||||||
|
circles = svgcontent.getElementsByTagNameNS(svgns, "circle"),
|
||||||
|
rects = svgcontent.getElementsByTagNameNS(svgns, "rect"),
|
||||||
|
ellipses = svgcontent.getElementsByTagNameNS(svgns, "ellipse");
|
||||||
|
equal(circles.length, 2, "Found two circles upon importing");
|
||||||
|
equal(rects.length, 1, "Found one rectangle upon importing");
|
||||||
|
equal(ellipses.length, 1, "Found one ellipse upon importing");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Test importing SVG remaps IDs", function() {
|
||||||
|
expect(6);
|
||||||
|
|
||||||
|
var doc = svgCanvas.setSvgString('<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">'+
|
||||||
|
'<g><title>Layer 1</title>'+
|
||||||
|
'<ellipse id="svg_1" cx="200" cy="200" rx="50" ry="20" fill="blue"/>'+
|
||||||
|
'<ellipse id="svg_2" cx="300" cy="100" rx="40" ry="30" fill="green"/>'+
|
||||||
|
'<ellipse id="svg_3" cx="300" cy="100" rx="40" ry="30" fill="green"/>'+
|
||||||
|
'</g>'+
|
||||||
|
'</svg>');
|
||||||
|
|
||||||
|
svgCanvas.importSvgString('<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink">'+
|
||||||
|
'<defs>'+
|
||||||
|
'<linearGradient id="svg_2">'+
|
||||||
|
'<stop stop-color="red" offset="0"/>'+
|
||||||
|
'<stop stop-color="green" offset="1"/>'+
|
||||||
|
'</linearGradient>'+
|
||||||
|
'<rect id="svg_3" width="20" height="20" fill="blue" stroke="url(#svg_2)"/>'+
|
||||||
|
'</defs>'+
|
||||||
|
'<circle id="svg_1" cx="50" cy="50" r="40" fill="url(#svg_2)"/>'+
|
||||||
|
'<use id="svg_4" width="30" height="30" xl:href="#svg_3"/>'+
|
||||||
|
'</svg>');
|
||||||
|
|
||||||
|
var svgcontent = document.getElementById("svgcontent"),
|
||||||
|
circles = svgcontent.getElementsByTagNameNS(svgns, "circle"),
|
||||||
|
rects = svgcontent.getElementsByTagNameNS(svgns, "rect"),
|
||||||
|
ellipses = svgcontent.getElementsByTagNameNS(svgns, "ellipse"),
|
||||||
|
defs = svgcontent.getElementsByTagNameNS(svgns, "defs"),
|
||||||
|
grads = svgcontent.getElementsByTagNameNS(svgns, "linearGradient"),
|
||||||
|
uses = svgcontent.getElementsByTagNameNS(svgns, "use");
|
||||||
|
notEqual(circles.item(0).id, "svg_1", "Circle not re-identified");
|
||||||
|
notEqual(rects.item(0).id, "svg_3", "Rectangle not re-identified");
|
||||||
|
// // TODO: determine why this test fails in WebKit browsers
|
||||||
|
// equal(grads.length, 1, "Linear gradient imported");
|
||||||
|
var grad = defs.item(0).firstChild;
|
||||||
|
notEqual(grad.id, "svg_2", "Linear gradient not re-identified");
|
||||||
|
notEqual(circles.item(0).getAttribute("fill"), "url(#svg_2)", "Circle fill value not remapped");
|
||||||
|
notEqual(rects.item(0).getAttribute("stroke"), "url(#svg_2)", "Rectangle stroke value not remapped");
|
||||||
|
notEqual(uses.item(0).getAttributeNS(xlinkns, "href"), "#svg_3");
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
Loading…
Reference in a new issue