Пример #1
0
    def __init__(self, _format, diagram, filename=None, **kwargs):
        self.format = _format.upper()
        self.diagram = diagram
        self.fill = kwargs.get('fill', (0, 0, 0))
        self.badgeFill = kwargs.get('badgeFill', 'pink')
        self.filename = filename
        self.shadow = self.shadow_colors[self.format.upper()]

        if self.format == 'PNG' and kwargs.get('antialias'):
            self.scale_ratio = 2
        else:
            self.scale_ratio = 1

        self.drawer = imagedraw.create(self.format,
                                       self.filename,
                                       filters=['linejump'],
                                       scale_ratio=self.scale_ratio,
                                       **kwargs)

        self.metrics = self.create_metrics(kwargs.get('basediagram', diagram),
                                           drawer=self.drawer,
                                           fontmap=kwargs.get('fontmap'))
        if self.scale_ratio == 2:
            self.metrics = AutoScaler(self.metrics,
                                      scale_ratio=self.scale_ratio)

        self.drawer.set_canvas_size(self.pagesize())
        self.drawer.set_options(jump_radius=self.metrics.cellsize / 2)
Пример #2
0
    def __init__(self, _format, diagram, filename=None, **kwargs):
        self.format = _format.upper()
        self.diagram = diagram
        self.fill = kwargs.get('fill', (0, 0, 0))
        self.badgeFill = kwargs.get('badgeFill', 'pink')
        self.filename = filename
        self.shadow = self.shadow_colors[self.format.upper()]

        if self.format == 'PNG' and kwargs.get('antialias'):
            self.scale_ratio = 2
        else:
            self.scale_ratio = 1

        self.drawer = imagedraw.create(self.format, self.filename,
                                       filters=['linejump'],
                                       scale_ratio=self.scale_ratio,
                                       **kwargs)

        self.metrics = self.create_metrics(kwargs.get('basediagram', diagram),
                                           drawer=self.drawer, **kwargs)
        if self.scale_ratio == 2:
            self.metrics = AutoScaler(self.metrics,
                                      scale_ratio=self.scale_ratio)

        self.drawer.set_canvas_size(self.pagesize())
        self.drawer.set_options(jump_radius=self.metrics.cellsize / 2)
