Evas

http://www.enlightenment.org/Libraries/Evas/
Evasでちょっと遊んでみた。それなりにおもしろい。
Enlightenment(綴りがむずい)の次バージョン(DR17)で使われるグラフィックライブラリ、らしい。なんだけど、単体でも使える。
http://enlightenment.freedesktop.org/
ダウンロードはここから。


あー、説明するのが面倒になってきた(なんじゃそりゃ)。とりあえず気が付いたのは、

  • インターフェースがなんか
  • XRenderは遅いんでは
  • 他細々と


2D描画ライブラリっていうと、画面の一部が書きかわるときにグラフィクスコンテクストがうんぬんでDraw_XXを呼ぶんだとか、そういうイメージがあるんだけど、Evasはちょっと違う。
描画オブジェクトを置いていって、あとは適当にrenderしていく。

	Evas_Object *line = evas_object_line_add( screen );
	evas_object_line_xy_set( line, 0, 0, 300, 200 );
	evas_object_color_set( line, 0xff, 0x00, 0xff, 0xff );
	evas_object_show( line );

	evas_render( screen );

こんな感じにしてやれば線が引ける。あとはこの線を動かすのは、evas_object_line_xy_setしたりとか、evas_object_moveするだとか。


Exposeイベントが飛んできた場合などは、その矩形を教えてやれば終わり。

		case Expose:
			evas_damage_rectangle_add( screen,
						   ev.xexpose.x,
						   ev.xexpose.y,
						   ev.xexpose.width,
						   ev.xexpose.height );
			evas_render( screen );
			break;
		}


こうやることで、dirty rect管理を全部中でやってくれるようになってるので非常に良い。っていうか、ウィンドウシステム用のだったら、確かにこういうインターフェースのほうが正解だと思ったんだけど、あんまり見ないな。僕が知らないだけかもしれんが。


そこらへんがなんか。


あと、バックエンドに、全部ソフトウェア、XRender、GL、その他諸々が選べたりするんだけど、ハードウェア機能を使ってるはずのXRenderが遅い。GLは速かったんだけど。
XRenderは謎だな。XRenderの理解は昔一回挫折してるのでよくない。


適当に書いたのが以下。

#include <X11/keysym.h>
#include <Evas.h>
#include <Evas_Engine_Software_X11.h>
#include <Evas_Engine_XRender_X11.h>
#include <stdio.h>

Evas *screen;
Display *display;
Window win;

static void
set_info( void )
{
	Evas_Engine_Info_Software_X11 *info = (Evas_Engine_Info_Software_X11*)evas_engine_info_get( screen );
	info->info.display = display;
	info->info.visual = DefaultVisual( display, DefaultScreen(display) );
	info->info.colormap = DefaultColormap( display, DefaultScreen(display) );
	info->info.drawable = win;
	info->info.depth = DefaultDepth( display, DefaultScreen(display) );
	info->info.rotation = 0;
	info->info.debug = 0;

	evas_engine_info_set( screen, (Evas_Engine_Info*)info );
}


static void
mainloop(void)
{
	int x=0, y=0;
	Evas_Object *line = evas_object_line_add( screen );
	Evas_Object *rect = evas_object_rectangle_add( screen );
	Evas_Object *rect2 = evas_object_rectangle_add( screen );
	Evas_Object *grad = evas_object_gradient_add( screen );
	evas_object_line_xy_set( line, 0, 0, 300, 200 );
	evas_object_color_set( line, 0xff, 0x00, 0xff, 0xff );
	evas_object_show( line );

	evas_object_move( rect, 100, 100 );
	evas_object_resize( rect, 300, 300 );
	evas_object_color_set( rect, 0x00, 0xff, 0xff, 0x33 );
	evas_object_show( rect );
	evas_object_move( rect2, 150, 150 );
	evas_object_resize( rect2, 300, 300 );
	evas_object_color_set( rect2, 0x00, 0xff, 0xff, 0x33 );
	evas_object_show( rect2 );

	evas_object_gradient_color_add( grad, 0, 0xff, 0xff, 0x33, 40 );
	evas_object_gradient_color_add( grad, 0, 0xff, 0x00, 0xff, 40 );
	evas_object_gradient_angle_set( grad, 90.0f );
	evas_object_move( grad, 50, 50 );
	evas_object_resize( grad, 300, 300 );

	evas_object_show( grad );

	XMapWindow( display, win );
	XRaiseWindow( display, win );

	while ( 1 ) {
		XEvent ev;
		XNextEvent( display, &ev );
		switch ( ev.type ) {
		case KeyPress: {
			KeySym sym = XKeycodeToKeysym( display,
						       ev.xkey.keycode,
						       0 );
			switch ( sym ) {
			case XK_Escape:
				goto end;
			case XK_Right:
				x+=4;
				evas_object_move( line, x, y );
				evas_render( screen );
				break;
			case XK_Left:
				x-=4;
				evas_object_move( line, x, y );
				evas_render( screen );
				break;

			case XK_Up:
				y-=4;
				evas_object_move( line, x, y );
				evas_render( screen );
				break;

			case XK_Down:
				y+=4;
				evas_object_move( line, x, y );
				evas_render( screen );
				break;
			}
			break;
		}
		case Expose:
			evas_damage_rectangle_add( screen,
						   ev.xexpose.x,
						   ev.xexpose.y,
						   ev.xexpose.width,
						   ev.xexpose.height );
			evas_render( screen );
			break;
		}
	}
 end:
	evas_object_del( line );
}


int
main()
{
	display = XOpenDisplay( NULL );
	win = XCreateSimpleWindow( display,
				   DefaultRootWindow(display),
				   0, 0,
				   640, 480, 1, 1, WhitePixel(display,
							      DefaultScreen(display)));
	evas_init();

	screen = evas_new();
	evas_output_method_set( screen,
				evas_render_method_lookup("software_x11") );

	set_info( );
	XSelectInput( display, win, KeyPressMask|ExposureMask );

	evas_output_size_set( screen, 640, 480 );
	evas_output_viewport_set( screen, 0, 0, 640, 480 );

	mainloop( );

	evas_free( screen );

	XDestroyWindow( display, win );
	XCloseDisplay( display );

	evas_shutdown();

	return 0;
}