canvas — ベクターグラフィクス

はじめに

 canvas モジュールはiOS上の非インタラクティブな2次元ベクターグラフィクスを生成するための関数群からなっています。シンプルなグラフィックやグラフ、ラインアートに適しています。

 全ての関数はPythonistaの出力画面の一枚のキャンパス上で動作します。この方法で生成される画像は,目下のところプログラムではできませんが、手動で、デバイスのフォトライブラリーに出力するか、クリップボードにコピーすることができます。

 座標系は左下の角を原点とした浮動小数型です。色は一般的には0.0から1.0の範囲の要素からなるRGB(A)で指定します。(注 RGB:赤、緑、青。A:透明度。0に近いほど透明)

 

赤い円を描く最小限の例は以下の通りです:

#画面いっぱいに赤で塗りつぶされた円を書く
import canvas
w = h = 512
canvas.set_size(w, h)
canvas.set_fill_color(1, 0, 0)
canvas.fill_ellipse(0, 0, w, h)

キャンバスの設定

 以下の関数は、キャンバス上の描画設定に使うことができます。一般的には、何を描くにせよ、まずset_size()を呼び出すことになります。

 描画の処理速度を改善したい場合には、描画開始前にbegin_updates()を呼び出し、描画終了後にend_updates() を呼び出すと良いでしょう。これらの関数により、描画の中間段階の表示を省いて処理速度を向上させ、一方で、描画のコーディング作業中は中間段階の結果を確認しやすくすることができます。

canvas.clear()

 canvasをクリアします。なお、全ての描画コマンド(例 変形、塗りつぶしなど)をリセットできるset_size()関数でもcanvasをクリアできます。

canvas.get_size()

 canvasのサイズを幅と高さのタプルの形で返します。

canvas.set_size(widthheight)

 canvasのサイズ(最小で16×16、最大で2048×2048)を設定し、全ての描画コマンド(例 変形、塗りつぶしなど)をリセットします。

canvas.begin_updates()

 描画コマンドのグループの先頭で呼び出します。描画結果はend_updates()を呼び出すまで画面には表示されません。この一連の手続きにより処理速度を著しく改善することができます。

canvas.end_updates()

 画面に表示せずメモリー上でバッファリングされていた描画結果を画面上に表示します。(begin_updates()を参照)

canvas.save_png(filename)

 現在のcanvas上の最新の描画内容をPNGファイルに保存します。

描画のパラメーターの設定

 以下の関数の使用は、全ての描画処理に影響を与えます。例えば、赤を指定してset_fill_color()を呼び出すと、別の色を設定するまで、その後に続くどのfill_rect()でも赤い長方形を描画することになります。

canvas.set_aa_enabled(flag)

 アンチエリアシングのオン/オフ

canvas.set_alpha(alpha)

 描画要素全体の透明度設定

(set_blend_mode()も参照)

canvas.set_blend_mode(mode)

 ブレンドモードの設定。末尾のBlend Modesのリストから一つを選択。

(set_alpha()も参照)

canvas.set_fill_color(rgb[, a])

 塗り潰し色の設定

canvas.set_line_width(width)

 線幅の設定

(set_stroke_color()も参照)

canvas.set_stroke_color(rgb[, a])

 縁取り(輪郭)色の設定

(set_line_width()も参照)

ベクター描画関数

 以下に示す関数はベクター形式のパス(ひと連なりの線や曲線からなる図形)や図形を描画するために使用します。

 canvasには常にadd_から始まる関数で操作できる「現在のパス」があります。add_line()add_curve()などを使って作った任意の複雑なパスを、fill_path()や draw_path()で塗り潰したり描画したりすることができます。線を塗り潰したい場合には、最初にclose_path()で線を閉じてください。パスの塗り潰しや描画をすると、「現在のパス」ではなくなります。

 

 下記の例はいくつかのパラメーターを設定して星の形を書くスクリプトです。

 

#Draw a star
import canvas
from math import sin, cos, pi

def draw_star(x, y, inner_r, outer_r, jags):
  canvas.move_to(w / 2, h / 2 + inner_r)
  for i in range(jags * 2):
    angle = (2 * pi / jags) * i / 2
    r = inner_r if i % 2 == 0 else outer_r
    x = w / 2 + r * sin(angle)
    y = h / 2 + r * cos(angle)
    canvas.add_line(x, y)
  canvas.close_path()
  canvas.set_line_width(3)
  canvas.draw_path()