Пример #3
0
class DiagramDraw(object):
    shadow_colors = defaultdict(lambda: (0, 0, 0))
    shadow_colors['PNG'] = (64, 64, 64)
    shadow_colors['PDF'] = (144, 144, 144)

    def __init__(self, _format, diagram, filename=None, **kwargs):
        self.format = _format.upper()
        self.diagram = diagram
        self.fill = kwargs.get('fill', (0, 0, 0))
        self.badgeFill = kwargs.get('badgeFill', 'pink')
        self.filename = filename
        self.shadow = self.shadow_colors[self.format.upper()]

        if self.format == 'PNG' and kwargs.get('antialias'):
            self.scale_ratio = 2
        else:
            self.scale_ratio = 1

        self.drawer = imagedraw.create(self.format, self.filename,
                                       filters=['linejump'],
                                       scale_ratio=self.scale_ratio,
                                       **kwargs)

        self.metrics = self.create_metrics(kwargs.get('basediagram', diagram),
                                           drawer=self.drawer, **kwargs)
        if self.scale_ratio == 2:
            self.metrics = AutoScaler(self.metrics,
                                      scale_ratio=self.scale_ratio)

        self.drawer.set_canvas_size(self.pagesize())
        self.drawer.set_options(jump_radius=self.metrics.cellsize / 2)

    def create_metrics(self, *args, **kwargs):
        return DiagramMetrics(*args, **kwargs)

    @property
    def nodes(self):
        for node in self.diagram.traverse_nodes():
            if node.drawable:
                yield node

    @property
    def groups(self):
        for group in self.diagram.traverse_groups(preorder=True):
            if not group.drawable:
                yield group

    @property
    def edges(self):
        edges = self.diagram.traverse_edges(preorder=True)
        for edge in (e for e in edges if e.style != 'none'):
            yield edge

    def pagesize(self, scaled=False):
        if scaled:
            metrics = self.metrics
        else:
            metrics = self.metrics.original_metrics

        width = self.diagram.colwidth
        height = self.diagram.colheight
        return metrics.pagesize(width, height)

    def draw(self, **kwargs):
        # switch metrics object during draw backgrounds
        temp, self.metrics = self.metrics, self.metrics.original_metrics
        self._draw_background()
        self.metrics = temp

        if self.scale_ratio > 1:
            pagesize = self.pagesize(scaled=True)
            self.drawer.resizeCanvas(pagesize)

        self._draw_elements(**kwargs)

    def _draw_background(self):
        # Draw node groups.
        for group in self.groups:
            if group.shape == 'box':
                box = self.metrics.group(group).marginbox
                if group.href and self.format == 'SVG':
                    drawer = self.drawer.anchor(group.href)
                else:
                    drawer = self.drawer

                drawer.rectangle(box, fill=group.color, filter='blur')

        # Drop node shadows.
        for node in self.nodes:
            if node.color != 'none' and self.diagram.shadow_style != 'none':
                r = noderenderer.get(node.shape)

                shape = r(node, self.metrics)
                if node.href and self.format == 'SVG':
                    drawer = self.drawer.anchor(node.href)
                else:
                    drawer = self.drawer

                shape.render(drawer, self.format,
                             fill=self.shadow, shadow=True,
                             style=self.diagram.shadow_style)

    def _draw_elements(self, **kwargs):
        for node in self.nodes:
            self.node(node, **kwargs)

        for edge in self.edges:
            self.edge(edge)

        for edge in self.edges:
            self.edge_label(edge)

        for group in self.groups:
            if group.shape == 'line':
                box = self.metrics.group(group).marginbox
                self.drawer.rectangle(box, fill='none', outline=group.color,
                                      style=group.style, thick=group.thick)

        for node in self.groups:
            self.group_label(node, **kwargs)

    def node(self, node, **kwargs):
        r = noderenderer.get(node.shape)
        shape = r(node, self.metrics)
        if node.href and self.format == 'SVG':
            drawer = self.drawer.anchor(node.href)
        else:
            drawer = self.drawer

        shape.render(drawer, self.format, fill=self.fill,
                     badgeFill=self.badgeFill)

    def group_label(self, group):
        m = self.metrics.group(group)
        font = self.metrics.font_for(group)

        if group.label and not group.separated:
            self.drawer.textarea(m.grouplabelbox, group.label, font=font,
                                 fill=group.textcolor)
        elif group.label:
            self.drawer.textarea(m.corebox, group.label, font=font,
                                 fill=group.textcolor)

    def edge(self, edge):
        metrics = self.metrics.edge(edge)

        radius = (edge.radius if edge.radius is not None else
                  self.diagram.edge_radius)

        for line in metrics.shaft.polylines:
            self.line(self.drawer, line, radius, fill=edge.color,
                      thick=edge.thick, style=edge.style, jump=True)

        for head in metrics.heads:
            if edge.hstyle in ('generalization', 'aggregation'):
                self.drawer.polygon(head, outline=edge.color, fill='white')
            else:
                self.drawer.polygon(head, outline=edge.color, fill=edge.color)

    @staticmethod
    def line(drawer, line, radius, **kwargs):
        if radius <= 0 or len(line) <= 2:
            drawer.line(line, **kwargs)
            return

        if "jump" in kwargs:
            kwarc = kwargs.copy()
            del(kwarc["jump"])
        else:
            kwarc = kwargs

        sign = lambda n: 0 if n == 0 else (1 if n > 0 else -1)

        def get_vector(p1, p2):
            # Return tuple represents vector of p1->p2
            #    [0:1] Unit vector
            #    [2]   Length
            #    [3]   Direction("u"p, "d"own, "f"orward, "b"ackward)
            # p1, p2 must be XY
            v1, v2 = p2.x - p1.x, p2.y - p1.y
            if v1 == 0:
                return 0, sign(v2), abs(v2), "d" if v2 > 0 else "u"
            elif v2 == 0:
                return sign(v1), 0, abs(v1), "f" if v1 > 0 else "b"
            else:   # Irregular :Neither horizontal nor vertical
                return 0, 0, 0, "?"

        st, ed = line[:2]
        for next in line[2:]:
            v1, v2 = get_vector(st, ed), get_vector(ed, next)
            rad = min(v1[2], v2[2], radius)
            if rad == 0:
                drawer.line((st, ed), **kwargs)
                st = ed
            else:
                # Draw streight line.
                ed2 = ed.shift(rad * v1[0] * -1, rad * v1[1] * -1)
                drawer.line((st, ed2), **kwargs)

                # Draw quater arc
                box = list(ed) * 2
                if v1[3] == "f" or v2[3] == "b":
                    box[0] -= 2 * rad
                else:
                    box[2] += 2 * rad
                if v1[3] == "d" or v2[3] == "u":
                    box[1] -= 2 * rad
                else:
                    box[3] += 2 * rad

                dir = v1[3] + v2[3]
                if dir in ("db", "fu"):
                    r1, r2 = 0, 90
                elif dir in ("bu", "df"):
                    r1, r2 = 90, 180
                elif dir in ("uf", "bd"):
                    r1, r2 = 180, 270
                else:
                    r1, r2 = 270, 360

                drawer.arc(Box(*box), r1, r2, **kwarc)

                st = ed.shift(rad * v2[0], rad * v2[1])
            ed = next

        # Draw last streight line
        drawer.line((st, ed), **kwargs)

    def edge_label(self, edge):
        if edge.label:
            metrics = self.metrics.edge(edge)

            font = self.metrics.font_for(edge)
            self.drawer.textarea(metrics.labelbox, edge.label, font=font,
                                 fill=edge.textcolor, outline=self.fill)

    def save(self, size=None):
        return self.drawer.save(self.filename, size, self.format)
