GTK において、グラフィックの描画を担当しているのがカイロ (Cairo) です。カイロはベクトルベースの 2D グラフィックスライブラリです。
例として cairo.c というファイルで作業していきます。
#include <gtk/gtk.h>
static void
draw (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data)
{
g_print ("draw\n");
}
static void
activate (GApplication *app, gpointer data)
{
GtkWidget * win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_title (GTK_WINDOW (win), "Cairo");
GtkWidget * area = gtk_drawing_area_new ();
gtk_window_set_child (GTK_WINDOW (win), area);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw, NULL, NULL);
gtk_window_present (GTK_WINDOW (win));
}
int
main (int argc, char **argv)
{
GtkApplication * app;
int stat;
app = gtk_application_new ("com.usodesu.cairo", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
stat = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return stat;
}
// ビルド
cc cairo.c -o cairo `pkg-config --cflags --libs gtk4`
// 実行
./cairo
// 起動した時とウィンドウ(ドローイングエリア)をリサイズした時に、ターミナルに draw と表示されます
draw
draw 関数で実際にすることを記述していきます。
#include <gtk/gtk.h>
static void
draw (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data)
{
guchar r = 100; // 外部からの入力があることを想定して変数を用いていま
guchar g = 128; // 外部からの入力があることを想定して変数を用いています
guchar b = 128; // 外部からの入力があることを想定して変数を用いています
GdkRGBA color;
gchar *rgb;
rgb = g_strdup_printf ("rgb(%d,%d,%d)", r, g, b);
gdk_rgba_parse (&color, rgb);
//rgb = g_strdup_printf ("rgb(%d,%d,%d)", 100, 128, 128); これもできます
//gdk_rgba_parse (&color, "#777"); これもできます
//gdk_rgba_parse (&color, "#777777"); これもできます
//gdk_rgba_parse (&color, "rgb(100, 128, 128)"); これもできます
//gdk_rgba_parse (&color, "rgb(r, g, b )"); これはできません。
// rgb () の中で変数を用いることはできません
g_free (rgb);
gdk_cairo_set_source_rgba (cr, &color);
cairo_paint (cr);
}
static void
activate (GApplication *app, gpointer data)
{
GtkWidget * win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_title (GTK_WINDOW (win), "Cairo");
GtkWidget * area = gtk_drawing_area_new ();
gtk_window_set_child (GTK_WINDOW (win), area);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw, NULL, NULL);
gtk_window_present (GTK_WINDOW (win));
}
int
main (int argc, char **argv)
{
GtkApplication * app;
int stat;
app = gtk_application_new ("com.usodesu.cairo", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
stat = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return stat;
}
// ビルド
cc cairo.c -o cairo `pkg-config --cflags --libs gtk4`
// 実行
./cairo
// 結果
次のような色のウィンドウが起動します
struct GdkRGBA {
gdouble red;
gdouble green;
gdluble blue;
gdouble alpha;
}
各メンバーは、0.0 から 1.0 までの値を保持します。alpha メンバーは opacity(不透明度)で、0.0 で透明、1.0 で不透明です。alpha メンバーは 1.0 で初期化されています。それ以外のメンバーの初期値は不定値です。
どのような値が入っているか分からないので、必ず値を設定してから使います。ドローイングエリア (drawing_area) は、絵を描くときのキャンバスで、カイロ (cairo_t *) は絵を描くときの筆です。 この筆はブラシになったりバケツになったりもします。GTK において色は赤、緑、青をそれぞれ 0.0 〜 1.0 までの浮動小数点数で保持します。 カイロに色を設定するには次の二つの関数があります。
cairo_set_source_rgb (cr, r, g, b);
r, g, b は、それぞれ変数でも数値でも買いませんが、0.0 〜 1.0 の値にしなければなりません。1.0 を超えた場合は 1.0 と解釈されます。
gdk_cairo_set_source_rgba (cr, &color);
前述の GdkRGBA 型が表す色の値をカイロに設定します。
GdkRGBA 型を使うには前述のサンプルコードのように数段階のステップを踏む必要がありますが、伝統的な 8 ビットの色の範囲 (0 〜 255) が使えます。
GdkRGBA 型で 255 を超えた場合は、2つのケースが考えられますので後述します。
どちらを使うかはケースバイケースでしょうが、RGBA 型が推奨されているという記事を読んだような気がします。
変数で設定するか数値 (リテラル) で設定するかによって違います。
// 変数を用いた場合
guchar r, g, b;
b = 256;
rgb = g_strdup_printf ("rgb(%d,%d,%d)", r, g, b);
gdk_rgba_parse (&color, rgb);
gdk_cairo_set_source_rgba (cr, &color);
guchar は 0 〜 255 の値しか保持できないため 256 を代入した場合は 0 になります。
結果 r と g は初期値の 0 に、b も 0 になり、黒になります。
// 数値を用いた場合
gdk_rgba_parse (&color, "rgb(0, 0, 256)");
gdk_rgba_parse (&color, rgb);
gdk_cairo_set_source_rgba (cr, &color);
255 も 256 も 1.0 に変換され、結果 r と g は初期値の 0 に、b は 1.0 になり、青になります。