def _render(self, parent): qrcode = self._generate() if not qrcode: return # Parse SVG and draw elements to the workspace output = StringIO() qrcode.save(output) output.seek(0) tree = ElementTree() tree.parse(output) root = tree.getroot() vbox = map(int, root.get("viewBox").split()) vbox = vbox[0]-self.options.padding*self.options.size/10, \ vbox[1]-self.options.padding*self.options.size/10, \ vbox[2]+2*self.options.padding*self.options.size/10, \ vbox[3]+2*self.options.padding*self.options.size/10 vbox = map(str, vbox) rect = inkex.etree.SubElement( parent, inkex.addNS('rect', 'svg'), {"x": vbox[0], "y": vbox[1], "width": vbox[2], "height": vbox[3], "style": "fill:#fff;"}) for m in root.getchildren(): attribs = {} for k in m.keys(): attribs[k] = str(m.get(k)) inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), attribs)
def computeBBox(aList,mat=[[1,0,0],[0,1,0]]): bbox=None for node in aList: m = parseTransform(node.get('transform')) m = composeTransform(mat,m) #TODO: text not supported! if node.get("d"): d = node.get('d') p = cubicsuperpath.parsePath(d) applyTransformToPath(m,p) bbox=boxunion(roughBBox(p),bbox) elif node.tag == inkex.addNS('rect','svg') or node.tag=='rect': w = float(node.get('width'))/2. h = float(node.get('height'))/2. x = float(node.get('x')) y = float(node.get('y')) C = [x + w , y + h ] applyTransformToPoint(mat,C) xmin = C[0] - abs(m[0][0]) * w - abs(m[0][1]) * h xmax = C[0] + abs(m[0][0]) * w + abs(m[0][1]) * h ymin = C[1] - abs(m[1][0]) * w - abs(m[1][1]) * h ymax = C[1] + abs(m[1][0]) * w + abs(m[1][1]) * h bbox = xmin,xmax,ymin,ymax elif node.tag == inkex.addNS('use','svg') or node.tag=='use': refid=node.get(inkex.addNS('href','xlink')) path = '//*[@id="%s"]' % refid[1:] refnode = node.xpath(path) bbox=boxunion(computeBBox(refnode,m),bbox) bbox=boxunion(computeBBox(node,m),bbox) return bbox
def draw_SVG_circle(r, cx, cy, width, fill, name, parent): style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': fill } circ_attribs = {'style':simplestyle.formatStyle(style), 'cx':str(cx), 'cy':str(cy), 'r':str(r), inkex.addNS('label','inkscape'):name} circle = inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs )
def drawCircles(self, circles, trans_point = (0.0, 0.0)): parent = self.current_layer i = 0 for layer in circles: for c in layer: x = trans_point[0] + c.x y = trans_point[1] + c.y if not self.options.tinned: material = 'CU' color = '#aa4400' else: material = 'CU-T' color = '#808080' style = {'stroke': 'none', 'fill': color} attribs = {'cx': str(x), 'cy': str(y), 'r': str(c.r), inkex.addNS('label', 'inkscape'):"is%d" %i, 'material':material, 'style': simplestyle.formatStyle(style)} inkex.etree.SubElement(parent, inkex.addNS('circle', 'svg'), attribs) i += 1
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): p = simplepath.parsePath(node.get('d')) a =[] pen = None subPathStart = None for cmd,params in p: if cmd == 'C': a.extend([['M', params[:2]], ['L', pen], ['M', params[2:4]], ['L', params[-2:]]]) if cmd == 'Q': a.extend([['M', params[:2]], ['L', pen], ['M', params[:2]], ['L', params[-2:]]]) if cmd == 'M': subPathStart = params if cmd == 'Z': pen = subPathStart else: pen = params[-2:] if len(a) > 0: s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#000000', 'stroke-linecap': 'butt', 'fill': 'none'} attribs = {'style':simplestyle.formatStyle(s),'d':simplepath.formatPath(a)} inkex.etree.SubElement(node.getparent(), inkex.addNS('path','svg'), attribs)
def draw_SVG_circle(parent, r, cx, cy, name, style): " add an SVG circle entity to parent " circ_attribs = {'style': simplestyle.formatStyle(style), 'cx': str(cx), 'cy': str(cy), 'r': str(r), inkex.addNS('label','inkscape'):name} circle = inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs )
def joinFillsWithNode ( self, node, stroke_width, path ): ''' Generate a SVG <path> element containing the path data "path". Then put this new <path> element into a <group> with the supplied node. This means making a new <group> element and moving node under it with the new <path> as a sibling element. ''' if ( not path ) or ( len( path ) == 0 ): return # Make a new SVG <group> element whose parent is the parent of node parent = node.getparent() #was: if not parent: if parent is None: parent = self.document.getroot() g = inkex.etree.SubElement( parent, inkex.addNS( 'g', 'svg' ) ) # Move node to be a child of this new <g> element g.append( node ) # Now make a <path> element which contains the hatches & is a child # of the new <g> element style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': '%f' % stroke_width} line_attribs = { 'style':simplestyle.formatStyle( style ), 'd': path } tran = node.get( 'transform' ) if ( tran != None ) and ( tran != '' ): line_attribs['transform'] = tran inkex.etree.SubElement( g, inkex.addNS( 'path', 'svg' ), line_attribs )
def make_double_line(self, length): opt = self.options w1 = float(opt.stroke_width_1) w2 = float(opt.stroke_width_2) offset = 0.5*(w1 + w2) line = inkex.etree.Element('g') style_line1 = { 'fill': 'none', 'stroke': simplestyle.svgcolors[opt.stroke_color_1], 'stroke-width': opt.stroke_width_1+'px',} path_atts_1 = { inkex.addNS('connector-curvature', 'inkscape'): "0", 'd': "M 0.0,0.0 %f,0.0" % (length,), 'style': simplestyle.formatStyle(style_line1), } inkex.etree.SubElement(line, 'path', path_atts_1) style_line2 = { 'fill': 'none', 'stroke': simplestyle.svgcolors[opt.stroke_color_2], 'stroke-width': opt.stroke_width_2+'px',} path_atts_2 = { inkex.addNS('connector-curvature', 'inkscape'): "0", 'd': "M 0.0,%f %f,%f.0" % (offset, length, offset), 'style': simplestyle.formatStyle(style_line2),} inkex.etree.SubElement(line, 'path', path_atts_2) return line
def process_clone(self, node): trans = node.get('transform') x = node.get('x') y = node.get('y') mat = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] if trans: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) if x: mat = simpletransform.composeTransform(mat, [[1.0, 0.0, float(x)], [0.0, 1.0, 0.0]]) if y: mat = simpletransform.composeTransform(mat, [[1.0, 0.0, 0.0], [0.0, 1.0, float(y)]]) # push transform if trans or x or y: self.groupmat.append(simpletransform.composeTransform(self.groupmat[-1], mat)) # get referenced node refid = node.get(inkex.addNS('href','xlink')) refnode = self.getElementById(refid[1:]) if refnode is not None: if refnode.tag == inkex.addNS('g','svg'): self.process_group(refnode) elif refnode.tag == inkex.addNS('use', 'svg'): self.process_clone(refnode) else: self.process_shape(refnode, self.groupmat[-1]) # pop transform if trans or x or y: self.groupmat.pop()
def export_MTEXT(): # mandatory group codes : (1 or 3, 10, 20) (text, x, y) if (vals[groups['1']] or vals[groups['3']]) and vals[groups['10']] and vals[groups['20']]: x = vals[groups['10']][0] y = vals[groups['20']][0] # optional group codes : (21, 40, 50) (direction, text height mm, text angle) size = 12 # default fontsize in px if vals[groups['40']] and vals[groups['40']][0]: size = scale*vals[groups['40']][0] attribs = {'x': '%f' % x, 'y': '%f' % y, 'style': 'font-size: %.1fpx; fill: %s; font-family: %s' % (size, color, options.font)} angle = 0 # default angle in degrees if vals[groups['50']]: angle = vals[groups['50']][0] attribs.update({'transform': 'rotate (%f %f %f)' % (-angle, x, y)}) elif vals[groups['21']]: if vals[groups['21']][0] == 1.0: attribs.update({'transform': 'rotate (%f %f %f)' % (-90, x, y)}) elif vals[groups['21']][0] == -1.0: attribs.update({'transform': 'rotate (%f %f %f)' % (90, x, y)}) attribs.update({inkex.addNS('linespacing','sodipodi'): '125%'}) node = inkex.etree.SubElement(layer, 'text', attribs) text = '' if vals[groups['3']]: for i in range (0, len(vals[groups['3']])): text += vals[groups['3']][i] if vals[groups['1']]: text += vals[groups['1']][0] found = text.find('\P') # new line while found > -1: tspan = inkex.etree.SubElement(node , 'tspan', {inkex.addNS('role','sodipodi'): 'line'}) tspan.text = text[:found] text = text[(found+2):] found = text.find('\P') tspan = inkex.etree.SubElement(node , 'tspan', {inkex.addNS('role','sodipodi'): 'line'}) tspan.text = text
def effect(self): #References: Minimum Requirements for Creating a DXF File of a 3D Model By Paul Bourke # NURB Curves: A Guide for the Uninitiated By Philip J. Schneider # The NURBS Book By Les Piegl and Wayne Tiller (Springer, 1995) # self.dxf_add("999\nDXF created by Inkscape\n") # Some programs do not take comments in DXF files (KLayout 0.21.12 for example) self.dxf_add(dxf_templates.r14_header) for node in self.document.getroot().xpath('//svg:g', namespaces=inkex.NSS): if node.get(inkex.addNS('groupmode', 'inkscape')) == 'layer': layer = node.get(inkex.addNS('label', 'inkscape')) layer = layer.replace(' ', '_') if layer and not layer in self.layers: self.layers.append(layer) self.dxf_add(" 2\nLAYER\n 5\n2\n100\nAcDbSymbolTable\n 70\n%s\n" % len(self.layers)) for i in range(len(self.layers)): self.dxf_add(" 0\nLAYER\n 5\n%x\n100\nAcDbSymbolTableRecord\n100\nAcDbLayerTableRecord\n 2\n%s\n 70\n0\n 6\nCONTINUOUS\n" % (i + 80, self.layers[i])) self.dxf_add(dxf_templates.r14_style) scale = eval(self.options.units) if not scale: scale = 25.4/90 # if no scale is specified, assume inch as baseunit h = inkex.unittouu(self.document.getroot().xpath('@height', namespaces=inkex.NSS)[0]) self.groupmat = [[[scale, 0.0, 0.0], [0.0, -scale, h*scale]]] doc = self.document.getroot() self.process_group(doc) if self.options.ROBO == 'true': self.ROBO_output() if self.options.POLY == 'true': self.LWPOLY_output() self.dxf_add(dxf_templates.r14_footer)
def effect(self): # Dimensions in mm width = 259.0 # Before adding spine width or bleed height = 183.0 # Before adding bleed bleed = self.options.dvd_cover_bleed spine = float(self.options.dvd_cover_spine) width += spine width += 2.0 * bleed height += 2.0 * bleed self.root = self.document.getroot() self.root.set("id", "SVGRoot") self.root.set("width", str(width) + "mm") self.root.set("height", str(height) + "mm") self.root.set("viewBox", "0 0 " + str(width) + " " + str(height)) namedview = self.root.find(inkex.addNS("namedview", "sodipodi")) if namedview is None: namedview = inkex.etree.SubElement(self.root, inkex.addNS("namedview", "sodipodi")) namedview.set(inkex.addNS("document-units", "inkscape"), "mm") # Until units are supported in 'cx', etc. namedview.set(inkex.addNS("cx", "inkscape"), str(self.uutounit(width, "px") / 2.0)) namedview.set(inkex.addNS("cy", "inkscape"), str(self.uutounit(height, "px") / 2.0)) self.create_horizontal_guideline("bottom", str(self.uutounit(bleed, "px"))) self.create_horizontal_guideline("top", str(self.uutounit(height - bleed, "px"))) self.create_vertical_guideline("left edge", str(self.uutounit(bleed, "px"))) self.create_vertical_guideline("left spline", str(self.uutounit((width - spine) / 2.0, "px"))) self.create_vertical_guideline("right spline", str(self.uutounit((width + spine) / 2.0, "px"))) self.create_vertical_guideline("left edge", str(self.uutounit(width - bleed, "px")))
def computeBBox(aList,mat=[[1,0,0],[0,1,0]]): bbox=None for node in aList: m = parseTransform(node.get('transform')) m = composeTransform(mat,m) #TODO: text not supported! if node.tag == inkex.addNS('rect','svg'): A=[0,0] B=[0,0] A[0] = float(node.get('x')) A[1] = float(node.get('y')) B[0] = A[0]+float(node.get('width')) B[1] = A[1]+float(node.get('height')) applyTransformToPoint(mat, A) applyTransformToPoint(mat, B) bbox = min(A[0], B[0]), max(A[0], B[0]), min(A[1], B[1]), max(A[1], B[1]) if node.get("d"): d = node.get('d') p = cubicsuperpath.parsePath(d) applyTransformToPath(m,p) bbox=boxunion(roughBBox(p),bbox) if node.tag == inkex.addNS('use','svg') or node.tag=='use': refid=node.get(inkex.addNS('href','xlink')) path = '//*[@id="%s"]' % refid[1:] refnode = node.getroottree().xpath(path, namespaces=inkex.NSS) bbox=boxunion(computeBBox(refnode,m),bbox) bbox=boxunion(computeBBox(node,m),bbox) return bbox
def split_letters(self, node): """Returns a list of letters""" letters = [] words = self.split_words(node) if not words: return letters for word in words: x = float(word.get("x")) y = word.get("y") #gets the font size. If element doesn't have a style attribute, it assumes font-size = 12px try: import simplestyle fontsize = simplestyle.parseStyle(word.get("style"))["font-size"] except: fontsize = "12px" fs = self.unittouu(fontsize) #for each letter in element string for letter in word[0].text: tspan = inkex.etree.Element(inkex.addNS("tspan", "svg")) tspan.text = letter text = inkex.etree.Element(inkex.addNS("text", "svg"), node.attrib) text.set("x", str(x)) text.set("y", str(y)) x += fs text.append(tspan) letters.append(text) return letters
def effect(self): """Applies the effect""" split_type = self.options.split_type preserve = self.options.preserve #checks if the selected elements are text nodes for id, node in self.selected.iteritems(): if not (node.tag == inkex.addNS("text", "svg") or node.tag == inkex.addNS("flowRoot", "svg")): inkex.debug("Please select only text elements.") break else: if split_type == "line": nodes = self.split_lines(node) elif split_type == "word": nodes = self.split_words(node) elif split_type == "letter": nodes = self.split_letters(node) for n in nodes: node.getparent().append(n) #preserve original element if not preserve and nodes: parent = node.getparent() parent.remove(node)
def effect(self): # Check version. scriptNodes = self.document.xpath("//svg:script[@jessyink:version='1.5.6']", namespaces=inkex.NSS) if len(scriptNodes) != 1: inkex.errormsg(_("The JessyInk script is not installed in this SVG file or has a different version than the JessyInk extensions. Please select \"install/update...\" from the \"JessyInk\" sub-menu of the \"Extensions\" menu to install or update the JessyInk script.\n\n")) if len(self.selected) == 0: inkex.errormsg(_("No object selected. Please select the object you want to assign an effect to and then press apply.\n")) for id, node in list(self.selected.items()): if self.options.effectIn in ("appear", "fade", "pop", "matrix"): attribs = { inkex.addNS('href','xlink'): '#'+id } clone = inkex.etree.SubElement(self.current_layer, inkex.addNS('use','svg'), attribs) clone.set("{" + inkex.NSS["jessyink"] + "}effectIn","name:" + self.options.effectIn + ";length:" + str(int(self.options.effectInDuration * 1000))) # Remove possible view argument. if "{" + inkex.NSS["jessyink"] + "}view" in node.attrib: del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] if self.options.effectOut in ("appear", "fade", "pop", "matrix"): attribs = { inkex.addNS('href','xlink'): '#'+id } clone = inkex.etree.SubElement(self.current_layer, inkex.addNS('use','svg'), attribs) clone.set("{" + inkex.NSS["jessyink"] + "}effectOut","name:" + self.options.effectOut + ";length:" + str(int(self.options.effectOutDuration * 1000))) # Remove possible view argument. if "{" + inkex.NSS["jessyink"] + "}view" in node.attrib: del node.attrib["{" + inkex.NSS["jessyink"] + "}view"]
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg')) new = inkex.etree.SubElement(self.group,inkex.addNS('path','svg')) try: t = node.get('transform') self.group.set('transform', t) except: pass s = simplestyle.parseStyle(node.get('style')) s['stroke-linecap']='round' s['stroke-width']=self.options.dotsize new.set('style', simplestyle.formatStyle(s)) a =[] p = simplepath.parsePath(node.get('d')) num = 1 for cmd,params in p: if cmd != 'Z': a.append(['M',params[-2:]]) a.append(['L',params[-2:]]) self.addText(self.group,params[-2],params[-1],num) num += 1 new.set('d', simplepath.formatPath(a)) node.clear()
def effect(self): width = self.unittouu(str(self.options.width)+self.options.unit) height = self.unittouu(str(self.options.height)+self.options.unit) thickness = self.unittouu(str(self.options.thickness)+self.options.unit) # Create main element t = 'translate(' + str(self.view_center[0]) + ',' + \ str(self.view_center[1]) + ')' g_attribs = { inkex.addNS('label', 'inkscape'): 'Box' + str(width) + "x"+str(height), 'transform': t} g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) style = {'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px'))} # Create path points=lc.make_plate((width,height), (self.options.iwidth,self.options.iheight), thickness,self.options.wsplit,self.options.hsplit, self.options.bottom,self.options.bottomshift, self.options.top,self.options.topshift, self.options.left,self.options.leftshift, self.options.right,self.options.rightshift) path = lc.points_to_svgd(points) # Create SVG Path for plate box_attribs = { 'style': formatStyle(style), 'd': path} box = inkex.etree.SubElement( g, inkex.addNS('path', 'svg'), box_attribs)
def makeMarkerstyle(self, name, rotate): " Markers added to defs for reuse " defs = self.xpathSingle('/svg:svg//svg:defs') if defs == None: defs = inkex.etree.SubElement(self.document.getroot(),inkex.addNS('defs','svg')) marker = inkex.etree.SubElement(defs ,inkex.addNS('marker','svg')) marker.set('id', name) marker.set('orient', 'auto') marker.set('refX', '0.0') marker.set('refY', '0.0') marker.set('style', 'overflow:visible') marker.set(inkex.addNS('stockid','inkscape'), name) arrow = inkex.etree.Element("path") # definition of arrows in beautiful DIN-shapes: if name.startswith('ArrowDIN-'): if rotate: arrow.set('d', 'M 8,0 -8,2.11 -8,-2.11 z') else: arrow.set('d', 'M -8,0 8,-2.11 8,2.11 z') if name.startswith('ArrowDINout-'): if rotate: arrow.set('d', 'M 0,0 16,2.11 16,0.5 26,0.5 26,-0.5 16,-0.5 16,-2.11 z') else: arrow.set('d', 'M 0,0 -16,2.11 -16,0.5 -26,0.5 -26,-0.5 -16,-0.5 -16,-2.11 z') arrow.set('style', 'fill:#000000;stroke:none') marker.append(arrow)
def parseLayerName(self,node): if ( node.get( inkex.addNS( 'groupmode', 'inkscape' ) ) == 'layer' ): strLayerName = node.get( inkex.addNS( 'label', 'inkscape' ) ) # inkex.errormsg('strLayerName: ' + str(strLayerName)) # inkex.errormsg('id: ' + str(node.get( 'id'))) TempNumString = 'x' stringPos = 1 layerNameInt = -1 #Check to see if the layer name begins with a number in the range of palette colors strLayerName = string.lstrip( strLayerName ) #remove leading whitespace MaxLength = len( strLayerName ) if MaxLength > 0: while stringPos <= MaxLength: if str.isdigit( strLayerName[:stringPos] ): TempNumString = strLayerName[:stringPos] # Store longest numeric string so far stringPos = stringPos + 1 else: break #If it's the first layer found of that color, add its ID to our layer lookup table. if ( str.isdigit( TempNumString ) ): layerNameInt = int( float( TempNumString ) ) if (layerNameInt >= 0) and (layerNameInt < len(self.paletteRGB)): if (self.layerLabels[layerNameInt] == "layerNotFound"): self.layerLabels[layerNameInt] = str(node.get('id'))
def effect(self): node_pos={} node_R=[] for node in self.selected.values() : if node.tag == inkex.addNS('path','svg') and node.get(inkex.addNS("cx","sodipodi")) is not None :#assume circle node_pos[node]=simpleprimitive.element_center(node) node_R.append(float(node.get(inkex.addNS("rx","sodipodi")))) if len(node_pos)>2 : size=sum(node_R)/len(node_R)*2. cx=sum([pt[0] for pt in node_pos.itervalues()])/len(node_pos) cy=sum([pt[1] for pt in node_pos.itervalues()])/len(node_pos) node_ref=iter(node_pos).next() parent=node_ref.getparent() box=simpleprimitive.box(parent,cx,cy,size,size,{"fill":simplestyle.svgcolors["blue"]}) box.set("id",self.uniqueId("rect")) angles=[(angle(node_pos[node_ref],pt,(cx,cy)),node) for node,pt in node_pos.iteritems()] angles.sort() nb=len(angles) for i in xrange(nb) : con=simpleprimitive.connect(parent,angles[i][1],angles[(i+1)%nb][1],{"stroke":simplestyle.svgcolors["magenta"]}) if con is not None : con.set("id",self.uniqueId("con")) for node in node_pos : con=simpleprimitive.connect(parent,box,node,{"stroke":simplestyle.svgcolors["green"]}) con.set("id",self.uniqueId("con")) else : raise UserWarning("must select at least 3 elements")
def effect(self): size = self.options.desktop_size width = self.options.desktop_width height = self.options.desktop_height if size != "Custom": p = re.compile('([0-9]*)x([0-9]*)') m = p.match( size ) width = int(m.group(1)) height = int(m.group(2)) root = self.document.getroot() root.set("id", "SVGRoot") root.set("width", str(width) + 'px') root.set("height", str(height) + 'px') root.set("viewBox", "0 0 " + str(width) + " " + str(height) ) namedview = root.find(inkex.addNS('namedview', 'sodipodi')) if namedview is None: namedview = inkex.etree.SubElement( root, inkex.addNS('namedview', 'sodipodi') ); namedview.set(inkex.addNS('document-units', 'inkscape'), 'px') namedview.set(inkex.addNS('cx', 'inkscape'), str(width/2.0) ) namedview.set(inkex.addNS('cy', 'inkscape'), str(height/2.0) )
def innerImage(self, x, y, width, height, padding, path, parent): with codecs.open(path, encoding="utf-8") as f: doc = etree.parse(f).getroot() imgWidth = self.unittouu(doc.get('width')) imgHeight = self.unittouu(doc.get('height')) sx = (width - padding) / imgWidth sy = (height - padding) / imgHeight scale = sx if sy < sx: scale = sy x += width / 2 - imgWidth * scale / 2 y += height / 2 - imgHeight * scale / 2 attrs = { 'transform' : 'translate(' + str(x) + ',' + str(y) + ') scale(' + str(scale) + ',' + str(scale) + ')' } logoLayer = inkex.etree.SubElement(parent, 'g', attrs) logoLayer.set(inkex.addNS('label', 'inkscape'), 'Logo Layer') logoLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') logoLayer.append(deepcopy(doc))
def upgrade_or_install(self, tag): """ Upgrade or install a script or a style sheet into the document. - tag: "script" or "style" Depending on the argument, the content of file "sozi.js" or "sozi.css" will be copied to the script or style element. """ # Check version and remove older versions latest_version_found = False for elt in self.document.xpath("//svg:" + tag + "[@id='sozi-" + tag + "']", namespaces=inkex.NSS): version = elt.attrib[inkex.addNS("version", "sozi")] if version == Sozi.VERSION: latest_version_found = True elif version < Sozi.VERSION: elt.getparent().remove(elt) else: sys.stderr.write("Document has been created using a higher version of Sozi. Please upgrade the Inkscape plugin.\n") exit() # Create new element if needed if not latest_version_found: ext = "js" if tag == "script" else "css" elt = inkex.etree.Element(inkex.addNS(tag, "svg")) elt.text = open(os.path.join(os.path.dirname(__file__), "sozi." + ext)).read() elt.set("id","sozi-" + tag) elt.set(inkex.addNS("version", "sozi"), Sozi.VERSION) self.document.getroot().append(elt)
def analyze_document(self): """ Analyze the document and collect information about the presentation. Frames with no corresponding SVG element are removed. Frames numbers are updated if needed. """ # Get list of valid frame elements and remove orphan frames self.frames = [] for f in self.document.xpath("//sozi:frame", namespaces=inkex.NSS): e = self.document.xpath("//svg:*[@id='" + f.attrib[inkex.addNS("refid", "sozi")] + "']", namespaces=inkex.NSS) if len(e) == 0: self.document.getroot().remove(f) else: self.frames.append( { "frame_element": f, "svg_element": e[0] } ) # Sort frames by sequence attribute sequence_attr = inkex.addNS("sequence", "sozi") self.frames = sorted(self.frames, key=lambda f: int(f["frame_element"].attrib[sequence_attr]) if sequence_attr in f["frame_element"].attrib else len(self.frames)) # Renumber frames for i, f in enumerate(self.frames): f["frame_element"].set(inkex.addNS("sequence", "sozi"), unicode(i+1))
def object_bounding_box(obj, box=None): """Get the bounding box of an SVG object. :param obj: The XML node defining the object. :param box: The existing :class:`bounds.BoundingBox` if available. :return: A :class:`bounds.BoundingBox` encompassing the object. SVG images are constructed of a number of primitive objects (paths, rectangles, circles, groups etc.). This function takes an arbitrary object, determines what type of object is, and calculates the bounding box correspondingly. If an existing bounding box is given in the ``box`` parameter, it is extended to encompass the object and returned. Otherwise, a new bounding box is created and returned. Currently, this function can only handle ``path`` and ``rect`` objects. """ if obj.tag == 'path' or obj.tag == inkex.addNS('path', 'svg'): objbox = path_bounding_box(obj, box) elif obj.tag in ['rect', inkex.addNS('rect', 'svg')]: objbox = rect_bounding_box(obj, box) else: objbox = BoundingBox(0, 0, 0, 0) return objbox
def parseArc(self,node,parent): #self.parsing_context = 'arc' style = node.get('style') style = self.parseStyleAttribute(style) arc = { 'id':node.get('id',''), 'svg':'arc', 'label':str(node.get(inkex.addNS('label', 'inkscape'),'')), 'cx': node.get(inkex.addNS('cx', 'sodipodi'),''), 'cy':node.get(inkex.addNS('cy', 'sodipodi'),''), 'rx':node.get(inkex.addNS('rx', 'sodipodi'),''), 'ry':node.get(inkex.addNS('ry', 'sodipodi'),''), 'path':simplepath.parsePath(node.get('d')), 'd':node.get('d',''), 'box':list(simpletransform.computeBBox([node])), 'fill':style.get('fill',''), 'fill-opacity':style.get('fillOpacity',''), 'stroke':style.get('stroke',''), 'stroke-width':style.get('strokeWidth',''), 'stroke-opacity':style.get('strokeOpacity',''), 'transform':node.get('transform','') } if(self.reposition): arc['path'] = self.movePath(node,0,0,'tl') else: arc['path'] = arc['d'] parent.append(arc)
def process_group(self, group): if group.get(inkex.addNS('groupmode', 'inkscape')) == 'layer': style = group.get('style') if style: style = simplestyle.parseStyle(style) if style.has_key('display'): if style['display'] == 'none' and self.options.layer_option and self.options.layer_option=='visible': return layer = group.get(inkex.addNS('label', 'inkscape')) if self.options.layer_name and self.options.layer_option and self.options.layer_option=='name' and not layer.lower() in self.options.layer_name: return layer = layer.replace(' ', '_') if layer in self.layers: self.layer = layer trans = group.get('transform') if trans: self.groupmat.append(simpletransform.composeTransform(self.groupmat[-1], simpletransform.parseTransform(trans))) for node in group: if node.tag == inkex.addNS('g','svg'): self.process_group(node) elif node.tag == inkex.addNS('use', 'svg'): self.process_clone(node) else: self.process_shape(node, self.groupmat[-1]) if trans: self.groupmat.pop()
def getSvg(self): actualLayer = 0 # prepare document self.doc = inkex.etree.parse(StringIO('<svg xmlns:sodipodi="' + inkex.NSS['sodipodi'] + '" xmlns:inkscape="' + inkex.NSS['inkscape'] + '" width="%smm" height="%smm" viewBox="0 0 %s %s"></svg>' % (self.options.docWidth, self.options.docHeight, self.options.docWidth, self.options.docHeight))) inkex.etree.SubElement(self.doc.getroot(), inkex.addNS('namedview', 'sodipodi'), {inkex.addNS('document-units', 'inkscape'): 'mm'}) if self.options.showMovements: self.layers[0] = inkex.etree.SubElement(self.doc.getroot(), 'g', {inkex.addNS('groupmode', 'inkscape'): 'layer', inkex.addNS('label', 'inkscape'): self.textMovements, 'id': self.textMovements}) # cut stream into commands hpglData = self.hpglString.split(';') # if number of commands is under needed minimum, no data was found if len(hpglData) < 3: raise Exception('NO_HPGL_DATA') # decode commands into svg data for i, command in enumerate(hpglData): if command.strip() != '': if command[:2] == 'IN' or command[:2] == 'FS' or command[:2] == 'VS': # if Initialize, force or speed command ignore it pass elif command[:2] == 'SP': # if Select Pen command actualLayer = int(command[2:]) elif command[:2] == 'PU': # if Pen Up command self.parametersToPath(command[2:], 0, True) elif command[:2] == 'PD': # if Pen Down command self.parametersToPath(command[2:], actualLayer + 1, False) else: self.warning = 'UNKNOWN_COMMANDS' return (self.doc, self.warning)
def updateArmatureData(self,layerSetName,layerGroup): stuff = "" layerSetId = layerSetName.replace(' ','') #has a data node been created query='//*[@class="data-node %s"]' % layerSetId nodes=self.armatureLayer.xpath(query) if not nodes is None and len(nodes)>0: #find the node, and update it for n in nodes: currentData = parseStyle( n.get( inkex.addNS('label', 'inkscape') ) ) if 'state' in currentData and currentData['state']=='on': currentData['on']=layerGroup['on'] else: currentData['off']=layerGroup=['off'] n.set(inkex.addNS('label', 'inkscape'), formatStyle(currentData) ) else: yNodes=self.armatureLayer.xpath('//*[@y]') maxY=0 for yNode in yNodes: className = yNode.get('class') if not className is None and 'data-node' in className: newY = float(yNode.get('y')) if newY>maxY: maxY=newY if maxY>self.cursorY: self.cursorY = maxY self.cursorY+=35 self.renderArmatureData(layerSetId,layerGroup)
def effect(self): ###Hauptprogramm # holt die Parameter aus Inkscape self.hoehe = self.options.hoehe self.durchmesser = self.options.durchmesser self.ueberstand = self.options.ueberstand self.radius = self.durchmesser / 2 self.radius_mit_ueberstand = self.radius + self.ueberstand self.winkel = self.options.winkel self.boden = self.options.boden self.material = self.options.material self.segmente = int(360 / self.winkel) #Ausschnittbreite errechnen y = sin(radians(self.winkel)) * self.radius beta = 180 - 90 - self.winkel b = sin(radians(beta)) * self.radius x = self.radius - b self.ausschnitt_breite = sqrt((x * x) + (y * y)) # what page are we on page_id = self.options.active_tab # sometimes wrong the very first time #Eigenschaften der SVG auslesen und die Größe der Dose anpassen svg = self.document.getroot() #viewbox_size = '0 0 ' + str(self.breite) + ' ' + str(self.hoehe) #svg.set('viewBox', viewbox_size) #svg.set('height', str(self.hoehe)) #svg.set('width', str(self.breite)) # Embed the path in a group to make animation easier: # Be sure to examine the internal structure by looking in the xml editor inside inkscape # Make a nice useful name g_attribs = { inkex.addNS('label', 'inkscape'): 'dosen-gruppe', 'id': "dose", } # add the group to the document's current layer self.topgroup = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) # Create SVG Path under this top level group # Make a nice useful name g_attribs = { inkex.addNS('label', 'inkscape'): 'einschnitt-gruppe', 'id': "einschnitte", } # add the group to the document's current layer self.undergroup = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) # Create SVG Path under this top level group self.deckel_erstellen() self.ausschnitt_erstellen() self.seite_erstellen() self.einschnitte_erstellen() # Make a nice useful name text_g_attribs = { inkex.addNS('label', 'inkscape'): 'dosen-gruppe', 'id': "Branding", } # add the group to the document's current layer textgroup = inkex.etree.SubElement(self.current_layer, 'g', text_g_attribs) line_style = { 'font-size': '10px', 'font-style': 'normal', 'font-weight': 'normal', 'fill': '#ff0000', 'font-family': 'Consolas', 'text-anchor': 'start' } branding_line_attribs = { inkex.addNS('label', 'inkscape'): 'branding-text', 'id': 'front text', 'style': simplestyle.formatStyle(line_style), 'x': str(0), 'y': str(0) } branding_line = inkex.etree.SubElement(textgroup, inkex.addNS('text', 'svg'), branding_line_attribs) branding_line.text = 'dosen-generator by mini revollo member of the erfindergarden' # Make a nice useful name einschnitt_text_g_attribs = { inkex.addNS('label', 'inkscape'): 'einschnitt-gruppe', 'id': "Einschnitte_Text", } # add the group to the document's current layer textgroup = inkex.etree.SubElement(self.current_layer, 'g', einschnitt_text_g_attribs) line_style = { 'font-size': '5px', 'font-style': 'normal', 'font-weight': 'normal', 'fill': '#00ff00', 'font-family': 'Consolas', 'text-anchor': 'start' } einschnitt_line_attribs = { inkex.addNS('label', 'inkscape'): 'Einschnitte_text', 'id': 'front text', 'style': simplestyle.formatStyle(line_style), 'x': str(0), 'y': str(self.radius_mit_ueberstand + self.hoehe / 2) } branding_line = inkex.etree.SubElement(textgroup, inkex.addNS('text', 'svg'), einschnitt_line_attribs) branding_line.text = 'Die Einschnitte nur zu 70 Prozent in das Material lasern'
def formatText(self, x, y, text, fontColor, bgColor, parent): # Declare the bbcode regex, ... bbCodeRegex = re.compile(r'\[(/)?((?(1)(i|b|color)|(i|b|color=[0-9a-fA-F]{3,6})))\]', re.IGNORECASE) # ... and check for matches. if not bbCodeRegex.findall(text): self.positonTspan(x, y, '_', bgColor, parent) self.createTspan(text, fontColor, parent) return # If there are matches fetch all of them. matches = bbCodeRegex.finditer(text) # Initialize the basic style, ... bbStyles = { 'b' : False, 'i' : False, 'color' : fontColor } # ... and the processing stack. stack = Stack() # Add a positioning tspan. self.positonTspan(x, y, '_', bgColor, parent) # Remember the last match position. lastMatch = 0 # Loop over all matches. for m in matches: # Extract important data from match. textChunk = text[lastMatch:m.start()] lastMatch = m.start() + len(str(m.group())) isClosing = False if m.groups()[0] == None else True bbTagName = m.groups()[1].split('=')[0] # Setup the basic tspan style. style = { 'font-weight' : 'bold' if bbStyles['b'] else 'normal', 'font-style' : 'italic' if bbStyles['i'] else 'normal', 'fill' : '#' + str(bbStyles['color']) } # Update the current style. if isClosing and stack.peek()[0] == bbTagName: bbStyles[bbTagName] = stack.pop()[1] elif isClosing is False and bbTagName == 'color': stack.push((bbTagName, bbStyles[bbTagName])) bbStyles[bbTagName] = m.groups()[1].split('=')[1] elif isClosing is False: stack.push((bbTagName, bbStyles[bbTagName])) bbStyles[bbTagName] = False if bbStyles[bbTagName] else True if len(textChunk) > 0: # Prepend spaces. if textChunk[0] == ' ': self.createTspan('_', bgColor, parent) # Create the new tspan element. tspan = inkex.etree.SubElement(parent, inkex.addNS('tspan', 'svg')) tspan.set('style', formatStyle(style)) tspan.text = textChunk # Append spaces. if textChunk[-1] == ' ' and len(textChunk) > 1: self.createTspan('_', bgColor, parent) if len(text) > 0: textChunk = text[lastMatch:] if len(textChunk.strip()) > 0: # Setup the basic tspan style. style = { 'font-weight' : 'bold' if bbStyles['b'] else 'normal', 'font-style' : 'italic' if bbStyles['i'] else 'normal', 'fill' : '#' + str(bbStyles['color']) } # Prepend spaces. if textChunk[0] == ' ': self.createTspan('_', bgColor, parent) # Create the new tspan element. tspan = inkex.etree.SubElement(parent, inkex.addNS('tspan', 'svg')) tspan.set('style', formatStyle(style)) tspan.text = textChunk
def effect(self): # Fetch the svg root element ... svg = self.document.getroot() # ... as well as the image width and height. width = self.unittouu(svg.get('width')) height = self.unittouu(svg.get('height')) # Fetch the extention parameters. self.sideOneIcon = self.options.sideOneIcon if self.options.sideOneIcon is not None and os.path.isfile(self.options.sideOneIcon) else None self.sideTwoIcon = self.options.sideTwoIcon if self.options.sideTwoIcon is not None and os.path.isfile(self.options.sideTwoIcon) else None self.sideThreeIcon = self.options.sideThreeIcon if self.options.sideThreeIcon is not None and os.path.isfile(self.options.sideThreeIcon) else None self.sideFourIcon = self.options.sideFourIcon if self.options.sideFourIcon is not None and os.path.isfile(self.options.sideFourIcon) else None self.bottomIcon = self.options.bottomIcon if self.options.bottomIcon is not None and os.path.isfile(self.options.bottomIcon) else None self.topIcon = self.options.topIcon if self.options.topIcon is not None and os.path.isfile(self.options.topIcon) else None # Replace 'none' with '' in strings. self.sideOneText = self.sideOneText if self.sideOneText is not None else '' self.sideOneHint = self.sideOneHint if self.sideOneHint is not None else '' self.sideTwoText = self.sideTwoText if self.sideTwoText is not None else '' self.sideTwoHint = self.sideTwoHint if self.sideTwoHint is not None else '' self.sideThreeText = self.sideThreeText if self.sideThreeText is not None else '' self.sideThreeHint = self.sideThreeHint if self.sideThreeHint is not None else '' self.sideFourText = self.sideFourText if self.sideFourText is not None else '' self.sideFourHint = self.sideFourHint if self.sideFourHint is not None else '' # Create a new layer, ... layer = inkex.etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), 'Basic Shape') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') # ... define and calculate the dimensions (in mm) of the basic shape ... cubeWidth = self.unittouu("8.5 cm") cubeHeight = self.unittouu("2.5 cm") cubeDepth = self.unittouu("5.6 cm") wingHeight = self.unittouu("1.0 cm") smallWingWidth = cubeDepth - 2 * wingHeight largeWingWidth = cubeWidth - 2 * wingHeight padding = wingHeight borderWidth = 1 # ... and the headline boxes. boxHintFontSize = cubeHeight / 25 * 3 boxTitleFontSize = cubeHeight / 5 boxBorderColor = 'ffffff' boxBorder = 0 raspiUsbWidth = self.unittouu("1.5 cm") raspiUsbHeight = self.unittouu("1.6 cm") raspiEthWidth = self.unittouu("1.6 cm") raspiEthHeight = self.unittouu("1.4 cm") raspiSoundWidth = raspiSoundHeight = self.unittouu("0.7 cm") raspiHdmiWidth = self.unittouu("1.6 cm") raspiHdmiHeight = self.unittouu("0.5 cm") raspiMusbWidth = self.unittouu("0.9 cm") raspiMusbHeight = self.unittouu("0.4 cm") raspiSdCardWidth = self.unittouu("1.2 cm") raspiSdCardHeight = self.unittouu("0.3 cm") raspiUsb1OffsetX = padding + wingHeight + cubeHeight + self.unittouu("0.2 cm") raspiUsb1OffsetY = padding + wingHeight + cubeHeight - self.unittouu("0.3 cm") raspiUsb2OffsetX = padding + wingHeight + cubeHeight + self.unittouu("2.0 cm") raspiUsb2OffsetY = padding + wingHeight + cubeHeight - self.unittouu("0.3 cm") raspiEthOffsetX = padding + wingHeight + cubeHeight + self.unittouu("3.8 cm") raspiEthOffsetY = padding + wingHeight + cubeHeight - self.unittouu("0.3 cm") raspiSoundOffsetX = padding + wingHeight + cubeHeight + cubeDepth + self.unittouu("0.3 cm") raspiSoundOffsetY = padding + wingHeight + cubeHeight + self.unittouu("3.5 cm") raspiHdmiOffsetX = padding + wingHeight + cubeHeight + cubeDepth + self.unittouu("0.3 cm") raspiHdmiOffsetY = padding + wingHeight + cubeHeight + self.unittouu("6.0 cm") raspiMusbOffsetX = padding + wingHeight + cubeHeight + cubeDepth + self.unittouu("0.3 cm") raspiMusbOffsetY = padding + wingHeight + cubeHeight + self.unittouu("7.9 cm") raspiSdCardOffsetX = padding + wingHeight + cubeHeight + self.unittouu("2.2 cm") raspiSdCardOffsetY = padding + wingHeight + cubeHeight + cubeWidth # Draw the basic shape (cutting edges). self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, layer, (padding, padding + cubeHeight + cubeWidth), (padding + 2 * wingHeight + cubeHeight, padding + 2 * wingHeight + 2 * cubeHeight + cubeWidth), (padding + cubeHeight + cubeDepth, padding + 2 * wingHeight + 2 * cubeHeight + cubeWidth), (padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth), (padding + 2 * wingHeight + 2 * cubeHeight + cubeDepth, padding + 2 * wingHeight + cubeHeight + cubeWidth), (padding + 2 * wingHeight + 2 * cubeHeight + cubeDepth + smallWingWidth, padding + 2 * wingHeight + cubeHeight + cubeWidth), (padding + 2 * wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + 2 * wingHeight + cubeHeight + largeWingWidth), (padding + 2 * wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + 2 * wingHeight + cubeHeight), (padding + 2 * cubeHeight + 2 * cubeDepth, padding + cubeHeight), (padding + 2 * wingHeight + 2 * cubeHeight + cubeDepth, padding + cubeHeight), (padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + cubeHeight + wingHeight), (padding + cubeHeight + cubeDepth, padding), (padding + 2 * wingHeight + cubeHeight, padding), (padding, padding + 2 * wingHeight + cubeHeight), (padding, padding + cubeHeight + cubeWidth), ) # Draw the headline boxes. leftLayerAttrs = { 'transform' : 'rotate(270, ' + str(padding + wingHeight + (cubeHeight / 2)) + ',' + str(padding + wingHeight + cubeHeight + (cubeWidth / 2)) + ')' } leftLayer = inkex.etree.SubElement(svg, 'g', leftLayerAttrs) leftLayer.set(inkex.addNS('label', 'inkscape'), 'Left Side') leftLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') self.drawSide(padding + wingHeight + (cubeHeight / 2) - (cubeWidth / 2), padding + wingHeight + cubeHeight + (cubeWidth / 2) - (cubeHeight / 2), cubeWidth, cubeHeight, boxBorder, boxBorderColor, leftLayer, self.sideOneText, self.titleBgColor, self.textColor, boxTitleFontSize, self.sideOneHint, self.hintBgColor, self.hintColor, boxHintFontSize, self.sideOneIcon) topLayer = inkex.etree.SubElement(svg, 'g', {}) topLayer.set(inkex.addNS('label', 'inkscape'), 'Top Side') topLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') self.drawSide(padding + wingHeight + cubeHeight, padding + wingHeight, cubeDepth, cubeHeight, boxBorder, boxBorderColor, topLayer, self.sideTwoText, self.titleBgColor, self.textColor, boxTitleFontSize, self.sideTwoHint, self.hintBgColor, self.hintColor, boxHintFontSize, self.sideTwoIcon) rightLayerAttrs = { 'transform' : 'rotate(90, ' + str(padding + wingHeight + cubeHeight + cubeDepth + (cubeHeight / 2)) + ',' + str(padding + wingHeight + cubeHeight + (cubeWidth / 2)) + ')' } rightLayer = inkex.etree.SubElement(svg, 'g', rightLayerAttrs) rightLayer.set(inkex.addNS('label', 'inkscape'), 'Right Side') rightLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') self.drawSide(padding + wingHeight + cubeHeight + cubeDepth + (cubeHeight / 2) - (cubeWidth / 2), padding + wingHeight + cubeHeight + (cubeWidth / 2) - (cubeHeight / 2), cubeWidth, cubeHeight, boxBorder, boxBorderColor, rightLayer, self.sideThreeText, self.titleBgColor, self.textColor, boxTitleFontSize, self.sideThreeHint, self.hintBgColor, self.hintColor, boxHintFontSize, self.sideThreeIcon) bottomLayerAttrs = { 'transform' : 'rotate(180, ' + str(padding + wingHeight + cubeHeight + (cubeDepth / 2)) + ',' + str(padding + wingHeight + cubeHeight + cubeWidth + (cubeHeight / 2)) + ')' } bottomLayer = inkex.etree.SubElement(svg, 'g', bottomLayerAttrs) bottomLayer.set(inkex.addNS('label', 'inkscape'), 'Bottom Side') bottomLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') self.drawSide(padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeWidth, cubeDepth, cubeHeight, boxBorder, boxBorderColor, bottomLayer, self.sideFourText, self.titleBgColor, self.textColor, boxTitleFontSize, self.sideFourHint, self.hintBgColor, self.hintColor, boxHintFontSize, self.sideFourIcon) # ... and the cutting edges for the slots. self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, topLayer, (raspiUsb1OffsetX, raspiUsb1OffsetY), (raspiUsb1OffsetX + raspiUsbWidth, raspiUsb1OffsetY), (raspiUsb1OffsetX + raspiUsbWidth, raspiUsb1OffsetY - raspiUsbHeight), (raspiUsb1OffsetX, raspiUsb1OffsetY - raspiUsbHeight), (raspiUsb1OffsetX, raspiUsb1OffsetY) ) self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, topLayer, (raspiUsb2OffsetX, raspiUsb2OffsetY), (raspiUsb2OffsetX + raspiUsbWidth, raspiUsb2OffsetY), (raspiUsb2OffsetX + raspiUsbWidth, raspiUsb2OffsetY - raspiUsbHeight), (raspiUsb2OffsetX, raspiUsb2OffsetY - raspiUsbHeight), (raspiUsb2OffsetX, raspiUsb2OffsetY) ) self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, topLayer, (raspiEthOffsetX, raspiEthOffsetY), (raspiEthOffsetX + raspiEthWidth, raspiEthOffsetY), (raspiEthOffsetX + raspiEthWidth, raspiEthOffsetY - raspiEthHeight), (raspiEthOffsetX, raspiEthOffsetY - raspiEthHeight), (raspiEthOffsetX, raspiEthOffsetY) ) rightLayer2Attrs = { 'transform' : 'rotate(0, ' + str(padding + wingHeight + cubeHeight + cubeDepth + (cubeHeight / 2)) + ',' + str(padding + wingHeight + cubeHeight + (cubeWidth / 2)) + ')' } rightLayer2 = inkex.etree.SubElement(svg, 'g', rightLayer2Attrs) rightLayer2.set(inkex.addNS('label', 'inkscape'), 'Right Side') rightLayer2.set(inkex.addNS('groupmode', 'inkscape'), 'layer') self.drawSide(padding + wingHeight + cubeHeight + cubeDepth + (cubeHeight / 2) - (cubeWidth / 2), padding + wingHeight + cubeHeight + (cubeWidth / 2) - (cubeHeight / 2), cubeWidth, cubeHeight, boxBorder, boxBorderColor, rightLayer, self.sideThreeText, self.titleBgColor, self.textColor, boxTitleFontSize, self.sideThreeHint, self.hintBgColor, self.hintColor, boxHintFontSize, self.sideThreeIcon) self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, rightLayer2, (raspiSoundOffsetX, raspiSoundOffsetY), (raspiSoundOffsetX + raspiSoundHeight, raspiSoundOffsetY), (raspiSoundOffsetX + raspiSoundHeight, raspiSoundOffsetY - raspiSoundWidth), (raspiSoundOffsetX, raspiSoundOffsetY - raspiSoundWidth), (raspiSoundOffsetX, raspiSoundOffsetY) ) self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, rightLayer2, (raspiHdmiOffsetX, raspiHdmiOffsetY), (raspiHdmiOffsetX + raspiHdmiHeight, raspiHdmiOffsetY), (raspiHdmiOffsetX + raspiHdmiHeight, raspiHdmiOffsetY - raspiHdmiWidth), (raspiHdmiOffsetX, raspiHdmiOffsetY - raspiHdmiWidth), (raspiHdmiOffsetX, raspiHdmiOffsetY) ) self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, rightLayer2, (raspiMusbOffsetX, raspiMusbOffsetY), (raspiMusbOffsetX + raspiMusbHeight, raspiMusbOffsetY), (raspiMusbOffsetX + raspiMusbHeight, raspiMusbOffsetY - raspiMusbWidth), (raspiMusbOffsetX, raspiMusbOffsetY - raspiMusbWidth), (raspiMusbOffsetX, raspiMusbOffsetY) ) self.drawPolygon( borderWidth, self.borderColor, self.mainBgColor, False, layer, (raspiSdCardOffsetX, raspiSdCardOffsetY), (raspiSdCardOffsetX + raspiSdCardWidth, raspiSdCardOffsetY), (raspiSdCardOffsetX + raspiSdCardWidth, raspiSdCardOffsetY - raspiSdCardHeight), (raspiSdCardOffsetX, raspiSdCardOffsetY - raspiSdCardHeight), (raspiSdCardOffsetX, raspiSdCardOffsetY) ) # Draw the top ... self.drawTopBot(padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, cubeDepth, cubeWidth, boxBorder, boxBorderColor, svg, self.topText, self.topBgColor, self.titleColor, cubeHeight / 5, self.topHint, cubeHeight / 25 * 3, self.topIcon) # ... and the bottom layer. self.drawTopBot(padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight, cubeDepth, cubeWidth, boxBorder, boxBorderColor, svg, self.bottomText, self.bottomBgColor, self.titleColor, cubeHeight / 5, self.bottomHint, cubeHeight / 25 * 3, self.bottomIcon) # Finally create a new layer for the inner folding and cutting edges ... innerEdgesLayer = inkex.etree.SubElement(svg, 'g', {}) innerEdgesLayer.set(inkex.addNS('label', 'inkscape'), 'Inner Edges') innerEdgesLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') # ... and draw the inner edges, ... self.drawPolygon( borderWidth, self.borderColor, None, True, innerEdgesLayer, (padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeWidth), (padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight + cubeWidth), (padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight), (padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight), (padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeWidth) ) # ... the wing folding edges, ... self.drawLine( padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, padding + 2 * wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, padding + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + cubeHeight + cubeWidth, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight, padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + 2 * wingHeight + cubeHeight, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight, padding + 2 * cubeHeight + 2 * cubeDepth, padding + wingHeight + cubeHeight, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, padding + 2 * wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, borderWidth, self.borderColor, False, innerEdgesLayer) # ... the triangle folding edges, ... self.drawLine( padding + wingHeight, padding + wingHeight + cubeHeight + cubeWidth, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeWidth, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeWidth, padding + wingHeight + cubeHeight, padding + wingHeight + 2 * cubeHeight + cubeWidth, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth + cubeHeight, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight, padding + wingHeight, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight, borderWidth, self.borderColor, True, innerEdgesLayer) # ... the inner triangle folding edges, ... self.drawLine( padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeWidth, padding + wingHeight + cubeHeight - cubeHeight / 2, padding + wingHeight + cubeHeight + cubeWidth + cubeHeight / 2, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, padding + wingHeight + cubeHeight + cubeDepth + cubeHeight / 2, padding + wingHeight + cubeHeight + cubeWidth + cubeHeight / 2, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeDepth + cubeHeight / 2, padding + wingHeight + cubeHeight - cubeHeight / 2, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight - cubeHeight / 2, padding + wingHeight + cubeHeight - cubeHeight / 2, borderWidth, self.borderColor, True, innerEdgesLayer) # ... the middle folding edges ... self.drawLine( padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, padding + wingHeight + cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, borderWidth, self.borderColor, True, innerEdgesLayer) self.drawLine( padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight, padding + wingHeight + 2 * cubeHeight + cubeDepth, padding + wingHeight + cubeHeight + cubeWidth, borderWidth, self.borderColor, True, innerEdgesLayer) # ... and the inner cutting edges. self.drawLine( padding + wingHeight + cubeHeight + wingHeight / 2, padding + wingHeight, padding + wingHeight + cubeHeight + cubeDepth - wingHeight / 2, padding + wingHeight, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight, padding + wingHeight + cubeHeight + wingHeight / 2, padding + wingHeight, padding + wingHeight + cubeHeight + cubeWidth - wingHeight / 2, borderWidth, self.borderColor, False, innerEdgesLayer) self.drawLine( padding + wingHeight + cubeHeight + wingHeight / 2, padding + wingHeight + 2 * cubeHeight + cubeWidth, padding + wingHeight + cubeHeight + cubeDepth - wingHeight / 2, padding + wingHeight + 2 * cubeHeight + cubeWidth, borderWidth, self.borderColor, False, innerEdgesLayer)
def effect(self): svg_file = self.args[-1] ttmp_orig = self.document.getroot() docname = ttmp_orig.get(inkex.addNS('docname',u'sodipodi')) if docname is None: docname = self.args[-1] doc_scale = self.getDocumentScale() res_scale = eval(self.options.resolution) / 96.0 scale = doc_scale * res_scale pageHeight = self.uutounit(self.unittouu(self.getDocumentHeight()), "px") pageWidth = self.uutounit(self.unittouu(self.getDocumentWidth()), "px") # Create os temp dir (to store exported pngs and Gimp log file) self.tmp_dir = tempfile.mkdtemp() # Guides hGuides = [] vGuides = [] if self.options.saveGuides: # Grab all guide tags in the namedview tag guideXpath = "sodipodi:namedview/sodipodi:guide" for guideNode in self.document.xpath(guideXpath, namespaces=inkex.NSS): ori = guideNode.get('orientation') if ori == '0,1': # This is a horizontal guide pos = self.uutounit(float(guideNode.get('position').split(',')[1]), "px") * doc_scale # GIMP doesn't like guides that are outside of the image if pos > 0 and pos < pageHeight: # The origin is at the top in GIMP land hGuides.append(str(int(round((pageHeight - pos) * res_scale)))) elif ori == '1,0': # This is a vertical guide pos = self.uutounit(float(guideNode.get('position').split(',')[0]), "px") * doc_scale # GIMP doesn't like guides that are outside of the image if pos > 0 and pos < pageWidth: vGuides.append(str(int(round(pos * res_scale)))) hGList = ' '.join(hGuides) vGList = ' '.join(vGuides) # Grid gridSpacingFunc = '' gridOriginFunc = '' # GIMP only allows one rectangular grid gridXpath = "sodipodi:namedview/inkscape:grid[@type='xygrid' and (not(@units) or @units='px')]" if (self.options.saveGrid and self.document.xpath(gridXpath, namespaces=inkex.NSS)): gridNode = self.xpathSingle(gridXpath) if gridNode != None: # These attributes could be nonexistent spacingX = gridNode.get('spacingx') if spacingX == None: spacingX = 1 else: spacingX = self.uutounit(float(spacingX),"px") * scale spacingY = gridNode.get('spacingy') if spacingY == None: spacingY = 1 else: spacingY = self.uutounit(float(spacingY),"px") * scale originX = gridNode.get('originx') if originX == None: originX = 0 else: originX = self.uutounit(float(originX),"px") * scale originY = gridNode.get('originy') if originY == None: originY = 0 else: originY = self.uutounit(float(originY),"px") * doc_scale offsetY = pageHeight % (self.uutounit(float(spacingY),"px") * doc_scale) originY = (pageHeight - originY) * res_scale gridSpacingFunc = '(gimp-image-grid-set-spacing img %s %s)' % (int(round(float(spacingX))), int(round(float(spacingY)))) gridOriginFunc = '(gimp-image-grid-set-offset img %s %s)'% (int(round(float(originX))), int(round(float(originY)))) # Layers area = '--export-area-page' opacity = '--export-background-opacity=' resolution = '--export-dpi=' + self.options.resolution if self.options.layerBackground: opacity += "1" else: opacity += "0" pngs = [] names = [] self.valid = 0 path = "/svg:svg/*[name()='g' or @style][@id]" for node in self.document.xpath(path, namespaces=inkex.NSS): if len(node) > 0: # Get rid of empty layers self.valid = 1 id = node.get('id') if node.get("{" + inkex.NSS["inkscape"] + "}label"): name = node.get("{" + inkex.NSS["inkscape"] + "}label") else: name = id filename = os.path.join(self.tmp_dir, "%s.png" % id) command = "inkscape -i \"%s\" -j %s %s -e \"%s\" %s %s" % (id, area, opacity, filename, svg_file, resolution) p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE) return_code = p.wait() f = p.stdout err = p.stderr stdin = p.stdin f.read() f.close() err.close() stdin.close() if return_code != 0: self.clear_tmp() raise GimpXCFInkscapeNotInstalled if os.name == 'nt': filename = filename.replace("\\", "/") pngs.append(filename) names.append(name) if (self.valid == 0): self.clear_tmp() inkex.errormsg(_('This extension requires at least one non empty layer.')) else: filelist = '"%s"' % '" "'.join(pngs) namelist = '"%s"' % '" "'.join(names) xcf = os.path.join(self.tmp_dir, "%s.xcf" % docname) if os.name == 'nt': xcf = xcf.replace("\\", "/") script_fu = """ (tracing 1) (define (png-to-layer img png_filename layer_name) (let* ( (png (car (file-png-load RUN-NONINTERACTIVE png_filename png_filename))) (png_layer (car (gimp-image-get-active-layer png))) (xcf_layer (car (gimp-layer-new-from-drawable png_layer img))) ) (gimp-image-add-layer img xcf_layer -1) (gimp-drawable-set-name xcf_layer layer_name) ) ) (let* ( (img (car (gimp-image-new 200 200 RGB))) ) (gimp-image-set-resolution img %s %s) (gimp-image-undo-disable img) (for-each (lambda (names) (png-to-layer img (car names) (cdr names)) ) (map cons '(%s) '(%s)) ) (gimp-image-resize-to-layers img) (for-each (lambda (hGuide) (gimp-image-add-hguide img hGuide) ) '(%s) ) (for-each (lambda (vGuide) (gimp-image-add-vguide img vGuide) ) '(%s) ) %s %s (gimp-image-undo-enable img) (gimp-file-save RUN-NONINTERACTIVE img (car (gimp-image-get-active-layer img)) "%s" "%s")) (gimp-quit 0) """ % (self.options.resolution, self.options.resolution, filelist, namelist, hGList, vGList, gridSpacingFunc, gridOriginFunc, xcf, xcf) junk = os.path.join(self.tmp_dir, 'junk_from_gimp.txt') command = 'gimp -i --batch-interpreter plug-in-script-fu-eval -b - > %s 2>&1' % junk p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE) f = p.stdin out = p.stdout err = p.stderr f.write(script_fu.encode('utf-8')) return_code = p.wait() if p.returncode != 0: self.clear_tmp() raise GimpXCFGimpNotInstalled f.close() err.close() out.close() # Uncomment these lines to see the output from gimp #err = open(junk, 'r') #inkex.debug(err.read()) #err.close() try: x = open(xcf, 'rb') except: self.clear_tmp() raise GimpXCFScriptFuError if os.name == 'nt': try: import msvcrt msvcrt.setmode(1, os.O_BINARY) except: pass try: sys.stdout.write(x.read()) finally: x.close() self.clear_tmp()
def effect(self): """ Calculate Gear factors from inputs. - Make list of radii, angles, and centers for each tooth and iterate through them - Turn on other visual features e.g. cross, rack, annotations, etc """ path_stroke = '#000000' # might expose one day path_fill = 'none' # no fill - just a line path_stroke_width = 0.6 # might expose one day path_stroke_light = path_stroke_width * 0.25 # guides are thinner # warnings = [] # list of extra messages to be shown in annotations # calculate unit factor for units defined in dialog. unit_factor = self.calc_unit_factor() # User defined options teeth = self.options.teeth # Angle of tangent to tooth at circular pitch wrt radial line. angle = self.options.angle # Clearance: Radial distance between top of tooth on one gear to # bottom of gap on another. clearance = self.options.clearance * unit_factor mount_hole = self.options.mount_hole * unit_factor # for spokes mount_radius = self.options.mount_diameter * 0.5 * unit_factor spoke_count = self.options.spoke_count spoke_width = self.options.spoke_width * unit_factor holes_rounding = self.options.holes_rounding * unit_factor # unused # visible guide lines centercross = self.options.centercross # draw center or not (boolean) pitchcircle = self.options.pitchcircle # draw pitch circle or not (boolean) # Accuracy of teeth curves accuracy_involute = 20 # Number of points of the involute curve accuracy_circular = 9 # Number of points on circular parts if self.options.accuracy is not None: if self.options.accuracy == 0: # automatic if teeth < 10: accuracy_involute = 20 elif teeth < 30: accuracy_involute = 12 else: accuracy_involute = 6 else: accuracy_involute = self.options.accuracy accuracy_circular = max(3, int(accuracy_involute / 2) - 1) # never less than three # print >>self.tty, "accuracy_circular=%s accuracy_involute=%s" % (accuracy_circular, accuracy_involute) # Pitch (circular pitch): Length of the arc from one tooth to the next) # Pitch diameter: Diameter of pitch circle. pitch = self.calc_circular_pitch() # Replace section below with this call to get the combined gear_calculations() above (pitch_radius, base_radius, addendum, dedendum, outer_radius, root_radius, tooth) = gear_calculations(teeth, pitch, angle, clearance, self.options.internal_ring, self.options.profile_shift * 0.01) # Detect Undercut of teeth ## undercut = int(ceil(undercut_min_teeth( angle ))) ## needs_undercut = teeth < undercut #? no longer needed ? if have_undercut(teeth, angle, 1.0): min_teeth = int(ceil(undercut_min_teeth(angle, 1.0))) min_angle = undercut_min_angle(teeth, 1.0) + .1 max_k = undercut_max_k(teeth, angle) msg = "Undercut Warning: This gear (%d teeth) will not work well.\nTry tooth count of %d or more,\nor a pressure angle of %.1f [deg] or more,\nor try a profile shift of %d %%.\nOr other decent combinations." % ( teeth, min_teeth, min_angle, int(100. * max_k) - 100.) # alas annotation cannot handle the degree symbol. Also it ignore newlines. # so split and make a list warnings.extend(msg.split("\n")) if self.options.undercut_alert: inkex.debug(msg) else: print >> self.tty, msg # All base calcs done. Start building gear points = generate_spur_points(teeth, base_radius, pitch_radius, outer_radius, root_radius, accuracy_involute, accuracy_circular) ## half_thick_angle = two_pi / (4.0 * teeth ) #?? = pi / (2.0 * teeth) ## pitch_to_base_angle = involute_intersect_angle( base_radius, pitch_radius ) ## pitch_to_outer_angle = involute_intersect_angle( base_radius, outer_radius ) - pitch_to_base_angle ## ## start_involute_radius = max(base_radius, root_radius) ## radii = linspace(start_involute_radius, outer_radius, accuracy_involute) ## angles = [involute_intersect_angle(base_radius, r) for r in radii] ## ## centers = [(x * two_pi / float( teeth) ) for x in range( teeth ) ] ## points = [] ## ## for c in centers: ## # Angles ## pitch1 = c - half_thick_angle ## base1 = pitch1 - pitch_to_base_angle ## offsetangles1 = [ base1 + x for x in angles] ## points1 = [ point_on_circle( radii[i], offsetangles1[i]) for i in range(0,len(radii)) ] ## ## pitch2 = c + half_thick_angle ## base2 = pitch2 + pitch_to_base_angle ## offsetangles2 = [ base2 - x for x in angles] ## points2 = [ point_on_circle( radii[i], offsetangles2[i]) for i in range(0,len(radii)) ] ## ## points_on_outer_radius = [ point_on_circle(outer_radius, x) for x in linspace(offsetangles1[-1], offsetangles2[-1], accuracy_circular) ] ## ## if root_radius > base_radius: ## pitch_to_root_angle = pitch_to_base_angle - involute_intersect_angle(base_radius, root_radius ) ## root1 = pitch1 - pitch_to_root_angle ## root2 = pitch2 + pitch_to_root_angle ## points_on_root = [point_on_circle (root_radius, x) for x in linspace(root2, root1+(two_pi/float(teeth)), accuracy_circular) ] ## p_tmp = points1 + points_on_outer_radius[1:-1] + points2[::-1] + points_on_root[1:-1] # [::-1] reverses list; [1:-1] removes first and last element ## else: ## points_on_root = [point_on_circle (root_radius, x) for x in linspace(base2, base1+(two_pi/float(teeth)), accuracy_circular) ] ## p_tmp = points1 + points_on_outer_radius[1:-1] + points2[::-1] + points_on_root # [::-1] reverses list ## ## points.extend( p_tmp ) path = points_to_svgd(points) bbox_center = points_to_bbox_center(points) # Spokes (add to current path) if not self.options.internal_ring: # only draw internals if spur gear spokes_path, msg = generate_spokes_path(root_radius, spoke_width, spoke_count, mount_radius, mount_hole, unit_factor, self.options.units) warnings.extend(msg) path += spokes_path # Draw mount hole # A : rx,ry x-axis-rotation, large-arch-flag, sweepflag x,y r = mount_hole / 2 path += ("M %f,%f" % (0, r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, -r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, r)) else: # its a ring gear # which only has an outer ring where width = spoke width r = outer_radius + spoke_width path += ("M %f,%f" % (0, r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, -r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, r)) # Embed gear in group to make animation easier: # Translate group, Rotate path. t = 'translate(' + str(self.view_center[0]) + ',' + str( self.view_center[1]) + ')' g_attribs = { inkex.addNS('label', 'inkscape'): 'Gear' + str(teeth), inkex.addNS('transform-center-x', 'inkscape'): str(-bbox_center[0]), inkex.addNS('transform-center-y', 'inkscape'): str(-bbox_center[1]), 'transform': t, 'info': 'N:' + str(teeth) + '; Pitch:' + str(pitch) + '; Pressure Angle: ' + str(angle) } # add the group to the current layer g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) # Create gear path under top level group style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_width } gear_attribs = {'style': simplestyle.formatStyle(style), 'd': path} gear = inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), gear_attribs) # Add center if centercross: style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_light } cs = str(pitch / 3) # centercross length d = 'M-' + cs + ',0L' + cs + ',0M0,-' + cs + 'L0,' + cs # 'M-10,0L10,0M0,-10L0,10' center_attribs = { inkex.addNS('label', 'inkscape'): 'Center cross', 'style': simplestyle.formatStyle(style), 'd': d } center = inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), center_attribs) # Add pitch circle (for mating) if pitchcircle: style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_light } draw_SVG_circle(g, pitch_radius, 0, 0, 'Pitch circle', style) # Add Rack (below) if self.options.drawrack: base_height = self.options.base_height * unit_factor tab_width = self.options.base_tab * unit_factor tooth_count = self.options.teeth_length (points, guide_path) = generate_rack_points(tooth_count, pitch, addendum, angle, base_height, tab_width, clearance, pitchcircle) path = points_to_svgd(points) # position below Gear, so that it meshes nicely # xoff = 0 ## if teeth % 4 == 2. # xoff = -0.5*pitch ## if teeth % 4 == 0. # xoff = -0.75*pitch ## if teeth % 4 == 3. # xoff = -0.25*pitch ## if teeth % 4 == 1. xoff = (-0.5, -0.25, 0, -0.75)[teeth % 4] * pitch t = 'translate(' + str(xoff) + ',' + str(pitch_radius) + ')' g_attribs = { inkex.addNS('label', 'inkscape'): 'RackGear' + str(tooth_count), 'transform': t } rack = inkex.etree.SubElement(g, 'g', g_attribs) # Create SVG Path for gear style = { 'stroke': path_stroke, 'fill': 'none', 'stroke-width': path_stroke_width } gear_attribs = {'style': simplestyle.formatStyle(style), 'd': path} gear = inkex.etree.SubElement(rack, inkex.addNS('path', 'svg'), gear_attribs) if guide_path is not None: style2 = { 'stroke': path_stroke, 'fill': 'none', 'stroke-width': path_stroke_light } gear_attribs2 = { 'style': simplestyle.formatStyle(style2), 'd': guide_path } gear = inkex.etree.SubElement(rack, inkex.addNS('path', 'svg'), gear_attribs2) # Add Annotations (above) if self.options.annotation: outer_dia = outer_radius * 2 if self.options.internal_ring: outer_dia += 2 * spoke_width notes = [] notes.extend(warnings) #notes.append('Document (%s) scale conversion = %2.4f' % (self.document.getroot().find(inkex.addNS('namedview', 'sodipodi')).get(inkex.addNS('document-units', 'inkscape')), unit_factor)) notes.extend([ 'Teeth: %d CP: %2.4f(%s) ' % (teeth, pitch / unit_factor, self.options.units), 'DP: %2.3f Module: %2.4f' % (pi / pitch * unit_factor, pitch / pi * 25.4), 'Pressure Angle: %2.2f degrees' % (angle), 'Pitch diameter: %2.3f %s' % (pitch_radius * 2 / unit_factor, self.options.units), 'Outer diameter: %2.3f %s' % (outer_dia / unit_factor, self.options.units), 'Base diameter: %2.3f %s' % (base_radius * 2 / unit_factor, self.options.units) #, #'Addendum: %2.4f %s' % (addendum / unit_factor, self.options.units), #'Dedendum: %2.4f %s' % (dedendum / unit_factor, self.options.units) ]) # text height relative to gear size. # ranges from 10 to 22 over outer radius size 60 to 360 text_height = max(10, min(10 + (outer_dia - 60) / 24, 22)) # position above y = -outer_radius - (len(notes) + 1) * text_height * 1.2 for note in notes: self.add_text(g, note, [0, y], text_height) y += text_height * 1.2
def make_paths(self, txt2paths=False ): self.txt2paths = txt2paths msg = "" ## self.inkscape_dpi = None ## try: ## Inkscape_Version = self.document.getroot().xpath('@inkscape:version', namespaces=inkex.NSS)[0].split(" ")[0] ## except: ## Inkscape_Version = None ## ## if Inkscape_Version <= .91: ## self.inkscape_dpi = 90.0 ## else: ## self.inkscape_dpi = 96.0 if (self.txt2paths): self.convert_text2paths() try: h_mm = self.unit2mm(self.document.getroot().xpath('@height', namespaces=inkex.NSS)[0]) w_mm = self.unit2mm(self.document.getroot().xpath('@width', namespaces=inkex.NSS)[0]) except: line1 = "Units not set in SVG File.\n" line2 = "Inkscape v0.90 or higher makes SVG files with units data.\n" line3 = "1.) In Inkscape (v0.90 or higher) select 'File'-'Document Properties'." line4 = "2.) In the 'Custom Size' region on the 'Page' tab set the 'Units' to 'mm' or 'in'." raise Exception("%s\n%s\n%s\n%s" %(line1,line2,line3,line4)) try: view_box_str = self.document.getroot().xpath('@viewBox', namespaces=inkex.NSS)[0] view_box_list = view_box_str.split(' ') Wpix = float(view_box_list[2]) Hpix = float(view_box_list[3]) scale_h = h_mm/Hpix scale_w = w_mm/Wpix Dx = float(view_box_list[0]) * scale_w Dy = float(view_box_list[1]) * scale_h except: line1 = "Cannot determine SVG scale (SVG Viewox Missing).\n" line2 = "In Inkscape (v0.92) select 'File'-'Document Properties'." line3 = "In the 'Scale' region on the 'Page' tab change the 'Scale x:' value" line4 = "and press enter. Changing the value will add the Viewbox attribute." line5 = "The 'Scale x:' can then be changed back to the original value." ##if self.inkscape_dpi==None: raise Exception("%s\n%s\n%s\n%s\n%s" %(line1,line2,line3,line4,line5)) ## print "Using guessed dpi value of: ",self.inkscape_dpi ## scale_h = 25.4/self.inkscape_dpi ## scale_w = 25.4/self.inkscape_dpi ## Dx = 0 ## Dy = 0 if abs(1.0-scale_h/scale_w) > .01: line1 ="SVG Files with different scales in X and Y are not supported.\n" line2 ="In Inkscape (v0.92): 'File'-'Document Properties'" line3 ="on the 'Page' tab adjust 'Scale x:' in the 'Scale' section" raise Exception("%s\n%s\n%s" %(line1,line2,line3)) for node in self.document.getroot().xpath('//svg:g', namespaces=inkex.NSS): if node.get(inkex.addNS('groupmode', 'inkscape')) == 'layer': layer = node.get(inkex.addNS('label', 'inkscape')) self.layernames.append(layer.lower()) layer = layer.replace(' ', '_') if layer and not layer in self.layers: self.layers.append(layer) self.groupmat = [[[scale_w, 0.0, 0.0-Dx], [0.0 , -scale_h, h_mm+Dy]]] self.process_group(self.document.getroot()) ################################################# #msg = msg + "Height(mm)= %f\n" %(h_mm) #msg = msg + "Width (mm)= %f\n" %(w_mm) #inkex.errormsg(_(msg)) ## if not self.raster: ## xmin= self.lines[0][0]+0.0 ## xmax= self.lines[0][0]+0.0 ## ymin= self.lines[0][1]+0.0 ## ymax= self.lines[0][1]+0.0 ## for line in self.lines: ## x1= line[0] ## y1= line[1] ## x2= line[2] ## y2= line[3] ## xmin = min(min(xmin,x1),x2) ## ymin = min(min(ymin,y1),y2) ## xmax = max(max(xmax,x1),x2) ## ymax = max(max(ymax,y1),y2) ## else: xmin= 0.0 xmax= w_mm ymin= -h_mm ymax= 0.0 self.Make_PNG() self.Xsize=xmax-xmin self.Ysize=ymax-ymin Xcorner=xmin Ycorner=ymax for ii in range(len(self.lines)): self.lines[ii][0] = self.lines[ii][0]-Xcorner self.lines[ii][1] = self.lines[ii][1]-Ycorner self.lines[ii][2] = self.lines[ii][2]-Xcorner self.lines[ii][3] = self.lines[ii][3]-Ycorner self.cut_lines = [] self.eng_lines = [] for line in self.lines: ID=line[5] if (self.Cut_Type[ID]=="engrave"): self.eng_lines.append([line[0],line[1],line[2],line[3]]) elif (self.Cut_Type[ID]=="cut"): self.cut_lines.append([line[0],line[1],line[2],line[3]]) else: pass
def process_shape(self, node, mat, group_stroke = None): ################################# ### Determine the shape type ### ################################# try: i = node.tag.find('}') if i >= 0: tag_type = node.tag[i+1:] except: tag_type="" ############################################## ### Set a unique identifier for each shape ### ############################################## self.id_cnt=self.id_cnt+1 path_id = "ID%d"%(self.id_cnt) sw_flag = False changed = False ####################################### ### Handle references to CSS data ### ####################################### class_val = node.get('class') if class_val: css_data = "" for cv in class_val.split(' '): if css_data!="": css_data = self.CSS_values.get_css_value(tag_type,cv)+";"+css_data else: css_data = self.CSS_values.get_css_value(tag_type,cv) # Remove the reference to the CSS data del node.attrib['class'] # Check if a style entry already exists. If it does # append the the existing style data to the CSS data # otherwise create a new style entry. if node.get('style'): if css_data!="": css_data = css_data + ";" + node.get('style') node.set('style', css_data) else: node.set('style', css_data) style = node.get('style') self.Cut_Type[path_id]="raster" # Set default type to raster text_message_warning = "SVG File with Color Coded Text Outlines Found: (i.e. Blue: engrave/ Red: cut)" line1 = "SVG File with color coded text outlines found (i.e. Blue: engrave/ Red: cut)." line2 = "Automatic conversion to paths failed: Try upgrading to Inkscape .90 or later" line3 = "To convert manually in Inkscape: select the text then select \"Path\"-\"Object to Path\" in the menu bar." text_message_fatal = "%s\n\n%s\n\n%s" %(line1,line2,line3) ############################################## ### Handle 'style' data outside of style ### ############################################## stroke_outside = node.get('stroke') if not stroke_outside: stroke_outside = group_stroke if stroke_outside: stroke_width_outside = node.get('stroke-width') col = stroke_outside col= col.strip() if simplestyle.isColor(col): c=simplestyle.parseColor(col) (new_val,changed)=self.colmod(c[0],c[1],c[2],path_id) else: new_val = col if changed: node.set('stroke',new_val) node.set('stroke-width',"0.0") sw_flag = True if sw_flag == True: if node.tag == inkex.addNS('text','svg') or node.tag == inkex.addNS('flowRoot','svg'): if (self.txt2paths==False): raise SVG_TEXT_EXCEPTION(text_message_warning) else: raise Exception(text_message_fatal) ############################################## ### Handle 'style' data ### ############################################## if style: declarations = style.split(';') i_sw = -1 sw_prop = 'stroke-width' for i,decl in enumerate(declarations): parts = decl.split(':', 2) if len(parts) == 2: (prop, col) = parts prop = prop.strip().lower() #if prop in color_props: if prop == sw_prop: i_sw = i if prop == 'stroke': col= col.strip() if simplestyle.isColor(col): c=simplestyle.parseColor(col) (new_val,changed)=self.colmod(c[0],c[1],c[2],path_id) else: new_val = col if changed: declarations[i] = prop + ':' + new_val sw_flag = True if sw_flag == True: if node.tag == inkex.addNS('text','svg') or node.tag == inkex.addNS('flowRoot','svg'): if (self.txt2paths==False): raise SVG_TEXT_EXCEPTION(text_message_warning) else: raise Exception(text_message_fatal) if i_sw != -1: declarations[i_sw] = sw_prop + ':' + "0.0" else: declarations.append(sw_prop + ':' + "0.0") node.set('style', ';'.join(declarations)) ############################################## ##################################################### ### If vector data was found save the path data ### ##################################################### if changed: if node.tag == inkex.addNS('path','svg'): d = node.get('d') if not d: return p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('rect','svg'): x = float(node.get('x')) y = float(node.get('y')) width = float(node.get('width')) height = float(node.get('height')) rx = 0.0 ry = 0.0 if node.get('rx'): rx=float(node.get('rx')) if node.get('ry'): ry=float(node.get('ry')) if max(rx,ry) > 0.0: if rx==0.0 or ry==0.0: rx = max(rx,ry) ry = rx Rxmax = abs(width)/2.0 Rymax = abs(height)/2.0 rx = min(rx,Rxmax) ry = min(ry,Rymax) L1 = "M %f,%f %f,%f " %(x+rx , y , x+width-rx , y ) C1 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width , y+ry ) L2 = "M %f,%f %f,%f " %(x+width , y+ry , x+width , y+height-ry) C2 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width-rx , y+height ) L3 = "M %f,%f %f,%f " %(x+width-rx , y+height , x+rx , y+height ) C3 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x , y+height-ry) L4 = "M %f,%f %f,%f " %(x , y+height-ry, x , y+ry ) C4 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+rx , y ) d = L1 + C1 + L2 + C2 + L3 + C3 + L4 + C4 else: d = "M %f,%f %f,%f %f,%f %f,%f Z" %(x,y, x+width,y, x+width,y+height, x,y+height) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('circle','svg'): cx = float(node.get('cx') ) cy = float(node.get('cy')) r = float(node.get('r')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" %(cx+r,cy, r,r,cx,cy+r, r,r,cx-r,cy, r,r,cx,cy-r, r,r,cx+r,cy) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('ellipse','svg'): cx = float(node.get('cx')) cy = float(node.get('cy')) rx = float(node.get('rx')) ry = float(node.get('ry')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" %(cx+rx,cy, rx,ry,cx,cy+ry, rx,ry,cx-rx,cy, rx,ry,cx,cy-ry, rx,ry,cx+rx,cy) p = cubicsuperpath.parsePath(d) elif (node.tag == inkex.addNS('polygon','svg')) or (node.tag == inkex.addNS('polyline','svg')): points = node.get('points') if not points: return points = points.replace(',', ' ') while points.find(' ') > -1: points = points.replace(' ', ' ') points = points.strip().split(" ") d = "M " for i in range(0,len(points),2): x = float(points[i]) y = float(points[i+1]) d = d + "%f,%f " %(x,y) #Close the loop if it is a ploygon if node.tag == inkex.addNS('polygon','svg'): d = d + "Z" p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('line','svg'): x1 = float(node.get('x1')) y1 = float(node.get('y1')) x2 = float(node.get('x2')) y2 = float(node.get('y2')) d = "M " d = "M %f,%f %f,%f" %(x1,y1,x2,y2) p = cubicsuperpath.parsePath(d) else: #print("something was ignored") #print(node.tag) return trans = node.get('transform') if trans: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, p) ########################################## ## Break Curves down into small lines ### ########################################## f = self.flatness is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, f) is_flat = 1 except IndexError: break except: f += 0.1 if f>2 : break #something has gone very wrong. ########################################## rgb=(0,0,0) for sub in p: for i in range(len(sub)-1): x1 = sub[i][1][0] y1 = sub[i][1][1] x2 = sub[i+1][1][0] y2 = sub[i+1][1][1] self.lines.append([x1,y1,x2,y2,rgb,path_id])
def effect(self): # retrieve label label = self.options.label # define styles style1 = { 'fill': '#d6e6ec', 'fill-opacity': '1', 'stroke': '#000000', 'stroke-width': '4', 'stroke-linecap': 'butt', 'stroke-linejoin': 'miter', 'stroke-miterlimit': '4', 'stroke-opacity': '1', 'stroke-dasharray': 'none' } style2 = { 'fill': '#ff4343', 'fill-opacity': '1', 'stroke': 'none', 'display': 'inline' } style3 = { 'opacity': '0.3', 'fill': '#000000', 'fill-opacity': '1', 'stroke': 'none' } style4 = { 'fill': 'none', 'stroke': '#000000', 'stroke-width': '4', 'stroke-linecap': 'butt', 'stroke-linejoin': 'miter', 'stroke-miterlimit': '4', 'stroke-opacity': '1', 'stroke-dasharray': 'none', 'display': 'inline' } # Get access to main SVG document element and get its dimensions. svg = self.document.getroot() width = inkex.unittouu(svg.get('width')) height = inkex.unittouu(svg.get('height')) # Create a new group for the shape group = inkex.etree.SubElement(svg, 'g') group.set('transform', 'matrix(0.2,0,0,0.2,%f,%f)' % (width / 2, height / 2)) # back 1/5 path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style1)) path.set( 'd', 'm 53.626832,237.83881 132.865088,87.10045 -9.70888,14.6732 L 43.825127,252.64 z' ) group.append(path) # back 2/5 path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style1)) path.set( 'd', 'm 90.193079,213.41382 -21.810543,34.09817 103.387834,67.77647 23.5192,-35.63517 z' ) group.append(path) # back 3/5 path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style1)) path.set('d', 'm 249.1764,338.56763 0,17.63402 151.03923,0 0,-17.63402 z') group.append(path) # back 4/5 path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style1)) path.set(inkex.addNS('nodetypes', 'sodipodi'), 'cczccc') path.set( 'd', 'm 257.61006,356.20165 0,230.00899 c 0,0 27.64765,226.9422 66.70261,226.9422 39.05496,0 68.236,-226.9422 68.236,-226.9422 l 0,-230.00899 z' ) group.append(path) # back 5/5 path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style1)) path.set(inkex.addNS('nodetypes', 'sodipodi'), 'czcczcc') path.set( 'd', 'm 184.71041,327.63169 c 0,0 12.71439,12.24709 23.75073,15.53612 11.03634,3.28903 40.71526,0 40.71526,0 l 0,9.96706 c 0,0 -29.85465,3.5594 -41.79819,0 -11.94354,-3.5594 -27.59766,-18.0526 -27.59766,-18.0526 z' ) group.append(path) # content 1/1 path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style2)) path.set(inkex.addNS('nodetypes', 'sodipodi'), 'cczccc') path.set( 'd', 'm 257.61006,356.20165 0,230.00899 c 0,0 27.64765,226.9422 66.70261,226.9422 39.05496,0 68.236,-226.9422 68.236,-226.9422 l 0,-230.00899 z' ) path.set(inkex.addNS('label', 'inkscape'), label) group.append(path) # front 1/x rect = inkex.etree.Element(inkex.addNS('rect', 'svg')) rect.set('style', formatStyle(style3)) rect.set('width', '72.836182') rect.set('height', '7.666966') rect.set('x', '267.57712') rect.set('y', '397.60327') rect.set('ry', '2.8527629') group.append(rect) # front 2/x rect = inkex.etree.Element(inkex.addNS('rect', 'svg')) rect.set('style', formatStyle(style3)) rect.set('width', '72.836182') rect.set('height', '7.666966') rect.set('x', '267.57712') rect.set('y', '510.30768') rect.set('ry', '2.8527629') group.append(rect) # front 3/x rect = inkex.etree.Element(inkex.addNS('rect', 'svg')) rect.set('style', formatStyle(style3)) rect.set('width', '72.836182') rect.set('height', '7.666966') rect.set('x', '267.57712') rect.set('y', '623.77875') rect.set('ry', '2.8527629') group.append(rect) # front 4/x path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style4)) path.set('d', 'm 249.1764,338.56763 0,17.63402 151.03923,0 0,-17.63402 z') group.append(path) # front 5/x path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('style', formatStyle(style4)) path.set(inkex.addNS('nodetypes', 'sodipodi'), 'cczccc') path.set( 'd', 'm 257.61006,356.20165 0,230.00899 c 0,0 27.64765,226.9422 66.70261,226.9422 39.05496,0 68.236,-226.9422 68.236,-226.9422 l 0,-230.00899 z' ) group.append(path)
def effect(self): # loop over all selected paths if self.options.selection == "Path_lengthselection": for id, node in self.svg.selected.items(): if node.tag == inkex.addNS('path', 'svg'): l1, l2, l3, l4, l5 = [], [], [], [], [] p = paths.CubicSuperPath(inkex.paths.Path(node.get('d'))) slengths = csplength(p) b = [slengths, p] # path length select for x in range(0, len(slengths)): if sum(b[0][x]) < self.options.len1: l1.append(b[1][x]) if self.options.len2 > sum( b[0][x]) >= self.options.len1: l2.append(b[1][x]) if self.options.len3 > sum( b[0][x]) >= self.options.len2: l3.append(b[1][x]) if self.options.len4 > sum( b[0][x]) >= self.options.len3: l4.append(b[1][x]) if sum(b[0][x]) >= self.options.len4: l5.append(b[1][x]) # make path lensel = [l1, l2, l3, l4, l5] strlen = [ '#FF0001', '#00FF02', '#AAFF03', '#87CEE4', '#000FF5' ] for i, x in zip(strlen, lensel): s = { 'stroke-linejoin': 'miter', 'stroke-width': '0.5px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': i, 'stroke-linecap': 'butt', 'fill': 'none' } attribs = { 'style': str(inkex.Style(s)), 'd': str( paths.Path( paths.CubicSuperPath(x).to_path().to_arrays())) } etree.SubElement(node.getparent(), inkex.addNS('path', 'svg'), attribs) if self.options.selection == "Path_slantselection": for id, node in self.svg.selected.items(): if node.tag == inkex.addNS('path', 'svg'): hor1, ver2, slan3 = [], [], [] p = paths.CubicSuperPath(inkex.paths.Path(node.get('d'))) # path slant select for i, x in enumerate(p): tn = roughBBox(x) if tn < self.options.hor: hor1.append(p[i]) elif tn > self.options.ver: ver2.append(p[i]) else: slan3.append(p[i]) # make path slnsel = [hor1, ver2, slan3] strsln = ['#FF0001', '#00FF02', '#000FF5'] for i, x in zip(strsln, slnsel): s = { 'stroke-linejoin': 'miter', 'stroke-width': '0.5px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': i, 'stroke-linecap': 'butt', 'fill': 'none' } attribs = { 'style': str(inkex.Style(s)), 'd': str( paths.Path( paths.CubicSuperPath(x).to_path().to_arrays())) } etree.SubElement(node.getparent(), inkex.addNS('path', 'svg'), attribs)
def newLayer(self, svg, name='no name'): layer = inkex.etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), name) layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') return layer
def effect(self): if (self.options.create_bearing_gear and self.options.active_tab == '"help"'): self.error("""English spport forum: http://www.cnc-club.ru/forum/viewforum.php?f=33 Russian support forum: http://cnc-club.ru/forum/viewtopic.php?f=15&t=287 """) return time_ = time.time() self.distance = self.options.distance * self.options.units self.options.linear_distance *= self.options.units self.options.gear_r *= self.options.units self.options.bearings_d *= self.options.units self.first_teeth = self.options.selected_puley_teeth self.second_teeth = self.options.generated_puley_teeth self.num = self.options.number_of_copies def add_circle(c, r, center_mark=False): return ("M%s,%s a %s,%s 0 1 1 %s,0 %s,%s 0 1 1 %s,0 z " % (c[0] + r, c[1], r, r, -2 * r, r, r, 2 * r) + #c+r,c r r -2*r r r 2*r (("M %s,%s l -11,-11 22,22 -11,-11 -11,11, 22,-22" % (c[0], c[1])) if center_mark else "")) c = list(self.view_center) d = "" d1 = "" if (self.options.create_bearing_gear and self.options.active_tab == '"linear_shaft"'): r = (self.options.gear_r * 2 + self.options.bearings_d / 2 + 100) for i in range(self.options.number_of_bearings): a = i * math.pi * 2 / self.options.number_of_bearings d += add_circle([ c[0] + math.cos(a) * self.options.gear_r, c[1] + math.sin(a) * self.options.gear_r ], self.options.bearings_d / 2) d1 += add_circle([ c[0] + math.cos(a) * self.options.gear_r, -r + c[1] + math.sin(a) * self.options.gear_r ], self.options.bearings_d / 2, True) d1 += add_circle([c[0], c[1] - r], self.options.gear_r, True) path = inkex.etree.SubElement( self.current_layer, inkex.addNS('path', 'svg'), { "d": d, "style": "stroke:#4d4d4d;fill:#ececec" }) path1 = inkex.etree.SubElement( self.current_layer, inkex.addNS('path', 'svg'), { "d": d1, "style": "stroke:#4d4d4d;fill:#ececec" }) csp = cubicsuperpath.parsePath(d) minx, miny, maxx, maxy = csp_true_bounds(csp) c1 = [(maxx[0] + minx[0]) / 2, (maxy[1] + miny[1]) / 2] path.set(inkex.addNS('transform-center-x', 'inkscape'), str(-c1[0] + c[0])) path.set(inkex.addNS('transform-center-y', 'inkscape'), str(-c1[1] + c[1])) self.selected = {"1": path} if len(self.selected) != 1: self.error('Please select one and only one path!', 'error') path = self.selected.values()[0] if "d" not in path.keys(): self.error('Please select a "Path"!', 'error') csp = cubicsuperpath.parsePath(path.get("d")) center_group = inkex.etree.SubElement(path.getparent(), inkex.addNS('g', 'svg')) group = inkex.etree.SubElement(path.getparent(), inkex.addNS('g', 'svg')) attrib = path.attrib if "transform" in path.keys(): t = path.get('transform') t = simpletransform.parseTransform(t) simpletransform.applyTransformToPath(t, csp) path.set("transform", "") path.set('d', cubicsuperpath.formatPath(csp)) inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), {"d": cubicsuperpath.formatPath(csp)}) self.error(path.get("transform")) # Will have to find center of bbox minx, miny, maxx, maxy = csp_true_bounds(csp) c1 = [(maxx[0] + minx[0]) / 2, (maxy[1] + miny[1]) / 2] w, h = max(maxx[0] - minx[0], abs(c1[0] - minx[0]), abs(c1[0] - maxx[0])), max(maxy[1] - miny[1], abs(c1[1] - miny[1]), abs(c1[1] - maxy[1])) if inkex.addNS('transform-center-x', 'inkscape') in path.keys(): c1[0] += float( path.get(inkex.addNS('transform-center-x', 'inkscape'))) if inkex.addNS('transform-center-y', 'inkscape') in path.keys(): c1[1] -= float( path.get(inkex.addNS('transform-center-y', 'inkscape'))) c2 = [c1[0] - self.distance, c1[1]] def get_transform(c1, c2, a1, a2): [c1x, c1y], [c2x, c2y] = c1, c2 # move c1 to 0 transform = [[1, 0, -c1x], [0, 1, -c1y]] # Rotate to a1 to 0 transform = simpletransform.composeTransform( [[math.cos(a1), -math.sin(a1), 0], [math.sin(a1), math.cos(a1), 0]], transform) # Move c2 to 0 transform = simpletransform.composeTransform( [[1, 0, -c2x + c1x], [0, 1, -c2y + c1y]], transform) # Rotate to a2 to 0 transform = simpletransform.composeTransform( [[math.cos(a2), -math.sin(a2), 0], [math.sin(a2), math.cos(a2), 0]], transform) # move c2 back to c2 transform = simpletransform.composeTransform( [[1, 0, c2x], [0, 1, c2y]], transform) return transform if not self.options.active_tab == '"linear_shaft"': # Radial gear if not self.options.variable_speed: for i in range(self.num): alpha = math.pi * 2 * (i) / self.num alpha1 = alpha * self.second_teeth alpha2 = alpha * self.first_teeth transform = get_transform(c1, c2, alpha1, alpha2) # add path's clone attrib["transform"] = simpletransform.formatTransform( transform) inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), attrib) else: def get_k(csp, c1, d): c2 = [c1[0] - d, c1[1]] alpha2_ = [] for n in range(self.num): alpha1 = math.pi * 2 * ( n) / self.num * self.second_teeth d_alpha1 = math.pi * 2 / self.num * self.second_teeth csp_ = [[[p[:] for p in point] for point in subpath] for subpath in csp] transform = get_transform(c1, c2, alpha1, 0) simpletransform.applyTransformToPath(transform, csp_) # r2 = distance to second gear's center [r2, i, j, t] = csp_to_point_distance(csp_, c2, dist_bounds=[0, 1e100], tolerance=.001) r2 = math.sqrt(r2) p = csp_at_t(csp_[i][j - 1], csp_[i][j], t) r1 = math.sqrt((p[0] - c1[0])**2 + (p[1] - c1[1])**2) # d_alpha2 = rotation speed factor if r2 == 0: return 1e100, [] alpha2_.append(d_alpha1 * r1 / r2) return math.pi * 2 * self.first_teeth / sum( alpha2_), alpha2_ #get K, firs calculate aproximate turn and then get the K if not self.options.optimize_distance: K, alpha2_ = get_k(csp, c1, self.distance) else: #set min and max distances dists = [ 0., math.sqrt(w**2 + h**2) * (1 + self.second_teeth / self.first_teeth) ] first = True for i in range(optimize_distance_max_iters): d = ( dists[0] + dists[1] ) / 2 # if not first and not dists[0]<self.distance<dists[1] else self.distance first = False K, alpha2_ = get_k(csp, c1, d) if K > 1: dists = [dists[0], d] else: dists = [d, dists[1]] if abs(1. - K) < optimize_distance_tolerance: break #self.error(str((i,K,d))) self.distance = d c2 = [c1[0] - self.distance, c1[1]] # Now create the paths alpha2 = 0 for i in range(self.num): alpha = math.pi * 2 * (i) / self.num alpha1 = alpha * self.second_teeth alpha2 += alpha2_[i] * K transform = get_transform(c1, c2, alpha1, alpha2) # add path's clone attrib["transform"] = simpletransform.formatTransform( transform) inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), attrib) self.error("Optimized distance: %s. " % (self.distance / self.options.units)) self.error( "Optimized parameter K: %s (the closer to 1.0 the better)." % K) self.error("Time elapsed %s seconds." % (time.time() - time_)) self.draw_pointer(c1, color="#000080", width=1, group=center_group) self.draw_pointer(c2, color="#000080", width=1, group=center_group) else: # Linear gear c1x, c1y = c1[0], c1[1] i = 0 self.distance = self.options.linear_distance if self.options.standatd_distance and self.options.create_bearing_gear: self.distance = self.options.gear_r + self.options.bearings_d / 2 while i <= self.options.rev * self.num: a = math.pi * 2 * i / self.num d = self.distance * a # Move c to 0 transform = [[1, 0, -c1x], [0, 1, -c1y]] # Rotate to a transform = simpletransform.composeTransform( [[math.cos(a), -math.sin(a), 0], [math.sin(a), math.cos(a), 0]], transform) # Move 0 to c + d transform = simpletransform.composeTransform( [[1, 0, c1x + d], [0, 1, c1y]], transform) attrib["transform"] = simpletransform.formatTransform( transform) inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), attrib) i += 1
def recursivelyTraverseSvg( self, aNodeList, matCurrent=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], parent_visibility='visible', cloneTransform=None ): ''' [ This too is largely lifted from eggbot.py ] Recursively walk the SVG document, building polygon vertex lists for each graphical element we support. Rendered SVG elements: <circle>, <ellipse>, <line>, <path>, <polygon>, <polyline>, <rect> Supported SVG elements: <group>, <use> Ignored SVG elements: <defs>, <eggbot>, <metadata>, <namedview>, <pattern>, processing directives All other SVG elements trigger an error (including <text>) ''' for node in aNodeList: # Ignore invisible nodes v = node.get( 'visibility', parent_visibility ) if v == 'inherit': v = parent_visibility if v == 'hidden' or v == 'collapse': pass # First apply the current matrix transform to this node's tranform matNew = simpletransform.composeTransform( matCurrent, simpletransform.parseTransform( node.get( "transform" ) ) ) if node.tag == inkex.addNS( 'g', 'svg' ) or node.tag == 'g': self.recursivelyTraverseSvg( node, matNew, parent_visibility=v ) elif node.tag == inkex.addNS( 'use', 'svg' ) or node.tag == 'use': # A <use> element refers to another SVG element via an xlink:href="#blah" # attribute. We will handle the element by doing an XPath search through # the document, looking for the element with the matching id="blah" # attribute. We then recursively process that element after applying # any necessary (x,y) translation. # # Notes: # 1. We ignore the height and width attributes as they do not apply to # path-like elements, and # 2. Even if the use element has visibility="hidden", SVG still calls # for processing the referenced element. The referenced element is # hidden only if its visibility is "inherit" or "hidden". refid = node.get( inkex.addNS( 'href', 'xlink' ) ) if not refid: pass # [1:] to ignore leading '#' in reference path = '//*[@id="%s"]' % refid[1:] refnode = node.xpath( path ) if refnode: x = float( node.get( 'x', '0' ) ) y = float( node.get( 'y', '0' ) ) # Note: the transform has already been applied if ( x != 0 ) or (y != 0 ): matNew2 = composeTransform( matNew, parseTransform( 'translate(%f,%f)' % (x,y) ) ) else: matNew2 = matNew v = node.get( 'visibility', v ) self.recursivelyTraverseSvg( refnode, matNew2, parent_visibility=v, cloneTransform=node.get( 'transform' ) ) elif node.tag == inkex.addNS( 'path', 'svg' ): path_data = node.get( 'd') if path_data: self.addPathVertices( path_data, node, matNew, cloneTransform ) elif node.tag == inkex.addNS( 'rect', 'svg' ) or node.tag == 'rect': # Manually transform # # <rect x="X" y="Y" width="W" height="H"/> # # into # # <path d="MX,Y lW,0 l0,H l-W,0 z"/> # # I.e., explicitly draw three sides of the rectangle and the # fourth side implicitly # Create a path with the outline of the rectangle x = float( node.get( 'x' ) ) y = float( node.get( 'y' ) ) if ( not x ) or ( not y ): pass w = float( node.get( 'width', '0' ) ) h = float( node.get( 'height', '0' ) ) a = [] a.append( ['M ', [x, y]] ) a.append( [' l ', [w, 0]] ) a.append( [' l ', [0, h]] ) a.append( [' l ', [-w, 0]] ) a.append( [' Z', []] ) self.addPathVertices( simplepath.formatPath( a ), node, matNew, cloneTransform ) elif node.tag == inkex.addNS( 'line', 'svg' ) or node.tag == 'line': # Convert # # <line x1="X1" y1="Y1" x2="X2" y2="Y2/> # # to # # <path d="MX1,Y1 LX2,Y2"/> x1 = float( node.get( 'x1' ) ) y1 = float( node.get( 'y1' ) ) x2 = float( node.get( 'x2' ) ) y2 = float( node.get( 'y2' ) ) if ( not x1 ) or ( not y1 ) or ( not x2 ) or ( not y2 ): pass a = [] a.append( ['M ', [x1, y1]] ) a.append( [' L ', [x2, y2]] ) self.addPathVertices( simplepath.formatPath( a ), node, matNew, cloneTransform ) elif node.tag == inkex.addNS( 'polyline', 'svg' ) or node.tag == 'polyline': # Convert # # <polyline points="x1,y1 x2,y2 x3,y3 [...]"/> # # to # # <path d="Mx1,y1 Lx2,y2 Lx3,y3 [...]"/> # # Note: we ignore polylines with no points pl = node.get( 'points', '' ).strip() if pl == '': pass pa = pl.split() d = "".join( ["M " + pa[i] if i == 0 else " L " + pa[i] for i in range( 0, len( pa ) )] ) self.addPathVertices( d, node, matNew, cloneTransform ) elif node.tag == inkex.addNS( 'polygon', 'svg' ) or node.tag == 'polygon': # Convert # # <polygon points="x1,y1 x2,y2 x3,y3 [...]"/> # # to # # <path d="Mx1,y1 Lx2,y2 Lx3,y3 [...] Z"/> # # Note: we ignore polygons with no points pl = node.get( 'points', '' ).strip() if pl == '': pass pa = pl.split() d = "".join( ["M " + pa[i] if i == 0 else " L " + pa[i] for i in range( 0, len( pa ) )] ) d += " Z" self.addPathVertices( d, node, matNew, cloneTransform ) elif node.tag == inkex.addNS( 'ellipse', 'svg' ) or \ node.tag == 'ellipse' or \ node.tag == inkex.addNS( 'circle', 'svg' ) or \ node.tag == 'circle': # Convert circles and ellipses to a path with two 180 degree arcs. # In general (an ellipse), we convert # # <ellipse rx="RX" ry="RY" cx="X" cy="Y"/> # # to # # <path d="MX1,CY A RX,RY 0 1 0 X2,CY A RX,RY 0 1 0 X1,CY"/> # # where # # X1 = CX - RX # X2 = CX + RX # # Note: ellipses or circles with a radius attribute of value 0 are ignored if node.tag == inkex.addNS( 'ellipse', 'svg' ) or node.tag == 'ellipse': rx = float( node.get( 'rx', '0' ) ) ry = float( node.get( 'ry', '0' ) ) else: rx = float( node.get( 'r', '0' ) ) ry = rx if rx == 0 or ry == 0: pass cx = float( node.get( 'cx', '0' ) ) cy = float( node.get( 'cy', '0' ) ) x1 = cx - rx x2 = cx + rx d = 'M %f,%f ' % ( x1, cy ) + \ 'A %f,%f ' % ( rx, ry ) + \ '0 1 0 %f,%f ' % ( x2, cy ) + \ 'A %f,%f ' % ( rx, ry ) + \ '0 1 0 %f,%f' % ( x1, cy ) self.addPathVertices( d, node, matNew, cloneTransform ) elif node.tag == inkex.addNS( 'pattern', 'svg' ) or node.tag == 'pattern': pass elif node.tag == inkex.addNS( 'metadata', 'svg' ) or node.tag == 'metadata': pass elif node.tag == inkex.addNS( 'defs', 'svg' ) or node.tag == 'defs': pass elif node.tag == inkex.addNS( 'namedview', 'sodipodi' ) or node.tag == 'namedview': pass elif node.tag == inkex.addNS( 'eggbot', 'svg' ) or node.tag == 'eggbot': pass elif node.tag == inkex.addNS( 'text', 'svg' ) or node.tag == 'text': inkex.errormsg( 'Warning: unable to draw text, please convert it to a path first.' ) pass elif not isinstance( node.tag, basestring ): pass else: inkex.errormsg( 'Warning: unable to draw object <%s>, please convert it to a path first.' % node.tag ) pass
def pattern(parent, id): '''Create a pattern group to hold a single pattern, parent should be the base group''' newPattern = addGroup(parent, id) newPattern.set(inkex.addNS('label', 'inkscape'), id) newPattern.set(inkex.addNS('groupmode', 'inkscape'), 'layer') return newPattern
def effect(self): if len(self.options.ids)<2: inkex.errormsg(_("This extension requires two selected paths.")) return self.prepareSelectionList() self.options.wave = (self.options.kind=="Ribbon") if self.options.copymode=="Single": self.options.repeat =False self.options.stretch=False elif self.options.copymode=="Repeated": self.options.repeat =True self.options.stretch=False elif self.options.copymode=="Single, stretched": self.options.repeat =False self.options.stretch=True elif self.options.copymode=="Repeated, stretched": self.options.repeat =True self.options.stretch=True bbox=simpletransform.computeBBox(self.patterns.values()) if self.options.vertical: #flipxy(bbox)... bbox=(-bbox[3],-bbox[2],-bbox[1],-bbox[0]) width=bbox[1]-bbox[0] dx=width+self.options.space if dx < 0.01: exit(_("The total length of the pattern is too small :\nPlease choose a larger object or set 'Space between copies' > 0")) for id, node in self.patterns.iteritems(): if node.tag == inkex.addNS('path','svg') or node.tag=='path': d = node.get('d') p0 = cubicsuperpath.parsePath(d) if self.options.vertical: flipxy(p0) newp=[] for skelnode in self.skeletons.itervalues(): self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) if self.options.vertical: flipxy(self.curSekeleton) for comp in self.curSekeleton: p=copy.deepcopy(p0) self.skelcomp,self.lengths=linearize(comp) #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1]) length=sum(self.lengths) xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset if self.options.repeat: NbCopies=max(1,int(round((length+self.options.space)/dx))) width=dx*NbCopies if not self.skelcompIsClosed: width-=self.options.space bbox=bbox[0],bbox[0]+width, bbox[2],bbox[3] new=[] for sub in p: for i in range(0,NbCopies,1): new.append(copy.deepcopy(sub)) offset(sub,dx,0) p=new for sub in p: offset(sub,xoffset,yoffset) if self.options.stretch: if not width: exit(_("The 'stretch' option requires that the pattern must have non-zero width :\nPlease edit the pattern width.")) for sub in p: stretch(sub,length/width,1,self.skelcomp[0]) for sub in p: for ctlpt in sub: self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2])) if self.options.vertical: flipxy(p) newp+=p node.set('d', cubicsuperpath.formatPath(newp))
def addText(self, node): for i in range(self.options.num): para = inkex.etree.SubElement(node, inkex.addNS('flowPara', 'svg')) para.text = self.makePara() inkex.etree.SubElement(node, inkex.addNS('flowPara', 'svg'))
def patternPiece(parent, id, name, fabric=2, interfacing=0, lining=0): '''Create a pattern piece group to hold a single pattern piece, parent should be a pattern group''' newPatternPiece = addGroup(parent, id) newPatternPiece.set(inkex.addNS('label', 'inkscape'), name) newPatternPiece.set(inkex.addNS('groupmode', 'inkscape'), 'layer') return newPatternPiece
def newUseNode(id_, x, y, href): use = Element(addNS('use', 'svg')) for name, value in [('id', id_), ('x', str(x)), ('y', str(y)), (addNS('href', 'xlink'), '#' + href)]: use.set(name, value) return use
def base(parent, id): '''Create a base group to contain all patterns, parent should be the document''' newBase = addGroup(parent, id) newBase.set(inkex.addNS('label', 'inkscape'), id) newBase.set(inkex.addNS('groupmode', 'inkscape'), 'layer') return newBase
def getParsedLabel(self): label = self.get(addNS('xmoto_label', 'xmoto'), '') parser = Factory().create('label_parser') return parser.parse(label)
from collections import MutableMapping from copy import deepcopy import json import re import inkex from stringcase import snakecase from ..commands import layer_commands from ..elements import EmbroideryElement, nodes_to_elements from ..i18n import _ from ..svg.tags import SVG_GROUP_TAG, INKSCAPE_GROUPMODE, SVG_DEFS_TAG, EMBROIDERABLE_TAGS SVG_METADATA_TAG = inkex.addNS("metadata", "svg") def strip_namespace(tag): """Remove xml namespace from a tag name. >>> {http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}namedview <<< namedview """ match = re.match(r'^\{[^}]+\}(.+)$', tag) if match: return match.group(1) else: return tag
if g is None: return (None, None, None) try: circle = g.getCircleChild() except Exception, e: _id = g.get('id', '') logging.warning("Sprite [%s] is an empty layer. \ Let's delete it\n%s" % (_id, e)) parent = g.getparent() parent.remove(g) return (None, None, None) use = g.find(addNS('use', 'svg')) if use is None: # deprecated, we no longer use images, uses instead image = g.find(addNS('image', 'svg')) if image is not None: g.remove(image) return (g, circle, use) def setNodeAsBitmap(self, svg, texName, radius, bitmaps, label, style,
def setNodeAsBitmap(self, svg, texName, radius, bitmaps, label, style, scale=1.0, _reversed=False, rotation=0.0): if self.isSubLayer(type=self.BLOCK): # remove one of the two children children = self.getchildren() child = children[0] self.remove(self.getchildren()[0]) (g, circle, use) = self.getImageNodes() if g is None: return # if the node has more than one circle, delete it circles = g.findall(addNS('path', 'svg')) if len(circles) > 1: for c in circles: if c == circle: continue else: g.remove(c) # set the xmoto_label on both the sublayer and the # circle (for backward compatibility) g.set(addNS('xmoto_label', 'xmoto'), label) circle.set(addNS('xmoto_label', 'xmoto'), label) circle.set('style', style) if g.get('style') is not None: del g.attrib['style'] circle = convertToXmNode(circle, self.svg) circle.setNodeAsCircle(scale * radius) # set the circle transform to the layer transform = circle.get('transform') if transform is not None: g.set('transform', transform) del circle.attrib['transform'] (x, y, cx, cy, width, height) = getImageDimensions(texName, scale, circle.getAABB()) imageId = svg.addImage(texName, bitmaps, width, height) if imageId is None: return if use is None: try: use = newUseNode('image_' + circle.get('id'), x, y, imageId) # insert the use as the first child so that # it get displayed before the circle in inkscape g.insert(0, use) except Exception, e: logging.info("Can't create image for sprite %s.\n%s" % (texName, e))
def effect(self): svg = self.document.getroot() width = self.svg.unittouu(svg.get('width')) height = self.svg.unittouu(svg.attrib['height']) layer = etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), 'CriCut') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') x = 0 each = "" obj_styles = {} identity = Transform("") # # For each unique line style, add it to a dictionary/set # so we can later use the id's to build a path for obj in svg.xpath('//svg:line|//svg:circle|//svg:rect', namespaces=inkex.NSS): #inkex.utils.debug(obj) style = obj.get('style', '') matrix = obj.transform * Transform(identity) #style = style + formatTransform(matrix) id = obj.get('id') if not style in obj_styles: obj_styles[style] = set() obj_styles[style].add(id) ## For each dictionary ## Iterate it's set and output paths instead. for obj_each in obj_styles: M = "" style = "" for obj_set in obj_styles[obj_each]: p = "//*[@id='" + obj_set + "']" element = svg.xpath(p, namespaces=inkex.NSS) style = element[0].get('style', '') element_type = QName(element[0]).localname new_transform = element[0].transform * Transform(identity) newM = "" if (element_type == "rect"): x = float(element[0].attrib['x']) y = float(element[0].attrib['y']) width = float(element[0].attrib['width']) height = float(element[0].attrib['height']) newM = " M " + str(x) + "," + str(y) + " " + str( x + width) + "," + str(y) + " " + str( x + width) + "," + str(y + height) + " " + str( x) + "," + str(y + height) + " " + str( x) + "," + str(y) + " " if (element_type == "line"): x1 = element[0].attrib['x1'] x2 = element[0].attrib['x2'] y1 = element[0].attrib['y1'] y2 = element[0].attrib['y2'] newM = " M " + x1 + "," + y1 + " L " + x1 + "," + y1 + " " + x2 + "," + y2 + " " if (element_type == "circle"): cy = element[0].attrib['cy'] cx = element[0].attrib['cx'] r = float(element[0].attrib['r']) newM += " M " + cx + " " + cy newM += " m " + str(r * -1) + ",0 " newM += " a " + str(r) + "," + str(r) + " 0 1,0 " + str( r * 2) + ",0 " newM += "a " + str(r) + "," + str(r) + " 0 1,0 " + str( (r * 2) * -1) + ",0 z " p = CubicSuperPath(newM) p.transform(new_transform) newM = str(p) M += newM # obj_each attribs = { 'd': M, 'style': style } ## , 'transform':formatTransform(new_transform) } ###inkex.addNS('label','inkscape'):name }, etree.SubElement(layer, inkex.addNS('path', 'svg'), attribs)
def setStyleLabel(self, label, style): self.set(addNS('xmoto_label', 'xmoto'), label) self.set('style', style)
def effect(self): # Check version. scriptNodes = self.document.xpath( "//svg:script[@jessyink:version='1.5.6']", namespaces=inkex.NSS) if len(scriptNodes) != 1: inkex.errormsg( _(u"JessyInk_c 还未安装到这个SVG文件,或者版本不同. 请使用 “扩展” 菜单下 “JessyInk_c” 的 “安装/升级...” 命令进行JessyInk_c 的安装。\n\n" )) # Remove old master slide property for node in self.document.xpath( "//svg:g[@jessyink:customKeyBindings='customKeyBindings']", namespaces=inkex.NSS): node.getparent().remove(node) # Set custom key bindings. nodeText = "function getCustomKeyBindingsSub()" + "\n" nodeText += "{" + "\n" nodeText += " var keyDict = new Object();" + "\n" nodeText += " keyDict[SLIDE_MODE] = new Object();" + "\n" nodeText += " keyDict[INDEX_MODE] = new Object();" + "\n" nodeText += " keyDict[DRAWING_MODE] = new Object();" + "\n" for key, value in list(self.slideKeyCodes.items()): nodeText += " keyDict[SLIDE_MODE][" + key + "] = function() { " + value + " };" + "\n" for key, value in list(self.drawingKeyCodes.items()): nodeText += " keyDict[DRAWING_MODE][" + key + "] = function() { " + value + " };" + "\n" for key, value in list(self.indexKeyCodes.items()): nodeText += " keyDict[INDEX_MODE][" + key + "] = function() { " + value + " };" + "\n" nodeText += " return keyDict;" + "\n" nodeText += "}" + "\n\n" # Set custom char bindings. nodeText += "function getCustomCharBindingsSub()" + "\n" nodeText += "{" + "\n" nodeText += " var charDict = new Object();" + "\n" nodeText += " charDict[SLIDE_MODE] = new Object();" + "\n" nodeText += " charDict[INDEX_MODE] = new Object();" + "\n" nodeText += " charDict[DRAWING_MODE] = new Object();" + "\n" for key, value in list(self.slideCharCodes.items()): nodeText += " charDict[SLIDE_MODE][\"" + key + "\"] = function() { " + value + " };" + "\n" for key, value in list(self.drawingCharCodes.items()): nodeText += " charDict[DRAWING_MODE][\"" + key + "\"] = function() { " + value + " };" + "\n" for key, value in list(self.indexCharCodes.items()): nodeText += " charDict[INDEX_MODE][\"" + key + "\"] = function() { " + value + " };" + "\n" nodeText += " return charDict;" + "\n" nodeText += "}" + "\n" # Create new script node scriptElm = inkex.etree.Element(inkex.addNS("script", "svg")) scriptElm.text = nodeText groupElm = inkex.etree.Element(inkex.addNS("g", "svg")) groupElm.set("{" + inkex.NSS["jessyink"] + "}customKeyBindings", "customKeyBindings") groupElm.set( "onload", "this.getCustomCharBindings = function() { return getCustomCharBindingsSub(); }; this.getCustomKeyBindings = function() { return getCustomKeyBindingsSub(); };" ) groupElm.append(scriptElm) self.document.getroot().append(groupElm)
def effect(self): #{{{ Check that elements have been selected if len(self.options.ids) == 0: inkex.errormsg(_("Please select objects!")) return #}}} #{{{ Drawing styles linestyle = { 'stroke': '#000000', 'stroke-width': str(self.unittouu('1px')), 'fill': 'none' } facestyle = { 'stroke': '#ff0000', 'stroke-width': str(self.unittouu('1px')), 'fill': 'none' } #}}} #{{{ Handle the transformation of the current group parentGroup = self.getParentNode(self.selected[self.options.ids[0]]) trans = self.getGlobalTransform(parentGroup) invtrans = None if trans: invtrans = self.invertTransform(trans) #}}} #{{{ Recovery of the selected objects pts = [] nodes = [] seeds = [] for id in self.options.ids: node = self.selected[id] nodes.append(node) bbox = simpletransform.computeBBox([node]) if bbox: cx = 0.5 * (bbox[0] + bbox[1]) cy = 0.5 * (bbox[2] + bbox[3]) pt = [cx, cy] if trans: simpletransform.applyTransformToPoint(trans, pt) pts.append(Point(pt[0], pt[1])) seeds.append(Point(cx, cy)) #}}} #{{{ Creation of groups to store the result if self.options.diagramType != 'Delaunay': # Voronoi groupVoronoi = inkex.etree.SubElement(parentGroup, inkex.addNS('g', 'svg')) groupVoronoi.set(inkex.addNS('label', 'inkscape'), 'Voronoi') if invtrans: simpletransform.applyTransformToNode(invtrans, groupVoronoi) if self.options.diagramType != 'Voronoi': # Delaunay groupDelaunay = inkex.etree.SubElement(parentGroup, inkex.addNS('g', 'svg')) groupDelaunay.set(inkex.addNS('label', 'inkscape'), 'Delaunay') #}}} #{{{ Clipping box handling if self.options.diagramType != 'Delaunay': #Clipping bounding box creation gBbox = simpletransform.computeBBox(nodes) #Clipbox is the box to which the Voronoi diagram is restricted clipBox = () if self.options.clipBox == 'Page': svg = self.document.getroot() w = self.unittouu(svg.get('width')) h = self.unittouu(svg.get('height')) clipBox = (0, w, 0, h) else: clipBox = (2 * gBbox[0] - gBbox[1], 2 * gBbox[1] - gBbox[0], 2 * gBbox[2] - gBbox[3], 2 * gBbox[3] - gBbox[2]) #Safebox adds points so that no Voronoi edge in clipBox is infinite safeBox = (2 * clipBox[0] - clipBox[1], 2 * clipBox[1] - clipBox[0], 2 * clipBox[2] - clipBox[3], 2 * clipBox[3] - clipBox[2]) pts.append(Point(safeBox[0], safeBox[2])) pts.append(Point(safeBox[1], safeBox[2])) pts.append(Point(safeBox[1], safeBox[3])) pts.append(Point(safeBox[0], safeBox[3])) if self.options.showClipBox: #Add the clip box to the drawing rect = inkex.etree.SubElement(groupVoronoi, inkex.addNS('rect', 'svg')) rect.set('x', str(clipBox[0])) rect.set('y', str(clipBox[2])) rect.set('width', str(clipBox[1] - clipBox[0])) rect.set('height', str(clipBox[3] - clipBox[2])) rect.set('style', simplestyle.formatStyle(linestyle)) #}}} #{{{ Voronoi diagram generation if self.options.diagramType != 'Delaunay': vertices, lines, edges = voronoi.computeVoronoiDiagram(pts) for edge in edges: line = edge[0] vindex1 = edge[1] vindex2 = edge[2] if (vindex1 < 0) or (vindex2 < 0): continue # infinite lines have no need to be handled in the clipped box else: segment = self.clipEdge(vertices, lines, edge, clipBox) #segment = [vertices[vindex1],vertices[vindex2]] # deactivate clipping if len(segment) > 1: v1 = segment[0] v2 = segment[1] cmds = [['M', [v1[0], v1[1]]], ['L', [v2[0], v2[1]]]] path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('d', simplepath.formatPath(cmds)) path.set('style', simplestyle.formatStyle(linestyle)) groupVoronoi.append(path) if self.options.diagramType != 'Voronoi': triangles = voronoi.computeDelaunayTriangulation(seeds) for triangle in triangles: p1 = seeds[triangle[0]] p2 = seeds[triangle[1]] p3 = seeds[triangle[2]] cmds = [['M', [p1.x, p1.y]], ['L', [p2.x, p2.y]], ['L', [p3.x, p3.y]], ['Z', []]] path = inkex.etree.Element(inkex.addNS('path', 'svg')) path.set('d', simplepath.formatPath(cmds)) path.set('style', simplestyle.formatStyle(facestyle)) groupDelaunay.append(path)
cc = ['white', 'black', 'grey'] style = { 'stroke': 'none', 'stroke-width': '0', 'fill': cc[c], 'fill-opacity': str(0.5 if c == 2 else 1.0) } attribs = { 'style': simplestyle.formatStyle(style), 'height': str(h), 'width': str(w), 'x': str(x), 'y': str(y) } circ = inkex.etree.SubElement(parent, inkex.addNS('rect', 'svg'), attribs) #turn a 2D array of 1's and 0's into a set of black squares def render_code(q, size, cx, cy, parent): for y in range(len(q)): for x in range(len(q[y])): if q[y][x] == None: draw_SVG_square((size * 1.1, size * 1.1), (x * size + cx, y * size + cy), 2, parent) elif q[y][x]: #A binary 1 is a filled square draw_SVG_square((size * 1.1, size * 1.1), (x * size + cx, y * size + cy), 1, parent)
def recursivelyTraverseSvg(self, nodeList, matCurrent=[[1.0, 0.0, 0.0], [0.0, -1.0, 0.0]], parent_visibility='visible'): """ Recursively traverse the svg file to plot out all of the paths. The function keeps track of the composite transformation that should be applied to each path. This function handles path, group, line, rect, polyline, polygon, circle, ellipse and use (clone) elements. Notable elements not handled include text. Unhandled elements should be converted to paths in Inkscape. TODO: There's a lot of inlined code in the eggbot version of this that would benefit from the Entities method of dealing with things. """ for node in nodeList: # Ignore invisible nodes v = node.get('visibility', parent_visibility) if v == 'inherit': v = parent_visibility if v == 'hidden' or v == 'collapse': pass # first apply the current matrix transform to this node's transform matNew = composeTransform(matCurrent, parseTransform(node.get("transform"))) if node.tag == inkex.addNS('g', 'svg') or node.tag == 'g': if (node.get(inkex.addNS('groupmode', 'inkscape')) == 'layer'): layer_name = node.get(inkex.addNS('label', 'inkscape')) if (self.pause_on_layer_change == 'true'): self.entities.append(SvgLayerChange(layer_name)) self.recursivelyTraverseSvg(node, matNew, parent_visibility=v) elif node.tag == inkex.addNS('use', 'svg') or node.tag == 'use': refid = node.get(inkex.addNS('href', 'xlink')) if refid: # [1:] to ignore leading '#' in reference path = '//*[@id="%s"]' % refid[1:] refnode = node.xpath(path) if refnode: x = float(node.get('x', '0')) y = float(node.get('y', '0')) # Note: the transform has already been applied if (x != 0) or (y != 0): matNew2 = composeTransform( matNew, parseTransform('translate(%f,%f)' % (x, y))) else: matNew2 = matNew v = node.get('visibility', v) self.recursivelyTraverseSvg(refnode, matNew2, parent_visibility=v) else: pass else: pass elif not isinstance(node.tag, basestring): pass else: entity = self.make_entity(node, matNew) if entity == None: inkex.errormsg( 'Warning: unable to draw object, please convert it to a path first.' )
def effect(self): if self.options.where_to_crop == 'selection': inkex.errormsg('Sory, the crop to selection is a TODO feature') # Get SVG document dimensions svg = self.document.getroot() self.width = width = inkex.unittouu(svg.get('width')) self.height = height = inkex.unittouu(svg.attrib['height']) # Convert parameters to user unit offset = inkex.unittouu( str(self.options.crop_offset) + self.options.unit) bt = inkex.unittouu(str(self.options.bleed_top) + self.options.unit) bb = inkex.unittouu(str(self.options.bleed_bottom) + self.options.unit) bl = inkex.unittouu(str(self.options.bleed_left) + self.options.unit) br = inkex.unittouu(str(self.options.bleed_right) + self.options.unit) # Bleed margin if bt < offset: bmt = 0 else: bmt = bt - offset if bb < offset: bmb = 0 else: bmb = bb - offset if bl < offset: bml = 0 else: bml = bl - offset if br < offset: bmr = 0 else: bmr = br - offset # Define the new document limits left = -offset right = width + offset top = -offset bottom = height + offset # Test if printing-marks layer existis layer = self.document.xpath( '//*[@id="printing-marks" and @inkscape:groupmode="layer"]', namespaces=inkex.NSS) if layer: svg.remove(layer[0]) # remove if it existis # Create a new layer layer = inkex.etree.SubElement(svg, 'g') layer.set('id', 'printing-marks') layer.set(inkex.addNS('label', 'inkscape'), 'Printing Marks') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') layer.set(inkex.addNS('insensitive', 'sodipodi'), 'true') # Crop Mark if self.options.crop_marks == True: # Create a group for Crop Mark g_attribs = { inkex.addNS('label', 'inkscape'): 'CropMarks', 'id': 'CropMarks' } g_crops = inkex.etree.SubElement(layer, 'g', g_attribs) # Top left Mark self.draw_crop_line(0, top, 0, top - self.mark_size, 'cropTL1', g_crops) self.draw_crop_line(left, 0, left - self.mark_size, 0, 'cropTL2', g_crops) # Top right Mark self.draw_crop_line(width, top, width, top - self.mark_size, 'cropTR1', g_crops) self.draw_crop_line(right, 0, right + self.mark_size, 0, 'cropTR2', g_crops) # Bottom left Mark self.draw_crop_line(0, bottom, 0, bottom + self.mark_size, 'cropBL1', g_crops) self.draw_crop_line(left, height, left - self.mark_size, height, 'cropBL2', g_crops) # Bottom right Mark self.draw_crop_line(width, bottom, width, bottom + self.mark_size, 'cropBR1', g_crops) self.draw_crop_line(right, height, right + self.mark_size, height, 'cropBR2', g_crops) # Bleed Mark if self.options.bleed_marks == True: # Create a group for Bleed Mark g_attribs = { inkex.addNS('label', 'inkscape'): 'BleedMarks', 'id': 'BleedMarks' } g_bleed = inkex.etree.SubElement(layer, 'g', g_attribs) # Top left Mark self.draw_bleed_line(-bl, top - bmt, -bl, top - bmt - self.mark_size, 'bleedTL1', g_bleed) self.draw_bleed_line(left - bml, -bt, left - bml - self.mark_size, -bt, 'bleedTL2', g_bleed) # Top right Mark self.draw_bleed_line(width + br, top - bmt, width + br, top - bmt - self.mark_size, 'bleedTR1', g_bleed) self.draw_bleed_line(right + bmr, -bt, right + bmr + self.mark_size, -bt, 'bleedTR2', g_bleed) # Bottom left Mark self.draw_bleed_line(-bl, bottom + bmb, -bl, bottom + bmb + self.mark_size, 'bleedBL1', g_bleed) self.draw_bleed_line(left - bml, height + bb, left - bml - self.mark_size, height + bb, 'bleedBL2', g_bleed) # Bottom right Mark self.draw_bleed_line(width + br, bottom + bmb, width + br, bottom + bmb + self.mark_size, 'bleedBR1', g_bleed) self.draw_bleed_line(right + bmr, height + bb, right + bmr + self.mark_size, height + bb, 'bleedBR2', g_bleed) # Registration Mark if self.options.reg_marks == True: # Create a group for Registration Mark g_attribs = { inkex.addNS('label', 'inkscape'): 'RegistrationMarks', 'id': 'RegistrationMarks' } g_center = inkex.etree.SubElement(layer, 'g', g_attribs) # Left Mark cx = max(bml + offset, self.min_mark_margin) self.draw_reg_marks(-cx - (self.mark_size / 2), (height / 2) - self.mark_size * 1.5, '0', 'regMarkL', g_center) # Right Mark cx = max(bmr + offset, self.min_mark_margin) self.draw_reg_marks(width + cx + (self.mark_size / 2), (height / 2) - self.mark_size * 1.5, '180', 'regMarkR', g_center) # Top Mark cy = max(bmt + offset, self.min_mark_margin) self.draw_reg_marks((width / 2) - self.mark_size * 1.5, -cy - (self.mark_size / 2), '90', 'regMarkT', g_center) # Bottom Mark cy = max(bmb + offset, self.min_mark_margin) self.draw_reg_marks((width / 2) - self.mark_size * 1.5, height + cy + (self.mark_size / 2), '-90', 'regMarkB', g_center) # Star Target if self.options.star_target == True: # Create a group for Star Target g_attribs = { inkex.addNS('label', 'inkscape'): 'StarTarget', 'id': 'StarTarget' } g_center = inkex.etree.SubElement(layer, 'g', g_attribs) if height < width: # Left Star cx = max(bml + offset, self.min_mark_margin) self.draw_star_target(-cx - (self.mark_size / 2), (height / 2), 'starTargetL', g_center) # Right Star cx = max(bmr + offset, self.min_mark_margin) self.draw_star_target(width + cx + (self.mark_size / 2), (height / 2), 'starTargetR', g_center) else: # Top Star cy = max(bmt + offset, self.min_mark_margin) self.draw_star_target((width / 2), -cy - (self.mark_size / 2), 'starTargetT', g_center) # Bottom Star cy = max(bmb + offset, self.min_mark_margin) self.draw_star_target((width / 2), height + cy + (self.mark_size / 2), 'starTargetB', g_center) # Colour Bars if self.options.colour_bars == True: # Create a group for Colour Bars g_attribs = { inkex.addNS('label', 'inkscape'): 'ColourBars', 'id': 'PrintingColourBars' } g_center = inkex.etree.SubElement(layer, 'g', g_attribs) if height > width: # Left Bars cx = max(bml + offset, self.min_mark_margin) self.draw_coluor_bars(-cx - (self.mark_size / 2), height / 2, 90, 'PrintingColourBarsL', g_center) # Right Bars cx = max(bmr + offset, self.min_mark_margin) self.draw_coluor_bars(width + cx + (self.mark_size / 2), height / 2, 90, 'PrintingColourBarsR', g_center) else: # Top Bars cy = max(bmt + offset, self.min_mark_margin) self.draw_coluor_bars(width / 2, -cy - (self.mark_size / 2), 0, 'PrintingColourBarsT', g_center) # Bottom Bars cy = max(bmb + offset, self.min_mark_margin) self.draw_coluor_bars(width / 2, height + cy + (self.mark_size / 2), 0, 'PrintingColourBarsB', g_center) # Page Information if self.options.page_info == True: # Create a group for Page Information g_attribs = { inkex.addNS('label', 'inkscape'): 'PageInformation', 'id': 'PageInformation' } g_pag_info = inkex.etree.SubElement(layer, 'g', g_attribs) y_margin = max(bmb + offset, self.min_mark_margin) txt_attribs = { 'style': 'font-size:12px;font-style:normal;font-weight:normal;fill:#000000;font-family:Bitstream Vera Sans,sans-serif;text-anchor:middle;text-align:center', 'x': str(width / 2), 'y': str(height + y_margin + self.mark_size + 20) } txt = inkex.etree.SubElement(g_pag_info, 'text', txt_attribs) txt.text = 'Page size: ' +\ str(round(inkex.uutounit(width,self.options.unit),2)) +\ 'x' +\ str(round(inkex.uutounit(height,self.options.unit),2)) +\ ' ' + self.options.unit
def effect(self): svg = self.document.getroot() # ************ Layer 1 Definition *************** layer = etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), 'Fretboard') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') # ************ Layer 2 Definition *************** layer2 = etree.SubElement(svg, 'g') layer2.set(inkex.addNS('label', 'inkscape'), 'Fret positions') layer2.set(inkex.addNS('groupmode', 'inkscape'), 'layer') # ************ Group Definitions *************** fb_id = svg.get_unique_id('fretboard') self.box = g = etree.SubElement(layer, 'g', {'id': fb_id}) fp_id = svg.get_unique_id('fret-positions') self.box2 = g3 = etree.SubElement(layer2, 'g', {'id': fp_id}) fm_id = svg.get_unique_id('fretmarkers') self.box4 = g4 = etree.SubElement(layer2, 'g', {'id': fm_id}) # ************ Style Definition *************** fill_black_style = str( inkex.Style({ 'stroke': 'none', 'fill': '#222222' })) fill_grey_style = str( inkex.Style({ 'stroke': 'none', 'fill': '#aaaaaa' })) fill_lightgrey_style = str( inkex.Style({ 'stroke': 'none', 'fill': '#dddddd' })) stroke_black_style = str( inkex.Style({ 'stroke': '#000000', 'fill': 'none' })) stroke_red_style = str( inkex.Style({ 'stroke': '#ff0000', 'fill': 'none' })) text_style = "font-family:DejaVu Sans;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-size:10px;" text_attributes = { 'x': '12mm', 'y': '10mm', inkex.addNS("space", "xml"): "preserve", 'style': text_style } text = "Scalelenght : {}\n".format(self.options.scale) text += "Nut width : {}\n".format(self.options.lnut) text += "12th fret width : {}\n".format(self.options.l12) text += "Number of frets : {}\n".format(self.options.numfret) text += "Extension below last fret : {}\n".format(self.options.fbext) text += "Fret width : {}".format(self.options.fretwidth) fretboard = Fretboard(svg.unittouu(str(self.options.scale))) fretboard.width_nut = svg.unittouu(str(self.options.lnut)) fretboard.width_12 = svg.unittouu(str(self.options.l12)) fretboard.extension = svg.unittouu(str(self.options.fbext)) fretboard.nb_frets = self.options.numfret fretboard.fret_width = svg.unittouu(str(self.options.fretwidth)) fb_body_path = fretboard.svg_contour() nut_line = fretboard.svg_fret_centerline(0) bridge_line = fretboard.svg_h_line( fretboard.fb_width_at(fretboard.scale), fretboard.scale) # ************ Apply style to objects *************** fb_body_object = { 'style': fill_black_style, 'id': fb_id + '-shape', 'd': fb_body_path } nut_line_object = { 'style': stroke_black_style, 'id': 'fret-0', 'd': nut_line } bridge_line_object = { 'style': stroke_black_style, 'id': 'bridge-line', 'd': bridge_line } # ************ Add objects to groups *************** etree.SubElement(g, inkex.addNS('path', 'svg'), fb_body_object) etree.SubElement(g, inkex.addNS('path', 'svg'), bridge_line_object) etree.SubElement(g3, inkex.addNS('path', 'svg'), bridge_line_object) etree.SubElement(g3, inkex.addNS('path', 'svg'), nut_line_object) t = etree.SubElement(layer2, inkex.addNS('text', 'svg'), text_attributes) text = str(text).split("\n") y = 100 for s in text: span = etree.SubElement(t, inkex.addNS('tspan', 'svg'), { 'x': '12', 'y': str(y), inkex.addNS("role", "sodipodi"): "line", }) y += 24 span.text = str(s) for index in range(1, self.options.numfret + 1): linefret_path = fretboard.svg_fret_centerline(index) fretpos_id = svg.get_unique_id('fretpos-' + str(index)) linefret_atts = { 'style': stroke_black_style, 'id': fretpos_id, 'd': linefret_path } etree.SubElement(g3, inkex.addNS('path', 'svg'), linefret_atts) line_path = fretboard.svg_fret_contour(index) curve_path = fretboard.svg_fret_end(index, 1.0) curve_path2 = fretboard.svg_fret_end(index, -1.0) fret_id = svg.get_unique_id('fret-' + str(index)) self.fret = g2 = etree.SubElement(self.box, 'g', {'id': fret_id}) fretbody_id = svg.get_unique_id('fret-' + str(index) + '-body') fretend_id1 = svg.get_unique_id('fret-' + str(index) + '-end1') fretend_id2 = svg.get_unique_id('fret-' + str(index) + '-end2') line_atts = { 'style': fill_grey_style, 'id': fretbody_id, 'd': line_path } curve_atts = { 'style': fill_lightgrey_style, 'id': fretend_id1, 'd': curve_path } curve2_atts = { 'style': fill_lightgrey_style, 'id': fretend_id2, 'd': curve_path2 } etree.SubElement(g2, inkex.addNS('path', 'svg'), line_atts) etree.SubElement(g2, inkex.addNS('path', 'svg'), curve_atts) etree.SubElement(g2, inkex.addNS('path', 'svg'), curve2_atts) # ************ Add inlay cross *************** val = index % 12 if val in [0, 3, 5, 7, 9]: hline_cross_path, vline_cross_path = fretboard.svg_fret_cross( index) fretpos_id = svg.get_unique_id('marker-cross-' + str(index)) hline_atts = { 'style': stroke_red_style, 'id': fretpos_id, 'd': hline_cross_path } vline_atts = { 'style': stroke_red_style, 'id': fretpos_id, 'd': vline_cross_path } etree.SubElement(g4, inkex.addNS('path', 'svg'), hline_atts) etree.SubElement(g4, inkex.addNS('path', 'svg'), vline_atts)