changeset 1067:7b4e80ab671a openvg

merge from default branch
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 01 Dec 2010 12:25:56 +0800
parents bd18951b51d5 (diff) 292fbb86d8f3 (current diff)
children aed05ad5102d
files configure.ac examples/calculator/Makefile.am include/mb_basic_types.h include/mb_config.h.in include/mb_graph_engine.h include/mb_graph_engine_cairo.h include/mb_graph_engine_skia.h include/mb_types.h nodejs/X_supp_njs.c nodejs/X_supp_njs.h nodejs/testcase.js src/Makefile.am src/X_supp.c src/dfb_supp.c src/event.c src/graph_engine_cairo.c src/graph_engine_dfb.c src/graph_engine_skia.cpp src/img_ldr.c src/img_ldr_imlib2.c src/paint.c src/redraw_man.c
diffstat 10 files changed, 1496 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Tue Nov 30 03:57:36 2010 +0800
+++ b/configure.ac	Wed Dec 01 12:25:56 2010 +0800
@@ -26,6 +26,12 @@
 AC_TYPE_UINT32_T
 AC_TYPE_UINT64_T
 
+# Explicit initialize pkg-config for conditional PKG_CHECK_MODULE
+# see http://www.flameeyes.eu/autotools-mythbuster/autoconf/macros.html
+# and http://www.flameeyes.eu/autotools-mythbuster/ \
+#		pkgconfig/pkg_check_modules.html
+PKG_PROG_PKG_CONFIG
+
 # Checks for library functions.
 AC_FUNC_MALLOC
 AC_FUNC_REALLOC
@@ -64,23 +70,48 @@
     AC_DEFINE([SH_STEXT])
 [fi]
 
+AC_ARG_ENABLE([mbaf],
+	[ --disable-mbaf	Turn off mbaf],
+[case "${enableval}" in
+  yes) mbaf=true ;;
+  no) mbaf=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --disable-mbaf]) ;;
+esac],[mbaf=true])
+
 AC_ARG_WITH([backend],
         [AS_HELP_STRING([--with-backend=FOO],[Use FOO as display backend (default is 'X')])],
         [case "${withval}" in
-            ('X') backend='X' ;;
-            ('dfb') backend='dfb' ;;
-            ('no') backend='none' ;;
+            ('X') backend='X'; default_graphic_engine="cairo" ;;
+            ('dfb') backend='dfb'; default_graphic_engine="dfb" ;;
+            ('no') backend='none'; default_graphic_engine="cairo" ;;
             (*) AC_MSG_ERROR([bad value ${withval} for --with-backend]) ;;
-        esac],[backend='X'])
+        esac],[backend='X'; default_graphic_engine="cairo"])
 
-AC_ARG_ENABLE([skia],
-        [AS_HELP_STRING([--enable-skia],[Turn on Skia instead of Cairo])],
-        [case "${enableval}" in
-            (yes) skia=true ;;
-            (no) skia=false ;;
-            (*) AC_MSG_ERROR([bad value ${enableval} for --enable-skia]) ;;
-        esac],[skia=false])
+AC_ARG_WITH([graphic-engine],
+	[AS_HELP_STRING([--with-graphic-engine=FOO],
+			[Use FOO as graphic engine (default is '${default_graphic_engine}')])],
+	[case "${withval}" in
+	    ('cairo') graphic_engine="cairo" ;;
+	    ('skia') graphic_engine="skia" ;;
+	    ('openvg') graphic_engine="openvg" ;;
+	    ('dfb') graphic_engine="dfb" ;;
+	    (*) AC_MSG_ERROR([bad value ${withval} for --with-graphic-engine])
+	    	;;
+	esac], [graphic_engine="${default_graphic_engine}"])
 
+AC_ARG_WITH([image-loader],
+	[AS_HELP_STRING([--with-image-loader=FOO],
+			[Use FOO as image loader (default is 'cairo')])],
+	[case "${withval}" in
+	    ('cairo') image_loader="cairo" ;;
+	    ('imlib2') image_loader="imlib2" ;;
+	    ('no') image_loader="none" ;;
+	    (*) AC_MSG_ERROR([bad value ${withval} for --with-image-loader])
+	    	;;
+	esac], [image_loader="cairo"])
+
+xshm=false
+[if [ x"${backend}" = x"X" ]; then ]
 AC_ARG_ENABLE([xshm],
 	[AS_HELP_STRING([--disable-xshm],[Turn off XSHM supporting])],
 	[case "${enableval}" in
@@ -88,18 +119,24 @@
 	    (no) xshm=false ;;
 	    (*) AC_MSG_ERROR([bad value ${enableval} for --disable-xshm]) ;;
 	esac], [xshm=true])
-
-AM_CONDITIONAL([SKIA_GRAPH_ENGINE], [test x$skia = xtrue])
-AM_CONDITIONAL([CAIRO_GRAPH_ENGINE], [test x$skia != xtrue])
+[fi]
 
-[if [ x"${skia}" = xtrue ]; then ]
+[if [ x"${graphic_engine}" = x"skia" ]; then ]
     AC_DEFINE([SKIA_GRAPH_ENGINE])
-    cairo=false
+[elif [ x"${graphic_engine}" = x"openvg" ]; then ]
+    AC_DEFINE([OPENVG_GRAPH_ENGINE])
+[elif [ x"${graphic_engine}" = x"dfb" ]; then ]
+    AC_DEFINE([DFB_GRAPH_ENGINE])
 [else]
     AC_DEFINE([CAIRO_GRAPH_ENGINE])
-    cairo=true
 [fi]
 
