HTML5 Canvas API

HTML5 の勉強。
canvas というのを試してみた。

<!DOCTYPE html>
<html>
<head>
<meta charset=UTF-8>
<title>Canvas API</title>

<!-- StyleSeet -->
<style>
body {
    background-color:#c0c0c0;
}
#cvs {
    background-color:#ffffff;
    border:#00ffff 2px solid;
}
</style>

<script>
function draw(num) {
    /* GetDC */
    var ctx = document.getElementById("cvs").getContext("2d");
    /* Clear */
    //ctx.clearRect(0, 0, 400, 200);
    /* Save the Default Setting */
    var globalAlpha = ctx.globalAlpha;
    var fillStyle = ctx.fillStyle;
    /* Branch */
    switch(num) {
    case 0:
        break;
    case 1:
        /* Rectangle */
        var x = 200;
        var y = 20;
        ctx.globalAlpha = 0.3;
        for (var i=0; i<3; i++) {
            ctx.fillRect(x, y, 150, 100);
            x += 30;
            y += 5;
        }
        break;
    case 2:
        /* Circle */
        ctx.globalAlpha = 0.3;
        /* #1 Red */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(255, 0, 0)';
        ctx.arc(70, 45, 35, 0, Math.PI*2, false);
        ctx.fill();
        /* #2 Green */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(0, 255, 0)';
        ctx.arc(45, 95, 35, 0, Math.PI*2, false);
        ctx.fill();
        /* #3 Blue */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(0, 0, 255)';
        ctx.arc(95, 95, 35, 0, Math.PI*2, false);
        ctx.fill();
        break;
    case 3:
        /* Drop Shadow */
        var text = "homuhomu";
        ctx.font = "82px 'sans'";
        ctx.globalAlpha = 0.3;
        ctx.fillText(text, 5, 105);
        ctx.globalAlpha = 1.0;
        ctx.fillText(text, 0, 100);
        break;
    default:
        alert("Error!");
    }
    /* Write back */
    ctx.globalAlpha = globalAlpha;
    ctx.fillStyle = fillStyle;
}
</script>

</head>

<body onLoad="draw(0)">
<canvas id="cvs" width="400" height="200">canvas</canvas><br />
<input type="button" onclick="draw(1)" value="Rectangle">
<input type="button" onclick="draw(2)" value="Circle">
<input type="button" onclick="draw(3)" value="Drop Shadow">
</body>
</html>

なんだよコレ、デバイスコンテキストとほとんど変わらない。
いやオブジェクト化されているから GDI+ なのか、RGBA も利用できるし。

canvas のサンプルコードは検索で沢山見つかるけどグローバル設定を書き戻す処理を入れていない人が多すぎて唖然。
globalAlpha や fillStyle を変更したら元に戻さなければ後々まで引き継がれてしまうんですけど。
デバイスコンテキストではペンやブラシを使ったら元に戻すなんて Windows API をやった人なら常識だよね。
GDI とか全然知らない人ばかりなのだろうか。

てか WM_PAINT と InvalidateRect 関数のようなものはいらないのかな?
ちなみに GnomeShell や Aero では 3D になるからウインドウを重ねても消滅しない。
2D 状態を試すため VirtualBox 仮想マシンの Ubuntu で動かしてみる。

ウインドウを重ねても最小化しても描写が消えない、ココは GDI と少し違う。
どうやって描写状態を記憶しているかは解らないけどそういうこと。

てゆーかフォントのせいではみ出す、絶対値描写はコレが最大の欠点なんだよな…
私が WindowsForm や GtkFixed をバカにしているのは絶対値配置だからですし。
レイアウタ方式なら絶対にはみ出さない、HTML さえもレイアウタ方式だ。

上記コードは重ねるために FillRect していない。
この状態で Circle ボタンを複数回押してみる。

Alpha 値で薄くしても重ねてしまえば当然のように濃い色になる。
やはりボタンやイベントで描写する場合は clearRect 等で一度全体を塗りつぶす必要があるね。
上記コードの Clear 部コメントアウトを外せば一つづつ描写されるようになる。

