changeset 1098:cb4a2ffdf9e8

Merge HEAD
author wycc
date Sat, 04 Dec 2010 16:58:25 +0800
parents 52d8bf5d12b4 (current diff) c18ad321844d (diff)
children 5ba2cab1d505
files
diffstat 22 files changed, 1702 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Sat Dec 04 07:43:51 2010 +0800
+++ b/configure.ac	Sat Dec 04 16:58:25 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,32 @@
 	    (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 ]
+# Validate options
+[case "${backend}-${graphic_engine}-${image_loader}" in
+    X-cairo-*|X-openvg-imlib2) ;;
+    dfb-cairo-*) ;;
+    none-*-*) ;;
+    *)] AC_MSG_ERROR([The combination of --with-backend=${backend}, --with-graphic-engine=${graphic_engine} and --with-image-loader=${image_loader} is invalid]) [;;
+esac]
+
+[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 +162,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'])
 
-[if [ x"${backend}" = x'X' -a x"${cairo}" = xtrue ]; then]
+[if [ x"${backend}" = x'X' ]; 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([EGL/egl.h],, [AC_MSG_ERROR([can not find EGL/egl.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 +247,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	Sat Dec 04 07:43:51 2010 +0800
+++ b/examples/menu/filebrowser.c	Sat Dec 04 16:58:25 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_basic_types.h	Sat Dec 04 07:43:51 2010 +0800
+++ b/include/mb_basic_types.h	Sat Dec 04 16:58:25 2010 +0800
@@ -10,4 +10,15 @@
     co_comp_t r, g, b, a;
 } grad_stop_t;
 
+/*! \brief An rectangle area.
+ *
+ * This type is used to describe an rectangle area in an image or on a
+ * screen.
+ */
+struct _area {
+    co_aix x, y;
+    co_aix w, h;
+};
+typedef struct _area area_t;
+
 #endif /* __MB_BASIC_TYPES_H_ */
--- a/include/mb_config.h.in	Sat Dec 04 07:43:51 2010 +0800
+++ b/include/mb_config.h.in	Sat Dec 04 16:58:25 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	Sat Dec 04 07:43:51 2010 +0800
+++ b/include/mb_graph_engine.h	Sat Dec 04 16:58:25 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_ */
--- a/include/mb_graph_engine_cairo.h	Sat Dec 04 07:43:51 2010 +0800
+++ b/include/mb_graph_engine_cairo.h	Sat Dec 04 16:58:25 2010 +0800
@@ -15,7 +15,9 @@
 #define MBE_OPERATOR_SOURCE CAIRO_OPERATOR_SOURCE
 #define MBE_STATUS_SUCCESS CAIRO_STATUS_SUCCESS
 
+/* This function is only used by img_ldr.c */
 #define mbe_image_surface_create_from_png cairo_image_surface_create_from_png
+
 #define mbe_pattern_create_for_surface cairo_pattern_create_for_surface
 #define mbe_scaled_font_text_extents cairo_scaled_font_text_extents
 #define mbe_image_surface_get_stride cairo_image_surface_get_stride
@@ -24,7 +26,7 @@
 #define mbe_image_surface_get_width cairo_image_surface_get_width
 #define mbe_image_surface_get_data cairo_image_surface_get_data
 #define mbe_scaled_font_reference cairo_scaled_font_reference
-#define mbe_xlib_surface_create cairo_xlib_surface_create
+#define mbe_win_surface_create cairo_xlib_surface_create
 #define mbe_scaled_font_destroy cairo_scaled_font_destroy
 #define mbe_font_face_reference cairo_font_face_reference
 #define mbe_font_face_destroy cairo_font_face_destroy
@@ -39,7 +41,7 @@
 #define mbe_get_font_face cairo_get_font_face
 #define mbe_fill_preserve cairo_fill_preserve
 #define mbe_set_source cairo_set_source
-#define mbe_reset_clip cairo_reset_clip
+#define mbe_reset_scissoring cairo_reset_clip
 #define mbe_get_target cairo_get_target
 #define mbe_close_path cairo_close_path
 #define mbe_text_path cairo_text_path
@@ -57,7 +59,7 @@
 #define mbe_paint cairo_paint
 #define mbe_save cairo_save
 #define mbe_fill cairo_fill
-#define mbe_clip cairo_clip
+#define mbe_init()
 
 typedef cairo_text_extents_t mbe_text_extents_t;
 typedef cairo_scaled_font_t mbe_scaled_font_t;
@@ -89,6 +91,8 @@
 						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_scissoring(mbe_t *canvas, int n_areas, area_t **areas);
 
 
 static void mbe_pattern_set_matrix(mbe_pattern_t *ptn,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/mb_graph_engine_dummy.h	Sat Dec 04 16:58:25 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	Sat Dec 04 16:58:25 2010 +0800
@@ -0,0 +1,263 @@
+#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)			\
+    do {								\
+	VGfloat _vg_data[6] = {x1, y1, x2, y2, x3, y3};			\
+	char _vg_cmd = VG_CUBIC_TO_ABS;					\
+	vgAppendPathData((canvas)->path, 1, &_vg_cmd, _vg_data);	\
+    } while(0)
+#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) (1)
+/* 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;
+    mb_img_fmt_t fmt;
+};
+
+struct _ge_openvg_pattern {
+    _ge_openvg_img_t *asso_img;
+    VGfloat mtx[9];
+    VGPaint paint;
+};
+
+#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_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 mbe_surface_t *
+mbe_image_surface_create_for_data(unsigned char *data,
+				  mb_img_fmt_t fmt,
+				  int width, int height,
+				  int stride);
+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/include/mb_types.h	Sat Dec 04 07:43:51 2010 +0800
+++ b/include/mb_types.h	Sat Dec 04 16:58:25 2010 +0800
@@ -10,7 +10,6 @@
 
 typedef struct _shape shape_t;
 typedef struct _geo geo_t;
-typedef struct _area area_t;
 typedef struct _shnode shnode_t;
 typedef struct _paint paint_t;
 typedef struct _mb_obj mb_obj_t;
@@ -103,11 +102,6 @@
     shnode_t *next;
 };
 
-struct _area {
-    co_aix x, y;
-    co_aix w, h;
-};
-
 /*! \brief Geometry data of a shape or a group of shape.
  */
 struct _geo {
--- a/nodejs/Makefile.am	Sat Dec 04 07:43:51 2010 +0800
+++ b/nodejs/Makefile.am	Sat Dec 04 16:58:25 2010 +0800
@@ -6,8 +6,14 @@
 mbfly_node_CFLAGS= -I$(abs_top_builddir)/include \
 	-I$(abs_top_srcdir)/include \
 	-I$(prefix)/include \
-	@pangocairo_CFLAGS@ $(CFLAGS)
-mbfly_node_LDFLAGS = -L$(abs_top_builddir)/src/.libs @pangocairo_LIBS@
+	@imlib2_CFLAGS@ \
+	@pangocairo_CFLAGS@ $(CFLAGS) $(CPPFLAGS)
+mbfly_node_LDFLAGS = -L$(abs_top_builddir)/src/.libs @pangocairo_LIBS@ \
+	@imlib2_LIBS@ $(LDFLAGS)
+
+if OPENVG_GRAPH_ENGINE
+mbfly_node_LDFLAGS += -lOpenVG
+endif
 
 if XSHM
 mbfly_node_LDFLAGS += -lXext
--- a/nodejs/run.sh	Sat Dec 04 07:43:51 2010 +0800
+++ b/nodejs/run.sh	Sat Dec 04 16:58:25 2010 +0800
@@ -1,11 +1,25 @@
 #!/bin/sh
 
 ABS=`realpath $0`
-BASE=`dirname $ABS`
-NODE_PATH=$BASE:$BASE/objs/default:$NODE_PATH
+if [ -z "$SRCDIR" ]; then
+    SRCDIR=`dirname $ABS`/..
+fi
+if [ -z "$BUILDDIR" ]; then
+    BUILDDIR=`dirname $ABS`/..
+fi
+
+NODE_PATH=${BUILDDIR}/nodejs/objs/default:${SRCDIR}/nodejs:$NODE_PATH
 export NODE_PATH
 
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${BUILDDIR}/src/.libs/
+export LD_LIBRARY_PATH
+
 DIR=`dirname $1`
 FNAME=`basename $1`
 
-cd $DIR; node $FNAME
+if [ -z "$DEBUG" ]; then
+    cd $DIR; node $FNAME
+else
+    # DEBUG
+    cd $DIR; gdb -args node $FNAME
+fi
--- a/nodejs/wscript	Sat Dec 04 07:43:51 2010 +0800
+++ b/nodejs/wscript	Sat Dec 04 16:58:25 2010 +0800
@@ -32,7 +32,7 @@
     obj.source = 'font.cc image_ldr.cc'
     obj.add_objects = 'njs_mb_supp.o observer.o coord.o mbfly_njs.o ' + \
         'shapes.o paints.o'
-    obj.staticlib = 'mbfly'
+    obj.lib = 'mbfly'
 
     for src in 'observer.cc coord.cc mbfly_njs.cc shapes.cc paints.cc'.split():
         obj = conf.new_task_gen('cxx', 'shlib', 'node_addon')
--- a/src/Makefile.am	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/Makefile.am	Sat Dec 04 16:58:25 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,10 @@
 	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 =
+libmbfly_la_LDFLAGS =
 
 if SH_TEXT
 libmbfly_la_SOURCES += shape_text.c
@@ -42,12 +45,21 @@
 libmbfly_la_SOURCES += dfb_supp.c
 endif
 
-libmbfly_la_LDFLAGS =
+if CAIRO_IMG_LOADER
+libmbfly_la_SOURCES += img_ldr.c
+endif
+
+if IMLIB2_IMG_LOADER
+libmbfly_la_SOURCES += img_ldr_imlib2.c
+
+libmbfly_la_CPPFLAGS += @imlib2_CFLAGS@
+libmbfly_la_LDFLAGS += @imlib2_LIBS@
+endif
 
 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 +71,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
+endif
+
 X_main_SOURCES = X_main.c
 X_main_LDADD = $(top_builddir)/src/libmbfly.la
 X_main_CPPFLAGS = @pangocairo_CFLAGS@ -I$(top_builddir)/include
--- a/src/X_main.c	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/X_main.c	Sat Dec 04 16:58:25 2010 +0800
@@ -467,9 +467,9 @@
 			CWOverrideRedirect, &wattr);
     r = XMapWindow(display, win);
 
-    surface = mbe_xlib_surface_create(display, win, visual, w, h);
+    surface = mbe_win_surface_create(display, win, visual, w, h);
     if(surface == NULL)
-	printf("mbe_xlib_surface_create\n");
+	printf("mbe_win_surface_create\n");
 
     drawing(surface, w, h);
 
--- a/src/X_supp.c	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/X_supp.c	Sat Dec 04 16:58:25 2010 +0800
@@ -5,7 +5,6 @@
 #include <string.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <cairo-xlib.h>
 #include "mb_graph_engine.h"
 #include "mb_redraw_man.h"
 #include "mb_timer.h"
@@ -49,7 +48,6 @@
     Window win;
     Visual *visual;
     mbe_surface_t *surface, *backend_surface;
-    mbe_pattern_t *surface_ptn;
     mbe_t *cr, *backend_cr;
     redraw_man_t *rdman;
     mb_img_ldr_t *img_ldr;
@@ -781,30 +779,29 @@
 #ifdef XSHM
     xshm_init(xmb_rt);
 #endif
-
+    
+    mbe_init();
+    
     xmb_rt->surface =
 	mbe_image_surface_create(MB_IFMT_ARGB32, w, h);
 
-    xmb_rt->surface_ptn =
-	mbe_pattern_create_for_surface(xmb_rt->surface);
-
     if(xmb_rt->backend_surface == NULL) /* xshm_init() may create one */
 	xmb_rt->backend_surface =
-	    mbe_xlib_surface_create(xmb_rt->display,
-				    xmb_rt->win,
-				    xmb_rt->visual,
-				    w, h);
+	    mbe_win_surface_create(xmb_rt->display,
+				   xmb_rt->win,
+				   xmb_rt->visual,
+				   w, h);
 
     xmb_rt->cr = mbe_create(xmb_rt->surface);
     xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface);
-
-    mbe_set_source(xmb_rt->backend_cr, xmb_rt->surface_ptn);
-
+    
     xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t));
     redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr);
-    // FIXME: This is a wired loopback reference. This is inly required when we need
-    //        to get the xmb_rt->tman for the animation. We should relocate the tman
-    //	      to the redraw_man_t instead.
+    /* FIXME: This is a wired loopback reference. This is inly
+     *        required when we need to get the xmb_rt->tman for the
+     *        animation. We should relocate the tman to the
+     *        redraw_man_t instead.
+     */
     xmb_rt->rdman->rt = xmb_rt;
 
     xmb_rt->io_man = mb_io_man_new(_io_factory);
@@ -905,8 +902,6 @@
 
     if(xmb_rt->surface)
 	mbe_surface_destroy(xmb_rt->surface);
-    if(xmb_rt->surface_ptn)
-	mbe_pattern_destroy(xmb_rt->surface_ptn);
     if(xmb_rt->backend_surface)
 	mbe_surface_destroy(xmb_rt->backend_surface);
 
--- a/src/event.c	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/event.c	Sat Dec 04 16:58:25 2010 +0800
@@ -697,6 +697,11 @@
 
 static
 void _draw_to_mask(shape_t *shape, mbe_t *cr) {
+    /* TODO: Find a new algorithm to check if a point is in the area
+     * covered by a shape.  This function is expected to work with
+     * _fill_and_check() to detect a collision.
+     */
+#if 0
     if(sh_get_flags(shape, GEF_OV_DRAW))
 	return;
 
@@ -704,10 +709,12 @@
     mbe_clip(cr);
 
     sh_set_flags(shape, GEF_OV_DRAW);
+#endif
 }
 
 static
 int _fill_and_check(shape_t *shape, mbe_t *cr) {
+#if 0
     int h, stride;
     mbe_surface_t *surface;
     unsigned char *data;
@@ -729,6 +736,9 @@
     }
 
     return FALSE;
+#else
+    return TRUE;
+#endif
 }
 
 /*! \brief Is a mb_obj_t overlaid with another mb_obj_t and
--- a/src/graph_engine_cairo.c	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/graph_engine_cairo.c	Sat Dec 04 16:58:25 2010 +0800
@@ -150,3 +150,57 @@
 
     return ptn;
 }
+
+mbe_pattern_t *
+mbe_pattern_create_image(mb_img_data_t *img) {
+    cairo_surface_t *surf;
+    cairo_pattern_t *ptn;
+    cairo_format_t fmt;
+
+    switch(img->fmt) {
+    case MB_IFMT_ARGB32:
+	fmt = CAIRO_FORMAT_ARGB32;
+	break;
+	
+    case MB_IFMT_RGB24:
+	fmt = CAIRO_FORMAT_RGB24;
+	break;
+	
+    case MB_IFMT_A8:
+	fmt = CAIRO_FORMAT_A8;
+	break;
+	
+    case MB_IFMT_A1:
+	fmt = CAIRO_FORMAT_A1;
+	break;
+	
+    case MB_IFMT_RGB16_565:
+	fmt = CAIRO_FORMAT_RGB16_565;
+	break;
+	
+    default:
+	return NULL;
+    }
+    
+    surf = cairo_image_surface_create_for_data(img->content, fmt,
+					       img->w, img->h, img->stride);
+    ptn = cairo_pattern_create_for_surface(surf);
+    cairo_surface_destroy(surf);
+    
+    return ptn;
+}
+
+void
+mbe_scissoring(mbe_t *canvas, int n_areas, area_t **areas) {
+    area_t *area;
+    int i;
+    
+    cairo_new_path(canvas);
+    
+    for(i = 0; i < n_areas; i++) {
+	area = areas[i];
+	cairo_rectangle(canvas, area->x, area->y, area->w, area->h);
+    }
+
+    cairo_clip(canvas);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/graph_engine_dfb.c	Sat Dec 04 16:58:25 2010 +0800
@@ -0,0 +1,1 @@
+/* Keep Me */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/graph_engine_openvg.c	Sat Dec 04 16:58:25 2010 +0800
@@ -0,0 +1,912 @@
+#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
+
+#ifndef ERR
+#include <stdio.h>
+#include <stdlib.h>
+#define ERR(msg) do { fprintf(stderr, __FILE__ ":%d: %s", __LINE__, msg); abort(); } while(0)
+#endif
+#ifndef NOT_IMPLEMENT
+#define NOT_IMPLEMENT(func)			\
+    ERR(func " is not impmemented\n")
+#endif
+
+#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)
+
+#define VG_MBE_SURFACE(mbe) ((mbe)->tgt->surface)
+
+/*! \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 SURFACE_VG_IMG(surface) ((surface)->tgt->asso_img->img)
+
+static EGLContext init_ctx;
+
+/*! \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) {
+    /* NOT_IMPLEMENT("_ge_vg_img_deactivate_for_surface"); */
+}
+
+/*! \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(ov_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;
+	cur_stop++;
+    }
+    
+    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;
+    VGfloat rgba[4];
+
+    paint = canvas->paint;
+    if(paint == VG_INVALID_HANDLE || canvas->src != NULL) {
+	/* previous one is not a color paint */
+	if(canvas->src) {
+	    mbe_pattern_destroy(canvas->src);
+	    canvas->src = NULL;
+	}
+	
+	paint = vgCreatePaint();
+	ASSERT(paint != VG_INVALID_HANDLE);
+	vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+	canvas->paint = paint;
+    }
+    
+    rgba[0] = r;
+    rgba[1] = g;
+    rgba[2] = b;
+    rgba[3] = a;
+    vgSetParameterfv(paint, VG_PAINT_COLOR, 4, rgba);
+    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_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_mbe = NULL;
+    surface->asso_img = NULL;
+    surface->fmt = fmt;
+
+    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[1] = {EGL_NONE};
+    _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();
+    /* Some implementation does not support pbuffer.
+     * We need use some other surface to replace this one.
+     *
+     * EGL does not support any attributes for pbuffer used by OpenVG.
+     */
+    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;
+    mbe_surface->fmt = fmt;
+
+    return mbe_surface;
+}
+
+mbe_surface_t *
+mbe_image_surface_create_for_data(unsigned char *data,
+				  mb_img_fmt_t fmt,
+				  int width, int height,
+				  int stride) {
+    NOT_IMPLEMENT("mbe_image_surface_create_for_data");
+    return NULL;
+}
+
+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;
+    EGLDisplay display;
+    
+    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 = SURFACE_VG_IMG(src_canvas);
+    vgDrawImage(vg_img);
+
+    display = _VG_DISPLAY();
+    eglSwapBuffers(display, VG_MBE_SURFACE(dst_canvas));
+}
+
+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;
+    int r;
+
+    display = _VG_DISPLAY();
+    
+    r = _openvg_find_config(surface->fmt, surface->w, surface->h, &config);
+    if(r != 0)
+	return NULL;
+    
+    /* shared = EGL_NO_CONTEXT; */
+    shared = init_ctx;
+    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;
+
+    surface->asso_mbe = canvas;
+    
+    /* 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 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	Sat Dec 04 16:58:25 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;
+}
--- a/src/paint.c	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/paint.c	Sat Dec 04 16:58:25 2010 +0800
@@ -182,6 +182,11 @@
 
 #define RDF_DIRTY 0x1
 
+#define pnt_radial_clear_flags(radial, _flags)	\
+    do {					\
+	(radial)->flags &= ~(_flags);		\
+    } while(0)
+
 int _paint_radial_size = sizeof(paint_radial_t);
 
 static void paint_radial_prepare(paint_t *paint, mbe_t *cr, shape_t *sh) {
@@ -202,8 +207,11 @@
 					radial->stops,
 					radial->n_stops);
 	ASSERT(ptn != NULL);
-	mbe_pattern_destroy(radial->ptn);
+	if(radial->ptn)
+	    mbe_pattern_destroy(radial->ptn);
 	radial->ptn = ptn;
+	
+	pnt_radial_clear_flags(radial, RDF_DIRTY);
     }
     mbe_set_source(cr, radial->ptn);
 }
@@ -266,7 +274,6 @@
 typedef struct _paint_image {
     paint_t paint;
     mb_img_data_t *img;
-    mbe_surface_t *surf;
     mbe_pattern_t *ptn;
 } paint_image_t;
 
@@ -286,7 +293,6 @@
     paint_image_t *paint_img = (paint_image_t *)paint;
     mb_img_data_t *img_data;
 
-    mbe_surface_destroy(paint_img->surf);
     img_data = paint_img->img;
     MB_IMG_DATA_FREE(img_data);
     paint_destroy(&paint_img->paint);
@@ -311,21 +317,9 @@
     paint_init(&paint->paint, MBP_IMAGE,
 	       paint_image_prepare, paint_image_free);
     paint->img = img;
-    paint->surf = mbe_image_surface_create_for_data(img->content,
-						      img->fmt,
-						      img->w,
-						      img->h,
-						      img->stride);
-    if(paint->surf == NULL) {
-	paint_destroy(&paint->paint);
-	elmpool_elm_free(rdman->paint_image_pool, paint);
-	return NULL;
-    }
-
-    paint->ptn = mbe_pattern_create_for_surface(paint->surf);
+    paint->ptn = mbe_pattern_create_image(img);
     if(paint->ptn == NULL) {
 	paint_destroy(&paint->paint);
-	mbe_surface_destroy(paint->surf);
 	elmpool_elm_free(rdman->paint_image_pool, paint);
 	return NULL;
     }
--- a/src/redraw_man.c	Sat Dec 04 07:43:51 2010 +0800
+++ b/src/redraw_man.c	Sat Dec 04 16:58:25 2010 +0800
@@ -2237,36 +2237,22 @@
     mbe_clear(canvas);
 }
 
-static void make_clip(mbe_t *cr, int n_dirty_areas,
-		      area_t **dirty_areas) {
-    int i;
-    area_t *area;
-
-    mbe_new_path(cr);
-    for(i = 0; i < n_dirty_areas; i++) {
-	area = dirty_areas[i];
-	if(area->w < 0.1 || area->h < 0.1)
-	    continue;
-	mbe_rectangle(cr, area->x, area->y, area->w, area->h);
-    }
-    mbe_clip(cr);
-}
+#define make_scissoring(canvas, n_dirty_areas, dirty_areas)	\
+    mbe_scissoring(canvas, n_dirty_areas, dirty_areas)
 
 static void reset_clip(canvas_t *cr) {
-    mbe_reset_clip(cr);
+    mbe_reset_scissoring(cr);
 }
 
 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas,
 			      area_t **dirty_areas) {
     if(n_dirty_areas)
-	make_clip(rdman->backend, n_dirty_areas, dirty_areas);
-
+	make_scissoring(rdman->backend, n_dirty_areas, dirty_areas);
+    
     mbe_copy_source(rdman->cr, rdman->backend);
 }
 #else /* UNITTEST */
-static void make_clip(mbe_t *cr, int n_dirty_areas,
-		      area_t **dirty_areas) {
-}
+#define make_scissoring(canvas, n_dirty_areas, dirty_areas)
 
 static void clear_canvas(canvas_t *canvas) {
 }
@@ -2401,7 +2387,7 @@
 	area->h = ceilf(area->h);
     }
 
-    make_clip(canvas, n_areas, areas);
+    make_scissoring(canvas, n_areas, areas);
     clear_canvas(canvas);
 
     r = draw_coord_shapes_in_dirty_areas(rdman, coord);