From 15d186ff33af1f9bfbe1f2ea9e36a9d61ad3ff68 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 15 Jul 2016 22:10:59 -0700 Subject: [PATCH] add ability to preserve svg-attributes Added svg_attributes attribute to wsvg and disvg. Added return_svg_attributes option to svg2paths. Added convenience function svg2paths2(). --- README.ipynb | 35 ++++++++++++++----------- README.rst | 7 ++++- output1.svg | 2 +- setup.py | 2 +- svgpathtools/__init__.py | 2 +- svgpathtools/paths2svg.py | 20 +++++++++----- svgpathtools/svg2paths.py | 55 +++++++++++++++++++++++++++++++++------ 7 files changed, 89 insertions(+), 34 deletions(-) diff --git a/README.ipynb b/README.ipynb index 9d9b225..d3d563c 100644 --- a/README.ipynb +++ b/README.ipynb @@ -86,7 +86,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 5, "metadata": { "collapsed": true }, @@ -97,7 +97,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 6, "metadata": { "collapsed": false }, @@ -147,7 +147,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 7, "metadata": { "collapsed": false }, @@ -224,7 +224,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 8, "metadata": { "collapsed": false }, @@ -244,6 +244,11 @@ "from svgpathtools import svg2paths, wsvg\n", "paths, attributes = svg2paths('test.svg')\n", "\n", + "# Update: You can now also extract the svg-attributes by setting\n", + "# return_svg_attributes=True, or with the convenience function svg2paths2\n", + "from svgpathtools import svg2paths2\n", + "paths, attributes, svg_attributes = svg2paths2('test.svg')\n", + "\n", "# Let's print out the first path object and the color it was in the SVG\n", "# We'll see it is composed of two CubicBezier objects and, in the SVG file it \n", "# came from, it was red\n", @@ -265,14 +270,14 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Let's make a new SVG that's identical to the first\n", - "wsvg(paths, attributes=attributes, filename='output1.svg')" + "wsvg(paths, attributes=attributes, svg_attributes=svg_attributes, filename='output1.svg')" ] }, { @@ -300,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 10, "metadata": { "collapsed": false }, @@ -363,7 +368,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 11, "metadata": { "collapsed": false }, @@ -411,7 +416,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 12, "metadata": { "collapsed": false }, @@ -466,7 +471,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 13, "metadata": { "collapsed": false }, @@ -509,7 +514,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 14, "metadata": { "collapsed": false }, @@ -551,7 +556,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 15, "metadata": { "collapsed": false }, @@ -606,7 +611,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 16, "metadata": { "collapsed": false }, @@ -641,7 +646,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 17, "metadata": { "collapsed": false }, @@ -734,7 +739,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.11" + "version": "2.7.12" } }, "nbformat": 4, diff --git a/README.rst b/README.rst index e581f46..6c99e3d 100644 --- a/README.rst +++ b/README.rst @@ -225,6 +225,11 @@ Reading SVGSs from svgpathtools import svg2paths, wsvg paths, attributes = svg2paths('test.svg') + # Update: You can now also extract the svg-attributes by setting + # return_svg_attributes=True, or with the convenience function svg2paths2 + from svgpathtools import svg2paths2 + paths, attributes, svg_attributes = svg2paths2('test.svg') + # Let's print out the first path object and the color it was in the SVG # We'll see it is composed of two CubicBezier objects and, in the SVG file it # came from, it was red @@ -254,7 +259,7 @@ viewer. .. code:: python # Let's make a new SVG that's identical to the first - wsvg(paths, attributes=attributes, filename='output1.svg') + wsvg(paths, attributes=attributes, svg_attributes=svg_attributes, filename='output1.svg') .. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/output1.svg :alt: output1.svg diff --git a/output1.svg b/output1.svg index 6cf4ff8..f27f28c 100644 --- a/output1.svg +++ b/output1.svg @@ -1,5 +1,5 @@ - + diff --git a/setup.py b/setup.py index 5f34583..9bf7c3f 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from distutils.core import setup -VERSION = '1.0.1' +VERSION = '1.1' AUTHOR_NAME = 'Andy Port' AUTHOR_EMAIL = 'AndyAPort@gmail.com' diff --git a/svgpathtools/__init__.py b/svgpathtools/__init__.py index fe52bc0..d0ef37b 100644 --- a/svgpathtools/__init__.py +++ b/svgpathtools/__init__.py @@ -14,6 +14,6 @@ from .misctools import hex2rgb, rgb2hex from .smoothing import smoothed_path, smoothed_joint, is_differentiable, kinks try: - from .svg2paths import svg2paths + from .svg2paths import svg2paths, svg2paths2 except ImportError: pass \ No newline at end of file diff --git a/svgpathtools/paths2svg.py b/svgpathtools/paths2svg.py index 0ec0f9a..a4ae48b 100644 --- a/svgpathtools/paths2svg.py +++ b/svgpathtools/paths2svg.py @@ -88,7 +88,7 @@ def disvg(paths=None, colors=None, openinbrowser=True, timestamp=False, margin_size=0.1, mindim=600, dimensions=None, viewbox=None, text=None, text_path=None, font_size=None, - attributes=None): + attributes=None, svg_attributes=None): """Takes in a list of paths and creates an SVG file containing said paths. REQUIRED INPUTS: :param paths - a list of paths @@ -148,8 +148,11 @@ def disvg(paths=None, colors=None, (min_x, min_y, width, height). This is different from the display dimension of the svg, which can be set through mindim or dimensions. - :param attributes - a dictionary of attributes for the input paths. - This will override any other conflicting settings. + :param attributes - a list of dictionaries of attributes for the input + paths. Note: This will override any other conflicting settings. + + :param svg_attributes - a dictionary of attributes for output svg. + Note: This will override any other conflicting settings. NOTES: -The unit of length here is assumed to be pixels in all variables. @@ -272,7 +275,10 @@ def disvg(paths=None, colors=None, szy = str(mindim) + 'px' # Create an SVG file - dwg = Drawing(filename=filename, size=(szx, szy), viewBox=viewbox) + if svg_attributes: + dwg = Drawing(filename=filename, **svg_attributes) + else: + dwg = Drawing(filename=filename, size=(szx, szy), viewBox=viewbox) # add paths if paths: @@ -367,7 +373,7 @@ def wsvg(paths=None, colors=None, openinbrowser=False, timestamp=False, margin_size=0.1, mindim=600, dimensions=None, viewbox=None, text=None, text_path=None, font_size=None, - attributes=None): + attributes=None, svg_attributes=None): """Convenience function; identical to disvg() except that openinbrowser=False by default. See disvg() docstring for more info.""" disvg(paths, colors=colors, filename=filename, @@ -375,5 +381,5 @@ def wsvg(paths=None, colors=None, node_colors=node_colors, node_radii=node_radii, openinbrowser=openinbrowser, timestamp=timestamp, margin_size=margin_size, mindim=mindim, dimensions=dimensions, - viewbox=viewbox, text=text, text_path=text_path, - font_size=font_size, attributes=attributes) + viewbox=viewbox, text=text, text_path=text_path, font_size=font_size, + attributes=attributes, svg_attributes=svg_attributes) diff --git a/svgpathtools/svg2paths.py b/svgpathtools/svg2paths.py index f5f465f..c3b66f9 100644 --- a/svgpathtools/svg2paths.py +++ b/svgpathtools/svg2paths.py @@ -5,6 +5,7 @@ The main tool being the svg2paths() function.""" from __future__ import division, absolute_import, print_function from xml.dom.minidom import parse from os import path as os_path, getcwd +from shutil import copyfile # Internal dependencies from .parser import parse_path @@ -31,9 +32,10 @@ def polyline2pathd(polyline_d): def svg2paths(svg_file_location, - convert_lines_to_paths=True, - convert_polylines_to_paths=True, - convert_polygons_to_paths=True): + convert_lines_to_paths=True, + convert_polylines_to_paths=True, + convert_polygons_to_paths=True, + return_svg_attributes=False): """ Converts an SVG file into a list of Path objects and a list of dictionaries containing their attributes. This currently supports @@ -45,12 +47,20 @@ def svg2paths(svg_file_location, objects (converted to Paths) :param convert_polygons_to_paths: Set to False to disclude SVG-Polygon objects (converted to Paths) - :return: list of Path objects + :param return_svg_attributes: Set to True and a dictionary of + svg-attributes will be extracted and returned + :return: list of Path objects, list of path attribute dictionaries, and + (optionally) a dictionary of svg-attributes + """ if os_path.dirname(svg_file_location) == '': svg_file_location = os_path.join(getcwd(), svg_file_location) - doc = parse(svg_file_location) # parseString also exists + # if pathless_svg: + # copyfile(svg_file_location, pathless_svg) + # doc = parse(pathless_svg) + # else: + doc = parse(svg_file_location) def dom2dict(element): """Converts DOM elements to dictionaries of attributes.""" @@ -62,6 +72,9 @@ def svg2paths(svg_file_location, paths = [dom2dict(el) for el in doc.getElementsByTagName('path')] d_strings = [el['d'] for el in paths] attribute_dictionary_list = paths + # if pathless_svg: + # for el in doc.getElementsByTagName('path'): + # el.parentNode.removeChild(el) # Use minidom to extract polyline strings from input SVG, convert to # path strings, add to list @@ -82,6 +95,32 @@ def svg2paths(svg_file_location, d_strings += [('M' + l['x1'] + ' ' + l['y1'] + 'L' + l['x2'] + ' ' + l['y2']) for l in lines] attribute_dictionary_list += lines - doc.unlink() - path_list = [parse_path(d) for d in d_strings] - return path_list, attribute_dictionary_list + + # if pathless_svg: + # with open(pathless_svg, "wb") as f: + # doc.writexml(f) + + if return_svg_attributes: + svg_attributes = dom2dict(doc.getElementsByTagName('svg')[0]) + doc.unlink() + path_list = [parse_path(d) for d in d_strings] + return path_list, attribute_dictionary_list, svg_attributes + else: + doc.unlink() + path_list = [parse_path(d) for d in d_strings] + return path_list, attribute_dictionary_list + + +def svg2paths2(svg_file_location, + convert_lines_to_paths=True, + convert_polylines_to_paths=True, + convert_polygons_to_paths=True, + return_svg_attributes=True): + """Convenience function; identical to svg2paths() except that + return_svg_attributes=True by default. See svg2paths() docstring for more + info.""" + return svg2paths(svg_file_location=svg_file_location, + convert_lines_to_paths=convert_lines_to_paths, + convert_polylines_to_paths=convert_polylines_to_paths, + convert_polygons_to_paths=convert_polygons_to_paths, + return_svg_attributes=return_svg_attributes)