Make sure that the default SVG settings are not lost on import.

This commit is contained in:
Jürg Lehni 2013-11-01 19:00:37 +01:00
parent 9b75362f3e
commit 4b97d3a6e0

View file

@ -71,7 +71,7 @@ new function() {
// Importer functions for various SVG node types // Importer functions for various SVG node types
function importGroup(node, type, options) { function importGroup(node, type, isRoot, options) {
var nodes = node.childNodes, var nodes = node.childNodes,
clip = type === 'clippath', clip = type === 'clippath',
item = new Group(), item = new Group(),
@ -82,7 +82,7 @@ new function() {
// Have the group not pass on all transformations to its children, // Have the group not pass on all transformations to its children,
// as this is how SVG works too. // as this is how SVG works too.
item._transformContent = false; item._transformContent = false;
item = applyAttributes(item, node); item = applyAttributes(item, node, isRoot);
// Style on items needs to be handled differently than all other // Style on items needs to be handled differently than all other
// items: We first apply the style to the item, then use it as the // items: We first apply the style to the item, then use it as the
// project's currentStyle, so it is used as a default for the // project's currentStyle, so it is used as a default for the
@ -95,7 +95,7 @@ new function() {
var childNode = nodes[i], var childNode = nodes[i],
child; child;
if (childNode.nodeType === 1 if (childNode.nodeType === 1
&& (child = importSVG(childNode, options)) && (child = importSVG(childNode, false, options))
&& !(child instanceof Symbol)) && !(child instanceof Symbol))
children.push(child); children.push(child);
} }
@ -103,7 +103,7 @@ new function() {
// Clip paths are reduced (unboxed) and their attributes applied at the // Clip paths are reduced (unboxed) and their attributes applied at the
// end. // end.
if (clip) if (clip)
item = applyAttributes(item.reduce(), node); item = applyAttributes(item.reduce(), node, isRoot);
// Restore currentStyle // Restore currentStyle
project._currentStyle = currentStyle; project._currentStyle = currentStyle;
if (clip || type === 'defs') { if (clip || type === 'defs') {
@ -166,8 +166,8 @@ new function() {
// NOTE: All importers are lowercase, since jsdom is using uppercase // NOTE: All importers are lowercase, since jsdom is using uppercase
// nodeNames still. // nodeNames still.
var importers = { var importers = {
'#document': function(node, type, options) { '#document': function(node, type, isRoot, options) {
return importSVG(node.childNodes[0], options); return importSVG(node.childNodes[0], isRoot, options);
}, },
// http://www.w3.org/TR/SVG/struct.html#Groups // http://www.w3.org/TR/SVG/struct.html#Groups
@ -200,9 +200,9 @@ new function() {
}, },
// http://www.w3.org/TR/SVG/struct.html#SymbolElement // http://www.w3.org/TR/SVG/struct.html#SymbolElement
symbol: function(node, type) { symbol: function(node, type, isRoot, options) {
// Pass true for dontCenter: // Pass true for dontCenter:
return new Symbol(importGroup(node, type), true); return new Symbol(importGroup(node, type, isRoot, options), true);
}, },
// http://www.w3.org/TR/SVG/struct.html#DefsElement // http://www.w3.org/TR/SVG/struct.html#DefsElement
@ -337,13 +337,12 @@ new function() {
// can affect gradient fills. // can affect gradient fills.
var attributes = Base.merge(Base.each(SVGStyles, function(entry) { var attributes = Base.merge(Base.each(SVGStyles, function(entry) {
this[entry.attribute] = function(item, value) { this[entry.attribute] = function(item, value) {
item[entry.set]( item[entry.set](convertValue(value, entry.type, entry.fromSVG));
convertValue(value, entry.type, entry.fromSVG)); // When applying gradient colors to shapes, we need to offset
// When applying gradient colors to shapes, we need to offset the // the shape's initial position to get the same results as SVG.
// shape's initial position to get the same results as SVG.
if (entry.type === 'color' && item instanceof Shape) { if (entry.type === 'color' && item instanceof Shape) {
// Do not use result of convertValue() above, since calling the // Do not use result of convertValue() above, since calling
// setter will produce a new cloned color. // the setter will produce a new cloned color.
var color = item[entry.get](); var color = item[entry.get]();
if (color) if (color)
color.transform(new Matrix().translate( color.transform(new Matrix().translate(
@ -466,12 +465,14 @@ new function() {
* @param {SVGSVGElement} node an SVG node to read style and attributes from. * @param {SVGSVGElement} node an SVG node to read style and attributes from.
* @param {Item} item the item to apply the style and attributes to. * @param {Item} item the item to apply the style and attributes to.
*/ */
function applyAttributes(item, node) { function applyAttributes(item, node, isRoot) {
// SVG attributes can be set both as styles and direct node attributes, // SVG attributes can be set both as styles and direct node attributes,
// so we need to handle both. // so we need to handle both.
var styles = { var styles = {
node: DomElement.getStyles(node) || {}, node: DomElement.getStyles(node) || {},
parent: DomElement.getStyles(node.parentNode) || {} // Do not check for inheritance if this is the root, since we want
// the default SVG settings to stick.
parent: !isRoot && DomElement.getStyles(node.parentNode) || {}
}; };
Base.each(attributes, function(apply, name) { Base.each(attributes, function(apply, name) {
var value = getAttribute(node, name, styles); var value = getAttribute(node, name, styles);
@ -489,7 +490,7 @@ new function() {
return match && definitions[match[1]]; return match && definitions[match[1]];
} }
function importSVG(node, options, clearDefs) { function importSVG(node, isRoot, options) {
if (!options) if (!options)
options = {}; options = {};
if (typeof node === 'string') if (typeof node === 'string')
@ -497,12 +498,12 @@ new function() {
// jsdom in Node.js uses uppercase values for nodeName... // jsdom in Node.js uses uppercase values for nodeName...
var type = node.nodeName.toLowerCase(), var type = node.nodeName.toLowerCase(),
importer = importers[type], importer = importers[type],
item = importer && importer(node, type, options), item = importer && importer(node, type, isRoot, options),
data = type !== '#document' && node.getAttribute('data-paper-data'); data = type !== '#document' && node.getAttribute('data-paper-data');
if (item) { if (item) {
// See importGroup() for an explanation of this filtering: // See importGroup() for an explanation of this filtering:
if (!(item instanceof Group)) if (!(item instanceof Group))
item = applyAttributes(item, node); item = applyAttributes(item, node, isRoot);
if (options.expandShapes && item instanceof Shape) { if (options.expandShapes && item instanceof Shape) {
item.remove(); item.remove();
item = item.toPath(); item = item.toPath();
@ -511,21 +512,21 @@ new function() {
item._data = JSON.parse(data); item._data = JSON.parse(data);
} }
// Clear definitions at the end of import? // Clear definitions at the end of import?
if (clearDefs) if (isRoot)
definitions = {}; definitions = {};
return item; return item;
} }
Item.inject({ Item.inject({
importSVG: function(node, options) { importSVG: function(node, options) {
return this.addChild(importSVG(node, options, true)); return this.addChild(importSVG(node, true, options));
} }
}); });
Project.inject({ Project.inject({
importSVG: function(node, options) { importSVG: function(node, options) {
this.activate(); this.activate();
return importSVG(node, options, true); return importSVG(node, true, options);
} }
}); });
}; };