JINZO Paintのプログラミング



  ここでは、これまでのプログラムミングでの苦労や工夫、まだまだ改善が必要なことなどを書いてみたいと思います。

1. 開発環境について

 開発環境は、以下の構成です。

  • ハード:
    • CPU : Pentium200MHz
    • メモリ: 96MByte
    • HDD : 8GByte
  • ソフト:
    • Windows NT 4.0 SP3
    • Vidual C++ 5.0
    • Vidual C++ 5.0 toolkit for WindowsCE
 後に、以下の構成に変更しました。
  • ハード:
    • CPU : MediaGX 200MHz (Pentium200MHz相当)
    • メモリ: 128MByte
    • HDD : 10GByte
  • ソフト:
    • Windows98
    • Vidual C++ 6.0
    • Vidual C++ 6.0 toolkit for WindowsCE
 JINZO Paint程度のプログラミングであれば、以下の程度のハードウエアでも十分かもしれません。
    • CPU : Pentium100MHz
    • メモリ: 64MByte
    • HDD : 4GByte

2. いざ、プログラミング

 WindowsCEの開発環境のウリは、VidualC++とWin32APIで、Win95/NTでのプログラムをほとんどそのまま持ってこれる、ということです。でも、Windows3.1/95/NTでプログラミング経験が無い私にはチンプンカンプン。いろいろ調べたり高価な本を購入したりしたところ、MFC(Microsoft Fundamental C++ library)という便利なC++ライブラリを使うか、低レベルなCの関数で泥くさいプログラムをするかの2通りがあることが分かりました。MFCを使えば楽チンらしいのですが、

  • MFC用の200KB近くあるDLLをユーザーのCE機にインストールしてもらう必要がある(たいていインストール済みらしいですが)
  • 実行ファイルのサイズが大きくなる(200KB弱の肥大化)
  • 細かいことが出来そうに無い
  • 速度の低下が心配
  • 私がC++を知らない(苦笑)

という理由から今回はMFCを使わず、しかもすべてC言語で行うことにしました。

 さて、方針は決まりましたが、一から自分で作るのは大変です。普通はスケルトンプログラムというサンプルプログラムを改造して作るのですが、VC++のスケルトンプログラムはどれも今ひとつ。途方に暮れていたのですが、神様のようなサイトがありました。TascalSoftさんのプログラミングコーナーに、スケルトンプログラムとTipsが満載。これからWinCEのプログラムに挑戦しようという人は必見です。

 プログラムを進める上でヘルプは多用するのですが、これもVC++はかなり使いにくい。例えば、とある関数のヘルプを検索すると同じ名前でWin95用とWinCE用の2種類があり、WinCE用のヘルプ情報をみるとWin95/NTの関数の差分しか書かれていない。つまり両方の情報を見比べないとWinCEでのプログラムは出来ないわけです。しかも、肝心な情報は英語だし...

 また、ヘルプは情報の体系化が散漫で、とある機能を実現する方法を調べたいとしても、それが何という関数で出来るのかが掴みづらい。そもそも、その機能自体が何という名前なのか分からない... 数万円もする開発環境としては、オソマツとしか言えません。

3. ピクセル操作

 直線などはOSのグラフィック関数を用いても描画出来ますが、複雑な機能を高速に行うためにはピクセル(ドット)単位の描画操作が必要です。つまり、あるピクセルに色を設定する機能、あるピクセルの色を取得する機能です。OSにもこの機能はありますが、お世辞にも高速ではありません。

 こんなときには、やはり先人の工夫を参考にさせてもらいましょう。伊藤さんが作成されたCaptCEという画像キャプチャプログラムのソースが公開されていますので、そこからノウハウをいただきました。このおかげで高速なピクセル操作が可能になりましたし、BMPファイルの操作方法も分かりました。

4. ペンイベントの謎

 E-55でプログラミングしていて困ったことです。

 ペンを液晶が面に押しつけて移動させることでフリー曲線を描画するとき、PenDownイベント、PenMoveイベント(複数)、PenUpイベントという一連の通知が来て、それぞれのイベントでの座標を直線で結んで実現します。ところが、E-55では途中でPenUpイベントとPenDownイベントが勝手に発生するという問題が発生しました。これだと、フリー曲線が途中で途切れてしまいますし、直線/四角/楕円ツールで始点でペンダウンして終点までペンを移動させている途中なのにペンアップのために 確定してしまいます。

 結局、ペンアップが発生しても一定時間以内にペンダウンが発生した場合はこのペンアップとペンダウンを無かったことにする処理を追加して解決しました。しかし、このせいで直線/四角/楕円ツールでのレスポンスが悪化してしまいました。

