def test_fontmap_empty_config(self): config = StringIO(u("")) fmap = FontMap(config) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(None, font1.path) self.assertEqual(11, font1.size) element = FontElement('sansserif', 11) font2 = fmap.find(element) self.assertEqual(font1.familyname, font2.familyname) self.assertEqual(font1.path, font2.path) self.assertEqual(font1.size, font2.size) element = FontElement('sansserif-normal', 11) font3 = fmap.find(element) self.assertEqual(font1.familyname, font3.familyname) self.assertEqual(font1.path, font3.path) self.assertEqual(font1.size, font3.size) # non-registered familyname element = FontElement('my-sansserif-normal', 11) font4 = fmap.find(element) self.assertEqual(font1.familyname, font4.familyname) self.assertEqual(font1.path, font4.path) self.assertEqual(font1.size, font4.size)
def test_fontmap_switch_defaultfamily(self): _config = u("[fontmap]\nserif-bold: %s\n") % self.fontpath[0] config = StringIO(_config) fmap = FontMap(config) font1 = fmap.find() self.assertEqual('sansserif-normal', font1.familyname) self.assertEqual(None, font1.path) self.assertEqual(11, font1.size) fmap.set_default_fontfamily('serif-bold') font2 = fmap.find() self.assertEqual('serif-bold', font2.familyname) self.assertEqual(self.fontpath[0], font2.path) self.assertEqual(11, font2.size) fmap.set_default_fontfamily('fantasy-italic') font3 = fmap.find() self.assertEqual('fantasy-italic', font3.familyname) self.assertEqual(None, font3.path) self.assertEqual(11, font3.size) fmap.fontsize = 20 font4 = fmap.find() self.assertEqual('fantasy-italic', font4.familyname) self.assertEqual(None, font4.path) self.assertEqual(20, font4.size)
def create_fontmap(options): fontmap = FontMap(options.fontmap) if fontmap.find().path is None or options.font: fontpath = detectfont(options) fontmap.set_default_font(fontpath) return fontmap
def test_fontmap_none_config(self): fmap = FontMap() font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(None, font1.path) self.assertEqual(11, font1.size)
def test_fontmap_with_nonexistence_fontpath(self): _config = u("[fontmap]\nserif: unknown_file\n") config = StringIO(_config) fmap = FontMap(config) font1 = fmap.find() self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(None, font1.path) self.assertEqual(11, font1.size)
def _create_fontmap(fontmap, font): """ Inspired from :epkg:`blockdiag` source file (*_bootstrap.py*). """ from blockdiag.utils.fontmap import FontMap fontmap = FontMap(fontmap) if fontmap.find().path is None or font: fontpath = _detectfont(font) fontmap.set_default_font(fontpath) return fontmap
def test_fontmap_using_fontalias(self): _config = (u("[fontmap]\nserif-bold: %s\n") + u("[fontalias]\ntest = serif-bold\n")) % self.fontpath[0] config = StringIO(_config) fmap = FontMap(config) element = FontElement('test', 20) font1 = fmap.find(element) self.assertEqual('serif-bold', font1.familyname) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(20, font1.size)
def test_fontmap_with_capital_character(self): _config = u("[fontmap]\nCapitalCase-sansserif: %s\n") % \ self.fontpath[0] config = StringIO(_config) fmap = FontMap(config) element = FontElement('CapitalCase-sansserif', 11) font1 = fmap.find(element) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual('capitalcase-sansserif-normal', font1.familyname) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size)
def test_fontmap_with_nodefault_fontentry(self): _config = u("[fontmap]\nserif: %s\n") % self.fontpath[0] config = StringIO(_config) fmap = FontMap(config) font1 = fmap.find() self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(None, font1.path) self.assertEqual(11, font1.size) element = FontElement('serif', 11) font2 = fmap.find(element) self.assertEqual('serif', font2.generic_family) self.assertEqual(self.fontpath[0], font2.path) self.assertEqual(font1.size, font2.size) element = FontElement('fantasy', 20) font3 = fmap.find(element) self.assertEqual('sans-serif', font3.generic_family) self.assertEqual(None, font3.path) self.assertEqual(20, font3.size)
def test_fontmap_duplicated_fontentry2(self): # this testcase is only for python2.6 or later if sys.version_info > (2, 6): _config = u("[fontmap]\nsansserif: %s\nsansserif-normal: %s\n") % \ (self.fontpath[0], self.fontpath[1]) config = StringIO(_config) fmap = FontMap(config) font1 = fmap.find() self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[1], font1.path) self.assertEqual(11, font1.size)
def test_fontmap_duplicated_fontentry1(self): _config = u("[fontmap]\nsansserif: %s\nsansserif: %s\n") % \ (self.fontpath[0], self.fontpath[1]) config = StringIO(_config) if sys.version_info[0] == 2: fmap = FontMap(config) font1 = fmap.find() self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[1], font1.path) self.assertEqual(11, font1.size) else: import configparser with self.assertRaises(configparser.DuplicateOptionError): FontMap(config)
def test_fontmap_duplicated_fontentry1(self): _config = u("[fontmap]\nsansserif: %s\nsansserif: %s\n") % \ (self.fontpath[0], self.fontpath[1]) config = StringIO(_config) if sys.version_info[0] == 2: fmap = FontMap(config) font1 = fmap.find() self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[1], font1.path) self.assertEqual(11, font1.size) else: import configparser with self.assertRaises(configparser.DuplicateOptionError): FontMap(config)
def test_fontmap_by_file(self): tmp = tempfile.mkstemp() _config = u("[fontmap]\nsansserif: %s\nsansserif-bold: %s\n") % \ (self.fontpath[0], self.fontpath[1]) fp = os.fdopen(tmp[0], 'wt') fp.write(_config) fp.close() fmap = FontMap(tmp[1]) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size) os.unlink(tmp[1])
def test_fontmap_by_file(self): tmp = tempfile.mkstemp() _config = "[fontmap]\nsansserif: %s\nsansserif-bold: %s\n" % \ (self.fontpath[0], self.fontpath[1]) fp = os.fdopen(tmp[0], 'wt') fp.write(_config) fp.close() fmap = FontMap(tmp[1]) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size) os.unlink(tmp[1])
def test_fontmap_including_bom_by_file(self): tmp = tempfile.mkstemp() _config = (u("[fontmap]\nsansserif: %s\n") + u("sansserif-bold: %s\n")) % \ (self.fontpath[0], self.fontpath[1]) try: fp = os.fdopen(tmp[0], 'wb') fp.write(_config.encode('utf-8-sig')) fp.close() fmap = FontMap(tmp[1]) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size) finally: os.unlink(tmp[1])
def test_fontmap_including_bom_by_file(self): tmp = tempfile.mkstemp() _config = ("[fontmap]\nsansserif: %s\n" + "sansserif-bold: %s\n") % \ (self.fontpath[0], self.fontpath[1]) try: fp = os.fdopen(tmp[0], 'wb') fp.write(_config.encode('utf-8-sig')) fp.close() fmap = FontMap(tmp[1]) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size) finally: os.unlink(tmp[1])
def test_fontmap_normal_config(self): _config = u("[fontmap]\nsansserif: %s\nsansserif-bold: %s\n") % \ (self.fontpath[0], self.fontpath[1]) config = StringIO(_config) fmap = FontMap(config) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size) element = FontElement('sansserif', 11) font2 = fmap.find(element) self.assertEqual(font1.familyname, font2.familyname) self.assertEqual(font1.path, font2.path) self.assertEqual(font1.size, font2.size) element = FontElement('sansserif-normal', 11) font3 = fmap.find(element) self.assertEqual(font1.familyname, font3.familyname) self.assertEqual(font1.path, font3.path) self.assertEqual(font1.size, font3.size) element = FontElement('sansserif-bold', 11) font4 = fmap.find(element) self.assertEqual('sansserif-bold', font4.familyname) self.assertEqual(self.fontpath[1], font4.path) self.assertEqual(font1.size, font4.size) element = FontElement(None, None) font5 = fmap.find(element) self.assertEqual(font1.familyname, font5.familyname) self.assertEqual(font1.path, font5.path) self.assertEqual(font1.size, font5.size) element = object() font6 = fmap.find(element) self.assertEqual(font1.familyname, font6.familyname) self.assertEqual(font1.path, font6.path) self.assertEqual(font1.size, font6.size)
def test_fontmap_normal_config(self): _config = "[fontmap]\nsansserif: %s\nsansserif-bold: %s\n" % \ (self.fontpath[0], self.fontpath[1]) config = StringIO(_config) fmap = FontMap(config) font1 = fmap.find() self.assertTrue(font1) self.assertEqual('sans-serif', font1.generic_family) self.assertEqual(self.fontpath[0], font1.path) self.assertEqual(11, font1.size) element = FontElement('sansserif', 11) font2 = fmap.find(element) self.assertEqual(font1.familyname, font2.familyname) self.assertEqual(font1.path, font2.path) self.assertEqual(font1.size, font2.size) element = FontElement('sansserif-normal', 11) font3 = fmap.find(element) self.assertEqual(font1.familyname, font3.familyname) self.assertEqual(font1.path, font3.path) self.assertEqual(font1.size, font3.size) element = FontElement('sansserif-bold', 11) font4 = fmap.find(element) self.assertEqual('sansserif-bold', font4.familyname) self.assertEqual(self.fontpath[1], font4.path) self.assertEqual(font1.size, font4.size) element = FontElement(None, None) font5 = fmap.find(element) self.assertEqual(font1.familyname, font5.familyname) self.assertEqual(font1.path, font5.path) self.assertEqual(font1.size, font5.size) element = object() font6 = fmap.find(element) self.assertEqual(font1.familyname, font6.familyname) self.assertEqual(font1.path, font6.path) self.assertEqual(font1.size, font6.size)
class PADImageDraw(SVGImageDraw): def __init__(self, *args, **kwargs): super(PADImageDraw, self).__init__(*args, **kwargs) self.fontmap = FontMap() self.fontmap.set_default_font('/Library/Fonts/Hiragino Sans GB W3.otf') self.font = self.fontmap.find() def if_block(self, x, y, stmt): width, height = self.statement(x + 1, y, stmt.body) textbox = box(x, y, height=height + 0.25).shift(y=NODE_HEIGHT / 3) shape = (textbox.topleft, textbox.topright, textbox.right.shift(x=-32), textbox.bottomright, textbox.bottomleft, textbox.topleft) self.line(shape, fill='black') self.textarea(textbox, "".join(stmt.test), self.font, fill='black') self.link(x, textbox.top.y) if stmt.orelse == []: height += 1 else: w, h = self.statement(x + 1, y + height, stmt.orelse) width = max(width, w) height += h self.link(x, textbox.bottom.y) return (width + 1, height) def while_block(self, x, y, stmt): textbox = box(x, y) self.rectangle(textbox, outline='black', fill='white') self.textarea(textbox, "".join(stmt.test), self.font, fill='black') self.line( (textbox.topleft.shift(x=12), textbox.bottomleft.shift(x=12)), fill='black') self.link(x, textbox.right.y) width, height = self.statement(x + 1, y, stmt.body) return (width + 1, height) def for_block(self, x, y, stmt): textbox = box(x, y) label = "for %s in %s" % ("".join(stmt.target), "".join(stmt.iter)) self.rectangle(textbox, outline='black', fill='white') self.textarea(textbox, label, self.font, fill='black') self.line( (textbox.topleft.shift(x=12), textbox.bottomleft.shift(x=12)), fill='black') self.link(x, textbox.right.y) width, height = self.statement(x + 1, y, stmt.body) return (width + 1, height) def render(self, tree): return self.statement(0, 0, tree.body) def statement(self, x, y, statements): height = 0 width = 0 for stmt in statements: if isinstance(stmt, str): w, h = self.process(x, y + height, stmt) elif isinstance(stmt, ast.If): w, h = self.if_block(x, y + height, stmt) elif isinstance(stmt, ast.While): w, h = self.while_block(x, y + height, stmt) elif isinstance(stmt, ast.For): w, h = self.for_block(x, y + height, stmt) else: w, h = (0, 0) height += h width = max(width, w) self.baseline(x, y, height) return (width, height) def process(self, x, y, text): textbox = box(x, y) self.rectangle(textbox, outline='black', fill='white') self.textarea(textbox, text, self.font, fill='black') return (1, 1) def baseline(self, x, y, height): start = box(x, y).shift(y=-SPAN_HEIGHT / 3) end = box(x, y + height - 1).shift(y=SPAN_HEIGHT / 3) self.line((start.topleft, end.bottomleft), fill='black') def link(self, x, py): start = XY(box(x, 0).right.x, py) end = XY(box(x + 1, 0).left.x, py) self.line((start, end), fill='black')
class DiagramMetrics(object): cellsize = cellsize edge_layout = 'normal' node_padding = 4 line_spacing = 2 shadow_offset = XY(3, 6) page_margin = XY(0, 0) page_padding = [0, 0, 0, 0] node_width = cellsize * 16 node_height = cellsize * 5 span_width = cellsize * 8 span_height = cellsize * 5 def __init__(self, diagram, drawer=None, fontmap=None): self.drawer = drawer if diagram.node_width is not None: self.node_width = diagram.node_width if diagram.node_height is not None: self.node_height = diagram.node_height if diagram.span_width is not None: self.span_width = diagram.span_width if diagram.span_height is not None: self.span_height = diagram.span_height if fontmap is not None: self.fontmap = fontmap else: self.fontmap = FontMap() if diagram.page_padding is not None: self.page_padding = diagram.page_padding if diagram.edge_layout is not None: self.edge_layout = diagram.edge_layout # setup spreadsheet sheet = self.spreadsheet = SpreadSheetMetrics(self) nodes = [n for n in diagram.traverse_nodes() if n.drawable] node_width = self.node_width for x in range(diagram.colwidth): widths = [n.width for n in nodes if n.xy.x == x] if widths: width = max(n or node_width for n in widths) sheet.set_node_width(x, width) node_height = self.node_height for y in range(diagram.colheight): heights = [n.height for n in nodes if n.xy.y == y] if heights: height = max(n or node_height for n in heights) sheet.set_node_height(y, height) @property def original_metrics(self): return self def shift(self, x, y): metrics = copy.copy(self) metrics.spreadsheet = copy.copy(self.spreadsheet) metrics.spreadsheet.metrics = metrics metrics.page_margin = XY(x, y) return metrics def textsize(self, string, font=None, width=65535): return self.drawer.textsize(string, font, maxwidth=width) def node(self, node): renderer = noderenderer.get(node.shape) if hasattr(renderer, 'render'): return renderer(node, self) else: return self.cell(node) def cell(self, node, use_padding=True): return self.spreadsheet.node(node, use_padding) def group(self, group): return self.spreadsheet.node(group, use_padding=False) def edge(self, edge): if self.edge_layout == 'flowchart': if edge.node1.group.orientation == 'landscape': return FlowchartLandscapeEdgeMetrics(edge, self) else: return FlowchartPortraitEdgeMetrics(edge, self) else: if edge.node1.group.orientation == 'landscape': return LandscapeEdgeMetrics(edge, self) else: return PortraitEdgeMetrics(edge, self) def font_for(self, element): return self.fontmap.find(element) def pagesize(self, width, height): return self.spreadsheet.pagesize(width, height)
class DiagramMetrics(object): cellsize = cellsize edge_layout = 'normal' node_padding = 4 line_spacing = 2 shadow_offset = XY(3, 6) page_margin = XY(0, 0) page_padding = [0, 0, 0, 0] node_width = cellsize * 16 node_height = cellsize * 5 span_width = cellsize * 8 span_height = cellsize * 5 def __init__(self, diagram, drawer=None, fontmap=None): self.drawer = drawer if diagram.node_width is not None: self.node_width = diagram.node_width if diagram.node_height is not None: self.node_height = diagram.node_height if diagram.span_width is not None: self.span_width = diagram.span_width if diagram.span_height is not None: self.span_height = diagram.span_height if fontmap is not None: self.fontmap = fontmap else: self.fontmap = FontMap() if diagram.page_padding is not None: self.page_padding = diagram.page_padding if diagram.edge_layout is not None: self.edge_layout = diagram.edge_layout # setup spreadsheet sheet = self.spreadsheet = SpreadSheetMetrics(self) nodes = [n for n in diagram.traverse_nodes() if n.drawable] node_width = self.node_width for x in range(diagram.colwidth): widths = [n.width for n in nodes if n.xy.x == x] if widths: width = max(n or node_width for n in widths) sheet.set_node_width(x, width) node_height = self.node_height for y in range(diagram.colheight): heights = [n.height for n in nodes if n.xy.y == y] if heights: height = max(n or node_height for n in heights) sheet.set_node_height(y, height) @property def original_metrics(self): return self def shift(self, x, y): metrics = copy.copy(self) metrics.spreadsheet = copy.copy(self.spreadsheet) metrics.spreadsheet.metrics = metrics metrics.page_margin = XY(x, y) return metrics def textsize(self, string, font=None, width=65535): return self.drawer.textsize(string, font, maxwidth=width) def node(self, node): renderer = noderenderer.get(node.shape) if hasattr(renderer, 'render'): return renderer(node, self) else: return self.cell(node) def cell(self, node, use_padding=True): return self.spreadsheet.node(node, use_padding) def group(self, group): return self.spreadsheet.node(group, use_padding=False) def edge(self, edge): if self.edge_layout == 'flowchart': if edge.node1.group.orientation == 'landscape': return FlowchartLandscapeEdgeMetrics(edge, self) else: return FlowchartPortraitEdgeMetrics(edge, self) else: if edge.node1.group.orientation == 'landscape': return LandscapeEdgeMetrics(edge, self) else: return PortraitEdgeMetrics(edge, self) def font_for(self, element): return self.fontmap.find(element) def pagesize(self, width, height): return self.spreadsheet.pagesize(width, height)