def query(self, cmd): if (self.port is not None) and (cmd is not None): response = '' try: self.write(cmd) response = self.readline() nRetryCount = 0 while (len(response) == 0) and (nRetryCount < 100): if self.doLog: self.log('QUERY', 'read %d' % nRetryCount) response = self.readline() nRetryCount += 1 if self.doLog: self.log('QUERY', 'response is '+response) # swallow 'ok' nRetryCount = 0 ok = self.readline() while (len(ok) == 0) and (nRetryCount < 100): ok = self.readline() nRetryCount += 1 except serial.SerialException: inkex.errormsg(gettext.gettext("Error reading serial data.")) return response else: return None
def get_filename_parts(self): ''' Attempts to get directory and image as passed in by the inkscape dialog. If the boolean ignore flag is set, then it will ignore these settings and try to use the settings from the export filename. ''' if self.options.ignore == False: if self.options.image == "" or self.options.image is None: inkex.errormsg("Please enter an image name") sys.exit(0) return (self.options.directory, self.options.image) else: ''' First get the export-filename from the document, if the document has been exported before (TODO: Will not work if it hasn't been exported yet), then uses this to return a tuple consisting of the directory to export to, and the filename without extension. ''' svg = self.document.getroot() att = '{http://www.inkscape.org/namespaces/inkscape}export-filename' try: export_file = svg.attrib[att] except KeyError: inkex.errormsg("To use the export hints option, you " + "need to have previously exported the document. " + "Otherwise no export hints exist!") sys.exit(-1) dirname, filename = os.path.split(export_file) filename = filename.rsplit(".", 1)[0] # Without extension return (dirname, filename)
def query( comPort, cmd ): if (comPort is not None) and (cmd is not None): response = '' try: debug('sending query:', cmd) comPort.write( cmd.encode('ascii') ) response = comPort.readline().decode('ascii') debug('response:', response) nRetryCount = 0 while ( len(response) == 0 ) and ( nRetryCount < 100 ): # get new response to replace null response if necessary response = comPort.readline() nRetryCount += 1 if cmd.strip().lower() not in ["v","i","a", "mr","pi","qm"]: #Most queries return an "OK" after the data requested. #We skip this for those few queries that do not return an extra line. unused_response = comPort.readline() #read in extra blank/OK line nRetryCount = 0 while ( len(unused_response) == 0 ) and ( nRetryCount < 100 ): # get new response to replace null response if necessary unused_response = comPort.readline() nRetryCount += 1 except: inkex.errormsg( gettext.gettext( "Error reading serial data." ) ) return response else: return None
def cspcofm(csp): area = csparea(csp) xc = 0.0 yc = 0.0 if abs(area) < 1.0e-8: inkex.errormsg(_("Area is zero, cannot calculate Center of Mass")) return 0, 0 for sp in csp: for i in range(len(sp)): # calculate polygon moment xc += ( sp[i - 1][1][1] * (sp[i - 2][1][0] - sp[i][1][0]) * (sp[i - 2][1][0] + sp[i - 1][1][0] + sp[i][1][0]) / 6 ) yc += ( sp[i - 1][1][0] * (sp[i][1][1] - sp[i - 2][1][1]) * (sp[i - 2][1][1] + sp[i - 1][1][1] + sp[i][1][1]) / 6 ) for i in range(1, len(sp)): # add contribution from cubic Bezier vec_x = numpy.matrix([sp[i - 1][1][0], sp[i - 1][2][0], sp[i][0][0], sp[i][1][0]]) vec_y = numpy.matrix([sp[i - 1][1][1], sp[i - 1][2][1], sp[i][0][1], sp[i][1][1]]) vec_t = numpy.matrix( [ (vec_x * mat_cofm_0 * vec_y.T)[0, 0], (vec_x * mat_cofm_1 * vec_y.T)[0, 0], (vec_x * mat_cofm_2 * vec_y.T)[0, 0], (vec_x * mat_cofm_3 * vec_y.T)[0, 0], ] ) xc += (vec_x * vec_t.T)[0, 0] / 280 yc += (vec_y * vec_t.T)[0, 0] / 280 return -xc / area, -yc / area
def collectAndZipImages(self, node, docname, z): xlink = node.get(inkex.addNS('href',u'xlink')) if (xlink[:4]!='data'): absref=node.get(inkex.addNS('absref',u'sodipodi')) url=urlparse.urlparse(xlink) href=urllib.url2pathname(url.path) if (href != None): absref=os.path.realpath(href) absref=unicode(absref, "utf-8") if (os.path.isfile(absref)): shutil.copy(absref, self.tmp_dir) z.write(absref, os.path.basename(absref).encode(self.encoding)) elif (os.path.isfile(os.path.join(self.tmp_dir, absref))): #TODO: please explain why this clause is necessary shutil.copy(os.path.join(self.tmp_dir, absref), self.tmp_dir) z.write(os.path.join(self.tmp_dir, absref), os.path.basename(absref).encode(self.encoding)) else: inkex.errormsg(_('Could not locate file: %s') % absref) node.set(inkex.addNS('href',u'xlink'),os.path.basename(absref)) node.set(inkex.addNS('absref',u'sodipodi'),os.path.basename(absref))
def autoNumber(errorCorrectLevel, dataList): for tn in range (1, 40): rsBlocks = QRRSBlock.getRSBlocks(tn, errorCorrectLevel) buffer = QRBitBuffer(); for i in range(len(dataList)): data = dataList[i] buffer.put(data.mode, 4) buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, tn) ) data.write(buffer) #// calc num max data. totalDataCount = 0; for i in range(len(rsBlocks)): totalDataCount += rsBlocks[i].dataCount if (buffer.getLengthInBits() <= totalDataCount * 8): return tn inkex.errormsg("Even the largest size won't take this much data (" + str(buffer.getLengthInBits()) + ">" + str(totalDataCount * 8) + ")") sys.exit()
def effect(self): # Check version. scriptNodes = self.document.xpath("//svg:script[@jessyink:version='1.5.5']", 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")) # Remove old mouse handler for node in self.document.xpath("//jessyink:mousehandler", namespaces=inkex.NSS): node.getparent().remove(node) if self.options.mouseSettings == "noclick": # Create new script node. scriptElm = inkex.etree.Element(inkex.addNS("script", "svg")) scriptElm.text = open(os.path.join(os.path.dirname(__file__), "jessyInk_core_mouseHandler_noclick.js")).read() groupElm = inkex.etree.Element(inkex.addNS("mousehandler", "jessyink")) groupElm.set("{" + inkex.NSS["jessyink"] + "}subtype", "jessyInk_core_mouseHandler_noclick") groupElm.append(scriptElm) self.document.getroot().append(groupElm) elif self.options.mouseSettings == "draggingZoom": # Create new script node. scriptElm = inkex.etree.Element(inkex.addNS("script", "svg")) scriptElm.text = open(os.path.join(os.path.dirname(__file__), "jessyInk_core_mouseHandler_zoomControl.js")).read() groupElm = inkex.etree.Element(inkex.addNS("mousehandler", "jessyink")) groupElm.set("{" + inkex.NSS["jessyink"] + "}subtype", "jessyInk_core_mouseHandler_zoomControl") groupElm.append(scriptElm) self.document.getroot().append(groupElm)
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")) if len(self.selected) == 0: inkex.errormsg(_(u"没有选择操作对象。请选择一个要设置演示特效的对象。\n")) for id, node in list(self.selected.items()): if (self.options.effectIn == "appear") or (self.options.effectIn == "fade") or (self.options.effectIn == "pop") or (self.options.effectIn == "tata"): node.set("{" + inkex.NSS["jessyink"] + "}effectIn","name:" + self.options.effectIn + ";order:" + self.options.effectInOrder + ";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"] else: if "{" + inkex.NSS["jessyink"] + "}effectIn" in node.attrib: del node.attrib["{" + inkex.NSS["jessyink"] + "}effectIn"] if (self.options.effectOut == "appear") or (self.options.effectOut == "fade") or (self.options.effectOut == "pop"): node.set("{" + inkex.NSS["jessyink"] + "}effectOut","name:" + self.options.effectOut + ";order:" + self.options.effectOutOrder + ";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"] else: if "{" + inkex.NSS["jessyink"] + "}effectOut" in node.attrib: del node.attrib["{" + inkex.NSS["jessyink"] + "}effectOut"]
def effect(self): scale = self.unittouu("1px") # convert to document units so = self.options if so.TEXT == "": # abort if converting blank text inkex.errormsg(_("Please enter an input text")) else: # INKSCAPE GROUP TO CONTAIN EVERYTHING so.TEXT = unicode(so.TEXT, so.input_encode) centre = tuple( computePointInNode(list(self.view_center), self.current_layer) ) # Put in in the centre of the current view grp_transform = "translate" + str(centre) + " scale(%f)" % scale grp_name = "QR Code: " + so.TEXT grp_attribs = {inkex.addNS("label", "inkscape"): grp_name, "transform": grp_transform} grp = inkex.etree.SubElement(self.current_layer, "g", grp_attribs) # the group to put everything in # GENERATE THE QRCODE qr = QRCode(int(so.TYPENUMBER), int(so.CORRECTIONLEVEL)) qr.addData(so.TEXT) qr.make() qr.makeSVG(grp, so.MODULESIZE)
def TOC_buildList(root): tocList = [] sectionIndex = 0 subsectionIndex = 0 for node in root: if node.tag == '{http://www.w3.org/2000/svg}g': if node.attrib['{http://www.inkscape.org/namespaces/inkscape}'+ 'groupmode'] == 'layer': label = node.attrib\ ['{http://www.inkscape.org/namespaces/inkscape}label'] titlePattern = re.compile("^\#(sub)?section ") if re.match(titlePattern, label): sectionPattern = re.compile("^\#section ") if re.match(sectionPattern, label): sectionIndex = sectionIndex+1 subsectionIndex = 0 else: if sectionIndex == 0: inkex.errormsg("Subsection outside any section") return [] subsectionIndex = subsectionIndex+1 index = (sectionIndex, subsectionIndex) title = label.split(' ', 1)[1] tocList.append({'id':node.attrib['id'], 'title':title, 'index':index}) return(tocList)
def pack(points): #最初の4点は輪郭とわかっている segments=[] #外枠部分 inkex.errormsg(u"外枠:"+str(points)) lastv=Vertex(points[0][0],points[0][1]) verts=[lastv] gVerts.append(lastv) for p in points[1:4]: v=Vertex(p[0],p[1]) gVerts.append(v) segment=Segment(lastv,v) segment.fixed=True segments.append(segment) v.pre=segment lastv.post=segment lastv=v #三角形を作る inkex.errormsg(u"gVerts:"+str(gVerts)) nodes=[Node(Triangle(gVerts[0],gVerts[1],gVerts[2]))] nodes.append(Node(Triangle(gVerts[2],gVerts[3],gVerts[0]))) #自分で描いたパス部分 for p in points[4:]: v=Vertex(p[0],p[1]) gVerts.append(v); segment=Segment(lastv,v) segments.append(segment) v.pre=segment lastv.post=segment lastv=v return segments,nodes
def effect(self): # Check version. scriptNodes = self.document.xpath("//svg:script[@jessyink:version='1.5.5']", 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 self.selected.items(): if ( (self.options.effectIn == "appear") or (self.options.effectIn == "fade") or (self.options.effectIn == "pop") ): node.set( "{" + inkex.NSS["jessyink"] + "}effectIn", "name:" + self.options.effectIn + ";order:" + self.options.effectInOrder + ";length:" + str(int(self.options.effectInDuration * 1000)), ) # Remove possible view argument. if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}view"): del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] else: if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}effectIn"): del node.attrib["{" + inkex.NSS["jessyink"] + "}effectIn"] if ( (self.options.effectOut == "appear") or (self.options.effectOut == "fade") or (self.options.effectOut == "pop") ): node.set( "{" + inkex.NSS["jessyink"] + "}effectOut", "name:" + self.options.effectOut + ";order:" + self.options.effectOutOrder + ";length:" + str(int(self.options.effectOutDuration * 1000)), ) # Remove possible view argument. if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}view"): del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] else: if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}effectOut"): del node.attrib["{" + inkex.NSS["jessyink"] + "}effectOut"]
def log(self, type, text): ts = datetime.datetime.now() try: with open("4xidraw-serial.log", "a") as myfile: myfile.write('--- %s\n%s\n%s\n' % (ts.isoformat(), type, escaped(text))) except: inkex.errormsg(gettext.gettext("Error logging serial data."))
def qrcode_generate(content, size, padding, version, em, ec): attribs = { 'content': content, 'size': size, 'padding': padding, 'em': em, 'ec': ec, 'format': 'svg', 'source': 'inkscape' } if version > 0: attribs['version'] = version headers = { #User-Agent: QRCode/3.0 (Windows 7; Inkscape; Python 2.7.2; U; en) "User-Agent": "QRCode/3.0 (%s %s; Inkscape; Python %s; U; en)" % (platform.system(), platform.release(), platform.python_version()), "Accept":"text/plain" } # Make a request to server to generate a vector QR Code con = httplib.HTTPConnection("www.esponce.com") query = urllib.urlencode(attribs) con.request("GET", "/api/v3/generate?%s" % query, None, headers) response = con.getresponse() if response.status == 200: result = response.read() else: inkex.errormsg(_('Error during the progress. Please check parameters.')) con.close() return result
def collect_images(self, docname, z): ''' Collects all images in the document and copy them to the temporary directory. ''' if locale.getpreferredencoding(): dir_locale = locale.getpreferredencoding() else: dir_locale = "UTF-8" dir = unicode(self.options.image_dir, dir_locale) for node in self.document.xpath('//svg:image', namespaces=inkex.NSS): xlink = node.get(inkex.addNS('href',u'xlink')) if (xlink[:4] != 'data'): absref = node.get(inkex.addNS('absref',u'sodipodi')) url = urlparse.urlparse(xlink) href = urllib.url2pathname(url.path) if (href != None): absref = os.path.realpath(href) absref = unicode(absref, "utf-8") image_path = os.path.join(dir, os.path.basename(absref)) if (os.path.isfile(absref)): shutil.copy(absref, self.tmp_dir) z.write(absref, image_path.encode(self.encoding)) elif (os.path.isfile(os.path.join(self.tmp_dir, absref))): # TODO: please explain why this clause is necessary shutil.copy(os.path.join(self.tmp_dir, absref), self.tmp_dir) z.write(os.path.join(self.tmp_dir, absref), image_path.encode(self.encoding)) else: inkex.errormsg(_('Could not locate file: %s') % absref) node.set(inkex.addNS('href',u'xlink'), image_path)
def convertToSegments(cls, path_node): path_start = None currentPoint = None # work on copy to be shure not breaking anything path = copy.deepcopy(path_node) # apply transformation info on path, otherwise dealing with transform would be a mess simpletransform.fuseTransform(path) for cmd, params in simplepath.parsePath(path.get('d')): print_('cmd, params', cmd, params) if cmd == 'M': if(path_start is None): path_start = params currentPoint = params elif cmd == 'L': yield Segment(currentPoint, params) currentPoint = params elif cmd in ['A', 'Q', 'C']: yield Segment(currentPoint, params[-2:], command=cmd, extra_parameters=params[:-2]) currentPoint = params[-2:] elif (cmd == 'Z'): # Z is a line between the last point and the start of the shape yield Segment(currentPoint, path_start) currentPoint = None path_start = None else: inkex.errormsg("Path Command %s not managed Yet" % cmd)
def validate_options(self): #inkex.errormsg( self.options.input_encode ) # Convert string names lists in real lists m = re.match('\s*(.*[^\s])\s*', self.options.month_names) self.options.month_names = re.split('\s+', m.group(1)) m = re.match('\s*(.*[^\s])\s*', self.options.day_names) self.options.day_names = re.split('\s+', m.group(1)) # Validate names lists if len(self.options.month_names) != 12: inkex.errormsg('The month name list "' + \ str(self.options.month_names) + \ '" is invalid. Using default.') self.options.month_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] if len(self.options.day_names) != 7: inkex.errormsg('The day name list "'+ str(self.options.day_names)+ '" is invalid. Using default.') self.options.day_names = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri','Sat'] # Convert year 0 to current year if self.options.year == 0: self.options.year = datetime.today().year # Year 1 starts it's week at monday, obligatorily if self.options.year == 1: self.options.start_day = 'mon' # Set the calendar start day if self.options.start_day=='sun': calendar.setfirstweekday(6) else: calendar.setfirstweekday(0) # Convert string numbers with unit to user space float numbers self.options.month_width = self.unittouu( self.options.month_width ) self.options.month_margin = self.unittouu( self.options.month_margin )
def effect(self): attr_val = [] attr_dict = {} cmd_scope = None if self.options.tab_main == '"tab_basic"': cmd_scope = "in_document" attr_dict['preserveAspectRatio'] = ("none" if self.options.fix_scaling else "unset") attr_dict['image-rendering'] = ("optimizeSpeed" if self.options.fix_rendering else "unset") elif self.options.tab_main == '"tab_aspectRatio"': attr_val = [self.options.aspect_ratio] if self.options.aspect_clip != "unset": attr_val.append(self.options.aspect_clip) attr_dict['preserveAspectRatio'] = ' '.join(attr_val) cmd_scope = self.options.aspect_ratio_scope elif self.options.tab_main == '"tab_image_rendering"': attr_dict['image-rendering'] = self.options.image_rendering cmd_scope = self.options.image_rendering_scope else: # help tab pass # dispatcher if cmd_scope is not None: try: change_cmd = getattr(self, 'change_{0}'.format(cmd_scope)) change_cmd(self.selected, attr_dict) except AttributeError: inkex.errormsg('Scope "{0}" not supported'.format(cmd_scope))
def effect(self): scale = self.unittouu('1px') # convert to document units so = self.options rows = so.ROWS cols = so.COLS if (so.SYMBOL != '' and (so.SYMBOL in symbols)): rows = symbols[so.SYMBOL][0] cols = symbols[so.SYMBOL][1] if so.TEXT == '': #abort if converting blank text inkex.errormsg(_('Please enter an input string')) else: #INKSCAPE GROUP TO CONTAIN EVERYTHING centre = tuple(computePointInNode(list(self.view_center), self.current_layer)) #Put in in the centre of the current view grp_transform = 'translate' + str( centre ) + ' scale(%f)' % scale grp_name = 'DataMatrix' grp_attribs = {inkex.addNS('label','inkscape'):grp_name, 'transform':grp_transform } grp = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)#the group to put everything in #GENERATE THE DATAMATRIX encoded = encode( so.TEXT, (rows, cols) ) #get the pattern of squares render_data_matrix( encoded, so.SIZE, cols*so.SIZE*1.5, grp ) # generate the SVG elements
def write_month_header(self, g, m): txt_atts = {'style': simplestyle.formatStyle(self.style_month), 'x': str((self.month_w - self.day_w) / 2), 'y': str(self.day_h / 5 )} try: inkex.etree.SubElement(g, 'text', txt_atts).text = unicode( self.options.month_names[m-1], self.options.input_encode) except: inkex.errormsg(_('You must select a correct system encoding.')) exit(1) gw = inkex.etree.SubElement(g, 'g') week_x = 0 if self.options.start_day=='sun': day_names = self.options.day_names[:] else: day_names = self.options.day_names[1:] day_names.append(self.options.day_names[0]) if self.options.show_weeknr: day_names.insert(0, self.options.weeknr_name) for wday in day_names: txt_atts = {'style': simplestyle.formatStyle(self.style_day_name), 'x': str( self.day_w * week_x ), 'y': str( self.day_h ) } try: inkex.etree.SubElement(gw, 'text', txt_atts).text = unicode( wday, self.options.input_encode) except: inkex.errormsg(_('You must select a correct system encoding.')) exit(1) week_x += 1
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")) # Find the script node, if present for node in self.document.xpath("//svg:script[@id='JessyInk']", namespaces=inkex.NSS): if node.get("{" + inkex.NSS["jessyink"] + "}version"): inkex.errormsg(_(u"安装的 JessyInk_c 版本是 {0}。").format(node.get("{" + inkex.NSS["jessyink"] + "}version"))) else: inkex.errormsg(_(u"JessyInk_c 已安装。")) slides = [] masterSlide = None for node in self.document.xpath("//svg:g[@inkscape:groupmode='layer']", namespaces=inkex.NSS): if node.get("{" + inkex.NSS["jessyink"] + "}masterSlide"): masterSlide = node else: slides.append(node) if masterSlide is not None: inkex.errormsg(_(u"\n幻灯片母板:")) self.describeNode(masterSlide, "\t", u"<幻灯片(层)序号>", str(len(slides)), u"<幻灯片(层)名字>") slideCounter = 1 for slide in slides: inkex.errormsg(_(u"\n幻灯片 {0!s}:").format(slideCounter)) self.describeNode(slide, "\t", str(slideCounter), str(len(slides)), slide.get("{" + inkex.NSS["inkscape"] + "}label")) slideCounter += 1
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): # Check version. scriptNodes = self.document.xpath("//svg:script[@jessyink:version='1.5.5']", 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")) # Find the script node, if present for node in self.document.xpath("//svg:script[@id='JessyInk']", namespaces=inkex.NSS): if node.get("{" + inkex.NSS["jessyink"] + "}version"): inkex.errormsg(_("JessyInk script version {0} installed.").format(node.get("{" + inkex.NSS["jessyink"] + "}version"))) else: inkex.errormsg(_("JessyInk script installed.")) slides = [] masterSlide = None for node in self.document.xpath("//svg:g[@inkscape:groupmode='layer']", namespaces=inkex.NSS): if node.get("{" + inkex.NSS["jessyink"] + "}masterSlide"): masterSlide = node else: slides.append(node) if masterSlide is not None: inkex.errormsg(_("\nMaster slide:")) self.describeNode(masterSlide, "\t", "<the number of the slide>", str(len(slides)), "<the title of the slide>") slideCounter = 1 for slide in slides: inkex.errormsg(_("\nSlide {0!s}:").format(slideCounter)) self.describeNode(slide, "\t", str(slideCounter), str(len(slides)), slide.get("{" + inkex.NSS["inkscape"] + "}label")) slideCounter += 1
def export_img(self, el, conf): if not self.has_magick: inkex.errormsg(_("You must install the ImageMagick to get JPG and GIF.")) conf["format"] = "png" img_name = os.path.join(self.options.dir, self.img_name(el, conf)) img_name_png = img_name if conf["format"] != "png": img_name_png = img_name + ".png" opts = "" if "bg-color" in conf: opts += ' -b "' + conf["bg-color"] + '" -y 1' if "dpi" in conf: opts += " -d " + conf["dpi"] if "dimension" in conf: dim = conf["dimension"].split("x") opts += " -w " + dim[0] + " -h " + dim[1] (status, output) = self.get_cmd_output( 'inkscape %s -i "%s" -e "%s" "%s"' % (opts, el.attrib["id"], img_name_png, self.tmp_svg) ) if conf["format"] != "png": opts = "" if conf["format"] == "jpg": opts += " -quality " + str(conf["quality"]) if conf["format"] == "gif": if conf["gif-type"] == "grayscale": opts += " -type Grayscale" else: opts += " -type Palette" if conf["palette-size"] < 256: opts += " -colors " + str(conf["palette-size"]) (status, output) = self.get_cmd_output('convert "%s" %s "%s"' % (img_name_png, opts, img_name)) if status != 0: inkex.errormsg("Upss... ImageMagick error: " + output) os.remove(img_name_png)
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()): 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:animate;length:-1") # Remove possible view argument. if "{" + inkex.NSS["jessyink"] + "}view" in node.attrib: del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] # Add the animation attribs = {'attributeName':self.options.attribute, 'begin':self.options.begin, 'dur':str(self.options.duration)+"s", 'repeatCount':self.options.repeat, 'from':self.options.origin, 'to':self.options.to, } if (self.options.values): attribs['values'] = self.options.values inkex.etree.SubElement(clone, inkex.addNS('animate','svg'), attribs)
def format_options(options): ''' Format options dictionary as therion options string. ''' ret = '' for key,value in options.items(): if len(ret) > 0: ret += ' ' for two_arg_key in two_arg_keys: if key.startswith(two_arg_key + '-'): ret += '-' + key.replace('-', ' ', 1) break else: ret += '-' + key if value == True: continue if not isinstance(value, basestring): ret += ' ' + str(value) elif len(value) == 0: inkex.errormsg('error: empty value: -' + key); elif value[0] == '[' or needquote.search(value) is None: ret += ' ' + value else: ret += ' "' + value.replace('"', '\\"') + '"' return ret
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): p = cubicsuperpath.parsePath(node.get('d')) coords = [] openPath = False for sub in p: if sub[0][0] == sub[-1][2]: p0 = sub[0][1] i = 0 while i < len(sub)-1: p1 = sub[i][2] p2 = sub[i+1][0] p3 = sub[i+1][1] bez = (p0, p1, p2, p3) coords.extend(bezlinearize(bez, self.options.num_points)) p0 = p3 i+=1 else: openPath = True inkex.errormsg("Path doesn't appear to be closed") if not openPath: c = centroid(coords) ## debug linearization # many_lines(coords, self.current_layer) # draw_SVG_dot(c, self.options.centroid_radius, "centroid-dot", self.current_layer)
def effect(self): if not self.options.path: inkex.errormsg('Empty file path!') exit() for resolution in self.should_export: flag = getattr(self.options, resolution) if flag.lower() == "true": self.should_export[resolution] = True else: self.should_export[resolution] = False # Checks if a path has the correct format if "{}" not in self.options.path: inkex.errormsg('The path entered does not have a {} inside it. ' 'Enter a path that has a {} in the place of the ' 'resolution name. In example, if you put the path ' '"folder/example/{}/my_image.png", this extension ' 'will export images for several paths: ' '"folder/example/mdpi/my_image.png", ' '"folder/example/xxhdpi/my_image.png"') exit() # Solves the paths that use "~" as the home directory filepath = os.path.expanduser(self.options.path) filepath = filepath.replace('{}', '{0}') area = self.get_selected_area() resolutions = filter(lambda res: self.should_export[res], self.resolution_multipliers.keys()) self.export_to_resolutions(filepath, area, resolutions)
def effect(self): """ Like cut but requires no selection and does no validation for text nodes. """ nodes = self.selected if not len(nodes): inkex.errormsg("There were no paths were selected.") return document = self.document if contains_text(self.selected.values()): document = convert_objects_to_paths(self.args[-1], self.document) #: If running from source if DEBUG: python = '~/inkcut/venv/bin/python' inkcut = '~/inkcut/main.py' cmd = [python, inkcut] else: cmd = ['inkcut'] cmd += ['open', '-', '--nodes']+[str(k) for k in nodes.keys()] p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=DEVNULL, stderr=subprocess.STDOUT, close_fds=sys.platform != "win32") p.stdin.write(inkex.etree.tostring(document)) p.stdin.close()
def effect(self): if len(self.options.ids)<2: inkex.errormsg(_("This extension requires two selected paths.")) return self.prepareSelectionList() self.tolerance=math.pow(10,self.options.space); 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) origin = p0[0][0][1]; newp=[] for skelnode in self.skeletons.itervalues(): self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: self.skelcomp=linearize(comp,self.tolerance) for comp in self.skelcomp: p=copy.deepcopy(p0) for sub in p: xoffset=comp[0]-origin[0]+self.options.xoffset yoffset=comp[1]-origin[1]+self.options.yoffset offset(sub,xoffset,yoffset) newp+=p node.set('d', cubicsuperpath.formatPath(newp))
def showDebugInfo(self, debugObject): # show debug information inkex.errormsg( "---------------------------------\nDebug information\n---------------------------------\n\nSettings:\n" ) inkex.errormsg(' Serial Port: ' + str(self.options.serialPort)) inkex.errormsg(' Serial baud rate: ' + str(self.options.serialBaudRate)) inkex.errormsg(' Flow control: ' + str(self.options.flowControl)) inkex.errormsg(' Command language: ' + str(self.options.commandLanguage)) inkex.errormsg(' Resolution X (dpi): ' + str(self.options.resolutionX)) inkex.errormsg(' Resolution Y (dpi): ' + str(self.options.resolutionY)) inkex.errormsg(' Pen number: ' + str(self.options.pen)) inkex.errormsg(' Pen force (g): ' + str(self.options.force)) inkex.errormsg(' Pen speed (cm/s): ' + str(self.options.speed)) inkex.errormsg(' Rotation (Clockwise): ' + str(self.options.orientation)) inkex.errormsg(' Mirror X axis: ' + str(self.options.mirrorX)) inkex.errormsg(' Mirror Y axis: ' + str(self.options.mirrorY)) inkex.errormsg(' Center zero point: ' + str(self.options.center)) inkex.errormsg(' Overcut (mm): ' + str(self.options.overcut)) inkex.errormsg(' Tool offset (mm): ' + str(self.options.toolOffset)) inkex.errormsg(' Use precut: ' + str(self.options.precut)) inkex.errormsg(' Curve flatness: ' + str(self.options.flat)) inkex.errormsg(' Auto align: ' + str(self.options.autoAlign)) inkex.errormsg(' Show debug information: ' + str(self.options.debug)) inkex.errormsg("\nDocument properties:\n") version = self.document.getroot().xpath('//@inkscape:version', namespaces=inkex.NSS) if version: inkex.errormsg(' Inkscape version: ' + version[0]) fileName = self.document.getroot().xpath('//@sodipodi:docname', namespaces=inkex.NSS) if fileName: inkex.errormsg(' Filename: ' + fileName[0]) inkex.errormsg(' Document unit: ' + self.getDocumentUnit()) inkex.errormsg(' Width: ' + str(debugObject.debugValues['docWidth']) + ' ' + self.getDocumentUnit()) inkex.errormsg(' Height: ' + str(debugObject.debugValues['docHeight']) + ' ' + self.getDocumentUnit()) if debugObject.debugValues['viewBoxWidth'] == "-": inkex.errormsg(' Viewbox Width: -') inkex.errormsg(' Viewbox Height: -') else: inkex.errormsg(' Viewbox Width: ' + str( self.unittouu( self.addDocumentUnit( debugObject.debugValues['viewBoxWidth']))) + ' ' + self.getDocumentUnit()) inkex.errormsg(' Viewbox Height: ' + str( self.unittouu( self.addDocumentUnit( debugObject.debugValues['viewBoxHeight']))) + ' ' + self.getDocumentUnit()) inkex.errormsg("\n" + self.options.commandLanguage + " properties:\n") inkex.errormsg(' Drawing width: ' + str( self.unittouu( self.addDocumentUnit( str(debugObject.debugValues['drawingWidthUU'])))) + ' ' + self.getDocumentUnit()) inkex.errormsg(' Drawing height: ' + str( self.unittouu( self.addDocumentUnit( str(debugObject.debugValues['drawingHeightUU'])))) + ' ' + self.getDocumentUnit()) inkex.errormsg(' Drawing width: ' + str(debugObject.debugValues['drawingWidth']) + ' plotter steps') inkex.errormsg(' Drawing height: ' + str(debugObject.debugValues['drawingHeight']) + ' plotter steps') inkex.errormsg(' Offset X: ' + str(debugObject.offsetX) + ' plotter steps') inkex.errormsg(' Offset Y: ' + str(debugObject.offsetX) + ' plotter steps') inkex.errormsg(' Overcut: ' + str(debugObject.overcut) + ' plotter steps') inkex.errormsg(' Tool offset: ' + str(debugObject.toolOffset) + ' plotter steps') inkex.errormsg(' Flatness: ' + str(debugObject.flat) + ' plotter steps') inkex.errormsg(' Tool offset flatness: ' + str(debugObject.toolOffsetFlat) + ' plotter steps') inkex.errormsg("\n" + self.options.commandLanguage + " data:\n") inkex.errormsg(self.hpgl)
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')) 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 load(self, node, mat): inkex.errormsg( 'Warning: unable to draw text. please convert it to a path first.') SvgIgnoredEntity.load(self, node, mat)
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 effect(self): # Get script's options values. # Factor to multiply in order to get user units (pixels) factor = self.unittouu('1' + self.options.unit) # document or selection target = self.options.target # boolean same_margins = self.options.same_margins # convert string to integer, in user units (pixels) top_margin = float(self.options.top_margin) * factor right_margin = float(self.options.right_margin) * factor bottom_margin = float(self.options.bottom_margin) * factor left_margin = float(self.options.left_margin) * factor # getting parent tag of the guides namedview = self.document.xpath( '/svg:svg/sodipodi:namedview', namespaces=inkex.NSS)[0] # getting the main SVG document element (canvas) svg = self.document.getroot() # if same margins, set them all to same value if same_margins: right_margin = top_margin bottom_margin = top_margin left_margin = top_margin # getting the width and height attributes of the canvas canvas_width = self.unittouu(svg.get('width')) canvas_height = self.unittouu(svg.get('height')) # If selection, draw around selection. Otherwise use document. if (target == "selection"): # If there is no selection, quit with message if not self.options.ids: inkex.errormsg(_("Please select an object first")) exit() # get bounding box obj_x1, obj_x2, obj_y1, obj_y2 = simpletransform.computeBBox([self.getElementById(id) for id in self.options.ids]) # start position of guides top_pos = canvas_height - obj_y1 - top_margin right_pos = obj_x2 - right_margin bottom_pos = canvas_height - obj_y2 + bottom_margin left_pos = obj_x1 + left_margin # Draw the four margin guides # TODO: only draw if not on border guidetools.drawGuide(top_pos, "horizontal", namedview) guidetools.drawGuide(right_pos, "vertical", namedview) guidetools.drawGuide(bottom_pos, "horizontal", namedview) guidetools.drawGuide(left_pos, "vertical", namedview) else: # draw margin guides (if not zero) if same_margins: right_margin = top_margin bottom_margin = top_margin left_margin = top_margin # start position of guides top_pos = canvas_height - top_margin right_pos = canvas_width - right_margin bottom_pos = bottom_margin left_pos = left_margin # Draw the four margin guides (if margin exists) if top_pos != canvas_height: guidetools.drawGuide(top_pos, "horizontal", namedview) if right_pos != canvas_width: guidetools.drawGuide(right_pos, "vertical", namedview) if bottom_pos != 0: guidetools.drawGuide(bottom_pos, "horizontal", namedview) if left_pos != 0: guidetools.drawGuide(left_pos, "vertical", namedview)
'fill': 'none' }) w = 0.5 # default lineweight for POINT if vals[groups['370']]: # Common Lineweight if vals[groups['370']][0] > 0: w = 96.0 / 25.4 * vals[groups['370']][0] / 100.0 if w < 0.5: w = 0.5 style = simplestyle.formatStyle({ 'stroke': '%s' % color, 'fill': 'none', 'stroke-width': '%.1f' % w }) if vals[groups['6']]: # Common Linetype if linetypes.has_key(vals[groups['6']][0]): style += ';' + linetypes[vals[groups['6']][0]] if entities[entity]: entities[entity]() entity = line[1] vals = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] seqs = [] if polylines: inkex.errormsg( _('%d ENTITIES of type POLYLINE encountered and ignored. Please try to convert to Release 13 format using QCad.' ) % polylines) doc.write(inkex.sys.stdout) # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
def effect(self): # version check if enabled in options if (self.options.scour_version_warn_old): scour_version = scour.__version__ scour_version_min = self.options.scour_version if (StrictVersion(scour_version) < StrictVersion(scour_version_min)): inkex.errormsg("The extension 'Optimized SVG Output' is designed for Scour " + scour_version_min + " and later " "but you're using the older version Scour " + scour_version + ".") inkex.errormsg("This usually works just fine but not all options available in the UI might be supported " "by the version of Scour installed on your system " "(see https://github.com/scour-project/scour/blob/master/HISTORY.md for release notes of Scour).") inkex.errormsg("Note: You can permanently disable this message on the 'About' tab of the extension window.") del self.options.scour_version del self.options.scour_version_warn_old # do the scouring try: input = file(self.args[0], "r") self.options.infilename = self.args[0] sys.stdout.write(scourString(input.read(), self.options).encode("UTF-8")) input.close() sys.stdout.close() except Exception as e: inkex.errormsg("Error during optimization.") inkex.errormsg("\nDetails:\n" + str(e)) inkex.errormsg("\nOS version: " + platform.platform()) inkex.errormsg("Python version: " + sys.version) inkex.errormsg("Scour version: " + scour.__version__) sys.exit()
def effect(self): # Viewbox handling self.handleViewBox() # First traverse the document (or selected items), reducing # everything to line segments. If working on a selection, # then determine the selection's bounding box in the process. # (Actually, we just need to know it's extrema on the x-axis.) if self.options.ids: # Traverse the selected objects for id in self.options.ids: transform = self.recursivelyGetEnclosingTransform( self.selected[id]) self.recursivelyTraverseSvg([self.selected[id]], transform) else: # Traverse the entire document building new, transformed paths self.recursivelyTraverseSvg( self.document.getroot(), self.docTransform) # Determine the center of the drawing's bounding box self.cx = self.xmin + (self.xmax - self.xmin) / 2.0 self.cy = self.ymin + (self.ymax - self.ymin) / 2.0 # Determine which polygons lie entirely within other polygons try: full_fname = os.path.expanduser(self.options.fname) if '/' != os.sep: full_fname = full_fname.replace('/', os.sep) self.f = open(full_fname, 'w') self.f.write(''' // Module names are of the form poly_<inkscape-path-id>(). As a result, // you can associate a polygon in this OpenSCAD program with the corresponding // SVG element in the Inkscape document by looking for the XML element with // the attribute id=\"inkscape-path-id\". // fudge value is used to ensure that subtracted solids are a tad taller // in the z dimension than the polygon being subtracted from. This helps // keep the resulting .stl file manifold. fudge = 0.1; ''') for key in self.paths: self.f.write('\n') self.convertPath(key) # Come up with a name for the module based on the file name. name = os.path.splitext(os.path.basename(self.options.fname))[0] # Remove all punctuation except underscore. name = re.sub( '[' + string.punctuation.replace('_', '') + ']', '', name) self.f.write('\nmodule %s(h)\n{\n' % name) # Now output the list of modules to call self.f.write('\n') for call in self.call_list: self.f.write(call) # The module that calls all the other ones. self.f.write('}\n\n%s(%s);\n' % (name, self.options.height)) self.f.close() except: inkex.errormsg('Unable to write file ' + self.options.fname) if self.options.scad2stl == 'true' or self.options.stlpost == 'true': stl_fname = re.sub(r"\.SCAD", "", full_fname, flags=re.I) + '.stl' cmd = self.options.scad2stlcmd.format( **{'SCAD': full_fname, 'STL': stl_fname}) try: os.unlink(stl_fname) except: pass import subprocess try: proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError as e: raise OSError("{0} failed: errno={1} {2}".format( cmd, e.errno, e.strerror)) stdout, stderr = proc.communicate() len = -1 try: len = os.path.getsize(stl_fname) except: pass if len < 1000: print >> sys.stderr, "CMD: {0}".format(cmd) # pep8 enforced 80 columns limit is here: --------------------v print >> sys.stderr, "WARNING: {0} is very small: {1} bytes.".\ format(stl_fname, len) print >> sys.stderr, "= " * 24 print >> sys.stderr, "STDOUT:\n", stdout, "= " * 24 print >> sys.stderr, "STDERR:\n", stderr, "= " * 24 if len <= 0: # something is wrong. better stop here self.options.stlpost = 'false' if self.options.stlpost == 'true': cmd = self.options.stlpostcmd.format(**{'STL': stl_fname}) try: tty = open("/dev/tty", "w") except: tty = subprocess.PIPE try: proc = subprocess.Popen(cmd, shell=True, stdin=tty, stdout=tty, stderr=tty) except OSError as e: raise OSError("%s failed: errno=%d %s" % (cmd, e.errno, e.strerror)) stdout, stderr = proc.communicate() if stdout or stderr: print >> sys.stderr, "CMD: ", cmd, "\n", "= " * 24 if stdout: print >> sys.stderr, "STDOUT:\n", stdout, "= " * 24 if stderr: print >> sys.stderr, "STDERR:\n", stderr, "= " * 24
def recursivelyTraverseSvg(self, aNodeList, matCurrent=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], parent_visibility='visible'): ''' [ 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, 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, v) elif node.tag == inkex.addNS('path', 'svg'): path_data = node.get('d') if path_data: self.getPathVertices(path_data, node, matNew) 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.getPathVertices(simplepath.formatPath(a), node, matNew) 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.getPathVertices(simplepath.formatPath(a), node, matNew) 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.getPathVertices(d, node, matNew) 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.getPathVertices(d, node, matNew) 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.getPathVertices(d, node, matNew) 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('desc', 'svg') or node.tag == 'desc': 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 node.tag == inkex.addNS('title', 'svg') or \ node.tag == 'title': pass elif node.tag == inkex.addNS('image', 'svg') or \ node.tag == 'image': if 'image' not in self.warnings: inkex.errormsg( gettext.gettext( 'Warning: unable to draw bitmap images; ' 'please convert them to line art first. ' 'Consider using the "Trace bitmap..." ' 'tool of the "Path" menu. Mac users please ' 'note that some X11 settings may ' 'cause cut-and-paste operations to paste in ' 'bitmap copies.')) self.warnings['image'] = 1 pass elif node.tag == inkex.addNS('pattern', 'svg') or \ node.tag == 'pattern': pass elif node.tag == inkex.addNS('radialGradient', 'svg') or \ node.tag == 'radialGradient': # Similar to pattern pass elif node.tag == inkex.addNS('linearGradient', 'svg') or \ node.tag == 'linearGradient': # Similar in pattern pass elif node.tag == inkex.addNS('style', 'svg') or \ node.tag == 'style': # This is a reference to an external style sheet and not the # value of a style attribute to be inherited by child elements pass elif node.tag == inkex.addNS('cursor', 'svg') or \ node.tag == 'cursor': pass elif node.tag == inkex.addNS('color-profile', 'svg') or \ node.tag == 'color-profile': # Gamma curves, color temp, etc. are not relevant to single # color output pass elif not isinstance(node.tag, basestring): # This is likely an XML processing instruction such as an XML # comment. lxml uses a function reference for such node tags # and as such the node tag is likely not a printable string. # Further, converting it to a printable string likely won't # be very useful. pass else: inkex.errormsg( 'Warning: unable to draw object <%s>, ' 'please convert it to a path first.' % node.tag) pass
else: p = Popen('uniconv', shell=True, stdout=PIPE, stderr=PIPE).wait() if p == 0: cmd = 'uniconv' except ImportError: from popen2 import Popen3 p = Popen3('uniconv', True).wait() if p != 32512: cmd = 'uniconv' p = Popen3('uniconvertor', True).wait() if p != 32512: cmd = 'uniconvertor' if cmd == None: # there's no succeffully-returning uniconv command; try to get the module directly (on Windows) try: # cannot simply import uniconvertor, it aborts if you import it without parameters import imp imp.find_module("uniconvertor") except ImportError: inkex.localize() inkex.errormsg(_('You need to install the UniConvertor software.\n'+\ 'For GNU/Linux: install the package python-uniconvertor.\n'+\ 'For Windows: download it from\n'+\ 'https://sk1project.net/modules.php?name=Products&product=uniconvertor&op=download\n'+\ 'and install into your Inkscape\'s Python location\n')) sys.exit(1) cmd = 'python -c "import uniconvertor; uniconvertor.uniconv_run()"' run((cmd + ' "%s" "%%s"') % sys.argv[1].replace("%", "%%"), "UniConvertor") # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
def effect(self): if not self.options.ids: inkex.errormsg(_("Please select an object")) exit() scale = self.unittouu('1px') # convert to document units self.options.size *= scale self.options.border *= scale q = { 'x': 0, 'y': 0, 'width': 0, 'height': 0 } # query the bounding box of ids[0] for query in q.keys(): p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query, self.options.ids[0], self.args[-1]), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = scale * float(p.stdout.read()) mat = simpletransform.composeParents( self.selected[self.options.ids[0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) defs = self.xpathSingle('/svg:svg//svg:defs') pattern = inkex.etree.SubElement(defs, inkex.addNS('pattern', 'svg')) pattern.set('id', 'Voronoi' + str(random.randint(1, 9999))) pattern.set('width', str(q['width'])) pattern.set('height', str(q['height'])) pattern.set( 'patternTransform', 'translate(%s,%s)' % (q['x'] - mat[0][2], q['y'] - mat[1][2])) pattern.set('patternUnits', 'userSpaceOnUse') # generate random pattern of points c = voronoi.Context() pts = [] b = float(self.options.border) # width of border for i in range( int(q['width'] * q['height'] / self.options.size / self.options.size)): x = random.random() * q['width'] y = random.random() * q['height'] if b > 0: # duplicate border area pts.append(voronoi.Site(x, y)) if x < b: pts.append(voronoi.Site(x + q['width'], y)) if y < b: pts.append( voronoi.Site(x + q['width'], y + q['height'])) if y > q['height'] - b: pts.append( voronoi.Site(x + q['width'], y - q['height'])) if x > q['width'] - b: pts.append(voronoi.Site(x - q['width'], y)) if y < b: pts.append( voronoi.Site(x - q['width'], y + q['height'])) if y > q['height'] - b: pts.append( voronoi.Site(x - q['width'], y - q['height'])) if y < b: pts.append(voronoi.Site(x, y + q['height'])) if y > q['height'] - b: pts.append(voronoi.Site(x, y - q['height'])) elif x > -b and y > -b and x < q['width'] + b and y < q[ 'height'] + b: pts.append(voronoi.Site(x, y)) # leave border area blank # dot = inkex.etree.SubElement(pattern, inkex.addNS('rect','svg')) # dot.set('x', str(x-1)) # dot.set('y', str(y-1)) # dot.set('width', '2') # dot.set('height', '2') if len(pts) < 3: inkex.errormsg( "Please choose a larger object, or smaller cell size") exit() # plot Voronoi diagram sl = voronoi.SiteList(pts) voronoi.voronoi(sl, c) path = "" for edge in c.edges: if edge[1] >= 0 and edge[2] >= 0: # two vertices [x1, y1, x2, y2 ] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], c.vertices[edge[2]][0], c.vertices[edge[2]][1], q['width'], q['height']) elif edge[1] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0] if c.vertices[edge[1]][1] > q['height'] / 2: ytemp = q['height'] else: ytemp = 0 else: xtemp = q['width'] ytemp = (c.lines[edge[0]][2] - q['width'] * c.lines[edge[0]][0]) / c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], xtemp, ytemp, q['width'], q['height']) elif edge[2] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0] if c.vertices[edge[2]][1] > q['height'] / 2: ytemp = q['height'] else: ytemp = 0 else: xtemp = 0 ytemp = c.lines[edge[0]][2] / c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(xtemp, ytemp, c.vertices[edge[2]][0], c.vertices[edge[2]][1], q['width'], q['height']) if x1 or x2 or y1 or y2: path += 'M %.3f,%.3f %.3f,%.3f ' % (x1, y1, x2, y2) patternstyle = {'stroke': '#000000', 'stroke-width': str(scale)} attribs = {'d': path, 'style': simplestyle.formatStyle(patternstyle)} inkex.etree.SubElement(pattern, inkex.addNS('path', 'svg'), attribs) # link selected object to pattern obj = self.selected[self.options.ids[0]] style = {} if obj.attrib.has_key('style'): style = simplestyle.parseStyle(obj.attrib['style']) style['fill'] = 'url(#%s)' % pattern.get('id') obj.attrib['style'] = simplestyle.formatStyle(style) if obj.tag == inkex.addNS('g', 'svg'): for node in obj: style = {} if node.attrib.has_key('style'): style = simplestyle.parseStyle(node.attrib['style']) style['fill'] = 'url(#%s)' % pattern.get('id') node.attrib['style'] = simplestyle.formatStyle(style)
class Plot(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) self.OptionParser.add_option('--tab', action='store', type='string', dest='tab') self.OptionParser.add_option('--serialPort', action='store', type='string', dest='serialPort', default='COM1', help='Serial port') self.OptionParser.add_option('--serialBaudRate', action='store', type='string', dest='serialBaudRate', default='9600', help='Serial Baud rate') self.OptionParser.add_option('--flowControl', action='store', type='string', dest='flowControl', default='0', help='Flow control') self.OptionParser.add_option('--commandLanguage', action='store', type='string', dest='commandLanguage', default='hpgl', help='Command Language') self.OptionParser.add_option('--resolutionX', action='store', type='float', dest='resolutionX', default=1016.0, help='Resolution X (dpi)') self.OptionParser.add_option('--resolutionY', action='store', type='float', dest='resolutionY', default=1016.0, help='Resolution Y (dpi)') self.OptionParser.add_option('--pen', action='store', type='int', dest='pen', default=1, help='Pen number') self.OptionParser.add_option('--force', action='store', type='int', dest='force', default=24, help='Pen force (g)') self.OptionParser.add_option('--speed', action='store', type='int', dest='speed', default=20, help='Pen speed (cm/s)') self.OptionParser.add_option('--orientation', action='store', type='string', dest='orientation', default='90', help='Rotation (Clockwise)') self.OptionParser.add_option('--mirrorX', action='store', type='inkbool', dest='mirrorX', default='FALSE', help='Mirror X axis') self.OptionParser.add_option('--mirrorY', action='store', type='inkbool', dest='mirrorY', default='FALSE', help='Mirror Y axis') self.OptionParser.add_option('--center', action='store', type='inkbool', dest='center', default='FALSE', help='Center zero point') self.OptionParser.add_option('--overcut', action='store', type='float', dest='overcut', default=1.0, help='Overcut (mm)') self.OptionParser.add_option('--toolOffset', action='store', type='float', dest='toolOffset', default=0.25, help='Tool offset (mm)') self.OptionParser.add_option('--precut', action='store', type='inkbool', dest='precut', default='TRUE', help='Use precut') self.OptionParser.add_option('--flat', action='store', type='float', dest='flat', default=1.2, help='Curve flatness') self.OptionParser.add_option('--autoAlign', action='store', type='inkbool', dest='autoAlign', default='TRUE', help='Auto align') self.OptionParser.add_option('--debug', action='store', type='inkbool', dest='debug', default='FALSE', help='Show debug information') def effect(self): # get hpgl data myHpglEncoder = hpgl_encoder.hpglEncoder(self) try: self.hpgl, debugObject = myHpglEncoder.getHpgl() except Exception as inst: if inst.args[0] == 'NO_PATHS': # issue error if no paths found inkex.errormsg( _("No paths where found. Please convert all objects you want to plot into paths." )) return 1 else: type, value, traceback = sys.exc_info() raise ValueError, ('', type, value), traceback # TODO: Get preview to work. This requires some work on the C++ side to be able to determine if it is # a preview or a final run. (Remember to set <effect needs-live-preview='false'> to true) ''' if MAGIC: # reparse data for preview self.options.showMovements = True self.options.docWidth = self.uutounit(self.unittouu(self.document.getroot().get('width')), "px") self.options.docHeight = self.uutounit(self.unittouu(self.document.getroot().get('height')), "px") myHpglDecoder = hpgl_decoder.hpglDecoder(self.hpgl, self.options) doc, warnings = myHpglDecoder.getSvg() # deliver document to inkscape self.document = doc else: ''' # convert to other formats if self.options.commandLanguage == 'HPGL': self.convertToHpgl() if self.options.commandLanguage == 'DMPL': self.convertToDmpl() if self.options.commandLanguage == 'ZING': self.convertToZing() # output if self.options.debug: self.showDebugInfo(debugObject) else: self.sendHpglToSerial() def convertToHpgl(self): # convert raw HPGL to HPGL hpglInit = 'IN;SP%d' % self.options.pen if self.options.force > 0: hpglInit += ';FS%d' % self.options.force if self.options.speed > 0: hpglInit += ';VS%d' % self.options.speed self.hpgl = hpglInit + self.hpgl + ';PU0,0;SP0;IN;' def convertToDmpl(self): # convert HPGL to DMPL # ;: = Initialise plotter # H = Home position # A = Absolute pen positioning # Ln = Line type # Pn = Pen select # Vn = velocity # ECn = Coordinate addressing, 1: 0.001 inch, 5: 0.005 inch, M: 0.1 mm # D = Pen down # U = Pen up # Z = Reset plotter # n,n, = Coordinate pair self.hpgl = self.hpgl.replace(';', ',') self.hpgl = self.hpgl.replace('PU', 'U') self.hpgl = self.hpgl.replace('PD', 'D') dmplInit = ';:HAL0P%d' % self.options.pen if self.options.speed > 0: dmplInit += 'V%d' % self.options.speed dmplInit += 'EC1' self.hpgl = dmplInit + self.hpgl[1:] + ',U0,0,P0Z' def convertToZing(self): # convert HPGL to Zing hpglInit = 'ZG;SP%d' % self.options.pen if self.options.force > 0: hpglInit += ';FS%d' % self.options.force if self.options.speed > 0: hpglInit += ';VS%d' % self.options.speed self.hpgl = hpglInit + self.hpgl + ';PU0,0;SP0;@' def sendHpglToSerial(self): # gracefully exit script when pySerial is missing try: import serial except ImportError, e: inkex.errormsg( _("pySerial is not installed." + "\n\n1. Download pySerial here (not the \".exe\"!): http://pypi.python.org/pypi/pyserial" + "\n2. Extract the \"serial\" subfolder from the zip to the following folder: C:\\[Program files]\\inkscape\\python\\Lib\\" + "\n3. Restart Inkscape.")) return # send data to plotter mySerial = serial.Serial() mySerial.port = self.options.serialPort mySerial.baudrate = self.options.serialBaudRate mySerial.timeout = 0.1 if self.options.flowControl == 'xonxoff': mySerial.xonxoff = True if self.options.flowControl == 'rtscts' or self.options.flowControl == 'dsrdtrrtscts': mySerial.rtscts = True if self.options.flowControl == 'dsrdtrrtscts': mySerial.dsrdtr = True try: mySerial.open() except Exception as inst: if 'ould not open port' in inst.args[0]: inkex.errormsg( _("Could not open port. Please check that your plotter is running, connected and the settings are correct." )) return else: type, value, traceback = sys.exc_info() raise ValueError, ('', type, value), traceback mySerial.write(self.hpgl) mySerial.read(2) mySerial.close()
from distutils.version import StrictVersion import inkex try: import scour try: from scour.scour import scourString except ImportError: # compatibility for very old Scour (<= 0.26) - deprecated! try: from scour import scourString scour.__version__ = scour.VER except: raise except Exception as e: inkex.errormsg("Failed to import Python module 'scour'.\nPlease make sure it is installed (e.g. using 'pip install scour' or 'sudo apt-get install python-scour') and try again.") inkex.errormsg("\nDetails:\n" + str(e)) sys.exit() try: import six except Exception as e: inkex.errormsg("Failed to import Python module 'six'.\nPlease make sure it is installed (e.g. using 'pip install six' or 'sudo apt-get install python-six') and try again.") inkex.errormsg("\nDetails:\n" + str(e)) sys.exit() class ScourInkscape (inkex.Effect): def __init__(self): inkex.Effect.__init__(self)
def get_parameters(nrow, ncol): #SQUARE SYMBOLS if ( nrow == 10 and ncol == 10 ): return 8, 8, 1, 1, 3, 5, 1 elif ( nrow == 12 and ncol == 12 ): return 10, 10, 1, 1, 5, 7, 1 elif ( nrow == 14 and ncol == 14 ): return 12, 12, 1, 1, 8, 10, 1 elif ( nrow == 16 and ncol == 16 ): return 14, 14, 1, 1, 12, 12, 1 elif ( nrow == 18 and ncol == 18 ): return 16, 16, 1, 1, 18, 14, 1 elif ( nrow == 20 and ncol == 20 ): return 18, 18, 1, 1, 22, 18, 1 elif ( nrow == 22 and ncol == 22 ): return 20, 20, 1, 1, 30, 20, 1 elif ( nrow == 24 and ncol == 24 ): return 22, 22, 1, 1, 36, 24, 1 elif ( nrow == 26 and ncol == 26 ): return 24, 24, 1, 1, 44, 28, 1 elif ( nrow == 32 and ncol == 32 ): return 14, 14, 2, 2, 62, 36, 1 elif ( nrow == 36 and ncol == 36 ): return 16, 16, 2, 2, 86, 42, 1 elif ( nrow == 40 and ncol == 40): return 18, 18, 2, 2, 114, 48, 1 elif ( nrow == 44 and ncol == 44): return 20, 20, 2, 2, 144, 56, 1 elif ( nrow == 48 and ncol == 48 ): return 22, 22, 2, 2, 174, 68, 1 elif ( nrow == 52 and ncol == 52 ): return 24, 24, 2, 2, 102, 42, 2 elif ( nrow == 64 and ncol == 64 ): return 16, 16, 4, 4, 140, 56, 2 elif ( nrow == 72 and ncol == 72 ): return 16, 16, 4, 4, 92, 36, 4 elif ( nrow == 80 and ncol == 80 ): return 18, 18, 4, 4, 114, 48, 4 elif ( nrow == 88 and ncol == 88 ): return 20, 20, 4, 4, 144, 56, 4 elif ( nrow == 96 and ncol == 96 ): return 22, 22, 4, 4, 174, 68, 4 elif ( nrow == 104 and ncol == 104 ): return 24, 24, 4, 4, 136, 56, 6 elif ( nrow == 120 and ncol == 120): return 18, 18, 6, 6, 175, 68, 6 elif ( nrow == 132 and ncol == 132): return 20, 20, 6, 6, 163, 62, 8 elif (nrow == 144 and ncol == 144): return 22, 22, 6, 6, 0, 0, 0 #there are two separate sections of the data matrix with #different interleaving and reed-solomon parameters. #this will be handled separately #RECTANGULAR SYMBOLS elif ( nrow == 8 and ncol == 18 ): return 6, 16, 1, 1, 5, 7, 1 elif ( nrow == 8 and ncol == 32 ): return 6, 14, 1, 2, 10, 11, 1 elif ( nrow == 12 and ncol == 26 ): return 10, 24, 1, 1, 16, 14, 1 elif ( nrow == 12 and ncol == 36 ): return 10, 16, 1, 2, 22, 18, 1 elif ( nrow == 16 and ncol == 36 ): return 14, 16, 1, 2, 32, 24, 1 elif ( nrow == 16 and ncol == 48 ): return 14, 22, 1, 2, 49, 28, 1 #RETURN ERROR else: inkex.errormsg(_('Unrecognised DataMatrix size')) exit(0) return None
# local library import inkex import simplestyle import simpletransform import cubicsuperpath import coloreffect import dxf_templates try: from numpy import * from numpy.linalg import solve except: # Initialize gettext for messages outside an inkex derived class inkex.localize() inkex.errormsg( _("Failed to import the numpy or numpy.linalg modules. These modules are required by this extension. Please install them and try again." )) inkex.sys.exit() def pointdistance((x1, y1), (x2, y2)): return math.sqrt(((x2 - x1)**2) + ((y2 - y1)**2)) def get_fit(u, csp, col): return (1 - u)**3 * csp[0][col] + 3 * (1 - u)**2 * u * csp[1][col] + 3 * ( 1 - u) * u**2 * csp[2][col] + u**3 * csp[3][col] def get_matrix(u, i, j): if j == i + 2:
return None file_name = os.path.splitext(os.path.basename(png_file))[0] output_file = os.path.join(output_dir, file_name + '.jpeg') command = ['convert', png_file, output_file] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if p.wait() != 0: raise Exception('Is ImageMagick installed?\n' 'Failed to convert %s to JPEG' % png_file) return output_file @contextlib.contextmanager def _make_temp_directory(): temp_dir = tempfile.mkdtemp(prefix='tmp-inkscape') try: yield temp_dir finally: shutil.rmtree(temp_dir) if __name__ == '__main__': try: LayerExport().affect(output=False) except Exception as e: inkex.errormsg(str(e)) sys.exit(1)
#!/usr/bin/env python # We will use the inkex module with the predefined Effect base class. import inkex import simpletransform import cubicsuperpath import bezmisc # The simplestyle module provides functions for style parsing. import simplestyle # third party try: import numpy except: inkex.errormsg( _("Failed to import the numpy modules. These modules are required by this extension. Please install them and try again. On a Debian-like system this can be done with the command, sudo apt-get install python-numpy." )) exit() mat_area = numpy.matrix([[0, 2, 1, -3], [-2, 0, 1, 1], [-1, -1, 0, 2], [3, -1, -2, 0]]) mat_cofm_0 = numpy.matrix([[0, 35, 10, -45], [-35, 0, 12, 23], [-10, -12, 0, 22], [45, -23, -22, 0]]) mat_cofm_1 = numpy.matrix([[0, 15, 3, -18], [-15, 0, 9, 6], [-3, -9, 0, 12], [18, -6, -12, 0]]) mat_cofm_2 = numpy.matrix([[0, 12, 6, -18], [-12, 0, 9, 3], [-6, -9, 0, 15], [18, -3, -15, 0]]) mat_cofm_3 = numpy.matrix([[0, 22, 23, -45], [-22, 0, 12, 10], [-23, -12, 0, 35], [45, -10, -35, 0]])
def effect(self): current_file = self.args[-1] bg_color = self.options.bg_color ##Implementare check_dir if (os.path.isdir(self.options.directory)) == True: ##CODICE SE ESISTE LA DIRECTORY #inkex.errormsg("OK") #DEBUG #Aggiungo un suffisso al nomefile per non sovrascrivere dei file if self.options.add_numeric_suffix_to_filename: dir_list = os.listdir( self.options.directory ) #List di tutti i file nella directory di lavoro temp_name = self.options.filename max_n = 0 for s in dir_list: r = re.match( r"^%s_0*(\d+)%s$" % (re.escape(temp_name), '.png'), s) if r: max_n = max(max_n, int(r.group(1))) self.options.filename = temp_name + "_" + ( "0" * (4 - len(str(max_n + 1))) + str(max_n + 1)) #genero i percorsi file da usare suffix = "" if self.options.conversion_type == 1: suffix = "_BWfix_" + str(self.options.BW_threshold) + "_" elif self.options.conversion_type == 2: suffix = "_BWrnd_" elif self.options.conversion_type == 3: suffix = "_H_" elif self.options.conversion_type == 4: suffix = "_Hrow_" elif self.options.conversion_type == 5: suffix = "_Hcol_" else: if self.options.grayscale_resolution == 1: suffix = "_Gray_256_" elif self.options.grayscale_resolution == 2: suffix = "_Gray_128_" elif self.options.grayscale_resolution == 4: suffix = "_Gray_64_" elif self.options.grayscale_resolution == 8: suffix = "_Gray_32_" elif self.options.grayscale_resolution == 16: suffix = "_Gray_16_" elif self.options.grayscale_resolution == 32: suffix = "_Gray_8_" else: suffix = "_Gray_" pos_file_png_exported = os.path.join( self.options.directory, self.options.filename + ".png") pos_file_png_BW = os.path.join( self.options.directory, self.options.filename + suffix + "preview.png") pos_file_gcode = os.path.join( self.options.directory, self.options.filename + suffix + "gcode.gcode") #Esporto l'immagine in PNG self.exportPage(pos_file_png_exported, current_file, bg_color) #DA FARE #Manipolo l'immagine PNG per generare il file Gcode self.PNGtoGcode(pos_file_png_exported, pos_file_png_BW, pos_file_gcode) else: inkex.errormsg( "Directory does not exist! Please specify existing directory!")
options.outdir = os.path.expanduser(options.outdir) if options.outdir is None: error("No output directory specified") if not os.path.isdir(options.outdir): error("Bad output directory specified:\n'%s' is no dir" % options.outdir) if not os.access(options.outdir, os.W_OK): error("Bad output directory specified:\nCould not write to '%s'" % options.outdir) if options.source not in ('"selected_ids"', '"page"'): error("Select something to export (selected items or whole page)") if options.source == '"selected_ids"' and options.ids is None: error("Select at least one item to export") if options.source == '"page"' and not options.pageName: error("Please enter a page name") if not checkForPath("inkscape"): error("Make sure you have 'inkscape' on your PATH") if options.strip and not checkForPath("convert"): error( "Make sure you have 'convert' on your PATH if you want to reduce the image size using ImageMagick" ) if options.optimize and not checkForPath("optipng"): error( "Make sure you have 'optipng' on your PATH if you want to reduce the image size using OptiPNG" ) export(svg, options) inkex.errormsg("done")
def effect(self): global parent,nomTab,equalTabs,thickness,correction, Z, unit # Get access to main SVG document element and get its dimensions. svg = self.document.getroot() # Get the attibutes: widthDoc = self.svg.unittouu(svg.get('width')) heightDoc = self.svg.unittouu(svg.get('height')) # Create a new layer. layer = etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), 'newlayer') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') parent=self.svg.get_current_layer() # Get script's option values. unit=self.options.unit inside=self.options.inside X = self.svg.unittouu( str(self.options.length) + unit ) Y = self.svg.unittouu( str(self.options.width) + unit ) Z = self.svg.unittouu( str(self.options.height) + unit ) thickness = self.svg.unittouu( str(self.options.thickness) + unit ) nomTab = self.svg.unittouu( str(self.options.tab) + unit ) equalTabs=self.options.equal kerf = self.svg.unittouu( str(self.options.kerf) + unit ) clearance = self.svg.unittouu( str(self.options.clearance) + unit ) layout=self.options.style spacing = self.svg.unittouu( str(self.options.spacing) + unit ) ring = 1 hingeOpt = self.options.hingeOpt hingeThick = self.options.hingeThick thumbTab = self.options.thumbTab if inside: # if inside dimension selected correct values to outside dimension X+=thickness*2 Y+=thickness*2 Z+=thickness*2 correction=kerf-clearance # check input values mainly to avoid python errors # TODO restrict values to *correct* solutions # TODO -- Do what the origial author suggested I do. QUALITY! error=0 if min(X,Y,Z)==0: inkex.errormsg('Error: Dimensions must be non zero') error=1 if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test inkex.errormsg('Error: Dimensions Too Large') error=1 if min(X,Y,Z)<3*nomTab: inkex.errormsg('Error: Tab size too large') error=1 if nomTab<thickness: inkex.errormsg('Error: Tab size too small') error=1 if thickness==0: inkex.errormsg('Error: Thickness is zero') error=1 if thickness>min(X,Y,Z)/3: # crude test inkex.errormsg('Error: Material too thick') error=1 if correction>min(X,Y,Z)/3: # crude test inkex.errormsg('Error: Kerf/Clearence too large') error=1 if spacing>max(X,Y,Z)*10: # crude test inkex.errormsg('Error: Spacing too large') error=1 if spacing<kerf: #if spacing is less then kerf, the laser cuts will overlap and blast meaningful material. inkex.errormsg('Error: Spacing too small') error=1 if error: exit() # layout format:(rootx),(rooty),Xlength,Ylength,tabInfo # root= (spacing,X,Y,Z) * values in tuple # tabInfo= <abcd> 0=holes 1=tabs if layout==0: # Diagramatic Layout TRBL pieces=[ #center low row [(2,0,0,1),(3,0,1,1),X,Z,0b1000,-2], #left middle row [(1,0,0,0),(2,0,0,1),Z,Y,0b1111,0], #center middle row [(2,0,0,1),(2,0,0,1),X,Y,0b0000,0], #right middle row [(3,1,0,1),(2,0,0,1),Z+(EllipseCircumference(X/2, Z/2)/4)+thickness,Y,0b1011,1], #center top row [(2,0,0,1),(1,0,0,0),X,Z,0b0010,-1]] elif layout==1: # Inline(compact) Layout pieces=[#Base [(1,0,0,0),(1,0,0,0),X,Y,0b0000,0], #Front panel [(2,1,0,0),(1,0,0,0),Z,Y,0b1111,0], #Sides with curves [(3,1,0,1),(1,0,0,0),X,Z,0b1000,-2], [(4,2,0,1),(1,0,0,0),X,Z,0b0010,-1], #Long piece w/ hinge [(5,3,0,1),(1,0,0,0),Z+(EllipseCircumference(X/2, Z/2)/4)+thickness,Y,0b1011,1] ] for piece in pieces: # generate and draw each piece of the box (xs,xx,xy,xz)=piece[0] (ys,yx,yy,yz)=piece[1] x=xs*spacing+xx*X+xy*Y+xz*Z # root x co-ord for piece y=ys*spacing+yx*X+yy*Y+yz*Z # root y co-ord for piece dx=piece[2] dy=piece[3] tabs=piece[4] a=tabs>>3&1; b=tabs>>2&1; c=tabs>>1&1; d=tabs&1 # extract tab status for each side. It's a nasty packed binary flag format, but I'm not fixing it now. longSide = 0 shortSide = 0 skew = 0 if piece[5] == 1: longSide = Z elif piece[5] < 0: shortSide = Z # generate and draw the sides of each piece if piece[5] != -1: drawS(side(x,y,d,a,-b,a,-thickness if a else thickness,dx,1,0,a,longSide)) # side a (top) else: drawS(side(x,y,d,a,-b,a,-thickness if a else thickness,dx/2,1,0,a,-1)) # side a (top) when the top participates in a curve if piece[5] != -1 and piece[5] != 1: drawS(side(x+dx+skew,y,-b,a,-b,-c,thickness if b else -thickness,dy,0,1,b,shortSide, False if piece[5] != -2 else True, False if piece[5] != 1 else True)) # side b (right) except for side with living hinge or curves elif piece[5] == -1: drawS(side(x+dx+skew,y+dy,-b,-c,-b,a,thickness if b else -thickness,dy,0,-1,b,shortSide, True)) # side b (right) when the right side participates in a curve else: #It is a cardnal sin to compare floats, so assume <0.0005 is 0 since the front end only gives you 3 digits of precision if float(0.0005) <= float(self.options.thumbTab): side(x+dx+skew,y,-b,a,-b,-c,thickness if b else -thickness,dy,0,1,b,shortSide, False, True, True) #The one call to side that doesn't actually draw. Instead, side draws boxes on its own drawS(box(x+dx+skew,y+thickness,x+dx+skew+self.svg.unittouu( thumbTab + unit ),y+dy-thickness, True)) else: drawS(side(x+dx+skew,y,-b,a,-b,-c,thickness if b else -thickness,dy,0,1,b,shortSide, False, True)) #side b (right) on the right side of a living hinge if piece[5] != -2: drawS(side(x,y+dy,d,-c,-b,-c,thickness if c else -thickness,dx,1,0,c,longSide)) # side c (bottom) else: drawS(side(x,y+dy,d,-c,-b,-c,thickness if c else -thickness,dx/2,1,0,c,-1)) # side c (bottom) when the bottom participates in a curve drawS(side(x,y+dy,d,-c,d,a,-thickness if d else thickness,dy,0,-1,d,0)) # side d (left) if piece[5] < 0: draw_SVG_ellipse(x+(dx/2), y+(dy/2), (dx/2), (dy/2), [(1.5*math.pi), 0] if piece[5] == -1 else [0, 0.5*math.pi]) #draw the curve if piece[5] == 1: #Piece should contain a living hinge if hingeOpt == 0: #Traditional parallel slit self.livingHinge2(x+(Z/2), y, x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4), y + (dy), hingeThick) elif hingeOpt == 1: #Single spiral if not inside: self.livingHinge3(x+(Z/2), y+thickness, x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4), y + dy - thickness, 1, hingeThick) else: self.livingHinge3(x+(Z/2), y + 2*thickness, x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4), y + dy - 2*thickness, 1, hingeThick) elif hingeOpt == 2: #Double spiral self.livingHinge3(x+(Z/2), y+thickness, x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4), y + (dy/2), 1, hingeThick) self.livingHinge3(x+(Z/2), y+(dy/2), x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4), y + dy - thickness, -1, hingeThick) elif hingeOpt == 3 or hingeOpt == 4: #Both snake-based designs self.livingHinge4(x+(Z/2), y, x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4), y + (dy), False if hingeOpt == 3 else True, 0, hingeThick) elif hingeOpt == 5: #Double snake design self.livingHinge4(x+(Z/2), y, x+(Z/2)+EllipseCircumference(X/2, Z/2)/4, y + (dy/2) + thickness, True, 0, hingeThick) #Add thickness as a cheat so design 4 doesn't have to know if it's a short or long variant self.livingHinge4(x+(Z/2), y + (dy/2) - thickness, (x+(Z/2)+(EllipseCircumference(X/2, Z/2)/4)), y + dy, True, 1, hingeThick)
def effect( self ): # Viewbox handling self.handleViewBox() # First traverse the document (or selected items), reducing # everything to line segments. If working on a selection, # then determine the selection's bounding box in the process. # (Actually, we just need to know it's extrema on the x-axis.) if self.options.ids: # Traverse the selected objects for id in self.options.ids: transform = self.recursivelyGetEnclosingTransform( self.selected[id] ) self.recursivelyTraverseSvg( [self.selected[id]], transform ) else: # Traverse the entire document building new, transformed paths self.recursivelyTraverseSvg( self.document.getroot(), self.docTransform ) # Determine the center of the drawing's bounding box self.cx = self.xmin + ( self.xmax - self.xmin ) / 2.0 self.cy = self.ymin + ( self.ymax - self.ymin ) / 2.0 # Determine which polygons lie entirely within other polygons try: if '/' == os.sep: self.f = open( os.path.expanduser( self.options.fname ), 'w') else: self.f = open( os.path.expanduser( self.options.fname ).replace('/', os.sep), 'w') self.f.write(''' // Module names are of the form poly_<inkscape-path-id>(). As a result, // you can associate a polygon in this OpenSCAD program with the corresponding // SVG element in the Inkscape document by looking for the XML element with // the attribute id=\"inkscape-path-id\". // fudge value is used to ensure that subtracted solids are a tad taller // in the z dimension than the polygon being subtracted from. This helps // keep the resulting .stl file manifold. fudge = 0.1; /// Global parameters grid = ''') if self.options.grid : self.f.write('''true''') else: self.f.write('''false''') self.f.write(''' ; //Use grid for multi elements cutters full= ''') if self.options.thickness : self.f.write('''false''') else: self.f.write('''true''') self.f.write(''' ; //For build full or empty objects (see instuctables for details) borderThick = %s ; //border thickness (mm) cutterThick = borderThick ; //cookiecutter wall thickness h= %s ; //total height of the cookie cutter (mm) borderType= %s ; //type of border, 0 none, 1-classic, 2-cone Lreb = %s; //Width of border (en mm) Hreb = %s ; //Thickness of border (mm) /// Grid parameters gridX=300; //Maximum X dimension Change only if you build cookies bigger than 30cm gridY=300; //Maximum Y dimension Change only if you build cookies bigger than 30cm meshSolid=%s; //width of solid part of grid meshSpace=%s; //width of blank part of grid gridThickness=Hreb; //thickness of grid moveGridX=0; //X shift for adujustments moveGridY=0; //Y shift for adjustments rotateGridZ=%s; //Z rotation for adjtments $fn = 10; ''' % (self.options.thickness, self.options.height, self.options.Flanges_type, self.options.Flange_width, self.options.Flange_height, self.options.gridBThick, self.options.gridBSpace, self.options.rotateZ ) ) for key in self.paths: self.f.write( '\n' ) self.convertPath( key ) # Now output the list of modules to call self.f.write( '\n' ) self.f.write(''' module shape(h){ ''' ) for call in self.call_list: self.f.write( call ) self.f.write(''' } //------------------------------------------------- /// Module grid have been imported from the Openscad grid creator by Glyn /// Orininaly published on http://www.thingiverse.com/thing:29211 /// Under the terms of Creative Commons By-Sa (08.26.2012) module grid(meshSolid, meshSpace, gridThickness, gridX, gridY){ meshX=gridX; meshY=gridY; nX=meshX/(meshSolid+meshSpace); nY=meshY/(meshSolid+meshSpace); for (i=[0:nX]) { translate([-(meshX/2)+i*(meshSolid+meshSpace),-meshY/2,-gridThickness/2]) cube(size=[meshSolid,meshY,gridThickness],center=false); } for (i=[0:nY]) { translate([-meshX/2,-(meshY/2)+i*(meshSolid+meshSpace),-gridThickness/2]) cube(size=[meshX,meshSolid,gridThickness],center=false); } } module rebords(borderType,borderThick,Lreb,Hreb){ if (borderType==0){} if (borderType==1){ cylinder(h = Hreb, r=(borderThick+Lreb));} if (borderType==2) { cylinder(h = Hreb, r1=(borderThick+Lreb),r2=(borderThick));} } module borders(h){ cylinder(r=cutterThick,h=h*.75); cylinder(r=cutterThick/2,h=h); } module fullVolume (borderType,borderThick,Lreb,Hreb,h) { minkowski(){ shape(0.001); union(){ borders(h); rebords(borderType,borderThick,Lreb,Hreb); }}} module finalShape(){ if (full == false){ difference(){ fullVolume(borderType,borderThick,Lreb,Hreb,h); translate([0,0,(-0.5*h)]) shape(3*h); }} else{ fullVolume(borderType,borderThick,Lreb,Hreb,h); } } if (grid==true){ union (){ finalShape(); intersection() { translate([moveGridX,moveGridY,(0.5*gridThickness)]) rotate([0,0,rotateGridZ]) grid(meshSolid, meshSpace, gridThickness, gridX, gridY); shape(); }} } else{ finalShape(); } // Enjoy your cookies ! :) ''') except: inkex.errormsg( 'Unable to open the file ' + self.options.fname )
def printError(string): inkex.errormsg(_(str(string)))
def command(comPort, cmd): if (comPort is not None) and (cmd is not None): try: comPort.write(cmd) response = comPort.readline() nRetryCount = 0 while (len(response) == 0) and (nRetryCount < 100): # get new response to replace null response if necessary response = comPort.readline() nRetryCount += 1 inkex.errormsg("Retry" + str(nRetryCount)) if response.strip().startswith("OK"): pass # inkex.errormsg( 'OK after command: ' + cmd ) #Debug option: indicate which command. else: if (response != ''): inkex.errormsg('Error: Unexpected response from EBB.') inkex.errormsg(' Command: ' + cmd.strip()) inkex.errormsg(' Response: ' + str(response.strip())) else: inkex.errormsg('EBB Serial Timeout after command: ' + cmd) # except Exception,e: # inkex.errormsg( str(e)) #For debugging: one may wish to display the error. except: inkex.errormsg('Failed after command: ' + cmd) pass
def effect(self): thickness = self.svg.unittouu( str(self.options.thickness) + self.options.unit) kerf = self.svg.unittouu( str(self.options.kerf) + self.options.unit) / 2 #kerf is diameter in UI and radius in lib spaceing = self.svg.unittouu( str(self.options.spaceing) + self.options.unit) XYZ = [ self.svg.unittouu(str(self.options.X_size) + self.options.unit), self.svg.unittouu(str(self.options.Y_size) + self.options.unit), self.svg.unittouu(str(self.options.Z_size) + self.options.unit) ] if ( self.options.inside == '0' ): #if the sizes are outside sizes reduce the size by thickness if the side gets drawn draw = (self.options.d_left, self.options.d_front, self.options.d_top, self.options.d_right, self.options.d_back, self.options.d_bottom ) #order in XYZXYZ for i in range(6): XYZ[i % 3] -= (thickness if draw[i] else 0 ) #remove a thickness if drawn #compartments on the X axis, devisons in Y direction X_divisions_distances = [] if (self.options.X_compartments > 1): if (self.options.X_mode == 'even'): #spliting in even compartments X_divisions_distances = [ ((XYZ[0]) - (self.options.X_compartments - 1) * (thickness)) / self.options.X_compartments ] else: for dist in self.options.X_divisions.replace( ",", ".").split(";"): #fixing seperator, spliting string X_divisions_distances += [ float(self.svg.unittouu(dist + self.options.unit)) ] #translate into universal units X_divisions_distances[0] += kerf #fixing for kerf if self.options.X_mode != 'absolut': #for even and relative fix list lenght and offset compartments to absolut distances while (len(X_divisions_distances) < self.options.X_compartments + 1): #making the list long enought for relative offsets X_divisions_distances += X_divisions_distances for i in range(1, self.options.X_compartments ): #offset to absolut distances X_divisions_distances[i] += X_divisions_distances[ i - 1] + thickness - kerf X_divisions_distances = X_divisions_distances[ 0:self.options.X_compartments] #cutting excesive lenght off if (X_divisions_distances[-2] + thickness > XYZ[0]) and not self.options.X_fit: inkex.errormsg("X Axis compartments outside of plate") if self.options.X_fit: XYZ[0] = X_divisions_distances[-1] - kerf X_divisions_distances = X_divisions_distances[ 0:-1] #cutting the last of Y_divisions_distances = [] if (self.options.Y_compartments > 1): if (self.options.Y_mode == 'even'): #spliting in even compartments Y_divisions_distances = [ ((XYZ[1]) - (self.options.Y_compartments - 1) * (thickness)) / self.options.Y_compartments ] else: for dist in self.options.Y_divisions.replace( ",", ".").split(";"): #fixing seperator, spliting string Y_divisions_distances += [ float(self.svg.unittouu(dist + self.options.unit)) ] #translate into universal units Y_divisions_distances[0] += kerf #fixing for kerf if self.options.Y_mode != 'absolut': #for even and relative fix list lenght and offset compartments to absolut distances while (len(Y_divisions_distances) < self.options.Y_compartments + 1): #making the list long enought for relative offsets Y_divisions_distances += Y_divisions_distances for i in range(1, self.options.Y_compartments ): #offset to absolut distances Y_divisions_distances[i] += Y_divisions_distances[ i - 1] + thickness - kerf Y_divisions_distances = Y_divisions_distances[ 0:self.options.Y_compartments] #cutting excesive lenght off if (Y_divisions_distances[-2] + thickness > XYZ[1]) and not self.options.X_fit: inkex.errormsg("Y Axis compartments outside of plate") if self.options.Y_fit: XYZ[1] = Y_divisions_distances[-1] - kerf Y_divisions_distances = Y_divisions_distances[ 0:-1] #cutting the last of if (self.options.tab_mode == 'number'): #fixed number of tabs Tabs_XYZ = [ self.options.X_tabs, self.options.Y_tabs, self.options.Z_tabs ] else: #compute apropriate number of tabs for the edges tab_size = float( self.svg.unittouu( str(self.options.tab_size) + self.options.unit)) Tabs_XYZ = [ max(1, int(XYZ[0] / (tab_size)) / 2), max(1, int(XYZ[1] / (tab_size)) / 2), max(1, int(XYZ[2] / (tab_size)) / 2) ] #top and bottom plate tabs_tb = (Tabs_XYZ[0] if self.options.d_back else 0, Tabs_XYZ[1] if self.options.d_right else 0, Tabs_XYZ[0] if self.options.d_front else 0, Tabs_XYZ[1] if self.options.d_left else 0) start_tb = (True if self.options.d_back else False, True if self.options.d_right else False, True if self.options.d_front else False, True if self.options.d_left else False) Plate_tb = mehr_plate.Mehr_plate((XYZ[0], XYZ[1]), tabs_tb, start_tb, thickness, kerf) #top and bottom plate for d in X_divisions_distances: Plate_tb.add_holes('Y', d, Tabs_XYZ[1]) for d in Y_divisions_distances: Plate_tb.add_holes('X', d, Tabs_XYZ[0]) #left and right plate tabs_lr = (Tabs_XYZ[2] if self.options.d_back else 0, Tabs_XYZ[1] if self.options.d_top else 0, Tabs_XYZ[2] if self.options.d_front else 0, Tabs_XYZ[1] if self.options.d_bottom else 0) start_lr = (True if self.options.d_back else False, False, True if self.options.d_front else False, False) Plate_lr = mehr_plate.Mehr_plate((XYZ[2], XYZ[1]), tabs_lr, start_lr, thickness, kerf) #left and right plate for d in Y_divisions_distances: Plate_lr.add_holes('X', d, Tabs_XYZ[2]) #front and back plate tabs_fb = (Tabs_XYZ[0] if self.options.d_top else 0, Tabs_XYZ[2] if self.options.d_right else 0, Tabs_XYZ[0] if self.options.d_bottom else 0, Tabs_XYZ[2] if self.options.d_left else 0) # start_fb = (False, False, False, False) Plate_fb = mehr_plate.Mehr_plate((XYZ[0], XYZ[2]), tabs_fb, start_fb, thickness, kerf) #font and back plate for d in X_divisions_distances: Plate_fb.add_holes('Y', d, Tabs_XYZ[2]) Plate_xc = mehr_plate.Mehr_plate( (XYZ[2], XYZ[1]), tabs_lr, (False, False, False, False), thickness, kerf) for d in Y_divisions_distances: Plate_xc.holes += [ Plate_xc.rect( [0, Plate_xc.corner_offset[1] + d + kerf], [Plate_xc.AABB[0] / 2 - kerf, thickness - 2 * kerf]) ] Plate_yc = mehr_plate.Mehr_plate( (XYZ[0], XYZ[2]), tabs_fb, (False, False, False, False), thickness, kerf) for d in X_divisions_distances: Plate_yc.holes += [ Plate_yc.rect( [Plate_yc.corner_offset[0] + d + kerf, 0], [thickness - 2 * kerf, Plate_yc.AABB[1] / 2 - kerf]) ] X_offset = 0 Y_offset = 0 if (self.options.d_top): Plate_tb.draw( [X_offset + spaceing, spaceing], ["#000000", "#ff0000"], self.svg.get_current_layer() ) #drawing a plate using black for the outline and red for holes X_offset += Plate_tb.AABB[0] + spaceing Y_offset = max(Y_offset, Plate_tb.AABB[1]) if (self.options.d_bottom): Plate_tb.draw([X_offset + spaceing, spaceing], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_tb.AABB[0] + spaceing Y_offset = max(Y_offset, Plate_tb.AABB[1]) if (self.options.d_left): Plate_lr.draw([X_offset + spaceing, spaceing], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_lr.AABB[0] + spaceing Y_offset = max(Y_offset, Plate_lr.AABB[1]) if (self.options.d_right): Plate_lr.draw([X_offset + spaceing, spaceing], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_lr.AABB[0] + spaceing Y_offset = max(Y_offset, Plate_lr.AABB[1]) if (self.options.d_front): Plate_fb.draw([X_offset + spaceing, spaceing], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_fb.AABB[0] + spaceing Y_offset = max(Y_offset, Plate_fb.AABB[1]) if (self.options.d_back): Plate_fb.draw([X_offset + spaceing, spaceing], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_fb.AABB[0] + spaceing Y_offset = max(Y_offset, Plate_fb.AABB[1]) X_offset = 0 for i in range(self.options.X_compartments - 1): Plate_xc.draw([X_offset + spaceing, spaceing + Y_offset], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_xc.AABB[0] + spaceing X_offset = 0 Y_offset += spaceing + Plate_xc.AABB[1] for i in range(self.options.Y_compartments - 1): Plate_yc.draw([X_offset + spaceing, spaceing + Y_offset], ["#000000", "#ff0000"], self.svg.get_current_layer()) X_offset += Plate_yc.AABB[0] + spaceing
import numpy as np import inkex from lxml import etree try: inkex.localization.localize() except: import gettext _ = gettext.gettext try: from PIL import Image except: inkex.errormsg( _("The python module PIL is required for this extension.\n\n" + "Technical details:\n%s" % (e, ))) sys.exit() class raster_to_svg_ordered_dithering(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) self.arg_parser.add_argument( "-t", "--width", action="store", type=int, dest="width", default=200,
def printDebug(string): inkex.errormsg(_(string))
def recursivelyTraverseSvg(self, aNodeList, matCurrent=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], parent_visibility='visible'): ''' 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> 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) elif node.tag == inkex.addNS('path', 'svg'): path_data = node.get('d') if path_data: self.addPathVertices(path_data, node, matNew) 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) 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) 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) 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) 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) 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 effect(self): # Adjust the document view for the desired sticker size root = self.svg.getElement("//svg:svg") subline_fontsize = 40 #px; one line of bottom text (id and owner) creates a box of that height #our DataMatrix has size 16x16, each cube is sized by 16x16px -> total size is 256x256px. We use 4px padding for all directions DataMatrix_xy = 16 DataMatrix_height = 16 * DataMatrix_xy DataMatrix_width = DataMatrix_height sticker_padding = 4 sticker_height = DataMatrix_height + subline_fontsize + 3 * sticker_padding sticker_width = 696 #configure font sizes and box heights to define how large the font size may be at maximum (to omit overflow) objectNameMaxHeight = sticker_height - 2 * subline_fontsize - 4 * sticker_padding objectNameMaxLines = 5 objectNameFontSize = objectNameMaxHeight / objectNameMaxLines #px; generate main font size from lines and box size root.set("width", str(sticker_width) + "px") root.set("height", str(sticker_height) + "px") root.set("viewBox", "%f %f %f %f" % (0, 0, sticker_width, sticker_height)) #clean the document (make it blank) to avoid printing duplicated things ct = 0 for node in self.document.xpath('//*', namespaces=inkex.NSS): ct = ct + 1 if ct > 3: #we keep svg:svg, sodipodi:namedview and svg:defs which defines the default canvas without any content inside #inkex.errormsg(str(node)) try: root.remove(node) except Exception as e: pass #set the document units self.document.getroot().find(inkex.addNS("namedview", "sodipodi")).set( "inkscape:document-units", "px") # Download the recent inventory CSV file and parse line by line to create an inventory sticker password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() password_mgr.add_password(None, self.options.server_address, self.options.htuser, self.options.htpassword) handler = urllib.request.HTTPBasicAuthHandler(password_mgr) opener = urllib.request.build_opener(handler) try: inventoryData = opener.open( self.options.server_address).read().decode("utf-8") urllib.request.install_opener(opener) inventoryCSVParent = os.path.join(self.options.export_dir, "InventorySticker") inventoryCSV = os.path.join(inventoryCSVParent, "inventory.csv") # To avoid messing with old stickers we remove the directory on Client before doing something new shutil.rmtree(inventoryCSVParent, ignore_errors=True ) #remove the output directory before doing new job # we are going to write the imported Server CSV file temporarily. Otherwise CSV reader seems to mess with the file if passed directly if not os.path.exists(inventoryCSVParent): os.mkdir(inventoryCSVParent) with open(inventoryCSV, 'w', encoding="utf-8") as f: f.write(inventoryData) f.close() #parse sticker Ids from user input if self.options.sticker_ids != "*": sticker_ids = self.options.sticker_ids.split(",") else: sticker_ids = None with open(inventoryCSV, 'r', encoding="utf-8") as csv_file: csv_reader = csv.reader(csv_file, delimiter=",") for row in csv_reader: internal_id = row[0] doc_title = row[1] sticker_id = row[2] level = row[3] zone = row[4] if sticker_ids is None or sticker_id in sticker_ids: #create new sub directories for each non-existent FabLab zone (if flat export is disabled) if self.options.flat_export == False: if not zone: zoneDir = os.path.join( inventoryCSVParent, "Keinem Bereich zugeordnet") else: zoneDir = os.path.join( inventoryCSVParent, get_valid_filename(zone) ) #remove invalid charaters from zone if not os.path.exists(zoneDir): os.mkdir(zoneDir) else: zoneDir = inventoryCSVParent #use top directory #Generate the recent sticker content stickerGroup = self.document.getroot().add( inkex.Group( id="InventorySticker_Id" + sticker_id)) #make a new group at root level DataMatrixStyle = inkex.Style({ "stroke": "none", "stroke-width": "1", "fill": "#000000" }) DataMatrixAttribs = { "style": str(DataMatrixStyle), "height": str(DataMatrix_xy) + "px", "width": str(DataMatrix_xy) + "px" } # 1 - create DataMatrix (create a 2d list corresponding to the 1"s and 0s of the DataMatrix) encoded = self.encode(self.options.target_url + "/" + sticker_id) DataMatrixGroup = stickerGroup.add( inkex.Group( id="DataMatrix_Id" + sticker_id)) #make a new group at root level for x, y in self.render_data_matrix( encoded, DataMatrix_xy): DataMatrixAttribs.update({ "x": str(x + sticker_padding), "y": str(y + sticker_padding) }) etree.SubElement(DataMatrixGroup, inkex.addNS("rect", "svg"), DataMatrixAttribs) inline_size = sticker_width - DataMatrix_width - 3 * sticker_padding #remaining width for objects next to the DataMatrix x_pos = DataMatrix_width + 2 * sticker_padding # 2 - Add Object Name Text objectName = etree.SubElement( stickerGroup, inkex.addNS("text", "svg"), { "font-size": str(objectNameFontSize) + "px", "x": str(x_pos) + "px", #"xml:space": "preserve", #we cannot add this here because InkScape throws an error #"y": "4px", #if set it does not correctly apply "text-align": "left", "text-anchor": "left", "vertical-align": "bottom", #style: inline-size required for text wrapping inside box; letter spacing is required to remove the additional whitespaces. The letter spacing depends to the selected font family (Miso) "style": str( inkex.Style( { "fill": "#000000", "inline-size": str(inline_size) + "px", "stroke": "none", "font-family": "Miso", "font-weight": "bold", "letter-spacing": "-3.66px" })) }) objectName.set("id", "objectName_Id" + sticker_id) objectName.set( "xml:space", "preserve" ) #so we add it here instead .. if multiple whitespaces in text are coming after each other just render them (preserve!) objectNameTextSpan = etree.SubElement( objectName, inkex.addNS("tspan", "svg"), {}) objectNameTextSpan.text = splitAt( doc_title, 1 ) #add 1 whitespace after each chacter. So we can simulate a in-word line break (break by char instead by word) # 3 - Add Object Id Text - use the same position but revert text anchors/align objectId = etree.SubElement( stickerGroup, inkex.addNS("text", "svg"), { "font-size": str(subline_fontsize) + "px", "x": str(sticker_padding) + "px", "transform": "translate(0," + str(sticker_height - subline_fontsize) + ")", "text-align": "left", "text-anchor": "left", "vertical-align": "bottom", "style": str( inkex.Style( { "fill": "#000000", "inline-size": str(inline_size) + "px", "stroke": "none", "font-family": "Miso", "font-weight": "bold" }) ) #inline-size required for text wrapping }) objectId.set("id", "objectId_Id" + sticker_id) objectIdTextSpan = etree.SubElement( objectId, inkex.addNS("tspan", "svg"), {}) objectIdTextSpan.text = "Thing #" + sticker_id # 4 - Add Owner Text owner = etree.SubElement( stickerGroup, inkex.addNS("text", "svg"), { "font-size": str(subline_fontsize) + "px", "x": str(x_pos) + "px", "transform": "translate(0," + str(sticker_height - subline_fontsize) + ")", "text-align": "right", "text-anchor": "right", "vertical-align": "bottom", "style": str( inkex.Style( { "fill": "#000000", "inline-size": str(inline_size) + "px", "stroke": "none", "font-family": "Miso", "font-weight": "300" }) ) #inline-size required for text wrapping }) owner.set("id", "owner_Id" + sticker_id) ownerTextSpan = etree.SubElement( owner, inkex.addNS("tspan", "svg"), {}) ownerTextSpan.text = self.options.target_owner # 5 - Add Level Text levelText = etree.SubElement( stickerGroup, inkex.addNS("text", "svg"), { "font-size": str(subline_fontsize) + "px", "x": str(x_pos) + "px", "transform": "translate(0," + str(sticker_height - subline_fontsize - subline_fontsize) + ")", "text-align": "right", "text-anchor": "right", "vertical-align": "bottom", "style": str( inkex.Style( { "fill": "#000000", "inline-size": str(inline_size) + "px", "stroke": "none", "font-family": "Miso", "font-weight": "bold" }) ) #inline-size required for text wrapping }) levelText.set("id", "level_Id" + sticker_id) levelTextTextSpan = etree.SubElement( levelText, inkex.addNS("tspan", "svg"), {}) levelTextTextSpan.text = level # 6 - Add horizontal divider line line_thickness = 2 #px line_x_pos = 350 #px; start of the line (left coord) line_length = sticker_width - line_x_pos divider = etree.SubElement( stickerGroup, inkex.addNS("path", "svg"), { "d": "m " + str(line_x_pos) + "," + str(sticker_height - subline_fontsize - subline_fontsize) + " h " + str(line_length), "style": str( inkex.Style( { "fill": "none", "stroke": "#000000", "stroke-width": str(line_thickness) + "px", "stroke-linecap": "butt", "stroke-linejoin": "miter", "stroke-opacity": "1" }) ) #inline-size required for text wrapping }) divider.set("id", "divider_Id" + sticker_id) if self.options.preview == False: export_file_name = sticker_id + "_" + get_valid_filename( doc_title) export_file_path = os.path.join( zoneDir, export_file_name) #"Export" as SVG by just copying the recent SVG document to the target directory. We need to remove special characters to have valid file names on Windows/Linux export_file_svg = open(export_file_path + ".svg", "w", encoding="utf-8") export_file_svg.write( str(etree.tostring(self.document), "utf-8")) export_file_svg.close() if self.options.export_png == False and self.options.export_svg == False: inkex.errormsg( "Nothing to export. Generating preview only ..." ) break if self.options.export_png == True: #we need to generate SVG before to get PNG. But if user selected PNG only we need to remove SVG afterwards #Make PNG from SVG (slow because each file is picked up separately. Takes about 10 minutes for 600 files inkscape( export_file_path + ".svg", actions= "export-dpi:96;export-background:white;export-filename:{file_name};export-do;FileClose" .format(file_name=export_file_path + ".png")) #fix for "usb.core.USBError: [Errno 13] Access denied (insufficient permissions)" #echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="04f9", ATTR{idProduct}=="2044", MODE="666"' > /etc/udev/rules.d/99-garmin.rules && sudo udevadm trigger if self.options.print_png > 0: if self.options.export_png == False: inkex.errormsg( "No file output for printing. Please set 'Export PNG' to true first." ) else: for x in range(self.options.print_png): command = "brother_ql -m QL-720NW --backend pyusb --printer usb://" + self.options.print_device + " print -l 62 --600dpi -r auto " + export_file_path + ".png" p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE ) #forr Windows: shell=False stdout, stderr = p.communicate() p.wait() if p.returncode != 0: inkex.errormsg( "brother_ql returned: %d %s %s" % (p.returncode, stdout, stderr)) if self.options.export_svg != True: #If user selected PNG only we need to remove SVG again os.remove(export_file_path + ".svg") self.document.getroot().remove( stickerGroup) #remove the stickerGroup again else: #create preview by just breaking the for loop without executing remove(stickerGroup) break csv_file.close() except Exception as e: inkex.errormsg(e)
along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ # standard library import random # local library import inkex import simplestyle, simpletransform import voronoi try: from subprocess import Popen, PIPE except: inkex.errormsg( _("Failed to import the subprocess module. Please report this as a bug at: https://bugs.launchpad.net/inkscape." )) inkex.errormsg(_("Python version is: ") + str(inkex.sys.version_info)) exit() def clip_line(x1, y1, x2, y2, w, h): if x1 < 0 and x2 < 0: return [0, 0, 0, 0] if x1 > w and x2 > w: return [0, 0, 0, 0] if x1 < 0: y1 = (y1 * x2 - y2 * x1) / (x2 - x1) x1 = 0 if x2 < 0: y2 = (y1 * x2 - y2 * x1) / (x2 - x1)
def die(msg="Dying!"): inkex.errormsg(msg) sys.exit(0)