DVI モジュールは、DVI 出力の制御と画面描画のための低レベル API を提供します。

Harucom にはテキストモードとグラフィックスモードの2つの表示モードがあり、 グラフィックスモードではピクセル単位の描画や図形・テキストの描画ができます。

より手軽に描画したい場合は、DVI::Graphics をラップした P5 描画ライブラリ を使います。

目次

基本的な使い方

テキストモード

DVI.set_mode(DVI::TEXT_MODE)

# 画面をクリア(黒背景・白文字)
attr = (DVI::Text::WHITE << 4) | DVI::Text::BLACK
DVI::Text.clear(attr)

# 文字列を表示
DVI::Text.put_string(0, 0, "Hello, world!", attr)
DVI::Text.commit

グラフィックスモード

DVI.set_mode(DVI::GRAPHICS_MODE)

G = DVI::Graphics

# 画面を黒で塗りつぶす
G.fill(0x00)

# 赤い円を描く
G.fill_circle(160, 120, 50, 0xE0)

# テキストを描く
G.draw_text(10, 10, "Hello!", 0xFF, G::FONT_MPLUS_12)

G.commit

DVI モジュールのメソッド

DVI.set_mode(mode)

DVI.set_mode(DVI::TEXT_MODE)
DVI.set_mode(DVI::GRAPHICS_MODE)

表示モードを切り替えます。切り替えは次の VBlank で反映されます。

定数 モード
DVI::TEXT_MODE テキストモード(106桁 x 37行)
DVI::GRAPHICS_MODE グラフィックスモード(640x480 または 320x240)

DVI.wait_vsync

DVI.wait_vsync

次の VBlank(垂直帰線期間)まで待ちます。

DVI.frame_count

DVI.frame_count  #=> Integer

DVI 出力を開始してからのフレーム数を返します。約60フレーム/秒で増加します。


DVI::Text(テキストモード)

テキストモードでは、106桁 x 37行の画面に文字を配置できます。 各セルには文字コードと属性(前景色・背景色)が設定されます。

画面サイズ

定数
DVI::Text::COLS 106(桁数)
DVI::Text::ROWS 37(行数)

色の定数

属性の前景色・背景色には次の定数が使えます。

定数
DVI::Text::BLACK
DVI::Text::BLUE
DVI::Text::GREEN
DVI::Text::CYAN シアン
DVI::Text::RED
DVI::Text::MAGENTA マゼンタ
DVI::Text::BROWN
DVI::Text::LIGHT_GRAY 明るい灰色
DVI::Text::DARK_GRAY 暗い灰色
DVI::Text::LIGHT_BLUE 明るい青
DVI::Text::LIGHT_GREEN 明るい緑
DVI::Text::LIGHT_CYAN 明るいシアン
DVI::Text::LIGHT_RED 明るい赤
DVI::Text::LIGHT_MAGENTA 明るいマゼンタ
DVI::Text::YELLOW
DVI::Text::WHITE

属性の作り方

属性は1バイトの値で、上位4ビットが前景色、下位4ビットが背景色です。

# 白い文字、黒い背景
attr = (DVI::Text::WHITE << 4) | DVI::Text::BLACK

# 黄色い文字、青い背景
attr = (DVI::Text::YELLOW << 4) | DVI::Text::BLUE

文字の表示

DVI::Text.put_char(col, row, ch, attr)

DVI::Text.put_char(0, 0, 65, attr)  # 'A' を表示

(col, row) の位置に文字コード ch を属性 attr で配置します。

DVI::Text.put_string(col, row, str, attr)

DVI::Text.put_string(0, 0, "Hello!", attr)

(col, row) の位置から UTF-8 文字列を属性 attr で表示します。 全角文字(日本語など)にも対応しています。

画面のクリア

DVI::Text.clear(attr)

DVI::Text.clear(attr)

画面全体を指定した属性でクリアします。

DVI::Text.clear_line(row, attr)

DVI::Text.clear_line(5, attr)

指定した行を属性 attr でクリアします。

DVI::Text.clear_range(col, row, width, attr)

DVI::Text.clear_range(10, 5, 20, attr)

(col, row) の位置から width セルぶんを属性 attr でクリアします。

スクロール

DVI::Text.scroll_up(lines, attr)

DVI::Text.scroll_up(1, attr)

画面を lines 行ぶん上にスクロールします。下側にできた空き行は属性 attr で埋められます。

DVI::Text.scroll_down(lines, attr)

DVI::Text.scroll_down(1, attr)

画面を lines 行ぶん下にスクロールします。上側にできた空き行は属性 attr で埋められます。

属性の操作

DVI::Text.get_attr(col, row)

a = DVI::Text.get_attr(0, 0)

(col, row) の位置にあるセルの属性を返します。

DVI::Text.set_attr(col, row, attr)