Пример #4
0
class DiagramDraw(object):
    shadow_colors = defaultdict(lambda: (0, 0, 0))
    shadow_colors['PNG'] = (64, 64, 64)
    shadow_colors['PDF'] = (144, 144, 144)

    def __init__(self, _format, diagram, filename=None, **kwargs):
        self.format = _format.upper()
        if self.format == 'TIKZ':
            self.drawer = imagedraw.create(self.format,
                                           filename,
                                           diagram=diagram,
                                           **kwargs)
            # monkey patch to omit DiagramDraw logic
            self.draw = self.drawer.draw
            self.save = self.drawer.save
            return

        self.diagram = diagram
        self.fill = kwargs.get('fill', (0, 0, 0))
        self.badgeFill = kwargs.get('badgeFill', 'pink')
        self.filename = filename
        self.shadow = self.shadow_colors[self.format.upper()]

        if self.format == 'PNG' and kwargs.get('antialias'):
            self.scale_ratio = 2
        else:
            self.scale_ratio = 1

        self.drawer = imagedraw.create(self.format,
                                       self.filename,
                                       filters=['linejump'],
                                       scale_ratio=self.scale_ratio,
                                       **kwargs)

        self.metrics = self.create_metrics(kwargs.get('basediagram', diagram),
                                           drawer=self.drawer,
                                           fontmap=kwargs.get('fontmap'))
        if self.scale_ratio == 2:
            self.metrics = AutoScaler(self.metrics,
                                      scale_ratio=self.scale_ratio)

        self.drawer.set_canvas_size(self.pagesize())
        self.drawer.set_options(jump_radius=self.metrics.cellsize / 2)

    def create_metrics(self, *args, **kwargs):
        return DiagramMetrics(*args, **kwargs)

    @property
    def nodes(self):
        for node in self.diagram.traverse_nodes():
            if node.drawable:
                yield node

    @property
    def groups(self):
        for group in self.diagram.traverse_groups(preorder=True):
            if not group.drawable:
                yield group

    @property
    def edges(self):
        edges = self.diagram.traverse_edges(preorder=True)
        for edge in (e for e in edges if e.style != 'none'):
            yield edge

    def pagesize(self, scaled=False):
        if scaled:
            metrics = self.metrics
        else:
            metrics = self.metrics.original_metrics

        width = self.diagram.colwidth
        height = self.diagram.colheight
        return metrics.pagesize(width, height)

    def draw(self, **kwargs):
        # switch metrics object during draw backgrounds
        temp, self.metrics = self.metrics, self.metrics.original_metrics
        self._draw_background()
        self.metrics = temp

        if self.scale_ratio > 1:
            pagesize = self.pagesize(scaled=True)
            self.drawer.resizeCanvas(pagesize)

        self._draw_elements(**kwargs)

    def _draw_background(self):
        # Draw node groups.
        for group in self.groups:
            if group.shape == 'box':
                box = self.metrics.group(group).marginbox
                if group.href and self.format == 'SVG':
                    drawer = self.drawer.anchor(group.href)
                else:
                    drawer = self.drawer

                drawer.rectangle(box, fill=group.color, filter='blur')

        # Drop node shadows.
        for node in self.nodes:
            if node.color != 'none' and self.diagram.shadow_style != 'none':
                r = noderenderer.get(node.shape)

                shape = r(node, self.metrics)
                if node.href and self.format == 'SVG':
                    drawer = self.drawer.anchor(node.href)
                else:
                    drawer = self.drawer

                shape.render(drawer,
                             self.format,
                             fill=self.shadow,
                             shadow=True,
                             style=self.diagram.shadow_style)

    def _draw_elements(self, **kwargs):
        for node in self.nodes:
            self.node(node, **kwargs)

        for edge in self.edges:
            self.edge(edge)

        for edge in self.edges:
            self.edge_label(edge)

        for group in self.groups:
            if group.shape == 'line':
                box = self.metrics.group(group).marginbox
                self.drawer.rectangle(box,
                                      fill='none',
                                      outline=group.color,
                                      style=group.style,
                                      thick=group.thick)

        for node in self.groups:
            self.group_label(node, **kwargs)

    def node(self, node, **kwargs):
        r = noderenderer.get(node.shape)
        shape = r(node, self.metrics)
        if node.href and self.format == 'SVG':
            drawer = self.drawer.anchor(node.href)
        else:
            drawer = self.drawer

        shape.render(drawer,
                     self.format,
                     fill=self.fill,
                     badgeFill=self.badgeFill)

    def group_label(self, group):
        m = self.metrics.group(group)
        font = self.metrics.font_for(group)

        if group.label and not group.separated:
            self.drawer.textarea(m.grouplabelbox,
                                 group.label,
                                 font=font,
                                 fill=group.textcolor)
        elif group.label:
            self.drawer.textarea(m.corebox,
                                 group.label,
                                 font=font,
                                 fill=group.textcolor)

    def edge(self, edge):
        metrics = self.metrics.edge(edge)

        for line in metrics.shaft.polylines:
            self.drawer.line(line,
                             fill=edge.color,
                             thick=edge.thick,
                             style=edge.style,
                             jump=True)

        for head in metrics.heads:
            if edge.hstyle in ('generalization', 'aggregation'):
                self.drawer.polygon(head, outline=edge.color, fill='white')
            else:
                self.drawer.polygon(head, outline=edge.color, fill=edge.color)

    def edge_label(self, edge):
        if edge.label:
            metrics = self.metrics.edge(edge)

            font = self.metrics.font_for(edge)
            self.drawer.textarea(metrics.labelbox,
                                 edge.label,
                                 font=font,
                                 fill=edge.textcolor,
                                 outline=self.fill)

    def save(self, size=None):
        return self.drawer.save(self.filename, size, self.format)
