Now remap xlink:href attributes when importing <use>, <filter>, <pattern>, <textPath> and gradients.

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1426 eee81c28-f429-11dd-99c0-75d572ba1ddd
master
Jeff Schiller 2010-02-22 02:22:08 +00:00
parent 6e15924461
commit 6039875f5a
2 changed files with 41 additions and 14 deletions

View File

@ -1392,7 +1392,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);
@ -5747,15 +5747,14 @@ function BatchCommand(text) {
// and we haven't tracked this ID yet // and we haven't tracked this ID yet
if (!(n.id in ids)) { if (!(n.id in ids)) {
// add this id to our map // add this id to our map
ids[n.id] = {elem:null, attrs:[]}; ids[n.id] = {elem:null, attrs:[], hrefs:[]};
} }
ids[n.id]['elem'] = n; ids[n.id]["elem"] = n;
} }
// now search for all attributes on this element that might refer // now search for all attributes on this element that might refer
// to other elements // to other elements
// TODO: also check for other attributes not of the url() form $.each(["clip-path", "fill", "filter", "marker-end", "marker-mid", "marker-start", "mask", "stroke"],function(i,attr) {
$.each(["clip-path", "fill", "marker-end", "marker-mid", "marker-start", "mask", "stroke"],function(i,attr) {
var attrnode = n.getAttributeNode(attr); var attrnode = n.getAttributeNode(attr);
if (attrnode) { if (attrnode) {
// the incoming file has been sanitized, so we should be able to safely just strip off the leading # // the incoming file has been sanitized, so we should be able to safely just strip off the leading #
@ -5764,31 +5763,56 @@ function BatchCommand(text) {
if (refid) { if (refid) {
if (!(refid in ids)) { if (!(refid in ids)) {
// add this id to our map // add this id to our map
ids[refid] = {elem:null, attrs:[]}; ids[refid] = {elem:null, attrs:[], hrefs:[]};
} }
// alert("pushing " + attrnode.name + " into ids[" + refid + "]"); ids[refid]["attrs"].push(attrnode);
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 // in ids, we now have a map of ids, elements and attributes, let's re-identify
for (var oldid in ids) { for (var oldid in ids) {
var elem = ids[oldid]['elem']; var elem = ids[oldid]["elem"];
if (elem) { if (elem) {
var newid = getNextId(); var newid = getNextId();
// manually increment obj_num because our cloned elements are not in the DOM yet // manually increment obj_num because our cloned elements are not in the DOM yet
obj_num++; obj_num++;
// assign element its new id
elem.id = newid; elem.id = newid;
var attrs = ids[oldid]['attrs'];
// remap all url() attributes
var attrs = ids[oldid]["attrs"];
var j = attrs.length; var j = attrs.length;
while (j--) { while (j--) {
var attr = attrs[j]; var attr = attrs[j];
attr.ownerElement.setAttribute(attr.name, "url(#" + newid + ")"); 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);
}
} }
} }

View File

@ -245,7 +245,7 @@
}); });
test("Test importing SVG remaps IDs", function() { test("Test importing SVG remaps IDs", function() {
expect(5); expect(6);
var doc = svgCanvas.setSvgString('<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">'+ var doc = svgCanvas.setSvgString('<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">'+
'<g><title>Layer 1</title>'+ '<g><title>Layer 1</title>'+
@ -255,15 +255,16 @@
'</g>'+ '</g>'+
'</svg>'); '</svg>');
svgCanvas.importSvgString('<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">'+ svgCanvas.importSvgString('<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'+
'<defs>'+ '<defs>'+
'<linearGradient id="svg_2">'+ '<linearGradient id="svg_2">'+
'<stop stop-color="red" offset="0"/>'+ '<stop stop-color="red" offset="0"/>'+
'<stop stop-color="green" offset="1"/>'+ '<stop stop-color="green" offset="1"/>'+
'</linearGradient>'+ '</linearGradient>'+
'<rect id="svg_3" width="20" height="20" fill="blue" stroke="url(#svg_2)"/>'+
'</defs>'+ '</defs>'+
'<circle id="svg_1" cx="50" cy="50" r="40" fill="url(#svg_2)"/>'+ '<circle id="svg_1" cx="50" cy="50" r="40" fill="url(#svg_2)"/>'+
'<rect id="svg_3" width="20" height="20" fill="blue" stroke="url(#svg_2)"/>'+ '<use id="svg_4" width="30" height="30" xlink:href="#svg_3"/>'+
'</svg>'); '</svg>');
var svgcontent = document.getElementById("svgcontent"), var svgcontent = document.getElementById("svgcontent"),
@ -271,7 +272,8 @@
rects = svgcontent.getElementsByTagNameNS(svgns, "rect"), rects = svgcontent.getElementsByTagNameNS(svgns, "rect"),
ellipses = svgcontent.getElementsByTagNameNS(svgns, "ellipse"), ellipses = svgcontent.getElementsByTagNameNS(svgns, "ellipse"),
defs = svgcontent.getElementsByTagNameNS(svgns, "defs"), defs = svgcontent.getElementsByTagNameNS(svgns, "defs"),
grads = svgcontent.getElementsByTagNameNS(svgns, "linearGradient"); grads = svgcontent.getElementsByTagNameNS(svgns, "linearGradient"),
uses = svgcontent.getElementsByTagNameNS(svgns, "use");
notEqual(circles.item(0).id, "svg_1", "Circle not re-identified"); notEqual(circles.item(0).id, "svg_1", "Circle not re-identified");
notEqual(rects.item(0).id, "svg_3", "Rectangle not re-identified"); notEqual(rects.item(0).id, "svg_3", "Rectangle not re-identified");
// // TODO: determine why this test fails in WebKit browsers // // TODO: determine why this test fails in WebKit browsers
@ -280,6 +282,7 @@
notEqual(grad.id, "svg_2", "Linear gradient not re-identified"); 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(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(rects.item(0).getAttribute("stroke"), "url(#svg_2)", "Rectangle stroke value not remapped");
notEqual(uses.item(0).getAttributeNS(xlinkns, "href"), "#svg_3");
}); });
}); });