サンプルXFCN GetPixpattern



ここですること:
 ・シンボルカードを理解し、ToolBox関数を登録する
 ・引数と変数の型について考える
 ・ハンドルを使ってみる

サンプルとして、矩形領域のグラフィックを取り込む XFCN を作ります。




 GetPix の例で、シンボルカードの話が出てきました。
 買ったままの CompileIt! では、ToolBox は一切使えないようになっています。ToolBox の利用は、それだけ危険を伴うものだからです。
 しかしせっかく CompileIt! を使うのであれば、ToolBox を指をくわえて見ている手はありません。爆弾を恐れず果敢にチャレンジしましょう!



(1)シンボルテーブルを眺める

 まず、シンボルテーブルに移動しましょう。
 CompileIt! メニューで「 options 」に移動すると、右上にシンボルテーブルのリストが現れます。CompileIt! のシンボルテーブルはいくつかのカテゴリに別れていて、CompileIt! 独自のもの、よく使われるもの、カラーに関するもの、などがそれぞれまとめられています。
 CompileIt Names for ToolBox Access     CompileIt! 独自のもの
 Useful ToolBox Commands & Functions    よく使われるルーチン
 ToolBox Variables & Fields             よく使われる ToolBox 変数とフィールド
 High-Level File Manager                ファイルマネージャ
 HyperCard 2 Names and CallBacks        HyperCard 2.0 コールバック
 Color QuickDraw Commands & Functions   カラーQDルーチン
 Print Manager Commands & Functions     プリントマネージャ
 Custom Symbol Edit                     シンボル編集
 SuperCard Commands & CallBacks         SuperCard コールバック
 取りあえず上から2行目をクリックして、「Useful ToolBox Commands & Functions」に移動してみましょう。左側にいくつかのボタン、右側に大きなスクロールフィールドがあります。

 右のフィールドには ToolBox のルーチン名や、フィールド名が並んでいます。これらを「シンボル」または「ネーム」と呼びます。シンボルは初期状態では一切使えないようになっていて、使うためには登録が必要です。これは誤用を避けるためです。登録は個々のルーチン毎に行ったり、スクリプト中で使っているものだけを登録したり、フィールド中の全てを一括登録したりすることが出来ます。また任意のものを登録から外すことも出来ます。
 左にあるボタン群はシンボルを登録したり解除したりするものです。
取りあえず左にあるボタンには触らずに、シンボルテーブルの中を散策してみましょう。

 画面下中央にある一組のボタンに注目して下さい。これはシンボルテーブル内を移動するボタンです。左の三角ボタンで前のシンボルテーブル、右の三角ボタンで次のシンボルテーブルに移動します。シンボルテーブルの最後まで行くと、最初のシンボルテーブルに戻るようになっています。これを使って、どんなシンボルテーブルがあるのか、一通り眺めてみて下さい。



(2)シンボルを登録する

 「Useful ToolBox Commands & Functions」に戻ってきて下さい。ここには一般によく使われる ToolBox ルーチンが並んでいます。
