Przeglądaj źródła

add support for svg <use> (inkscape "clone")

Mike Smith 6 lat temu
rodzic
commit
4fc3d1183b
2 zmienionych plików z 115 dodań i 2 usunięć
  1. 14 2
      flatcamParsers/ParseSVG.py
  2. 101 0
      tests/svg/use.svg

+ 14 - 2
flatcamParsers/ParseSVG.py

@@ -284,7 +284,7 @@ def svgpolygon2shapely(polygon):
     # return LinearRing(points)
 
 
-def getsvggeo(node, object_type):
+def getsvggeo(node, object_type, root = None):
     """
     Extracts and flattens all geometry from an SVG node
     into a list of Shapely geometry.
@@ -293,13 +293,16 @@ def getsvggeo(node, object_type):
     :return: List of Shapely geometry
     :rtype: list
     """
+    if root is None:
+        root = node
+
     kind = re.search('(?:\{.*\})?(.*)$', node.tag).group(1)
     geo = []
 
     # Recurse
     if len(node) > 0:
         for child in node:
-            subgeo = getsvggeo(child, object_type)
+            subgeo = getsvggeo(child, object_type, root)
             if subgeo is not None:
                 geo += subgeo
 
@@ -341,6 +344,15 @@ def getsvggeo(node, object_type):
         pline = svgpolyline2shapely(node)
         geo = [pline]
 
+    elif kind == 'use':
+        log.debug('***USE***')
+        # href= is the preferred name for this[1], but inkscape still generates xlink:href=.
+        # [1] https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use#Attributes
+        href = node.attrib['href'] if 'href' in node.attrib else node.attrib['{http://www.w3.org/1999/xlink}href']
+        ref = root.find(".//*[@id='%s']" % href.replace('#', ''))
+        if ref is not None:
+            geo = getsvggeo(ref, object_type, root)
+
     else:
         log.warning("Unknown kind: " + kind)
         geo = None

+ 101 - 0
tests/svg/use.svg

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="50mm"
+   height="50mm"
+   viewBox="0 0 50 50"
+   version="1.1"
+   id="svg8"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14"
+   sodipodi:docname="use.svg">
+  <defs
+     id="defs2" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.4679048"
+     inkscape:cx="113.26276"
+     inkscape:cy="109.86475"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="3834"
+     inkscape:window-height="2095"
+     inkscape:window-x="0"
+     inkscape:window-y="28"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-247)">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 6.2421073,283.98351 c -2.4960796,-5.97466 14.6658087,-0.0283 2.7443869,-28.40936 -2.6185936,-6.23403 13.3146118,1.40862 15.4980508,1.40862"
+       id="path815"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csc" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#path815"
+       id="use817"
+       transform="matrix(-1,0,0,1,48.96909,0)"
+       width="100%"
+       height="100%" />
+    <rect
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
+       id="rect942"
+       width="4.3065705"
+       height="4.7904549"
+       x="13.742314"
+       y="288.14493" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#rect942"
+       id="use944"
+       transform="matrix(2.4752181,0,0,1.0534789,-4.8199296,-20.27984)"
+       width="100%"
+       height="100%" />
+    <circle
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
+       id="path948"
+       cx="18.823099"
+       cy="275.70914"
+       r="4.5485125" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#path948"
+       id="use950"
+       transform="translate(10.50029,-10.984174)"
+       width="100%"
+       height="100%" />
+  </g>
+</svg>