つまり canvas 2d は GDI のようなものだと。
しかも JavaScript コードも GDI, GDI+ を勉強した人ならすぐ理解できる。
Windows SDK で何かを作れる人は色々試すと面白いかも。

Totem Alt key

凄くどうでもいいことを見つけた。

Totem 3.0.1 で音楽再生中に Opera をアクティブにしているとする。
すると数秒毎に Opera のメインメニューがドロップダウンする。
何だよコレ、又 Opera が変になったかと思って何回も再起動してしまったわい。

Firefox では何も起こらない、同じようなメニューなのに何故?
違いを調べた、Opera は Alt キーでメインメニューがドロップするんだね。
何年も Opera を利用しているのに今頃気がついた私って…

とにかく Totem が何かしているのは間違いないんだよな。
同じデコーダーを利用する Y901x で試しても何も起こらないもん。
ということはもしかして、xev を起動して調べる。

Totem は再生中は左右 Alt キーを約二十秒毎に押したり離したりしている。
しかもその時点のアクティブウインドウにシグナルをせっせと送っている。
何でこんな処理を入れているのだ?

スクリーンセーバー抑制を旧 Y901 と同じようにやっているのだろうか。
定期的に何かキーを押した「フリ」をして抑制する冗談みたいな方法である。
と思ったけど動画のみ抑制に変更しても結果は同じ、ポカミスの可能性もあるけど。
視覚効果も関係無かった、つかアクティブウインドウにシグナルを送る意味が不明。
ようするに、よくワカラン。

とにかく Totem で BGM を流しながら作業をする人は注意してください。
……….

いや、こんなカナル型ヘッドフォンを買ったのでテストしていて気づいたわけで。

シフト勤務が長引いているので夜中に Youtube をみる為用、なのに奮発してコレを。
使用感は Amazon の人達とまったく同じ、とにかく低音には文句の付けようが無い。
こもった感じはたしかにあるけど動画用なら迫力面でプラスに。

いや、YouTube で主に見るのは車やバイクの動画だったりするんですけど…

MP3 や AAC に圧縮した糞なはずの音楽もアレッと思うくらい聴けることにちょっと驚き。
BlackBerry に又音楽を入れてみようかな、音楽機能をまったく使っていないし。

Original Webkit Browser @ Fedora 15

HTML5 の勉強、その前に。
WebKit 自作ブラウザが不便すぎ、もう少しまともな形にしよう。

チョロミウム入れようかな、とも思うけど表示テスト以外で使わないだろうし。
テスト用なんだからとにかく最小限機能だけ付けて軽いほうがいいし。
しかし Fedora の Firefox は何故こんなに起動が遅いのやら…
だから Opera が手放せないんだよ、よく落ちるけど。

/usr/share/doc/pywebkitgtk-1.1.8/demos/browser.py
のコードはまだ GTK2, pywebkit のまま、でも参考にはなる。
本格的に作るならキャッシュ指定や Flash, JAVA の利用処理とかが必要になる。
今はワカンネエ。

WebKitGTK+ Reference Manual

仕様を決める、メニューはリロードだけあれば充分かな。
アドレスバーに打ち込んで Enter でも表示できるようにして。
HTML ファイルをドロップの受け入れは WebKit.WebView が勝手にやってくれる。
読み込んだらタイトルバーにタイトルを入れて、ロード中なんかも表示して。
後はリンク先をステータスバーに表示する、こんな仕様で充分だろう。

まてよ?
GtkApplication で動かす場合 Quit 処理はどうするんだろう?
Gtk.main() でのループではないので Gtk.main_quit() はおかしいよな。

GtkApplication

gtk_application_remove_window に自分のポインタを入れればいいってことかな。

def on_quit(self, widget, data=None):
    app = self.get_application()
    app.remove_window(self)

これで終了してくれた、やっぱり Delphi の TApplication もどきだね。
gtk_window_close(GtkWindow) 関数なんてものを用意すると勘違いする人が出そうだしこれでいいだろう。