DVI::Text.set_attr(0, 0, attr)

(col, row) の位置にあるセルの属性を変更します。

行の読み書き

DVI::Text.read_line(row)

line = DVI::Text.read_line(0)

指定した行の内容を DVI::Text::Line オブジェクトとして読み取ります。 スクロールバックバッファなどに使えます。

DVI::Text.write_line(row, line)

DVI::Text.write_line(5, line)

read_line で読み取った DVI::Text::Line オブジェクトを指定した行に書き込みます。

画面の反映

DVI::Text.commit

DVI::Text.commit

裏画面の内容を表画面に反映します。VBlank を待ってからコピーするため、 画面のちらつきが起きません。


DVI::Graphics(グラフィックスモード)

グラフィックスモードでは、ピクセル単位で画面に描画できます。 色は RGB332 形式(1バイト)で指定します。

画面の制御

DVI::Graphics.width

DVI::Graphics.width  #=> 640 または 320

フレームバッファの幅をピクセル数で返します。

DVI::Graphics.height

DVI::Graphics.height  #=> 480 または 240

フレームバッファの高さをピクセル数で返します。

DVI::Graphics.set_resolution(width, height)

DVI::Graphics.set_resolution(320, 240)  # 320x240 に切り替え
DVI::Graphics.set_resolution(640, 480)  # 640x480 に戻す

画面の解像度を切り替えます。指定できるのは 640x480(初期値)と 320x240 の2種類です。

DVI::Graphics.fill(color)

DVI::Graphics.fill(0x00)  # 画面を黒で塗りつぶす

画面全体を指定した RGB332 カラーで塗りつぶします。

DVI::Graphics.commit

DVI::Graphics.commit

VBlank を待ってから裏画面の内容を表画面にコピーして表示します。 1フレームぶんの描画が終わったあとに呼び出してください。

ピクセル操作

DVI::Graphics.set_pixel(x, y, color)

DVI::Graphics.set_pixel(100, 50, 0xFF)

(x, y) の位置のピクセルを指定した RGB332 カラーに設定します。

DVI::Graphics.get_pixel(x, y)

c = DVI::Graphics.get_pixel(100, 50)

(x, y) の位置にあるピクセルの RGB332 カラー値を返します。 範囲外の場合は 0 を返します。

図形の描画

図形の描画メソッドには、塗りつぶし用(fill_ ではじまるもの)と 輪郭線のみ(draw_ ではじまるもの)の2種類があります。

DVI::Graphics.fill_rect(x, y, w, h, color)

DVI::Graphics.fill_rect(10, 10, 100, 50, 0xE0)

(x, y) を左上の角として、幅 w、高さ h の塗りつぶした長方形を描きます。

DVI::Graphics.draw_rect(x, y, w, h, color)

DVI::Graphics.draw_rect(10, 10, 100, 50, 0xFF)

(x, y) を左上の角として、幅 w、高さ h の長方形の輪郭を描きます。

DVI::Graphics.fill_circle(cx, cy, r, color)

DVI::Graphics.fill_circle(160, 120, 50, 0xE0)

(cx, cy) を中心、r を半径とする塗りつぶした円を描きます。

DVI::Graphics.draw_circle(cx, cy, r, color)

DVI::Graphics.draw_circle(160, 120, 50, 0xFF)

(cx, cy) を中心、r を半径とする円の輪郭を描きます。

DVI::Graphics.fill_ellipse(cx, cy, rx, ry, color)

DVI::Graphics.fill_ellipse(160, 120, 80, 40, 0xE0)

(cx, cy) を中心、rx と ry をそれぞれ横と縦の半径とする塗りつぶした楕円を描きます。

DVI::Graphics.draw_ellipse(cx, cy, rx, ry, color)

DVI::Graphics.draw_ellipse(160, 120, 80, 40, 0xFF)

(cx, cy) を中心とする楕円の輪郭を描きます。

DVI::Graphics.fill_triangle(x0, y0, x1, y1, x2, y2, color)

DVI::Graphics.fill_triangle(100, 10, 50, 90, 150, 90, 0x1C)

3つの頂点を結ぶ塗りつぶした三角形を描きます。

DVI::Graphics.fill_arc(cx, cy, r, start_angle, stop_angle, color)

DVI::Graphics.fill_arc(160, 120, 50, 0, Math::PI / 2, 0xE0)

塗りつぶした扇形を描きます。角度はラジアンで指定します(0 が右方向、PI/2 が下方向)。

DVI::Graphics.draw_arc(cx, cy, r, start_angle, stop_angle, color)

DVI::Graphics.draw_arc(160, 120, 50, 0, Math::PI / 2, 0xFF)

扇形の輪郭を描きます。

線の描画

DVI::Graphics.draw_line(x0, y0, x1, y1, color)

