def local_render(self): """Function to render only on text of this module. It's slower than writing all texts to one latex file and then render it to dvi then svg. """ if self.latex_text != '': pretex = r""" \documentclass[crop=true]{standalone} \usepackage[utf8x]{inputenc} \usepackage{fix-cm} \usepackage[hypertex]{hyperref} \usepackage[svgnames]{xcolor} \renewcommand{\familydefault}{\sfdefault} \usepackage{varwidth} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} """ pretex += '\n'.join(self.extra_packages + document._latex_packages) pretex += r'\begin{document}' pretex += self.latex_text pretex += r'\end{document}' #latex2svg self.svgtext = latex2svg(pretex) else: self.svgtext = ''
def render_tikz( tikzcommands, args ): """ Latex -> dvi -> svg for tikz image """ tex_pt_to_px = 96/72.27 #replace '\slidewidth' tiktikzcommands = tikzcommands.replace( r'\slidewidth','%ipt'%0.75*document._width) #Include extrac packages for tex if 'tex_packages' in args: extra_tex_packages = '\n'.join(['\\usepackages{%s}'%pkg for pkg in args['tex_packages']]) else: extra_tex_packages = '' #Include extra tikz headers if 'tikzheader' in args: extra_tex_packages += '\n' + args['tikzheader'] #Tikzfigure options in [] if 'tikzfigureoptions' in args: tikz_fig_opts = '['+args['tikzfigureoptions']+']' else: tikz_fig_opts = '' #Render to a dvi file pretex = """ \\documentclass[tikz,svgnames]{standalone} \\usepackage[utf8x]{inputenc} %s \\begin{document} \\begin{tikzpicture}%s %s \\end{tikzpicture} \\end{document} """%(extra_tex_packages,tikz_fig_opts,tikzcommands) #latex2svg svgout = latex2svg(pretex) if svgout != '': #Parse the svg soup = BeautifulSoup(svgout, 'xml') #Change svg id with global ids #soup = make_global_svg_defs(soup) #Find the width and height svgsoup = soup.find('svg') g = soup.find('g') xinit, yinit, tikz_width, tikz_height = svgsoup.get('viewBox').split() tikz_width = float(tikz_width) tikz_height = float(tikz_height) newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)'%(tex_pt_to_px, -float(xinit), -float(yinit)) g['transform'] = newmatrix output = svgsoup.renderContents() else: #print(tex_msg) output = '' tikz_height = 0 tikz_width = 0 return output, tikz_width, tikz_height
def render_text(ct, usetex=True): """ Function to render the text using latex latex -> dvi -> dvi2svgm -> svg Use the svg output for the text in the frame """ args = ct['args'] textin = ct['content'] #Check if their is width in args or if we need to use the default width if "width" in args: w = float(ct['positionner'].width) else: w = float(document._width) if usetex: #Check if a color is defined in args if 'color' in args: textin = color_text(textin, args['color']) if 'center' in args['align']: texalign = r'\centering' else: texalign = '' #fontsize{size}{interlinear_size} pretex = r""" \documentclass[crop=True]{standalone} \usepackage[utf8x]{inputenc} \usepackage{fix-cm} \usepackage[hypertex]{hyperref} \usepackage[svgnames]{xcolor} \renewcommand{\familydefault}{\sfdefault} \usepackage{varwidth} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \begin{document} \begin{varwidth}{%ipt} %s \fontsize{%i}{%i}\selectfont %s \end{varwidth} \end{document} """ % (w * (72.27 / 96.), texalign, args['size'], (args['size'] + args['size'] * 0.1), textin) #96/72.27 pt_to_px for latex #latex2svg testsvg = latex2svg(pretex) if testsvg == '': print("Latex Compilation Error") print("Beampy Input") print(pretex) sys.exit(0) #Parse the ouput with beautifullsoup soup = BeautifulSoup(testsvg, 'xml') svgsoup = soup.find('svg') #Get id of paths element to make a global counter over the entire document if 'path' not in document._global_counter: document._global_counter['path'] = 0 #Create unique_id_ with time text_id = ("%0.2f" % time.time()).split('.')[-1] for path in soup.find_all('path'): pid = path.get('id') new_pid = '%s_%i' % (text_id, document._global_counter['path']) testsvg = re.sub(pid, new_pid, testsvg) #path['id'] = new_pid //Need to change also the id ine each use elements ... replace (above) is simpler document._global_counter['path'] += 1 #Reparse the svg soup = BeautifulSoup(testsvg, 'xml') #Change id in svg defs to use the global id system soup = make_global_svg_defs(soup) svgsoup = soup.find('svg') xinit, yinit, text_width, text_height = svgsoup.get('viewBox').split() text_width = float(text_width) text_height = float(text_height) #Find all links to apply the style defined in theme['link'] links = soup.find_all('a') style = ' '.join([ '%s:%s;' % (str(key), str(value)) for key, value in document._theme['link'].items() ]) for link in links: link['style'] = style #Use the first <use> in svg to get the y of the first letter try: uses = soup.find_all('use') except: print soup if len(uses) > 0: #TODO: need to make a more fine definition of baseline baseline = 0 for use in uses: if use.has_attr('y'): baseline = float(use.get('y')) break if baseline == 0: print("Baseline one TeX error and is put to 0") #print baseline #Get the group tag to get the transform matrix to add yoffset g = soup.find('g') transform_matrix = g.get('transform') if 'va' in args and args['va'] == 'baseline': yoffset = -float(baseline) xoffset = -float(xinit) #for the box plot (see boxed below) oldyinit = yinit yinit = -float(baseline) + float(yinit) baseline = -float(oldyinit) + float(baseline) else: yoffset = -float(yinit) xoffset = -float(xinit) #For the box plot baseline = -float(yinit) + float(baseline) yinit = 0 #print baseline, float(yinit), yoffset #newmatrix = 'translate(%s,%0.4f)'%(-float(xoffset),-float(yoffset) ) tex_pt_to_px = 96 / 72.27 newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)' % ( tex_pt_to_px, xoffset, yoffset) g['transform'] = newmatrix text_width = text_width * tex_pt_to_px text_height = text_height * tex_pt_to_px baseline = baseline * tex_pt_to_px yinit = yinit * tex_pt_to_px #g['viewBox'] = svgsoup.get('viewBox') output = svgsoup.renderContents() #Add red box around the text if document._text_box: boxed = '''<g transform="translate(%0.1f,%0.1f)"> <line x1="0" y1="0" x2="%i" y2="0" style="stroke: red"/> <line x1="%i" y1="0" x2="%i" y2="%i" style="stroke: red"/> <line x1="%i" y1="%i" x2="0" y2="%i" style="stroke: red"/> <line x1="0" y1="%i" x2="0" y2="0" style="stroke: red"/> <line x1="0" y1="%i" x2="%i" y2="%i" style="stroke: green"/> </g>''' output += boxed % (0, float(yinit), text_width, text_width, text_width, text_height, text_width, text_height, text_height, text_height, baseline, text_width, baseline) #print output else: #Render as svg text #args['x'] = convert_unit(args['x']) #args['y'] = convert_unit(args['y']) #args = ' '.join( [str(arg)+"='"+str(val)+"'" for arg, val in args.iteritems()] ) print('[WARNING !!!]: Classic text not yet implemented') output = "<text>%s</text>" % (textin.decode('utf-8')) #TODO: Need to fix the estimation of te width #print("[WARNING!!!] Width of classic svg text can't be estimated") text_width = 0 text_height = 0 #Update positionner with the correct width and height of the final svg ct['positionner'].update_size(text_width, text_height) return output
def render_text( textin, args, usetex=True): """ Function to render the text using latex latex -> dvi -> dvi2svgm -> svg Use the svg output for the text in the frame """ #Check if their is width in args or if we need to use the default width if "width" in args: w = float(convert_unit(str(args['width']))) else: w = float(document._width) if usetex: #Check if a color is defined in args if 'fill' in args: if "#" in args['fill']: textin = r'{\color[HTML]{%s} %s }'%(args['fill'].replace('#','').upper(), textin) else: textin =r'{\color{%s} %s }'%(args['fill'], textin) if 'center' in args['align']: texalign = r'\centering' else: texalign = '' #fontsize{size}{interlinear_size} pretex = r""" \documentclass[crop=True]{standalone} \usepackage[utf8x]{inputenc} \usepackage{fix-cm} \usepackage{hyperref} \usepackage[svgnames]{xcolor} \renewcommand{\familydefault}{\sfdefault} \usepackage{varwidth} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \special{html} \begin{document} \begin{varwidth}{%ipt} %s \fontsize{%i}{%i}\selectfont %s \end{varwidth} \end{document} """%(w*(72.27/96.),texalign,args['font-size'],(args['font-size']+args['font-size']*0.1),textin) #96/72.27 pt_to_px for latex #latex2svg testsvg = latex2svg( pretex ) if testsvg == '': print("Latex Compilation Error") print("Beampy Input") print(pretex) sys.exit(0) #Parse the ouput with beautifullsoup soup = BeautifulSoup(testsvg, 'xml') svgsoup = soup.find('svg') #Get id of paths element to make a global counter over the entire document if 'path' not in document._global_counter: document._global_counter['path'] = 0 #Create unique_id_ with time text_id = ("%0.2f"%time.time()).split('.')[-1] for path in soup.find_all('path'): pid = path.get('id') new_pid = '%s_%i'%(text_id, document._global_counter['path']) testsvg = re.sub(pid,new_pid, testsvg) #path['id'] = new_pid //Need to change also the id ine each use elements ... replace (above) is simpler document._global_counter['path'] += 1 #Reparse the svg soup = BeautifulSoup(testsvg, 'xml') #Change id in svg defs to use the global id system soup = make_global_svg_defs(soup) svgsoup = soup.find('svg') xinit, yinit, text_width, text_height = svgsoup.get('viewBox').split() text_width = float(text_width) text_height = float(text_height) #Use the first <use> in svg to get the y of the first letter try: uses = soup.find_all('use') except: print soup if len(uses) > 0: #TODO: need to make a more fine definition of baseline baseline = 0 for use in uses: if use.has_attr('y'): baseline = float(use.get('y')) break if baseline == 0: print("Baseline one TeX error and is put to 0") #print baseline #Get the group tag to get the transform matrix to add yoffset g = soup.find('g') transform_matrix = g.get('transform') if 'va' in args and args['va'] == 'baseline': yoffset = - float(baseline) xoffset = - float(xinit) #for the box plot (see boxed below) oldyinit = yinit yinit = - float(baseline) + float(yinit) baseline = -float(oldyinit) + float(baseline) else: yoffset = -float(yinit) xoffset = -float(xinit) #For the box plot baseline = -float(yinit) + float(baseline) yinit = 0 #print baseline, float(yinit), yoffset #newmatrix = 'translate(%s,%0.4f)'%(-float(xoffset),-float(yoffset) ) tex_pt_to_px = 96/72.27 newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)'%(tex_pt_to_px, xoffset, yoffset) g['transform'] = newmatrix text_width = text_width * tex_pt_to_px text_height = text_height * tex_pt_to_px baseline = baseline * tex_pt_to_px yinit = yinit * tex_pt_to_px #g['viewBox'] = svgsoup.get('viewBox') output = svgsoup.renderContents() #Add red box around the text if document._text_box: boxed = '''<g transform="translate(%0.1f,%0.1f)"> <line x1="0" y1="0" x2="%i" y2="0" style="stroke: red"/> <line x1="%i" y1="0" x2="%i" y2="%i" style="stroke: red"/> <line x1="%i" y1="%i" x2="0" y2="%i" style="stroke: red"/> <line x1="0" y1="%i" x2="0" y2="0" style="stroke: red"/> <line x1="0" y1="%i" x2="%i" y2="%i" style="stroke: green"/> </g>''' output += boxed%( 0, float(yinit), text_width, text_width,text_width,text_height, text_width,text_height,text_height, text_height, baseline,text_width,baseline) #print output else: #Render as svg text args['x'] = convert_unit(args['x']) args['y'] = convert_unit(args['y']) args = ' '.join( [str(arg)+"='"+str(val)+"'" for arg, val in args.iteritems()] ) output = "<text %s>%s</text>"%(args, textin.decode('utf-8')) #TODO: Need to fix the estimation of te width #print("[WARNING!!!] Width of classic svg text can't be estimated") text_width = 0 text_height = 0 return output, text_width, text_height
def render(self): """ Latex -> dvi -> svg for tikz image """ tikzcommands = self.content #args = ct['args'] tex_pt_to_px = 96 / 72.27 #replace '\slidewidth' tiktikzcommands = tikzcommands.replace( r'\slidewidth', '%ipt' % (0.75 * document._slides[gcs()].curwidth)) #Include extrac packages for tex if getattr(self, 'tex_packages', False): extra_tex_packages = '\n'.join( ['\\usepackages{%s}' % pkg for pkg in self.tex_packages]) else: extra_tex_packages = '' #Include extra tikz headers if getattr(self, 'tikz_header', False): extra_tex_packages += '\n%s' % (self.tikz_header) #Tikzfigure options in [] if getattr(self, 'figure_options', False): tikz_fig_opts = '[' + self.figure_options + ']' else: tikz_fig_opts = '' # Render to a dvi file pretex = """ \\documentclass[tikz,svgnames]{standalone} \\usepackage[utf8x]{inputenc} %s \\begin{document} \\begin{tikzpicture}%s %s \\end{tikzpicture} \\end{document} """ % (extra_tex_packages, tikz_fig_opts, tikzcommands) #latex2svg svgout = latex2svg(pretex) if svgout != '': #Parse the svg soup = BeautifulSoup(svgout, 'xml') #Find the width and height svgsoup = soup.find('svg') g = soup.find('g') xinit, yinit, tikz_width, tikz_height = svgsoup.get( 'viewBox').split() tikz_width = float(tikz_width) * tex_pt_to_px tikz_height = float(tikz_height) * tex_pt_to_px print(tikz_width, tikz_height) # Default is args['figure_anchor'] == top_left dx = -float(xinit) dy = -float(yinit) print(self.positionner.x, self.positionner.y) if 'bottom' in self.figure_anchor: self.positionner.y['anchor'] = 'bottom' if 'right' in self.figure_anchor: self.positionner.x['anchor'] = 'right' newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)' % (tex_pt_to_px, dx, dy) g['transform'] = newmatrix output = svgsoup.renderContents() else: output = '' tikz_height = 0 tikz_width = 0 self.update_size(tikz_width, tikz_height) self.svgout = output self.rendered = True
def render(self): """ Text is rendered using latex if self.usetex = True if not use simple svg """ if self.usetex: #Check if a color is defined in args if hasattr(self, 'color'): textin = color_text(self.content, self.color) else: textin = self.content if 'center' in self.align: texalign = r'\centering' elif 'right' in self.align: texalign = r'\flushright' else: texalign = '' #fontsize{size}{interlinear_size} pretex = r""" \documentclass[crop=True]{standalone} \usepackage[utf8x]{inputenc} \usepackage{fix-cm} \usepackage[hypertex]{hyperref} \usepackage[svgnames]{xcolor} \renewcommand{\familydefault}{\sfdefault} \usepackage{varwidth} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \begin{document} \begin{varwidth}{%ipt} %s \fontsize{%i}{%i}\selectfont %s \end{varwidth} \end{document} """ % (self.width * (72.27 / 96.), texalign, self.size, (self.size + self.size * 0.1), textin) #96/72.27 pt_to_px for latex #latex2svg testsvg = latex2svg(pretex) if testsvg == '': print("Latex Compilation Error") print("Beampy Input") print(pretex) sys.exit(0) #Parse the ouput with beautifullsoup soup = BeautifulSoup(testsvg, 'xml') svgsoup = soup.find('svg') #print(soup) #Find the width and height xinit, yinit, text_width, text_height = svgsoup.get( 'viewBox').split() text_width = float(text_width) text_height = float(text_height) #TODO: REPLACE BeautifulSoup by lxml (which is faster) #from lxml import etree #doc = etree.fromstring(testsvg) #dtest = doc.xpath('//path/id') #print(dtest) #Get id of paths element to make a global counter over the entire document if 'path' not in document._global_counter: document._global_counter['path'] = 0 #Create unique_id_ with time #text_id = ("%0.2f"%time.time()).split('.')[-1] """ for path in soup.find_all('path'): pid = path.get('id') new_pid = '%s_%i'%(text_id, document._global_counter['path']) #Check genereta an hash of the glyphs svg path and check if it's #already define in the global store md5print = hashlib.md5(path.get('d')).hexdigest() new_svg_path = "<path d='%s', id='%s'> "%(path.get('d'), new_pid) print(new_svg_path) print(md5print, 'for ', pid, 'nid', new_pid) #Old way on the global svg testsvg = re.sub(pid, new_pid, testsvg) document._global_counter['path'] += 1 #Reparse the svg soup = BeautifulSoup(testsvg, 'xml') """ #New method with a global glyph store svgsoup = parse_dvisvgm_svg(svgsoup) #Change id in svg defs to use the global id system #soup = make_global_svg_defs(soup) #svgsoup = soup.find('svg') #Find all links to apply the style defined in theme['link'] links = svgsoup.find_all('a') style = ' '.join([ '%s:%s;' % (str(key), str(value)) for key, value in document._theme['link'].items() ]) for link in links: link['style'] = style #Use the first <use> in svg to get the y of the first letter try: uses = svgsoup.find_all('use') except: print(soup) if len(uses) > 0: #TODO: need to make a more fine definition of baseline baseline = 0 for use in uses: if use.has_attr('y'): baseline = float(use.get('y')) break if baseline == 0: print("No Baseline found in TeX and is put to 0") #print baseline #Get the group tag to get the transform matrix to add yoffset g = svgsoup.find('g') transform_matrix = g.get('transform') if getattr(self, 'va', False) and self.va == 'baseline': yoffset = -float(baseline) xoffset = -float(xinit) #for the box plot (see boxed below) oldyinit = yinit yinit = -float(baseline) + float(yinit) baseline = -float(oldyinit) + float(baseline) else: yoffset = -float(yinit) xoffset = -float(xinit) #For the box plot baseline = -float(yinit) + float(baseline) yinit = 0 #print baseline, float(yinit), yoffset #newmatrix = 'translate(%s,%0.4f)'%(-float(xoffset),-float(yoffset) ) tex_pt_to_px = 96 / 72.27 newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)' % ( tex_pt_to_px, xoffset, yoffset) g['transform'] = newmatrix text_width = text_width * tex_pt_to_px text_height = text_height * tex_pt_to_px baseline = baseline * tex_pt_to_px yinit = yinit * tex_pt_to_px #g['viewBox'] = svgsoup.get('viewBox') output = svgsoup.renderContents() #Add red box around the text if document._text_box: boxed = '''<g transform="translate(%0.1f,%0.1f)"> <line x1="0" y1="0" x2="%i" y2="0" style="stroke: red"/> <line x1="%i" y1="0" x2="%i" y2="%i" style="stroke: red"/> <line x1="%i" y1="%i" x2="0" y2="%i" style="stroke: red"/> <line x1="0" y1="%i" x2="0" y2="0" style="stroke: red"/> <line x1="0" y1="%i" x2="%i" y2="%i" style="stroke: green"/> </g>''' output += boxed % (0, float(yinit), text_width, text_width, text_width, text_height, text_width, text_height, text_height, text_height, baseline, text_width, baseline) #print output else: #Render as svg text #print('[WARNING !!!]: Classic text not yet implemented') textin = self.content style = '' if hasattr(self, 'color'): style += 'color:%s' % (self.color) output = '<text style="%s">%s</text>' % (style, textin.decode('utf-8')) tmpsvg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" xmlns:xlink="http://www.w3.org/1999/xlink">%s</svg>' % output #Need to create a temp file tmpfile, tmpnam = tempfile.mkstemp(prefix='beampytmp') with open(tmpnam + '.svg', 'w') as f: f.write(tmpsvg) text_width = getsvgwidth(tmpnam + '.svg') text_height = getsvgheight(tmpnam + '.svg') os.remove(tmpnam + '.svg') print(text_width, text_height) #Update positionner with the correct width and height of the final svg self.update_size(text_width, text_height) #Store the output svg self.svgout = output #Update the rendered state of the module self.rendered = True
def render(self): """ Latex -> dvi -> svg for tikz image """ tikzcommands = self.content #args = ct['args'] tex_pt_to_px = 96/72.27 #replace '\slidewidth' tiktikzcommands = tikzcommands.replace( r'\slidewidth','%ipt'%0.75*document._width) #Include extrac packages for tex if getattr(self, 'tex_packages', False): extra_tex_packages = '\n'.join(['\\usepackages{%s}'%pkg for pkg in self.tex_packages]) else: extra_tex_packages = '' #Include extra tikz headers if getattr(self, 'tikz_header', False): extra_tex_packages += '\n%s'%(self.tikz_header) #Tikzfigure options in [] if getattr(self,'figure_options', False): tikz_fig_opts = '['+self.figure_options+']' else: tikz_fig_opts = '' #Render to a dvi file pretex = """ \\documentclass[tikz,svgnames]{standalone} \\usepackage[utf8x]{inputenc} %s \\begin{document} \\begin{tikzpicture}%s %s \\end{tikzpicture} \\end{document} """%(extra_tex_packages,tikz_fig_opts,tikzcommands) #latex2svg svgout = latex2svg(pretex) if svgout != '': #Parse the svg soup = BeautifulSoup(svgout, 'xml') #Change svg id with global ids #soup = make_global_svg_defs(soup) #Find the width and height svgsoup = soup.find('svg') g = soup.find('g') xinit, yinit, tikz_width, tikz_height = svgsoup.get('viewBox').split() tikz_width = float(tikz_width) tikz_height = float(tikz_height) #Default is args['figure_anchor'] == top_left dx = -float(xinit) dy = -float(yinit) if 'bottom' in self.figure_anchor: dy = -float(yinit) - tikz_height if 'right' in self.figure_anchor: dx = -float(xinit)-tikz_width newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)'%(tex_pt_to_px, dx, dy) g['transform'] = newmatrix output = svgsoup.renderContents() else: #print(tex_msg) output = '' tikz_height = 0 tikz_width = 0 self.update_size(tikz_width, tikz_height) self.svgout = output self.rendered = True
def render(self): """ Text is rendered using latex if self.usetex = True if not use simple svg """ if self.usetex: #Check if a color is defined in args if hasattr(self, 'color'): textin = color_text( self.content, self.color ) else: textin = self.content if 'center' in self.align: texalign = r'\centering' elif 'right' in self.align: texalign = r'\flushright' else: texalign = '' #fontsize{size}{interlinear_size} pretex = r""" \documentclass[crop=True]{standalone} \usepackage[utf8x]{inputenc} \usepackage{fix-cm} \usepackage[hypertex]{hyperref} \usepackage[svgnames]{xcolor} \renewcommand{\familydefault}{\sfdefault} \usepackage{varwidth} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \begin{document} \begin{varwidth}{%ipt} %s \fontsize{%i}{%i}\selectfont %s \end{varwidth} \end{document} """%( self.width*(72.27/96.), texalign, self.size, (self.size+self.size*0.1), textin ) #96/72.27 pt_to_px for latex #latex2svg testsvg = latex2svg( pretex ) if testsvg == '': print("Latex Compilation Error") print("Beampy Input") print(pretex) sys.exit(0) #Parse the ouput with beautifullsoup soup = BeautifulSoup(testsvg, 'xml') svgsoup = soup.find('svg') #Get id of paths element to make a global counter over the entire document if 'path' not in document._global_counter: document._global_counter['path'] = 0 #Create unique_id_ with time text_id = ("%0.2f"%time.time()).split('.')[-1] for path in soup.find_all('path'): pid = path.get('id') new_pid = '%s_%i'%(text_id, document._global_counter['path']) testsvg = re.sub(pid,new_pid, testsvg) #path['id'] = new_pid //Need to change also the id ine each use elements ... replace (above) is simpler document._global_counter['path'] += 1 #Reparse the svg soup = BeautifulSoup(testsvg, 'xml') #Change id in svg defs to use the global id system soup = make_global_svg_defs(soup) svgsoup = soup.find('svg') xinit, yinit, text_width, text_height = svgsoup.get('viewBox').split() text_width = float(text_width) text_height = float(text_height) #Find all links to apply the style defined in theme['link'] links = soup.find_all('a') style = ' '.join(['%s:%s;'%(str(key), str(value)) for key, value in document._theme['link'].items()]) for link in links: link['style'] = style #Use the first <use> in svg to get the y of the first letter try: uses = soup.find_all('use') except: print soup if len(uses) > 0: #TODO: need to make a more fine definition of baseline baseline = 0 for use in uses: if use.has_attr('y'): baseline = float(use.get('y')) break if baseline == 0: print("No Baseline found in TeX and is put to 0") #print baseline #Get the group tag to get the transform matrix to add yoffset g = soup.find('g') transform_matrix = g.get('transform') if getattr(self, 'va', False) and self.va == 'baseline': yoffset = - float(baseline) xoffset = - float(xinit) #for the box plot (see boxed below) oldyinit = yinit yinit = - float(baseline) + float(yinit) baseline = -float(oldyinit) + float(baseline) else: yoffset = -float(yinit) xoffset = -float(xinit) #For the box plot baseline = -float(yinit) + float(baseline) yinit = 0 #print baseline, float(yinit), yoffset #newmatrix = 'translate(%s,%0.4f)'%(-float(xoffset),-float(yoffset) ) tex_pt_to_px = 96/72.27 newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)'%(tex_pt_to_px, xoffset, yoffset) g['transform'] = newmatrix text_width = text_width * tex_pt_to_px text_height = text_height * tex_pt_to_px baseline = baseline * tex_pt_to_px yinit = yinit * tex_pt_to_px #g['viewBox'] = svgsoup.get('viewBox') output = svgsoup.renderContents() #Add red box around the text if document._text_box: boxed = '''<g transform="translate(%0.1f,%0.1f)"> <line x1="0" y1="0" x2="%i" y2="0" style="stroke: red"/> <line x1="%i" y1="0" x2="%i" y2="%i" style="stroke: red"/> <line x1="%i" y1="%i" x2="0" y2="%i" style="stroke: red"/> <line x1="0" y1="%i" x2="0" y2="0" style="stroke: red"/> <line x1="0" y1="%i" x2="%i" y2="%i" style="stroke: green"/> </g>''' output += boxed%( 0, float(yinit), text_width, text_width,text_width,text_height, text_width,text_height,text_height, text_height, baseline,text_width,baseline) #print output else: #Render as svg text #print('[WARNING !!!]: Classic text not yet implemented') textin = self.content style = '' if hasattr(self, 'color'): style += 'color:%s'%(self.color) output = '<text style="%s">%s</text>'%(style, textin.decode('utf-8')) tmpsvg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" xmlns:xlink="http://www.w3.org/1999/xlink">%s</svg>'%output #Need to create a temp file tmpfile, tmpnam = tempfile.mkstemp(prefix='beampytmp') with open( tmpnam + '.svg', 'w' ) as f: f.write( tmpsvg ) text_width = getsvgwidth(tmpnam + '.svg') text_height = getsvgheight(tmpnam + '.svg') os.remove(tmpnam + '.svg') print(text_width, text_height) #Update positionner with the correct width and height of the final svg self.update_size(text_width, text_height) #Store the output svg self.svgout = output #Update the rendered state of the module self.rendered = True
def render_tikz( ct ): """ Latex -> dvi -> svg for tikz image """ tikzcommands = ct['content'] args = ct['args'] tex_pt_to_px = 96/72.27 #replace '\slidewidth' tiktikzcommands = tikzcommands.replace( r'\slidewidth','%ipt'%0.75*document._width) #Include extrac packages for tex if args['tex_packages']: extra_tex_packages = '\n'.join(['\\usepackages{%s}'%pkg for pkg in args['tex_packages']]) else: extra_tex_packages = '' #Include extra tikz headers if args['tikz_header']: extra_tex_packages += '\n' + args['tikz_header'] #Tikzfigure options in [] if args['figure_options']: tikz_fig_opts = '['+args['figure_options']+']' else: tikz_fig_opts = '' #Render to a dvi file pretex = """ \\documentclass[tikz,svgnames]{standalone} \\usepackage[utf8x]{inputenc} %s \\begin{document} \\begin{tikzpicture}%s %s \\end{tikzpicture} \\end{document} """%(extra_tex_packages,tikz_fig_opts,tikzcommands) #latex2svg svgout = latex2svg(pretex) if svgout != '': #Parse the svg soup = BeautifulSoup(svgout, 'xml') #Change svg id with global ids #soup = make_global_svg_defs(soup) #Find the width and height svgsoup = soup.find('svg') g = soup.find('g') xinit, yinit, tikz_width, tikz_height = svgsoup.get('viewBox').split() tikz_width = float(tikz_width) tikz_height = float(tikz_height) #Default is args['figure_anchor'] == top_left dx = -float(xinit) dy = -float(yinit) if 'bottom' in args['figure_anchor']: dy = -float(yinit) - tikz_height if 'right' in args['figure_anchor']: dx = -float(xinit)-tikz_width newmatrix = 'scale(%0.3f) translate(%0.1f,%0.1f)'%(tex_pt_to_px, dx, dy) g['transform'] = newmatrix output = svgsoup.renderContents() else: #print(tex_msg) output = '' tikz_height = 0 tikz_width = 0 ct['positionner'].update_size(tikz_width, tikz_height) return output