blockdiag は サンプル のように 各ノードの形状を変化させることができます。
この各ノードの形状をレンダリングするプログラムが blockdiag レンダラ(blockdiag node renderer)です。 blockdiag レンダラは setuptools を利用したプラグイン構造になっているため、 標準のパーツでは物足りない場合に好きな形状を組み込むことができます。
ここでは blockdiag レンダラのサンプルである blockdiagcontrib-square を参考に、 プラグインの作り方を説明します。 blockdiagcontrib-square は正方形の形状を描画するためのサンプルレンダラです。
hg コマンドで blockdiagcontrib-square を取得しておくと参考になるでしょう。
% hg clone https://bitbucket.org/tk0miya/blockdiagcontrib-square/src
レンダラパッケージは以下のファイルで構成されます。
| ファイル名 | 概要 |
|---|---|
| README.txt | blockdiag レンダラの説明書です。 |
| bootstrap.py | buildout 構成ファイルです。 |
| buildout.cfg | buildout 構成ファイルです。 |
| setup.py | setuptools 用の設定ファイルです。 パッケージ名やプラグイン用の設定を行います。 |
| MANIFEST.in | パッケージング用の構成ファイルです。 |
| blockdiagcontrib/__init__.py | |
| blockdiagcontrib/square.py | blockdiag レンダラの本体です。 |
setup.py にはレンダラのパッケージ情報が記載されています。 必要に応じ適切な情報に書き換えてください。 主な書き換え箇所はパッケージ名(name)、作者の情報(author, author_email, url) です。
setup(
name='blockdiagcontrib-square',
version=version,
description='noderenderer plugin for blockdiag',
long_description=long_description,
classifiers=classifiers,
keywords=['diagram','generator'],
author='Takeshi Komiya',
author_email='i.tkomiya at gmail.com',
url='http://tk0miya.bitbucket.org/blockdiag/build/html/index.html',
license='PSL',
また、パッケージ名に合わせて entry_points も書き換えます。 (square を置き換える)
entry_points="""
[blockdiag_noderenderer]
square = blockdiagcontrib.square
""",
__init__() メソッドではノード描画の基本設定を行います。
| パラメータ名 | 意味 |
|---|---|
| node | 描画対象となるノードです。 blockdiag.element.DiagramNode のインスタンスです。 |
| metrix | 座標を決める際に利用するパラメータ情報です。 blockdiag.DiagramMetrix.DiagramMetrix のインスタンスです。 |
__init__() メソッドで設定できる項目はエッジの接点とテキスト描画領域の二つです。
テキストを描画する箇所を定義します。 self.textarea 配列に描画虜域の x1, y1, x2, y2 座標を格納します。 初期値はセル領域全体です。
参考:minidiamond や endpoint などのレンダラでは、 図形が小さいため描画領域を図形の外側に配置しています。
ノードの基本系である Box (長方形)から設定を変更する必要がない場合は、 特別に設定を行う必要はありません。 なお、__init__() メソッドを定義する場合は かならず super() 関数で親クラスの __init__() を呼び出す必要があります。
以下、blockdiagcontrib-square の説明。
def __init__(self, node, metrix=None):
# 初期化処理:かならず super() を呼ぶこと
super(Square, self).__init__(node, metrix)
# ノードの縦、横の短い辺を求める
# 図形を大きくするため、少しだけ(cellSize 分)大きくする
r = min(metrix.nodeWidth, metrix.nodeHeight) / 2 + metrix.cellSize / 2
# ノードの中心座標を求める
# 他にも左上、右上などの座標を調べることができます。
# (See blockdiag.DiagramMetrix.NodeMetrix)
pt = metrix.cell(node).center()
# 接点を設定する (配列は上、右、下、左の順)
self.connectors = [XY(pt.x, pt.y - r), # top
XY(pt.x + r, pt.y), # right
XY(pt.x, pt.y + r), # bottom
XY(pt.x - r, pt.y)] # left
# テキスト描画領域を設定する (正方形と同じ大きさに設定)
self.textbox = (pt.x - r, pt.y - r, pt.x + r, pt.y + r)
render_shape() メソッドではノードの描画を行います。
| パラメータ名 | 意味 |
|---|---|
| drawer | 描画エンジンです。 フォーマットにあわせて ImageDrawEx, SVGImageDraw, PDFImageDraw の いずれかが渡されます。 |
| format | 出力フォーマットです。’PNG’, ‘SVG’, ‘PDF’ のいずれかが渡されます。 |
| **kwargs | 描画パラメータです。
|
render_shape() メソッドでは渡されるパラメータによって、 以下のように動きを変える必要があります。
黒く塗りつぶされた図形を描画する必要がある
以下、blockdiagcontrib-square の説明。
def render_shape(self, drawer, format, **kwargs):
outline = kwargs.get('outline')
fill = kwargs.get('fill')
if kwargs.get('shadow'):
# 影を描画する
box = self.shift_shadow(self.textbox)
drawer.rectangle(box, fill=fill, outline=fill,
filter='transp-blur')
elif self.node.background:
# 背景画像がある場合は塗りつぶし→画像→外枠の順に描する
drawer.rectangle(self.textbox, fill=self.node.color,
outline=self.node.color)
drawer.loadImage(self.node.background, self.textbox)
drawer.rectangle(self.textbox, fill="none", outline=outline,
style=self.node.style)
else:
# 普通に描画する
drawer.rectangle(self.textbox, fill=self.node.color,
outline=outline, style=self.node.style)
setup() 関数ではレンダラのインストールを行います。 install_renderer() 関数にパッケージ名とレンダラクラスを渡します。
ここで登録した名称が .diag ファイルで指定される名称になります。
以下、blockdiagcontrib-square の説明。
def setup(self):
# square という名称でレンダラクラスを登録
# → hoge [shape = square] として利用可能になる
install_renderer('square', Square)
よく使われそうなレンダラは blockdiag と一緒に配布すると 他のユーザも幸せになれると思います。
素敵なレンダラを作った場合は @tk0miya に声をかけてください。
より深い情報が必要な場合は blockdiag に同梱されている レンダラの実装を参照してください。