diff --git a/src/item/Item.js b/src/item/Item.js index 95dfd543..3858f3e8 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -1633,11 +1633,15 @@ var Item = Base.extend(Callback, /** @lends Item# */{ }; }, /** @lends Item# */{ /** - * {@grouptitle Importing To / Exporting From JSON & SVG} + * {@grouptitle Importing / Exporting JSON and SVG} * * Exports (serializes) the item with its content and child items to a JSON * data string. * + * The options object offers control over some aspects of the SVG export: + * options.precision: {@code Number} – the amount of fractional + * digits in numbers used in JSON data. + * * @name Item#exportJSON * @function * @param {Object} [options={ precision: 5 }] the serialization options @@ -1646,8 +1650,9 @@ var Item = Base.extend(Callback, /** @lends Item# */{ /** * Imports (deserializes) the stored JSON data into this item's - * {@link Item#children} list. Note that the item is not cleared first. - * You can call {@link Item#removeChildren()} to do so. + * {@link Item#children} list. + * Note that the item is not cleared first. You can call + * {@link Item#removeChildren()} to do so. * * @param {String} json the JSON data to import from. */ @@ -1658,20 +1663,36 @@ var Item = Base.extend(Callback, /** @lends Item# */{ /** * Exports the item with its content and child items as an SVG DOM. * + * The options object offers control over some aspects of the SVG export: + * options.asString: {@code Boolean} – wether a SVG node or a String + * is to be returned. + * options.precision: {@code Number} – the amount of fractional + * digits in numbers used in SVG data. + * options.matchShapes: {@code Boolean} – wether imported path + * items should tried to be converted to shape items, if their geometries + * match. + * * @name Item#exportSVG * @function - * @param {Object} [options={ asString: false, precision: 5 }] the export - * options. + * @param {Object} [options={ asString: false, precision: 5, + * matchShapes: false }] the export options. * @return {SVGSVGElement} the item converted to an SVG node */ /** * Converts the provided SVG content into Paper.js items and adds them to * the this item's children list. + * Note that the item is not cleared first. You can call + * {@link Item#removeChildren()} to do so. + * + * The options object offers control over some aspects of the SVG import: + * options.expandShapes: {@code Boolean} – wether imported shape + * items should be expanded to path items. * * @name Item#importSVG * @function * @param {SVGSVGElement|String} svg the SVG content to import + * @param {Object} [options={ expandShapes: false }] the import options * @return {Item} the imported Paper.js parent item */ diff --git a/src/project/Project.js b/src/project/Project.js index f3bd6d09..e2741a4d 100644 --- a/src/project/Project.js +++ b/src/project/Project.js @@ -292,11 +292,15 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{ }; }, /** @lends Project# */{ /** - * {@grouptitle Importing To / Exporting From JSON & SVG} + * {@grouptitle Importing / Exporting JSON and SVG} * * Exports (serializes) the project with all its layers and child items to * a JSON data string. * + * The options object offers control over some aspects of the SVG export: + * options.precision: {@code Number} – the amount of fractional + * digits in numbers used in JSON data. + * * @name Project#exportJSON * @function * @param {Object} [options={ precision: 5 }] the serialization options @@ -304,9 +308,9 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{ */ /** - * Imports (deserializes) the stored JSON data into the project. Note that - * the project is not cleared first. You can call {@link Project#clear()} to - * do so. + * Imports (deserializes) the stored JSON data into the project. + * Note that the project is not cleared first. You can call + * {@link Project#clear()} to do so. * * @param {String} json the JSON data to import from. */ @@ -319,20 +323,36 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{ * Exports the project with all its layers and child items as an SVG DOM, * all contained in one top level SVG group node. * + * The options object offers control over some aspects of the SVG export: + * options.asString: {@code Boolean} – wether a SVG node or a String + * is to be returned. + * options.precision: {@code Number} – the amount of fractional + * digits in numbers used in SVG data. + * options.matchShapes: {@code Boolean} – wether imported path + * items should tried to be converted to shape items, if their geometries + * match. + * * @name Project#exportSVG * @function - * @param {Object} [options={ asString: false, precision: 5 }] the export - * options. + * @param {Object} [options={ asString: false, precision: 5, + * matchShapes: false }] the export options. * @return {SVGSVGElement} the project converted to an SVG node */ /** * Converts the provided SVG content into Paper.js items and adds them to * the active layer of this project. + * Note that the project is not cleared first. You can call + * {@link Project#clear()} to do so. + * + * The options object offers control over some aspects of the SVG import: + * options.expandShapes: {@code Boolean} – wether imported shape + * items should be expanded to path items. * * @name Project#importSVG * @function * @param {SVGSVGElement|String} svg the SVG content to import + * @param {Object} [options={ expandShapes: false }] the import options * @return {Item} the imported Paper.js parent item */ diff --git a/src/svg/SVGExport.js b/src/svg/SVGExport.js index 52affd13..11ccc42a 100644 --- a/src/svg/SVGExport.js +++ b/src/svg/SVGExport.js @@ -15,6 +15,7 @@ * Paper.js DOM to a SVG DOM. */ new function() { + // TODO: Consider moving formatter into options object, and pass it along. var formatter; function setAttributes(node, attrs) { @@ -76,13 +77,13 @@ new function() { return attrs; } - function exportGroup(item) { + function exportGroup(item, options) { var attrs = getTransform(item), children = item._children; var node = createElement('g', attrs); for (var i = 0, l = children.length; i < l; i++) { var child = children[i]; - var childNode = exportSVG(child); + var childNode = exportSVG(child, options); if (childNode) { if (child.isClipMask()) { var clip = createElement('clipPath'); @@ -111,7 +112,12 @@ new function() { return createElement('image', attrs); } - function exportPath(item) { + function exportPath(item, options) { + if (options.matchShapes) { + var shape = item.toShape(false); + if (shape) + return exportShape(shape, options); + } var segments = item._segments, type, attrs; @@ -180,7 +186,7 @@ new function() { return createElement('path', attrs); } - function exportPlacedSymbol(item) { + function exportPlacedSymbol(item, options) { var attrs = getTransform(item, true), symbol = item.getSymbol(), symbolNode = getDefinition(symbol, 'symbol'), @@ -190,7 +196,7 @@ new function() { symbolNode = createElement('symbol', { viewBox: formatter.rectangle(bounds) }); - symbolNode.appendChild(exportSVG(definition)); + symbolNode.appendChild(exportSVG(definition, options)); setDefinition(symbol, symbolNode, 'symbol'); } attrs.href = '#' + symbolNode.id; @@ -369,9 +375,9 @@ new function() { : svg; } - function exportSVG(item) { + function exportSVG(item, options) { var exporter = exporters[item._type], - node = exporter && exporter(item, item._type); + node = exporter && exporter(item, options); if (node && item._data) node.setAttribute('data-paper-data', JSON.stringify(item._data)); return node && applyStyle(item, node); @@ -387,7 +393,7 @@ new function() { Item.inject({ exportSVG: function(options) { options = setOptions(options); - return exportDefinitions(exportSVG(this), options); + return exportDefinitions(exportSVG(this, options), options); } }); @@ -406,7 +412,7 @@ new function() { 'xmlns:xlink': 'http://www.w3.org/1999/xlink' }); for (var i = 0, l = layers.length; i < l; i++) - node.appendChild(exportSVG(layers[i])); + node.appendChild(exportSVG(layers[i], options)); return exportDefinitions(node, options); } });