Пример #5
0
class DiagramDraw(object):
    shadow_colors = defaultdict(lambda: (0, 0, 0))
    shadow_colors['PNG'] = (64, 64, 64)
    shadow_colors['PDF'] = (144, 144, 144)

    def __init__(self, _format, diagram, filename=None, **kwargs):
        self.format = _format.upper()
        self.diagram = diagram
        self.fill = kwargs.get('fill', (0, 0, 0))
        self.badgeFill = kwargs.get('badgeFill', 'pink')
        self.filename = filename
        self.shadow = self.shadow_colors[self.format.upper()]

        if self.format == 'PNG' and kwargs.get('antialias'):
            self.scale_ratio = 2
        else:
            self.scale_ratio = 1

        self.drawer = imagedraw.create(self.format, self.filename,
                                       filters=['linejump'],
                                       scale_ratio=self.scale_ratio,
                                       **kwargs)

        self.metrics = self.create_metrics(kwargs.get('basediagram', diagram),
                                           drawer=self.drawer,
                                           fontmap=kwargs.get('fontmap'))
        if self.scale_ratio == 2:
            self.metrics = AutoScaler(self.metrics,
                                      scale_ratio=self.scale_ratio)

        self.drawer.set_canvas_size(self.pagesize())
        self.drawer.set_options(jump_radius=self.metrics.cellsize / 2)

    def create_metrics(self, *args, **kwargs):
        return DiagramMetrics(*args, **kwargs)

    @property
    def nodes(self):
        for node in self.diagram.traverse_nodes():
            if node.drawable:
                yield node

    @property
    def groups(self):
        for group in self.diagram.traverse_groups(preorder=True):
            if not group.drawable:
                yield group

    @property
    def edges(self):
        edges = self.diagram.traverse_edges(preorder=True)
        for edge in (e for e in edges if e.style != 'none'):
            yield edge

    def pagesize(self, scaled=False):
        if scaled:
            metrics = self.metrics
        else:
            metrics = self.metrics.original_metrics

        width = self.diagram.colwidth
        height = self.diagram.colheight
        return metrics.pagesize(width, height)

    def draw(self, **kwargs):
        # switch metrics object during draw backgrounds
        temp, self.metrics = self.metrics, self.metrics.original_metrics
        self._draw_background()
        self.metrics = temp

        if self.scale_ratio > 1:
            pagesize = self.pagesize(scaled=True)
            self.drawer.resizeCanvas(pagesize)

        self._draw_elements(**kwargs)

    def _draw_background(self):
        # Draw node groups.
        for group in self.groups:
            if group.shape == 'box':
                box = self.metrics.group(group).marginbox
                if group.href and self.format == 'SVG':
                    drawer = self.drawer.anchor(group.href)
                else:
                    drawer = self.drawer

                drawer.rectangle(box, fill=group.color, filter='blur')

        # Drop node shadows.
        for node in self.nodes:
            if node.color != 'none' and self.diagram.shadow_style != 'none':
                r = noderenderer.get(node.shape)

                shape = r(node, self.metrics)
                if node.href and self.format == 'SVG':
                    drawer = self.drawer.anchor(node.href)
                else:
                    drawer = self.drawer

                shape.render(drawer, self.format,
                             fill=self.shadow, shadow=True,
                             style=self.diagram.shadow_style)

    def _draw_elements(self, **kwargs):
        for node in self.nodes:
            self.node(node, **kwargs)

        for edge in self.edges:
            self.edge(edge)

        for edge in self.edges:
            self.edge_label(edge)

        for group in self.groups:
            if group.shape == 'line':
                box = self.metrics.group(group).marginbox
                self.drawer.rectangle(box, fill='none', outline=group.color,
                                      style=group.style, thick=group.thick)

        for node in self.groups:
            self.group_label(node, **kwargs)

    def node(self, node, **kwargs):
        r = noderenderer.get(node.shape)
        shape = r(node, self.metrics)
        if node.href and self.format == 'SVG':
            drawer = self.drawer.anchor(node.href)
        else:
            drawer = self.drawer

        shape.render(drawer, self.format, fill=self.fill,
                     badgeFill=self.badgeFill)

    def group_label(self, group):
        m = self.metrics.group(group)
        font = self.metrics.font_for(group)

        if group.label and not group.separated:
            self.drawer.textarea(m.grouplabelbox, group.label, font=font,
                                 fill=group.textcolor)
        elif group.label:
            self.drawer.textarea(m.corebox, group.label, font=font,
                                 fill=group.textcolor)

    def edge(self, edge):
        metrics = self.metrics.edge(edge)

        for line in metrics.shaft.polylines:
            self.drawer.line(line, fill=edge.color, thick=edge.thick,
                             style=edge.style, jump=True)

        for head in metrics.heads:
            if edge.hstyle in ('generalization', 'aggregation'):
                self.drawer.polygon(head, outline=edge.color, fill='white')
            else:
                self.drawer.polygon(head, outline=edge.color, fill=edge.color)

    def edge_label(self, edge):
        if edge.label:
            metrics = self.metrics.edge(edge)

            font = self.metrics.font_for(edge)
            self.drawer.textarea(metrics.labelbox, edge.label, font=font,
                                 fill=edge.textcolor, outline=self.fill)

    def save(self, size=None):
        return self.drawer.save(self.filename, size, self.format)