左に並んでいるボタン群を見てみましょう。
 Mark Used Names   スクリプト中で使用しているものにマークする
 Add All           全てのシンボルを登録する
 Remove All        全てのシンボルを登録解除する
 Add Marked        マークされているシンボルを登録する
 Remove            マークされているシンボルを登録解除する
 Clear Marks       全てのマークを消す
 よほどメモリが逼迫している(例えばハイパカに 1250k しか割り当てていない)のでなければ、ここのシンボルは全て登録してしまっていいでしょう。「Add All」ボタンをクリックして下さい。
 以後、ここにあるシンボル名は ToolBox ルーチンと認識され、これを用いたスクリプトでは、ToolBox が呼び出されるようになります。つまり、爆弾を出す準備が出来たということです(笑)

 「Add All」ボタンをクリックした時に、「重複しているものがあるよ」というダイアログが出ることがあります。
 これは、例えば left という ToolBox フィールドを登録した時に出るダイアログで、以後、left というキーワードは ToolBox の用語として用いられることを警告したものです。ダイアログが出ると同時にフィールドの該当個所にダイアモンドマークが付けられます。
 もしも left を HyperTalk の left として使いたいのであれば、ダイアモンドマークの付いたシンボルを探し出してクリックし、マークを付けて、Remove ボタンをクリックすれば元に戻ります。
 また、重複するシンボルがある場合は一番下のボタン Clear Marks が Mark Only Dupes に変わるので、このボタンをクリックすれば重複しているシンボル全てにマークを付けられます。あとは Remove ボタンで全ての重複シンボルを登録解除することが出来ます。
 このへんは HyperTalk と ToolBox を共存させるための苦肉の策と言えそうです。

 画面下中央にある一組のボタンのうち、左のボタンをクリックして、「CompileIt Names for ToolBox Access」に移動して下さい。ここには CompileIt! 独自のシンボルが登録されています。
 ここにあるシンボルは Inside Macintosh には載っていません。CompileIt! の解釈する HyperTalk と、ToolBox の解釈できるデータ型との仲介役を務めるルーチンが集められています。
 ここのシンボルも全て必要になりますので、「Add All」ボタンで全て登録します。

 同様にして、「ToolBox Variables & Fields」、「High-Level File Manager」、「HyperCard 2 Names and CallBacks」、「Color QuickDraw Commands & Functions」の各シンボルテーブルも全て登録して下さい。
 つまり「SuperCard Commands & CallBacks」以外は全てこれから必要になるということです。

 HyperTalk と ToolBox で用語が重複する問題は多少やっかいです。ひとつのスクリプト内ではどちらかひとつしか使えないことになります。と言っても、今のところ私は困ったことはありませんが。
 シンボルリストの中を一通り眺めて、どんなものが ToolBox シンボルとして使われているかを見て置いて下さい。自分のスクリプトが思うようにコンパイルされなかった時や、意外なコンパイルエラーが出た時、疑わしいキーワードをすぐ見つけられるようになります。



(3)GetPixPattern

 矩形領域を指定して一気にグラフィックパターンを文字列に変換するXです。簡単な応用問題ですね。どうです。まんま HyperTalk でしょう。
-- CompileIt! script
function GetPixPattern thePt, width, height
  --
  if ( thePt is "?" ) or ( paramCount() = 0 ) then
    return "GetPixPattern( topLeft, width, height ) "
  end if
  if thePt is "!" then
    return "GetPixPattern 1.0"
  end if
  --
  put (item 1 of thePt) + 0 into L   -- 座標から left を取り出す
  put (item 2 of thePt) + 0 into T   -- 座標から top を取り出す
  put T + height - 1 into B          -- top に 高さを加えて bottom を作る
  put L + width - 1 into R           -- left に 幅を加えて right を作る
  --
  put "" into theResult
  --
  repeat with V = T to B
    repeat with H = L to R
      if GetPixel(H,V) is true then  -- ToolBox 関数
        put "1" after theResult
      else
        put "0" after theResult
      end if
    end repeat
    put return after theResult
  end repeat
  --
  delete last char of theResult
  return theResult
  --
end GetPixPattern
 まずスクリプト中の「 +0 」に注目して下さい。
 HyperTalk は「変数の型」を持たない言語ですが、ToolBox プログラミングでは、この「型」が重要な意味を持ちます。
 型には大まかに分けて「文字列」と「数値」がありますが、Xが引数としてハイパカから受け取るのは必ず「文字列」です。仮に 123 という数値をXに渡しても、Xが受け取るのは "123" という文字列です。
 CompileIt! は文字列と数値とをうまくコンバートし、ToolBox に必要な型に変換することが出来ます。しかし元の HyperTalk に型の概念がない以上、完全ではあり得ません。そこで、「これは数値だよ」というシルシとして、「 +0 」を書いてやります。こうすることで、CompileIt! はその変数が数値を扱うものであるということをハッキリと知ることが出来ます。
 スクリプト中で使われているそれぞれの変数を CompileIt! がどんな型として認識したのかは、コンパイル後に Analysis カードを見て知ることが出来ます。Analysis カードの中央に変数リストがありますが、変数名の頭に「 I 」や「 L 」が付いているものが数値で、「 H 」のついているものは文字列です。
 基本的には CompileIt! 任せでちゃんと動くXが出来るのですが、細かくチューンナップしたい場合にはこういったテクニックが必要になる場合もあります。

 HyperTalk しか使ったことのない人には変数の「型」という概念を理解するのが大変かも知れませんが、Xを作るには避けて通れませんので慣れるようにして下さい。変数の型についてはまたいつか説明します。

 テストには前回の GetPix で使ったスタックを使います。ボタンをひとつ追加して、以下のスクリプトをどーぞ。
