def findFirstChild(self, node, id): for child in node.iterchildren(): a=child.get(u"id") if a==id: return child inkex.debug(str(id) + ' not found in ' + str(node)) return False
def movePath(self, node, x, y, origin): tagName = self.getTagName(node) if tagName != "path": inkex.debug('movePath only works on SVG Path elements. Argument was of type "' + tagName + '"') return False path = simplepath.parsePath(node.get("d")) id = node.get("id") box = list(simpletransform.computeBBox([node])) offset_x = box[0] - x offset_y = box[2] - (y) for cmd in path: params = cmd[1] i = 0 while i < len(params): if i % 2 == 0: # inkex.debug('x point at ' + str( round( params[i] ))) params[i] = params[i] - offset_x # inkex.debug('moved to ' + str( round( params[i] ))) else: # inkex.debug('y point at ' + str( round( params[i]) )) params[i] = params[i] - offset_y # inkex.debug('moved to ' + str( round( params[i] ))) i = i + 1 return simplepath.formatPath(path)
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 get_layers(self, src): svg_layers = self.document.xpath( '//svg:g[@inkscape:groupmode="layer"]', namespaces=inkex.NSS) layers = [] for layer in svg_layers: label_attrib_name = "{%s}label" % layer.nsmap['inkscape'] if label_attrib_name not in layer.attrib: continue layer_id = layer.attrib["id"] layer_label = layer.attrib[label_attrib_name] layer_label_name = layer_label inkex.debug(layer_label_name) if layer_label_name in self.layer_map.iterkeys(): layer_type = "export" layer_label = layer_label_name elif layer_label.lower().startswith("[fixed] "): layer_type = "fixed" layer_label = layer_label[8:] else: continue layers.append([layer_id, layer_label, layer_type]) return layers
def exportCurrent(self): self.deactivateAll() for layer in self.activeLayers: self.activateOne(layer) inkex.debug("Exporting "+self.filename); self.tempfileCounter += 1 useFile = self.parseFile+'-'+str(self.tempfileCounter) self.writeFile(useFile, tostring(self.SVG)) infile = os.path.abspath(useFile) outfile = self.options.outdir+'/'+str(self.filenameCounter).zfill(2)+'-'+self.filename+'.png' if(self.renderBoxId): shellCmd = [self.treatPath(self.inkscapeExecutable),'-i', self.renderBoxId, '-z', '-e', self.treatPath(outfile), '-d', "90", self.treatPath(infile)] else: shellCmd = [self.treatPath(self.inkscapeExecutable),'-z', '-e', self.treatPath(outfile), '-d', "90", self.treatPath(infile)] try: os.unlink(self.treatPath(outfile)) except: pass subprocess.Popen(shellCmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ''' cleanup thread. 20 seconds max render time ''' def clearTempFileWhenDone(): t = 0 while not os.path.isfile(outfile) and t < 20: time.sleep(1); t += 1 if t >= 20: print("- Not ready within 20 seconds. Result may be broken."); os.unlink(self.treatPath(infile)) t = threading.Timer(1, clearTempFileWhenDone).start();
def effect(self): """Generate inline Equation""" param = { 'formula': self.options.formula, 'document': getattr(self, 'document', None), 'packages': self.options.packages, 'debug': self.options.debug, 'output': self.options.output, } debug = self.options.debug if debug: logging.debug("Standalone Mode") equation = Equation(param=param) current_eq = equation.generate(standalone=STANDALONE) if current_eq != None: self.current_layer.append(current_eq) if debug: logging.debug('Equation added to current layer') else: if debug: logging.debug('Equation not generated') inkex.debug('No Equation was generated\n')
def createKey(self, parent, key): key = key.upper() key = key.strip() octave = 1 dies = '#' in key if dies : if (len(key) > 2): if key[2].isdigit(): octave = int(key[2]) note = key[0:2] else: inkex.debug("len(key) = " + str(len(key))) if (len(key) > 1) : if key[1].isdigit(): octave = int(key[1]) note = key[0] # if key in notes: # inkex.debug('key is a note (' + note + ')') # else: # inkex.debug('key is not a note (' + note + ')') # inkex.debug("note = " + note) # inkex.debug("keys[note] = " + keys[note] ) if keys[note] == "W": self.createWhiteKey(parent, int(keys_numbers[note])+7*(octave-1)) else: self.createBlackKey(parent, int(keys_numbers[note])+7*(octave-1))
def draw_stroke(xpa, ypa, endx, endy, parent): xpa = float(xpa) xpa = xpa * pxmm ypa = float(ypa) ypa = ypa * pxmm # constant px/mm ypa = -ypa + yorigin # Replace Origin Point to Inkscape-Document Origin Point (x axis is already clear) endy = float(endy) endy = endy * pxmm endy = -endy + yorigin endx = float(endx) endx = endx * pxmm if Debug: inkex.debug("Stroke YPA: " + str(ypa) + " Stroke XPA: " + str(xpa) + "\n") style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': '0.5', 'stroke-miterlimit': '4', } text_attribs = { 'style': simplestyle.formatStyle(style), 'd': 'M ' + str(xpa) + ' ' + str(ypa) + ' L ' + str(endx) + ' ' + str(endy) } inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), text_attribs) ll2g_attribs = {inkex.addNS('label', 'inkscape'): 'Layout Sroke'} ll2g = inkex.etree.SubElement(parent, 'h', ll2g_attribs) tls = 'translate(0,0)' ll2g.set('transform', tls)
def createKey(self, parent, key): key = key.upper() key = key.strip() octave = 1 dies = '#' in key if dies: if (len(key) > 2): if key[2].isdigit(): octave = int(key[2]) note = key[0:2] else: inkex.debug("len(key) = " + str(len(key))) if (len(key) > 1): if key[1].isdigit(): octave = int(key[1]) note = key[0] # if key in notes: # inkex.debug('key is a note (' + note + ')') # else: # inkex.debug('key is not a note (' + note + ')') # inkex.debug("note = " + note) # inkex.debug("keys[note] = " + keys[note] ) if keys[note] == "W": self.createWhiteKey(parent, int(keys_numbers[note]) + 7 * (octave - 1)) else: self.createBlackKey(parent, int(keys_numbers[note]) + 7 * (octave - 1))
def effect(self): import os import subprocess from lxml import etree with open("settings.json") as inp: settings = json.load(inp) python3_path = settings['python3_path'] tempfilename = 'protein.svg' vals = [ os.path.abspath(python3_path), os.path.abspath("dirty_hack.py"), tempfilename ] for key, value in self.options.__dict__.items(): if "color" in key: value = convert_to_cairo(value) if key in ("selected_nodes", "ids", "tab", "name"): continue vals.append("--{}".format(key)) vals.append(str(value)) inkex.debug(" ".join(vals)) subprocess.check_call(vals) t = etree.parse(tempfilename) self.document.getroot().append(t.getroot()) os.remove(tempfilename)
def effect(self): """Fix text layout in regular and flowed text elements.""" items = self.selected.values() or self.document.getroot() for node in items: self.process_items(node) if self.options.verbose: inkex.debug(inkex.etree.tostring(self.document))
def select_imaging_module(module): """Switch Python Imaging module based on argument. Verify availability of selected module and notify user if the selected module is not available. """ global USE_WAND global USE_PIL not_available = _("Selected python imaging module is not available") if module == "wand" or module == "Wand": if HAVE_WAND: USE_WAND = True USE_PIL = False if DEBUG: inkex.debug('Setting imaging module to {}.'.format(module)) else: inkex.errormsg('{0}: {1}'.format(not_available, module)) elif module == 'pil' or module == 'PIL': if HAVE_PIL: USE_WAND = False USE_PIL = True if DEBUG: inkex.debug('Setting imaging module to {}.'.format(module)) else: inkex.errormsg('{0}: {1}'.format(not_available, module)) elif module == 'default': pass else: inkex.errormsg('{0}: {1}'.format(not_available, module))
def fix_font_name(node, debug=False): """Fix generic font names (sans-serif, serif, monospace).""" prop = 'font-family' ink_prop = '-inkscape-font-specification' # inner style for child in node.iterchildren(tag=inkex.etree.Element): fix_font_name(child, debug) # outer style if prop in node.attrib: name = node.get(prop) if name in FONTFAMILY_GENERIC: node.set(prop, FONTFAMILY_GENERIC[name]) pdict = simplestyle.parseStyle(node.get('style')) if prop in pdict: name = pdict[prop] if name in FONTFAMILY_GENERIC: pdict[prop] = FONTFAMILY_GENERIC[name] node.set('style', simplestyle.formatStyle(pdict)) if ink_prop in pdict: if debug: inkex.debug(pdict[ink_prop]) ink_val = pdict[ink_prop].strip("'").split() name = ink_val[0] if name in FONTFAMILY_GENERIC: if len(ink_val) > 1: ink_val[0] = FONTFAMILY_GENERIC[name] pdict[ink_prop] = "'" + ' '.join(ink_val) + "'" elif len(ink_val): pdict[ink_prop] = FONTFAMILY_GENERIC[name] node.set('style', simplestyle.formatStyle(pdict))
def getLength(self, name, default): ''' Get the <svg> attribute with name "name" and default value "default" Parse the attribute into a value and associated units. Then, accept no units (''), units of pixels ('px'), and units of percentage ('%'). ''' str = self.svg.get(name) conversions = { 'in': 90.0, 'ft': 1080.0, 'mm': 1.0 / 0.28222, 'cm': 1.0 / 0.028222, } if str: v, u = parseLengthWithUnits(str) if not v: # Couldn't parse the value inkex.debug("Couldn't parse %s" % str) return None elif (u == '') or (u == 'px'): return v elif u in conversions: return v * conversions[u] elif u == '%': return float(default) * v / 100.0 else: inkex.debug("Unsported units %s" % str) # Unsupported units return None else: # No width specified; assume the default value return float(default)
def effect(self): """Process current document.""" global DEBUG DEBUG = self.options.debug if DEBUG: report_imaging_module("Default imaging module") if self.options.tab == '"tab_basic"': cmd_scope = "in_document" elif self.options.tab == '"tab_attribute"': cmd_scope = self.options.scope_attribute elif self.options.tab == '"tab_property"': cmd_scope = self.options.scope_property elif self.options.tab == '"help"': pass else: cmd_scope = self.options.scope params = self.get_params() if cmd_scope is not None: try: change_cmd = getattr(self, 'change_{0}'.format(cmd_scope)) except AttributeError as error_msg: inkex.debug('Scope "{0}" not supported'.format(cmd_scope)) inkex.debug('Technical details:\n{0}'.format(error_msg)) else: change_cmd(self.selected, params)
def effect(self): totalPathCoords = [] for node in self.document.getroot().iter(): if node.tag == '{http://www.w3.org/2000/svg}path': # TODO: Ugly d = node.get('d') path = parsePath(d) pathCoords = [] for point in path: x = point[1][0] y = point[1][1] pathCoords.append([x, y]) revPathCoords = pathCoords[:] # TODO: Ugly revPathCoords.reverse() if isInTotalPaths(pathCoords, totalPathCoords, self.options.radius): inkex.debug("I WANT TO BREAK FREE") node.getparent().remove(node) elif self.options.reverse and isInTotalPaths(revPathCoords, totalPathCoords, self.options.radius): inkex.debug("I WANT TO BREAK FREE") node.getparent().remove(node) else: totalPathCoords.append(pathCoords)
def effect(self): gcode = "" i = 0 doc = self.document.getroot() factor = self.unittouu(doc.get('width')) inkex.debug(factor) for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] first = True gcode = "M3 S255(colona " + str(i) + ") \n" #+"G01 F500.000\n" for csp in p[0]: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) gcode += "G01 X" + str( round(self.uutounit(csp[1][0], "mm"), 2)) + " Y" + str( round(self.uutounit(csp[1][1], "mm"), 2)) + "\n" node.set('d', simplepath.formatPath(np)) f = open("costycnc.nc", 'w') f.write(str(gcode)) f.close()
def effect(self): if not os.path.exists(self.options.config): inkex.debug("! Config file not found. Path correct?"); return if not os.path.exists(self.options.outdir): inkex.debug("! Output path inaccessible. Permissions?"); return self.SVG = self.document.getroot() self.scanAvailableLayers() self.parseFile = self.options.outdir+'/temp.MockupMachine' configLines = (line.rstrip('\n') for line in open(self.options.config, 'r')) for line in configLines: line = line.strip() command1 = line[:1] command2 = line[:2] command2val = line[2:].strip() exported = False if(command1 == ';'): # comment, no action continue if(command2 == '--' or line == ''): self.exportCurrent() exported = True self.renderBoxId = '' if(command2 == '- '): if not command2val in self.availableLayers: inkex.debug("!- Layer '"+command2val+"' unknown.") else: while command2val in self.activeLayers: self.activeLayers.remove(command2val) list(set(self.activeLayers)) elif(command2 == '+ '): if not command2val in self.availableLayers: inkex.debug("!+ Layer '"+command2val+"' unknown.") else: if not command2val in self.activeLayers: self.activeLayers.append(command2val) list(set(self.activeLayers)) elif(command2 == '# '): if self.getElementById(command2val) is not None: self.renderBoxId = command2val else: inkex.debug("!# Box ID '"+command2val+"' unknown.") elif(command2 == '--'): self.activeLayers = [] elif(line == ''): pass else: self.filename = line[:-1] self.filenameCounter = self.filenameCounter + 1 ''' export the last pending image ''' if not exported: self.exportCurrent()
def effect(self): unit = self.options.unit # which direction are we cutting dir = self.options.direction # starting cut length. Will be adjusted for get an integer number of cuts in the y-direction. l = self.unittouu(str(self.options.cut_length) + unit) # cut separation in the y-direction d = self.unittouu(str(self.options.gap_length) + unit) # starting separation between lines of cuts in the x-direction. Will be adjusted to get an integer # number of cut lines in the x-direction. dd = self.unittouu(str(self.options.sep_distance) + unit) # get selected nodes if self.selected: # put lines on the current layer parent = self.current_layer for id, node in self.selected.iteritems(): # inkex.debug("id:" + id) # for key in node.attrib.keys(): # inkex.debug(key + ": " + node.get(key)) x = float(node.get("x")) dx = float(node.get("width")) y = float(node.get("y")) dy = float(node.get("height")) # calculate the cut lines for the hinge if (dir == "y"): lines, l_actual, d_actual, dd_actual = self.calcYCutLines( x, y, dx, dy, l, d, dd) else: lines, l_actual, d_actual, dd_actual = self.calcXCutLines( x, y, dx, dy, l, d, dd) # all the lines are one path. Prepare the string that describes the path. s = '' for line in lines: s = s + "M %s, %s L %s, %s " % (line['x1'], line['y1'], line['x2'], line['y2']) # add the path to the document style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': self.unittouu("0.1 mm") } drw = {'style': simplestyle.formatStyle(style), 'd': s} hinge = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), drw) # add a description element to hold the parameters used to create the cut lines desc = inkex.etree.SubElement(hinge, inkex.addNS('desc', 'svg')) desc.text = "Hinge cut parameters: actual(requested)\n" \ "cut length: %.2f %s (%.2f %s)\n" \ "gap length: %.2f %s (%.2f %s)\n" \ "separation distance: %.2f %s (%.2f %s)" % (self.uutounit(l_actual, unit), unit, self.uutounit(l, unit), unit, self.uutounit(d_actual, unit), unit, self.uutounit(d, unit), unit, self.uutounit(dd_actual, unit), unit, self.uutounit(dd, unit), unit) else: inkex.debug("No rectangle(s) have been selected.")
def effect(self): if not os.path.exists(self.options.config): inkex.debug("! Config file not found. Path correct?") return if not os.path.exists(self.options.outdir): inkex.debug("! Output path inaccessible. Permissions?") return self.SVG = self.document.getroot() self.scanAvailableLayers() self.parseFile = self.options.outdir + '/temp.MockupMachine' configLines = (line.rstrip('\n') for line in open(self.options.config, 'r')) for line in configLines: line = line.strip() command1 = line[:1] command2 = line[:2] command2val = line[2:].strip() exported = False if (command1 == ';'): # comment, no action continue if (command2 == '--' or line == ''): self.exportCurrent() exported = True self.renderBoxId = '' if (command2 == '- '): if not command2val in self.availableLayers: inkex.debug("!- Layer '" + command2val + "' unknown.") else: while command2val in self.activeLayers: self.activeLayers.remove(command2val) list(set(self.activeLayers)) elif (command2 == '+ '): if not command2val in self.availableLayers: inkex.debug("!+ Layer '" + command2val + "' unknown.") else: if not command2val in self.activeLayers: self.activeLayers.append(command2val) list(set(self.activeLayers)) elif (command2 == '# '): if self.getElementById(command2val) is not None: self.renderBoxId = command2val else: inkex.debug("!# Box ID '" + command2val + "' unknown.") elif (command2 == '--'): self.activeLayers = [] elif (line == ''): pass else: self.filename = line[:-1] ''' export the last pending image ''' if not exported: self.exportCurrent()
def load_xml(filename, sel_layout, textlines, cur_layer): # Load XML File which selected from Configuration Tab try: xmldoc = minidom.parse(filename) LayoutsDOM(xmldoc, sel_layout, textlines, cur_layer) except xml.parsers.expat.ExpatError, e: inkex.debug("Sorry, something seems wrong with your .xml File:\n" + str(e) + "\n\n")
def inMasterLayer(self): layer=self.current_layer while layer!=None: if layer.get(u"{" + inkex.NSS[u"interink"]+ u"}type")=='root': return True layer=layer.getparent() inkex.debug("Vous devez sélectionner le calque 'interinkdoc' ou un calque enfant.") return False
def handleIfCoords(ifclauses, sizex, sizey, textlines, cur_layer): # Handle each IF- Coordinates for ifclause in ifclauses: if Debug: inkex.debug(str("IfClause Braces: " + str(ifclause) + "\n")) coords = ifclause.getElementsByTagName("coords") ifset = ifclause.getAttribute("set") # Which Value should be watched handleCoords(ifset, coords, sizex, sizey, textlines, cur_layer)
def effect(self): if len(self.options.ids) < 2: inkex.debug( "Requires two selected paths. The second must be exctly four nodes long." ) exit() #obj is selected second obj = self.selected[self.options.ids[0]] envelope = self.selected[self.options.ids[1]] if (obj.tagName == 'path' or obj.tagName == 'g') and envelope.tagName == 'path': path = cubicsuperpath.parsePath( envelope.attributes.getNamedItem('d').value) dp = zeros((4, 2), dtype=float64) for i in range(4): dp[i][0] = path[0][i][1][0] dp[i][1] = path[0][i][1][1] #query inkscape about the bounding box of obj q = {'x': 0, 'y': 0, 'width': 0, 'height': 0} file = self.args[-1] id = self.options.ids[0] for query in q.keys(): f = os.popen("inkscape --query-%s --query-id=%s %s" % (query, id, file)) q[query] = float(f.read()) f.close() sp = array([[q['x'], q['y'] + q['height']], [q['x'], q['y']], [q['x'] + q['width'], q['y']], [q['x'] + q['width'], q['y'] + q['height']]], dtype=float64) solmatrix = zeros((8, 8), dtype=float64) free_term = zeros((8), dtype=float64) for i in (0, 1, 2, 3): solmatrix[i][0] = sp[i][0] solmatrix[i][1] = sp[i][1] solmatrix[i][2] = 1 solmatrix[i][6] = -dp[i][0] * sp[i][0] solmatrix[i][7] = -dp[i][0] * sp[i][1] solmatrix[i + 4][3] = sp[i][0] solmatrix[i + 4][4] = sp[i][1] solmatrix[i + 4][5] = 1 solmatrix[i + 4][6] = -dp[i][1] * sp[i][0] solmatrix[i + 4][7] = -dp[i][1] * sp[i][1] free_term[i] = dp[i][0] free_term[i + 4] = dp[i][1] res = solve(solmatrix, free_term) projmatrix = array( [[res[0], res[1], res[2]], [res[3], res[4], res[5]], [res[6], res[7], 1.0]], dtype=float64) if obj.tagName == "path": self.process_path(obj, projmatrix) if obj.tagName == "g": self.process_group(obj, projmatrix)
def effect(self): defs = self.xpathSingle('/svg//defs') if not defs: defs = self.document.createElement('svg:defs') self.document.documentElement.appendChile(defs) for id, node in self.selected.iteritems(): mprops = ['marker', 'marker-start', 'marker-mid', 'marker-end'] try: style = simplestyle.parseStyle( node.attributes.getNamedItem('style').value) except: inkex.debug("No style attribute found for id: %s" % id) continue stroke = style.get('stroke', '#000000') for mprop in mprops: if style.has_key(mprop) and style[mprop] != 'none' and style[ mprop][:5] == 'url(#': marker_id = style[mprop][5:-1] try: old_mnode = self.xpathSingle('/svg//marker[@id="%s"]' % marker_id) if not self.options.modify: mnode = old_mnode.cloneNode(True) else: mnode = old_mnode except: inkex.debug("unable to locate marker: %s" % marker_id) continue new_id = self.uniqueId(marker_id, not self.options.modify) style[mprop] = "url(#%s)" % new_id mnode.attributes.getNamedItem('id').value = new_id mnode.attributes.getNamedItemNS(inkex.NSS['inkscape'], 'stockid').value = new_id defs.appendChild(mnode) children = inkex.xml.xpath.Evaluate( '/svg//marker[@id="%s"]//*[@style]' % new_id, self.document, context=self.ctx) for child in children: cstyle = simplestyle.parseStyle( child.attributes.getNamedItem('style').value) if ('stroke' in cstyle and cstyle['stroke'] != 'none' ) or 'stroke' not in cstyle: cstyle['stroke'] = stroke if ('fill' in cstyle and cstyle['fill'] != 'none' ) or 'fill' not in cstyle: cstyle['fill'] = stroke child.attributes.getNamedItem( 'style').value = simplestyle.formatStyle(cstyle) node.attributes.getNamedItem( 'style').value = simplestyle.formatStyle(style)
def split_lines(self, node): """Returns a list of lines""" lines = [] count = 1 for n in node: if not (n.tag == inkex.addNS("flowPara", "svg") or n.tag == inkex.addNS("tspan", "svg")): if n.tag == inkex.addNS("textPath", "svg"): inkex.debug("This type of text element isn't supported. First remove text from path.") break else: continue text = inkex.etree.Element(inkex.addNS("text", "svg"), node.attrib) # handling flowed text nodes if node.tag == inkex.addNS("flowRoot", "svg"): try: from simplestyle import parseStyle fontsize = parseStyle(node.get("style"))["font-size"] except: fontsize = "12px" fs = inkex.unittouu(fontsize) # selects the flowRegion's child (svg:rect) to get @X and @Y id = node.get("id") flowref = self.xpathSingle('/svg:svg//*[@id="%s"]/svg:flowRegion[1]' % id)[0] if flowref.tag == inkex.addNS("rect", "svg"): text.set("x", flowref.get("x")) text.set("y", str(float(flowref.get("y")) + fs * count)) count += 1 else: inkex.debug("This type of text element isn't supported. First unflow text.") break # now let's convert flowPara into tspan tspan = inkex.etree.Element(inkex.addNS("tspan", "svg")) tspan.set(inkex.addNS("role", "sodipodi"), "line") tspan.text = n.text text.append(tspan) else: from copy import copy x = n.get("x") or node.get("x") y = n.get("y") or node.get("y") text.set("x", x) text.set("y", y) text.append(copy(n)) lines.append(text) return lines
def debug_points(cls, paths): """ Plots points of path tree in drawing order. """ if type(paths) == Path: inkex.debug(paths.points) elif type(paths) == list: for sub_path in paths: Path.debug_points(sub_path)
def effect(self): defs = self.xpathSingle('/svg//defs') if not defs: defs = self.document.createElement('svg:defs') self.document.documentElement.appendChile(defs) for id, node in self.selected.iteritems(): mprops = ['marker', 'marker-start', 'marker-mid', 'marker-end'] try: style = simplestyle.parseStyle( node.attributes.getNamedItem('style').value) except: inkex.debug("No style attribute found for id: %s" % id) continue stroke = style.get('stroke', '#000000') for mprop in mprops: if style.has_key(mprop) and style[mprop] != 'none' and style[ mprop][:5] == 'url(#': marker_id = style[mprop][5:-1] try: old_mnode = self.xpathSingle( '/svg//marker[@id="%s"]' % marker_id) if not self.options.modify: mnode = old_mnode.cloneNode(True) else: mnode = old_mnode except: inkex.debug("unable to locate marker: %s" % marker_id) continue new_id = self.uniqueId(marker_id, not self.options.modify) style[mprop] = "url(#%s)" % new_id mnode.attributes.getNamedItem('id').value = new_id mnode.attributes.getNamedItemNS(inkex.NSS['inkscape'], 'stockid').value = new_id defs.appendChild(mnode) children = inkex.xml.xpath.Evaluate( '/svg//marker[@id="%s"]//*[@style]' % new_id, self.document, context=self.ctx) for child in children: cstyle = simplestyle.parseStyle( child.attributes.getNamedItem('style').value) if ('stroke' in cstyle and cstyle['stroke'] != 'none' ) or 'stroke' not in cstyle: cstyle['stroke'] = stroke if ('fill' in cstyle and cstyle['fill'] != 'none' ) or 'fill' not in cstyle: cstyle['fill'] = stroke child.attributes.getNamedItem( 'style').value = simplestyle.formatStyle(cstyle) node.attributes.getNamedItem( 'style').value = simplestyle.formatStyle(style)
def effect(self): for node in self.svg.selection: self.convert2dash(node) if self.not_converted: inkex.errormsg( _('Total number of objects not converted: {}\n').format( len(self.not_converted))) # return list of IDs in case the user needs to find a specific object inkex.debug(self.not_converted)
def effect(self): if len(self.options.ids) < 2: inkex.debug("This extension requires that you select two paths.") return self.prepareSelectionList() #center at (0,0) bbox = pathmodifier.computeBBox([self.patternNode]) mat = [[1, 0, -(bbox[0] + bbox[1]) / 2], [0, 1, -(bbox[2] + bbox[3]) / 2]] if self.options.vertical: bbox = [-bbox[3], -bbox[2], bbox[0], bbox[1]] mat = simpletransform.composeTransform([[0, -1, 0], [1, 0, 0]], mat) mat[1][2] += self.options.noffset simpletransform.applyTransformToNode(mat, self.patternNode) width = bbox[1] - bbox[0] dx = width + self.options.space for skelnode in self.skeletons.itervalues(): self.curSekeleton = cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: 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) if self.options.stretch: dx = width + self.options.space n = int( (length - self.options.toffset + self.options.space) / dx) if n > 0: dx = (length - self.options.toffset) / n xoffset = self.skelcomp[0][0] - bbox[0] + self.options.toffset yoffset = self.skelcomp[0][1] - ( bbox[2] + bbox[3]) / 2 - self.options.noffset s = self.options.toffset while s <= length: mat = self.localTransformAt(s, self.options.follow) clone = copy.deepcopy(self.patternNode) #!!!--> should it be given an id? #seems to work without this!?! myid = self.patternNode.tag.split('}')[-1] clone.set("id", self.uniqueId(myid)) self.gNode.append(clone) simpletransform.applyTransformToNode(mat, clone) s += dx self.patternNode.getparent().remove(self.patternNode)
def parseSVG(self,file): #"""Parse document in specified file or on stdin""" try: stream = open(file,'r') doc=etree.parse(stream) stream.close() except: inkex.debug('File ' + str(file) + ' not found') doc=False return (doc)
def exportToPng(self, svg_path, output_path): area_param = '-D' if self.options.crop else 'C' command = "inkscape %s -d %s -e \"%s\" \"%s\"" % ( area_param, self.options.dpi, output_path, svg_path) if (self.options.debug): inkex.debug(command) return subprocess.Popen(command.encode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def handleLayoutTitle(layout, layout2, sel_layout, textlines, cur_layer): # Place Text on its Coordinates and selected Alignment on matching with selected Layout layouttitle = layout.firstChild.data if layouttitle == sel_layout: sizex = layout2.getAttribute("x") # Get Width of Layout sizey = layout2.getAttribute("y") # Get Height of Layout handleIfCoords(layout2.getElementsByTagName("if"), sizex, sizey, textlines, cur_layer) handleCoords(False,layout2.getElementsByTagName("coords"), sizex, sizey, textlines, cur_layer) if Debug: inkex.debug(str("X: " + sizex) + str(" Y: " + sizey)) inkex.debug(str("LayoutTitle: " + layouttitle + " Selected Layout: " + str(sel_layout) + "\n"))
def isInTotalPaths(path, totalPaths, tolerance): for totalPath in totalPaths: commonPoints = 0 for (pathPoint, totalPathPoint) in (path, totalPath): if distance(pathPoint, totalPathPoint) <= tolerance: commonPoints += 1 if commonPoints >= len(path): return True return False class removeDuplicates(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) self.OptionParser.add_option("--title") self.OptionParser.add_option("-r", "--radius", action="store", type="float", dest="radius", default=0.0, help="Maximum radius (px)") self.OptionParser.add_option("-rev", "--reverse", action="store", type="bool", dest="reverse", default=0.0, help="Consider reversed paths as equals") self.OptionParser.add_option("--tab", action="store", type="string", dest="tab", help="The selected UI-tab when OK was pressed") def effect(self): totalPathCoords = [] for node in self.document.getroot().iter(): if node.tag == '{http://www.w3.org/2000/svg}path': # TODO: Ugly d = node.get('d') path = parsePath(d) pathCoords = [] for point in path: x = point[1][0] y = point[1][1] pathCoords.append([x, y]) revPathCoords = pathCoords[:] # TODO: Ugly revPathCoords.reverse() if isInTotalPaths(pathCoords, totalPathCoords, self.options.radius): inkex.debug("I WANT TO BREAK FREE") node.getparent().remove(node) elif self.options.reverse and isInTotalPaths(revPathCoords, totalPathCoords, self.options.radius): inkex.debug("I WANT TO BREAK FREE") node.getparent().remove(node) else: totalPathCoords.append(pathCoords) inkex.debug('done')
def effect(self): """ Main function """ # A function to convert to millimiters to_mm = lambda value: self.uutounit(value, 'mm') # A function to convert to user units. This must be used to write units in the svg to_uu = lambda value: self.unittouu(str(value) + "mm") # Extracting the height of the document. This is needed to flip y axis coordinates (y=0 is # at bottom in inkscape but at top in svg...). We get the height in millimeters self.doc_height = to_mm( self.unittouu(self.document.getroot().get('height'))) # Draw the working area working_area_generator = WorkingAreaGenerator(self.doc_height, to_uu, WORKING_AREA_ID) working_area_generator.set_size(self.options.dim_x, self.options.dim_y) working_area_generator.upsert(self.current_layer) if not self.options.ids: # print info and exit # Using error message even if this it not really an error... inkex.debug( _(("No path was seletect, only the working area was generated. Now draw a " "path inside the working area and select it to generate the g-code" ))) else: # Extracting paths in machine coordinates paths_extractor = PathsExtractor( self.selected.values(), self.doc_height, to_mm, WORKING_AREA_ID, FlattenBezier(self.options.flatness)) paths_extractor.extract() # Joining paths. This will also check that all paths are closed paths_joiner = PathsJoiner(paths_extractor.paths(), CLOSE_DISTANCE) paths_joiner.unite() # Generate tool positions and orientations tool_path_generator = CuttingToolPathsGenerator( paths_joiner.union_path(), CLOSE_DISTANCE) tool_path_generator.generate() # Generating g-code gcode_generator = CuttingGCodeGenerator(tool_path_generator.path(), self.options.speed, self.options.temperature) gcode_generator.generate() # Writing to file filename = gcode_filename(self.options.filename, self.gcode_file_path) write_gcode_file(gcode_generator.gcode(), filename) inkex.debug(_("The generate g-code has been save to ") + filename)
def getiiNode(self, type): path=self.objectPath + type +u".svg" file=self.parseSVG(path) if file==False: return False svg=file.getroot() node=self.findFirstChild(svg, type) if node==False: inkex.debug('Corruption du fichier '+ path) return False return node
def foreach_selected(self, f, args=None): for id, node in self.selected.iteritems(): shapename = self.svg_getattr(node, inkex.addNS('shape','gdadin')) if not shapename: inkex.debug('WARNING: one of the selected objects isn\'t a defined shape (use Gdadin -> Define Shape). I\'ll ignore it.') continue if args: f(id, node, shapename, *args) else: f(id, node, shapename)
def saveToFile(self,content,filename): FILE = open(filename,'w') if(FILE): FILE.write(content) FILE.close() return True else: inkex.debug('Bonsai.templateOutput: Unable to open output file "'+filename+'". Aborting.') return False
def draw_svg_text(char, face, offset, vertoffset, parent): style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': '0.5', 'stroke-miterlimit': '4', } pathString = face[char] splitString = pathString.split() midpoint = offset - int(splitString[0]) pathString = pathString[pathString.find("M"):] #portion after first move trans = 'translate(' + str(midpoint) + ',' + str(vertoffset) + ')' text_attribs = {'style':simplestyle.formatStyle(style), 'd':pathString, 'transform':trans} inkex.etree.SubElement(parent, inkex.addNS('path','svg'), text_attribs) if Debug: inkex.debug("Char: " + str(char) + " PathString: " + str(pathString) + str(" Midpoint: " + str(midpoint) + " SplitString0: " + str(splitString[0]) + " SplitString1: " + str(splitString[1]) + "\n")) return midpoint + int(splitString[1]) #new offset value
def getColorString(self, longColor, verbose=False): """ Convert the long into a #RRGGBB color value - verbose=true pops up value for us in defaults conversion back is A + B*256^1 + G*256^2 + R*256^3 """ if verbose: inkex.debug("%s ="%(longColor)) longColor = long(longColor) if longColor <0: longColor = long(longColor) & 0xFFFFFFFF hexColor = hex(longColor)[2:-3] hexColor = '#' + hexColor.rjust(6, '0').upper() if verbose: inkex.debug(" %s for color default value"%(hexColor)) return hexColor
def effect(self): if len(self.options.ids)<2: inkex.debug("This extension requires that you select two paths.") return self.prepareSelectionList() #center at (0,0) bbox=pathmodifier.computeBBox([self.patternNode]) mat=[[1,0,-(bbox[0]+bbox[1])/2],[0,1,-(bbox[2]+bbox[3])/2]] if self.options.vertical: bbox=[-bbox[3],-bbox[2],bbox[0],bbox[1]] mat=simpletransform.composeTransform([[0,-1,0],[1,0,0]],mat) mat[1][2] += self.options.noffset simpletransform.applyTransformToNode(mat,self.patternNode) width=bbox[1]-bbox[0] dx=width+self.options.space for skelnode in self.skeletons.itervalues(): self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: 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) if self.options.stretch: dx=width+self.options.space n=int((length-self.options.toffset+self.options.space)/dx) if n>0: dx=(length-self.options.toffset)/n xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset s=self.options.toffset while s<=length: mat=self.localTransformAt(s,self.options.follow) clone=copy.deepcopy(self.patternNode) #!!!--> should it be given an id? #seems to work without this!?! myid = self.patternNode.tag.split('}')[-1] clone.set("id", self.uniqueId(myid)) self.gNode.append(clone) simpletransform.applyTransformToNode(mat,clone) s+=dx self.patternNode.getparent().remove(self.patternNode)
def wpi_import_direct(self, infile, custom_opts=''): """ Import via inklingreader's direct SVG output (no temp file needed) """ helper_app = 'inklingreader' inout_opts = ' --file "%s" --direct-output' # run external command if self.verbose: inkex.debug(((helper_app + custom_opts + inout_opts) % infile, helper_app, self.verbose)) run_direct((helper_app + custom_opts + inout_opts) % infile, helper_app, self.verbose)
def effect(self): f = urllib.urlopen("https://raw.github.com/renaultd/lasercut/" + \ "master/lc_version.py") j = f.read() if (re.match("__version__ = \([0-9]+,[0-9]+,[0-9]+\)\n",j)): vstr = re.findall("[a-z_]+ = \(([0-9]+),([0-9]+),([0-9]+)\)\n",j)[0] version = (int(vstr[0]),int(vstr[1]),int(vstr[2])) inkex.debug("Current version : " + str(version)) inkex.debug("Most recent version : " + str(__version__)) pwd = os.path.dirname(os.path.realpath(__file__)) fd,zipn = tempfile.mkstemp() urllib.urlretrieve("https://api.github.com/repos/" + \ "renaultd/lasercut/zipball/", zipn) zip = zipfile.ZipFile(zipn) ms = [ m for m in zip.namelist() if re.match(".*\.(py|inx)",m) ] t = tempfile.mkdtemp() for m in ms: inkex.debug(m) zip.extract(m,t) shutil.copy(os.path.join(t,m), pwd) os.close(fd) os.remove(zipn) shutil.rmtree(t) else: inkex.debug("Unable to fetch distant repository")
def templateOutput(self,templateName = '',placeholder = ''): if(placeholder == ''): inkex.debug('Bonsai.templateOutput: Mandatory argument "placeholder" missing. Aborting.') return False if(templateName == ''): inkex.debug('Bonsai.templateOutput: Mandatory argument "templateName" missing. Aborting.') return False FILE = open(templateName,'r') if(FILE): template = FILE.read() FILE.close() if(len(template) > 0): content = ','.join([str(el) for el in self.json_output]) tplResult = string.replace(template,placeholder,content) return tplResult else: inkex.debug('Bonsai.templateOutput: Empty template file "'+templateName+'". Aborting.') return False else: inkex.debug('Bonsai.templateOutput: Unable to open template file "'+templateName+'". Aborting.') return False
def effect(self): clippingLineSegments = None pathTag = inkex.addNS('path','svg') groupTag = inkex.addNS('g','svg') error_messages = [] for id in self.options.ids: # the selection, top-down node = self.selected[id] if node.tag == pathTag: if clippingLineSegments is None: # first path is the clipper (clippingLineSegments, errors) = self.simplepathToLineSegments(simplepath.parsePath(node.get('d'))) error_messages.extend(['{}: {}'.format(id, err) for err in errors]) else: # do all the work! segmentsToClip, errors = self.simplepathToLineSegments(simplepath.parsePath(node.get('d'))) error_messages.extend(['{}: {}'.format(id, err) for err in errors]) clippedSegments = self.clipLineSegments(segmentsToClip, clippingLineSegments) if len(clippedSegments) != 0: # replace the path node.set('d', simplepath.formatPath(self.linesgmentsToSimplePath(clippedSegments))) else: # don't put back an empty path(?) could perhaps put move, move? inkex.debug('Object {} clipped to nothing, will not be updated.'.format(node.get('id'))) elif node.tag == groupTag: # we don't look inside groups for paths inkex.debug('Group object {} will be ignored. Please ungroup before running the script.'.format(id)) else: # something else inkex.debug('Object {} is not of type path ({}), and will be ignored. Current type "{}".'.format(id, pathTag, node.tag)) for error in error_messages: inkex.debug(error)
def translateElement(self, node, x, y, relative=False): # Grab transform attribute if it exists. transform = node.get("transform", "") # Compute the nodes bounding box box = list(simpletransform.computeBBox([node])) pos_x = box[0] pos_y = box[2] # rotation center is not a breeze to calculate from the matrix, so thanks inkscape ;) origin_x = float(node.get(inkex.addNS("transform-center-x", "inkscape"), 0)) origin_y = float(node.get(inkex.addNS("transform-center-y", "inkscape"), 0)) origin_x = origin_x + (box[1] / 2) origin_y = (origin_y * -1) + (box[3] / 2) if transform == "": # If there is no transform attribute on the node we add one node.attrib["transform"] = "" # simpletransform returns a multi dim array of matrix values transform = simpletransform.parseTransform(transform) transformObject = self.normalizeMatrix(transform) inkex.debug(transformObject) # offset_x = (transform[0][2]-pos_x) # offset_y = (transform[1][2]-pos_y) offset_x = pos_x * -1 offset_y = pos_y * -1 inkex.debug([offset_x, offset_y]) transform = simpletransform.parseTransform( ("translate(" + str(offset_x) + " " + str(offset_y) + ")"), transform ) transformObject = self.normalizeMatrix(transform) inkex.debug(transformObject) inkex.debug(transform) if relative == False: matrix = simpletransform.formatTransform(transform) node.set("transform", matrix) inkex.debug(matrix) else: simpletransform.applyTransformToNode(transform, node)
def objectToPath(self,node,doReplace=True): #--TODO: support other object types!!!! #--TODO: make sure cubicsuperpath supports A and Q commands... if node.tagName == 'rect': return(self.rectToPath(node,doReplace)) elif node.tagName == 'path': attributes = node.attributes.keys() for uri,attName in attributes: if uri in [inkex.NSS[u'sodipodi'],inkex.NSS[u'inkscape']]: # if attName not in ["d","id","style","transform"]: node.removeAttributeNS(uri,attName) fuseTransform(node) return node else: inkex.debug("Please first convert objects to paths!...(got '%s')"%node.tagName) return None
def effect(self): if len(self.options.ids) < 2: inkex.debug("Requires two selected paths. The second must be exctly four nodes long.") exit() #obj is selected second obj = self.selected[self.options.ids[0]] envelope = self.selected[self.options.ids[1]] if (obj.tagName == 'path' or obj.tagName == 'g') and envelope.tagName == 'path': path = cubicsuperpath.parsePath(envelope.attributes.getNamedItem('d').value) dp = zeros((4,2), dtype=float64) for i in range(4): dp[i][0] = path[0][i][1][0] dp[i][1] = path[0][i][1][1] #query inkscape about the bounding box of obj q = {'x':0,'y':0,'width':0,'height':0} file = self.args[-1] id = self.options.ids[0] for query in q.keys(): f = os.popen("inkscape --query-%s --query-id=%s %s" % (query,id,file)) q[query] = float(f.read()) f.close() sp = array([[q['x'], q['y']+q['height']],[q['x'], q['y']],[q['x']+q['width'], q['y']],[q['x']+q['width'], q['y']+q['height']]], dtype=float64) solmatrix = zeros((8,8), dtype=float64) free_term = zeros((8), dtype=float64) for i in (0,1,2,3): solmatrix[i][0] = sp[i][0] solmatrix[i][1] = sp[i][1] solmatrix[i][2] = 1 solmatrix[i][6] = -dp[i][0]*sp[i][0] solmatrix[i][7] = -dp[i][0]*sp[i][1] solmatrix[i+4][3] = sp[i][0] solmatrix[i+4][4] = sp[i][1] solmatrix[i+4][5] = 1 solmatrix[i+4][6] = -dp[i][1]*sp[i][0] solmatrix[i+4][7] = -dp[i][1]*sp[i][1] free_term[i] = dp[i][0] free_term[i+4] = dp[i][1] res = solve(solmatrix, free_term) projmatrix = array([[res[0],res[1],res[2]],[res[3],res[4],res[5]],[res[6],res[7],1.0]],dtype=float64) if obj.tagName == "path": self.process_path(obj,projmatrix) if obj.tagName == "g": self.process_group(obj,projmatrix)
def make_string(string, font, spacing, spacing1, spacing2, group): #evaluate text string #Check which Font is selected w = 0 letterVals = [ord(q) - 32 for q in unicode(string,'utf-8')] if Debug: inkex.debug("FOR Q: " + str(letterVals) + " String:" + str(string) + "\n") for q in letterVals: if Debug: inkex.debug("For Q: " + str(q) + "\n") # Ignore unavailable Letters except german umlaute if (q == 164 or q == 182 or q == 188 or q == 191 or q == 196 or q == 214 or q == 220 or 0 <= q < 93): w = draw_svg_text(q, font, w+spacing1, spacing2, group) else: w += 2*spacing return w
def effect(self): unit=self.options.unit # starting cut length. Will be adjusted for get an integer number of cuts in the y-direction. l = self.unittouu(str(self.options.cut_length) + unit) # cut separation in the y-direction d = self.unittouu(str(self.options.gap_length) + unit) # starting separation between lines of cuts in the x-direction. Will be adjusted to get an integer # number of cut lines in the x-direction. dd = self.unittouu(str(self.options.sep_distance) + unit) # get selected nodes if self.selected: # put lines on the current layer parent = self.current_layer for id, node in self.selected.iteritems(): # inkex.debug("id:" + id) # for key in node.attrib.keys(): # inkex.debug(key + ": " + node.get(key)) x = float(node.get("x")) dx = float(node.get("width")) y = float(node.get("y")) dy = float(node.get("height")) # calculate the cut lines for the hinge lines, l_actual, d_actual, dd_actual = self.calcCutLines(x, y, dx, dy, l, d, dd) # all the lines are one path. Prepare the string that describes the path. s = '' for line in lines: s = s + "M %s, %s L %s, %s " % (line['x1'], line['y1'], line['x2'], line['y2']) # add the path to the document style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': self.unittouu("0.1 mm")} drw = {'style':simplestyle.formatStyle(style), 'd': s} hinge = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), drw) # add a description element to hold the parameters used to create the cut lines desc = inkex.etree.SubElement(hinge, inkex.addNS('desc', 'svg')) desc.text = "Hinge cut parameters: actual(requested)\n" \ "cut length: %.2f %s (%.2f %s)\n" \ "gap length: %.2f %s (%.2f %s)\n" \ "separation distance: %.2f %s (%.2f %s)" % (self.uutounit(l_actual, unit), unit, self.uutounit(l, unit), unit, self.uutounit(d_actual, unit), unit, self.uutounit(d, unit), unit, self.uutounit(dd_actual, unit), unit, self.uutounit(dd, unit), unit) else: inkex.debug("No rectangle(s) have been selected.")
def render(self): if self.at_least_one(): return random.seed(self.options.renderseed) self.set_gdadin_shapeids() self.render_stack=[] recursedata = { 'firstid' : None, 'mat' : None, 'hue' : 0.0, 'sat' : 0.0, 'bri' : 0.0, 'opa' : 0.0, 'hf' : -1, 'hc' : -1, 'sf' : -1, 'sc' : -1, 'bf' : -1, 'bc' : -1, 'of' : 0, 'oc' : 1 } def doit(id, node, shapename, rdata): self.compute_shape_bbox(id, node, shapename) self.add_rendergroup(id, node, shapename) self.render_shape(id, node, shapename, rdata) self.foreach_selected(doit, (recursedata,)) nshapes=0 maxnshapes=int(self.options.rendermaxshapes) while len(self.render_stack): if maxnshapes and nshapes > maxnshapes: inkex.debug('Maximum number of shapes reached ('+str(maxnshapes)+')') break args=self.render_stack.pop(0) self._render_shape(*args) nshapes+=1 if nshapes: self.adjust_document_dim()
def effect(self): # get number of digits prec = int(self.options.precision) total = 0 stotal = 0 totals = {} # loop over all selected paths for node in self.document.getroot().iterdescendants(): # path = "*" # for node in self.document.xpath(path, namespaces=inkex.NSS): if node.tag == inkex.addNS("path", "svg"): id = node.get("id") self.group = inkex.etree.SubElement(node.getparent(), inkex.addNS("text", "svg")) t = node.get("transform") # inkex.debug(node.get("style")) d = node.get("d") if not ("stroke" in simplestyle.parseStyle(node.get("style")) and len(simplepath.parsePath(d))): continue stroke = simplestyle.parseStyle(node.get("style"))["stroke"] a = [] p = cubicsuperpath.parsePath(node.get("d")) num = 1 factor = 1.0 / inkex.unittouu("1" + self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) else: stotal, x0, y0 = csparea(p) stotal *= factor * self.options.scale total += stotal if stroke in totals: totals[stroke] += stotal else: totals[stroke] = stotal # Format the length as string for key in totals: lenstr = locale.format( "%(len)25." + str(prec) + "f", {"len": round(totals[key] * factor * self.options.scale, prec)} ).strip() val = key for color in simplestyle.svgcolors.keys(): if simplestyle.svgcolors.get(color) == key: val = color inkex.debug(val + ":\t" + lenstr + "\t" + self.options.unit)
def startPlacerLoop(cur_layer, textline1, textline2, sizex, sizey, xpa, ypa, align, tsize, textf, sbtwl, vco, vcp, hcp, mrg): regline1 = pattern.match(str(textline1)) regline2 = pattern.match(str(textline2)) VAR1 = regline1.group(1) INT1 = regline1.group(2) VAR2 = regline2.group(1) INT2 = regline2.group(2) INTDIFF = int(INT2) - int(INT1) global i if i < 2: textline = VAR1 + INT1 else: textline = VAR1 + str(int(INT1) + INTDIFF * (i-1)) placeLayoutetText(cur_layer, textline, sizex, sizey, xpa, ypa, align, tsize, textf, sbtwl, vco, vcp, hcp, mrg) if Debug: inkex.debug(str("Looper: " + textline) + str(" Int: " + str(i) + "\n")) i += 1
def effect(self): if len(self.options.ids)<1: inkex.debug("This extension requires that you select at least one path.") return 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') ) self.dotGroup = inkex.etree.SubElement( self.group, inkex.addNS('g','svg') ) self.numGroup = inkex.etree.SubElement( self.group, inkex.addNS('g','svg') ) try: t = node.get('transform') self.group.set('transform', t) except: pass style = simplestyle.formatStyle({ 'stroke': 'none', 'fill': '#000' }) a = [] p = simplepath.parsePath(node.get('d')) self.separateLastAndFirst(p) num = 1 for cmd,params in p: if cmd != 'Z' and cmd != 'z': dot_att = { 'style': style, 'r': str( inkex.unittouu(self.options.dotsize) / 2 ), 'cx': str( params[-2] ), 'cy': str( params[-1] ) } inkex.etree.SubElement( self.dotGroup, inkex.addNS('circle','svg'), dot_att ) self.addText( self.numGroup, params[-2] + ( inkex.unittouu(self.options.dotsize) / 2 ), params[-1] - ( inkex.unittouu(self.options.dotsize) / 2 ), num ) num += 1 node.getparent().remove( node )
def createMarkersFromIntervals(self, parent, intervals): """ Check intervals. Then gather keys which need markers and the text for each one. Make markers. """ # Check intervals are well defined and markers are legit. intervalSumm = sum([int(i) for i in intervals]) if intervalSumm != 12: inkex.debug("Warning! Scale must have 12 half-tones. But %d defined."%(intervalSumm)) firstKeyNum = keyNumberFromNote(self.options.firstNote) lastKeyNum = keyNumberFromNote(self.options.lastNote) markedKeys = () markerText = () if keyNumberFromNote(self.options.keynote) in range(firstKeyNum, lastKeyNum+1): currentKey = keyNumberFromNote(self.options.keynote) markedKeys = (currentKey,) markerText = ('1',) currentInterval = 0 for key in range(keyNumberFromNote(self.options.keynote), lastKeyNum+1): if key - currentKey == int(intervals[currentInterval]): markedKeys += (key,) currentInterval += 1 markerText += (str(currentInterval+1),) if currentInterval == len(intervals): currentInterval = 0 currentKey = key # currentKey = keyNumberFromNote(self.options.keynote) currentInterval = len(intervals)-1 for key in range(keyNumberFromNote(self.options.keynote), firstKeyNum-1, -1): if currentKey - key == int(intervals[currentInterval]): markedKeys += (key,) markerText += (str(currentInterval+1),) currentInterval -= 1 if currentInterval == -1: currentInterval = len(intervals)-1 currentKey = key # make the markers self.createMarkers(parent, markedKeys, markerText)
def calc_circular_pitch(self): """ We use math based on circular pitch. Expressed in inkscape units which is 90dpi 'pixel' units. """ dimension = self.options.dimension # print >> self.tty, "unit_factor=%s, doc_units=%s, dialog_units=%s (%s), system=%s" % (unit_factor, doc_units, dialog_units, self.options.units, self.options.system) if self.options.system == 'CP': # circular pitch circular_pitch = dimension elif self.options.system == 'DP': # diametral pitch circular_pitch = pi / dimension elif self.options.system == 'MM': # module (metric) circular_pitch = dimension * pi / 25.4 else: inkex.debug("unknown system '%s', try CP, DP, MM" % self.options.system) # circular_pitch defines the size in inches. # We divide the internal inch factor (px = 90dpi), to remove the inch # unit. # The internal inkscape unit is always px, # it is independent of the doc_units! return circular_pitch / uutounit(self, 1.0, 'in')
def effect(self): """ Effect behaviour. Overrides base class' method and draws something. """ self.options.color = self.getColorString(self.options.color) conversion = self.getUnittouu("1" + self.options.units) if len(self.selected) != 1: inkex.debug('no object selected, or more than one selected') return selected = self.selected.values()[0] if not self.isBezier(selected): inkex.debug('selected element is not a Bezier curve') return self.findCandidatesForStyleChange(selected) self.style = 'fill:none;stroke:{1};stroke-width:{0}'.format(self.options.width*conversion, self.options.color) csp = cubicsuperpath.parsePath(selected.get('d')) self.selected.values()[0].attrib['style'] = self.style self.applyToAdjacent(self.startPoint(csp)) self.applyToAdjacent(self.endPoint(csp))