Gauche で IE を制御する (ことが出来たらよかったのだけど)

プログラミング言語 Scheme を利用する人のなかには Scheme 自体がどうこうではなく SICP を読み進めるためという人も少なくない割合でいるようだ。 SICP のコードはそれなりに仕様に沿っているのでだいたいの処理系で動くし、そうでなくてもささいな修正で動くのだけれど、例外的に画像を扱う部分については仮の語彙群を用意してそれを土台にする形で記述されている。

では、処理系として Gauche を使うのであればグラフィックスを扱う方法はどんなものがあるだろうか。 グラフィック関連の拡張パッケージを見ると、 OpenGLGTKSDL などのバインディングが存在するので、それらを導入するのが手っ取り早い方法だ。 しかし、バインディングであるからには元となるライブラリを導入しなければならないのが Windows 環境では少しばかり面倒くさい。 また、それぞれのライブラリはそれぞれの理念に基いた API 設計になっているので、これらに馴染めずに他の選択肢が欲しいという人もいるだろう。

そこで私は考えた。 近頃であればフロントエンドにはウェブブラウザを利用するのは良い思い付きではないだろうか。 ちょうど良いことに、私が以前に作った Gauche-OLE を用いれば Internet Explorer を制御することは簡単である。

http://saito.hatenablog.jp/entry/2014/10/09/184445

JavaScript でならグラフィックを扱った経験がある人も多いだろうし、その API がそのまま Gauche で使えれば習熟もたやすい。

では実際に簡単な図形を書くプログラムを書いてみよう。

#!/usr/bin/env gosh
(use win.ole)

(define IE (make-ole "InternetExplorer.Application"))
(set! (~ IE 'Visible) #t)
(while (~ IE 'busy) (sys-sleep 1))
(IE 'Navigate "about:blank")
(define canvas (& IE 'Document & 'createElement "canvas"))
(set! (~ canvas 'height) 300)
(set! (~ canvas 'width) 400)

(& IE 'Document & 'body & 'appendChild canvas)

(define context (canvas 'getContext "2d"))
(context 'beginPath)
(context 'moveTo 30 10)
(context 'lineTo 45 50)
(context 'lineTo 5 50)
(set! (~ context 'lineWidth) 5)
(set! (~ context 'strokeStyle) "black")
(context 'closePath)
(context 'stroke)
(set! (~ context 'fillStyle) "red")

(context 'fillRect 20 40 50 100)
(context 'arc 70 45 30 0 6 #f)
(context 'fill)
(ole-release!)

しかし、どういうわけか canvas に対する描画が fillRect しか機能していない。

f:id:SaitoAtsushi:20150729001801p:plain

何を間違ったのか検証しようと同じ意味のコードを JScript で書いたみた。

var IEApp = new ActiveXObject( "InternetExplorer.Application" );

IEApp.Visible = true;
while(IEApp.busy) sleep(1);

IEApp.Navigate("about:blank")
var canvas = IEApp.document.createElement('canvas');
canvas.height = 300;
canvas.width = 400;
IEApp.document.body.appendChild(canvas);
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(30, 10);
context.lineTo(45, 50);
context.lineTo(5, 50);
context.lineWidth = 5;
context.strokeStyle = 'black';
context.closePath();
context.stroke();
context.fillStyle = 'red';

context.fillRect(20,40,50,100);
context.arc(150,75,30,0,6,true);
context.fill();

IEApp = null;

JScript だと問題なく描画できている。

f:id:SaitoAtsushi:20150729001814p:plain

どうやら Gauche-OLE にはどこかにバグがあるようだ。 描画できていないのならともかく、 fillRect だけは機能しているのは不可解であることだ。

Document ID: d57552b62753e822ae842e82441547de