DVI::Graphics.draw_line(0, 0, 100, 100, 0xFF)

(x0, y0) から (x1, y1) へ線を引きます。

DVI::Graphics.draw_thick_line(x0, y0, x1, y1, thickness, color)

DVI::Graphics.draw_thick_line(0, 0, 100, 100, 3, 0xFF)

太さ thickness ピクセルの線を引きます。

テキストの描画

DVI::Graphics.draw_text(x, y, text, color, font = FONT_8X8, wide_font = nil)

# 基本的な使い方
DVI::Graphics.draw_text(10, 10, "Hello!", 0xFF)

# フォントを指定
DVI::Graphics.draw_text(10, 10, "Hello!", 0xFF, DVI::Graphics::FONT_MPLUS_12)

# 日本語フォントも指定
DVI::Graphics.draw_text(10, 10, "こんにちは", 0xFF,
  DVI::Graphics::FONT_MPLUS_12, DVI::Graphics::FONT_MPLUS_J12)

(x, y) の位置に UTF-8 文字列を描画します。 第5引数にフォント、第6引数に全角文字用フォントを指定できます。

DVI::Graphics.text_width(text, font = FONT_8X8, wide_font = nil)

w = DVI::Graphics.text_width("Hello!", DVI::Graphics::FONT_MPLUS_12)

文字列を描画したときの幅をピクセル数で返します(実際には描画しません)。

DVI::Graphics.font_height(font)

h = DVI::Graphics.font_height(DVI::Graphics::FONT_MPLUS_12)

指定したフォントのグリフの高さをピクセル数で返します。

画像の描画

DVI::Graphics.draw_image(data, x, y, w, h)

DVI::Graphics.draw_image(pixel_data, 10, 10, 32, 32)

RGB332 形式の画像データ(バイト列)を (x, y) の位置に描画します。 data の長さは w * h バイト以上が必要です。

DVI::Graphics.draw_image_masked(data, mask, x, y, w, h)

DVI::Graphics.draw_image_masked(pixel_data, mask_data, 10, 10, 32, 32)

透過マスク付きで画像を描画します。 mask は 1bpp(1ビット/ピクセル)の透過マスクで、1 のビットが不透明、0 のビットが透明です。 mask の長さは (w * h + 7) / 8 バイト以上が必要です。

ブレンドモード

DVI::Graphics.set_blend_mode(mode)

DVI::Graphics.set_blend_mode(DVI::Graphics::BLEND_ADD)

ピクセルの合成方法を変更します。

定数 動作
DVI::Graphics::BLEND_REPLACE 上書き(初期値)
DVI::Graphics::BLEND_ADD チャンネルごとに加算(飽和加算)
DVI::Graphics::BLEND_SUBTRACT チャンネルごとに減算(飽和減算)
DVI::Graphics::BLEND_MULTIPLY チャンネルごとに乗算
DVI::Graphics::BLEND_SCREEN チャンネルごとにスクリーン合成
DVI::Graphics::BLEND_ALPHA アルファブレンド(set_alpha で不透明度を設定)

DVI::Graphics.set_alpha(alpha)

DVI::Graphics.set_alpha(128)  # 半透明

BLEND_ALPHA モード時の不透明度(0〜255)を設定します。 0 で完全に透明、255 で完全に不透明になります。


色の形式

グラフィックスモードでは RGB332 形式(1バイト)で色を指定します。

ビット 7-5: 赤(0〜7)
ビット 4-2: 緑(0〜7)
ビット 1-0: 青(0〜3)

よく使う色の例:

0x00
0xFF
0xE0
0x1C
0x03
0xFC

P5 描画ライブラリcolor(r, g, b) メソッドを使うと、通常の RGB 値(0〜255) から RGB332 に変換できます。


フォント一覧

DVI::Graphics で使えるフォントの定数です。

定数 説明
FONT_8X8 8x8 等幅フォント
FONT_MPLUS_12 M+ 12px プロポーショナルフォント
FONT_FIXED_4X6 Misc-Fixed 4x6 等幅フォント
FONT_FIXED_5X7 Misc-Fixed 5x7 等幅フォント
FONT_FIXED_6X13 Misc-Fixed 6x13 等幅フォント
FONT_SPLEEN_5X8 Spleen 5x8 等幅フォント
FONT_SPLEEN_8X16 Spleen 8x16 等幅フォント
FONT_SPLEEN_12X24 Spleen 12x24 等幅フォント
FONT_DENKICHIP DenkiChip 12px フォント(ASCII)
FONT_MPLUS_J12 M+ 12px 日本語フォント(JIS X 0208)
FONT_DENKICHIP_J DenkiChip 12px 日本語フォント(JIS X 0208)

日本語などの全角文字を表示するには、draw_text の wide_font 引数に FONT_MPLUS_J12 または FONT_DENKICHIP_J を指定します。