CairoとSDLを組合せてつかう
cairoの描画フロントエンドとしてSDLを使ってみた。ちょっと画面に表示させるだけなのにCocoaだのなんだのを使うのが面倒だったので…。
見た感じ、cairo image surfaceとSDL surfaceを比較すると、cairoの方がピクセルフォーマットに対する許容度が低かったので、SDL側でフォーマット差を吸収させています。たとえば、cairo image surfaceではRGB888の24bppフォーマットが使えません。
なお、リソースの開放はしてますが、エラーチェックはしてません。
#include <cmath> #include <memory> #include <cairo/cairo.h> #include <SDL/SDL.h> const int W = 640; const int H = 480; template <class T, class F> std::unique_ptr<T, F> wrap_ptr(T* p, F&& f) { return std::unique_ptr<T, F>(p, std::forward<F>(f)); } template <class Pre, class Post> struct scoped_guard_fn { scoped_guard_fn(Pre&& pre, Post&& post) : post_(std::forward<Post>(post)) { pre(); } ~scoped_guard_fn() { post_(); } private: Post post_; }; template <class Pre, class Post> scoped_guard_fn<Pre, Post> scoped_guard(Pre&& pre, Post&& post) { return scoped_guard_fn<Pre, Post>(std::forward<Pre>(pre), std::forward<Post>(post)); } int main(int, char**) { auto _sdl = scoped_guard(std::bind(SDL_Init, SDL_INIT_VIDEO), SDL_Quit); auto screen = SDL_SetVideoMode(W, H, 0, SDL_SWSURFACE | SDL_DOUBLEBUF); auto cs = wrap_ptr(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H), cairo_surface_destroy); auto cr = wrap_ptr(cairo_create(cs.get()), cairo_destroy); auto s = wrap_ptr(SDL_CreateRGBSurfaceFrom(cairo_image_surface_get_data(cs.get()), W, H, 32, cairo_image_surface_get_stride(cs.get()), 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000), SDL_FreeSurface); cairo_set_source_rgb(cr.get(), 1, 1, 1); cairo_rectangle(cr.get(), 0, 0, W, H); cairo_fill(cr.get()); cairo_set_source_rgb(cr.get(), 0, 0, 0); cairo_arc(cr.get(), W / 2, H / 2, 60, 0, 2 * M_PI); cairo_stroke(cr.get()); SDL_BlitSurface(s.get(), NULL, screen, NULL); SDL_Flip(screen); for (;;) { SDL_Event ev; SDL_WaitEvent(&ev); if (ev.type == SDL_QUIT) { break; } } return 0; }