w = h = 600
jags = 7 #Number of jags
inner_r = 120 #Inner radius
outer_r = 250 #Outer radius
canvas.set_size(w, h)
draw_star(w/2, h/2, inner_r, outer_r, jags)
canvas.add_curve(cp1xcp1ycp2xcp2yxy)

 パス上の現在の位置を始点とし、終点(x,y)との間に、制御点1(cp1x,cp1y)と制御点2(cp2x,cp2y)による3次元ベジェ曲線を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.add_ellipse(xywidthheight)

 現在のパスに長方形を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.add_line(xy)

 現在のパスに直線を追加します。

(begin_path()draw_path()fill_path()move_to()も参照)

canvas.add_quad_curve(cpxcpyxy)

 現在のパスの点(x,y)にコントロールポイント(cpx,cpy)による2次元ベジェ曲線を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.add_rect(xywidthheight)

 現在のパスに長方形を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.begin_path()

 新しいパスを開始します。add_line()add_rect()などを使用することによって、このパスに図形を加え、draw_path() やfill_path()で実際に描画します。

canvas.clip()

 表示済みの現在のパスに続いて描画される要素を消します。(表示済あらかじめの内容は消さない)

(begin_path()も参照)

canvas.close_path()

 現在のパスを閉じます。(最後の点から最初の点までを直線で結び閉じたパスにします)

(begin_path()draw_path()fill_path()も参照)

canvas.draw_ellipse(xywidthheight)

 パラメーターで指定された長方形の中に楕円を書きます。

(set_stroke_color()set_line_width()も参照)

canvas.draw_line(x1y1x2y2)

 2点を結ぶ直線を描きます。

(set_stroke_color()set_line_width()も参照)

canvas.draw_path()

 指定した線幅と色で、現在のpathを線で描画します。

(begin_path()fill_path()set_stroke_color()set_line_width()も参照)

canvas.draw_rect(xywidthheight)

 長方形を描画します。

(set_stroke_color()set_line_width()も参照)

canvas.fill_ellipse(xywidthheight)

 左下の頂点座標が(x,y)で、幅がwidth、高さがheightの長方形の中に楕円を描き、塗り潰します。

(draw_ellipse()も参照)

canvas.fill_path()

 現在のパスで囲まれた図形を、あらかじめ指定してある色で塗り潰します。

(begin_path()draw_path()set_fill_color()も参照)

canvas.fill_pixel(xy)

 (x,y)にあるピクセルを、あらかじめ指定してある色で塗り潰します。

canvas.fill_rect(xywidthheight)

 左下の頂点座標が(x,y)で、幅がwidth、高さがheightの長方形の領域を塗り潰します。

canvas.move_to(xy)

 「ペン」を点(x,y)へ移動します。

(add_line()も参照)

変形

 以下の変形機能を使うことにより、キャンバス上の「現在の変形マトリクス(Current Transformation Matrix:CTM)」を操作することができます。これは、例えば図形を回転させたり拡大縮小させたりするのに利用できます。キャンバスを変形すると、本質的には、後述する変化を及ぼすように座標系を変化させることになります。

 一時的にのみ変形を適用することが、便利なことがしばしばあります。これは、2つの関数save_gstate() とrestore_gstate()を使えば実現できます。save_gstate()は現在の変形のスナップショットを撮り、そして、(その他のグラフィックの状態を示す、塗り潰し色のようなパラメーターも)後入れ先出しのスタック領域で保存します。スタック領域に最後に保存した内容は、関数restore_gstate()を呼び出すことで復旧することができます。

 画像の状況を保存しないで、変形を完全にリセットしたい場合は、set_size()関数を使うことができます。

 下記は、数字を回転させた時計の文字盤を描画する例です。

# Draw a clock face
import canvas
from math import pi

canvas.set_size(600, 600)
canvas.set_fill_color(0.7, 0.7, 0.7)
canvas.fill_ellipse(0, 0, 600, 600)
canvas.set_fill_color(0, 0, 0)
canvas.fill_ellipse(290, 290, 20, 20)

