def recursiveFuseTransform(self, node, transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): transf = Transform(transf) * Transform(node.get("transform", None)) if 'transform' in node.attrib: del node.attrib['transform'] node = ApplyTransform.objectToPath(node) if 'd' in node.attrib: d = node.get('d') p = CubicSuperPath(d) p = Path(p).to_absolute().transform(transf, True) node.set('d', Path(CubicSuperPath(p).to_path())) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS('polygon', 'svg'), inkex.addNS('polyline', 'svg') ]: points = node.get('points') points = points.strip().split(' ') for k, p in enumerate(points): if ',' in p: p = p.split(',') p = [float(p[0]), float(p[1])] applyTransformToPoint(transf, p) p = [str(p[0]), str(p[1])] p = ','.join(p) points[k] = p points = ' '.join(points) node.set('points', points) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS('rect', 'svg'), inkex.addNS('text', 'svg'), inkex.addNS('image', 'svg'), inkex.addNS('use', 'svg'), inkex.addNS('circle', 'svg') ]: # node.set('transform', str(Transform(transf))) inkex.utils.errormsg("Shape %s not yet supported" % node.tag) else: # e.g. <g style="..."> self.scaleStrokeWidth(node, transf) for child in node.getchildren(): self.recursiveFuseTransform(child, transf)
def recursiveFuseTransform(self, node, transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): # Modification by David Burghoff: # Since transforms apply to an object's clips, before applying the transform # we will need to duplicate the clip path and transform it clippathurl = node.get('clip-path') if clippathurl is not None and node.get("transform") is not None: myn = node while not (myn.getparent() == None): # get svg handle myn = myn.getparent() svg = myn clippath = svg.getElementById(clippathurl[5:-1]) if clippath is not None: d = clippath.duplicate() clippathurl = "url(#" + d.get("id") + ")" node.set("clip-path", clippathurl) for k in d.getchildren(): if k.get('transform') is not None: tr = Transform(node.get("transform")) * Transform( k.get('transform')) else: tr = Transform(node.get("transform")) k.set('transform', tr) transf = Transform(transf) * Transform(node.get("transform", None)) if 'transform' in node.attrib: del node.attrib['transform'] node = ApplyTransform.objectToPath(node) if transf == NULL_TRANSFORM: # Don't do anything if there is effectively no transform applied # reduces alerts for unsupported nodes pass elif 'd' in node.attrib: d = node.get('d') p = CubicSuperPath(d) p = Path(p).to_absolute().transform(transf, True) node.set('d', str(Path(CubicSuperPath(p).to_path()))) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS('polygon', 'svg'), inkex.addNS('polyline', 'svg') ]: points = node.get('points') points = points.strip().split(' ') for k, p in enumerate(points): if ',' in p: p = p.split(',') p = [float(p[0]), float(p[1])] p = transf.apply_to_point(p) p = [str(p[0]), str(p[1])] p = ','.join(p) points[k] = p points = ' '.join(points) node.set('points', points) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS("ellipse", "svg"), inkex.addNS("circle", "svg") ]: def isequal(a, b): return abs(a - b) <= transf.absolute_tolerance if node.TAG == "ellipse": rx = float(node.get("rx")) ry = float(node.get("ry")) else: rx = float(node.get("r")) ry = rx cx = float(node.get("cx")) cy = float(node.get("cy")) sqxy1 = (cx - rx, cy - ry) sqxy2 = (cx + rx, cy - ry) sqxy3 = (cx + rx, cy + ry) newxy1 = transf.apply_to_point(sqxy1) newxy2 = transf.apply_to_point(sqxy2) newxy3 = transf.apply_to_point(sqxy3) node.set("cx", (newxy1[0] + newxy3[0]) / 2) node.set("cy", (newxy1[1] + newxy3[1]) / 2) edgex = math.sqrt( abs(newxy1[0] - newxy2[0])**2 + abs(newxy1[1] - newxy2[1])**2) edgey = math.sqrt( abs(newxy2[0] - newxy3[0])**2 + abs(newxy2[1] - newxy3[1])**2) if not isequal(edgex, edgey) and ( node.TAG == "circle" or not isequal(newxy2[0], newxy3[0]) or not isequal(newxy1[1], newxy2[1])): inkex.utils.errormsg( "Warning: Shape %s (%s) is approximate only, try Object to path first for better results" % (node.TAG, node.get("id"))) if node.TAG == "ellipse": node.set("rx", edgex / 2) node.set("ry", edgey / 2) else: node.set("r", edgex / 2) # Modficiation by David Burghoff: Added support for lines elif node.tag in inkex.addNS('line', 'svg'): x1 = node.get('x1') x2 = node.get('x2') y1 = node.get('y1') y2 = node.get('y2') p1 = transf.apply_to_point([x1, y1]) p2 = transf.apply_to_point([x2, y2]) node.set('x1', str(p1[0])) node.set('y1', str(p1[1])) node.set('x2', str(p2[0])) node.set('y2', str(p2[1])) self.scaleStrokeWidth(node, transf) elif node.typename in ['Rectangle']: x = float(node.get('x')) y = float(node.get('y')) w = float(node.get('width')) h = float(node.get('height')) pts = [[x, y], [x + w, y], [x + w, y + h], [x, y + h], [x, y]] xs = [] ys = [] for p in pts: p = transf.apply_to_point(p) xs.append(p.x) ys.append(p.y) node.set('x', str(min(xs))) node.set('y', str(min(ys))) node.set('width', str(max(xs) - min(xs))) node.set('height', str(max(ys) - min(ys))) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS('text', 'svg'), inkex.addNS('image', 'svg'), inkex.addNS('use', 'svg') ]: inkex.utils.errormsg( "Shape %s (%s) not yet supported, try Object to path first" % (node.TAG, node.get("id"))) else: # e.g. <g style="..."> self.scaleStrokeWidth(node, transf) for child in node.getchildren(): self.recursiveFuseTransform(child, transf)
def recursiveFuseTransform(self, node, transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): transf = Transform(transf) * Transform(node.get("transform", None)) if 'transform' in node.attrib: del node.attrib['transform'] node = ApplyTransform.objectToPath(node) if transf == NULL_TRANSFORM: # Don't do anything if there is effectively no transform applied # reduces alerts for unsupported nodes pass elif 'd' in node.attrib: d = node.get('d') p = CubicSuperPath(d) p = Path(p).to_absolute().transform(transf, True) node.set('d', Path(CubicSuperPath(p).to_path())) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS('polygon', 'svg'), inkex.addNS('polyline', 'svg') ]: points = node.get('points') points = points.strip().split(' ') for k, p in enumerate(points): if ',' in p: p = p.split(',') p = [float(p[0]), float(p[1])] p = transf.apply_to_point(p) p = [str(p[0]), str(p[1])] p = ','.join(p) points[k] = p points = ' '.join(points) node.set('points', points) self.scaleStrokeWidth(node, transf) elif node.tag in [ inkex.addNS("ellipse", "svg"), inkex.addNS("circle", "svg") ]: def isequal(a, b): return abs(a - b) <= transf.absolute_tolerance if node.TAG == "ellipse": rx = float(node.get("rx")) ry = float(node.get("ry")) else: rx = float(node.get("r")) ry = rx cx = float(node.get("cx")) cy = float(node.get("cy")) sqxy1 = (cx - rx, cy - ry) sqxy2 = (cx + rx, cy - ry) sqxy3 = (cx + rx, cy + ry) newxy1 = transf.apply_to_point(sqxy1) newxy2 = transf.apply_to_point(sqxy2) newxy3 = transf.apply_to_point(sqxy3) node.set("cx", (newxy1[0] + newxy3[0]) / 2) node.set("cy", (newxy1[1] + newxy3[1]) / 2) edgex = math.sqrt( abs(newxy1[0] - newxy2[0])**2 + abs(newxy1[1] - newxy2[1])**2) edgey = math.sqrt( abs(newxy2[0] - newxy3[0])**2 + abs(newxy2[1] - newxy3[1])**2) if not isequal(edgex, edgey) and ( node.TAG == "circle" or not isequal(newxy2[0], newxy3[0]) or not isequal(newxy1[1], newxy2[1])): inkex.utils.errormsg( "Warning: Shape %s (%s) is approximate only, try Object to path first for better results" % (node.TAG, node.get("id"))) if node.TAG == "ellipse": node.set("rx", edgex / 2) node.set("ry", edgey / 2) else: node.set("r", edgex / 2) elif node.tag in [ inkex.addNS('rect', 'svg'), inkex.addNS('text', 'svg'), inkex.addNS('image', 'svg'), inkex.addNS('use', 'svg') ]: inkex.utils.errormsg( "Shape %s (%s) not yet supported, try Object to path first" % (node.TAG, node.get("id"))) else: # e.g. <g style="..."> self.scaleStrokeWidth(node, transf) for child in node.getchildren(): self.recursiveFuseTransform(child, transf)
def recursiveFuseTransform(self, element, transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): transf = Transform(transf) * Transform(element.get( "transform", None)) #a, b, c, d = linear transformations / e, f = translations if 'transform' in element.attrib: del element.attrib['transform'] element = ApplyTransform.objectToPath(element) if transf == NULL_TRANSFORM: # Don't do anything if there is effectively no transform applied # reduces alerts for unsupported elements pass elif 'd' in element.attrib: d = element.get('d') p = CubicSuperPath(d) p = Path(p).to_absolute().transform(transf, True) element.set('d', str(Path(CubicSuperPath(p).to_path()))) self.scaleStrokeWidth(element, transf) elif element.tag in [ inkex.addNS('polygon', 'svg'), inkex.addNS('polyline', 'svg') ]: points = element.get('points') points = points.strip().split(' ') for k, p in enumerate(points): if ',' in p: p = p.split(',') p = [float(p[0]), float(p[1])] p = transf.apply_to_point(p) p = [str(p[0]), str(p[1])] p = ','.join(p) points[k] = p points = ' '.join(points) element.set('points', points) self.scaleStrokeWidth(element, transf) elif element.tag in [ inkex.addNS("ellipse", "svg"), inkex.addNS("circle", "svg") ]: def isequal(a, b): return abs(a - b) <= transf.absolute_tolerance if element.TAG == "ellipse": rx = float(element.get("rx")) ry = float(element.get("ry")) else: rx = float(element.get("r")) ry = rx cx = float(element.get("cx")) cy = float(element.get("cy")) sqxy1 = (cx - rx, cy - ry) sqxy2 = (cx + rx, cy - ry) sqxy3 = (cx + rx, cy + ry) newxy1 = transf.apply_to_point(sqxy1) newxy2 = transf.apply_to_point(sqxy2) newxy3 = transf.apply_to_point(sqxy3) element.set("cx", (newxy1[0] + newxy3[0]) / 2) element.set("cy", (newxy1[1] + newxy3[1]) / 2) edgex = math.sqrt( abs(newxy1[0] - newxy2[0])**2 + abs(newxy1[1] - newxy2[1])**2) edgey = math.sqrt( abs(newxy2[0] - newxy3[0])**2 + abs(newxy2[1] - newxy3[1])**2) if not isequal(edgex, edgey) and (element.TAG == "circle" or not isequal(newxy2[0], newxy3[0]) or not isequal(newxy1[1], newxy2[1])): inkex.utils.errormsg( "Warning: Shape %s (%s) is approximate only, try Object to path first for better results" % (element.TAG, element.get("id"))) if element.TAG == "ellipse": element.set("rx", edgex / 2) element.set("ry", edgey / 2) else: element.set("r", edgex / 2) # this is unstable at the moment elif element.tag == inkex.addNS("use", "svg"): href = None old_href_key = '{http://www.w3.org/1999/xlink}href' new_href_key = 'href' if element.attrib.has_key( old_href_key ) is True: # {http://www.w3.org/1999/xlink}href (which gets displayed as 'xlink:href') attribute is deprecated. the newer attribute is just 'href' href = element.attrib.get(old_href_key) #element.attrib.pop(old_href_key) if element.attrib.has_key(new_href_key) is True: href = element.attrib.get( new_href_key ) #we might overwrite the previous deprecated xlink:href but it's okay #element.attrib.pop(new_href_key) #get the linked object from href attribute linkedObject = self.document.getroot().xpath( "//*[@id = '%s']" % href.lstrip('#')) #we must remove hashtag symbol linkedObjectCopy = copy.copy(linkedObject[0]) objectType = linkedObject[0].tag if objectType == inkex.addNS("image", "svg"): mask = None #image might have an alpha channel new_mask_id = self.svg.get_unique_id("mask") newMask = None if element.attrib.has_key('mask') is True: mask = element.attrib.get('mask') #element.attrib.pop('mask') #get the linked mask from mask attribute. We remove the old and create a new if mask is not None: linkedMask = self.document.getroot().xpath( "//*[@id = '%s']" % mask.lstrip('url(#').rstrip(')') ) #we must remove hashtag symbol linkedMask[0].delete() maskAttributes = {'id': new_mask_id} newMask = etree.SubElement(self.document.getroot(), inkex.addNS('mask', 'svg'), maskAttributes) width = float(linkedObjectCopy.get('width')) * transf.a height = float(linkedObjectCopy.get('height')) * transf.d linkedObjectCopy.set('width', '{:1.6f}'.format(width)) linkedObjectCopy.set('height', '{:1.6f}'.format(height)) linkedObjectCopy.set('x', '{:1.6f}'.format(transf.e)) linkedObjectCopy.set('y', '{:1.6f}'.format(transf.f)) if newMask is not None: linkedObjectCopy.set('mask', 'url(#' + new_mask_id + ')') maskRectAttributes = { 'x': '{:1.6f}'.format(transf.e), 'y': '{:1.6f}'.format(transf.f), 'width': '{:1.6f}'.format(width), 'height': '{:1.6f}'.format(height), 'style': 'fill:#ffffff;' } maskRect = etree.SubElement(newMask, inkex.addNS('rect', 'svg'), maskRectAttributes) self.document.getroot().append( linkedObjectCopy ) #for each svg:use we append a copy to the document root element.delete() #then we remove the use object else: #self.recursiveFuseTransform(linkedObjectCopy, transf) self.recursiveFuseTransform(element.unlink(), transf) elif element.tag in [ inkex.addNS('rect', 'svg'), inkex.addNS('text', 'svg'), inkex.addNS('image', 'svg') ]: inkex.utils.errormsg( "Shape %s (%s) not yet supported, try Object to path first" % (element.TAG, element.get("id"))) else: # e.g. <g style="..."> self.scaleStrokeWidth(element, transf) for child in element.getchildren(): self.recursiveFuseTransform(child, transf)