1# -*- coding: utf-8 -*-2# Copyright 2011 Takeshi KOMIYA3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.1516from blockdiag.imagedraw.simplesvg import pathdata17from blockdiag.noderenderer import install_renderer18from blockdiag.noderenderer.base import NodeShape19from blockdiag.utils import XY, Box202122class RoundedBox(NodeShape):23 def render_shape(self, drawer, _, **kwargs):24 # draw background25 self.render_shape_background(drawer, **kwargs)2627 # draw outline28 box = self.metrics.cell(self.node).box29 if not kwargs.get('shadow'):30 if self.node.background:31 drawer.image(box, self.node.background)3233 self.render_shape_outline(drawer, **kwargs)3435 def render_shape_outline(self, drawer, **kwargs):36 m = self.metrics.cell(self.node)37 r = self.metrics.cellsize38 box = m.box3940 lines = [(XY(box[0] + r, box[1]), XY(box[2] - r, box[1])),41 (XY(box[2], box[1] + r), XY(box[2], box[3] - r)),42 (XY(box[0] + r, box[3]), XY(box[2] - r, box[3])),43 (XY(box[0], box[1] + r), XY(box[0], box[3] - r))]44 for line in lines:45 drawer.line(line, fill=self.node.linecolor, style=self.node.style)4647 r2 = r * 248 arcs = [(Box(box[0], box[1], box[0] + r2, box[1] + r2), 180, 270),49 (Box(box[2] - r2, box[1], box[2], box[1] + r2), 270, 360),50 (Box(box[2] - r2, box[3] - r2, box[2], box[3]), 0, 90),51 (Box(box[0], box[3] - r2, box[0] + r2, box[3]), 90, 180)]52 for arc in arcs:53 drawer.arc(arc[0], arc[1], arc[2],54 fill=self.node.linecolor, style=self.node.style)5556 def render_shape_background(self, drawer, **kwargs):57 fill = kwargs.get('fill')5859 m = self.metrics.cell(self.node)60 r = self.metrics.cellsize6162 box = m.box63 ellipses = [Box(box[0], box[1], box[0] + r * 2, box[1] + r * 2),64 Box(box[2] - r * 2, box[1], box[2], box[1] + r * 2),65 Box(box[0], box[3] - r * 2, box[0] + r * 2, box[3]),66 Box(box[2] - r * 2, box[3] - r * 2, box[2], box[3])]6768 for e in ellipses:69 if kwargs.get('shadow'):70 e = self.shift_shadow(e)71 if kwargs.get('style') == 'blur':72 drawer.ellipse(e, fill=fill, outline=fill,73 filter='transp-blur')74 else:75 drawer.ellipse(e, fill=fill, outline=fill)76 else:77 drawer.ellipse(e, fill=self.node.color,78 outline=self.node.color)7980 rects = [Box(box[0] + r, box[1], box[2] - r, box[3]),81 Box(box[0], box[1] + r, box[2], box[3] - r)]82 for rect in rects:83 if kwargs.get('shadow'):84 rect = self.shift_shadow(rect)85 if kwargs.get('style') == 'blur':86 drawer.rectangle(rect, fill=fill, outline=fill,87 filter='transp-blur')88 else:89 drawer.rectangle(rect, fill=fill, outline=fill)90 else:91 drawer.rectangle(rect, fill=self.node.color,92 outline=self.node.color)9394 def render_vector_shape(self, drawer, _, **kwargs):95 fill = kwargs.get('fill')9697 # create pathdata98 box = self.metrics.cell(self.node).box99 r = self.metrics.cellsize100101 if kwargs.get('shadow'):102 box = self.shift_shadow(box)103104 path = pathdata(box[0] + r, box[1])105 path.line(box[2] - r, box[1])106 path.ellarc(r, r, 0, 0, 1, box[2], box[1] + r)107 path.line(box[2], box[3] - r)108 path.ellarc(r, r, 0, 0, 1, box[2] - r, box[3])109 path.line(box[0] + r, box[3])110 path.ellarc(r, r, 0, 0, 1, box[0], box[3] - r)111 path.line(box[0], box[1] + r)112 path.ellarc(r, r, 0, 0, 1, box[0] + r, box[1])113114 # draw outline115 if kwargs.get('shadow'):116 if kwargs.get('style') == 'blur':117 drawer.path(path, fill=fill, outline=fill,118 filter='transp-blur')119 else:120 drawer.path(path, fill=fill, outline=fill)121 elif self.node.background:122 drawer.path(path, fill=self.node.color, outline=self.node.color)123 drawer.image(self.textbox, self.node.background)124 drawer.path(path, fill="none",125 outline=self.node.linecolor, style=self.node.style)126 else:127 drawer.path(path, fill=self.node.color,128 outline=self.node.linecolor, style=self.node.style)129130131def setup(self):132 install_renderer('roundedbox', RoundedBox)