示例#1
0
    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)
示例#2
0
    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)
示例#3
0
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
示例#4
0
    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)
示例#5
0
    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)
示例#6
0
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
示例#7
0
    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)
示例#8
0
    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)
示例#9
0
    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)
示例#10
0
    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)
示例#11
0
    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)
示例#12
0
    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)
示例#13
0
    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])
示例#14
0
    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])
示例#15
0
    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])
示例#16
0
    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])
示例#17
0
    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)
示例#18
0
    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)
示例#19
0
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')
示例#20
0
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)
示例#21
0
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)