def convertToSegments(cls, path_node): path_start = None currentPoint = None # work on copy to be shure not breaking anything path = copy.deepcopy(path_node) # apply transformation info on path, otherwise dealing with transform would be a mess simpletransform.fuseTransform(path) for cmd, params in simplepath.parsePath(path.get('d')): print_('cmd, params', cmd, params) if cmd == 'M': if(path_start is None): path_start = params currentPoint = params elif cmd == 'L': yield Segment(currentPoint, params) currentPoint = params elif cmd in ['A', 'Q', 'C']: yield Segment(currentPoint, params[-2:], command=cmd, extra_parameters=params[:-2]) currentPoint = params[-2:] elif (cmd == 'Z'): # Z is a line between the last point and the start of the shape yield Segment(currentPoint, path_start) currentPoint = None path_start = None else: inkex.errormsg("Path Command %s not managed Yet" % cmd)
def effect(self): sep = self.options.seperator f = open( os.path.join(self.options.output_dir, self.options.output_filename), "w") x_off = self.options.x_offset y_off = self.options.y_offset # Get document height and trim the units string off the end doc_h = float(self.getDocumentHeight()[:-2]) for node in self.selected.values(): if node.tag == inkex.addNS("path", "svg"): # Make sure the path is in absolute coords simpletransform.fuseTransform(node) path = cubicsuperpath.parsePath(node.get("d")) for sub_path in path: # sub_path represents a list of all nodes in the path for node in sub_path: # node type is SubPath[(point_a, bezier, point_b) # We dont want the control points, we only want the bezier # point_a, bezier, and point_b is a list of length 2 and type float x = node[1][0] y = node[1][1] x = x + x_off if self.options.origin == "south_west_corner": y = doc_h - y + y_off else: y = y + y_off f.write(str(x) + sep + str(y) + sep + "\n") f.close()
def effect(self): # for node in self.selected.items(): output_nodes = "" shapeid = 1 for id, node in self.selected.items(): output_nodes += "{\n" output_nodes += "\t\"id\":" output_nodes += str(shapeid) output_nodes += ",\n" output_nodes += "\t\"points\":[\n" output_nodes += "\t\t" if node.tag == inkex.addNS('path', 'svg'): simpletransform.fuseTransform(node) d = node.get('d') p = cubicsuperpath.parsePath(d) first = 1 # whe need the coordinates in the form MOVE XY, ..."CP1 XY, CP2 XY, PT XY,"... for subpath in p: # for csp in subpath: cnt = len(subpath) - 1 i = 1 fsp = subpath[0] output_nodes += str(round(fsp[1][0])) # MOVE x output_nodes += "," output_nodes += str(round(fsp[1][1])) # MOVE y output_nodes += "," while i < cnt: psp = subpath[i - 1] output_nodes += str(round(psp[2][0])) # CP1 x output_nodes += "," output_nodes += str(round(psp[2][1])) # CP1 y output_nodes += "," csp = subpath[i] output_nodes += str(round(csp[0][0])) # CP2 x output_nodes += "," output_nodes += str(round(csp[0][1])) # CP2 y output_nodes += "," output_nodes += str(round(csp[1][0])) # PT x output_nodes += "," output_nodes += str(round(csp[1][1])) # PR y i = i + 1 if i < cnt: # omit last output_nodes += "," lsp = subpath[cnt - 1] if round(fsp[1][0]) != round(lsp[1][0]) or round( fsp[1][1]) != round(lsp[1][1]): output_nodes += "\n* OPEN *" # while # for subpath # if output_nodes += "\n" output_nodes += "\t]\n" output_nodes += "},\n" shapeid += 1 sys.stderr.write(output_nodes)
def effect(self): for node in self.selected.items(): output_all = output_nodes = "" output_nodes_xy = {'x': "", 'y': ""} float_value = 2 for id, node in self.selected.items(): if node.tag == inkex.addNS('path', 'svg'): output_all += "" output_nodes += "" simpletransform.fuseTransform(node) d = node.get('d') p = cubicsuperpath.parsePath(d) for subpath in p: for csp in subpath: output_nodes_xy['x'] += str( round(csp[1][0], float_value)) + ", " output_nodes_xy['y'] += str( round(csp[1][1], float_value)) + ", " output_nodes += str(csp[1][0]) + "\t" + str( csp[1][1]) + "\n" sys.stderr.write("XY list:\n") sys.stderr.write(output_nodes) sys.stderr.write("\n\nPython dict:\n") sys.stderr.write("{\n'x':[" + output_nodes_xy['x'][:-2] + "],\n'y':[" + output_nodes_xy['y'][:-2] + "]\n}\n")
def _move_to_origin(self): translate_x = -self._min_x translate_y = -self._baseline transform = "translate(%s, %s)" % (translate_x, translate_y) for node in self.node.iter(SVG_PATH_TAG): node.set('transform', transform) simpletransform.fuseTransform(node)
def _handle_node(self, node, layer): stroke = self._get_stroke(node) fill = self._get_fill(node) has_classes = node.get( 'class', None ) is not None # TODO parse styles instead of assuming that the style applies visibility visible = has_classes or stroke['visible'] or fill['visible'] or ( stroke['color'] == 'unset' and fill['color'] == 'unset') processColor = self._process_color(stroke['color']) if (visible and processColor): simpletransform.fuseTransform(node) self.paths[layer] = self.paths[layer] + [ node ] if layer in self.paths else [node]
def effect(self): #Loop through all the selected items in Inkscape for node in self.selected.iteritems(): #Create the string variable which will hold the formatted data (note that '\n' defines a line break) output_all = output_nodes = "" #Iterate through all the selected objects in Inkscape for id, node in self.selected.iteritems(): #Check if the node is a path ( "svg:path" node in XML ) if node.tag == inkex.addNS('path', 'svg'): #Create the string variables which will hold the formatted data output_all += "" output_nodes += "" # bake (or fuse) transform simpletransform.fuseTransform(node) #turn into cubicsuperpath d = node.get('d') p = cubicsuperpath.parsePath(d) for subpath in p: # there may be several paths joined together (e.g. holes) for csp in subpath: # groups of three to handle control points. # just the points no control points (handles) output_nodes += str(csp[1][0]) + "," + str( csp[1][1]) + "\n" # all the points output_all += str(csp[0][0]) + "," + str( csp[0][1]) + " " output_all += str(csp[1][0]) + "," + str( csp[1][1]) + " " output_all += str(csp[2][0]) + "," + str( csp[2][1]) + "\n" output_all += ";\n" path = str(self.document.getroot().get( "{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}docname")) fileName = path[:len(path) - 4] f = open(fileName + '.txt', 'w') f.write(output_all)
def convertToSegments(cls, path_node): path_start = None currentPoint = None # work on copy to be shure not breaking anything path = copy.deepcopy(path_node) # apply transformation info on path, otherwise dealing with transform would be a mess simpletransform.fuseTransform(path) for cmd, params in simplepath.parsePath(path.get('d')): print_('cmd, params', cmd, params) if cmd == 'M': if (path_start is None): path_start = params currentPoint = params elif cmd == 'L': yield Segment(currentPoint, params) currentPoint = params elif cmd in ['A', 'Q', 'C']: yield Segment(currentPoint, params[-2:], command=cmd, extra_parameters=params[:-2]) currentPoint = params[-2:] elif (cmd == 'Z'): # Z is a line between the last point and the start of the shape yield Segment(currentPoint, path_start) currentPoint = None path_start = None else: inkex.errormsg("Path Command %s not managed Yet" % cmd)
def effect(self): if len(self.options.ids) != 2: inkex.errormsg(_("This extension requires two selected objects. The first selected object must be the straight line with two nodes.")) exit() # drawing that will be scaled is selected second, must be a single object scalepath = self.selected[self.options.ids[0]] drawing = self.selected[self.options.ids[1]] if scalepath.tag != inkex.addNS('path','svg'): inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead.")) exit() # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length simpletransform.fuseTransform(scalepath) path = cubicsuperpath.parsePath(scalepath.get('d')) if len(path) < 1 or len(path[0]) < 2: inkex.errormsg(_("This extension requires that the first selected path be two nodes long.")) exit() # calculate path length p1_x = path[0][0][1][0] p1_y = path[0][0][1][1] p2_x = path[0][1][1][0] p2_y = path[0][1][1][1] p_length = self.getUnittouu(str(distance((p1_x, p1_y),(p2_x, p2_y))) + self.getDocumentUnit()) # Find Drawing Scale if self.options.choosescale == 'metric': drawing_scale = int(self.options.metric) elif self.options.choosescale == 'imperial': drawing_scale = int(self.options.imperial) elif self.options.choosescale == 'custom': drawing_scale = int(self.options.custom_scale) # calculate scaling center center = self.calc_scale_center(p1_x, p1_y, p2_x, p2_y) # calculate scaling factor target_length = self.getUnittouu(str(self.options.length) + self.options.unit) factor = (target_length / p_length) / drawing_scale # inkex.debug("%s, %s %s" % (target_length, p_length, factor)) # Add scale ruler if self.options.showscale == "true": dist = int(self.options.unitlength) ruler_length = self.getUnittouu(str(dist) + self.options.unit) / drawing_scale ruler_pos = (p1_x + (p2_x - p1_x)/2, (p1_y + (p2_y - p1_y)/2) - self.getUnittouu('4 mm')) # TODO: add into current layer instead self.create_ruler(self.document.getroot(), ruler_length, ruler_pos, dist, drawing_scale) # Get drawing and current transformations for obj in (scalepath, drawing): # Scale both objects about the center, first translate back to origin scale_matrix = [[1, 0.0, -center[0]], [0.0, 1, -center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then scale scale_matrix = [[factor, 0.0, 0.0], [0.0, factor, 0.0]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then translate back to original scale center location scale_matrix = [[1, 0.0, center[0]], [0.0, 1, center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj)
def effect(self): # Get number of digits scale = self.unittouu('1px') # Convert to document units factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = self.unittouu(doc.get('width'))/float(vieww) if self.unittouu(doc.get('height'))/float(viewh) < factor: factor = self.unittouu(doc.get('height'))/float(viewh) factor /= self.unittouu('1px') # Loop over all selected paths obj_lengths = [] obj_ids = [] obj_nodes = [] for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) node.set('d', cubicsuperpath.formatPath(p)) simpletransform.applyTransformToPath(mat, p) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) # Save the path length and segment lengths in the document node.set('pathlength', str(stotal)) tmp = '' for slen in slengths[0][::-1]: tmp += str(slen) + ' ' tmp = tmp[:-1] # Remove the space at the end node.set('segmentlengths', tmp) obj_lengths += [stotal] obj_ids += [id] obj_nodes += [node] id_min = 0 id_max = 1 minOrigin = [] maxOrigin = [] # Set bigger and smaller object if obj_lengths[id_min] > obj_lengths[id_max]: id_min = 1 id_max = 0 minOrigin = originParse(obj_nodes[id_min]) maxOrigin = originParse(obj_nodes[id_max]) #Scaling Radio Button Options if self.options.radioScale == "B2S": ratio = obj_lengths[id_min] / obj_lengths[id_max] obj_ori = [] ori_trans = [] obj_nodes[id_max].set('transform', 'scale(' + str(ratio) + ' ' + str(ratio) +')') fuseTransform(obj_nodes[id_max]) obj_ori = originParse(obj_nodes[id_max]) ori_trans = [(maxOrigin[0] - obj_ori[0]), (maxOrigin[1] - obj_ori[1])] obj_nodes[id_max].set('transform', 'translate(' + str(ori_trans[0]) + ' ' + str(ori_trans[1]) +')') fuseTransform(obj_nodes[id_max]) elif self.options.radioScale == "S2B": ratio = obj_lengths[id_max] / obj_lengths[id_min] obj_ori = [] ori_trans = [] obj_nodes[id_min].set('transform', 'scale(' + str(ratio) + ' ' + str(ratio) +')') fuseTransform(obj_nodes[id_min]) obj_ori = originParse(obj_nodes[id_min]) ori_trans = [(minOrigin[0] - obj_ori[0]), (minOrigin[1] - obj_ori[1])] obj_nodes[id_min].set('transform', 'translate(' + str(ori_trans[0]) + ' ' + str(ori_trans[1]) +')') fuseTransform(obj_nodes[id_min]) # Get paths and collect pathlength and segmentlengths obj_lengths = [] obj_ids = [] obj_nodes = [] for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) node.set('d', cubicsuperpath.formatPath(p)) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) # Save the path length and segment lengths in the document node.set('pathlength', str(stotal)) tmp = '' for slen in slengths[0][::-1]: tmp += str(slen) + ' ' tmp = tmp[:-1] #Remove the space at the end node.set('segmentlengths', tmp) obj_lengths += [stotal] obj_ids += [id] obj_nodes += [node] # Format the length as string points = [] # Run Functions based on active Tab if self.options.tab == "\"stitch\"": addStitching(obj_nodes[id_min], self.options.points, self.options.offset, self.options.paraStitch, doc) addStitching(obj_nodes[id_max], self.options.points, self.options.offset, self.options.paraStitch, doc) elif self.options.tab == "\"tooth\"": addNotches(obj_nodes[id_min], self.options.points, self.options.offset, False, self.options.paraTooth,doc) addNotches(obj_nodes[id_max], self.options.points, self.options.offset, True, self.options.paraTooth,doc) elif self.options.tab == "\"leaf\"": addLeaves(obj_nodes[id_min], self.options.points, self.options.offset, self.options.paraLeaf, doc) addLeaves(obj_nodes[id_max], self.options.points, self.options.offset, self.options.paraLeaf, doc)
def propagate_attribs(node, parent_style={}, parent_transform=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): """Propagate style and transform to remove inheritance""" # Don't enter non-graphical portions of the document if (node.tag == addNS("namedview", "sodipodi") or node.tag == addNS("defs", "svg") or node.tag == addNS("metadata", "svg") or node.tag == addNS("foreignObject", "svg")): return # Compose the transformations if node.tag == addNS("svg", "svg") and node.get("viewBox"): vx, vy, vw, vh = [get_dimension(x) for x in node.get("viewBox").split()] dw = get_dimension(node.get("width", vw)) dh = get_dimension(node.get("height", vh)) t = "translate(%f, %f) scale(%f, %f)" % (-vx, -vy, dw/vw, dh/vh) this_transform = simpletransform.parseTransform(t, parent_transform) this_transform = simpletransform.parseTransform(node.get("transform"), this_transform) del node.attrib["viewBox"] else: this_transform = simpletransform.parseTransform(node.get("transform"), parent_transform) # Compose the style attribs this_style = simplestyle.parseStyle(node.get("style", "")) remaining_style = {} # Style attributes that are not propagated non_propagated = ["filter"] # Filters should remain on the topmost ancestor for key in non_propagated: if key in this_style.keys(): remaining_style[key] = this_style[key] del this_style[key] # Create a copy of the parent style, and merge this style into it parent_style_copy = parent_style.copy() parent_style_copy.update(this_style) this_style = parent_style_copy # Merge in any attributes outside of the style style_attribs = ["fill", "stroke"] for attrib in style_attribs: if node.get(attrib): this_style[attrib] = node.get(attrib) del node.attrib[attrib] if (node.tag == addNS("svg", "svg") or node.tag == addNS("g", "svg") or node.tag == addNS("a", "svg") or node.tag == addNS("switch", "svg")): # Leave only non-propagating style attributes if len(remaining_style) == 0: if "style" in node.keys(): del node.attrib["style"] else: node.set("style", simplestyle.formatStyle(remaining_style)) # Remove the transform attribute if "transform" in node.keys(): del node.attrib["transform"] # Continue propagating on subelements for c in node.iterchildren(): propagate_attribs(c, this_style, this_transform) else: # This element is not a container # Merge remaining_style into this_style this_style.update(remaining_style) # Set the element's style and transform attribs node.set("style", simplestyle.formatStyle(this_style)) node.set("transform", simpletransform.formatTransform(this_transform)) if node.get('d')!=None: simpletransform.fuseTransform(node)
def effect(self): if len(self.options.ids) != 2: inkex.errormsg(_("This extension requires two selected objects. The first selected object must be the straight line with two nodes.")) exit() # drawing that will be scaled is selected second, must be a single object scalepath = self.selected[self.options.ids[0]] drawing = self.selected[self.options.ids[1]] if scalepath.tag != inkex.addNS('path','svg'): inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead.")) exit() # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length simpletransform.fuseTransform(scalepath) path = cubicsuperpath.parsePath(scalepath.get('d')) if len(path) < 1 or len(path[0]) < 2: inkex.errormsg(_("This extension requires that the first selected path be two nodes long.")) exit() # calculate path length p1_x = path[0][0][1][0] p1_y = path[0][0][1][1] p2_x = path[0][1][1][0] p2_y = path[0][1][1][1] p_length = self.getUnittouu(str(distance((p1_x, p1_y),(p2_x, p2_y))) + self.getDocumentUnit()) # Find Drawing Scale if self.options.choosescale == 'metric': drawing_scale = int(self.options.metric) elif self.options.choosescale == 'imperial': drawing_scale = int(self.options.imperial) elif self.options.choosescale == 'custom': drawing_scale = self.options.custom_scale # calculate scaling center center = self.calc_scale_center(p1_x, p1_y, p2_x, p2_y) # calculate scaling factor target_length = self.getUnittouu(str(self.options.length) + self.options.unit) factor = (target_length / p_length) / drawing_scale # inkex.debug("%s, %s %s" % (target_length, p_length, factor)) # Add scale ruler if self.options.showscale == "true": dist = int(self.options.unitlength) ruler_length = self.getUnittouu(str(dist) + self.options.unit) / drawing_scale ruler_pos = (p1_x + (p2_x - p1_x)/2, (p1_y + (p2_y - p1_y)/2) - self.getUnittouu('4 mm')) # TODO: add into current layer instead self.create_ruler(self.document.getroot(), ruler_length, ruler_pos, dist, drawing_scale) # Get drawing and current transformations for obj in (scalepath, drawing): # Scale both objects about the center, first translate back to origin scale_matrix = [[1, 0.0, -center[0]], [0.0, 1, -center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then scale scale_matrix = [[factor, 0.0, 0.0], [0.0, factor, 0.0]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then translate back to original scale center location scale_matrix = [[1, 0.0, center[0]], [0.0, 1, center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj)