Gjs で Cogl 描画

Gjs で Cogl を使った描画を試してみた。
Colg での描画関数に描画する Actor を指定する関数が無いので、適当に Class をでっち上げ、そこに描画するみたい。

ソースは以下のようになる。円弧の描画、直線の描画、長方形の描画、楕円の描画、そして、タートルグラフィックスによる描画を行った。
多角形 polygon 描画はよくわからない。。。

const Clutter = imports.gi.Clutter;
const Cogl = imports.gi.Cogl;
const Lang = imports.lang;

const CoglActor = new Lang.Class({
    Name: 'CoglActor',
    _init: function() {
        this.actor = new Clutter.Actor();
        this.actor.connect('paint', Lang.bind(this, this._paint));
    },
    _paint: function() {
        Cogl.set_source_color4ub(0, 255, 0, 255);

        Cogl.path_arc(25, 25, 20, 20, 0, 90);
        Cogl.path_stroke();

        Cogl.path_arc(75, 25, 20, 20, 270, 360);
        Cogl.path_fill();

        Cogl.path_line(110, 10, 140, 40);
        Cogl.path_stroke();

        Cogl.path_rectangle(160, 10, 190, 40);
        Cogl.path_stroke();

        Cogl.path_rectangle(10, 60, 40, 90);
        Cogl.path_fill();

        Cogl.path_round_rectangle(60, 60, 90, 90, 10, 1)
        Cogl.path_stroke();

        Cogl.path_round_rectangle(110, 60, 140, 90, 10, 1)
        Cogl.path_fill();

        Cogl.path_ellipse(175, 75, 20, 20);
        Cogl.path_stroke();

        Cogl.path_ellipse(25, 125, 20, 20);
        Cogl.path_fill();

        Cogl.path_set_fill_rule(Cogl.PathFillRule.NON_ZERO);
        Cogl.path_move_to(75, 100);
        Cogl.path_line_to(60, 150);
        Cogl.path_line_to(100, 120);
        Cogl.path_line_to(50, 120);
        Cogl.path_line_to(90, 150);
        Cogl.path_line_to(75, 100);
        Cogl.path_fill();

        Cogl.path_set_fill_rule(Cogl.PathFillRule.EVEN_ODD);
        Cogl.path_move_to(125, 100);
        Cogl.path_line_to(110, 150);
        Cogl.path_line_to(150, 120);
        Cogl.path_line_to(100, 120);
        Cogl.path_line_to(140, 150);
        Cogl.path_line_to(125, 100);
        Cogl.path_fill();
    }
});

Clutter.init(null);

let stage = Clutter.Stage.get_default();
stage.set_title("Cogl Test");
stage.set_size(200, 150);
stage.set_background_color(new Clutter.Color({red:0, blue:0, green:0, alpha:255}));
stage.connect('destroy', Clutter.main_quit);

let coglactor = new CoglActor();
stage.add_actor(coglactor.actor);

stage.show();
Clutter.main();

最初から説明すると、まず、Clutter と Cogl を使うので imports する。

const Clutter = imports.gi.Clutter;
const Cogl = imports.gi.Cogl;

クラスを作成するので、 lang を imports する。

const Lang = imports.lang;

CoglActor クラスを作る。Name で CoglActor を指定し、 new で呼び出される _init を設定する。また、 paint イベントを _paint に割り当てる。

_paint の関数では、最初に Cogl.set_source_color4ub() で色を設定する。
次に、 Cogl.path_arc() 、 Cogl.path_line() 、 Cogl.path_rectangle() 、 Cogl.path_round_rectangle() 、 Cogl.path_ellipse() 、 Cogl.path_move_to() 、 Cogl.path_line_to() などを使って図形データを設定し、 Cogl.path_stroke() 、 Cogl.path_stroke() で描画を完成させる。
Cogl.path_set_fill_rule() を使って Cogl.path_fill() の挙動を変更する。

const CoglActor = new Lang.Class({
    Name: 'CoglActor',
    _init: function() {
        this.actor = new Clutter.Actor();
        this.actor.connect('paint', Lang.bind(this, this._paint));
    },
    _paint: function() {
        Cogl.set_source_color4ub(0, 255, 0, 255);

        Cogl.path_arc(25, 25, 20, 20, 0, 90);
        Cogl.path_stroke();

        Cogl.path_arc(75, 25, 20, 20, 270, 360);
        Cogl.path_fill();

        Cogl.path_line(110, 10, 140, 40);
        Cogl.path_stroke();

        Cogl.path_rectangle(160, 10, 190, 40);
        Cogl.path_stroke();

        Cogl.path_rectangle(10, 60, 40, 90);
        Cogl.path_fill();

        Cogl.path_round_rectangle(60, 60, 90, 90, 10, 1)
        Cogl.path_stroke();

        Cogl.path_round_rectangle(110, 60, 140, 90, 10, 1)
        Cogl.path_fill();

        Cogl.path_ellipse(175, 75, 20, 20);
        Cogl.path_stroke();

        Cogl.path_ellipse(25, 125, 20, 20);
        Cogl.path_fill();

        Cogl.path_set_fill_rule(Cogl.PathFillRule.NON_ZERO);
        Cogl.path_move_to(75, 100);
        Cogl.path_line_to(60, 150);
        Cogl.path_line_to(100, 120);
        Cogl.path_line_to(50, 120);
        Cogl.path_line_to(90, 150);
        Cogl.path_line_to(75, 100);
        Cogl.path_fill();

        Cogl.path_set_fill_rule(Cogl.PathFillRule.EVEN_ODD);
        Cogl.path_move_to(125, 100);
        Cogl.path_line_to(110, 150);
        Cogl.path_line_to(150, 120);
        Cogl.path_line_to(100, 120);
        Cogl.path_line_to(140, 150);
        Cogl.path_line_to(125, 100);
        Cogl.path_fill();
    }
});

これ以降は、いつものmain関数ぽいものです。
Clutterを初期化し、Clutter.Stage型のオブジェクトを作り、タイトル、大きさ、そして色を設定し、'destroy'イベントに Clutter.main_quit() を割り当てます。

次に、先ほど作成した CoglActor クラスのオブジェクトを作成し、stageに追加します。

そして、stageを表示した後、Clutter.main でメインループに入ります。

Clutter.init(null);

let stage = Clutter.Stage.get_default();
stage.set_title("Cogl Test");
stage.set_size(200, 150);
stage.set_background_color(new Clutter.Color({red:0, blue:0, green:0, alpha:255}));
stage.connect('destroy', Clutter.main_quit);

let coglactor = new CoglActor();
stage.add_actor(coglactor.actor);

stage.show();
Clutter.main();

Cogl 描画ができるので、actorを回転させたり、描画した Cogle オブジェクトを Cogl.scale() で拡大縮小したり、Cogl.translate() で平行移動したり、Cogl.rotate()で回転したりできるようです。