5. プルダウンメニューの▼マーク

 PsPCでは、横幅が240ドットしかないため、ボタンやメニューを安易に追加することは出来ません。『手書きメモ』のようなスライドメニューを採用するという手もありますし、実際に搭載したバージョンも作りましたが、どうしても個人的に好きになれませんでした。

 ところで、ルーペボタンのようにアイコンボタンを押すととプルダウンメニューが表示されるのは分かりやすくてよい方法だと思っているのですが、WinCEに用意されているプルダウンメニューでは▼マーク付きになってしまいます。いろいろ調べましたが、既成のプルダウンメニューから▼マーク無しにすることは無理だったので、普通のボタンを押されるとプルダウンメニューを自前で呼びだすことにしました。泥くさい解決方法ですが...

6. x86エミュレーション

 WinNT上でプログラム環境を揃えると、x86エミュレーションというパソコン上の動作環境でデバッグ出来ます。最初は結構便利に使っていたのですが、いろいろと機能を追加すると実機との動作と食い違いが起こるようになってきました。MIPS/SH3とx86とで#ifdefを用いてコードを別に書けば解決できたのかもしれないのですが、めんどくさいのでエミュレーションは使わず、すべて実機で開発することにしました。そんなわけで、WinNTからWin98に開発環境を移しています。

7. 塗りつぶし機能

 ドット絵を描くツールとしては、塗りつぶし機能は必須です。しかし信じられないことに、Win95/NT/CEには塗りつぶしのグラフィック機能が無い! 仕方なく自分でお手軽再帰ルーチンを組みましたが、やはりあっという間にスタックがあふれてハングアップ。途方に暮れていましたが、こんなときにはインターネットが便利ですね。塗りつぶし機能のプログラム方法が紹介されたWebサイトがありました。ここでは直線描画機能についても紹介されていましたので、それも参考にしました。

 塗りつぶし機能があると、いろいろと応用が効きます。たとえば、不定形カット&ペーストなど、簡単に作れてしまいます。

8. 線の描画

 初期のバージョンでは、線の描画ではOSの直線描画ルーチンを使用していました。1ドット幅の線ならば問題なかったのですが、太い線では問題がありました。OSの直線描画では始点・終点・太さを指定(その他にも色とか描画パターンとかも)します。その際、直線は長方形として描画されます。曲線は一連の座標による直線を結んで描画するため、これらの直線をOSの直線描画の長方形で描画すると、ギシャギシャになってしまうのです。


ギシャギシャな描線

 これを回避するために、複数の座標を直線で繋ぐOSの描画関数を使用しました。この関数で(現在の座標,1つ前の座標,2つ前の座標)を描画すると,繋ぎ目は綺麗に埋めて描画されるため滑らかな曲線となります。  しばらくはこの方法で描画していたのですが、ペンのスタイルということで、ある間引いたパターンでの線描画をサポートす機能を追加していると、描画速度が気になりはじめました。仮想画面をまずクリアし、OSの線描画関数を用いて間引き無しで描画し、その描画結果をスキャンして描画されたピクセルであればスタイルに応じて実画面に描画する、という処理でしたが、やはりオーバーヘッドが大きかったようです。


改善した描線

 現在は、スタイルを加味したペンの形状で点を描画(太ペンだと円を描画)するルーチンを連続して呼び出す方法にしています。これはこれで無駄が多いですが、OSの直線描画機能を使うよりも高速なようです。


改善した描線その2

9. カラー対応

 カラー対応のJINZO Paint 16色版を作る上でも、問題がありました。固定16色版はスムーズに作成できましたが、任意16色ということでパレット色を変更出来るようにするときのことです。

 WinCEではメニューボタンは固定16色なのです。ですから、色情報を変更してしまうと、その色をボタンに表示することは出来ません。結局、タイマイベントで数百ミリ秒毎にボタンの位置にその色で塗りつぶした正方形を直接描画することにしました。ただ、このままだとJINZO Paintを実行したまま他のアプリケーションをアクティブにした場合にもそのアプリケーションの上に描画してしまいますので、JINZO Paintがアクティブでなくなったら描画するのを止めるとか、複雑な制御が必要となりました。