Canvas画像は、ドキュメントビューアや可視化ツール、動的に計算されるアニメーションやゲームなどで、高いフレームレートで効率的に更新・表示できます。Canvas画像には、ARGB32形式の書き込み可能なピクセルバッファが付随しています。移植性を確保するため、この形式はすべてのプラットフォームで共通です。Emacsでサポートされている他の画像タイプとは異なり、Canvas画像は更新のたびに新しいEmacs Lispオブジェクトを作成する必要はありません。
:type canvas を用いた画像指定子は、例えば次のようにキャンバスを作成します。
(defvar my-canvas
'(image :type canvas
:id my-canvas
:data-width 800
:data-height 600))
画像指定オブジェクトは、(eq に対して)一意にキャンバス画像オブジェクトを識別します。プロパティ
:data-width、:data-height、および :id
は必須です。幅と高さはともに正の整数である必要があり、id はシンボルである必要があります。
キャンバスは、ARGB32データを固定小数点数のベクトルとして、あるいは:dataにユニバイト文字列として指定することで作成できます。また、:fileにARGB32データを含むファイルへのパスを指定することも可能です。さらに、create-imageでは以下のようにキャンバス画像を作成でき、その際、データは最初にファイルまたはベクトルから読み込まれます:
(setq my-file-canvas (create-image "/path/to/file"
'canvas nil
:data-width 800
:data-height 600))
(setq my-vec (make-vector (* 800 600) #xFFFF0000))
(setq my-vec-canvas (create-image my-vec
'canvas t
:data-width 800
:data-height 600))
寸法の値が変更された場合(すなわち :data-height または :data-width)、Emacs
は基盤となるピクセルバッファを自動的に調整し、キャンバスのサイズを変更します。
:scale、:margin、:relief、:transform-smoothing、:map
といったその他の画像プロパティもサポートされています。これらのプロパティの詳細については、画像記述子を参照してください。
キャンバスを表示するには、文字列またはオーバーレイの display プロパティとして指定してください:
(insert (propertize "#" 'display my-canvas)) (overlay-put some-overlay 'display my-canvas)
キャンバス画像オブジェクトが作成・表示された後は、canvas-refresh
を介して「リフレッシュ」することができます。
キャンバス image をリフレッシュし、画面上に更新します。オプション引数 reload-data が nil でない場合は、キャンバスを再描画する前に、画像指定から :data または file を再読み込みします。
以下のコードは、データやファイルを再読み込みすることでキャンバスを更新します。
;; Draw pixels (aset my-vec <index> <color>) ;; Reload and refresh canvas images (canvas-refresh my-vec-canvas 'reload-data)
ループ内でキャンバスを更新する際は、明示的に redisplay を呼び出す必要があります:
(setq canvas (create-image (make-vector (* 100 100) 0) 'canvas t :data-width 100 :data-height 100)) (insert (propertize "#" 'display canvas)) (dotimes (i (* 100 100)) (aset (plist-get (cdr canvas) :data) i #xFF) (canvas-refresh canvas 'reload-data) (redisplay))
ただし、タイマーやコマンドでキャンバスを更新する場合、タイマーやコマンドの実行後に redisplay
が暗黙的に呼び出されます。以下の例では、上記のキャンバスをタイマーによって1秒間に約30回更新します:
(let ((i 0)) (run-at-time nil 0.033 (lambda () (when (< i (* 100 100)) (aset (plist-get (cdr canvas) :data) i #xFF) (incf i) (canvas-refresh canvas 'reload-data)))))
Canvas画像は、ダイナミックモジュールを通じて操作や更新が可能です。詳細については、モジュールでのCanvas APIの使用を参照してください。