def itemize(items_list, **kwargs): ''' Generates a list or an enumeration. See THEME['itemize'] for option TODO: ADD doc for function arguments ''' args = check_function_args(itemize, kwargs) number = 1 if args['width'] != None: in_width = float(convert_unit(args['width'])) - float( convert_unit(args['item_indent'])) else: in_width = float(document._width) - float( convert_unit(args['item_indent'])) with group(width=args['width'], x=args['x'], y=args['y']): for i, the_item in enumerate(items_list): if args['item_style'] == 'bullet': item_char = r'$\bullet$' elif args['item_style'] == 'number': item_char = str(number) + r'.' number += 1 else: item_char = args['item_style'] # Add color item_char = color_text(item_char, args['item_color']) the_item = color_text(the_item, args['text_color']) if i == 0: text(item_char + r' ' + the_item, x=args['item_indent'], y=0, width=in_width) else: text(item_char + r' ' + the_item, x=args['item_indent'], y=args['item_spacing'], width=in_width)
def pre_render(self): """ Prepare the latex render of the text """ 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 = '' template = r"""\begin{varwidth}{%ipt} %s \fontsize{%i}{%i}\selectfont %s \end{varwidth}""" # Matplotlib uses fontsize * 1.25 for spacing self.latex_text = template % (self.width.value * (72.27 / 96.), texalign, self.size, (self.size + self.size * 0.1), textin) # fontsize{size}{interlinear_size} #96/72.27 pt_to_px for latex else: self.latex_text = ''
def itemize( items_list, **kwargs): ''' Generates a list or an enumeration. See THEME['itemize'] for option TODO: ADD doc for function arguments ''' args = check_function_args(itemize, kwargs) number = 1 if args['width']!=None: in_width = float(convert_unit(args['width'])) - float(convert_unit(args['item_indent'])) else: in_width = float(document._width) - float(convert_unit(args['item_indent'])) with group(width=args['width'], x=args['x'], y=args['y']): for i, the_item in enumerate(items_list) : if args['item_style'] == 'bullet' : item_char = r'$\bullet$' elif args['item_style'] == 'number' : item_char = str(number) + r'.' number += 1 else : item_char = item_style # Add color item_char = color_text( item_char, args['item_color'] ) the_item = color_text( the_item, args['text_color'] ) if i == 0 : text( item_char + r' ' + the_item, x = args['item_indent'], y = 0, width=in_width ) else: text( item_char + r' ' + the_item, x = args['item_indent'], y = args['item_spacing'], width=in_width )
def theme_maketitle(titlein, author = [], affiliation = None, meeting = None, lead_author = None, date=None ): """ Function to create the presentation title slide """ # get_command_line(maketitle) # Check function arguments from THEME args = THEME['maketitle'] if lead_author is not None and len(author) > lead_author: print('Color author: %s in %s' % (author[lead_author], args['lead_author_color'])) author[lead_author] = color_text(author[lead_author], args['lead_author_color']) author_string = '\hspace{0.7cm} '.join(author) if date in ('Today', 'today', 'now'): date = datetime.datetime.now().strftime("%d/%m/%Y") if isinstance(affiliation, list): affiliation = r'\\'.join(affiliation) with group(y="center"): with box(width='85%', y=0, auto_height_margin=20, background_color=lead_color) as tg: text(titlein, color=args['title_color'], size=args['title_size'], align='center', y=0, x='center', width='90%') if len(author) > 0: text(author_string, width='80%', y=tg.bottom+"1.5cm", color=args['author_color'], size=args['author_size'], align='center') if affiliation is not None: text(affiliation, width='90%', y="+1cm", color=args['affiliation_color'], size=args['affiliation_size'], align='center') if meeting is not None: text(meeting, width='90%', y="+1cm", color=args['meeting_color'], size=args['subtitle_size'], align='center') if date is not None: text(date, width=750, y="+1cm", color=args['date_color'], size=args['date_size'])
def pre_render(self): """ The pre render will be run at the biginig to create a unique latex file This reducde the number of calls to latex self.latex_tmp will be stack using "newpage" latex command to separate each text the svg produced from the dvi will be load in self.svgtext If their is no output from latex self.svgtext = '' """ 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 = '' self.latex_tmp = r""" \begin{varwidth}{%ipt} %s \fontsize{%i}{%i}\selectfont %s \end{varwidth} """ % (self.width * (72.27 / 96.), texalign, self.size, (self.size + self.size * 0.1), textin) else: self.latex_tmp = ''
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(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): """ 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 itemize(items_list, **kwargs): ''' Generates a list or an enumeration. Parameters ---------- items_list : list of str List of item sentences. x : int or float or {'center', 'auto'} or str, optional Horizontal position for the item list (the default is 'center'). See positioning system of Beampy. y : int or float or {'center', 'auto'} or str, optional Vertical position for the item list (the default is 'auto'). See positioning system of Beampy. width : int or float or None, optional Width of the group containing items (the default is None, which implies that the width is computed to fit the longest item width). item_style : {'bullet','number'} or str, optional Style of the item markers (the default theme sets this value to 'bullet', which implies that item marker decorator is a bullet). The bullet could be replaced by any string, including latex symbols. When `item_style`='number', the item makers is an increasing number to create an enumeration. item_spacing : int or float or str, optional Vertical spacing between items (the default theme sets this value to '+1cm'). `item_spacing` accepts the same values as Beampy `x` or `y`. item_indent : int or float or str, optional Horizontal item indent (the default theme sets this value to '0cm'). `item_indent` accepts the same values as Beampy `x` or `y`. item_color : str, optional Color of item marker (the default theme sets this value to doc._theme['title']['color']). Color could be given as svg-color-names or HTML color hex values (expl: #fffff for white). text_color : str, optional Color of the item texts (the default theme sets this value to doc._theme['text']['color']). Color could be given as svg-color-names or HTML color hex values (expl: #fffff for white). item_layers : (list of int or string) or None, optional Place items into layers to animate them (the default theme sets this value to None, which implies that all items are displayed on the same layer). The list should have the same length as the `items_list`. The item in `item_layers` list could refers to a given layer number, given as int, or use python list index syntax (like ':', ':-1', '3:') given as string. >>> itemize(['item1 on all layers', 'item2 on layer 1'], item_layers=[':',1]) ''' args = check_function_args(itemize, kwargs) number = 1 if args['width'] is not None: in_width = float(convert_unit(args['width'])) - float( convert_unit(args['item_indent'])) else: in_width = float(document._width) - float( convert_unit(args['item_indent'])) if args['item_layers'] is not None: if len(items_list) != len(args['item_layers']): raise ValueError( 'Length of item_layers is not the same as the length of items_list' ) with group(width=args['width'], x=args['x'], y=args['y']) as groupitem: for i, the_item in enumerate(items_list): if args['item_style'] == 'bullet': item_char = r'$\bullet$' elif args['item_style'] == 'number': item_char = str(number) + r'.' number += 1 else: item_char = args['item_style'] # Add color item_char = color_text(item_char, args['item_color']) the_item = color_text(the_item, args['text_color']) if i == 0: t = text(item_char + r' ' + the_item, x=args['item_indent'], y=0, width=in_width) else: t = text(item_char + r' ' + the_item, x=args['item_indent'], y=args['item_spacing'], width=in_width) # Add layers to item if args['item_layers'] is not None: layer = args['item_layers'][i] if isinstance(layer, str): eval('t[%s]' % layer) else: t[args['item_layers'][i]] return groupitem