GTK4   カイロ

ホーム   C/C++チュートリアル  

カイロ入門

GTK において、グラフィックの描画を担当しているのがカイロ (Cairo) です。カイロはベクトルベースの 2D グラフィックスライブラリです。

例として cairo.c というファイルで作業していきます。

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
  

コード説明

  1. GtkWidget * area = gtk_drawing_area_new ();
    ドローイングエリア (drawing_area) を作成しています。グラフィックスはドローイングエリアの上に描画されます。
  2. gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw, NULL, NULL);
    ドローイングエリアが描画されるタイミングで呼び出される関数を設定しています。
    呼び出されるタイミングは、ドローイングエリアが最初に表示された時と、ドローイングエリアがリサイズされた時と、 gtk_widget_queue_draw 関数が呼びだされたときです。
  3. draw (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data)
    これが呼び出される関数です。

draw 関数で実際にすることを記述していきます。

cairo.c


#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
  
  // 結果
 次のような色のウィンドウが起動します
  

コード説明

  1. GdkRGBA color;
    GTK で色を保持する GdkRGBA 型の変数を宣言しています。GdkRGBA は次のような構造体になっています。
    
      struct GdkRGBA {
      	gdouble red;
      	gdouble green;
      	gdluble blue;
      	gdouble alpha;
      }
      
    各メンバーは、0.0 から 1.0 までの値を保持します。alpha メンバーは opacity(不透明度)で、0.0 で透明、1.0 で不透明です。alpha メンバーは 1.0 で初期化されています。それ以外のメンバーの初期値は不定値です。 どのような値が入っているか分からないので、必ず値を設定してから使います。
  2. gchar *rgb;
    GTK で文字列を保持する gchar 型の変数を宣言しています。
  3. rgb = g_strdup_printf ("rgb(%d,%d,%d)", r, g, b);
    g_strdup_rintf は、引数で指定した書式の文字列を作ります。色は0 〜 255の範囲で指定します。 1 を表す変数もしくは 1 という数値を設定した場合は、0 〜 1.0 の 1.0 ではなく、 0 〜 255 の中の 1 という意味になります。
  4. gdk_rgba_parse (&color, rgb);
    gdk_rgba_parse 関数は文字列で表された色を、カイロの色として変数 color に設定します。
  5. g_free (rgb);
    rgb は gchar *型なので関数が終了してもポインターは破棄されますが、実際の値が格納されたメモリーは解放されません。 g_free 関数で値が格納されたメモリーを解放しておきます。
  6. gdk_cairo_set_source_rgba (cr, &color);
    カイロ (cr) に color が表す色を設定しています。変数 cr は、この draw 関数の引数で宣言されています。
  7. cairo_paint (cr)
    cairo_paint はカイロに設定された色でドローイングエリアを塗りつぶします。

追加説明

ドローイングエリア (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 型が推奨されているという記事を読んだような気がします。

GdkRGBA 型に 255 を超える値を設定した場合

変数で設定するか数値 (リテラル) で設定するかによって違います。


// 変数を用いた場合

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 になり、青になります。


237 visits
Posted: Mar. 20, 2025
Update: Mar. 22, 2025

ホーム   C/C++チュートリアル   目次