Copyright 2016-2020 Moddable Tech, Inc.
改訂: 2020年11月4日
このドキュメントは、Pocoレンダラーについて、Pocoを使う上での主要な概念を紹介する一連のサンプルから説明します。サンプルに続いて、Pocoのリファレンスがあり、各関数の呼び出しが完全に説明されています。
これらのサンプルはPocoレンダラーを使用する方法を解説しています。すべてのサンプルはJavaScriptAPIを使用し、またCommodettoのアセットローダーやその他の機能も利用しています。
以下のサンプルを簡潔かつ集中して説明するために、コードではいくつかの前提条件を設定しています。
-
サンプルでは、グローバル変数
screen
にPixelsOut
オブジェクトがあることを前提としています -
以下のカラー変数が定義されていることを前提としています:
let white = poco.makeColor(255, 255, 255); let black = poco.makeColor(0, 0, 0); let gray = poco.makeColor(128, 128, 128); let red = poco.makeColor(255, 0, 0); let green = poco.makeColor(0, 255, 0); let blue = poco.makeColor(0, 0, 255);
-
描画コマンドが
begin
とend
の呼び出しの間に実行されることを前提としています。let poco = new Poco(screen); poco.begin(); ... // example code here poco.end();
各サンプルには、コードによってレンダリングされた画像が含まれています。画像は見やすくするために150%に拡大されています。この拡大によって一部のぼやけやジャギーが生じることがありますが、実際の画像にはこれらは含まれません。
このサンプルでは、screen
を灰色のピクセルで埋め、左半分を赤色のピクセルで覆い、その後、画面の中央半分に50%のブレンドレベル(128)で青色のピクセルを描画します。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
poco.fillRectangle(red, 0, 0, poco.width / 2, poco.height);
poco.blendRectangle(blue, 128, poco.width / 4, 0, poco.width / 2, poco.height);
このサンプルでは、描画の原点を移動する方法を示します。Pocoは、原点が変更されるときにプッシュされ、引数なしで origin
が呼び出されるとポップされる原点スタックを保持します。各原点の変更では、前の原点からの相対的な移動を行います。原点スタックは、コンテナベースのユーザーインターフェースを構築するのに便利です。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
poco.origin(10, 10);
poco.fillRectangle(red, 0, 0, 40, 20);
poco.origin(25, 25);
poco.fillRectangle(green, 0, 0, 40, 20);
poco.origin(25, 25);
poco.fillRectangle(blue, 0, 0, 40, 20);
poco.blendRectangle(black, 128, -4, -4, 20, 10);
poco.origin();
poco.blendRectangle(black, 128, -4, -4, 20, 10);
poco.origin();
poco.blendRectangle(black, 128, -4, -4, 20, 10);
poco.origin();
このサンプルでは、描画のクリップを使用する方法を示します。Pocoは、クリップが変更されるときにプッシュされ、引数なしでclip
が呼び出されるとポップされるクリップスタックを保持します。各クリップの変更では、前のクリップと交差する領域に描画を制限します。クリップスタックは、コンテナベースのユーザーインターフェースを構築するのに便利です。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
poco.clip(20, 20, poco.width - 40, poco.height - 40);
poco.fillRectangle(green, 0, 0, poco.width, poco.height);
poco.clip(0, 0, 40, 40);
poco.fillRectangle(blue, 0, 0, poco.width, poco.height);
poco.fillRectangle(white, 26, 0, 2, poco.height);
poco.clip();
poco.fillRectangle(red, 30, 0, 2, poco.height);
poco.clip();
poco.fillRectangle(black, 34, 0, 2, poco.height);
このサンプルでは、ピクセルがすべて黒または白である封筒のモノクロビットマップを描画します。前景および背景ピクセルの色を制御する方法や、それぞれのピクセルが描画されるかどうかを示しています。ビットマップは32 x 23のサイズの1ビットBMPファイルに格納されています。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
let envelope = parseBMP(new Resource("envelope.bmp"));
poco.drawMonochrome(envelope, black, white, 14, 10);
poco.drawMonochrome(envelope, red, white, 14, 55);
poco.drawMonochrome(envelope, green, undefined, 74, 10);
poco.drawMonochrome(envelope, undefined, blue, 74, 55);
このサンプルでは、顔のカラービットマップ画像を2つの方法でdrawBitmap
を使用して描画します。画面の左側には全体の画像を描画します。右側にはdrawBitmap
のオプション引数のソース矩形パラメーターを使って、目と口だけを描画しています。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
let image = parseBMP(new Resource("lvb.bmp"));
let x = 0;
let y = Math.round((poco.height - image.height) / 2);
poco.drawBitmap(image, x, y);
x = image.width;
poco.drawBitmap(image, x + 25, y + 38, 25, 38, 11, 7); // left eye
poco.drawBitmap(image, x + 7, y + 40, 7, 40, 10, 6); // right eye
poco.drawBitmap(image, x + 15, y + 56, 15, 56, 16, 6); // mouth
このサンプルでは、fillPattern
を使用して、30ピクセル四方のパターンを2つの方法で描画します。最初に画面全体をそのパターンで埋め、その後パターンの7ピクセル四方の領域を使用して画面中央部分を埋めます。
前のサンプルとは異なり、最初に画面をクリアするためにfillRectangle
を呼び出しません。これは、最初のfillPattern
の呼び出しで画面のすべてのピクセルが覆われるためです。
let pattern = parseBMP(new Resource("pattern1.bmp"));
poco.fillPattern(pattern, 0, 0, poco.width, poco.height);
poco.fillPattern(pattern, 28, 28, 63, 35, 21, 14, 7, 7);
このサンプルでは、drawGray
を使用して16階調のグレー画像を複数の色で描画します。drawGray
はピクセル値をアルファブレンドレベルとして扱い、指定された色を背景とブレンドします。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
let image = parseBMP(new Resource("envelope-gray.bmp"));
poco.drawGray(image, black, 10, 2);
poco.drawGray(image, white, 10, 47);
poco.drawGray(image, black, 70, 2);
poco.drawGray(image, green, 70 + 2, 2 + 2);
poco.drawGray(image, white, 70, 47);
poco.drawGray(image, red, 70 + 2, 47 + 2);
このサンプルでは、BufferOut
を使用してオフスクリーンビットマップを作成し、一連の内側に向かう四角形でビットマップを埋めます。次に、そのオフスクリーンビットマップをパターンとして使用して画面を埋めます。このサンプルでは、2つのPoco
インスタンスを使用します。最初のインスタンスはオフスクリーンビットマップに描画し、2番目のインスタンスは画面に描画します。
import BufferOut from "commodetto/BufferOut";
let offscreen = new BufferOut({width: 30, height: 30, pixelFormat: poco.pixelsOut.pixelFormat});
let pocoOff = new Poco(offscreen);
pocoOff.begin();
pocoOff.fillRectangle(gray, 0, 0, 30, 30);
pocoOff.fillRectangle(red, 2, 2, 26, 26);
pocoOff.fillRectangle(black, 4, 4, 22, 22);
pocoOff.fillRectangle(blue, 6, 6, 18, 18);
pocoOff.fillRectangle(white, 8, 8, 14, 14);
pocoOff.fillRectangle(green, 10, 10, 10, 10);
pocoOff.fillRectangle(gray, 13, 13, 4, 4);
pocoOff.end();
poco.fillPattern(offscreen.bitmap, 0, 0, poco.width, poco.height);
このサンプルでは、アルファマスクを使用してビットマップを描画する方法を示します。描画するビットマップとマスクは別々のビットマップとして存在し、1つの画像に対して複数のアルファマスクを使用して描画することができます。このサンプルでは、1つのビットマップをぞれぞれ円形マスクと四角形マスクを通して描画し、さらに元の画像とマスクも描画します。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
let girl = parseBMP(new Resource("girl.bmp"));
let circle = parseBMP(new Resource("mask_circle.bmp"));
let square = parseBMP(new Resource("mask_square.bmp"));
poco.drawBitmap(girl, 0, 2);
poco.drawGray(circle, black, 40, 2);
poco.drawMasked(girl, 80, 2, 0, 0,
circle.width, circle.height, circle, 0, 0);
poco.drawBitmap(girl, 0, 47);
poco.drawGray(square, black, 40, 47);
poco.drawMasked(girl, 80, 47, 0, 0,
square.width, square.height, square, 0, 0);
これらの2つのサンプルでは、JPEG画像を扱う異なる方法を示します。最初のサンプルは、JPEG全体をメモリ内のビットマップに解凍し、次にそのビットマップを画面に描画します。trace
の呼び出しは、ビットマップの幅と高さにアクセスする方法を示しています。
import JPEG from "commodetto/readJPEG";
let piano = JPEG.decompress(new Resource("piano.jpg"));
trace(`width ${piano.width}, height ${piano.height}\n`);
poco.drawBitmap(piano, 0, 0);
2つ目のサンプルでは、JPEG画像を1ブロックずつデコードし、次のブロックをデコードする前にそのブロックを画面に描画します。このアプローチの利点は、メモリに必要なのが通常8 x 8または16 x 16ピクセルの単一のJPEGブロックだけで済むことです。欠点は、JPEG画像が一度にすべて表示されるのではなく、ユーザーにはブロックごとに表示されることです。
let jpeg = new JPEG(new Resource("piano.jpg"));
let block;
while (block = jpeg.read()) {
poco.begin(block.x, block.y, block.width, block.height);
poco.drawBitmap(block, block.x, block.y);
poco.end();
}
どちらの方法でも、最終的には同じ結果が得られます。
Pocoはテキスト描画に使用するフォントとしてBMPFont形式をサポートしています。BMFontは、アンチエイリアス処理が施された灰色またはカラーフォントで、主にゲームで使用されます。BMFontはフォントメトリクスとフォント画像の2つのファイルから構成されます。
以下のサンプルでは、36ポイントのPalatino BMFontを読み込み、描画しています。
import parseBMF from "commodetto/parseBMF";
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
poco.fillRectangle(white, 2, 2, poco.width - 4, poco.height - 4);
let palatino36 = parseBMF(new Resource("palatino_36.fnt"));
palatino36.bitmap = parseBMP(new Resource("palatino_36.bmp"));
poco.drawText("Hello.", palatino36, black, 4, 20);
poco.drawText("Hello.", palatino36, green, 4, 55);
テキストを描画する際に切り詰めるためには、drawText
のオプション引数width
を指定して、テキストに使用できる横幅を設定します。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
poco.fillRectangle(white, 2, 2, poco.width - 4, poco.height - 4);
let palatino36 = parseBMF(new Resource("palatino_36.fnt"));
palatino36.bitmap = parseBMP(new Resource("palatino_36.bmp"));
poco.drawText("Hello, world. This is long.", palatino36, red, 2, 10);
poco.drawText("Hello, world. This is long.", palatino36, green, 2, 45, poco.width - 2);
フォントのheight
プロパティを使用してテキストを水平および垂直に配置し、getTextWidth
を使用して文字列の幅を測定します。
poco.fillRectangle(gray, 0, 0, poco.width, poco.height);
poco.fillRectangle(white, 2, 2, poco.width - 4, poco.height - 4);
let palatino12 = parseBMF(new Resource("OpenSans-SemiboldItalic-18.fnt"));
palatino12.bitmap = parseBMP(new Resource("OpenSans-SemiboldItalic-18.bmp"));
poco.drawText("T Left", palatino12, red,
2, 2);
poco.drawText("T Right", palatino12, green,
poco.width - 2 - poco.getTextWidth("T Right", palatino12), 2);
poco.drawText("B Left", palatino12, blue,
2, poco.height - 2 - palatino12.height);
poco.drawText("B Right", palatino12, gray,
poco.width - 2 - poco.getTextWidth("B Right", palatino12),
poco.height - 2 - palatino12.height);
poco.drawText("Centered", palatino12, black,
(poco.width - poco.getTextWidth("Centered", palatino12)) / 2,
(poco.height - palatino12.height) / 2);
drawText
関数は、16階調のグレーレベルアルファビットマップをcolor
引数に受け取ることもできます。このビットマップを使用して、複数の色で構成されたフォントを描画できます。以下のサンプルでは、Open Sans Bold Italicを黒と白のピクセルで描画しています。
poco.fillRectangle(green, 0, 0, screen.width, screen.height);
let openSans52 = parseBMF(new Resource("OpenSans-BoldItalic-52.fnt"));
openSans52.bitmap = parseBMP(new Resource("OpenSans-BoldItalic-52-color.bmp"));
openSans52.mask = parseBMP(new Resource("OpenSans-BoldItalic-52-alpha.bmp"));
poco.drawText("Poco", openSans52, openSans52.mask, 0, 5);
以下の画像は、OpenSans-BoldItalic-52.bmp
ファイルの一部で、グリフイメージが含まれています。
こちらは、グリフイメージのアルファチャンネルが含まれているOpenSans-BoldItalic-52-alpha.bmp
ファイルの一部です。
Pocoは以下のピクセルフォーマットでレンダリングします:
- 16ビットRGB565リトルエンディアン
- 8ビットRGB332
- 8ビットグレー
- 4ビットインデックスカラー
- 4ビットグレー
ターゲットデバイスにデプロイするコードのサイズを小さく保つために、Pocoはビルド時にこれらのピクセルフォーマットのうち1つだけをレンダリングするように設定されます。
異なる出力形式を必要とするディスプレイの場合、ディスプレイドライバはサポートされているレンダリングフォーマットとハードウェアが要求するフォーマットの間で変換を行います。例えば、多くの一般的なLCDコントローラーは16ビットのRGB565ビッグエンディアンピクセルを必要とします。これらのコントローラー用のディスプレイドライバは、Pocoがレンダリングした16ビットRGB565リトルエンディアンピクセルを受け取り、LCDコントローラーに送信する際にビッグエンディアンに変換します。同様に、多くのディスプレイはモノクロ(1ビット)です。これらのディスプレイドライバは4ビットまたは8ビットのグレーでレンダリングされたピクセルを受け取り、モノクロディスプレイ用に1ビットに変換します。
Pocoは、すべてのピクセルフォーマットへのレンダリング用ソースとして、1ビットモノクロームおよび4ビットグレービットマップをサポートしています。さらに、設定された出力ピクセルフォーマットも常にソースフォーマットとしてサポートされます。例えば、レンダリングピクセルフォーマットが16ビットRGB565リトルエンディアンの場合、サポートされるソースピクセルフォーマットは1ビットモノクローム、4ビットグレー、および16ビットRGB565リトルエンディアンです。
Pocoは、2つの圧縮ピクセルフォーマットをサポートしています。
1つ目は、4ビットグレービットマップの重み付きランレングス圧縮です。これは、アンチエイリアスフォントやイメージマスクによく使用されます。これらはCommodettoBitmap
およびPocoBitmap
のデータ構造を使用し、ピクセルフォーマットが(kCommodettoBitmapGray16 | kCommodettoBitmapPacked)
に設定されています。
2つ目は、フルカラー画像を圧縮するために使用されるColorCellアルゴリズムの一種です。これらはCommodettoBitmap
やPocoBitmap
のデータ構造で参照されることはなく、BMP、PNG、JPEGと同様に画像ファイルとして扱われます。ColorCell画像は16ビットRGB565リトルエンディアンピクセルを使用するため、16ビットRGB565リトルエンディアンの出力先でのみレンダリングされます。
デフォルトでは、Pocoはスキャンライン表示リストレンダラーです。つまり、すべての描画コマンドを保存し、指定されたフレームのすべての描画コマンドがキューに入ったときに、それらを一度にレンダリングします。Pocoがアクセス可能なメモリに保存されたフルフレームバッファを持ち、ダブルバッファ(例:2つのフレームバッファを交互に使用する)を持つディスプレイで使用される場合、スキャンライン表示リストレンダリングは、各描画コマンドが受信されるとすぐに実行するイミディエイトモードレンダリングよりも効率が低くなります。
Pocoはオプションで即時モードレンダリングをサポートしています。このサポートを有効にするには、Pocoをビルドする際にkPocoFrameBuffer
を1に定義し、Cコード内でPocoDrawingBegin
/PocoDrawingEnd
の代わりにPocoDrawingBeginFrameBuffer
/PocoDrawingEndFrameBuffer
を使用します。即時モードレンダリングを使用するためにJavaScriptコードの変更は必要ありません。
Pocoは、PixelsOut
への描画を0度、90度、180度、または270度の回転でサポートしています。このサポートにより、ハードウェアのスキャン順序に関係なく、任意の向きでディスプレイを使用できます。
回転は実行時ではなくビルド時に、kPocoRotation
をターゲットの回転角度(例:90)に定義することで選択されます。デフォルトの回転値は0です。回転はすべての描画操作の座標、出力先とソースの両方に適用されます。任意のアセット(例:保存されたビットマップやフォント)は、Pocoに渡される前に回転させる必要があります。これは手動(例:Photoshopによって)または自動(例:Moddable SDKのpng2bmpツールによって)で行います。
回転に対するこのアプローチは、回転していない画像と同じパフォーマンスレベルで、中間ビットマップバッファを必要とせずに、回転した出力をレンダリングすることができます。
Pocoは、CommodettoのRender
クラスのサブクラスであるレンダラーです。
class Poco extends Render
PocoはRender
のディクショナリを拡張し、ディスプレイリストバッファのサイズをバイト単位で指定するdisplayListLength
プロパティを追加します。アプリケーションは通常、デフォルトのディスプレイリスト長を使用します。Pocoは描画操作がディスプレイリストをオーバーフローしそうになったときに検出し、描画操作を無視し、end
が呼ばれたときに例外をスローします。
import Poco from "commodetto/Poco";
let screen = ... // SPIOut instance
let poco = new Poco(screen, {displayListLength: 4096});
Pocoによって割り当てられたすべてのメモリを解放します。close
を呼び出した後、そのインスタンスの他の関数を呼び出すことはできません。
Pocoは、すべての描画操作に適用されるクリップ矩形を保持します。
begin
が呼び出されると、クリップ矩形はbegin
に渡された更新領域に設定されます。Pocoはクリップスタックを保持しているため、アプリケーションが現在のクリップを保存および復元する必要はありません。4つの引数でclip
を呼び出すと、現在のクリップと引数で指定された領域の交差部分が設定されます。引数なしで呼び出すと、クリップスタックの最後のクリップが削除され、前のクリップが復元されます。
poco.clip(10, 10, 10, 10);
poco.clip();
クリップスタックは次のようにいくつかのクリップを保持します:
poco.begin(); // Clip is entire PixelsOut area
poco.clip(10, 10, 10, 10); // Clip is {x: 10, y: 10, w: 10, h: 10}
poco.clip(0, 0, 15, 15); // Clip is {x: 10, y: 10, w: 5, h: 5}
poco.clip(); // Clip is {x: 10, y: 10, w: 10, h: 10}
poco.clip() // Clip is entire PixelsOut area
poco.end();
クリップスタックがオーバーフローまたはアンダーフローすると、end
から例外がスローされます。end
が呼び出されたときにクリップスタックが空でないと、例外がスローされます。
4つの引数でclipを呼び出すと、結果の領域に1ピクセル以上含まれている場合はtrue
が返され、クリップ領域が空の場合はundefined
が返されます。
注意:
clip
とorigin
は同じスタックを共有しているため、プッシュされた順序でポップする必要があります。
Pocoは、すべての描画操作に適用される原点を保持します。
begin
が呼び出されると、原点は{x: 0, y: 0}
に設定されます。Pocoは原点スタックを保持しているため、アプリケーションが現在の原点を保存および復元する必要はありません。2つの引数でorigin
を呼び出すと、現在の原点がその引数分だけオフセットされます。引数なしで呼び出すと、原点スタックの最後の原点が削除され、前の原点が復元されます。
poco.begin(); // Origin is {x: 0, y: 0}
poco.origin(10, 10); // Origin is {x: 10, y: 10}
poco.origin(5, 5); // Origin is {x: 15, y: 15}
poco.origin(); // Origin is {x: 10, y: 10}
poco.origin(); // Origin is {x: 0, y: 0}
poco.end();
原点スタックがオーバーフローまたはアンダーフローすると、end
から例外がスローされます。end
が呼び出されたときに原点スタックが空でないと、例外がスローされます。
注意: 原点を変更してもクリップ矩形は変更されません。また、
clip
とorigin
は同じスタックを共有しているため、プッシュされた順序でポップする必要があります。
makeColor
関数は、0から255までの赤、緑、青の値を受け取り、対応するピクセル値を返します。返されるピクセルは、Poco
インスタンスにバインドされたPixelsOut
インスタンスのフォーマットに従います。
let red = poco.makeColor(255, 0, 0);
let green = poco.makeColor(0, 255, 0);
let blue = poco.makeColor(0, 0, 255);
let black = poco.makeColor(0, 0, 0);
let white = poco.makeColor(255, 255, 255);
let gray = poco.makeColor(127, 127, 127);
多くの描画関数は、引数として色を受け取ります。ピクセルフォーマットに依存しないようにするために、色を計算するにはmakeColor
を使用します。
fillRectangle
関数は、x
、y
、width
、およびheight
の引数で指定された領域を指定された色で塗りつぶします。
poco.fillRectangle(green, 10, 20, 40, 40);
blendRectangle
関数は、指定された色をx
、y
、width
、およびheight
の引数で指定された領域のピクセルとブレンドします。blend
引数はブレンドのレベルを決定し、0は透明、255は不透明を意味します。
以下のコードは、不透明度が増加する16本の水平な緑の線を描画します。
let green = poco.makeColor(0, 255, 0);
for (let blend = 15, y = 0; blend < 256; blend += 16, y += 1)
poco.blendRectangle(green, blend, 0, y, pixelsOut.width, 1);
drawPixel
関数は、指定された色のピクセルをx
およびy
の引数で指定された位置に描画します。
poco.drawPixel(poco.makeColor(0, 0, 127), 5, 5);
注意: 1フレームで
drawPixel
を多用すると、ディスプレイリストがすぐに満たされる可能性があります。
drawBitmap
関数は、ピクセルタイプがBitmap.Default
であるビットマップの全部または一部を描画します。ビットマップはbits
引数で指定され、ビットマップを描画する位置はx
およびy
引数で指定されます。以下のコードは、画像全体を位置{x: 10, y: 5}
に描画します。
let image = parseBMP(new Resource("image.bmp"));
poco.drawBitmap(image, 10, 5);
オプションのsx
、sy
、sw
およびsh
引数は、描画するビットマップの領域を指定します。これらを省略すると、ビットマップ全体が描画されます。
以下のコードは、ビットマップの下半分を位置{x: 0, y: 0}
に描画します。
poco.drawBitmap(image, 0, 0, 0, image.height / 2, image.width, image.height / 2);
drawMonochrome
関数は、ピクセルタイプがBitmap.Monochrome
のビットマップの全部または一部を描画します。ビットマップはbits
引数で指定され、ビットマップを描画する位置はx
およびy
引数で指定されます。
fore
およびback
引数は、ビットマップの白黒ピクセルに適用される前景色および背景色を指定します。fore
がundefined
の場合、前景ピクセルは描画されません。back
がundefined
の場合、背景ピクセルは描画されません。
let red = poco.makeColor(255, 0, 0);
let gray = poco.makeColor(128, 128, 128);
let white = poco.makeColor(255, 255, 255);
let icon = parseBMP(new Resource("icon.bmp"));
poco.drawMonochrome(icon, red, white, 0, 5); // red foreground and white background
poco.drawMonochrome(icon, gray, undefined, 0, 5); // only foreground pixels in gray
poco.drawMonochrome(icon, undefined, red, 0, 5); // only background pixels in red
オプションのsx
、sy
、sw
およびsh
引数は、描画するビットマップの領域を指定します。これらを省略すると、ビットマップ全体が描画されます。
drawGray
関数は、ピクセルタイプがBitmap.Gray16
のビットマップの全部または一部を描画します。ビットマップはbits
引数で指定され、ビットマップを描画する位置はx
およびy
引数で指定されます。ビットマップのピクセルはアルファ値として扱われ、背景とブレンドされます。color
引数はブレンド時に適用する色を指定します。
オプションのsx
、sy
、sw
およびsh
引数は、描画するビットマップの領域を指定します。これらを省略すると、ビットマップ全体が描画されます。
オプションのblend
引数は、背景とブレンドする前に、ビットマップ内のすべてのピクセルに追加のブレンドレベルを適用します。blend
値は、0が透明で255が不透明です。
drawMasked
関数は、画像とアルファチャネルの2つのビットマップを使用して、マスクを通じて画像をアルファブレンドし、目的の位置に合成します。bits
引数で指定された画像はBitmap.Default
フォーマットです。mask
引数で指定されたアルファチャネルはBitmap.Gray16
フォーマットです。
x
とy
引数は出力の中で合成画像を配置する位置を指定します。sx
、sy
、sw
、およびsh
引数は、使用する画像の領域を指定します。mask_sx
とmask_sy
引数は使用するマスクビットマップの左上隅を指定します。マスクビットマップ領域の寸法はsw
とsh
引数から取得されます。
以下のサンプルは、アルファチャネルを使用してボタン画像を描画する方法を示しています。画像とアルファチャネルは、それぞれアルファチャネルを持つPNGファイルから抽出され、別々のファイルに保存されています。
let buttonImage = parseBMP(new Resource("button_image.bmp"));
let buttonAlpha = parseBMP(new Resource("button_alpha.bmp"));
poco.drawMasked(buttonImage, 0, 0, 0, 0,
buttonImage.width, buttonImage.height, buttonAlpha, 0, 0);
アルファチャネルを画像とは別に保存することは珍しいですが、リソースに制約のあるデバイスでは次のような利点があります:
- アルファチャネル画像はピクセルあたり4ビットにすることができ、半分のサイズで良好な結果を得ることができます。
- 画像はアルファチャネル付きとなしの両方でレンダリングできます。
- 単一のマスクを任意の画像に適用でき、エフェクトやアニメーションを実現できます。
オプションのblend
引数は、背景とブレンドする前にアルファチャネルビットマップのすべてのピクセルに追加のブレンドレベルを適用します。blend
値は透明の場合は0、不透明の場合は255です。
fillPattern
関数は、Bitmap.Default
タイプのピクセルで構成されるビットマップの全部または一部を繰り返し描画することで、指定された領域を埋めます。ビットマップは bits
引数で指定されます。塗りつぶす領域の位置はx
とy
引数で指定され、その領域の寸法はw
とh
引数で指定されます。
let pattern = parseBMP(new Resource("pattern.bmp"));
poco.fillPattern(pattern, 10, 10, 90, 90);
オプションのsx
、sy
、sw
、およびsh
引数は、ビットマップのどの部分を使用するかを指定します。これらの引数が省略された場合、ビットマップ全体が使用されます。
poco.fillPattern(pattern, 10, 10, 90, 90, 0, 0, 8, 8);
drawText
関数は、font
引数に指定されたBMFontを使用してtext
文字列を描画します。テキストは、color
引数で指定された色で、x
およびy
引数の位置に描画されます。テキストは左上揃えで描画されます。
次のコードは、"Hello, world"
という文字列を2回描画します。最初は画面の左上隅にChicagoフォントを使用して黒で描画し、その下にPalatino 36フォントを使用して赤で描画します。
poco.drawText("Hello, world", chicagoFont, black, 0, 0);
poco.drawText("Hello, world", palatino36, red, 0, chicagoFont.height);
オプションの引数width
を指定すると、テキストが長すぎて利用可能な幅に収まらない場合、右端で切り詰められます。切り詰めが発生すると、3つのピリオド(...
)が文字列の末尾に描画されます。
フォントに含まれていない文字列内の文字は無視されます。
エッジにアンチエイリアスをかけたフルカラーのテキストを描画するには、Bitmap.Default
フォーマットのビットマップを持つBMFontを使用します。color
引数の代わりに、Bitmap.Gray16
フォーマットのマスクビットマップを渡します。マスクは少なくともBMFontのグリフアトラスと同じ大きさでなければなりません。各グリフが描画されるとき、フォント画像内のグリフに対応するマスク画像内のピクセルが、各グリフを描画先にアルファブレンドするために使用されます。
getTextWidth
関数は、font
を使用してレンダリングされたときのtext
文字列の幅をピクセル単位で計算します。
次のコードは、"Hello, world"
という文字列をディスプレイの上部に水平中央に配置して描画します。
let text = "Hello, world";
let width = poco.getTextWidth(text, palatino36);
poco.drawText(text, palatino36, green, (pixelsOut.width - width) / 2, 0);
フォントの高さはfont.height
プロパティで利用できます。
テキスト文字列内のフォントに含まれていない文字はレンダリングされません。
drawFrame
関数は、frame
引数で参照されるColorCell圧縮画像を、x
およびy
引数で指定された位置にレンダリングします。dictionary
引数は、画像のサイズを示す幅と高さのプロパティを含むObject
です。
回転を適用した後のPocoインスタンスのピクセル単位の論理的な高さ。回転が0または180の場合、これはPixelsOut
インスタンスの高さに等しくなります。回転が90または270の場合、これはPixelsOut
インスタンスの幅に等しくなります。
回転を適用した後のPocoインスタンスのピクセル単位の論理的な幅。回転が0または180の場合、これはPixelsOut
インスタンスの幅と等しくなります。回転が90または270の場合、これはPixelsOut
インスタンスの高さと等しくなります。
Poco C APIは低レベルのレンダリングエンジンです。これはディスプレイリストに基づいており、すべての描画呼び出しはレンダリング前にリストにキューイングされることを意味します。ディスプレイリストを使用することで、レンダラーは一度に1スキャンライン分の完全な出力を生成すればよいので、アプリケーションプロセッサのメモリ内にフレームバッファを必要せず、メモリ使用量を最小限に抑えられます。
Poco C APIは、CommodettoやそのJavaScript APIとは独立して使用することができます。メモリ割り当ては行わず、ほとんど外部呼び出しも行わず(memcpy
への呼び出しのみ)、呼び出し元のメモリ提供に依存します。
PocoRecord
はPocoの状態を保持します。多くのフィールドはプライベート実装であり、ライブラリのユーザーが直接アクセスしてはいけません。PocoRecord
データ構造は0に初期化する必要があり、すべてのPoco関数呼び出しに対して同じPocoRecord
構造体を渡す必要があります。
次のPocoRecord
のフィールドはパブリックであり、ライブラリのユーザーがアクセスできます。Pocoは最初の呼び出しが行われる前に、ライブラリのユーザによってこれらのフィールドが初期化されることを期待しています。
フィールド | 説明 |
---|---|
width |
ピクセル単位の出力の幅 |
height |
ピクセル単位の出力の高さ |
displayList |
ディスプレイリストのメモリ開始位置へのポインタ |
displayListEnd |
ディスプレイリストのメモリ終了位置へのポインタ |
pixelsLength |
バイト単位のピクセル配列のサイズ |
次のフィールドはPocoDrawingBegin
とPocoDrawingEnd
の呼び出しの間に PocoRecord
構造体から読み取ることができます:
フィールド | 説明 |
---|---|
xOrigin |
描画の原点のx座標 |
yOrigin |
描画の原点のy座標 |
x |
描画クリップのx座標 |
y |
描画クリップのy座標 |
w |
描画クリップの幅 |
h |
描画クリップの高さ |
xMax |
描画クリップの右側の座標、x + w |
yMax |
描画クリップの下側の座標、y + h |
PocoCoordinate
は符号付き整数値です。Commodettoで使用される場合、CommodettoCoordinate
としてエイリアスされています。詳細については、CommodettoドキュメントのCommodettoCoordinate
の説明を参照してください。
PocoDimension
は符号なし整数値です。Commodettoで使用される場合、CommodettoDimension
としてエイリアスされています。詳細については、CommodettoドキュメントのCommodettoDimension
の説明を参照してください。
PocoPixel
は整数値です。Commodettoで使用される場合、CommodettoPixel
としてエイリアスされています。詳細については、CommodettoドキュメントのCommodettoPixel
の説明を参照してください。
PocoBitmapFormat
は整数値です。Commodettoで使用される場合、CommodettoBitmapFormat
としてエイリアスされています。詳細については、CommodettoドキュメントのCommodettoBitmapFormat
の説明を参照してください。
PocoRectangle
は矩形で囲まれた領域を定義し、左上の座標と寸法を指定します。
typedef struct {
PocoCoordinate x;
PocoCoordinate y;
PocoDimension w;
PocoDimension h;
} PocoRectangleRecord, *PocoRectangle;
PocoBitmap
構造体には、ビットマップのピクセル単位の幅と高さ、ビットマップ内のピクセルフォーマット、およびピクセルデータへのポインタが含まれています。
typedef struct PocoBitmapRecord {
PocoDimension width;
PocoDimension height;
PocoBitmapFormat format;
PocoPixel *pixels;
} PocoBitmapRecord, *PocoBitmap;
ピクセルは左から右、上から下へと並んでおり、行間にパディングはありません。PocoBitmap
にはrowBytes
やstride
フィールドはありません。
注意:
CommodettoBitmap
と異なり、PocoBitmap
にはピクセルポインタの代わりにオフセットを格納するオプションはありません。
Pocoの呼び出しを行う前に、PocoRecord
構造体を確保して初期化する必要があります。詳細はPocoRecord
を参照してください。
PocoPixel PocoMakeColor(Poco poco, uint8_t r, uint8_t g, uint8_t b);
PocoMakeColor
は0から255までの赤、緑、および青の値を受け取り、PocoPixel
値を返します。返されるピクセル値は、いくつかのレンダリング呼び出しで色引数として使用できます。
注意: 現在の実装では、Pocoは常に単一の出力ピクセルフォーマットをサポートしてビルドされるため、pocoパラメータは使用されません。
void PocoDrawingBegin(Poco poco, PocoCoordinate x, PocoCoordinate y,
PocoDimension w, PocoDimension h);
PocoDrawingBegin
は、x
、y
、w
、h
パラメータで囲まれたピクセルの更新エリアに対するレンダリングプロセスを開始します。描画の呼び出しはPocoDrawingBegin
と PocoDrawingEnd
の間でのみ行うことができます。
重要:
PocoDrawingBegin
の呼び出し元は、描画呼び出しが更新エリア内のすべてのピクセルをカバーすることを確認する責任があります。Pocoは前のフレームを保持しません。描画されないピクセルには予測不可能な値を含むことになります。
int PocoDrawingEnd(Poco poco, PocoPixel *pixels, int byteLength,
PocoRenderedPixelsReceiver pixelReceiver, void *refCon);
typedef void (*PocoRenderedPixelsReceiver)(PocoPixel *pixels,
int byteCount, void *refCon);
PocoDrawingEnd
は、PocoDrawingBegin
の呼び出し以降にディスプレイリストに追加された描画コマンドをレンダリングします。
PocoDrawingEnd
の呼び出し元は、レンダリングされたピクセルのバッファをpixels
とbyteLength
引数で提供します。Pocoはバッファにできるだけ多くのピクセル行をレンダリングし、その後pixelReceiver
関数を呼び出してピクセルを出力します。バッファは単一のピクセル行を保持するのに十分なサイズであればよく、複数行のピクセルを保持できるバッファを使用するとレンダリングのオーバーヘッドが減少します。
描画呼び出しの結果やPocoDrawingEnd
の実行中にコマンドを表示リストに追加してエラーが発生した場合、PocoDrawingEnd
は0以外の結果を返します:
- 1 -- ディスプレイリストのオーバーフロー
- 2 -- クリップおよび原点スタックのオーバーフロー
- 3 -- クリップおよび原点スタックのアンダーフロー、または順序外のポップ
void PocoRectangleFill(Poco poco, PocoPixel color, uint8_t blend,
PocoCoordinate x, PocoCoordinate y, PocoDimension w, PocoDimension h);
PocoRectangleFill
は、x
、y
、w
、h
引数で定義された領域を指定された color
で塗りつぶします。blend
で指定されたレベルがkPocoOpaque
(255)の場合、色はブレンドされずに背景に上書きされます。他のブレンドレベルの場合、色は背景と比率に応じてブレンドされます。
void PocoPixelDraw(Poco poco, PocoPixel color,
PocoCoordinate x, PocoCoordinate y);
PocoPixelDraw
は、指定されたx
とy
の位置に指定された色で単一のピクセルを描画します。
PocoCommand PocoBitmapDraw(Poco poco, PocoBitmap bits,
PocoCoordinate x, PocoCoordinate y,
PocoDimension sx, PocoDimension sy,
PocoDimension sw, PocoDimension sh);
PocoBitmapDraw
は、x
とy
で指定された位置に、kCommodettoBitmapDefault
型のビットマップであるbits
の全体または一部を描画します。sx
、sy
、sw
、sh
の引数は、描画するビットマップの領域を定義します。
void PocoMonochromeBitmapDraw(Poco poco, PocoBitmap bits,
PocoMonochromeMode mode, PocoPixel fgColor, PocoPixel bgColor,
PocoCoordinate x, PocoCoordinate y,
PocoDimension sx, PocoDimension sy,
PocoDimension sw, PocoDimension sh);
PocoMonochromeBitmapDraw
は、x
とy
で指定された位置に、kCommodettoBitmapMonochrome
型のビットマップであるbits
の全体または一部を描画します。sx
、sy
、sw
、sh
の引数は、描画するビットマップの領域を定義します。mode
引数は、どのピクセルを描画するかを決定します:
kPocoMonochromeForeground
-- 前景ピクセル(ビットマップ内の値が1のピクセル)のみを描画します。kPocoMonochromeBackground
-- 背景ピクセル(ビットマップ内の値が0のピクセル)のみを描画します。kPocoMonochromeForeAndBackground
-- 前景および背景ピクセルの両方を描画します。
fgColor
とbgColor
引数は、前景と背景ピクセルの描画に使用する色を指定します。
void PocoGrayBitmapDraw(Poco poco, PocoBitmap bits,
PocoPixel color, uint8_t blend,
PocoCoordinate x, PocoCoordinate y,
PocoDimension sx, PocoDimension sy,
PocoDimension sw, PocoDimension sh);
PocoGrayBitmapDraw
は、x
とy
で指定された位置に、kCommodettoBitmapGray16
型のビットマップであるbits
の全体または一部を描画します。sx
、sy
、sw
、sh
の引数は、描画するビットマップの領域を定義します。ビットマップのピクセルはアルファブレンドレベルとして扱われ、color
引数の色と背景ピクセルとがブレンドされます。blend
引数は各ピクセルのブレンドレベルに適用され、値は0が透明で255が不透明です。
void PocoBitmapDrawMasked(Poco poco, PocoBitmap bits, uint8_t blend,
PocoCoordinate x, PocoCoordinate y,
PocoDimension sx, PocoDimension sy,
PocoDimension sw, PocoDimension sh,
PocoBitmap mask, PocoDimension mask_sx, PocoDimension mask_sy);
PocoBitmapDrawMasked
は、x
とy
で指定された位置に、kCommodettoBitmapDefault
型のビットマップであるbits
の、sx
、sy
、sw
、sh
で囲まれたピクセルを描画します。ピクセルはkCommodettoBitmapGray16
型のビットマップであるmask
の、mask_sx
、mask_sy
,sw
、sh
で囲まれた対応するピクセルを、アルファブレンディングレベルとして描画します。blend
引数は各ピクセルのブレンドレベルに適用され、値は0が透明で255が不透明です。
void PocoBitmapPattern(Poco poco, PocoBitmap bits,
PocoCoordinate x, PocoCoordinate y,
PocoDimension w, PocoDimension h,
PocoDimension sx, PocoDimension sy,
PocoDimension sw, PocoDimension sh);
PocoBitmapPattern
は、x
、y
、w
、h
引数で囲まれた領域を、sx
、sy
、sw
、sh
引数で囲まれたビットマップbits
の領域の繰り返しコピーで塗りつぶします。ビットマップはkCommodettoBitmapDefault
型でなければなりません。
void PocoDrawFrame(Poco poco,
uint8_t *data, uint32_t dataSize,
PocoCoordinate x, PocoCoordinate y,
PocoDimension w, PocoDimension h);
PocoDrawFrame
は、ModdableのColorCellアルゴリズムの一種で保存された圧縮画像をレンダリングします。レンダリングする画像はdata
引数で示され、バイト数はdataSize
引数で指定されます。画像は、x
およびy
引数で指定された位置にレンダリングされます。圧縮画像のソース寸法(クリップされていないサイズ)は、w
およびh
引数によって与えられます。
void PocoClipPush(Poco poco, PocoCoordinate x, PocoCoordinate y,
PocoDimension w, PocoDimension h);
PocoClipPush
は現在のクリップ領域をスタックにプッシュし、その後、現在のクリップとx
、y
、w
、h
引数で囲まれた領域が交差する領域で現在のクリップを置き換えます。
void PocoClipPop(Poco poco);
PocoClipPop
はスタックからクリップをポップし、現在のクリップをポップした値で置き換えます。
void PocoOriginPush(Poco poco, PocoCoordinate x, PocoCoordinate y);
PocoOriginPush
は現在の原点をスタックにプッシュし、その後、x
およびy
引数で現在の原点をオフセットします。
void PocoOriginPop(Poco poco);
PocoOriginPop
は原点をスタックからポップし、現在の原点をポップした値で置き換えます。
void PocoDrawingBeginFrameBuffer(Poco poco, PocoCoordinate x, PocoCoordinate y,
PocoDimension w, PocoDimension h,
PocoPixel *pixels, int16_t rowBytes);
PocoDrawingBeginFrameBuffer
は、x
、y
、w
、h
パラメータによって囲まれたピクセルの更新領域に対して、即時モードレンダリング処理を開始します。pixels
パラメータは出力ピクセルの最初のスキャンラインを指します。rowBytes
パラメータは、各スキャンライン間のバイト単位のストライドです。
int PocoDrawingEndFrameBuffer(Poco poco;)
PocoDrawingEndFrameBuffer
は、現在のフレームに対するすべての描画が完了したことを示します。
void PocoDrawExternal(Poco poco, PocoRenderExternal doDrawExternal,
uint8_t *data, uint8_t dataSize,
PocoCoordinate x, PocoCoordinate y,
PocoDimension w, PocoDimension h);
typedef void (*PocoRenderExternal)(Poco poco, uint8_t *data,
PocoPixel *dst, PocoDimension w, PocoDimension h, uint8_t xphase);
PocoDrawExternal
はカスタムレンダリング要素を現在のPocoディスプレイリストにインストールします。data
引数は、描画操作を定義するdataSize
バイト長のデータブロックを指します。このデータはPocoディスプレイリストにコピーされるので、できるだけコンパクトである必要があります。描画操作の境界はx
、y
、w
、h
引数で定義されます。doDrawExternal
コールバック関数は呼び出されると、一度に1つまたは複数のスキャンラインでカスタム要素を描画します。
Pocoは、レンダリング操作でクリッピングや回転を行いません。これらは、レンダリングデータを作成するコードおよび/またはレンダリングコールバック関数で適用する必要があります。
複数のピクセルが1バイトに格納されているピクセルフォーマットで描画する場合、xphase
は描画が開始されるピクセルを示します。例えば、1ピクセルあたり4ビットを使用するピクセルフォーマットでは、xphaseはバイト内の最初のピクセルに対しては0、2番目のピクセルに対しては1になります。
注意: カスタムレンダリング要素の実装は高度なテクニックであり、Pocoレンダリングエンジンの実装に精通している必要があります。
PocoのC APIはCommodettoから独立して使用することができます。PocoはCommodettoに統合された最初のレンダラーです。PocoはCommodettoをサポートするすべてのハードウェア、特にXS JavaScriptエンジンで動作します。PocoのC APIはCommodettoと比較して、かなり性能の低いハードウェアでも動作します。
pocoは音楽用語で「少し」を意味します。