とりあえず作ってみた。
タブを付けたいところだけどココでは最小限の IE6 スタイルで。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from gi.repository import WebKit, Gtk, Gio, Gdk

menu_xml = """<ui>
    <menubar name="MenuBar">
        <menu action="file">
            <menuitem action="reload"/>
            <separator/>
            <menuitem action="quit"/>
        </menu>
    </menubar>
</ui>"""

class WebKitWindow(Gtk.Window):
    """
        WebKit PyGi Version
        from Fedora 15 x86_64
    """
    def __init__(self):
        # Window
        Gtk.Window.__init__(self)
        self.resize(640, 480)
        self.set_title("WebKit")
        # GtkUIManager and GtkAccelGroup
        self.uimanager = Gtk.UIManager()
        accelgroup = self.uimanager.get_accel_group()
        self.add_accel_group(accelgroup)
        # GtkActionGroup
        self.actiongroup = Gtk.ActionGroup("seeme_menu")
        # GtkActionEntry
        self.ac = [ ("reload", Gtk.STOCK_REFRESH, "_Reload", "F5", "Reload", self.on_reload),
                    ("quit", Gtk.STOCK_QUIT, "_Quit", "<Control>Q", "Quit", self.on_quit),
                    ("file", None, "_File") ]
        self.actiongroup.add_actions(self.ac)
        self.uimanager.insert_action_group(self.actiongroup, 0)
        self.uimanager.add_ui_from_string(menu_xml)
        # menubar
        menubar = self.uimanager.get_widget("/MenuBar")
        # entry
        self.entry = Gtk.Entry()
        self.entry.connect("activate", self.on_entry_activate)
        # WebKit
        self.webview = WebKit.WebView()
        #self.webview.load_uri(HTML_URI)
        self.webview.connect("load-started", self.on_load_started)
        self.webview.connect("load-finished", self.on_load_finished)
        self.webview.connect("title-changed", self.on_title_changed)
        self.webview.connect("hovering-over-link", self.on_hovering_over_link)
        # ScrollWindow
        sw = Gtk.ScrolledWindow()
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        sw.add(self.webview)
        # statusbar
        self.statusbar = Gtk.Statusbar()
        # box
        vbox = Gtk.VBox()
        vbox.pack_start(menubar, False, True, 0)
        vbox.pack_start(self.entry, False, True, 0)
        vbox.pack_start(sw, True, True, 0)
        vbox.pack_start(self.statusbar, False, True, 0)
        self.add(vbox)
        self.show_all()

    def on_load_started(self, webview, frame):
        self.statusbar.push(0, "Loading...")

    def on_load_finished(self, webview, frame):
        self.statusbar.push(0, "")

    def on_title_changed(self, webview, frame, title):
        self.set_title("{0} - WebKit".format(title))
        self.entry.set_text(webview.get_uri())

    def on_hovering_over_link(self, webview, title, uri):
        if uri:
            self.statusbar.push(0, uri)
        else:
            self.statusbar.push(0, "")

    def on_entry_activate(self, entry):
        self.webview.load_uri(entry.get_text())

    def on_reload(self, widget, data=None):
        self.webview.reload()

    def on_quit(self, widget, data=None):
        app = self.get_application()
        app.remove_window(self)

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(
                self,
                application_id="apps.test.webkit",
                flags=Gio.ApplicationFlags.FLAGS_NONE)
        self.connect("activate", self.on_activate)
        
    def on_activate(self, data=None):
        l = self.get_windows()
        if l:
            return
        w = WebKitWindow()
        w.set_application(self)
    
if __name__ == "__main__":
    app = App()
    app.run(sys.argv)

リンク先をステータスバーに表示した後で消す方法に迷ったけど上記でイケた。
リンクをマウスカーソルが外れると uri に NULL がセットされて送られるようです。
GtkApplication 関連以外はほとんど PyGtk と同じでイケます。

どうでもいいけど。
GTK+ 関連のアクセスがドイツやスウェーデンといったヨーロッパからばかりなんだが…
アッチの google で検索してココがヒットするのも変な気分、どのくらい読解できるやら。
まあ私も GTK+ 関連は日本語では探さないんですけどね。