for i in range(12):
    canvas.save_gstate()
    canvas.translate(300, 300)
    canvas.rotate(-2 * pi / 12.0 * i)
    canvas.set_fill_color(0, 0, 0)
    s = 40
    fnt = 'Helvetica-Bold'
    n = str(12 if i == 0 else i)
    w, h = canvas.get_text_size(n, fnt, s)
    canvas.draw_text(n, -w/2, 240, fnt, s)
    canvas.restore_gstate()
canvas.restore_gstate()

save_gstate()関数で最後に保存した状態を、現在の描画条件として設定します。

canvas.rotate(angle)

現在の変形マトリックスに回転を加えます。

(save_gstate()restore_gstate()も参照)

canvas.save_gstate()

 描画条件のスタック領域に、現在の描画条件(変形、選択色など)のコピーを保存します。

(restore_gstate()も参照)

canvas.scale(sxsy)

 現在の変形マトリックスに拡大縮小倍率(x軸方向にsx倍、y軸方向にsy倍)を設定します。

(save_gstate()restore_gstate()も参照)

canvas.translate(txty)

 現在の変形マトリックスの原点を(tx,ty)に設定します。

(save_gstate()restore_gstate()も参照)

ビットマップ画像の描画

 そもそもはベクターグラフィクスのためにデザインされたcanvasモジュールですが、sceneモジュールと同様の、ビットマップ描画のための関数もいくつかあります。名前の付けられた画像やクリップボードに保管されている現在のコンテンツを描画することができます。

 

canvas.draw_image(image_namexy[, widthheight])

 名前の付けられた画像を、(x,y)を左下にし、幅width、高さheightの長方形の中に描画します。

widthやheightを省略した場合には、イメージは元のサイズで描画されます。

canvas.draw_clipboard(xywidthheight)

 クリップボードに保管されている画像を、(x,y)を左下にし、幅width、高さheightの長方形の中に描画します。

canvas.get_clipboard_size()

 クリップボードに保管されている画像のサイズをポイント単位で、幅と高さのタプルの形で返します。ラティナディスプレイでは、2ピクセルを1ポイントとしてカウントします。クリップボードが空の場合には、(0,0)を返します。

canvas.get_image_size(image_name)

 名前がつけられている画像のサイズをポイント単位で、幅と高さのタプルの形で返します。ラティナディスプレイでは、2ピクセルを1ポイントとしてカウントします。名前に該当する画像がない場合には、(0,0)を返します。

文字の描画

 canvasモジュールには文字の描画とサイズを測る2つの簡便な関数があります。

 draw_text()で描画される文字の色は、前もって呼び出したset_fill_color()によって決まります。

 

canvas.draw_text(textxyfont_name='Helvetica'font_size=16.0)

 1行分のテキストを点(x,y)を左下端とする行として描画します。

canvas.get_text_size(textfont_name='Helvetica'font_size=16.0)

 draw_text()関数で描画した場合と同じように、文字の行のサイズを幅と高さのタプルの形式で返します。

ブレンド・モード

 set_blend_mode()では、以下のブレンド・モードを使用することができます。

canvas.BLEND_NORMAL
canvas.BLEND_MULTIPLY
canvas.BLEND_DIFFERENCE
canvas.BLEND_SCREEN
canvas.BLEND_OVERLAY
canvas.BLEND_DARKEN
canvas.BLEND_LIGHTEN
canvas.BLEND_COLOR_DODGE
canvas.BLEND_COLOR_BURN
canvas.BLEND_SOFT_LIGHT
canvas.BLEND_HARD_LIGHT
canvas.BLEND_DIFFERENCE
canvas.BLEND_EXCLUSION
canvas.BLEND_HUE
canvas.BLEND_SATURATION
canvas.BLEND_COLOR
canvas.BLEND_LUMINOSITY
canvas.BLEND_CLEAR
canvas.BLEND_COPY
canvas.BLEND_SOURCE_IN
canvas.BLEND_SOURCE_OUT
canvas.BLEND_SOURCE_ATOP
canvas.BLEND_DESTINATION_OVER
canvas.BLEND_DESTINATION_ATOP
canvas.BLEND_XOR
canvas.BLEND_PLUS_DARKER
canvas.BLEND_PLUS_LIGHTER