svgtopy.py
1 # SPDX-FileCopyrightText: 2019 Kevin J. Walters for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 #!/usr/bin/python3 6 7 ### svgtopy v1.0 8 """Print vectors from an SVG input file in python list format 9 for easy pasting into a program. 10 11 This is Python code not intended for running on a microcontroller board. 12 """ 13 14 ### MIT License 15 16 ### Copyright (c) 2019 Kevin J. Walters 17 18 ### Permission is hereby granted, free of charge, to any person obtaining a copy 19 ### of this software and associated documentation files (the "Software"), to deal 20 ### in the Software without restriction, including without limitation the rights 21 ### to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 ### copies of the Software, and to permit persons to whom the Software is 23 ### furnished to do so, subject to the following conditions: 24 25 ### The above copyright notice and this permission notice shall be included in all 26 ### copies or substantial portions of the Software. 27 28 ### THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 ### IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 ### FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 ### AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 ### LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 ### OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 ### SOFTWARE. 35 36 37 ### it only understands M and L in SVG 38 39 ### Worth looking at SVG libraries to see if they 40 ### can parse/transform SVG data 41 42 import getopt 43 import sys 44 import re 45 ##import fileinput 46 import xml.etree.ElementTree as ET 47 48 ### globals 49 ### pylint: disable=invalid-name 50 debug = 0 51 verbose = False 52 53 54 def usage(exit_code): ### pylint: disable=missing-docstring 55 print("""Usage: svgtopy [-d] [-h] [-v] [--help] 56 Convert an svg file from from standard input to comma-separated tuples 57 on standard output for inclusion as a list in a python program.""", 58 file=sys.stderr) 59 if exit_code is not None: 60 sys.exit(exit_code) 61 62 63 def search_path_d(svgdata, point_groups): 64 """Look for M and L in the SVG d attribute of a path node""" 65 66 points = [] 67 for match in re.finditer(r"([A-Za-z])([\d\.]+)\s+([\d\.]+)\s*", svgdata): 68 if match: 69 cmd = match.group(1) 70 if cmd == "M": ### Start of a new part 71 mx, my = match.group(2, 3) 72 if points: 73 point_groups.append(points) 74 points = [] 75 points.append((float(mx), float(my))) 76 if debug: 77 print("M pos", mx, my) 78 79 elif cmd == "L": ### Continuation of current part 80 lx, ly = match.group(2, 3) 81 points.append((float(lx), float(ly))) 82 if debug: 83 print("L pos", lx, ly) 84 85 else: 86 print("SVG cmd not implemented:", cmd, 87 file=sys.stderr) 88 else: 89 print("some parsing issue", 90 file=sys.stderr) 91 92 # Add the last part to point_groups 93 if points: 94 point_groups.append(points) 95 points = [] 96 97 98 def main(cmdlineargs): 99 """main(args)""" 100 global debug, verbose ### pylint: disable=global-statement 101 102 try: 103 opts, _ = getopt.getopt(cmdlineargs, 104 "dhv", ["help"]) 105 except getopt.GetoptError as err: 106 print(err, 107 file=sys.stderr) 108 usage(2) 109 for opt, _ in opts: 110 if opt == "-d": 111 debug = True 112 elif opt == "-v": 113 verbose = True 114 elif opt in ("-h", "--help"): 115 usage(0) 116 else: 117 print("Internal error: unhandled option", 118 file=sys.stderr) 119 sys.exit(3) 120 121 xml_ns = {"svg": "http://www.w3.org/2000/svg"} 122 tree = ET.parse(sys.stdin) 123 point_groups = [] 124 for path in tree.findall("svg:path", xml_ns): 125 svgdata = path.attrib["d"] 126 if verbose: 127 print("Processing path with {0:d} length".format(len(svgdata))) 128 search_path_d(svgdata, point_groups) 129 130 131 132 for idx, points in enumerate(point_groups): 133 print("# Group", idx + 1) 134 for point in points: 135 print(" ", point, ",", sep="") 136 137 if __name__ == "__main__": 138 main(sys.argv[1:])