なぜかCairo

Cのポインタと構造体の練習として、スタック、キューに続いて連結リストを作ってみようと思った。ちょろっと書き始めてみたところ、何だか思ったよりも関数の個数が必要で大がかりなので、無味乾燥な例ではやる気にならない。せっかくやるなら、少しぐらいは実例っぽいものを。

とか思って最初に思いついたのは図形オブジェクト。折れ線とか、曲線とか、多角形とか、オブジェクトに含まれる頂点の数が任意に伸びてほしくてつながっている感じのもの。

とか思って2DのベクトルグラフィックライブラリのCairoを調べてみたら、結局CairoとX11(Xlib?)の基本的な使い方みたいなことを調べたりして、ふむふむなるほど、ライブラリってのは、そうやって使うのかとやってる間にリストにはたどり着きもしなかった。

以下、ほとんどどっかのサイトから取ってきてあれこれやった結果。

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xutil.h>
#include <X11/Xlib.h>
#include <cairo.h>
#include <cairo-xlib.h>

Display* disp;
int screenNumber;
unsigned long white, black;
int width, height;

void paint(cairo_surface_t *cs){
  cairo_t *c;
  int i;

  c = cairo_create(cs);
  cairo_rectangle(c, 0.0, 0.0, width, height);
  cairo_set_source_rgb(c, 0.0, 0.0, 0.3);
  cairo_fill(c);
  cairo_set_font_size (c, 80.0);
  for (i = 0; i < 5; i++) {
    cairo_set_source_rgb(c, 1.0 - i * 0.2, 1.0 - i * 0.2, 0.0);
    cairo_move_to(c, 20.0 + i * 10, 80.0 + i * 10);
    cairo_show_text(c, "こんにちは!");
  }
  cairo_show_page(c);
  cairo_destroy(c);
}

int main(int argc, char** argv){
  disp = XOpenDisplay(NULL);
  if(disp==NULL) exit(1);
  screenNumber = DefaultScreen(disp);
  white = WhitePixel(disp,screenNumber);
  black = BlackPixel(disp,screenNumber);
  cairo_surface_t *cs;
  width = 640;
  height = 480;
  Window win = XCreateSimpleWindow(disp,
				   RootWindow(disp, screenNumber),
				   0, 0,   // origin
				   width, height, // size
				   0, black, // border
				   black );  // backgd
  XMapWindow(disp, win);
  XStoreName(disp, win, "Hello World!");
  XSelectInput(disp, win, ExposureMask|ButtonPressMask);
  cs=cairo_xlib_surface_create(disp, win, DefaultVisual(disp, 0), 200, 200);
  XEvent evt;
  while(1) {
    XNextEvent(disp, &evt);
    if(evt.type==Expose && evt.xexpose.count<1) {
      width = evt.xexpose.width;
      height = evt.xexpose.height;
      cairo_surface_destroy(cs);
      cs=cairo_xlib_surface_create(disp, win, DefaultVisual(disp, 0), width, height);
    }
    paint(cs);
  }
  cairo_surface_destroy(cs);
  XDestroyWindow(disp, win);
  XCloseDisplay(disp);
  return 0;
}
$ gcc -Wall `pkg-config --cflags --libs cairo` hello.c ;./a.out

で、実行結果は以下。

それにしても、色々手を出してすべてでHello worldだけやっててもしょうがないだろうと、自分のことながら思ったりもする。