clone

a browser-first diagram editor with live svg previews, local drafts and encrypted, accountless sharing

main
diagramzip / renderers / python / blockdiag-family / src / blockdiag / noderenderer / actor.py
actor.py 4.6K
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 __future__ import division1718from blockdiag.noderenderer import install_renderer19from blockdiag.noderenderer.base import NodeShape20from blockdiag.utils import XY, Box, Size212223class Actor(NodeShape):24 def __init__(self, node, metrics=None):25 super(Actor, self).__init__(node, metrics)2627 m = metrics.cell(node)28 if node.label:29 font = metrics.font_for(self.node)30 textsize = metrics.textsize(node.label, font)31 shortside = min(m.width, m.height - textsize.height)32 else:33 textsize = Size(0, 0)34 shortside = min(m.width, m.height)3536 r = self.radius = shortside // 8 # radius of actor's head37 self.center = metrics.cell(node).center3839 self.connectors[0] = XY(self.center.x, self.center.y - r * 9 // 2)40 self.connectors[1] = XY(self.center.x + r * 4, self.center.y)41 self.connectors[2] = XY(self.center.x,42 self.center.y + r * 4 + textsize.height)43 self.connectors[3] = XY(self.center.x - r * 4, self.center.y)4445 self.textbox = Box(m.left.x,46 self.center.y + r * 4,47 m.right.x,48 self.connectors[2].y)4950 def head_part(self):51 r = self.radius * 3 // 252 pt = self.metrics.cell(self.node).center.shift(y=-self.radius * 3)53 return Box(pt.x - r, pt.y - r, pt.x + r, pt.y + r)5455 def body_part(self):56 r = self.radius57 m = self.metrics.cell(self.node)5859 bodyC = m.center60 neckWidth = r * 2 // 3 # neck size61 arm = r * 4 # arm length62 armWidth = r63 bodyWidth = r * 2 // 3 # half of body width64 bodyHeight = r65 legXout = r * 7 // 2 # toe outer position66 legYout = bodyHeight + r * 367 legXin = r * 2 # toe inner position68 legYin = bodyHeight + r * 36970 return [XY(bodyC.x + neckWidth, bodyC.y - r * 2),71 XY(bodyC.x + neckWidth, bodyC.y - armWidth), # neck end72 XY(bodyC.x + arm, bodyC.y - armWidth),73 XY(bodyC.x + arm, bodyC.y), # right arm end74 XY(bodyC.x + bodyWidth, bodyC.y), # right body end75 XY(bodyC.x + bodyWidth, bodyC.y + bodyHeight),76 XY(bodyC.x + legXout, bodyC.y + legYout),77 XY(bodyC.x + legXin, bodyC.y + legYin),7879 XY(bodyC.x, bodyC.y + (bodyHeight * 2)), # body bottom center8081 XY(bodyC.x - legXin, bodyC.y + legYin),82 XY(bodyC.x - legXout, bodyC.y + legYout),83 XY(bodyC.x - bodyWidth, bodyC.y + bodyHeight),84 XY(bodyC.x - bodyWidth, bodyC.y), # left body end85 XY(bodyC.x - arm, bodyC.y),86 XY(bodyC.x - arm, bodyC.y - armWidth),87 XY(bodyC.x - neckWidth, bodyC.y - armWidth), # left arm end88 XY(bodyC.x - neckWidth, bodyC.y - r * 2)]8990 def render_shape(self, drawer, _, **kwargs):91 fill = kwargs.get('fill')9293 # draw body part94 body = self.body_part()95 if kwargs.get('shadow'):96 body = self.shift_shadow(body)97 if kwargs.get('style') == 'blur':98 drawer.polygon(body, fill=fill, filter='transp-blur')99 else:100 drawer.polygon(body, fill=fill)101 else:102 drawer.polygon(body, fill=self.node.color,103 outline=self.node.linecolor, style=self.node.style)104105 # draw head part106 head = self.head_part()107 if kwargs.get('shadow'):108 head = self.shift_shadow(head)109 if kwargs.get('style') == 'blur':110 drawer.ellipse(head, fill=fill, outline=self.node.linecolor,111 filter='transp-blur')112 else:113 drawer.ellipse(head, fill=fill, outline=self.node.linecolor)114 else:115 drawer.ellipse(head, fill=self.node.color,116 outline=self.node.linecolor, style=self.node.style)117118119def setup(self):120 install_renderer('actor', Actor)