Added proper support for child SVG elements and made image library import SVGs, taking care of more of issue 71. Also fixed Opera 10.60 layer bug
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1633 eee81c28-f429-11dd-99c0-75d572ba1dddmaster
parent
f0ec659f19
commit
eb575ef68d
|
@ -18,7 +18,7 @@ svgEditor.addExtension("imagelib", function() {
|
||||||
name: 'Demo library (external)',
|
name: 'Demo library (external)',
|
||||||
url: 'http://a.deveria.com/tests/clip-art/',
|
url: 'http://a.deveria.com/tests/clip-art/',
|
||||||
description: 'Demonstration library for SVG-edit on another domain'
|
description: 'Demonstration library for SVG-edit on another domain'
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,11 +39,13 @@ svgEditor.addExtension("imagelib", function() {
|
||||||
|
|
||||||
switch (char1) {
|
switch (char1) {
|
||||||
case '<':
|
case '<':
|
||||||
svgEditor.loadFromString(response);
|
svgCanvas.importSvgString(response);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if(response.indexOf('data:') === 0) {
|
if(response.indexOf('data:') === 0) {
|
||||||
svgEditor.loadFromDataURI(response);
|
var pre = 'data:image/svg+xml;base64,';
|
||||||
|
var src = response.substring(pre.length);
|
||||||
|
svgCanvas.importSvgString(svgCanvas.Utils.decode64(src));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Else fall through
|
// Else fall through
|
||||||
|
|
|
@ -145,6 +145,7 @@
|
||||||
// - invoke a file chooser dialog in 'save' mode
|
// - invoke a file chooser dialog in 'save' mode
|
||||||
// - save the file to location chosen by the user
|
// - save the file to location chosen by the user
|
||||||
Editor.setCustomHandlers = function(opts) {
|
Editor.setCustomHandlers = function(opts) {
|
||||||
|
Editor.ready(function() {
|
||||||
if(opts.open) {
|
if(opts.open) {
|
||||||
$('#tool_open').show();
|
$('#tool_open').show();
|
||||||
svgCanvas.open = opts.open;
|
svgCanvas.open = opts.open;
|
||||||
|
@ -157,6 +158,7 @@
|
||||||
svgCanvas.bind("exported", opts.pngsave);
|
svgCanvas.bind("exported", opts.pngsave);
|
||||||
}
|
}
|
||||||
customHandlers = opts;
|
customHandlers = opts;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor.randomizeIds = function() {
|
Editor.randomizeIds = function() {
|
||||||
|
@ -182,6 +184,7 @@
|
||||||
|
|
||||||
svgEditor.setConfig(urldata);
|
svgEditor.setConfig(urldata);
|
||||||
|
|
||||||
|
// FIXME: This is null if Data URL ends with '='.
|
||||||
var src = urldata.source;
|
var src = urldata.source;
|
||||||
var qstr = $.param.querystring();
|
var qstr = $.param.querystring();
|
||||||
|
|
||||||
|
@ -1340,6 +1343,10 @@
|
||||||
|
|
||||||
var el_name = elem.tagName;
|
var el_name = elem.tagName;
|
||||||
|
|
||||||
|
if($(elem).data('gsvg')) {
|
||||||
|
el_name = 'svg';
|
||||||
|
}
|
||||||
|
|
||||||
if(panels[el_name]) {
|
if(panels[el_name]) {
|
||||||
var cur_panel = panels[el_name];
|
var cur_panel = panels[el_name];
|
||||||
|
|
||||||
|
@ -3561,7 +3568,7 @@
|
||||||
if(this.files.length==1) {
|
if(this.files.length==1) {
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
reader.onloadend = function(e) {
|
reader.onloadend = function(e) {
|
||||||
svgCanvas.importSvgString(e.target.result);
|
svgCanvas.importSvgString(e.target.result, true);
|
||||||
updateCanvas();
|
updateCanvas();
|
||||||
};
|
};
|
||||||
reader.readAsText(this.files[0]);
|
reader.readAsText(this.files[0]);
|
||||||
|
@ -3815,6 +3822,7 @@
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
// ?iconsize=s&bkgd_color=555
|
// ?iconsize=s&bkgd_color=555
|
||||||
|
|
||||||
// svgEditor.setConfig({
|
// svgEditor.setConfig({
|
||||||
|
|
|
@ -1249,7 +1249,7 @@ var SelectorManager;
|
||||||
offset += 2/current_zoom;
|
offset += 2/current_zoom;
|
||||||
}
|
}
|
||||||
var bbox = getBBox(selected);
|
var bbox = getBBox(selected);
|
||||||
if(selected.tagName == 'g') {
|
if(selected.tagName == 'g' && !$(selected).data('gsvg')) {
|
||||||
// The bbox for a group does not include stroke vals, so we
|
// The bbox for a group does not include stroke vals, so we
|
||||||
// get the bbox based on its children.
|
// get the bbox based on its children.
|
||||||
var stroked_bbox = getStrokedBBox(selected.childNodes);
|
var stroked_bbox = getStrokedBBox(selected.childNodes);
|
||||||
|
@ -2223,6 +2223,18 @@ var getVisibleElements = this.getVisibleElements = function(parent, includeBBox)
|
||||||
return contentElems.reverse();
|
return contentElems.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function: groupSvgElem
|
||||||
|
// Wrap an SVG element into a group element, mark the group as 'gsvg'
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// elem - SVG element to wrap
|
||||||
|
var groupSvgElem = this.groupSvgElem = function(elem) {
|
||||||
|
var g = document.createElementNS(svgns, "g");
|
||||||
|
elem.parentNode.replaceChild(g, elem);
|
||||||
|
$(g).append(elem).data('gsvg', elem)[0].id = getNextId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function: copyElem
|
// Function: copyElem
|
||||||
// Create a clone of an element, updating its ID and its children's IDs when needed
|
// Create a clone of an element, updating its ID and its children's IDs when needed
|
||||||
//
|
//
|
||||||
|
@ -2264,7 +2276,10 @@ var copyElem = function(el) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(new_el.tagName == 'image') {
|
|
||||||
|
if($(el).data('gsvg')) {
|
||||||
|
$(new_el).data('gsvg', new_el.firstChild);
|
||||||
|
} else if(new_el.tagName == 'image') {
|
||||||
preventClickDefault(new_el);
|
preventClickDefault(new_el);
|
||||||
}
|
}
|
||||||
return new_el;
|
return new_el;
|
||||||
|
@ -2394,6 +2409,7 @@ var sanitizeSvg = this.sanitizeSvg = function(node) {
|
||||||
|
|
||||||
// if this element is allowed
|
// if this element is allowed
|
||||||
if (allowedAttrs != undefined) {
|
if (allowedAttrs != undefined) {
|
||||||
|
|
||||||
var se_attrs = [];
|
var se_attrs = [];
|
||||||
|
|
||||||
var i = node.attributes.length;
|
var i = node.attributes.length;
|
||||||
|
@ -2872,6 +2888,7 @@ var remapElement = this.remapElement = function(selected,changes,m) {
|
||||||
changes["x"] = pt1.x;
|
changes["x"] = pt1.x;
|
||||||
changes["y"] = pt1.y;
|
changes["y"] = pt1.y;
|
||||||
break;
|
break;
|
||||||
|
case "g":
|
||||||
case "text":
|
case "text":
|
||||||
// if it was a translate, then just update x,y
|
// if it was a translate, then just update x,y
|
||||||
if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 &&
|
if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 &&
|
||||||
|
@ -2993,6 +3010,12 @@ var remapElement = this.remapElement = function(selected,changes,m) {
|
||||||
case "text":
|
case "text":
|
||||||
assignAttributes(selected, changes, 1000, true);
|
assignAttributes(selected, changes, 1000, true);
|
||||||
break;
|
break;
|
||||||
|
case "g":
|
||||||
|
var gsvg = $(selected).data('gsvg');
|
||||||
|
if(gsvg) {
|
||||||
|
assignAttributes(gsvg, changes, 1000, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "polyline":
|
case "polyline":
|
||||||
case "polygon":
|
case "polygon":
|
||||||
var len = changes["points"].length;
|
var len = changes["points"].length;
|
||||||
|
@ -3119,6 +3142,9 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grouped SVG element
|
||||||
|
var gsvg = $(selected).data('gsvg');
|
||||||
|
|
||||||
// we know we have some transforms, so set up return variable
|
// we know we have some transforms, so set up return variable
|
||||||
var batchCmd = new BatchCommand("Transform");
|
var batchCmd = new BatchCommand("Transform");
|
||||||
|
|
||||||
|
@ -3170,6 +3196,12 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
||||||
$.each(changes, function(attr, val) {
|
$.each(changes, function(attr, val) {
|
||||||
changes[attr] = convertToNum(attr, val);
|
changes[attr] = convertToNum(attr, val);
|
||||||
});
|
});
|
||||||
|
} else if(gsvg) {
|
||||||
|
// GSVG exception
|
||||||
|
changes = {
|
||||||
|
x: $(gsvg).attr('x') || 0,
|
||||||
|
y: $(gsvg).attr('y') || 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we haven't created an initial array in polygon/polyline/path, then
|
// if we haven't created an initial array in polygon/polyline/path, then
|
||||||
|
@ -3183,8 +3215,8 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
||||||
// save the start transform value too
|
// save the start transform value too
|
||||||
initial["transform"] = start_transform ? start_transform : "";
|
initial["transform"] = start_transform ? start_transform : "";
|
||||||
|
|
||||||
// if it's a group, we have special processing to flatten transforms
|
// if it's a regular group, we have special processing to flatten transforms
|
||||||
if (selected.tagName == "g" || selected.tagName == "a") {
|
if ((selected.tagName == "g" && !gsvg) || selected.tagName == "a") {
|
||||||
var box = getBBox(selected),
|
var box = 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,
|
||||||
|
@ -3770,6 +3802,10 @@ var matrixMultiply = this.matrixMultiply = function() {
|
||||||
// Returns:
|
// Returns:
|
||||||
// A single matrix transform object
|
// A single matrix transform object
|
||||||
var transformListToTransform = this.transformListToTransform = function(tlist, min, max) {
|
var transformListToTransform = this.transformListToTransform = function(tlist, min, max) {
|
||||||
|
if(tlist == null) {
|
||||||
|
// Or should tlist = null have been prevented before this?
|
||||||
|
return svgroot.createSVGTransformFromMatrix(svgroot.createSVGMatrix());
|
||||||
|
}
|
||||||
var min = min == undefined ? 0 : min;
|
var min = min == undefined ? 0 : min;
|
||||||
var max = max == undefined ? (tlist.numberOfItems-1) : max;
|
var max = max == undefined ? (tlist.numberOfItems-1) : max;
|
||||||
min = parseInt(min);
|
min = parseInt(min);
|
||||||
|
@ -3901,6 +3937,7 @@ var addToSelection = this.addToSelection = function(elemsToAdd, showGrips) {
|
||||||
if (elemsToAdd.length == 0) { return; }
|
if (elemsToAdd.length == 0) { return; }
|
||||||
// find the first null in our selectedElements array
|
// find the first null in our selectedElements array
|
||||||
var j = 0;
|
var j = 0;
|
||||||
|
|
||||||
while (j < selectedElements.length) {
|
while (j < selectedElements.length) {
|
||||||
if (selectedElements[j] == null) {
|
if (selectedElements[j] == null) {
|
||||||
break;
|
break;
|
||||||
|
@ -4083,15 +4120,38 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// go up until we hit a child of a layer
|
// Get the desired mouse_target with jQuery selector-fu
|
||||||
while (mouse_target.parentNode.parentNode.tagName == "g") {
|
// If it's root-like, select the root
|
||||||
|
if($.inArray(mouse_target, [svgroot, container, svgcontent, current_layer]) !== -1) {
|
||||||
|
return svgroot;
|
||||||
|
}
|
||||||
|
|
||||||
|
var $target = $(mouse_target);
|
||||||
|
|
||||||
|
// If it's a selection grip, return the grip parent
|
||||||
|
if($target.closest('#selectorParentGroup').length) {
|
||||||
|
// While we could instead have just returned mouse_target,
|
||||||
|
// this makes it easier to indentify as being a selector grip
|
||||||
|
return selectorManager.selectorParentGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (mouse_target.parentNode !== current_layer) {
|
||||||
mouse_target = mouse_target.parentNode;
|
mouse_target = mouse_target.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mouse_target;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// // go up until we hit a child of a layer
|
||||||
|
// while (mouse_target.parentNode.parentNode.tagName == 'g') {
|
||||||
|
// mouse_target = mouse_target.parentNode;
|
||||||
|
// }
|
||||||
// Webkit bubbles the mouse event all the way up to the div, so we
|
// Webkit bubbles the mouse event all the way up to the div, so we
|
||||||
// set the mouse_target to the svgroot like the other browsers
|
// set the mouse_target to the svgroot like the other browsers
|
||||||
if (mouse_target.nodeName.toLowerCase() == "div") {
|
// if (mouse_target.nodeName.toLowerCase() == "div") {
|
||||||
mouse_target = svgroot;
|
// mouse_target = svgroot;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return mouse_target;
|
return mouse_target;
|
||||||
};
|
};
|
||||||
|
@ -4137,7 +4197,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
||||||
|
|
||||||
// if it is a selector grip, then it must be a single element selected,
|
// if it is a selector grip, then it must be a single element selected,
|
||||||
// set the mouse_target to that and update the mode to rotate/resize
|
// set the mouse_target to that and update the mode to rotate/resize
|
||||||
if (mouse_target.parentNode == selectorManager.selectorParentGroup && selectedElements[0] != null) {
|
if (mouse_target == selectorManager.selectorParentGroup && selectedElements[0] != null) {
|
||||||
var gripid = evt.target.id,
|
var gripid = evt.target.id,
|
||||||
griptype = gripid.substr(0,20);
|
griptype = gripid.substr(0,20);
|
||||||
// rotating
|
// rotating
|
||||||
|
@ -4582,6 +4642,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
||||||
}
|
}
|
||||||
var selectedBBox = selectedBBoxes[0];
|
var selectedBBox = selectedBBoxes[0];
|
||||||
|
|
||||||
|
if(selectedBBox) {
|
||||||
// reset selected bbox top-left position
|
// reset selected bbox top-left position
|
||||||
selectedBBox.x = left;
|
selectedBBox.x = left;
|
||||||
selectedBBox.y = top;
|
selectedBBox.y = top;
|
||||||
|
@ -4593,7 +4654,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
||||||
if (ty) {
|
if (ty) {
|
||||||
selectedBBox.y += dy;
|
selectedBBox.y += dy;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
selectorManager.requestSelector(selected).resize();
|
selectorManager.requestSelector(selected).resize();
|
||||||
break;
|
break;
|
||||||
case "zoom":
|
case "zoom":
|
||||||
|
@ -7377,7 +7438,34 @@ var svgCanvasToString = this.svgCanvasToString = function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var naked_svgs = [];
|
||||||
|
|
||||||
|
// Unwrap gsvg if it has no special attributes (only id and style)
|
||||||
|
$(svgcontent).find('g:data(gsvg)').each(function() {
|
||||||
|
var attrs = this.attributes;
|
||||||
|
var len = attrs.length;
|
||||||
|
for(var i=0; i<len; i++) {
|
||||||
|
if(attrs[i].nodeName == 'id' || attrs[i].nodeName == 'style') {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No significant attributes, so ungroup
|
||||||
|
if(len <= 0) {
|
||||||
|
var svg = this.firstChild;
|
||||||
|
naked_svgs.push(svg);
|
||||||
|
$(this).replaceWith(svg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var output = svgToString(svgcontent, 0);
|
var output = svgToString(svgcontent, 0);
|
||||||
|
|
||||||
|
// Rewrap gsvg
|
||||||
|
if(naked_svgs.length) {
|
||||||
|
$(naked_svgs).each(function() {
|
||||||
|
groupSvgElem(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7481,6 +7569,7 @@ var svgToString = this.svgToString = function(elem, indent) {
|
||||||
out.push(">");
|
out.push(">");
|
||||||
indent++;
|
indent++;
|
||||||
var bOneLine = false;
|
var bOneLine = false;
|
||||||
|
|
||||||
for (var i=0; i<childs.length; i++)
|
for (var i=0; i<childs.length; i++)
|
||||||
{
|
{
|
||||||
var child = childs.item(i);
|
var child = childs.item(i);
|
||||||
|
@ -7645,6 +7734,94 @@ this.randomizeIds = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function: uniquifyElems
|
||||||
|
// Ensure each element has a unique ID
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// g - The parent element of the tree to give unique IDs
|
||||||
|
var uniquifyElems = this.uniquifyElems = function(g) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually increment obj_num because our cloned elements are not in the DOM yet
|
||||||
|
obj_num++;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Function: setSvgString
|
// Function: setSvgString
|
||||||
// This function sets the current drawing as the input SVG XML.
|
// This function sets the current drawing as the input SVG XML.
|
||||||
|
@ -7699,6 +7876,20 @@ this.setSvgString = function(xmlString) {
|
||||||
canvas.embedImage(val);
|
canvas.embedImage(val);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wrap child SVGs in group elements
|
||||||
|
$(svgcontent).find('svg').each(function() {
|
||||||
|
uniquifyElems(this);
|
||||||
|
|
||||||
|
// Check if it already has a gsvg group
|
||||||
|
var pa = this.parentNode;
|
||||||
|
if(pa.children.length === 1 && pa.nodeName === 'g') {
|
||||||
|
$(pa).data('gsvg', this);
|
||||||
|
pa.id = pa.id || getNextId();
|
||||||
|
} else {
|
||||||
|
groupSvgElem(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// convert gradients with userSpaceOnUse to objectBoundingBox
|
// convert gradients with userSpaceOnUse to objectBoundingBox
|
||||||
$(svgcontent).find('linearGradient, radialGradient').each(function() {
|
$(svgcontent).find('linearGradient, radialGradient').each(function() {
|
||||||
var grad = this;
|
var grad = this;
|
||||||
|
@ -7825,6 +8016,8 @@ this.setSvgString = function(xmlString) {
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// xmlString - The SVG as XML text.
|
// xmlString - The SVG as XML text.
|
||||||
|
// toElements - Boolean indicating whether or not to convert the SVG to a group
|
||||||
|
// with children
|
||||||
//
|
//
|
||||||
// Returns:
|
// Returns:
|
||||||
// This function returns false if the import was unsuccessful, true otherwise.
|
// This function returns false if the import was unsuccessful, true otherwise.
|
||||||
|
@ -7836,7 +8029,7 @@ this.setSvgString = function(xmlString) {
|
||||||
// was obtained
|
// was obtained
|
||||||
// * import should happen in top-left of current zoomed viewport
|
// * import should happen in top-left of current zoomed viewport
|
||||||
// * create a new layer for the imported SVG
|
// * create a new layer for the imported SVG
|
||||||
this.importSvgString = function(xmlString) {
|
this.importSvgString = function(xmlString, toElements) {
|
||||||
try {
|
try {
|
||||||
// convert string into XML document
|
// convert string into XML document
|
||||||
var newDoc = Utils.text2xml(xmlString);
|
var newDoc = Utils.text2xml(xmlString);
|
||||||
|
@ -7848,11 +8041,8 @@ this.importSvgString = function(xmlString) {
|
||||||
// import new svg document into our document
|
// import new svg document into our document
|
||||||
var importedNode = svgdoc.importNode(newDoc.documentElement, true);
|
var importedNode = svgdoc.importNode(newDoc.documentElement, true);
|
||||||
|
|
||||||
if (current_layer) {
|
var innerw = convertToNum('width', importedNode.getAttribute("width")),
|
||||||
// TODO: properly handle if width/height are not specified or if in percentages
|
innerh = convertToNum('height', importedNode.getAttribute("height")),
|
||||||
// TODO: properly handle if width/height are in units (px, etc)
|
|
||||||
var innerw = importedNode.getAttribute("width"),
|
|
||||||
innerh = importedNode.getAttribute("height"),
|
|
||||||
innervb = importedNode.getAttribute("viewBox"),
|
innervb = importedNode.getAttribute("viewBox"),
|
||||||
// if no explicit viewbox, create one out of the width and height
|
// if no explicit viewbox, create one out of the width and height
|
||||||
vb = innervb ? innervb.split(" ") : [0,0,innerw,innerh];
|
vb = innervb ? innervb.split(" ") : [0,0,innerw,innerh];
|
||||||
|
@ -7863,6 +8053,7 @@ this.importSvgString = function(xmlString) {
|
||||||
var canvasw = Number(svgcontent.getAttribute("width")),
|
var canvasw = Number(svgcontent.getAttribute("width")),
|
||||||
canvash = Number(svgcontent.getAttribute("height"));
|
canvash = Number(svgcontent.getAttribute("height"));
|
||||||
// imported content should be 1/3 of the canvas on its largest dimension
|
// imported content should be 1/3 of the canvas on its largest dimension
|
||||||
|
|
||||||
if (innerh > innerw) {
|
if (innerh > innerw) {
|
||||||
var ts = "scale(" + (canvash/3)/vb[3] + ")";
|
var ts = "scale(" + (canvash/3)/vb[3] + ")";
|
||||||
}
|
}
|
||||||
|
@ -7873,6 +8064,21 @@ this.importSvgString = function(xmlString) {
|
||||||
// Hack to make recalculateDimensions understand how to scale
|
// Hack to make recalculateDimensions understand how to scale
|
||||||
ts = "translate(0) " + ts + " translate(0)";
|
ts = "translate(0) " + ts + " translate(0)";
|
||||||
|
|
||||||
|
if(!toElements) {
|
||||||
|
var elem = $(importedNode).appendTo(current_layer)[0];
|
||||||
|
groupSvgElem(elem);
|
||||||
|
clearSelection();
|
||||||
|
|
||||||
|
var g = elem.parentNode;
|
||||||
|
|
||||||
|
g.setAttribute("transform", ts);
|
||||||
|
recalculateDimensions(g);
|
||||||
|
|
||||||
|
addToSelection([g]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Find way to add this in a recalculateDimensions-parsable way
|
// TODO: Find way to add this in a recalculateDimensions-parsable way
|
||||||
// if (vb[0] != 0 || vb[1] != 0)
|
// if (vb[0] != 0 || vb[1] != 0)
|
||||||
// ts = "translate(" + (-vb[0]) + "," + (-vb[1]) + ") " + ts;
|
// ts = "translate(" + (-vb[0]) + "," + (-vb[1]) + ") " + ts;
|
||||||
|
@ -7884,93 +8090,12 @@ this.importSvgString = function(xmlString) {
|
||||||
if (ts)
|
if (ts)
|
||||||
g.setAttribute("transform", ts);
|
g.setAttribute("transform", ts);
|
||||||
|
|
||||||
// now ensure each element has a unique ID
|
uniquifyElems(g);
|
||||||
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
|
// now give the g itself a new id
|
||||||
|
|
||||||
g.id = getNextId();
|
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);
|
||||||
}
|
|
||||||
|
|
||||||
// change image href vals if possible
|
// change image href vals if possible
|
||||||
// $(svgcontent).find('image').each(function() {
|
// $(svgcontent).find('image').each(function() {
|
||||||
|
@ -8036,6 +8161,12 @@ var identifyLayers = function() {
|
||||||
if (child && child.nodeType == 1) {
|
if (child && child.nodeType == 1) {
|
||||||
if (child.tagName == "g") {
|
if (child.tagName == "g") {
|
||||||
var name = $("title",child).text();
|
var name = $("title",child).text();
|
||||||
|
|
||||||
|
// Hack for Opera 10.60
|
||||||
|
if(!name && isOpera && child.querySelectorAll) {
|
||||||
|
name = $(child.querySelectorAll('title')).text();
|
||||||
|
}
|
||||||
|
|
||||||
// store layer and name in global variable
|
// store layer and name in global variable
|
||||||
if (name) {
|
if (name) {
|
||||||
layernames.push(name);
|
layernames.push(name);
|
||||||
|
|
Loading…
Reference in New Issue