+AM_CONDITIONAL([SKIA_GRAPH_ENGINE], [test x"${graphic_engine}" = x"skia"])
+AM_CONDITIONAL([OPENVG_GRAPH_ENGINE], [test x"${graphic_engine}" = x"openvg"])
+AM_CONDITIONAL([DFB_GRAPH_ENGINE], [test x"${graphic_engine}" = x"dfb"])
+AM_CONDITIONAL([CAIRO_GRAPH_ENGINE], [test x"${graphic_engine}" = x"cairo"])
+AM_CONDITIONAL([MBAF], [test x"$mbaf" = xtrue])
+
 AC_ARG_ENABLE([nodejs],
         [AS_HELP_STRING([--enable-nodejs],[Turn on nodejs support])],
         [case "${enableval}" in
@@ -117,35 +154,63 @@
 
 # Define AM and AC variable for sh_text
 
-AM_CONDITIONAL([SH_TEXT], [test x$sh_text = xtrue -a x$cairo = xtrue])
+AM_CONDITIONAL([SH_TEXT],
+	[test x$sh_text = xtrue -a x"${graphic_engine}" = x"cairo"])
 
-[if [ x"${sh_text}" = xtrue -a x$cairo = xtrue ]; then]
+[if [ x"${sh_text}" = xtrue -a x"${graphic_engine}" = x"cairo" ]; then]
     AC_DEFINE([SH_TEXT])
 [fi]
 
 # Define AM and AC variable for display backend
 
-AM_CONDITIONAL([X_BACKEND], [test x$backend = x'X' -a x$cairo = xtrue])
+AM_CONDITIONAL([X_BACKEND],
+	[test x$backend = x'X' -a x"${graphic_engine}" = x"cairo"])
 
-[if [ x"${backend}" = x'X' -a x"${cairo}" = xtrue ]; then]
+[if [ x"${backend}" = x'X' -a x"${graphic_engine}" = x"cairo" ]; then]
     AC_DEFINE([X_BACKEND])
 [fi]
 
-AM_CONDITIONAL([DFB_BACKEND], [test x$backend = x'dfb' -a x$cairo = xtrue])
+AM_CONDITIONAL([DFB_BACKEND],
+	[test x$backend = x'dfb' -a x"${graphic_engine}" = x"cairo"])
 
-[if [ x"${backend}" = x'dfb' -a x"${cairo}" = xtrue ]; then]
+[if [ x"${backend}" = x'dfb' -a x"${graphic_engine}" = x"cairo" ]; then]
     AC_DEFINE([DFB_BACKEND])
 [fi]
 
-AM_CONDITIONAL([XSHM], [test x"${xshm}" = xtrue -a x"${cairo}" = xtrue -a x$backend = x'X'])
+AM_CONDITIONAL([CAIRO_IMG_LOADER],
+	[test x"${image_loader}" = x"cairo"])
+
+[if [ x"${image_loader}" = x"cairo" ]; then]
+    AC_DEFINE([CAIRO_IMG_LOADER])
+    [if [ x"${graphic_engine}" != x"cairo" ]; then]
+        AC_MSG_ERROR([bad value cairo for --with-image-loader while value of --with-graphic-engine is not cairo])
+    [fi]
+[fi]
 
-[if [ x"${xshm}" = xtrue -a x"${cairo}" = xtrue -a x$backend = x'X' ]; then]
+AM_CONDITIONAL([IMLIB2_IMG_LOADER],
+	[test x"${image_loader}" = x"imlib2"])
+
+[if [ x"${image_loader}" = x"imlib2" ]; then]
+    AC_DEFINE([IMLIB2_IMG_LOADER])
+[fi]
+
+AM_CONDITIONAL([XSHM],
+	[test x"${xshm}" = xtrue -a x"${graphic_engine}" = x"cairo" -a x$backend = x'X'])
+
+[if [ x"${xshm}" = xtrue -a x"${graphic_engine}" = x"cairo" -a x$backend = x'X' ]; then]
     AC_DEFINE([XSHM])
 [fi]
 
 # Checks for libraries.
+[if [ x"${graphic_engine}" = x"openvg" ]; then]
+AC_CHECK_HEADERS([GL/glut.h],, [AC_MSG_ERROR([can not find GL/glut.h])])
+[fi]
 
-[if [ x"${cairo}" = xtrue ]; then]
+[if [ x"${image_loader}" = x"imlib2" ]; then]
+PKG_CHECK_MODULES([imlib2], [imlib2 >= 1.4.1], , AC_MSG_ERROR([imlib2 >= 1.4.1 not found]))
+[fi]
+
+[if [ x"${graphic_engine}" = x"cairo" ]; then]
     PKG_CHECK_MODULES([cairo], [cairo >= 1.6], , AC_MSG_ERROR([cairo >= 1.6 not found]))
     #PKG_CHECK_MODULES([cairo2], [cairo2 >= 2.0], , AC_MSG_ERROR([cairo2 >= 2.0 not found]))
     [if [ x"${sh_text}" = xtrue ]; then]
@@ -174,7 +239,11 @@
 AH_TEMPLATE([SH_TEXT],[Enable sh_text object])
 AH_TEMPLATE([SH_STEXT],[Enable sh_stext object])
 AH_TEMPLATE([SKIA_GRAPH_ENGINE], [Enable Skia Graphic Engine])
+AH_TEMPLATE([OPENVG_GRAPH_ENGINE], [Enable OpenVG Graphic Engine])
 AH_TEMPLATE([CAIRO_GRAPH_ENGINE], [Enable Cairo Graphic Engine])
+AH_TEMPLATE([DFB_GRAPH_ENGINE], [Enable DirectFB Graphic Engine])
+AH_TEMPLATE([CAIRO_IMG_LOADER], [Enable Cairo Image Loader])
+AH_TEMPLATE([IMLIB2_IMG_LOADER], [Enable Imlib2 Image Loader])
 AH_TEMPLATE([X_BACKEND], [Enable X backend])
 AH_TEMPLATE([DFB_BACKEND], [Enable DirectFB backend])
 AH_TEMPLATE([XSHM], [Enable XSHM])
--- a/examples/menu/filebrowser.c	Tue Nov 30 03:57:36 2010 +0800
+++ b/examples/menu/filebrowser.c	Wed Dec 01 12:25:56 2010 +0800
@@ -51,14 +51,14 @@
     if (strcmp(data->titles[select],"..")==0) {
 	    strcpy(path, data->curDir);
 	    len = strlen(path);
-	    for(i=len-1;i>0;i--) {
+	    for(i=len-2;i>0;i--) {
 		    if (path[i] == '/') {
 			    path[i] = 0;
 			    break;
 		    }
 	    }
     } else {
-    	snprintf(path,1024,"%s/%s", data->curDir,data->titles[select]);
+    	snprintf(path,1024,"%s%s", data->curDir,data->titles[select]);
     }
 
     MyApp_fillDirInfo(app, path);
@@ -112,7 +112,8 @@
 
     printf("check %s\n",s);
 
-    if (endWith(s,".png")) {
+    if (endWith(s,".png") || endWith(s, ".jpg") ||
+	endWith(s, ".PNG") || endWith(s, ".JPG")) {
     	    snprintf(path,1024,"%s%s", data->curDir,data->titles[select]);
 	    mypreview(data,path);
     }
@@ -146,6 +147,8 @@
     DIR *dir;
     struct dirent *e;
     struct fileinfo *f;
+    char *path;
+    int sz;
     int i;
 
     dir = opendir(curdir);
@@ -156,7 +159,14 @@
 
     if (data->curDir)
 	    free(data->curDir);
-    data->curDir = strdup(curdir);
+    
+    sz = strlen(curdir);
+    if(curdir[sz - 1] != '/')
+	sz++;
+    data->curDir = (char *)malloc(sz + 1);
+    strcpy(data->curDir, curdir);
+    if(curdir[sz - 1] == '\0')
+	strcat(data->curDir, "/");
     
     if (data->files) {
 	    for(i=0;i<data->nFiles;i++) {
--- a/include/mb_config.h.in	Tue Nov 30 03:57:36 2010 +0800
+++ b/include/mb_config.h.in	Wed Dec 01 12:25:56 2010 +0800
@@ -9,6 +9,18 @@
 /* Enable Skia Graphic Engine */
 #undef SKIA_GRAPH_ENGINE
 
+/* Enable OpenVG Graphic Engine */
+#undef OPENVG_GRAPH_ENGINE
+
+/* Enable DirectFB Graphic Engine */
+#undef DFB_GRAPH_ENGINE
+
+/* Enable Cairo Image Loader */
+#undef CAIRO_IMG_LOADER
+
+/* Enable Imlib2 Image Loader */
+#undef IMLIB2_IMG_LOADER
+
 /* Enable sh_text */
 #undef SH_TEXT
 
--- a/include/mb_graph_engine.h	Tue Nov 30 03:57:36 2010 +0800
+++ b/include/mb_graph_engine.h	Wed Dec 01 12:25:56 2010 +0800
@@ -1,3 +1,15 @@
+/*! \page create_graph_engine Create a Graphic Engine.
+ *
+ * To create a graphic engine, you need to declare and define types
+ * and functions that had been declared in
+ * include/mb_graph_engine_cairo.h in a separated header an c file.
+ * Likes what mb_graph_engine_skia.h does.
+ *
+ * You should also add options in configure.ac to enable the graphic
+ * engine.  You also need to add lines in include/mb_config.h.in and
+ * include/mb_graph_engine.h to include correct header for the graphic
+ * engine enabled by the user.
+ */
 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
 // vim: sw=4:ts=8:sts=4
 #ifndef __MBE_H_
@@ -12,4 +24,8 @@
 #include <mb_graph_engine_skia.h>
 #endif
 
+#ifdef OPENVG_GRAPH_ENGINE
+#include <mb_graph_engine_openvg.h>
+#endif
+
 #endif /* __MBE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/mb_graph_engine_dummy.h	Wed Dec 01 12:25:56 2010 +0800
@@ -0,0 +1,99 @@
+/* This is a dummy Graphic Engine to consume all graphic operators.
+ */
+#ifndef __MB_GE_OPENVG_H_
+#define __MB_GE_OPENVG_H_
+
+#include <stdio.h>
+#include <GL/glut.h>
+#include "mb_basic_types.h"
+#include "mb_img_ldr.h"
+
+/*! \defgroup mb_ge_dummy Dummy Implementation of MadButterfly Graphic Engine
+ * @{
+ */
+#define mbe_pattern_create_for_surface(surface) ((mbe_pattern_t *)NULL)
+#define mbe_scaled_font_text_extents(scaled, utf8, extents)
+#define mbe_image_surface_get_stride(surface) (20)
+#define mbe_image_surface_get_format(surface) ((mb_img_fmt_t)0)
+#define mbe_image_surface_get_height(surface) (1)
+#define mbe_image_surface_get_width(surface) (1)
+#define mbe_image_surface_get_data(surface) ((unsigned char *)NULL)
+#define mbe_scaled_font_reference(scaled) ((mbe_scaled_font_t *)NULL)
+/* For OpenVG backend, never invoke xlib surface.
+ * #define mbe_xlib_surface_create cairo_xlib_surface_create
+ */
+#define mbe_pattern_create_radial(cx0, cy0, radius0,			\
+				  cx1, cy1, radius1, stops, stop_cnt)	\
+    ((mbe_pattern_t *)NULL)
+#define mbe_pattern_create_linear(x0, y0, x1, y1, stops, stop_cnt)	\
+    ((mbe_pattern_t *)NULL)
+#define mbe_pattern_create_image(img) ((mbe_pattern_t *)NULL)
+#define mbe_image_surface_create(fmt, w, h) ((mbe_surface_t *)NULL)
+#define mbe_scaled_font_destroy(scaled)
+#define mbe_font_face_reference(face) ((mbe_font_face_t *)NULL)
+#define mbe_scaled_font_create(face, fnt_mtx, ctm) ((mbe_scaled_font_t *)NULL)
+#define mbe_pattern_set_matrix(ptn, mtx)
+#define mbe_font_face_destroy(face)
+#define mbe_paint_with_alpha(canvas, alpha)
+#define mbe_surface_destroy(surface)
+#define mbe_set_source_rgba(canvas, r, g, b, a)
+#define mbe_set_scaled_font(canvas, scaled)
+#define mbe_pattern_destroy(pattern)
+#define mbe_get_scaled_font(canvas) ((mbe_scaled_font_t *)NULL)
+#define mbe_query_font_face(family, slant, weight) ((mbe_font_face_t *)NULL)
+#define mbe_free_font_face(face)
+#define mbe_set_line_width(canvas, w)
+#define mbe_set_source_rgb(canvas, r, g, b)
+#define mbe_get_font_face(canvas) ((mbe_font_face_t *)NULL)
+#define mbe_fill_preserve(canvas)
+#define mbe_copy_source(src_canvas, dst_canvas)
+#define mbe_set_source(canvas, pattern)
+#define mbe_reset_scissoring(canvas)
+#define mbe_get_target(canvas) ((mbe_surface_t *)NULL)
+#define mbe_close_path(canvas)
+#define mbe_text_path(canvas, utf8)
+#define mbe_transform(canvas, mtx)
+#define mbe_rectangle(canvas, x, y, w, h)
+#define mbe_in_stroke(canvas, x, y) (0)
+#define mbe_new_path(canvas)
+#define mbe_curve_to(canvas, x1, y1, x2, y2, x3, y3)
+#define mbe_restore(canvas)
+#define mbe_move_to(canvas, x, y)
+#define mbe_line_to(canvas, x, y)
+#define mbe_in_fill(canvas, x, y) (0)
+#define mbe_destroy(canvas)
+#define mbe_stroke(canvas)
+#define mbe_create(surface) ((mbe_t *)NULL)
+#define mbe_clear(canvas)
+#define mbe_paint(canvas)
+#define mbe_save(canvas)
+#define mbe_fill(canvas)
+/*! \brief Make scissoring rectangles.
+ *
+ * It would reset all previous pathes.
+ */
+#define mbe_scissoring(canvas, n_areas, areas)
+#define mbe_arc(canvas, x, y, radius, angle_start, angle_stop)
+
+/*! \brief Initialize graphic engine */
+#define mbe_init()
+
+typedef struct _mbe_text_extents_t mbe_text_extents_t;
+typedef int mbe_scaled_font_t;
+typedef int mbe_font_face_t;
+typedef int mbe_surface_t;
+typedef int mbe_pattern_t;
+typedef int mbe_t;
+
+struct _mbe_text_extents_t {
+    co_aix x_bearing;
+    co_aix y_bearing;
+    co_aix width;
+    co_aix height;
+    co_aix x_advance;
+    co_aix y_advance;
+};
+
+/* @} */
+
+#endif /* __MB_GE_OPENVG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/mb_graph_engine_openvg.h	Wed Dec 01 12:25:56 2010 +0800
@@ -0,0 +1,279 @@
+#ifndef __MB_GE_OPENVG_H_
+#define __MB_GE_OPENVG_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <EGL/egl.h>
+#include <VG/openvg.h>
+#include "mb_basic_types.h"
+#include "mb_img_ldr.h"
+
+/*! \defgroup mb_ge_openvg MadButterfly Graphic Engine with OpenVG
+ * @{
+ */
+#define mbe_scaled_font_text_extents(scaled, utf8, extents)
+#define mbe_image_surface_get_stride(surface) (20)
+#define mbe_image_surface_get_format(surface) ((mb_img_fmt_t)0)
+#define mbe_image_surface_get_height(surface) (surface)->h
+#define mbe_image_surface_get_width(surface) (surface)->w
+#define mbe_image_surface_get_data(surface) ((unsigned char *)NULL)
+#define mbe_scaled_font_reference(scaled) ((mbe_scaled_font_t *)NULL)
+#define mbe_scaled_font_destroy(scaled)
+#define mbe_font_face_reference(face) ((mbe_font_face_t *)NULL)
+#define mbe_scaled_font_create(face, fnt_mtx, ctm) ((mbe_scaled_font_t *)NULL)
+#define mbe_font_face_destroy(face)
+#define mbe_set_scaled_font(canvas, scaled)
+#define mbe_get_scaled_font(canvas) ((mbe_scaled_font_t *)NULL)
+#define mbe_query_font_face(family, slant, weight) ((mbe_font_face_t *)NULL)
+#define mbe_free_font_face(face)
+#define mbe_set_line_width(canvas, w)		\
+    do {					\
+	_MK_CURRENT_CTX(canvas);		\
+	vgSetf(VG_STROKE_LINE_WIDTH, w);	\
+    } while(0)
+#define mbe_set_source_rgb(canvas, r, g, b)	\
+    mbe_set_source_rgba(canvas, r, g, b, 1)
+#define mbe_get_font_face(canvas) ((mbe_font_face_t *)NULL)
+#define mbe_set_source(canvas, pattern)		\
+    do {					\
+	(canvas)->src = (pattern);		\
+	(canvas)->paint = (pattern)->paint;	\
+	(canvas)->paint_installed = 0;		\
+    } while(0)
+#define mbe_reset_scissoring(canvas)		\
+    do {					\
+	_MK_CURRENT_CTX(canvas);		\
+	vgSeti(VG_SCISSORING, VG_FALSE);	\
+    } while(0)
+#define mbe_get_target(canvas) ((mbe_surface_t *)(canvas)->tgt)
+#define mbe_close_path(canvas)			\
+    do {								\
+	char _vg_cmd = VG_CLOSE_PATH;					\
+	vgAppendPathData((canvas)->path, 1, &_vg_cmd, NULL);		\
+    } while(0)
+#define mbe_text_path(canvas, utf8)
+#define mbe_rectangle(canvas, x, y, w, h)
+#define mbe_in_stroke(canvas, x, y) (0)
+#define mbe_new_path(canvas)				\
+    vgClearPath((canvas)->path, VG_PATH_CAPABILITY_ALL)
+#define mbe_curve_to(canvas, x1, y1, x2, y2, x3, y3)
+#define mbe_move_to(canvas, x, y)					\
+    do {								\
+	VGfloat _vg_data[2] = {x, y};					\
+	char _vg_cmd = VG_MOVE_TO_ABS;					\
+	vgAppendPathData((canvas)->path, 1, &_vg_cmd, _vg_data);	\
+    } while(0)
+#define mbe_line_to(canvas, x, y)					\
+    do {								\
+	VGfloat _vg_data[2] = {x, y};					\
+	char _vg_cmd = VG_LINE_TO_ABS;					\
+	vgAppendPathData((canvas)->path, 1, &_vg_cmd, _vg_data);	\
+    } while(0)
+#define mbe_in_fill(canvas, x, y) (0)
+/* TODO: change prototype of mbe_arc() to remove mbe_save() and
+ *	 mbe_restore().
+ */
+#define mbe_save(canvas)
+#define mbe_restore(canvas)
+#define mbe_arc(canvas, x, y, radius, angle_start, angle_stop)
+
+typedef struct _mbe_text_extents_t mbe_text_extents_t;
+typedef int mbe_scaled_font_t;
+typedef int mbe_font_face_t;
+typedef struct _ge_openvg_surface mbe_surface_t;
+typedef struct _ge_openvg_pattern mbe_pattern_t;
+typedef struct _ge_openvg_mbe mbe_t;
+typedef struct _ge_openvg_img _ge_openvg_img_t;
+
+struct _mbe_text_extents_t {
+    co_aix x_bearing;
+    co_aix y_bearing;
+    co_aix width;
+    co_aix height;
+    co_aix x_advance;
+    co_aix y_advance;
+};
+
+struct _ge_openvg_mbe {
+    mbe_pattern_t *src;
+    VGPaint paint;		/*!< \brief The paint associated with
+				 * the src pattern */
+    int paint_installed;
+    mbe_surface_t *tgt;
+    EGLContext ctx;
+    VGPath path;
+
+    VGfloat mtx[9];
+};
+
+struct _ge_openvg_surface {
+    void *surface;
+    mbe_t *asso_mbe;		/* There is a association between
+				 * surface and mbe */
+    _ge_openvg_img_t *asso_img;
+    int w, h;
+};
+
+struct _ge_openvg_pattern {
+    _ge_openvg_img_t *asso_img;
+    VGfloat mtx[9];
+    VGPaint paint;
+};
+
+/*! \brief Information associated with VGImage.
+ *
+ * A VGImage can associated one of pattern or surface.  This type is
+ * used to make sure previous associated pattern or surface being
+ * released before new association.
+ *
+ * A _ge_openvg_img can be associated by mutltiple patterns and
+ * surfaces.  But, at most one of associated patterns or surfaces, the
+ * _ge_openvg_img can be activated for at any instant.
+ * _ge_openvg_img::activated_for trace the object it being activated
+ * for.  When a context will be current, the _ge_openvg_img associated
+ * with its surface would be activated for the surface.  When a paint
+ * wil be used, the _ge_openvg_img associated must be activated for
+ * the paint.  Before activated, the old activation must be
+ * deactivated.  _ge_openvg_img::deactivate_func is a pointer to
+ * deactivation function of activated pattern or surface.
+ *
+ * \sa _ge_openvg_img_t
+ * \note This is type is for internal using of OpenVG graphic engine.
+ */
+struct _ge_openvg_img {
+    int ref;
+    VGImage img;
+    void *activated_for;
+    void (*deactivate_func)(void *obj);
+};
+
+#define MB_MATRIX_2_OPENVG(vgmtx, mtx) do {	\
+	(vgmtx)[0] = (mtx)[0];			\
+	(vgmtx)[1] = (mtx)[1];			\
+	(vgmtx)[2] = (mtx)[2];			\
+	(vgmtx)[3] = (mtx)[3];			\
+	(vgmtx)[4] = (mtx)[4];			\
+	(vgmtx)[5] = (mtx)[5];			\
+	(vgmtx)[6] = 0;				\
+	(vgmtx)[7] = 0;				\
+	(vgmtx)[8] = 1;				\
+    } while(0)
+
+extern EGLNativeDisplayType _ge_openvg_disp_id;
+extern mbe_t *_ge_openvg_current_canvas;
+extern void _mbe_load_pattern_mtx(VGfloat *mtx1, VGfloat *mtx2, int mode);
+extern void _ge_vg_img_activate_for_pattern(mbe_pattern_t *ptn);
+extern void _ge_vg_img_activate_for_surface(mbe_surface_t *surf);
+
+extern mbe_pattern_t *mbe_pattern_create_for_surface(mbe_surface_t *surface);
+extern mbe_pattern_t *mbe_pattern_create_radial(co_aix cx0, co_aix cy0,
+						co_aix radius0,	
+						co_aix cx1, co_aix cy1,
+						co_aix radius1,
+						grad_stop_t *stops,
+						int stop_cnt);
+extern mbe_pattern_t *mbe_pattern_create_linear(co_aix x0, co_aix y0,
+						co_aix x1, co_aix y1,
+						grad_stop_t *stops,
+						int stop_cnt);
+extern mbe_pattern_t *mbe_pattern_create_image(mb_img_data_t *img);
+extern void mbe_pattern_destroy(mbe_pattern_t *ptn);
+extern void mbe_pattern_set_matrix(mbe_pattern_t *ptn, co_aix *mtx);
+extern void mbe_set_source_rgba(mbe_t *canvas, co_comp_t r, co_comp_t g,
+				co_comp_t b, co_comp_t a);
+/* TODO: rename n_areas to areas_cnt and make it after areas */
+extern void mbe_scissoring(mbe_t *canvas, int n_areas, area_t **areas);
+
+
+#define _VG_DISPLAY() eglGetDisplay(_ge_openvg_disp_id)
+
+/* \brief Make the context of a canvas to be current context.
+ *
+ * TODO: swtich VGImage between VGPaint and Surface.
+ */
+#define _MK_CURRENT_CTX(canvas) do {				\
+	if(_ge_openvg_current_canvas != (canvas)) {		\
+	    _ge_openvg_current_canvas = canvas;			\
+	    eglMakeCurrent(_VG_DISPLAY(),			\
+			   (canvas)->tgt->surface,		\
+			   (canvas)->tgt->surface,		\
+			   (canvas)->ctx);			\
+	}							\
+	/* \sa _ge_openvg_img_t */				\
+	_ge_vg_img_activate_for_surface((canvas)->tgt);		\
+    } while(0)
+/* TODO: switch VGImage between VGPaint and surface. */
+#define _MK_CURRENT_PAINT(canvas)					\
+    do {								\
+	if((canvas)->paint_installed == 0) {				\
+	    vgSetPaint((canvas)->paint, VG_FILL_PATH|VG_STROKE_PATH);	\
+	    (canvas)->paint_installed = 1;				\
+	}								\
+	/* \sa _ge_openvg_img_t */					\
+	if((canvas)->src)						\
+	    _ge_vg_img_activate_for_pattern((canvas)->src);		\
+    } while(0)
+
+#define mbe_transform(canvas, _mtx)				\
+    do {							\
+	_MK_CURRENT_CTX(canvas);				\
+	MB_MATRIX_2_OPENVG((canvas)->mtx, _mtx);		\
+	_mbe_load_pattern_mtx(_mtx, NULL,			\
+			      VG_MATRIX_PATH_USER_TO_SURFACE);	\
+    } while(0)
+
+
+#define EGL_GLX 1
+#ifdef EGL_GLX
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+extern mbe_surface_t *mbe_vg_win_surface_create(Display *display,
+						Drawable drawable,
+						Visual *visual,
+						int width, int height);
+#endif
+
+extern mbe_surface_t *mbe_image_surface_create(mb_img_fmt_t fmt,
+					       int w, int h);
+extern void mbe_surface_destroy(mbe_surface_t *surface);
+
+extern void mbe_copy_source(mbe_t *src_canvas, mbe_t *dst_canvas);
+extern mbe_t *mbe_create(mbe_surface_t *surface);
+extern void mbe_destroy(mbe_t *canvas);
+extern void mbe_paint_with_alpha(mbe_t *canvas, co_comp_t alpha);
+extern void mbe_paint(mbe_t *canvas);
+extern void mbe_clear(mbe_t *canvas);
+extern void mbe_init();
+
+static void
+mbe_stroke(mbe_t *canvas) {
+    _MK_CURRENT_CTX(canvas);
+    _MK_CURRENT_PAINT(canvas);
+    if(canvas->src)
+	_mbe_load_pattern_mtx(canvas->src->mtx, NULL,
+			      VG_MATRIX_STROKE_PAINT_TO_USER);
+
+    vgDrawPath(canvas->path, VG_STROKE_PATH);
+    vgClearPath(canvas->path, VG_PATH_CAPABILITY_ALL);
+}
+
+static void
+mbe_fill_preserve(mbe_t *canvas) {
+    _MK_CURRENT_CTX(canvas);
+    _MK_CURRENT_PAINT(canvas);
+    if(canvas->src)
+	_mbe_load_pattern_mtx(canvas->src->mtx, NULL,
+			      VG_MATRIX_FILL_PAINT_TO_USER);
+
+    vgDrawPath(canvas->path, VG_FILL_PATH);
+}
+
+static void
+mbe_fill(mbe_t *canvas) {
+    mbe_fill_preserve(canvas);
+    vgClearPath(canvas->path, VG_PATH_CAPABILITY_ALL);
+}
+/* @} */
+
+#endif /* __MB_GE_OPENVG_H_ */
--- a/src/Makefile.am	Tue Nov 30 03:57:36 2010 +0800
+++ b/src/Makefile.am	Wed Dec 01 12:25:56 2010 +0800
@@ -14,7 +14,7 @@
 noinst_PROGRAMS += testcase
 endif
 
-if X_BACKEND
+if MBAF
 MBAF_SOURCES=mbaf/mbapp.c mbaf/mbbutton.c mbaf/mbobject.c mbaf/animated_menu.c
 else
 MBAF_SOURCES=
@@ -24,7 +24,9 @@
 	observer.c paint.c redraw_man.c rotate.c shape_path.c		\
 	shape_rect.c shift.c subtree_free.c timer.c 			\
 	timertool.c tools.c visibility.c prop.c sprite.c	\
-	mouse.c shape_image.c img_ldr.c $(MBAF_SOURCES)
+	mouse.c shape_image.c $(MBAF_SOURCES)
+libmbfly_la_CPPFLAGS = @imlib2_CFLAGS@
+libmbfly_la_LDFLAGS = @imlib2_LIBS@
 
 if SH_TEXT
 libmbfly_la_SOURCES += shape_text.c
@@ -42,12 +44,20 @@
 libmbfly_la_SOURCES += dfb_supp.c
 endif
 
+if CAIRO_IMG_LOADER
+libmbfly_la_SOURCES += img_ldr.c
+endif
+
+if IMLIB2_IMG_LOADER
+libmbfly_la_SOURCES += img_ldr_imlib2.c
+endif
+
 libmbfly_la_LDFLAGS =
 
 if CAIRO_GRAPH_ENGINE
 libmbfly_la_SOURCES += graph_engine_cairo.c
 
-libmbfly_la_CPPFLAGS = @cairo_CFLAGS@ @pangocairo_CFLAGS@
+libmbfly_la_CPPFLAGS += @cairo_CFLAGS@ @pangocairo_CFLAGS@
 libmbfly_la_LDFLAGS += @cairo_LIBS@ @pangocairo_LIBS@
 endif
 
@@ -59,6 +69,15 @@
 libmbfly_la_SOURCES += graph_engine_skia.cpp
 endif
 
+if DFB_GRAPH_ENGINE
+libmbfly_la_SOURCES += graph_engine_dfb.c
+endif
+
+if OPENVG_GRAPH_ENGINE
+libmbfly_la_SOURCES += graph_engine_openvg.c
+libmbfly_la_LDFLAGS += -lOpenVG -lEGL
+endif
+
 X_main_SOURCES = X_main.c
 X_main_LDADD = $(top_builddir)/src/libmbfly.la
 X_main_CPPFLAGS = @pangocairo_CFLAGS@ -I$(top_builddir)/include
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/graph_engine_dfb.c	Wed Dec 01 12:25:56 2010 +0800
@@ -0,0 +1,1 @@
+/* Keep Me */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/graph_engine_openvg.c	Wed Dec 01 12:25:56 2010 +0800
@@ -0,0 +1,841 @@
+#include "mb_graph_engine_openvg.h"
+#include "mb_tools.h"
+
+EGLNativeDisplayType _ge_openvg_disp_id = EGL_DEFAULT_DISPLAY;
+mbe_t *_ge_openvg_current_canvas = NULL;
+
+#ifndef ASSERT
+#define ASSERT(x)
+#endif
+
+#define MB_2_VG_COLOR(r, g, b, a) ((((int)(0xf * r) & 0xf) << 24) |	\
+				   (((int)(0xf * g) & 0xf) << 16) |	\
+				   (((int)(0xf * b) & 0xf) << 16) |	\
+				   ((int)(0xf * a) & 0xf))
+
+#define MK_ID(mtx)				\
+    do {					\
+	(mtx)[0] = 1;				\
+	(mtx)[1] = 0;				\
+	(mtx)[2] = 0;				\
+	(mtx)[3] = 0;				\
+	(mtx)[4] = 1;				\
+	(mtx)[5] = 0;				\
+	(mtx)[6] = 0;				\
+	(mtx)[7] = 0;				\
+	(mtx)[8] = 1;				\
+    } while(0)
+
+/*! \brief Convert mb_img_fmt_t to VGImageFormat */
+static VGImageFormat
+_mb_ifmt_2_vgifmt(mb_img_fmt_t fmt) {
+    VGImageFormat vgifmt;
+    
+    switch(fmt) {
+    case MB_IFMT_ARGB32:
+	vgifmt = VG_sARGB_8888;
+	break;
+	
+    case MB_IFMT_RGB24:
+	vgifmt = -1;
+	break;
+	
+    case MB_IFMT_A8:
+	vgifmt = VG_A_8;
+	break;
+	
+    case MB_IFMT_A1:
+	vgifmt = -1;
+	break;
+	
+    case MB_IFMT_RGB16_565:
+	vgifmt = VG_sRGB_565;
+	break;
+	
+    default:
+	return -1;
+    }
+
+    return vgifmt;
+}
+
+/*! \brief create image object for OpenVG */
+static _ge_openvg_img_t *
+_alloc_vgimage(mb_img_fmt_t fmt, int w, int h) {
+    VGImage vg_img;
+    VGImageFormat vgifmt;
+    _ge_openvg_img_t *ge_img;
+    
+    vgifmt = _mb_ifmt_2_vgifmt(fmt);
+    if(vgifmt == -1)
+	return NULL;
+    vg_img = vgCreateImage(vgifmt, w, h,
+			   VG_IMAGE_QUALITY_NONANTIALIASED);
+    if(vg_img == VG_INVALID_HANDLE)
+	return NULL;
+    ge_img = O_ALLOC(_ge_openvg_img_t);
+    if(ge_img == NULL) {
+	vgDestroyImage(vg_img);
+	return NULL;
+    }
+    ge_img->ref = 1;
+    ge_img->img = vg_img;
+    ge_img->activated_for = NULL;
+    ge_img->deactivate_func = NULL;
+
+    return ge_img;
+}
+
+/*! \brief Free image object for OpenVG */
+static void
+_free_vgimage(_ge_openvg_img_t *ge_img) {
+    if(--ge_img->ref > 0) {
+	if(ge_img->activated_for) {
+	    ge_img->deactivate_func(ge_img->activated_for);
+	    ge_img->activated_for = NULL;
+	}
+	return;
+    }
+    
+    vgDestroyImage(ge_img->img);
+    free(ge_img);
+}
+
+static void
+_ge_vg_img_deactivate_for_pattern(void *obj) {
+    mbe_pattern_t *ptn = (mbe_pattern_t *)obj;
+    VGPaint vg_paint;
+
+    vg_paint = ptn->paint;
+    vgPaintPattern(vg_paint, VG_INVALID_HANDLE);
+}
+
+/*! \brief Activate a VGImage for a pattern paint.
+ * 
+ * \sa _ge_openvg_img
+ */
+void
+_ge_vg_img_activate_for_pattern(mbe_pattern_t *ptn) {
+    _ge_openvg_img_t *ge_img;
+    VGPaint vg_paint;
+    VGImage vg_img;
+
+    ge_img = ptn->asso_img;
+    if(ge_img == NULL)
+	return;
+
+    if(ge_img->activated_for == (void *)ptn)
+	return;
+
+    if(ge_img->activated_for)
+	ge_img->deactivate_func(ge_img->activated_for);
+
+    ge_img->activated_for = ptn;
+    ge_img->deactivate_func = _ge_vg_img_deactivate_for_pattern;
+    
+    vg_img = ge_img->img;
+    vg_paint = ptn->paint;
+
+    vgPaintPattern(vg_paint, vg_img);
+}
+
+/*! \brief Deactivate a VGImage for a VGSurface.
+ *
+ * A VGImage can not deatached from VGSurface.  But, it is not clear
+ * in the document of EGL.  We assume that a VGImage can be used as
+ * pattern of a paint, once associated surface is not current
+ * rendering context.
+ */
+static void
+_ge_vg_img_deactivate_for_surface(void *obj) {
+}
+
+/*! \brief Activate a VGImage for a surface
+ * 
+ * \sa _ge_openvg_img
+ */
+void
+_ge_vg_img_activate_for_surface(mbe_surface_t *surf) {
+    _ge_openvg_img_t *ge_img;
+    
+    ge_img = surf->asso_img;
+    if(ge_img == NULL)
+	return;
+    
+    if(ge_img->activated_for == (void *)surf)
+	return;
+
+    if(ge_img->activated_for)
+	ge_img->deactivate_func(ge_img->activated_for);
+    
+    ge_img->activated_for = surf;
+    ge_img->deactivate_func = _ge_vg_img_deactivate_for_surface;
+}
+
+/*
+ * This implementation supports only from image surface.
+ */
+mbe_pattern_t *
+mbe_pattern_create_for_surface(mbe_surface_t *surface) {
+    mbe_pattern_t *pattern;
+    _ge_openvg_img_t *ge_img;
+    VGfloat *mtx;
+    VGPaint paint;
+
+    /* Support only from image surface */
+    if(surface->asso_img == NULL)
+	return NULL;
+
+    paint = vgCreatePaint();
+    if(paint == VG_INVALID_HANDLE)
+	return NULL;
+
+    ge_img = surface->asso_img;
+    pattern = O_ALLOC(mbe_pattern_t);
+    pattern->asso_img = ge_img;
+    ge_img->ref++;		/* increase reference count */
+    pattern->paint = paint;
+
+    mtx = pattern->mtx;
+    MK_ID(mtx);
+
+    return pattern;
+}
+
+void
+_mbe_load_pattern_mtx(VGfloat *mtx1, VGfloat *mtx2, int mode) {
+    VGfloat affine;
+
+    vgSeti(VG_MATRIX_MODE, mode);
+    vgLoadMatrix(mtx1);
+    if(mtx2)
+	vgMultMatrix(mtx2);
+}
+
+static mbe_pattern_t *
+_mbe_pattern_create_gradient(VGfloat *gradient, int grad_len,
+			     int grad_type,
+			     grad_stop_t *stops, int stop_cnt) {
+    VGPaint paint;
+    mbe_pattern_t *pattern;
+    static VGfloat *ov_stops = 0;
+    static int max_stop_cnt = 0;
+    VGfloat *cur_ov_stop;
+    grad_stop_t *cur_stop;
+    int i;
+
+    /* Make sure there is enough space */
+    if(max_stop_cnt < stop_cnt) {
+	max_stop_cnt = (stop_cnt + 0xf) & ~0xf;
+	cur_ov_stop = (VGfloat *)realloc(stops,
+					 max_stop_cnt * sizeof(VGfloat) * 5);
+	if(cur_ov_stop == NULL) {
+	    max_stop_cnt = 0;
+	    return NULL;
+	}
+	ov_stops = cur_ov_stop;
+    }
+    cur_ov_stop = ov_stops;
+
+    cur_stop = stops;
+    for(i = 0; i < stop_cnt; i++) {
+	*cur_ov_stop++ = cur_stop->offset;
+	*cur_ov_stop++ = cur_stop->r;
+	*cur_ov_stop++ = cur_stop->g;
+	*cur_ov_stop++ = cur_stop->b;
+	*cur_ov_stop++ = cur_stop->a;
+    }
+    
+    paint = vgCreatePaint();
+    if(paint == VG_INVALID_HANDLE)
+	return NULL;
+    vgSetParameteri(paint, VG_PAINT_TYPE, grad_type);
+    vgSetParameterfv(paint, VG_PAINT_RADIAL_GRADIENT, grad_len, gradient);
+    vgSetParameterfv(paint, VG_PAINT_COLOR_RAMP_STOPS, 5 * stop_cnt, ov_stops);
+
+    pattern = O_ALLOC(mbe_pattern_t);
+    if(pattern == NULL) {
+	vgDestroyPaint(paint);
+	return NULL;
+    }
+
+    pattern->paint = paint;
+    pattern->asso_img = NULL;
+
+    MK_ID(pattern->mtx);
+    
+    return pattern;
+}
+
+/*
+ * \note OpenVG does not support start circle, it supports only focal
+ * point.  It means radius0 is not working.
+ */
+mbe_pattern_t *
+mbe_pattern_create_radial(co_aix cx0, co_aix cy0,
+			  co_aix radius0,	
+			  co_aix cx1, co_aix cy1,
+			  co_aix radius1, grad_stop_t *stops,
+			  int stop_cnt) {
+    mbe_pattern_t *pattern;
+    VGfloat gradient[] = {cx0, cy0, cx1, cy1, radius1};
+
+    pattern = _mbe_pattern_create_gradient(gradient, 5,
+					   VG_PAINT_TYPE_RADIAL_GRADIENT,
+					   stops, stop_cnt);
+    return pattern;
+}
+
+mbe_pattern_t *
+mbe_pattern_create_linear(co_aix x0, co_aix y0,
+			  co_aix x1, co_aix y1,
+			  grad_stop_t *stops, int stop_cnt) {
+    mbe_pattern_t *pattern;
+    VGfloat gradient[] = {x0, y0, x1, y1};
+
+    pattern = _mbe_pattern_create_gradient(gradient, 4,
+					   VG_PAINT_TYPE_LINEAR_GRADIENT,
+					   stops, stop_cnt);
+    return pattern;
+}
+
+mbe_pattern_t *
+mbe_pattern_create_image(mb_img_data_t *img) {
+    VGPaint paint;
+    mbe_pattern_t *pattern;
+    _ge_openvg_img_t *ge_img;
+    VGImage vg_img;
+    VGImageFormat fmt = VG_sARGB_8888;
+    
+    /* \note OpenVG implementation supports one \ref MB_IFMT_ARGB32
+     * image.
+     */
+    if(img->fmt != MB_IFMT_ARGB32)
+	return NULL;
+    
+    /* Allocate objects */
+    ge_img = _alloc_vgimage(MB_IFMT_ARGB32, img->w, img->h);
+    pattern = O_ALLOC(mbe_pattern_t);
+    paint = vgCreatePaint();
+    if(ge_img == NULL || pattern == NULL || paint == VG_INVALID_HANDLE)
+	goto err;
+    
+    /* Create and copy pixels into VGImage */
+    vg_img = ge_img->img;
+    vgImageSubData(vg_img, img->content, img->stride, fmt,
+		   0, 0, img->w, img->h);
+    
+    pattern->paint = paint;
+    pattern->asso_img = ge_img;
+
+    return pattern;
+
+ err:
+    if(ge_img) _free_vgimage(ge_img);
+    if(pattern) free(pattern);
+    if(paint != VG_INVALID_HANDLE) vgDestroyPaint(paint);
+    vgDestroyImage(vg_img);
+    return NULL;
+}
+
+void
+mbe_pattern_destroy(mbe_pattern_t *ptn) {
+    if(ptn->asso_img)
+	_free_vgimage(ptn->asso_img);
+    vgDestroyPaint(ptn->paint);
+    free(ptn);
+}
+
+void
+mbe_pattern_set_matrix(mbe_pattern_t *ptn, co_aix *mtx) {
+    co_aix rev[6];
+
+    compute_reverse(mtx, rev);
+    ptn->mtx[0] = rev[0];
+    ptn->mtx[1] = rev[3];
+    ptn->mtx[2] = 0;
+    ptn->mtx[3] = rev[1];
+    ptn->mtx[4] = rev[4];
+    ptn->mtx[5] = 0;
+    ptn->mtx[6] = rev[2];
+    ptn->mtx[7] = rev[5];
+    ptn->mtx[8] = 1;
+}
+
+void
+mbe_set_source_rgba(mbe_t *canvas, co_comp_t r, co_comp_t g,
+		    co_comp_t b, co_comp_t a) {
+    VGPaint paint;
+    VGuint color;
+
+    if(paint != VG_INVALID_HANDLE && canvas->src == NULL)
+	paint = canvas->paint;	/* previous one is also a color paint */
+    else {
+	paint = vgCreatePaint();
+	ASSERT(paint != VG_INVALID_HANDLE);
+	canvas->paint = paint;
+	canvas->src = NULL;
+    }
+    
+    color = MB_2_VG_COLOR(r, g, b, a);
+    vgSetColor(paint, color);
+    canvas->paint_installed = 0;
+}
+
+void
+mbe_scissoring(mbe_t *canvas, int n_areas, area_t **areas) {
+    static VGint *scissors = NULL;
+    static int n_scissors = 0;
+    VGint *coord;
+    area_t *area;
+    int i;
+
+    _MK_CURRENT_CTX(canvas);
+
+    if(n_areas > n_scissors) {
+	if(scissors) free(scissors);
+	n_scissors = (n_areas + 0xf) & ~0xf;
+	scissors = (VGint *)malloc(sizeof(VGint) * n_scissors * 4);
+	ASSERT(scissors != NULL);
+    }
+    
+    coord = scissors;
+    for(i = 0; i < n_areas; i++) {
+	area = areas[i];
+	*coord++ = area->x;
+	*coord++ = area->y;
+	*coord++ = area->w;
+	*coord++ = area->h;
+    }
+
+    vgSeti(VG_SCISSORING, VG_TRUE);
+    vgSetiv(VG_SCISSOR_RECTS, n_areas * 4, scissors);
+}
+
+static int
+_openvg_find_config(mb_img_fmt_t fmt, int w, int h,
+		   EGLConfig *config) {
+    EGLDisplay display;
+    EGLint attrib_list[32];
+    EGLConfig configs[1];
+    EGLint nconfigs;
+    int i = 0;
+    EGLBoolean r;
+    
+    switch(fmt) {
+    case MB_IFMT_ARGB32:
+	attrib_list[i++] = EGL_RED_SIZE;
+	attrib_list[i++] = 8;
+	attrib_list[i++] = EGL_GREEN_SIZE;
+	attrib_list[i++] = 8;
+	attrib_list[i++] = EGL_BLUE_SIZE;
+	attrib_list[i++] = 8;
+	attrib_list[i++] = EGL_ALPHA_SIZE;
+	attrib_list[i++] = 8;
+	break;
+	
+    case MB_IFMT_RGB24:
+	attrib_list[i++] = EGL_RED_SIZE;
+	attrib_list[i++] = 8;
+	attrib_list[i++] = EGL_GREEN_SIZE;
+	attrib_list[i++] = 8;
+	attrib_list[i++] = EGL_BLUE_SIZE;
+	attrib_list[i++] = 8;
+	break;
+	
+    case MB_IFMT_A8:
+	attrib_list[i++] = EGL_ALPHA_SIZE;
+	attrib_list[i++] = 8;
+	break;
+	
+    case MB_IFMT_A1:
+	attrib_list[i++] = EGL_ALPHA_SIZE;
+	attrib_list[i++] = 1;
+	break;
+	
+    case MB_IFMT_RGB16_565:
+	attrib_list[i++] = EGL_RED_SIZE;
+	attrib_list[i++] = 5;
+	attrib_list[i++] = EGL_GREEN_SIZE;
+	attrib_list[i++] = 6;
+	attrib_list[i++] = EGL_BLUE_SIZE;
+	attrib_list[i++] = 5;
+	break;
+	
+    default:
+	return -1;
+    }
+
+    attrib_list[i++] = EGL_SURFACE_TYPE;
+    attrib_list[i++] = EGL_PBUFFER_BIT;
+#if 0
+    attrib_list[i++] = EGL_MAX_PBUFFER_WIDTH;
+    attrib_list[i++] = w;
+    attrib_list[i++] = EGL_MAX_PBUFFER_HEIGHT;
+    attrib_list[i++] = h;
+#endif
+
+    attrib_list[i++] = EGL_RENDERABLE_TYPE;
+    attrib_list[i++] = EGL_OPENVG_BIT;
+    
+    attrib_list[i++] = EGL_NONE;
+    
+    display = _VG_DISPLAY();
+    r = eglChooseConfig(display, attrib_list, configs, 1, &nconfigs);
+    if(!r)
+	return -1;
+
+    *config = configs[0];
+    
+    return 0;
+}
+
+#ifdef EGL_GLX
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+static int
+_get_img_fmt_from_xvisual(Display *display, Visual *visual) {
+    VisualID visual_id;
+    XVisualInfo temp;
+    XVisualInfo *infos;
+    int n;
+    int fmt = -1;
+    
+    visual_id = XVisualIDFromVisual(visual);
+    temp.visualid = visual_id;
+    infos = XGetVisualInfo(display, VisualIDMask, &temp, &n);
+    if(n != 1)
+	return -1;
+
+    switch(infos->depth) {
+    case 32:
+	fmt = MB_IFMT_ARGB32;
+	break;
+	
+    case 24:
+	fmt = MB_IFMT_RGB24;
+	break;
+	
+    case 16:
+	fmt = MB_IFMT_RGB16_565;
+	break;
+	
+    case 8:
+	fmt = MB_IFMT_A8;
+	break;
+	
+    case 1:
+	fmt = MB_IFMT_A1;
+	break;
+    }
+
+    return fmt;
+}
+
+/*! \brief Create an EGL window surface for X11.
+ *
+ * This function is compiled only for GLX enabled.
+ */
+mbe_surface_t *
+mbe_vg_win_surface_create(Display *display, Drawable drawable,
+			  Visual *visual, int width, int height) {
+    EGLDisplay egl_disp;
+    EGLSurface egl_surface;
+    mbe_surface_t *surface;
+    EGLConfig config;
+    EGLint attrib_list[2] = {EGL_NONE};
+    int fmt;
+    int r;
+
+    fmt = _get_img_fmt_from_xvisual(display, visual);
+    if(fmt == -1)
+	return NULL;
+    
+    r = _openvg_find_config(fmt, width, height, &config);
+    if(r != 0)
+	return NULL;
+
+    egl_disp = eglGetDisplay(display);
+    if(egl_disp == EGL_NO_DISPLAY || egl_disp != _VG_DISPLAY())
+	return NULL;
+
+    egl_surface = eglCreateWindowSurface(egl_disp, config, drawable,
+					 attrib_list);
+
+    surface = O_ALLOC(mbe_surface_t);
+    if(surface == NULL) {
+	eglDestroySurface(egl_disp, egl_surface);
+	return NULL;
+    }
+
+    surface->surface = egl_surface;
+    surface->asso_img = NULL;
+
+    return surface;
+}
+
+#endif
+
+mbe_surface_t *
+mbe_image_surface_create(mb_img_fmt_t fmt, int w, int h) {
+    EGLSurface surface;
+    EGLDisplay display;
+    EGLConfig config;
+    EGLint attrib_list[5];
+    _ge_openvg_img_t *ge_img;
+    mbe_surface_t *mbe_surface;
+    int r;
+
+
+    r = _openvg_find_config(fmt, w, h, &config);
+    if(r != 0)
+	return NULL;
+
+    ge_img = _alloc_vgimage(fmt, w, h);
+    if(ge_img == NULL)
+	return NULL;
+
+    display = _VG_DISPLAY();
+    attrib_list[0] = EGL_WIDTH;
+    attrib_list[1] = w;
+    attrib_list[2] = EGL_HEIGHT;
+    attrib_list[3] = h;
+    attrib_list[4] = EGL_NONE;
+    /* Some implementation does not support pbuffer.
+     * We need use some other surface to replace this one.
+     */
+    surface = eglCreatePbufferFromClientBuffer(display, EGL_OPENVG_IMAGE,
+					       (EGLClientBuffer)ge_img->img,
+					       config, attrib_list);
+    if(surface == EGL_NO_SURFACE) {
+	_free_vgimage(ge_img);
+	return NULL;
+    }
+    
+    mbe_surface = O_ALLOC(mbe_surface_t);
+    if(mbe_surface == NULL) {
+	_free_vgimage(ge_img);
+	eglDestroySurface(display, surface);
+	return NULL;
+    }
+    mbe_surface->surface = surface;
+    mbe_surface->asso_mbe = NULL;
+    mbe_surface->asso_img = ge_img;
+    mbe_surface->w = w;
+    mbe_surface->h = h;
+
+    return mbe_surface;
+}
+
+void
+mbe_surface_destroy(mbe_surface_t *surface) {
+    EGLDisplay display;
+
+    display = _VG_DISPLAY();
+    eglDestroySurface(display, surface->surface);
+    
+    if(surface->asso_mbe)
+	surface->asso_mbe->tgt = NULL;
+
+    if(surface->asso_img)
+	_free_vgimage(surface->asso_img);
+    
+    free(surface);
+}
+
+void
+mbe_copy_source(mbe_t *src_canvas, mbe_t *dst_canvas) {
+    VGImage vg_img;
+    
+    ASSERT(src_canvas->tgt->asso_img != NULL);
+    
+    _MK_CURRENT_CTX(dst_canvas);
+    
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    vgLoadIdentity();
+    
+    vg_img = src_canvas->tgt->asso_img;
+    vgDrawImage(vg_img);
+}
+
+mbe_t *
+mbe_create(mbe_surface_t *surface) {
+    EGLDisplay display;
+    EGLConfig config;
+    EGLContext ctx, shared;
+    VGPath path;
+    EGLint attrib_list[2] = {EGL_NONE};
+    static VGfloat clear_color[4] = {0, 0, 0, 1};
+    mbe_t *canvas;
+
+    display = _VG_DISPLAY();
+    ctx = eglCreateContext(display, config, shared, attrib_list);
+    if(ctx == EGL_NO_CONTEXT)
+	return NULL;
+
+    path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
+			1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+    if(path == VG_INVALID_HANDLE) {
+	eglDestroyContext(display, ctx);
+	return NULL;
+    }
+    
+    canvas = O_ALLOC(mbe_t);
+    if(canvas == NULL) {
+	eglDestroyContext(display, ctx);
+	vgDestroyPath(path);
+	return NULL;
+    }
+    
+    canvas->src = NULL;
+    canvas->paint = VG_INVALID_HANDLE;
+    canvas->paint_installed = 0;
+    canvas->tgt = surface;
+    canvas->ctx = ctx;
+    canvas->path = path;
+    
+    /* Set clear color for the context */
+    _MK_CURRENT_CTX(canvas);
+    vgSetfv(VG_CLEAR_COLOR, 4, clear_color);
+
+    return canvas;
+}
+
+void
+mbe_destroy(mbe_t *canvas) {
+    EGLDisplay display;
+
+    display = _VG_DISPLAY();
+    
+    vgDestroyPath(canvas->path);
+    eglDestroyContext(display, canvas->ctx);
+    canvas->tgt->asso_mbe = NULL; /* remove association */
+    free(canvas);
+}
+
+void
+mbe_paint_with_alpha(mbe_t *canvas, co_comp_t alpha) {
+    VGfloat color_trans[8] = {1, 1, 1, alpha, 0, 0, 0, 0};
+    EGLDisplay display;
+    EGLint w, h;
+    EGLBoolean r;
+    
+    _MK_CURRENT_CTX(canvas);
+
+    display = _VG_DISPLAY();
+    
+    r = eglQuerySurface(display, canvas->tgt, EGL_WIDTH, &w);
+    ASSERT(r == EGL_TRUE);
+    r = eglQuerySurface(display, canvas->tgt, EGL_HEIGHT, &h);
+    ASSERT(r == EGL_TRUE);
+
+    /* Setup color transform for alpha */
+#ifdef OPENVG_1_1
+    vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, color_trans);
+    vgSeti(VG_COLOR_TRANSFORM, VG_TRUE);
+#endif
+        
+    mbe_paint(canvas);
+
+#ifdef OPENVG_1_1
+    vgSeti(VG_COLOR_TRANSFORM, VG_FALSE);
+#endif
+}
+
+void
+mbe_paint(mbe_t *canvas) {
+    EGLDisplay display;
+    EGLint w, h;
+    EGLBoolean r;
+    VGPath path;
+    
+    _MK_CURRENT_CTX(canvas);
+    _MK_CURRENT_PAINT(canvas);
+    if(canvas->src)
+	_mbe_load_pattern_mtx(canvas->src->mtx, NULL,
+			      VG_MATRIX_FILL_PAINT_TO_USER);
+    
+    display = _VG_DISPLAY();
+    
+    r = eglQuerySurface(display, canvas->tgt, EGL_WIDTH, &w);
+    ASSERT(r == EGL_TRUE);
+    r = eglQuerySurface(display, canvas->tgt, EGL_HEIGHT, &h);
+    ASSERT(r == EGL_TRUE);
+
+    /*
+     * Disable scissoring and identity transform matrix.
+     *
+     * Transform matrix from path to surface is assigned by
+     * mbe_transform().  Here, we temporary set it to identity, and
+     * restore it after paint.
+     */
+    vgSeti(VG_SCISSORING, VG_FALSE);
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+    vgLoadIdentity();
+    
+    path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
+			1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+    vguRect(path, 0, 0, w, h);
+    vgDrawPath(path, VG_FILL_PATH);
+    vgDestroyPath(path);
+    
+    /* re-enable scissoring and restore transform matrix */
+    vgLoadMatrix(canvas->mtx);
+    vgSeti(VG_SCISSORING, VG_TRUE);
+}
+
+void
+mbe_clear(mbe_t *canvas) {
+    EGLDisplay display;
+    EGLint w, h;
+    EGLBoolean r;
+
+    _MK_CURRENT_CTX(canvas);
+
+    display = _VG_DISPLAY();
+    
+    r = eglQuerySurface(display, canvas->tgt, EGL_WIDTH, &w);
+    ASSERT(r == EGL_TRUE);
+    r = eglQuerySurface(display, canvas->tgt, EGL_HEIGHT, &h);
+    ASSERT(r == EGL_TRUE);
+    
+    /* Clear regions to the color specified by mbe_create() */
+    vgClear(0, 0, w, h);
+}
+
+void mbe_init() {
+    static EGLContext init_ctx;
+    static EGLSurface init_surf;
+    EGLDisplay display;
+    EGLConfig config;
+    EGLint nconfigs;
+    EGLint attrib_list[] = {
+	EGL_RED_SIZE, 1,
+	EGL_GREEN_SIZE, 1,
+	EGL_BLUE_SIZE, 1,
+	EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+	EGL_NONE};
+    EGLint surf_attribs[] = {
+	EGL_WIDTH, 1,
+	EGL_HEIGHT, 1,
+	EGL_NONE};
+    EGLBoolean r;
+
+    display = _VG_DISPLAY();
+    eglInitialize(display, NULL, NULL);
+
+    r = eglChooseConfig(display, attrib_list, &config, 1, &nconfigs);
+    ASSERT(r);
+    
+    eglBindAPI(EGL_OPENVG_API);
+
+    init_ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
+    ASSERT(init_ctx != EGL_NO_CONTEXT);
+
+    init_surf = eglCreatePbufferSurface(display, config, surf_attribs);
+    ASSERT(init_surf != EGL_NO_SURFACE);
+    
+    eglMakeCurrent(display, init_surf, init_surf, init_ctx);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/img_ldr_imlib2.c	Wed Dec 01 12:25:56 2010 +0800
@@ -0,0 +1,117 @@
+// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
+// vim: sw=4:ts=8:sts=4
+#include <stdio.h>
+#include <string.h>
+#include <Imlib2.h>
+#include "mb_graph_engine.h"
+#include "mb_tools.h"
+#include "mb_paint.h"
+#include "mb_img_ldr.h"
+
+/*! \brief Simple image loader.
+ *
+ */
+struct _simple_mb_img_ldr {
+    mb_img_ldr_t ldr;
+    const char *repo;		/*!< \brief The directory of repository. */
+};
+typedef struct _simple_mb_img_ldr simple_mb_img_ldr_t;
+
+struct _simple_mb_img_data {
+    mb_img_data_t img;
+    Imlib_Image img_hdl;
+};
+typedef struct _simple_mb_img_data simple_mb_img_data_t;
+
+static void simple_mb_img_ldr_img_free(mb_img_data_t *img);
+
+static
+mb_img_data_t *simple_mb_img_ldr_load(mb_img_ldr_t *ldr, const char *img_id) {
+    simple_mb_img_ldr_t *sldr = (simple_mb_img_ldr_t *)ldr;
+    simple_mb_img_data_t *img;
+    Imlib_Image img_hdl;
+    int w, h;
+    void *data;
+    char *fname;
+    int sz;
+
+    sz = strlen(sldr->repo);
+    sz += strlen(img_id);
+    fname = (char *)malloc(sz + 2);
+	if (img_id[0] != '/')
+        strcpy(fname, sldr->repo);
+	else
+		fname[0] = 0;
+    strcat(fname, img_id);
+    
+    img_hdl = imlib_load_image(fname);
+    if(!img_hdl)
+	return NULL;
+    imlib_context_set_image(img_hdl);
+    w = imlib_image_get_width();
+    h = imlib_image_get_height();
+    data = imlib_image_get_data_for_reading_only();
+
+    img = O_ALLOC(simple_mb_img_data_t);
+    if(img == NULL) {
+	imlib_free_image();
+	return NULL;
+    }
+    img->img.content = data;
+    img->img.w = w;
+    img->img.h = h;
+    img->img.stride = w * 4;
+    img->img.fmt = MB_IFMT_ARGB32;
+    img->img.free = simple_mb_img_ldr_img_free;
+    img->img_hdl = img_hdl;
+
+    return (mb_img_data_t *)img;
+}
+
+static
+void simple_mb_img_ldr_img_free(mb_img_data_t *img) {
+    simple_mb_img_data_t *simg = (simple_mb_img_data_t *)img;
+
+    imlib_context_set_image(simg->img_hdl);
+    imlib_free_image();
+    free(img);
+}
+
+static
+void simple_mb_img_ldr_free(mb_img_ldr_t *ldr) {
+    simple_mb_img_ldr_t *defldr = (simple_mb_img_ldr_t *)ldr;
+
+    free((void *)defldr->repo);
+}
+
+mb_img_ldr_t *simple_mb_img_ldr_new(const char *img_repository) {
+    simple_mb_img_ldr_t *ldr;
+    int sz;
+
+    if(img_repository == NULL)
+	return NULL;
+
+    ldr = O_ALLOC(simple_mb_img_ldr_t);
+    if(ldr == NULL)
+	return NULL;
+
+    /*
+     * Copy and formalize path of image repository.
+     */
+    sz = strlen(img_repository);
+    ldr->repo = (const char *)malloc(sz + 2);
+    if(ldr->repo == NULL) {
+	free(ldr);
+	return NULL;
+    }
+    strcpy((char *)ldr->repo, img_repository);
+    if(img_repository[sz - 1] != '/' && strlen(img_repository) != 0) {
+	((char *)ldr->repo)[sz] = '/';
+	((char *)ldr->repo)[sz + 1] = 0;
+    }
+
+    ldr->ldr.load = simple_mb_img_ldr_load;
+    ldr->ldr.free = simple_mb_img_ldr_free;
+
+    return (mb_img_ldr_t *)ldr;
+}