def flush(self): if not self.line: return metrics = [font.metrics() for x, word, font in self.line] maxascent = max([metric["ascent"] for metric in metrics]) baseline = self.cursor_y + 1.2 * maxascent for x, word, font in self.line: y = baseline - font.metrics("ascent") self.displaylist.append((x, y, word, font)) self.cursor_x = MARGIN self.line = [] maxdescent = max([metric["descent"] for metric in metrics]) self.cursor_y = baseline + 1.2 * maxdescent
def flush(self): if not self.line: return metrics = [font.metrics() for x, word, font in self.line] max_ascent = max([metric["ascent"] for metric in metrics]) baseline = self.cy + 1.2 * max_ascent for x, word, font in self.line: y = baseline - font.metrics("ascent") self.display_list.append((x, y, word, font)) self.cx = self.x self.line = [] max_descent = max([metric["descent"] for metric in metrics]) self.cy = baseline + 1.2 * max_descent
def token(self, tok): font = get_font(self.size, self.weight, self.style) if isinstance(tok, Text): for word in tok.text.split(): w = font.measure(word) if self.cursor_x + w > WIDTH - HSTEP: self.cursor_y += font.metrics("linespace") * 1.25 self.cursor_x = HSTEP self.display_list.append( (self.cursor_x, self.cursor_y, word, font)) self.cursor_x += w + font.measure(" ") elif tok.tag == "i": self.style = "italic" elif tok.tag == "/i": self.style = "roman" elif tok.tag == "b": self.weight = "bold" elif tok.tag == "/b": self.weight = "normal" elif tok.tag == "small": self.size -= 2 elif tok.tag == "/small": self.size += 2 elif tok.tag == "big": self.size += 4 elif tok.tag == "/big": self.size -= 4 elif tok.tag == "br": self.flush() elif tok.tag == "/p": self.flush() self.cursor_y += VSTEP # elif tok.tag == "h1": # self.size = 30 # elif tok.tag == "h2": # self.size = 26 # elif tok.tag == "h3": # self.size = 24 # elif tok.tag == "h4": # self.size = 18 elif tok.tag == "/blockqoute": self.flush() self.cursor_y += VSTEP elif tok.tag == "/h1": self.size = 16 self.flush() self.cursor_y += VSTEP elif tok.tag == "/h2": self.size = 16 self.flush() self.cursor_y += VSTEP elif tok.tag == "/h3": self.size = 16 self.flush() self.cursor_y += VSTEP elif tok.tag == "/h4": self.size = 16 self.flush() self.cursor_y += VSTEP
def __init__(self, x1, y1, text, font): self.top = y1 self.left = x1 self.text = text self.font = font self.bottom = y1 + font.metrics("linespace")
def __init__(self, x1, y1, text, font): self.x1 = x1 self.y1 = y1 self.text = text self.font = font self.y2 = y1 + font.metrics("linespace")
def text(self, text, offset=(0, 0), horiz=base.Renderer.LEFT, vert=base.Renderer.BOTTOM, *, angle=None, font=None, colour, width=None): anchors = { (self.TOP, self.LEFT): tkinter.NW, (self.TOP, self.CENTRE): tkinter.N, (self.TOP, self.RIGHT): tkinter.NE, (self.CENTRE, self.LEFT): tkinter.W, (self.CENTRE, self.CENTRE): tkinter.CENTER, (self.CENTRE, self.RIGHT): tkinter.E, (self.BOTTOM, self.LEFT): tkinter.SW, (self.BOTTOM, self.CENTRE): tkinter.S, (self.BOTTOM, self.RIGHT): tkinter.SE, } kw = dict() if angle is not None: kw.update(angle=angle) if font is None: font = self.defaultfont else: font = self.fonts[font] kw.update(font=font) colour = self._colour(colour) kw.update(fill=colour) (ox, oy) = offset ox *= self.scaling[0] oy *= self.scaling[1] if isinstance(text, str): kw.update(anchor=anchors[(vert, horiz)]) if width is not None: kw.update(width=width * self.scaling[0]) self.canvas.create_text(ox, oy, text=text, **kw) return length = sum(font.measure(seg["text"]) for seg in text) anchor = anchors[(vert, self.LEFT)] anchors = {self.LEFT: 0, self.CENTRE: 0.5, self.RIGHT: 1} pos = -length * anchors[horiz] (cos, sin) = self._rotation(angle or 0) for seg in text: x = ox + pos * cos y = oy + pos * sin text = seg["text"] self.canvas.create_text(x, y, text=text, anchor=anchor, **kw) newpos = pos + font.measure(text) if seg.get("overline"): linespace = font.metrics("linespace") anchors = {self.TOP: 0, self.CENTRE: 0.5, self.RIGHT: 1} linespace *= anchors[vert] dx = +linespace * sin dy = -linespace * cos nx = ox + dx + newpos * cos ny = oy + dy + newpos * sin self.canvas.create_line(x + dx, y + dy, nx, ny, fill=colour) pos = newpos
def height( self, font ): ''' simple call to tkfont metrics for the given font object params: tk font object return: height in pixels ''' return font.metrics("linespace")
def layout(tokens): display_list = [] fonts = { # (bold, italic) -> font (False, False): tkinter.font.Font(family="Times", size=16), (True, False): tkinter.font.Font(family="Times", size=16, weight="bold"), (False, True): tkinter.font.Font(family="Times", size=16, slant="italic"), (True, True): tkinter.font.Font(family="Times", size=16, weight="bold", slant="italic"), } x, y = 13, 13 bold, italic = False, False terminal_space = True for tok in tokens: font = fonts[bold, italic] if isinstance(tok, Text): if tok.text[0].isspace() and not terminal_space: x += font.measure(" ") words = tok.text.split() for i, word in enumerate(words): w = font.measure(word) if x + w > 787: x = 13 y += font.metrics('linespace') * 1.2 display_list.append((x, y, word, font)) x += w + (0 if i == len(words) - 1 else font.measure(" ")) terminal_space = tok.text[-1].isspace() if terminal_space and words: x += font.measure(" ") elif isinstance(tok, Tag): if tok.tag == "i": italic = True elif tok.tag == "/i": italic = False elif tok.tag == "b": bold = True elif tok.tag == "/b": bold = False elif tok.tag == "/p": terminal_space = True x = 13 y += font.metrics("linespace") * 1.2 + 16 return display_list
def render(self): self.canvas.delete("all") for x, y, word, font in self.display_list: if y > self.scroll + HEIGHT: continue if y + font.metrics("linespace") < self.scroll: continue self.canvas.create_text(x, y - self.scroll, text=word, font=font, anchor="nw")
def layout_close(node, state): x, y, bold, italic, terminal_space, display_list = state font = tkinter.font.Font(family="Times", size=16, weight="bold" if bold else "normal", slant="italic" if italic else "roman") if node.tag == "b": bold = False elif node.tag == "i": italic = False elif node.tag == "p" or node.tag == "br": terminal_space = True x = 13 y += font.metrics('linespace') * 1.2 + 16 else: pass return x, y, bold, italic, terminal_space, display_list
def word_to_widget(s, canvas, basefont='helvetica', fontsize=12, color='black', bold=False): """ Parse a node or leaf substring from a tree string, and return a corresponding widget. """ textwidgets = [] # Convert each piece of the word to a widget. for (italic, subscript, text) in parse_word(s): if not text: continue # Strip remaining backslashes text = re.sub(r'\\(.)', r'\1', text) # Decide on a font size = fontsize if subscript: size = size * 2 / 3 slant = italic and 'italic' or 'roman' weight = bold and 'bold' or 'normal' font = tkinter.font.Font(family=basefont, size=size, weight=weight, slant=slant) # Create the widget. textwidgets.append(TextWidget(canvas, text, font=font, color=color)) global metrics metrics[basefont, size, weight, slant] = font.metrics() # If there's only one widget, return it; otherwise, use a # sequencewidget to join them. Use align=bottom to make # subscripting work. if len(textwidgets) == 0: w = SpaceWidget(canvas, 1, 1) w.set_width(0) w.set_height(0) return w if len(textwidgets) == 1: return textwidgets[0] else: return SequenceWidget(canvas, align='bottom', space=-2, *textwidgets)
def text(self, node): font = self.font() if node.text[0].isspace() and not self.terminal_space: self.x += font.measure(" ") words = node.text.split() for i, word in enumerate(words): w = font.measure(word) if self.x + w > self.parent.content_left( ) + self.parent.content_width(): self.x = self.parent.content_left() self.y += font.metrics('linespace') * 1.2 self.dl.append(DrawText(self.x, self.y, word, font)) self.x += w + (0 if i == len(words) - 1 else font.measure(" ")) self.terminal_space = node.text[-1].isspace() if self.terminal_space and words: self.x += font.measure(" ")
def word_to_widget(s, canvas, basefont='helvetica', fontsize=12, color='black', bold=False): """ Parse a node or leaf substring from a tree string, and return a corresponding widget. """ textwidgets = [] # Convert each piece of the word to a widget. for (italic, subscript, text) in parse_word(s): if not text: continue # Strip remaining backslashes text = re.sub(r'\\(.)', r'\1', text) # Decide on a font size = fontsize if subscript: size = size*2/3 slant = italic and 'italic' or 'roman' weight = bold and 'bold' or 'normal' font = tkinter.font.Font(family=basefont, size=size, weight=weight, slant=slant) # Create the widget. textwidgets.append(TextWidget(canvas, text, font=font, color=color)) global metrics metrics[basefont, size, weight, slant] = font.metrics() # If there's only one widget, return it; otherwise, use a # sequencewidget to join them. Use align=bottom to make # subscripting work. if len(textwidgets) == 0: w = SpaceWidget(canvas, 1, 1) w.set_width(0) w.set_height(0) return w if len(textwidgets) == 1: return textwidgets[0] else: return SequenceWidget(canvas, align='bottom', space=-2, *textwidgets)
def layout_text(node, state): x, y, bold, italic, terminal_space, display_list = state font = tkinter.font.Font(family="Times", size=16, weight="bold" if bold else "normal", slant="italic" if italic else "roman") if node.text[0].isspace() and not terminal_space: x += font.measure(" ") words = node.text.split() for i, word in enumerate(words): w = font.measure(word) if x + w > 787: x = 13 y += font.metrics('linespace') * 1.2 display_list.append((x, y, word, font)) x += w + (0 if i == len(words) - 1 else font.measure(" ")) terminal_space = node.text[-1].isspace() if terminal_space and words: x += font.measure(" ") return x, y, bold, italic, terminal_space, display_list
def getTextHeight(self): f,s,b = self.config['font'] font = tkinter.font.Font(family=f, size=s) h = font.metrics("linespace") return h
def layout(tokens): display_list = [] x, y = 13, 13 bold, italic, uline = False, False, False family, size, color = "Times", 16, "black" pre = False terminal_space = True for tok in tokens: font = tkinter.font.Font(family=family, size=size, weight=("bold" if bold else "normal"), slant=("italic" if italic else "roman")) if isinstance(tok, Text): if tok.text[0].isspace() and not pre and not terminal_space: x += font.measure(" ") words = tok.text.split("\n") if pre else tok.text.split() for i, word in enumerate(words): w = font.measure(word) if x + w > 787 and not pre: x = 13 y += font.metrics('linespace') * 1.2 display_list.append(DL.Text(word, x, y, font, color)) if uline: yl = y + font.metrics("ascent") + 1 display_list.append(DL.Line(x, yl, x + w, yl, color)) if pre: if i == len(words) - 1: x += w else: x = 13 y += font.metrics("linespace") * 1.2 else: x += w + (0 if i == len(words) - 1 else font.measure(" ")) terminal_space = tok.text[-1].isspace() if terminal_space and words and not pre: x += font.measure(" ") elif isinstance(tok, Tag): if tok.tag == "i": italic = True elif tok.tag == "/i": italic = False elif tok.tag == "b": bold = True elif tok.tag == "/b": bold = False elif tok.tag == "pre": family = "Courier New" pre = True elif tok.tag == "/pre": family = "Times" pre = False terminal_space = True x = 13 y += font.metrics("linespace") * 1.2 + 16 elif tok.tag == "a": color = "blue" uline = True elif tok.tag == "/a": color = "black" uline = False elif tok.tag == "h1": # Exercise 1 bold = True elif tok.tag == "/h1": bold = False terminal_space = True x = 13 y += font.metrics("linespace") * 1.2 + 16 elif tok.tag == "/p": terminal_space = True x = 13 y += font.metrics("linespace") * 1.2 + 16 return display_list
def get_text_size(text): font = UnscaledFont return font.measure(text), font.metrics("linespace")
def get_text_size(text, font_size): tkinter.Frame().destroy() font = tkinter.font.Font(family='Helvetica Neue', size=font_size) return (font.measure(text) + 10, font.metrics('linespace'))
def height(self): font = self.font() return (self.y + font.metrics('linespace') * 1.2) - self.parent.y
def get_height(self, font): return font.metrics("linespace")