-- button script for GetPixPattern test stack
on mouseUp
  put "" into cd fld 1
  set the cursor to watch
  put GetPixPattern( "0,0", 32, 32 ) into cd fld 1
end mouseUp
 うほほほほほ。一瞬でフィールドにパターンが現れますね。あ〜幸せ(笑)
 GetPix の速度と、GetPixPattern の速度を比べて下さい。これが CompileIt! の速さです。しかし更に、更に速くすることが出来るのです。



(4)高等編:ハンドルを使う

 先ほどの例では theResult を文字列として扱っています。これをハンドル経由で使うようにすると、Xは劇的に速くなります。ハンドルという概念は少々やっかいなものですが、CompileIt! からは比較的容易に扱うことが出来ます。取りあえずサンプルとしてスクリプトを挙げておきます。細かい説明はまたいつか。
-- CompileIt! script
function GetPixPattern2 thePt, width, height
  --
  if thePt is "!" then
    return "GetPixPattern 2.0"
  end if
  if ( thePt is "?" ) or ( thePt is "" ) then
    return "GetPixPattern2( topLeft, width, height ) "
  end if
  --
  put (item 1 of thePt) + 0 into L
  put (item 2 of thePt) + 0 into T
  put T + height - 1 into B
  put L + width - 1 into R
  --
  put NewHandleClear ( ( width + 1 ) * height ) into theResult -- 文字列を
  if ( ( MemErr <> 0 ) or ( theResult = nil ) ) then           -- 格納する
    return "Error : memory error "                             -- メモリを
  end if                                                       -- 準備する
  --
  put 1 into strIndex
  --
  repeat with V = T to B
    repeat with H = L to R
      if GetPixel(H,V) is true then
        put "1" into char strIndex of Handle theResult          -- "Handle"
      else                                                      -- に注目
        put "0" into char strIndex of Handle theResult
      end if
      add 1 to strIndex
    end repeat
    put return into char strIndex of Handle theResult
    add 1 to strIndex
  end repeat
  --
  put numToChar(0) into char strIndex - 1 of Handle theResult
  --
  return HyperCardText( theResult )
  --
end GetPixPattern2
 スタックは前回用いたものをそのまま使えます。GetPixPattern で使ったボタンをコピーして名前を GetPixPattern2 に変え、GetPixPattern() の部分を GetPixPattern2() として下さい。
 コンパイルの手順も全く同じです。NewHandleClear という新しい ToolBox 関数を使っていますし、HyperCardText という CompileIt! ネームを用いていますが、全てのシンボルを登録してあれば、問題なくコンパイル出来るはずです。

 ツールボックス関連の命令を使う時はコンパイルが終わったら必ず Analysis カードを確認して下さい。ToolBox のつもりで書いた関数が TextCallBacks にリストアップされていたら、スクリプトかシンボルカードの再確認が必要です。HyperTalk だけの時と違って、ToolBox 関数をテキストコールバック扱いすると、必ず致命的なエラー(爆弾/フリーズ)を起こします。

 さあテストです。GetPixPattern と GetPixPattern2 のスピードの違いが実感出来ますね。ちなみに 32x32 のパターンを 10 回ループで get したら、GetPixPattern XFCN が 345 ticks、GetPixPattern2 XFCN は 12 ticks でした。これが CompileIt! の真の実力です。このような高速な XFCN を、ほとんど HyperTalk のままのコーディングで作れてしまうところが、CompileIt! の偉大なところです。実行スピードもコードサイズも、C言語にひけを取りません。

inserted by FC2 system
Next



CompileIt! Lab.

UDI's HomePage