html5 Test

いいかげんに HTML5 の勉強をやろうとこんなムックを買ってきた。

月刊誌である日経ソフトウエアでの記事をまとめたものらしい。
ココの月刊誌自体は未だに WindowsForm だとか寒い記事ばかりだがムックはあなどれない。
私が普通にアプリを作れるようになったキッカケも以下のムックのおかげだ。
Windows徹底理解 | PaePoi
ヘタにぶ厚い解説本を買うよりムックのほうが不要な解説が少ない所がいいね。

記事のコードも以下から落として利用できるから楽チン。
ダウンロード – 日経ソフトウエア ダウンロード:ITpro

とりあえずイントロダクションを試す。
コードのダウンロードは 2011/01 なのね、最後のページに書いていた。
もう LHA 配布は消した方が…とにかく tr1101.zip を落として展開。

meta charset=”utf-8″ を推しておいて readme.txt は Shift-JIS とかヤメてくれ!
Linux では普通に開くと文字化けするっつーの、UTF-8 に BOM を付けていないのは評価する。
画像は自分で用意しなきゃダメか、まどかばかりじゃアレだからあずにゃんを用意した。

Opera で試したけどアニメーションしないんだが…
ってよく見たらこの CSS の -webkit-transition って WebKit 専用じゃんかよ。
何故か mozilla のページで見つかった。

CSS transitions – MDN

Opera は -o- Firefox は -moz- のプリフィクスが必要、IE はまだ無い。
Linux てか Fedora 上で試すから IE が使えないのでどうでもいいけど。

とにかく style.css に以下の感じで適所に追記する。

-webkit-transition: 0.2s linear;
-o-transition: 0.2s linear;
-moz-transition: 0.2s linear;

WebKit のブラウザは入れていないけどライブラリはあるから PyGI で作る。
PyGtk で作るのとほぼ同じでイケた、Gtk.PolicyType に気おつけて。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from gi.repository import WebKit, Gtk, Gio

# Rewrite Your HTML5 File URI
HTML_URI = "file:///home/sasakima-nao/html5/tr1101/index.html"

class WebKitWindow(Gtk.Window):
    """
        WebKit PyGi Version
        from Fedora 15 x86_64
    """
    def __init__(self):
        # Window
        Gtk.Window.__init__(self)
        self.resize(800, 480)
        self.set_title("My WebKit Window")
        # WebKit
        w = WebKit.WebView()
        w.load_uri(HTML_URI)
        # ScrollWindow
        sw = Gtk.ScrolledWindow()
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        # add
        sw.add(w)
        self.add(sw)
        self.show_all()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(
                self,
                application_id="apps.test.webkit",
                flags=Gio.ApplicationFlags.FLAGS_NONE)
        self.connect("activate", self.on_activate)
        
    def on_activate(self, data=None):
        l = self.get_windows()
        if l:
            return
        w = WebKitWindow()
        w.set_application(self)
    
if __name__ == "__main__":
    app = App()
    app.run(sys.argv)

上記と Firefox 6.0 と Opera 11.51 で index.html を表示

よしよし、ドレでもアニメーションするようになった。
Linux でも全然イケるようです。

Web

X86_64 Fedora 15 & Opera 11.50 & Flash 11 Beta で遊べた。
5 時間使って完成させたけどスクショ撮るの忘れた…
魔法少女まどか☆マギカのジグソーパズル | パズコレ 無料オンラインFLASHジグソーパズル ゲーム

どんだけ私はまどかが大好きなんだはともかく…
Web ブラウザのみで 5 時間も遊び続けられる時代になっちゃったんだな…
Python や GTK+ ではなく Flash を勉強すべきだったか…

http://www.google.com/pacman/

まだ遊べるんだ。
HTML5 ならこれからだから勉強はコッチ重視にしたいかも。
Web アプリって大量のデータを持っていないと意味が無いと思っていたのに。

さて工場にシフト出勤するか…