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 __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)
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)
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)
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)