Mercurial > MadButterfly
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 (current diff) 292fbb86d8f3 (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 | 161 files changed, 15226 insertions(+), 2478 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYING.h Mon Jul 19 15:44:49 2010 +0800 +++ b/COPYING.h Wed Dec 01 12:25:56 2010 +0800 @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. *
--- a/Doxyfile Mon Jul 19 15:44:49 2010 +0800 +++ b/Doxyfile Wed Dec 01 12:25:56 2010 +0800 @@ -534,7 +534,7 @@ # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = src tools include dox README.h COPYING.h +INPUT = src tools include dox README.h COPYING.h nodejs # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build-mipsel.sh Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,5 @@ +#!/bin/sh + +autoreconf -ifs +./configure --host mipsel-linux --build i686-pc-linux-gnu --prefix ${TANGO} --disable-sh_text --with-backend=dfb +make && make install
--- a/config.mk Mon Jul 19 15:44:49 2010 +0800 +++ b/config.mk Wed Dec 01 12:25:56 2010 +0800 @@ -1,1 +1,9 @@ INCLUDES = -I$(top_srcdir)/include + +if SH_TEXT +APPCFLAGS = @pangocairo_CFLAGS@ +APPLDFLAGS = @pangocairo_LIBS@ +else +APPCFLAGS = @cairo_CFLAGS@ +APPLDFLAGS = @cairo_LIBS@ +endif \ No newline at end of file
--- a/configure.ac Mon Jul 19 15:44:49 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 @@ -33,32 +39,35 @@ AC_CHECK_FUNCS([gettimeofday memset select sqrt strdup]) AC_ARG_ENABLE([testcase], - [ --enable-testcase Enable testcase], -[case "${enableval}" in - yes) testcase=true ;; - no) testcase=false ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-testcase]) ;; -esac],[testcase=false]) + [AS_HELP_STRING([--enable-testcase],[Enable testcase])], + [case "${enableval}" in + (yes) testcase=true ;; + (no) testcase=false ;; + (*) AC_MSG_ERROR([bad value ${enableval} for --enable-testcase]) ;; + esac],[testcase=false]) + AM_CONDITIONAL([TESTCASE], [test x$testcase = xtrue]) AC_ARG_ENABLE([sh_text], - [ --disable-sh_text Turn off sh_text], -[case "${enableval}" in - yes) sh_text=true ;; - no) sh_text=false ;; - *) AC_MSG_ERROR([bad value ${enableval} for --disable-sh_text]) ;; -esac],[sh_text=true]) + [AS_HELP_STRING([--disable-sh_text],[Turn off sh_text])], + [case "${enableval}" in + (yes) sh_text=true ;; + (no) sh_text=false ;; + (*) AC_MSG_ERROR([bad value ${enableval} for --disable-sh_text]) ;; + esac],[sh_text=true]) AC_ARG_ENABLE([sh_stext], - [ --disable-sh_stext Turn off sh_stext], -[case "${enableval}" in - yes) sh_stext=true ;; - no) sh_stext=false ;; - *) AC_MSG_ERROR([bad value ${enableval} for --disable-sh_stext]) ;; -esac],[sh_stext=true]) + [AS_HELP_STRING([--disable-sh_stext],[Turn off sh_stext])], + [case "${enableval}" in + (yes) sh_stext=true ;; + (no) sh_stext=false ;; + (*) AC_MSG_ERROR([bad value ${enableval} for --disable-sh_stext]) ;; + esac],[sh_stext=true]) + AM_CONDITIONAL([SH_STEXT], [test x$sh_stext = xtrue]) + [if [ x"${sh_stext}" = xtrue ]; then] -AC_DEFINE([SH_STEXT]) + AC_DEFINE([SH_STEXT]) [fi] AC_ARG_ENABLE([mbaf], @@ -69,109 +78,174 @@ *) AC_MSG_ERROR([bad value ${enableval} for --disable-mbaf]) ;; esac],[mbaf=true]) -AC_ARG_ENABLE([X_supp], - [ --disable-X_supp Turn off X backend], -[case "${enableval}" in - yes) X_supp=true ;; - no) X_supp=false ;; - *) AC_MSG_ERROR([bad value ${enableval} for --disable-X_supp]) ;; -esac],[X_supp=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'; 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'; default_graphic_engine="cairo"]) + +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_ENABLE([skia], - [ --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([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"]) -AC_ARG_ENABLE([openvg], - [ --enable-openvg Turn on OpenVG instead of Cairo or Skia], -[case "${enableval}" in - yes) openvg=true ;; - no) openvg=false ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-openvg]) ;; -esac],[openvg=false]) - -[if [ x"$skia-%openvg" = xtrue-true ]; then] - AC_MSG_ERROR([confliction on --enable-skia and --enable-openvg]) +xshm=false +[if [ x"${backend}" = x"X" ]; then ] +AC_ARG_ENABLE([xshm], + [AS_HELP_STRING([--disable-xshm],[Turn off XSHM supporting])], + [case "${enableval}" in + (yes) xshm=true ;; + (no) xshm=false ;; + (*) AC_MSG_ERROR([bad value ${enableval} for --disable-xshm]) ;; + esac], [xshm=true]) [fi] -[if [ x"${skia}" = xtrue ]; then ] -AC_DEFINE([SKIA_GRAPH_ENGINE]) -cairo=false -[elif [ x"${openvg}" = xtrue ]; then ] -AC_DEFINE([OPENVG_GRAPH_ENGINE]) -cairo=false -mbaf=false +[if [ x"${graphic_engine}" = x"skia" ]; then ] + AC_DEFINE([SKIA_GRAPH_ENGINE]) +[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 + AC_DEFINE([CAIRO_GRAPH_ENGINE]) [fi] -AM_CONDITIONAL([SKIA_GRAPH_ENGINE], [test x$skia = xtrue]) -AM_CONDITIONAL([OPENVG_GRAPH_ENGINE], [test x$openvg = xtrue]) -AM_CONDITIONAL([CAIRO_GRAPH_ENGINE], [test x"$cairo" = xtrue]) +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], - [ --enable-nodejs Turn on nodejs support], -[case "${enableval}" in - yes) nodejs=true ;; - no) nodejs=false ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-nodejs]) ;; -esac],[nodejs=false]) + [AS_HELP_STRING([--enable-nodejs],[Turn on nodejs support])], + [case "${enableval}" in + (yes) nodejs=true ;; + (no) nodejs=false ;; + (*) AC_MSG_ERROR([bad value ${enableval} for --enable-nodejs]) ;; + esac],[nodejs=false]) + [if [ x"${nodejs}" = xtrue ]; then ] - AC_PATH_PROG([NODE_WAF], [node-waf]) - AC_CHECK_PROG([has_node], [node], [true], [false]) + AC_PATH_PROG([NODE_WAF], [node-waf]) + AC_CHECK_PROG([has_node], [node], [true], [false]) [fi] + AM_CONDITIONAL([NODEJS], [test x"${nodejs}-${has_node}" = xtrue-true]) # Define AM and AC variable for sh_text -AM_CONDITIONAL([SH_TEXT], [test x$sh_text = xtrue -a x$cairo = xtrue]) -[if [ x"${sh_text}" = xtrue -a x$cairo = xtrue ]; then] -AC_DEFINE([SH_TEXT]) + +AM_CONDITIONAL([SH_TEXT], + [test x$sh_text = xtrue -a x"${graphic_engine}" = x"cairo"]) + +[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"${graphic_engine}" = x"cairo"]) + +[if [ x"${backend}" = x'X' -a x"${graphic_engine}" = x"cairo" ]; then] + AC_DEFINE([X_BACKEND]) [fi] -# Define AM and AC variable for X_supp -AM_CONDITIONAL([X_SUPP], - [test x$X_supp = xtrue -a \( x$cairo = xtrue -o x$openvg = xtrue \)]) -[if [ x"${X_supp}" = xtrue -a \( x"${cairo}" = xtrue -o x"${openvg}" = xtrue \) ]; then] -AC_DEFINE([X_SUPP]) +AM_CONDITIONAL([DFB_BACKEND], + [test x$backend = x'dfb' -a x"${graphic_engine}" = x"cairo"]) + +[if [ x"${backend}" = x'dfb' -a x"${graphic_engine}" = x"cairo" ]; then] + AC_DEFINE([DFB_BACKEND]) +[fi] + +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] + +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"${openvg}" = xtrue ]; then] +[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"${image_loader}" = x"imlib2" ]; then] PKG_CHECK_MODULES([imlib2], [imlib2 >= 1.4.1], , AC_MSG_ERROR([imlib2 >= 1.4.1 not found])) -[if [ x"${cairo}" = xtrue ]; then] -PKG_CHECK_MODULES([cairo], [cairo >= 1.6], , AC_MSG_ERROR([cairo >= 1.6 not found])) -PKG_CHECK_MODULES([pangocairo], [pangocairo >= 1.0], , AC_MSG_ERROR([pangocairo >= 1.0 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] + PKG_CHECK_MODULES([pangocairo], [pangocairo >= 1.0], , AC_MSG_ERROR([pangocairo >= 1.0 not found: use --disable-sh_text to configure without pangocairo.])) + [fi] [fi] -AC_CONFIG_FILES([Makefile - libmbfly.pc - libmbfly-uninstalled.pc - examples/Makefile - examples/calculator/Makefile - examples/svg2code_ex/Makefile - examples/tank/Makefile - examples/drag/Makefile - examples/dynamic/Makefile - examples/menu/Makefile - src/Makefile - include/Makefile - inkscape/Makefile - nodejs/Makefile - tools/Makefile]) +AC_CONFIG_FILES([ + Makefile + libmbfly.pc + libmbfly-uninstalled.pc + examples/Makefile + examples/calculator/Makefile + examples/svg2code_ex/Makefile + examples/tank/Makefile + examples/drag/Makefile + examples/dynamic/Makefile + examples/menu/Makefile + src/Makefile + include/Makefile + inkscape/Makefile + nodejs/Makefile + tools/Makefile + ]) 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([X_SUPP], [Enable X backend]) +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]) AC_OUTPUT
--- a/dox/define_backend.h Mon Jul 19 15:44:49 2010 +0800 +++ b/dox/define_backend.h Wed Dec 01 12:25:56 2010 +0800 @@ -6,24 +6,84 @@ * that will show everything drawing on it. It also translate and * relay input events, mouse or keyboard, to MadButterfly. * The tasks that a backend should do are listed following, - * - to prepare a backend surface, - * - to prepare a front surface, - * - to translate and relay input events to MadButterfly, - * - to handle a timer, and relay timeout events to MadButterfly. + * - tranlsate and relay mouse events to MadButterfly. + * - to provide + * - *_MB_new()/*_MB_free function to create and free a runtime. + * - prepare a backend surface, + * - prepare a front surface, + * - *_MB_kbevents() to return a subject, for keyboard + * events, associated with a runtime. + * - translate and relay keyboard events to MadButterfly, + * - *_MB_tman() to return a timer manager associated with + * a runtime. + * - to handle a timer, and relay timeout events to MadButterfly. + * - *_MB_ob_factory() to return an observer factory. + * - *_MB_img_ldr() to return an image loader. * - * The output device surface for X Window is a surface return by - * cairo_xlib_surface_create(). MadButterfly will copy everything - * from front surface to backend surface to show graphy to user. - * The copying is to avoid user find slowly redrawing. The latency - * between X client and server can be large. For this situation, - * we need a font surface as a buffer drawing, and copy image from - * front surface to backend surface after completion of a series - * of drawing. A front surface can be an image surface for this - * situation. + * \section backend_mb_new_n_free *_MB_new()/*_MB_free() + * + * MadButterfly supposes that application programmers may create more + * than one instance of MadButterfly to draw mutliple windows for an + * application. So, we need you, backend developer, to provide a + * *_MB_new()/*_MB_free() to create/free an instance respective. + * + * *_MB_new() should return an *_MB_runtime_t object to keep states of + * an instance. The definition of *_MB_runtime_t is up to backend + * developers. + * + * For each *_MB_runtime_t, backend should create a redraw manager, + * a.k.a rdman, by calling malloc() and redraw_man_init(). For each + * rdman, you should give it one or two surfaces. Rdman draws shapes + * on first one, called 'cr' (should be changed), as an off-screen + * buffer and copy it to 2nd one, called 'backend' surface, as an + * on-screen buffer. For X, the 'backend' should be a window surface. + * The reason of two surfaces are to prevent user from seeing + * intermediate result of drawing procedure. You can also pass a NULL + * pointer for 2nd surface if you dont care intermediate result, HW + * accelerator is fast enough, or with HW dobule buffering. + * + * \section backend_kbevents Keyboard Events + * + * *_MB_kbevents() returns a subject (\see + * http://en.wikipedia.org/wiki/Observer_pattern). Applications want + * to receive keyboard events would register an observer on this + * subject. A backend should translate keyboard events for + * MadButterfly, and notify observers of this subject. + * Subject-observer had implemented by MadBuffery. * - * The input events of X Window should be translated to raw events of - * MadButterfly and sent them to rdman through notify_coord_or_shape() - * function. + * \section backend_timer Timer + * + * *_MB_tman() should return a timer manager, with type of mb_tman_t. + * When an application want to get notified at some time later, it + * would register a callback with the mb_tman_t. A backend should + * call mb_tman_handle_timeout() at proper time. You can call + * mb_tman_next_timeout() to get the time to call + * mb_tman_handle_timeout() for next timeout. For nodejs or other + * binding that has their-owned timer, you can skip *_MB_tman(). But, + * C code need this one. + * + * \section backend_obfactory Observer Factory + * + * *_MB_ob_factory() returns an observer factory, ob_factory_t. It is + * reponsible for creation of observers. Applications call observer + * to allocate and free observers and subjects. ob_factory_t is + * defined in mb_observer.h, there are 5 function pointers in it. You + * can use functions of default implementation instead of new ones. + * + * \section backend_img_ldr Image Loader + * + * *_MB_img_ldr() returns an image loader, mb_img_ldr_t. A backend + * developer can use the default implementation. He can also + * implement a new one, but it should implement the interface defined + * by mb_img_ldr_t and mb_img_data_t. + * + * \section backend_mouse_events Mouse Events + * + * A backend should also translate and relay mouse events to + * MadButterfly. The mouse events should be dispatched by notifing + * observers of the subject of a coord or shape of an rdman. The + * backend developers can check handle_single_x_event() in X_supp.c + * for how to dispatch mouse events. * * \see X_supp.c */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dox/dictionary.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,23 @@ +/*! \page dictionary Dictionary + * + * This page is a list of acronyms and their meaning. + * + * - \b cb stands for CallBack. + * - \b coord stands for COORDinate. + * - \b elm stands for ELMent. + * - \b fact stands for FACTory. + * - \b geo stands for GEOmetry. + * - \b ldr stands for LoaDeR. + * - \b man stands for MANager. + * - \b mb stands for MadButterfly. + * - \b mbe stands for MadButterfly graphic Engine. + * - \b obj stands for OBJect. + * - \b prop stands for PROPerty. + * - \b rdman stands for ReDraw MANager. + * - \b rect stands for RECTangle. + * - \b rm stands for ReMove. + * - \b rt stands for RunTime. + * - \b sh stands for SHapes. + * - \b tman stands for Timer MANager. + * - \b val stands for VALue. + */
--- a/examples/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,6 @@ -if X_SUPP -SUBDIRS = calculator svg2code_ex tank dynamic drag menu +if X_BACKEND +SUBDIRS = calculator tank drag +if SH_TEXT +SUBDIRS += svg2code_ex dynamic menu endif +endif
--- a/examples/calculator/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/calculator/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -5,16 +5,12 @@ calc_SOURCES = main.c nodist_calc_SOURCES = calculator_scr.c calculator_scr.h -calc_CPPFLAGS = @pangocairo_CFLAGS@ $(INCLUDES) -calc_LDFLAGS = @pangocairo_LIBS@ +calc_CPPFLAGS = $(APPCFLAGS) $(INCLUDES) +calc_LDFLAGS = $(APPLDFLAGS) calc_LDADD = $(top_builddir)/src/libmbfly.la BUILT_SOURCES = calculator_scr.c calculator_scr.h calculator_scr.mb CLEANFILES = calculator_scr.c calculator_scr.h calculator_scr.mb -if OPENVG_GRAPH_ENGINE -calc_LDFLAGS += -lOpenVG -lEGL -endif - calculator_scr.mb: $(srcdir)/calculator_scr.svg $(top_srcdir)/tools/svg2code.py -s $? $@
--- a/examples/calculator/main.c Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/calculator/main.c Wed Dec 01 12:25:56 2010 +0800 @@ -5,7 +5,7 @@ typedef struct _calc_data calc_data_t; struct _calc_data { - X_MB_runtime_t *rt; + mb_rt_t *rt; calculator_scr_t *code; }; @@ -64,7 +64,7 @@ char buf[20]; redraw_man_t *rdman; - rdman = X_MB_rdman(calc_data->rt); + rdman = mb_runtime_rdman(calc_data->rt); sprintf(buf, "%d%s", num, suffix); sh_stext_set_text(calc_data->code->screen_text_u, buf); @@ -142,7 +142,7 @@ break; } } - rdman = X_MB_rdman(calc_data->rt); + rdman = mb_runtime_rdman(calc_data->rt); rdman_redraw_changed(rdman); } @@ -174,24 +174,24 @@ } int main(int argc, char * const argv[]) { - X_MB_runtime_t *rt; + mb_rt_t *rt; redraw_man_t *rdman; calculator_scr_t *calculator_scr; calc_data_t calc_data; - rt = X_MB_new(":0.0", 300, 400); + rt = mb_runtime_new(":0.0", 300, 400); - rdman = X_MB_rdman(rt); + rdman = mb_runtime_rdman(rt); calculator_scr = calculator_scr_new(rdman, rdman->root_coord); calc_data.rt = rt; calc_data.code = calculator_scr; setup_observers(&calc_data); - X_MB_handle_connection(rt); + mb_runtime_event_loop(rt); calculator_scr_free(calculator_scr); - X_MB_free(rt); + mb_runtime_free(rt); return 0; }
--- a/examples/drag/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/drag/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -5,8 +5,8 @@ ex1_SOURCES = main.c nodist_ex1_SOURCES = menu.c menu.h -ex1_CPPFLAGS = @pangocairo_CFLAGS@ -I$(top_srcdir) -ex1_LDFLAGS = @pangocairo_LIBS@ +ex1_CPPFLAGS = $(APPCFLAGS) -I$(top_srcdir) +ex1_LDFLAGS = $(APPLDFLAGS) ex1_LDADD = $(top_builddir)/src/libmbfly.la BUILT_SOURCES = menu.c menu.h menu.mb CLEANFILES = menu.c menu.h menu.mb
--- a/examples/drag/main.c Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/drag/main.c Wed Dec 01 12:25:56 2010 +0800 @@ -10,7 +10,7 @@ typedef struct _engine engine_t; struct _engine { - X_MB_runtime_t *rt; + mb_rt_t *rt; redraw_man_t *rdman; menu_t *menu; int state; @@ -21,12 +21,12 @@ engine_t *engine_init() { - X_MB_runtime_t *rt; - rt = X_MB_new(":0.0", 800, 600); + mb_rt_t *rt; + rt = mb_runtime_new(":0.0", 800, 600); engine_t *en = (engine_t *) malloc(sizeof(engine_t)); en->rt = rt; - en->rdman = X_MB_rdman(rt); + en->rdman = mb_runtime_rdman(rt); en->state = 0; return en; } @@ -36,13 +36,13 @@ * Start handle connections, includes one to X server. * User start to interact with the application. */ - X_MB_handle_connection(en->rt); + mb_runtime_event_loop(en->rt); /* * Clean */ menu_free(en->menu); - X_MB_free(en->rt); + mb_runtime_free(en->rt); free(en); } #define COORD_SHOW(group) coord_show(group);rdman_coord_changed(X_MB_rdman(ex_rt->rt), group)
--- a/examples/dynamic/main.c Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/dynamic/main.c Wed Dec 01 12:25:56 2010 +0800 @@ -109,7 +109,7 @@ get_now(&timer); MB_TIMEVAL_SET(&interval, 1 ,0); MB_TIMEVAL_ADD(&timer, &interval); - mb_tman_timeout( mbaf_get_timer(app), &timer, switch_scene, app); + mb_timer_man_timeout( mbaf_get_timer(app), &timer, switch_scene, app); en->currentscene = (en->currentscene + 1) % 2; printf("switch to scene %d\n", en->currentscene + 1); @@ -147,7 +147,7 @@ MyApp_InitContent(); get_now(&tmo); MB_TIMEVAL_SET(&interval, 1 ,0); - mb_tman_timeout( mbaf_get_timer(app), &tmo, switch_scene, app); + mb_timer_man_timeout( mbaf_get_timer(app), &tmo, switch_scene, app); mbaf_loop(app);
--- a/examples/svg2code_ex/main.c Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/svg2code_ex/main.c Wed Dec 01 12:25:56 2010 +0800 @@ -10,31 +10,41 @@ typedef struct _ex_rt ex_rt_t; struct _ex_rt { - X_MB_runtime_t *rt; + mb_rt_t *rt; svg2code_ex_t *code; }; -#define COORD_SHOW(group) coord_show(group);rdman_coord_changed(X_MB_rdman(ex_rt->rt), group) -#define COORD_HIDE(group) coord_hide(group);rdman_coord_changed(X_MB_rdman(ex_rt->rt), group) +#define COORD_SHOW(group) do { \ + coord_show(group); \ + rdman_coord_changed(mb_runtime_rdman(ex_rt->rt), group); \ + } while(0) +#define COORD_HIDE(group) do { \ + coord_hide(group); \ + rdman_coord_changed(mb_runtime_rdman(ex_rt->rt), group); \ + } while(0) static void file_button_handler(event_t *evt, void *arg) { ex_rt_t *ex_rt = (ex_rt_t *)arg; + redraw_man_t *rdman; COORD_SHOW(ex_rt->code->file_menu); + rdman = mb_runtime_rdman(ex_rt->rt); /* Update changed part to UI. */ - rdman_redraw_changed(X_MB_rdman(ex_rt->rt)); + rdman_redraw_changed(rdman); } static void file_menu_handler(event_t *evt, void *arg) { ex_rt_t *ex_rt = (ex_rt_t *)arg; + redraw_man_t *rdman; COORD_HIDE(ex_rt->code->file_menu); + rdman = mb_runtime_rdman(ex_rt->rt); /* Update changed part to UI. */ - rdman_redraw_changed(X_MB_rdman(ex_rt->rt)); + rdman_redraw_changed(rdman); } int main(int argc, char * const argv[]) { - X_MB_runtime_t *rt; + mb_rt_t *rt; redraw_man_t *rdman; svg2code_ex_t *svg2code; subject_t *subject; @@ -43,12 +53,12 @@ /* * Initialize a runtime with XLib as backend. */ - rt = X_MB_new(":0.0", 800, 600); + rt = mb_runtime_new(":0.0", 800, 600); /* * Instantiate objects from a SVG file. */ - rdman = X_MB_rdman(rt); + rdman = mb_runtime_rdman(rt); svg2code = svg2code_ex_new(rdman, rdman->root_coord); /* @@ -65,13 +75,13 @@ * Start handle connections, includes one to X server. * User start to interact with the application. */ - X_MB_handle_connection(rt); + mb_runtime_event_loop(rt); /* * Clean */ svg2code_ex_free(svg2code); - X_MB_free(rt); + mb_runtime_free(rt); return 0; }
--- a/examples/tank/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/tank/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -7,8 +7,8 @@ tank_SOURCES = tank_main.c nodist_tank_SOURCES = svgs.h \ $(svg_sources) $(svg_sources:.c=.h) $(svg_sources:.c=.mb) -tank_CPPFLAGS = @pangocairo_CFLAGS@ -tank_LDFLAGS = @pangocairo_LIBS@ +tank_CPPFLAGS = $(APPCFLAGS) +tank_LDFLAGS = $(APPLDFLAGS) tank_LDADD = $(top_builddir)/src/libmbfly.la BUILT_SOURCES = svgs.h \ $(svg_sources) $(svg_sources:.c=.h) $(svg_sources:.c=.mb)
--- a/examples/tank/tank_main.c Mon Jul 19 15:44:49 2010 +0800 +++ b/examples/tank/tank_main.c Wed Dec 01 12:25:56 2010 +0800 @@ -58,9 +58,9 @@ int direction; mb_progm_t *progm; mb_timeval_t start_time; - observer_t *ob_redraw; - mb_timer_t *hit_tmr; - mb_tman_t *tman; + observer_t *observer_redraw; + int hit_tmr; + mb_timer_man_t *timer_man; }; typedef struct _tank_bullet tank_bullet_t; /*! \brief The direction a bullet is going. @@ -106,7 +106,7 @@ tank_t *tanks[12]; int n_tanks; void *map[12][16]; - X_MB_runtime_t *mb_rt; + mb_rt_t *mb_rt; observer_t *kb_observer; }; @@ -124,7 +124,7 @@ if(tank == NULL) return NULL; - rdman = X_MB_rdman(tank_rt->mb_rt); + rdman = mb_runtime_rdman(tank_rt->mb_rt); tank->coord_pos = coord_pos; tank->coord_rot = coord_rot; @@ -145,11 +145,8 @@ return tank; } -static void tank_free(tank_t *tank, X_MB_runtime_t *xmb_rt) { - mb_tman_t *tman; - +static void tank_free(tank_t *tank, mb_rt_t *mb_rt) { if(tank->progm) { - tman = X_MB_tman(xmb_rt); mb_progm_abort(tank->progm); } free(tank); @@ -170,10 +167,10 @@ static void tank_move(tank_t *tank, int direction, tank_rt_t *tank_rt) { - X_MB_runtime_t *xmb_rt = tank_rt->mb_rt; + mb_rt_t *mb_rt = tank_rt->mb_rt; redraw_man_t *rdman; - mb_tman_t *tman; - ob_factory_t *factory; + mb_timer_man_t *timer_man; + observer_factory_t *factory; /* for the program */ mb_progm_t *progm; subject_t *comp_sub; @@ -239,9 +236,9 @@ } } - rdman = X_MB_rdman(xmb_rt); - tman = X_MB_tman(xmb_rt); - factory = X_MB_ob_factory(xmb_rt); + rdman = mb_runtime_rdman(mb_rt); + timer_man = mb_runtime_timer_man(mb_rt); + factory = mb_runtime_observer_factory(mb_rt); progm = mb_progm_new(1, rdman); tank->progm = progm; @@ -269,7 +266,7 @@ subject_add_observer(comp_sub, clean_tank_progm_handler, tank); get_now(&now); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); } /* @} */ @@ -310,6 +307,7 @@ bullet = O_ALLOC(tank_bullet_t); bullet->rdman = rdman; + bullet->hit_tmr = -1; make_bullet_elf_coords(rdman, &bullet->coord_pos, &bullet->coord_rot, @@ -338,6 +336,8 @@ } static void tank_bullet_free(tank_bullet_t *bullet) { + if(bullet->hit_tmr != -1) + mb_timer_man_remove(bullet->timer_man, bullet->hit_tmr); bullet_free(bullet->bullet_obj); rdman_coord_subtree_free(bullet->rdman, bullet->coord_pos); } @@ -350,8 +350,10 @@ bullet = tank->bullet; rdman = bullet->rdman; - if(bullet->hit_tmr != NULL) - mb_tman_remove(bullet->tman, bullet->hit_tmr); + if(bullet->hit_tmr != -1) { + mb_timer_man_remove(bullet->timer_man, bullet->hit_tmr); + bullet->hit_tmr = -1; + } coord_hide(bullet->coord_pos); rdman_coord_changed(rdman, bullet->coord_pos); @@ -364,7 +366,7 @@ static void bullet_bang(tank_bullet_t *bullet, int map_x, int map_y) { redraw_man_t *rdman; - mb_tman_t *tman; + mb_timer_man_t *timer_man; mb_progm_t *progm; mb_word_t *word; mb_timeval_t start, playing; @@ -373,7 +375,7 @@ co_aix *matrix; rdman = bullet->rdman; - tman = bullet->tman; + timer_man = bullet->timer_man; bang = bang_new(rdman, rdman->root_coord); matrix = bang->root_coord->matrix; @@ -401,11 +403,12 @@ mb_progm_free_completed(progm); get_now(&now); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); } /*! \brief To check if a bullet hits walls or tanks. */ -static void bullet_hit_chk(const mb_timeval_t *tmo, +static void bullet_hit_chk(int hdl, + const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg) { tank_t *tank = (tank_t *)arg; @@ -422,9 +425,9 @@ static int move_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; bullet = tank->bullet; - bullet->hit_tmr = NULL; /* clear hit timer that bullet_go_out_map() - * can not remove it & currupt memory. - */ + bullet->hit_tmr = -1; /* clear hit timer that bullet_go_out_map() + * can not remove it & currupt memory. + */ MB_TIMEVAL_CP(&diff, now); MB_TIMEVAL_DIFF(&diff, &bullet->start_time); @@ -480,13 +483,13 @@ MB_TIMEVAL_SET(&next, 0, 100000); MB_TIMEVAL_ADD(&next, now); - bullet->hit_tmr = mb_tman_timeout(bullet->tman, &next, - bullet_hit_chk, arg); + bullet->hit_tmr = mb_timer_man_timeout(bullet->timer_man, &next, + bullet_hit_chk, arg); } /*! \brief To fire a bullet for a tank. */ static void tank_fire_bullet(tank_rt_t *tank_rt, tank_t *tank) { - X_MB_runtime_t *xmb_rt; + mb_rt_t *mb_rt; redraw_man_t *rdman; int map_x, map_y; int shift_x, shift_y; @@ -498,16 +501,16 @@ mb_action_t *act; mb_timeval_t start, playing; mb_timeval_t now, next; - mb_tman_t *tman; + mb_timer_man_t *timer_man; subject_t *subject; static int map_xy_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; if(tank->bullet != NULL) return; - xmb_rt = tank_rt->mb_rt; - rdman = X_MB_rdman(xmb_rt); - tman = X_MB_tman(xmb_rt); + mb_rt = tank_rt->mb_rt; + rdman = mb_runtime_rdman(mb_rt); + timer_man = mb_runtime_timer_man(mb_rt); dir = tank->direction; map_x = tank->map_x + map_xy_adj[dir][0]; @@ -540,7 +543,7 @@ tank->bullet = tank_bullet_new(rdman, map_x, map_y, dir); bullet = tank->bullet; - bullet->tman = tman; + bullet->timer_man = timer_man; progm = mb_progm_new(2, rdman); MB_TIMEVAL_SET(&start, 0, 0); @@ -555,11 +558,12 @@ get_now(&now); MB_TIMEVAL_CP(&bullet->start_time, &now); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); MB_TIMEVAL_SET(&next, 0, 100000); MB_TIMEVAL_ADD(&next, &now); - bullet->hit_tmr = mb_tman_timeout(tman, &next, bullet_hit_chk, tank); + bullet->hit_tmr = mb_timer_man_timeout(timer_man, &next, + bullet_hit_chk, tank); } /* @} */ @@ -615,14 +619,14 @@ } static void init_keyboard(tank_rt_t *tank_rt) { - X_MB_runtime_t *mb_rt; + mb_rt_t *mb_rt; subject_t *kbevents; redraw_man_t *rdman; mb_rt = tank_rt->mb_rt; - kbevents = X_MB_kbevents(mb_rt); + kbevents = mb_runtime_kbevents(mb_rt); - rdman = X_MB_rdman(mb_rt); + rdman = mb_runtime_rdman(mb_rt); tank_rt->kb_observer = subject_add_observer(kbevents, keyboard_handler, tank_rt); @@ -654,7 +658,7 @@ } void -initial_tank(tank_rt_t *tank_rt, X_MB_runtime_t *mb_rt) { +initial_tank(tank_rt_t *tank_rt, mb_rt_t *mb_rt) { redraw_man_t *rdman; /* for map areas */ mud_t *mud; @@ -668,7 +672,7 @@ tank_en_t *tank_en_o; int i, j; - rdman = X_MB_rdman(mb_rt); + rdman = mb_runtime_rdman(mb_rt); tank_rt->mb_rt = mb_rt; for(i = 0; i < 12; i++) { @@ -727,16 +731,16 @@ int main(int argc, char *const argv[]) { - X_MB_runtime_t *rt; + mb_rt_t *rt; tank_rt_t tank_rt; - rt = X_MB_new(":0.0", 800, 600); + rt = mb_runtime_new(":0.0", 800, 600); initial_tank(&tank_rt, rt); - X_MB_handle_connection(rt); + mb_runtime_event_loop(rt); - X_MB_free(rt); + mb_runtime_free(rt); } /* @} */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/img/highlevel.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,912 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448819" + height="1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="highlevel.svg"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <inkscape:perspective + id="perspective2830" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2852" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2877" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2905" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2938" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2987" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3015" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3043" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3071" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3099" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3207" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3256" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3287" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3339" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1" + inkscape:cx="195.30247" + inkscape:cy="627.63476" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1440" + inkscape:window-height="900" + inkscape:window-x="-1" + inkscape:window-y="-1" + inkscape:window-maximized="0" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + id="g3128" + transform="matrix(0.49,0,0,0.49,150.2233,284.31953)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="213.8497" + inkscape:bbox-y="653.14279" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="653.14279" + inkscape:bbox-x="213.8497" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="173.17871" + x="132.52283" + height="58.637783" + width="269.73572" + id="rect2816" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="10.432598" + inkscape:bbox-width="120.12752" + inkscape:bbox-y="663.60253" + inkscape:bbox-x="221.18097" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818" + y="208.56694" + x="142.96393" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="10.432598" + inkscape:bbox-width="120.12752" + inkscape:bbox-y="663.60253" + inkscape:bbox-x="221.18097" + y="208.56694" + x="142.96393" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820" + sodipodi:role="line">rdman/paint/shapes</tspan></text> + </g> + <g + id="g3133" + transform="matrix(0,-0.49,0.49,0,449.04412,564.75137)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="569.75296" + inkscape:bbox-y="549.7048" + inkscape:bbox-width="31.352081" + inkscape:bbox-height="134.79007" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="134.79007" + inkscape:bbox-width="31.352081" + inkscape:bbox-y="549.70479" + inkscape:bbox-x="569.75296" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="249.01759" + x="129.39545" + height="58.637783" + width="269.73572" + id="rect2816-7" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="53.352578" + inkscape:bbox-width="8.3429199" + inkscape:bbox-y="590.42354" + inkscape:bbox-x="581.25754" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9" + y="286.53815" + x="208.87659" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="53.352578" + inkscape:bbox-width="8.3429199" + inkscape:bbox-y="590.42354" + inkscape:bbox-x="581.25754" + y="286.53815" + x="208.87659" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3" + sodipodi:role="line">observer</tspan></text> + </g> + <g + id="g3181" + transform="matrix(0.49,0,0,0.49,57.15012,178.96602)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="352.12911" + inkscape:bbox-y="595.67724" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="595.67724" + inkscape:bbox-x="352.12911" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="505.46249" + x="604.67096" + height="58.637783" + width="269.73572" + id="rect2816-7-8" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="10.516816" + inkscape:bbox-width="90.161436" + inkscape:bbox-y="606.09488" + inkscape:bbox-x="374.44342" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0" + y="540.76477" + x="647.24731" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="10.516816" + inkscape:bbox-width="90.161436" + inkscape:bbox-y="606.09488" + inkscape:bbox-x="374.44342" + y="540.76477" + x="647.24731" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2" + sodipodi:role="line">timer manager</tspan></text> + </g> + <g + id="g3143" + transform="matrix(0.49,0,0,0.49,-1.3250335,168.4974)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="263.04767" + inkscape:bbox-y="711.11625" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="711.11626" + inkscape:bbox-x="263.04767" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="291.23721" + x="542.20917" + height="58.637783" + width="269.73572" + id="rect2816-7-8-4" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="8.3429199" + inkscape:bbox-width="49.194277" + inkscape:bbox-y="722.62084" + inkscape:bbox-x="305.84557" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-8" + y="328.75775" + x="625.03113" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="8.3429199" + inkscape:bbox-width="49.194277" + inkscape:bbox-y="722.62084" + inkscape:bbox-x="305.84557" + y="328.75775" + x="625.03113" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-3" + sodipodi:role="line">backend</tspan></text> + </g> + <g + id="g3153" + transform="matrix(0.49,0,0,0.49,108.0819,221.28227)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="213.8497" + inkscape:bbox-y="557.95824" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="557.95824" + inkscape:bbox-x="213.8497" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="496.08035" + x="218.52568" + height="58.637783" + width="269.73572" + id="rect2816-7-8-9" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="10.516816" + inkscape:bbox-width="90.019316" + inkscape:bbox-y="568.37588" + inkscape:bbox-x="236.23509" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-0" + y="531.38263" + x="260.54883" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="10.516816" + inkscape:bbox-width="90.019316" + inkscape:bbox-y="568.37588" + inkscape:bbox-x="236.23509" + y="531.38263" + x="260.54883" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-5" + sodipodi:role="line">graphic engine</tspan></text> + </g> + <g + id="g3163" + transform="matrix(0.49,0,0,0.49,145.98816,39.516328)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="352.12911" + inkscape:bbox-y="653.14278" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="653.14278" + inkscape:bbox-x="352.12911" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="672.7771" + x="423.36884" + height="58.637783" + width="269.73572" + id="rect2816-7-8-9-2" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="8.3429199" + inkscape:bbox-width="48.688965" + inkscape:bbox-y="664.64735" + inkscape:bbox-x="395.17966" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-0-2" + y="710.29767" + x="507.60876" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="8.3429199" + inkscape:bbox-width="48.688965" + inkscape:bbox-y="664.64735" + inkscape:bbox-x="395.17966" + y="710.29767" + x="507.60876" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-5-7" + sodipodi:role="line">animate</tspan></text> + </g> + <g + id="g3168" + transform="matrix(0,-0.49,0.49,0,111.91294,803.04184)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="494.66467" + inkscape:bbox-y="549.70479" + inkscape:bbox-width="31.352081" + inkscape:bbox-height="134.79007" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="134.79007" + inkscape:bbox-width="31.352081" + inkscape:bbox-y="549.70479" + inkscape:bbox-x="494.66467" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="783.79901" + x="615.70251" + height="58.637783" + width="269.73572" + id="rect2816-7-8-9-2-3" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="78.82875" + inkscape:bbox-width="10.516816" + inkscape:bbox-y="577.68545" + inkscape:bbox-x="505.08231" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-0-2-7" + y="819.10132" + x="668.28522" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="78.82875" + inkscape:bbox-width="10.516816" + inkscape:bbox-y="577.68545" + inkscape:bbox-x="505.08231" + y="819.10132" + x="668.28522" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-5-7-9" + sodipodi:role="line">image loader</tspan></text> + </g> + <g + id="g3173" + transform="matrix(0,-0.49,0.49,0,141.02882,584.67276)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="534.50744" + inkscape:bbox-y="549.70479" + inkscape:bbox-width="31.352081" + inkscape:bbox-height="134.79007" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="134.79007" + inkscape:bbox-width="31.352081" + inkscape:bbox-y="549.70479" + inkscape:bbox-x="534.50743" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="805.69061" + x="170.05133" + height="58.637783" + width="269.73572" + id="rect2816-7-8-9-2-0" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="51.910332" + inkscape:bbox-width="9.8957031" + inkscape:bbox-y="591.14466" + inkscape:bbox-x="545.23563" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-0-2-2" + y="840.35913" + x="250.10181" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="51.910332" + inkscape:bbox-width="9.8957031" + inkscape:bbox-y="591.14466" + inkscape:bbox-x="545.23563" + y="840.35913" + x="250.10181" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-5-7-3" + sodipodi:role="line">property</tspan></text> + </g> + <g + id="g3158" + transform="matrix(0.49,0,0,0.49,174.74193,126.86394)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="213.8497" + inkscape:bbox-y="595.67724" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="595.67724" + inkscape:bbox-x="213.8497" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="611.79327" + x="82.48481" + height="58.637783" + width="269.73572" + id="rect2816-7-8-9-9" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="10.432598" + inkscape:bbox-width="78.333965" + inkscape:bbox-y="606.13697" + inkscape:bbox-x="242.07775" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-0-9" + y="647.18152" + x="136.47473" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="10.432598" + inkscape:bbox-width="78.333965" + inkscape:bbox-y="606.13697" + inkscape:bbox-x="242.07775" + y="647.18152" + x="136.47473" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-5-70" + sodipodi:role="line">element pool</tspan></text> + </g> + <g + id="g3148" + transform="matrix(0.49,0,0,0.49,36.985323,103.36979)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="408.62703" + inkscape:bbox-y="711.11625" + inkscape:bbox-width="134.79007" + inkscape:bbox-height="31.352081" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.352081" + inkscape:bbox-width="134.79007" + inkscape:bbox-y="711.11625" + inkscape:bbox-x="408.62703" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="424.1507" + x="761.12549" + height="58.637783" + width="269.73572" + id="rect2816-7-8-4-9" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" /> + <text + inkscape:bbox-height="8.3429199" + inkscape:bbox-width="46.68877" + inkscape:bbox-y="722.62084" + inkscape:bbox-x="452.67768" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-0-8-8" + y="461.67123" + x="846.50409" + style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="8.3429199" + inkscape:bbox-width="46.68877" + inkscape:bbox-y="722.62084" + inkscape:bbox-x="452.67768" + y="461.67123" + x="846.50409" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-2-3-6" + sodipodi:role="line">runtime</tspan></text> + </g> + <g + id="g3194" + transform="matrix(0.49,0,0,0.49,290.43922,204.63397)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="222.3793" + inkscape:bbox-y="634.08892" + inkscape:bbox-width="111.6012" + inkscape:bbox-height="9.6956378" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="9.6956378" + inkscape:bbox-width="111.6012" + inkscape:bbox-y="634.08891" + inkscape:bbox-x="222.3793" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="416.21155" + x="-138.8978" + height="19.787016" + width="227.75755" + id="rect3186" + style="fill:#cccccc;fill-opacity:1;stroke:none" /> + <text + inkscape:bbox-height="6.7528125" + inkscape:bbox-width="21.877734" + inkscape:bbox-y="635.56033" + inkscape:bbox-x="267.24104" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text3190" + y="432.65582" + x="-49.218239" + style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="6.7528125" + inkscape:bbox-width="21.877734" + inkscape:bbox-y="635.56033" + inkscape:bbox-x="267.24104" + y="432.65582" + x="-49.218239" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan3192" + sodipodi:role="line">use</tspan></text> + </g> + <g + id="g3243" + transform="matrix(0.49,0,0,0.49,164.01503,215.36088)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="219.31448" + inkscape:bbox-y="691.17135" + inkscape:bbox-width="368.28064" + inkscape:bbox-height="9.6956378" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="9.6956378" + inkscape:bbox-width="368.28064" + inkscape:bbox-y="691.17135" + inkscape:bbox-x="219.31448" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="277.82513" + x="112.85602" + height="19.787016" + width="751.59314" + id="rect3186-7" + style="fill:#cccccc;fill-opacity:1;stroke:none" /> + <text + inkscape:bbox-height="6.7528125" + inkscape:bbox-width="21.877734" + inkscape:bbox-y="692.64277" + inkscape:bbox-x="392.51593" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text3190-6" + y="294.26941" + x="464.45337" + style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="6.7528125" + inkscape:bbox-width="21.877734" + inkscape:bbox-y="692.64277" + inkscape:bbox-x="392.51593" + y="294.26941" + x="464.45337" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan3192-2" + sodipodi:role="line">use</tspan></text> + </g> + <g + id="g3194-7" + transform="matrix(0.49,0,0,0.49,431.78345,204.63397)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="363.72353" + inkscape:bbox-y="634.08892" + inkscape:bbox-width="111.6012" + inkscape:bbox-height="9.6956378" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="9.6956378" + inkscape:bbox-width="111.6012" + inkscape:bbox-y="634.08891" + inkscape:bbox-x="363.72353" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="416.21155" + x="-138.8978" + height="19.787016" + width="227.75755" + id="rect3186-0" + style="fill:#cccccc;fill-opacity:1;stroke:none" /> + <text + inkscape:bbox-height="6.7528125" + inkscape:bbox-width="21.877734" + inkscape:bbox-y="635.56033" + inkscape:bbox-x="408.58527" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text3190-3" + y="432.65582" + x="-49.218239" + style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="6.7528125" + inkscape:bbox-width="21.877734" + inkscape:bbox-y="635.56033" + inkscape:bbox-x="408.58527" + y="432.65582" + x="-49.218239" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan3192-9" + sodipodi:role="line">use</tspan></text> + </g> + <g + id="g3404" + transform="translate(-10.31929,0)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="211.22823" + inkscape:bbox-y="781.89572" + inkscape:bbox-width="384.44808" + inkscape:bbox-height="31.35208" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="31.35208" + inkscape:bbox-width="384.44808" + inkscape:bbox-y="781.89572" + inkscape:bbox-x="211.22823" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="241.26933" + x="223.70247" + height="27.042181" + width="380.13818" + id="rect2816-7-9" + style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:4.30989933" /> + <text + inkscape:bbox-height="10.432597" + inkscape:bbox-width="67.943473" + inkscape:bbox-y="792.35545" + inkscape:bbox-x="369.48054" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text2818-9-1" + y="257.7644" + x="379.74719" + style="font-size:10.77999973px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="10.432597" + inkscape:bbox-width="67.943473" + inkscape:bbox-y="792.35545" + inkscape:bbox-x="369.48054" + y="257.7644" + x="379.74719" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan2820-3-7" + sodipodi:role="line">Application</tspan></text> + </g> + <g + id="g3396" + transform="translate(-10,0)" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="210.06335" + inkscape:bbox-y="765.72395" + inkscape:bbox-width="386.77783" + inkscape:bbox-height="9.6956377" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + inkscape:bbox-height="9.6956377" + inkscape:bbox-width="386.77783" + inkscape:bbox-y="765.72395" + inkscape:bbox-x="210.06335" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + y="276.9426" + x="220.06335" + height="9.6956377" + width="386.77783" + id="rect3186-7-3" + style="fill:#cccccc;fill-opacity:1;stroke:none" /> + <text + inkscape:bbox-height="6.7528126" + inkscape:bbox-width="21.877735" + inkscape:bbox-y="767.19538" + inkscape:bbox-x="392.51342" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + sodipodi:linespacing="125%" + id="text3190-6-6" + y="285.00027" + x="401.59467" + style="font-size:11.76000023px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve"><tspan + inkscape:bbox-height="6.7528126" + inkscape:bbox-width="21.877735" + inkscape:bbox-y="767.19538" + inkscape:bbox-x="392.51342" + y="285.00027" + x="401.59467" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="tspan3192-2-5" + sodipodi:role="line">use</tspan></text> + </g> + <rect + style="fill:none;stroke:#999999;stroke-width:0.83045471" + id="rect3375" + width="401.16956" + height="206.16954" + x="206.91522" + y="301.2774" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="206.49999" + inkscape:bbox-y="544.50001" + inkscape:bbox-width="402.00001" + inkscape:bbox-height="207" + inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> +</svg>
--- a/include/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/include/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 include_HEADERS = \ mb_config.h \ mb_animate.h \ @@ -10,9 +12,16 @@ mb_shapes.h \ mb_tools.h \ mb_prop.h \ - mb_X_supp.h \ mb_img_ldr.h \ mb_af.h \ mb_ani_menu.h \ mbbutton.h \ mb_so.h + +if X_BACKEND +include_HEADERS += mb_X_supp.h +endif + +if DFB_BACKEND +include_HEADERS += mb_dfb_supp.h +endif
--- a/include/mb.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_H_ #define __MB_H_ @@ -5,10 +7,15 @@ #include "mb_types.h" #include "mb_redraw_man.h" -#ifdef X_SUPP +#ifdef X_BACKEND #include "mb_X_supp.h" #endif +#ifdef DFB_BACKEND +#include "mb_dfb_supp.h" +#endif #include "mb_animate.h" #include "mb_shapes.h" +#include "mb_backend.h" +#include "mb_sprite.h" #endif /* __MB_H_ */
--- a/include/mb_X_supp.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_X_supp.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __X_SUPP_H_ #define __X_SUPP_H_ @@ -21,16 +23,9 @@ /* @} */ -typedef struct _X_MB_runtime X_MB_runtime_t; - -extern void X_MB_handle_connection(void *rt); -extern void *X_MB_new(const char *display_name, int w, int h); -extern void X_MB_free(void *xmb_rt); +typedef struct _X_supp_runtime X_supp_runtime_t; -extern subject_t *X_MB_kbevents(void *xmb_rt); -extern redraw_man_t *X_MB_rdman(void *xmb_rt); -extern mb_tman_t *X_MB_tman(void *xmb_rt); -extern ob_factory_t *X_MB_ob_factory(void *xmb_rt); -extern mb_img_ldr_t *X_MB_img_ldr(void *xmb_rt); +typedef Window MB_WINDOW; +typedef Display *MB_DISPLAY; #endif
--- a/include/mb_af.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_af.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,9 +1,13 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __APP_H #define __APP_H +#include "mb_backend.h" + typedef struct _mbapp mbaf_t; struct _mbapp { - void *rt; + mb_rt_t *rt; redraw_man_t *rdman; mb_sprite_t *rootsprite; mb_obj_t *root; @@ -12,7 +16,7 @@ }; mbaf_t *mbaf_init(const char *module, const char *module_dir); void mbaf_set_data(mbaf_t *app,void *data); -mb_tman_t *mbaf_get_timer(mbaf_t *app); +mb_timer_man_t *mbaf_get_timer(mbaf_t *app); void mbaf_loop(mbaf_t *app); #define MBAF_DATA(app,type) ((type *) ((app)->private)) #define MBAF_RDMAN(app) (((mbaf_t *) app)->rdman)
--- a/include/mb_ani_menu.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_ani_menu.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __ANIMATED_MENU_H #define __ANIMATED_MENU_H typedef struct _mb_animated_menu { @@ -19,9 +21,9 @@ X_kb_event_t pending_keys[16]; int pending_pos, pending_last; } mb_animated_menu_t; -/** \brief Create an instace of animated menu. +/** \brief Create an instace of animated menu. * - * The objectnames is used to extract symbols from the SVG file. + * The objectnames is used to extract symbols from the SVG file. * ${objectnames}0 - ${objectnames}8 is the text object. * ${objectnames}_lightbar is the lightbar. *
--- a/include/mb_animate.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_animate.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,9 +1,11 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __ANIMATE_H_ #define __ANIMATE_H_ #include "mb_types.h" -#include "mb_timer.h" #include "mb_paint.h" +#include "mb_backend.h" /*! \page def_action How to Define An Action? * @@ -40,7 +42,7 @@ extern mb_word_t *mb_progm_next_word(mb_progm_t *progm, const mb_timeval_t *start, const mb_timeval_t *playing); -extern void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, +extern void mb_progm_start(mb_progm_t *progm, mb_timer_man_t *timer_man, mb_timeval_t *now); extern void mb_progm_abort(mb_progm_t *progm); extern subject_t *mb_progm_get_complete(mb_progm_t *progm);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_backend.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,196 @@ +#ifndef __MB_BACKEND_H_ +#define __MB_BACKEND_H_ + +#include "mb_redraw_man.h" +#include "mb_timer.h" +#include "mb_observer.h" +#include "mb_img_ldr.h" + +#include "mb_config.h" + +#ifdef X_BACKEND +#include "mb_X_supp.h" +#endif + +#ifdef DFB_BACKEND +#inclde "mb_dfb_supp.h" +#endif + +struct _mb_rt; +typedef struct _mb_rt mb_rt_t; + +struct _mb_timer_man; +struct _mb_timer_factory; +struct _mb_IO_man; +struct _mb_IO_factory; + +/*! \brief Type of IO that registered with an IO manager. + */ +enum _MB_IO_TYPE {MB_IO_DUMMY, MB_IO_R, MB_IO_W, MB_IO_RW}; + +typedef struct _mb_timer_man mb_timer_man_t; +typedef struct _mb_timer_factory mb_timer_factory_t; +typedef struct _mb_IO_man mb_IO_man_t; +typedef struct _mb_IO_factory mb_IO_factory_t; +typedef enum _MB_IO_TYPE MB_IO_TYPE; + +/*! \brief Function signature of callback functions for IO requests. + */ +typedef void (*mb_IO_cb_t)(int hdl, int fd, MB_IO_TYPE type, void *data); + +/*! \brief The backend engine mb_backend_t is used to define the + * interface to realize the MB. + * + * A backend is used to receive events from the system. The MB does + * not define the backend by itself. Instead, it define an interface + * which allow the lower layer to implement the event system. Each + * backend need to provides the following events. + * + * - keyboard event + * - timer event + * - image loader(?) + * - render manager(?) + */ +typedef struct { + mb_rt_t *(*rt_new)(const char *display, int w,int h); + mb_rt_t *(*rt_new_with_win)(MB_DISPLAY display, MB_WINDOW win); + + void (*rt_free)(mb_rt_t *rt); + void (*rt_free_keep_win)(mb_rt_t *rt); + /*! \brief Request the backend to start monitoring a file descriptor. + * + * This is used only when the backend is responsible for event loop. + */ + int (*add_event)(mb_rt_t *rt, int fd, MB_IO_TYPE type, + mb_IO_cb_t f,void *arg); + /*! \brief Request the backend to stop monitoring a file descriptor. + * + * This is used only when the backend is responsible for event loop. + */ + void (*remove_event)(mb_rt_t *rt, int hdl); + /*! \brief Event Loop + * + * This is called when main application does not handle event + * loop. Or, it should register an IO factory (i.e \ref + * mb_IO_factory_t) with the backend. + */ + void (*event_loop)(mb_rt_t *rt); + + /*! \brief Flush requests to screen server if existed */ + int (*flush)(mb_rt_t *rt); + + subject_t *(*kbevents)(mb_rt_t *rt); + redraw_man_t *(*rdman)(mb_rt_t *rt); + mb_timer_man_t *(*timer_man)(mb_rt_t *rt); + observer_factory_t *(*observer_factory)(mb_rt_t *rt); + mb_img_ldr_t *(*loader)(mb_rt_t *rt); + + /* + * Following two methods are used to integrate a backend to + * event loop of main application. + */ + void (*reg_IO_factory)(mb_IO_factory_t *io_man); + void (*reg_timer_factory)(mb_timer_factory_t *tm_man); +} mb_backend_t; + +#define mb_runtime_new(disp, w, h) \ + mb_dfl_backend.rt_new((disp), (w), (h)) +#define mb_runtime_new_with_win(disp, win) \ + mb_dfl_backend.rt_new_with_win((disp), (win)) +#define mb_reg_IO_factory(io_fact) \ + mb_dfl_backend.reg_IO_factory(io_fact) +#define mb_reg_timer_factory(tm_fact) \ + mb_dfl_backend.reg_timer_factory(tm_fact) + +/* + * This is defined by backend implementations. For example, X_supp.c + * or dfb_supp.c should defined a backend. + */ +extern mb_backend_t mb_dfl_backend; + +#define mb_runtime_free(rt) \ + mb_dfl_backend.rt_free(rt) +#define mb_runtime_free_keep_win(rt) \ + mb_dfl_backend.rt_free_keep_win(rt) +#define mb_runtime_add_event(rt, fd, type, cb, arg) \ + mb_dfl_backend.add_event((rt), (fd), (type), (cb), (arg)) +#define mb_runtime_remove_event(hdl) \ + mb_dfl_backend.remove_event((rt), (hdl)) +#define mb_runtime_event_loop(rt) \ + mb_dfl_backend.event_loop(rt) +#define mb_runtime_flush(rt) \ + mb_dfl_backend.flush(rt) +#define mb_runtime_kbevents(rt) \ + mb_dfl_backend.kbevents(rt) +#define mb_runtime_rdman(rt) \ + mb_dfl_backend.rdman(rt) +#define mb_runtime_timer_man(rt) \ + mb_dfl_backend.timer_man(rt) +#define mb_runtime_observer_factory(rt) \ + mb_dfl_backend.observer_factory(rt) +#define mb_runtime_loader(rt) \ + mb_dfl_backend.loader(rt) + + +/*! \brief IO Manager + */ +struct _mb_IO_man { + int (*reg)(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data); + void (*unreg)(struct _mb_IO_man *io_man, + int io_hdl); +}; + +/*! \brief Factory of IO managers. + */ +struct _mb_IO_factory { + mb_IO_man_t *(*io_man_new)(void); + void (*io_man_free)(mb_IO_man_t *io_man); +}; + +#define mb_io_man_reg(io_man, fd, type, cb, data) \ + (io_man)->reg(io_man, fd, type, cb, data) +#define mb_io_man_unreg(io_man, io_hdl) \ + (io_man)->unreg(io_man, io_hdl) +#define mb_io_man_new(io_fact) (io_fact)->io_man_new() +#define mb_io_man_free(io_fact, io_man) (io_fact)->io_man_free(io_man) + +/*! \brief Function signature of callback functions for timers. + */ +typedef void (*mb_timer_cb_t)(int hdl, + const mb_timeval_t *tmo, + const mb_timeval_t *now, + void *data); + +/*! \brief Timer manager + */ +struct _mb_timer_man { + /*! \brief Setup a timeout callback. + * + * \return -1 for error. + */ + int (*timeout)(struct _mb_timer_man *tm_man, + mb_timeval_t *tmout, /* tiemout (wall time) */ + mb_timer_cb_t cb, void *data); + /*! \brief Remove a timeout request. + * + * \param tm_hdl is the handle returned by _mb_timer_man::timeout. + */ + void (*remove)(struct _mb_timer_man *tm_man, int tm_hdl); +}; + +/*! \brief Factory of timer manager. + */ +struct _mb_timer_factory { + mb_timer_man_t *(*timer_man_new)(void); + void (*timer_man_free)(mb_timer_man_t *timer_man); +}; + +#define mb_timer_man_timeout(tm_man, tmout, cb, data) \ + (tm_man)->timeout((tm_man), (tmout), (cb), (data)) +#define mb_timer_man_remove(tm_man, tm_hdl) \ + (tm_man)->remove((tm_man), (tm_hdl)) +#define mb_timer_man_new(tm_fact) (tm_fact)->timer_man_new() +#define mb_timer_man_free(tm_fact, tm_man) (tm_fact)->timer_man_free(tm_man) + +#endif /* __MB_BACKEND_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_backend_utils.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,12 @@ +#ifndef __MB_BACKEND_UTILS_H_ +#define __MB_BACKEND_UTILS_H_ + +#include "mb_backend.h" +#include "mb_timer.h" + +/*! \brief A facotry of timer manager implemented with mb_tman_t. + */ +extern mb_timer_factory_t tman_timer_factory; +extern mb_tman_t *tman_timer_man_get_tman(mb_timer_man_t *tm_man); + +#endif /* __MB_BACKEND_UTILS_H_ */
--- a/include/mb_basic_types.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_basic_types.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_BASIC_TYPES_H_ #define __MB_BASIC_TYPES_H_ @@ -7,9 +9,5 @@ co_aix offset; co_comp_t r, g, b, a; } grad_stop_t; -typedef struct _area { - co_aix x, y; - co_aix w, h; -} area_t; #endif /* __MB_BASIC_TYPES_H_ */
--- a/include/mb_config.h.in Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_config.h.in Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_CONFIG_H_ #define __MB_CONFIG_H_ @@ -10,6 +12,15 @@ /* 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 @@ -17,6 +28,9 @@ #undef SH_STEXT /* Enable X backend */ -#undef X_SUPP +#undef X_BACKEND + +/* Enable DirectFB backend */ +#undef DFB_BACKEND #endif /* __MB_CONFIG_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_dfb_supp.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,38 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +#ifndef __DFB_SUPP_H_ +#define __DFB_SUPP_H_ + +#include "mb_types.h" +#include "mb_timer.h" +#include "mb_redraw_man.h" +#include "mb_img_ldr.h" + +/*! \ingroup xkb + * @{ + */ +typedef struct _X_kb_info X_kb_info_t; + +struct _X_kb_event { + event_t event; + int keycode; + int sym; +}; +typedef struct _X_kb_event X_kb_event_t; + +/* @} */ + +typedef struct _X_MB_runtime X_MB_runtime_t; + +extern void X_MB_handle_connection(void *rt); +extern void *X_MB_new(const char *display_name, int w, int h); +extern void X_MB_free(void *xmb_rt); +extern void X_MB_free_keep_win(void *rt); + +extern subject_t *X_MB_kbevents(void *xmb_rt); +extern redraw_man_t *X_MB_rdman(void *xmb_rt); +extern mb_tman_t *X_MB_tman(void *xmb_rt); +extern observer_factory_t *X_MB_observer_factory(void *xmb_rt); +extern mb_img_ldr_t *X_MB_img_ldr(void *xmb_rt); + +#endif
--- a/include/mb_graph_engine.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_graph_engine.h Wed Dec 01 12:25:56 2010 +0800 @@ -10,6 +10,8 @@ * 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_ #define __MBE_H_ #include <mb_config.h>
--- a/include/mb_graph_engine_cairo.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_graph_engine_cairo.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,19 +1,26 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_GE_CAIRO_H_ #define __MB_GE_CAIRO_H_ #include <stdio.h> #include <cairo.h> -#include <cairo-xlib.h> #include "mb_basic_types.h" #include "mb_img_ldr.h" /*! \defgroup mb_ge_cairo MadButterfly Graphic Engine with Cairo * @{ */ +#define MBE_OPERATOR_CLEAR CAIRO_OPERATOR_CLEAR +#define MBE_OPERATOR_SOURCE CAIRO_OPERATOR_SOURCE +#define MBE_STATUS_SUCCESS CAIRO_STATUS_SUCCESS + +#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 #define mbe_image_surface_get_height cairo_image_surface_get_height +#define mbe_directfb_surface_create cairo_directfb_surface_create #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 @@ -32,7 +39,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_scissoring cairo_reset_clip +#define mbe_reset_clip cairo_reset_clip #define mbe_get_target cairo_get_target #define mbe_close_path cairo_close_path #define mbe_text_path cairo_text_path @@ -50,7 +57,7 @@ #define mbe_paint cairo_paint #define mbe_save cairo_save #define mbe_fill cairo_fill -#define mbe_init() +#define mbe_clip cairo_clip typedef cairo_text_extents_t mbe_text_extents_t; typedef cairo_scaled_font_t mbe_scaled_font_t; @@ -82,8 +89,6 @@ 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, @@ -96,7 +101,7 @@ static void mbe_clear(mbe_t *canvas) { cairo_operator_t old_op; - + old_op = cairo_get_operator(canvas); cairo_set_operator(canvas, CAIRO_OPERATOR_CLEAR); cairo_paint(canvas); @@ -107,10 +112,10 @@ cairo_operator_t saved_op; cairo_surface_t *surf; cairo_pattern_t *ptn; - + surf = cairo_get_target(src); ptn = cairo_pattern_create_for_surface(surf); - cairo_set_source(dst, ptn); + cairo_set_source(src, ptn); cairo_pattern_destroy(ptn); saved_op = cairo_get_operator(dst); cairo_set_operator(dst, CAIRO_OPERATOR_SOURCE); @@ -128,16 +133,43 @@ options = cairo_font_options_create(); if(options == NULL) return NULL; - + MB_MATRIX_2_CAIRO(cfnt_mtx, fnt_mtx); MB_MATRIX_2_CAIRO(cctm, ctm); scaled = cairo_scaled_font_create(face, &cfnt_mtx, &cctm, options); cairo_font_options_destroy(options); - + return scaled; } +static mbe_surface_t * +mbe_image_surface_create_for_data(unsigned char *data, + mb_img_fmt_t fmt, + int width, int height, + int stride) { + cairo_format_t _fmt; + + switch(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; + default: + return NULL; + } + return cairo_image_surface_create_for_data(data, _fmt, + width, height, stride); +} + static mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface) { cairo_format_t _fmt; @@ -168,7 +200,7 @@ static mbe_surface_t * mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height) { cairo_format_t _fmt; - + switch(fmt) { case MB_IFMT_ARGB32: _fmt = CAIRO_FORMAT_ARGB32; @@ -185,7 +217,7 @@ default: return NULL; } - + return cairo_image_surface_create(_fmt, width, height); }
--- a/include/mb_graph_engine_skia.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_graph_engine_skia.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_GE_SKIA_H_ #define __MB_GE_SKIA_H_ @@ -8,6 +10,10 @@ /*! \defgroup mb_ge_skia MadButterfly Graphic Engine with Skia * @{ */ +#define MBE_OPERATOR_CLEAR 2 +#define MBE_OPERATOR_SOURCE 1 +#define MBE_STATUS_SUCCESS 0 + struct _mbe_text_extents_t { co_aix x_bearing; co_aix y_bearing; @@ -40,7 +46,6 @@ 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_set_matrix(mbe_pattern_t *ptn, const co_aix matrix[6]); extern void mbe_pattern_destroy(mbe_pattern_t *ptn); @@ -49,6 +54,12 @@ extern int mbe_image_surface_get_height(mbe_surface_t *surface); extern int mbe_image_surface_get_width(mbe_surface_t *surface); extern unsigned char *mbe_image_surface_get_data(mbe_surface_t *surface); +extern mbe_surface_t *mbe_image_surface_create_from_png(const char *filename); +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 mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface); extern mbe_surface_t * mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height); @@ -76,7 +87,7 @@ extern mbe_font_face_t *mbe_get_font_face(mbe_t *canvas); extern void mbe_fill_preserve(mbe_t *canvas); extern void mbe_set_source(mbe_t *canvas, mbe_pattern_t *source); -extern void mbe_reset_scissoring(mbe_t *canvas); +extern void mbe_reset_clip(mbe_t *canvas); extern mbe_surface_t *mbe_get_target(mbe_t *canvas); extern void mbe_close_path(mbe_t *canvas); extern void mbe_text_path(mbe_t *canvas, const char *txt); @@ -97,7 +108,7 @@ extern void mbe_paint(mbe_t *canvas); extern void mbe_save(mbe_t *canvas); extern void mbe_fill(mbe_t *canvas); -extern void mbe_scissoring(mbe_t *canvas, int n_areas, area_t **areas); +extern void mbe_clip(mbe_t *canvas); extern mbe_font_face_t * mbe_query_font_face(const char *family, int slant, int weight); @@ -108,7 +119,6 @@ extern void mbe_transform(mbe_t *mbe, co_aix matrix[6]); extern void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, co_aix angle_start, co_aix angle_stop); -#define mbe_init() /* @} */ #endif /* __MB_GE_SKIA_H_ */
--- a/include/mb_img_ldr.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_img_ldr.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_IMG_LDR_H_ #define __MB_IMG_LDR_H_
--- a/include/mb_obj.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_obj.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MBOBJ_H #define __MBOBJ_H #include "mb_shapes.h"
--- a/include/mb_observer.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_observer.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __OBSERVER_H_ #define __OBSERVER_H_ @@ -8,7 +10,7 @@ typedef struct _subject subject_t; typedef struct _mouse_event mouse_event_t; typedef struct _monitor_event monitor_event_t; -typedef struct _ob_factory ob_factory_t; +typedef struct _observer_factory observer_factory_t; typedef void (*evt_handler)(event_t *event, void *arg); struct _event { @@ -53,7 +55,7 @@ int flags; subject_t *monitor_sub; /*!< \brief Monitor adding/removing * obervers on this subject. */ - ob_factory_t *factory; + observer_factory_t *factory; STAILQ(observer_t) observers; }; /*! \brief Flag that make a subject to stop propagate events to parents. */ @@ -85,13 +87,13 @@ * It provides functions for allocation of subject and observer objects, * and strategy function for getting the subject of parent coord object. */ -struct _ob_factory { - subject_t *(*subject_alloc)(ob_factory_t *factory); - void (*subject_free)(ob_factory_t *factory, subject_t *subject); - observer_t *(*observer_alloc)(ob_factory_t *factory); - void (*observer_free)(ob_factory_t *factory, observer_t *observer); +struct _observer_factory { + subject_t *(*subject_alloc)(observer_factory_t *factory); + void (*subject_free)(observer_factory_t *factory, subject_t *subject); + observer_t *(*observer_alloc)(observer_factory_t *factory); + void (*observer_free)(observer_factory_t *factory, observer_t *observer); /*! This is a strategy function to get subjects of parents. */ - subject_t *(*get_parent_subject)(ob_factory_t *factory, + subject_t *(*get_parent_subject)(observer_factory_t *factory, subject_t *cur_subject); }; @@ -103,7 +105,7 @@ EVT_MOUSE_MOVE_RAW }; -extern subject_t *subject_new(ob_factory_t *factory, +extern subject_t *subject_new(observer_factory_t *factory, void *obj, int obj_type); extern void subject_free(subject_t *subject); extern void subject_notify(subject_t *subject, event_t *evt);
--- a/include/mb_paint.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_paint.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __PAINT_H_ #define __PAINT_H_
--- a/include/mb_prop.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_prop.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_PROP_H_ #define __MB_PROP_H_ @@ -32,6 +34,7 @@ PROP_DUMMY, PROP_MEVT_OB_CNT, PROP_MEVT_OBSERVER, + PROP_JSOBJ, PROP_LAST };
--- a/include/mb_redraw_man.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_redraw_man.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __REDRAW_MAN_H_ #define __REDRAW_MAN_H_ @@ -6,10 +8,15 @@ #include "mb_types.h" #include "mb_observer.h" #include "mb_img_ldr.h" -#include "mb_timer.h" +/*! \defgroup rdman Redraw Manager + * @{ + */ typedef struct _redraw_man redraw_man_t; +/*! \defgroup rdman_private Private Types of Redraw Manager + * @{ + */ typedef void (*free_func_t)(redraw_man_t *rdman, void *obj); struct _free_obj { void *obj; @@ -24,6 +31,7 @@ DARRAY(coords, coord_t *); DARRAY(geos, geo_t *); +/* @} */ /*! \brief Manage redrawing of shapes (graphic elements). * @@ -48,14 +56,18 @@ elmpool_t *geo_pool; elmpool_t *coord_pool; elmpool_t *shnode_pool; + elmpool_t *sh_path_pool; + elmpool_t *sh_rect_pool; elmpool_t *observer_pool; elmpool_t *subject_pool; elmpool_t *paint_color_pool; + elmpool_t *paint_linear_pool; + elmpool_t *paint_radial_pool; + elmpool_t *paint_image_pool; elmpool_t *pent_pool; elmpool_t *coord_canvas_pool; coords_t dirty_coords; - coords_t dirty_pcache_area_coords; geos_t dirty_geos; int n_dirty_areas; /*!< \brief Number of all dirty areas. */ @@ -70,7 +82,7 @@ mbe_t *cr; mbe_t *backend; - ob_factory_t ob_factory; + observer_factory_t observer_factory; subject_t *redraw; /*!< \brief Notified after redrawing. */ subject_t *addrm_monitor; /*!< \brief Monitor adding/removing observers @@ -78,8 +90,8 @@ * \see addrm_monitor_hdlr() */ mb_obj_t *last_mouse_over; - void *rt; /*!< \brief This is a pointer to the current - * graphic backend. + void *rt; /*!< \brief This is a pointer to the current + * graphic backend. * \see rdman_attach_backend() */ mb_prop_store_t props; @@ -100,13 +112,15 @@ extern int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord); /*! \brief Make a shape been managed by a redraw manager. */ -#define rdman_shape_man(rdman, shape) \ +#define rdman_man_shape(rdman, shape) \ do { \ mb_prop_store_init(&((mb_obj_t *)(shape))->props, \ (rdman)->pent_pool); \ STAILQ_INS_TAIL(rdman->shapes, shape_t, sh_next, shape); \ if(rdman->last_mouse_over == (mb_obj_t *)(shape)) \ rdman->last_mouse_over = NULL; \ + mb_prop_store_init(&((mb_obj_t *)(shape))->props, \ + (rdman)->pent_pool); \ } while(0) extern int rdman_shape_free(redraw_man_t *rdman, shape_t *shape); @@ -140,6 +154,10 @@ } \ shnode_free(rdman, __last); \ } while(0) + +/*! \defgroup rdman_paints Paints Supporting of Redraw Manger + * @{ + */ #define _rdman_paint_child(rdman, paint, shape) \ do { \ shnode_t *__node; \ @@ -183,14 +201,23 @@ (shape)->stroke = paint; \ } while(0) extern int rdman_paint_changed(redraw_man_t *rdman, paint_t *paint); +/* @} */ +/*! \defgroup rdman_pos Position/Overlay Detection for Managed Objects + * @{ + */ extern shape_t *find_shape_at_pos(redraw_man_t *rdman, co_aix x, co_aix y, int *in_stroke); extern int mb_obj_pos_is_in(redraw_man_t *rdman, mb_obj_t *obj, co_aix x, co_aix y, int *in_stroke); extern int mb_objs_are_overlay(redraw_man_t *rdman, mb_obj_t *obj1, mb_obj_t *obj2); -#define rdman_get_ob_factory(rdman) (&(rdman)->ob_factory) +/* @} */ + +/*! \defgroup rdman_accessors Accessors of Redraw Manager + * @{ + */ +#define rdman_get_observer_factory(rdman) (&(rdman)->observer_factory) #define rdman_get_redraw_subject(rdman) ((rdman)->redraw) #define rdman_get_root(rdman) ((rdman)->root_coord) #define rdman_get_cr(rdman) ((rdman)->cr) @@ -204,62 +231,24 @@ rdman_get_gen_geos(rdman)->num #define rdman_clear_shape_gl(rdman) \ DARRAY_CLEAN(rdman_get_gen_geos(rdman)) +#define _coord_get_canvas(coord) ((coord)->canvas_info->canvas) +#define _coord_set_canvas(coord, _canvas) \ + do { \ + (coord)->canvas_info->canvas = _canvas; \ + } while(0) #define rdman_prop_store(rdman) ((rdman)->props) #define rdman_img_ldr(rdman) ((rdman)->img_ldr) #define rdman_set_img_ldr(rdman, ldr) \ do { (rdman)->img_ldr = ldr; } while(0) +/* @} */ /*! \brief Attach backend to the redraw manager so that we can hide the backend from the users. * */ #define rdman_attach_backend(rdman,backend) (((rdman)->rt)=(backend)) -/*! \brief Load sprite dymanicly from the shared object module. - * - * The search path can be changed by sprite_set_search_path. The name - * can have a relative path in the front of it. - * This function will search the object in the current working directory - * and then search the system search path. - */ -extern mb_sprite_t *sprite_load(const char *name, redraw_man_t *rdman, - coord_t *root); - -/*! \brief Set the search path of dymanic object loading. - * - */ -extern void sprite_set_search_path(char *path); extern paint_t *rdman_img_ldr_load_paint(redraw_man_t *rdman, const char *img_id); - -typedef void (*mb_eventcb_t )(int fd,void *arg); -#define MONITOR_READ 1 -#define MONITOR_WRITE 2 - -/*! \brief The backend engine mb_backend_t is used to define the interface to realize the MB. - * - * A backend is used to receive events from the system. The MB does not define the backend by itself. - * Instead, it define an interface which allow the lower layer to implement the event system. Each - * backend need to provides the following events. - * - * - keyboard event - * - timer event - * - image loader(?) - * - render manager(?) - */ -typedef struct { - - void *(*init)(char *display,int w,int h); - void (*free)(void *be); - void (*add_event)(void *be,int type, int fd, mb_eventcb_t f,void *arg); - void (*remove_event)(void *be,int type, int fd); - void (*loop)(void *be); - subject_t *(*kbevents)(void *be); - redraw_man_t *(*rdman)(void *be); - mb_tman_t *(*tman)(void *be); - ob_factory_t *(*factory)(void *be); - mb_img_ldr_t *(*loader)(void *be); -} mb_backend_t; - -extern mb_backend_t backend; +/* @} */ #endif /* __REDRAW_MAN_H_ */
--- a/include/mb_shapes.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_shapes.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \file * \brief Declare interfaces of shapes. * @@ -26,7 +28,7 @@ * - mb_obj_init() to initialize shape_t::obj. * - assign *_free() to \ref shape_t::free. * - make new object been managed by a redraw manager. - * - call rdman_shape_man() + * - call rdman_man_shape() * - *_free() * - assigned to \ref shape_t::free. * - *_transform() @@ -34,7 +36,7 @@ * - *_draw() is responsive to define shape. How the shape is filled * or stroked is defined by paint. * - first member variable of a shape type must be a shape_t. - * + * * Must modify * - event.c::draw_shape_path() * - redraw_man.c::clean_shape() @@ -48,14 +50,14 @@ * update geo_t. * * \section rdman_man_shape Make a redraw manager managing a shape. - * + * * It means managing life cycle of a shape to make a redraw manager * managing a shape. Shapes are referenced by a redraw manager to * update output device. So, a redraw manager must make sure all * shapes are valid when they are needed to update output. To make sure * lifecycle of shapes are synchronized with status of a redraw manager, * lifecycle of shapes are managed by associated redraw manager. - * + * */ /*! \defgroup shapes Shapes @@ -85,12 +87,12 @@ co_aix font_size, mbe_font_face_t *face,PangoAttrList *attrs); /*! \brief Change the content of the text element. - * In the SVG, the content of a text tag can be composed of several tspan inside it. The Madbutterfly parser will collect all content of a + * In the SVG, the content of a text tag can be composed of several tspan inside it. The Madbutterfly parser will collect all content of a * text segement as a single string. The attribute of these characters are saved in a seperate data structure. In the program level, we will - * not keep the SVG text tree. Instead, all attributes will be expanded into a list. + * not keep the SVG text tree. Instead, all attributes will be expanded into a list. * - * When you change the content of a text element, please remember that the attributes will not be removed by the way. You need to change - * them seperately. + * When you change the content of a text element, please remember that the attributes will not be removed by the way. You need to change + * them seperately. * */ extern void sh_text_set_text(shape_t *shape, const char *txt); @@ -142,34 +144,34 @@ /*! \brief Change the style of the text. * - * This function can add a couple of attributes to a segment of text or the whole text field. If the @end is -1, the attributes + * This function can add a couple of attributes to a segment of text or the whole text field. If the @end is -1, the attributes * will be applied to the whole text field. The @style should be initialized by using the mb_textstyle_xxx functions. All attributes * which is not initialized will not be changed. It means that the @style will be added into all existing style instead of reaplcing * it. */ extern void sh_text_set_style(shape_t *shape,int begin,int end,mb_textstyle_t *format); /*! \brief Change the color of the text field - * Change the color of the whole text field. This will removed all existing color attribute. If you want to change part of the text + * Change the color of the whole text field. This will removed all existing color attribute. If you want to change part of the text * field only, please use the sh_text_set_style instead. */ extern void sh_text_set_color(shape_t *shape, unsigned color); /*! \brief Turn on/off the bold attribute. - * Turn on/off the font weight of the whole text field. This will removed all existing bold setting. If you want to change part of the text + * Turn on/off the font weight of the whole text field. This will removed all existing bold setting. If you want to change part of the text * field only, please use the sh_text_set_style instead. */ extern void sh_text_set_bold(shape_t *shape, int bold); /*! \brief Turn on/off the italic attribute. - * Turn on/off the italic of the whole text field. This will removed all existing italic setting. If you want to change part of the text + * Turn on/off the italic of the whole text field. This will removed all existing italic setting. If you want to change part of the text * field only, please use the sh_text_set_style instead. */ extern void sh_text_set_italic(shape_t *shape, int italic); /*! \brief Turn on/off the underline attribute. - * Turn on/off the underline of the whole text field. This will removed all existing underline setting. If you want to change part of the text + * Turn on/off the underline of the whole text field. This will removed all existing underline setting. If you want to change part of the text * field only, please use the sh_text_set_style instead. */ extern void sh_text_set_underline(shape_t *shape, int underline); /*! \brief Change the font of the text field. - * Change the font of the whole text field. This will removed all existing underline setting. If you want to change part of the text + * Change the font of the whole text field. This will removed all existing underline setting. If you want to change part of the text * field only, please use the sh_text_set_style instead. */ extern void sh_text_set_font(shape_t *shape, char *family); @@ -195,7 +197,7 @@ return NULL; } extern void mb_textstyle_set_bold(mb_textstyle_t *style, int bold); -static inline int mb_textstyle_get_bold(mb_textstyle_t *style) +static inline int mb_textstyle_get_bold(mb_textstyle_t *style) { return style->property & TEXTSTYLE_BOLD; }
--- a/include/mb_so.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_so.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \file * \brief Define types for sprite shared objects. *
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_sprite.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,69 @@ +#ifndef __MB_SPRITE_H_ +#define __MB_SPRITE_H_ + +#include "mb_types.h" +#include "mb_redraw_man.h" + +/*! \defgroup mb_sprite Implement sprites for animation. + * @{ + */ +/*! \brief A sprite is a set of graphics that being an object in animation. + * + * A sprite include graphics comprise an object. For example, a tank, in + * example tank, is comprised a set of graphics that is represented as a + * sprite. + */ +struct _mb_sprite { + void (*free)(mb_sprite_t *); + mb_obj_t *(*get_obj_with_name)(mb_sprite_t *sprite, const char *id); + /*! Return non-zero for error. */ + int (*goto_scene)(mb_sprite_t *sprite, int scene_no); +}; + +#define MB_SPRITE_FREE(sprite) ((mb_sprite_t *)(sprite))->free(sprite) +#define MB_SPRITE_GET_OBJ(sprite, name) \ + ((mb_sprite_t *)(sprite))->get_obj_with_name((mb_sprite_t *)(sprite), \ + (name)) +#define MB_SPRITE_GOTO_SCENE(sprite, scene_no) \ + ((mb_sprite_t *)(sprite))->goto_scene((mb_sprite_t *)(sprite), scene_no) + + +/*! \brief Load sprite dymanicly from the shared object module. + * + * The search path can be changed by sprite_set_search_path. The name + * can have a relative path in the front of it. + * This function will search the object in the current working directory + * and then search the system search path. + */ +extern mb_sprite_t *sprite_load(const char *name, redraw_man_t *rdman, + coord_t *root); + +/*! \brief Set the search path of dymanic object loading. + * + */ +extern void sprite_set_search_path(const char *path); + +/*! \defgroup mb_sprite_lsym Sprite with linear symbol table. + * @{ + */ +struct _mb_sprite_lsym_entry { + const char *sym; + const int offset; +}; +typedef struct _mb_sprite_lsym_entry mb_sprite_lsym_entry_t; + +/*! \brief A sub-type of mb_sprite_t with linear symbol table. + * + * This type of sprite search symbols with linear/or binary searching. + */ +struct _mb_sprite_lsym { + mb_sprite_t sprite; + int num_entries; + mb_sprite_lsym_entry_t *entries; +}; +typedef struct _mb_sprite_lsym mb_sprite_lsym_t; +/* @} */ +/* @} */ + +#endif /* __MB_SPRITE_H_ */ +
--- a/include/mb_timer.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_timer.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_TIMER_H_ #define __MB_TIMER_H_
--- a/include/mb_tools.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_tools.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __TOOLS_H_ #define __TOOLS_H_
--- a/include/mb_types.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mb_types.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MB_TYPES_H_ #define __MB_TYPES_H_ @@ -8,6 +10,7 @@ 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; @@ -30,9 +33,11 @@ * mb_obj_t should be initialized with mb_obj_init() and destroied with * mb_obj_destroy(). * - * We have defined a set of convienent API which will wrap the coord_t or shape_t API accoridng to its type. - * Please refer to http://www.assembla.com/wiki/show/dFrSMOtDer3BZUab7jnrAJ/MBAF_Object for the details. This - * API is designed for regular programmers which can be used to change some common properties of objects without + * We have defined a set of convienent API which will wrap the coord_t + * or shape_t API accoridng to its type. Please refer to + * http://www.assembla.com/wiki/show/dFrSMOtDer3BZUab7jnrAJ/MBAF_Object + * for the details. This API is designed for regular programmers which + * can be used to change some common properties of objects without * checking its type. */ struct _mb_obj { @@ -79,7 +84,7 @@ struct _paint { int pnt_type; int flags; - void (*prepare)(paint_t *paint, mbe_t *cr); + void (*prepare)(paint_t *paint, mbe_t *cr, shape_t *sh); void (*free)(struct _redraw_man *rdman, paint_t *paint); STAILQ(shnode_t) members; paint_t *pnt_next; /*!< \brief Collect all paints of a rdman. */ @@ -98,6 +103,11 @@ 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 { @@ -118,6 +128,13 @@ #define GEF_FREE 0x4 #define GEF_OV_DRAW 0x8 /*!< To flag drawed for a overlay testing. */ #define GEF_SWAP 0x10 +#define GEF_NOT_SHOWED 0x20 /*!< This geo is not showed. + * + * A geo is not showed if it is hidden + * or one of its ancestors is hidden. + * Redraw manager uses this flag to + * determine who is not showed. + */ extern int areas_are_overlay(area_t *r1, area_t *r2); extern void area_init(area_t *area, int n_pos, co_aix pos[][2]); @@ -160,6 +177,12 @@ * cached. */ area_t *pcache_cur_area; /*!< Current area for parent cached. */ area_t *pcache_last_area; /*!< Last area for parent cached. */ + co_aix cache_2_pdev[6]; /*!< Transfrom matrix from space of + * cached one to its parent. */ + co_aix cache_2_pdev_rev[6]; /*!< Reverse of cache_2_pdev. */ + co_aix aggr_2_pdev[6]; /*!< Aggregation of cache_2_pdev from root */ + co_aix aggr_2_pdev_rev[6]; /*!< Aggregation of cache_2_pdev_rev + * from root */ } coord_canvas_info_t; /*! \brief A coordination system. @@ -214,7 +237,7 @@ #define COF_DIRTY 0x1 #define COF_HIDDEN 0x2 /*!< A coord is hidden. */ #define COF_OWN_CANVAS 0x4 /*!< A coord owns a canvas or inherit it - * from an ancestor. + * from an ancestor. */ #define COF_SKIP_TRIVAL 0x8 /*!< temporary skip descendants * when trivaling. @@ -238,15 +261,19 @@ */ #define COF_TEMP_MARK 0x400 /*!< \brief Temporary mark a coord. */ #define COF_JUST_ZERO 0x800 /*!< \brief The coord is real peformed zeroing. - * + * * It's canvas is changed by zeroing. */ -#define COF_DIRTY_PCACHE_AREA 0x1000 /*!< \brief pcache_area shoud be - * updated. - */ +/*! \brief pcache_area shoud be updated. + * + * A coord is marked with COF_DIRTY_PCACHE_AREA means its pcache_area + * must be re-computed when zeroing. + */ +#define COF_DIRTY_PCACHE_AREA 0x1000 #define COF_SKIP_ZERO 0x2000 /*!< \brief The coord just skip zeroing. * No real zeroing was performed. */ +#define COF_ALWAYS_CACHE 0x4000 /*!< \brief The coord always own a canvas */ /* @} */ extern void matrix_mul(co_aix *m1, co_aix *m2, co_aix *dst); @@ -284,21 +311,9 @@ (co)->flags &= ~COF_CACHE_MASK; \ } while(0) #define coord_is_root(co) ((co)->parent == NULL) -#define coord_is_cached(co) ((co)->flags & COF_OWN_CANVAS) -#define coord_is_fast_cached(co) ((co)->flags & COF_FAST_MASK) -#define coord_is_precise_cached(co) ((co)->flags & COF_PRECISE_MASK) -#define coord_is_zeroing(co) ((co)->flags & COF_MUST_ZEROING) -#define coord_set_zeroing(co) \ - do { (co)->flags |= COF_MUST_ZEROING; } while(0) -#define coord_clear_zeroing(co) \ - do { (co)->flags &= ~COF_MUST_ZEROING; } while(0) -#define coord_set_flags(co, _flags) \ - do { (co)->flags |= (_flags); } while(0) -#define coord_get_parent(co) ((co)->parent) -#define coord_get_flags(co, _flags) ((co)->flags & (_flags)) -#define coord_clear_flags(co, _flags) \ - do { (co)->flags &= ~(_flags); } while(0) #define coord_get_mouse_event(coord) ((coord)->mouse_event) +#define coord_get_opacity(coord) ((coord)->opacity) +#define coord_set_opacity(coord, v) do { (coord)->opacity = v; } while(0) #define coord_get_aggr_matrix(coord) ((coord)->aggr_matrix) #define coord_get_matrix(coord) ((coord)->matrix) #define FOR_COORDS_POSTORDER(coord, cur) \ @@ -333,18 +348,6 @@ sh_get_geo(shape)))) #define coord_get_area(coord) ((coord)->cur_area) #define coord_get_last_area(coord) ((coord)->last_area) -#define coord_get_pcache_area(coord) ((coord)->canvas_info->pcache_cur_area) -#define coord_get_pcache_last_area(coord) \ - ((coord)->canvas_info->pcache_last_area) -#define coord_get_cached(coord) ((coord)->canvas_info->owner) -#define _coord_get_canvas(coord) ((coord)->canvas_info->canvas) -#define _coord_set_canvas(coord, _canvas) \ - do { \ - (coord)->canvas_info->canvas = _canvas; \ - } while(0) -#define _coord_get_dirty_areas(coord) (&(coord)->canvas_info->dirty_areas) -#define _coord_get_aggr_dirty_areas(coord) \ - ((coord)->canvas_info->aggr_dirty_areas) /* @} */ @@ -396,48 +399,4 @@ #define sh_set_stroke_width(sh, v) do { (sh)->stroke_width = (v); } while(0) #define sh_get_stroke_width(sh) (sh)->stroke_width - -/*! \brief A sprite is a set of graphics that being an object in animation. - * - * A sprite include graphics comprise an object. For example, a tank, in - * example tank, is comprised a set of graphics that is represented as a - * sprite. - */ -struct _mb_sprite { - void (*free)(mb_sprite_t *); - mb_obj_t *(*get_obj_with_name)(mb_sprite_t *sprite, const char *id); - /*! Return non-zero for error. */ - int (*goto_scene)(mb_sprite_t *sprite, int scene_no); -}; - -#define MB_SPRITE_FREE(sprite) ((mb_sprite_t *)(sprite))->free(sprite) -#define MB_SPRITE_GET_OBJ(sprite, name) \ - ((mb_sprite_t *)(sprite))->get_obj_with_name((mb_sprite_t *)(sprite), \ - (name)) -#define MB_SPRITE_GOTO_SCENE(sprite, scene_no) \ - ((mb_sprite_t *)(sprite))->goto_scene((mb_sprite_t *)(sprite), scene_no) - - -/*! \defgroup mb_sprite_lsym Sprite with linear symbol table. - * @{ - */ -struct _mb_sprite_lsym_entry { - const char *sym; - const int offset; -}; -typedef struct _mb_sprite_lsym_entry mb_sprite_lsym_entry_t; - -/*! \brief A sub-type of mb_sprite_t with linear symbol table. - * - * This type of sprite search symbols with linear/or binary searching. - */ -struct _mb_sprite_lsym { - mb_sprite_t sprite; - int num_entries; - mb_sprite_lsym_entry_t *entries; -}; -typedef struct _mb_sprite_lsym mb_sprite_lsym_t; - -/* @} */ - #endif /* __MB_TYPES_H_ */
--- a/include/mbbutton.h Mon Jul 19 15:44:49 2010 +0800 +++ b/include/mbbutton.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MBBUTTON_H #define __MBBUTTON_H typedef struct _mb_button {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/INSTALL.txt Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,24 @@ +svg.js: +=============== + +The sample code to load an SVG file. It requires the libxmljs, which is +available at http://github.com/polotek/libxmljs/tree/refactor. Please +copy the libxmljs.node to the objs/default if you want to test the +libxmljs+mbfly without installing them into the system. The path can be +defined by the NODE_PATH environment variable. + +(1) Compile MadButterfly with nodejs support + ~user/MadButterfly$ ./configure --enable-nodejs; make + +(2) Compile libxmljs + ~user/MadButterfly/nodejs$ git clone http://github.com/polotek/libxmljs.git + ~user/MadButterfly/nodejs$ cd libxmljs; make; cd .. + +(3) Copy the libxmljs.node to the nodejs build directory + ~user/MadButterfly/nodejs$ cp libxmljs/libjsxml.node objs/default +(4) Set the path + ~user/MadButterfly/nodejs$ export NODE_PATH=objs/default + +(5) Execute testsvg.js + ~user/MadButterfly/nodejs$ ./run examples/testsvg/testsvg.js +
--- a/nodejs/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -1,5 +1,7 @@ +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 -mbfly_node_SRCS = mbfly_njs.cc X_supp_njs.c coord.cc shapes.cc paints.cc \ +mbfly_node_SRCS = mbfly_njs.cc njs_mb_supp.c coord.cc shapes.cc paints.cc \ font.cc mbfly_node_CFLAGS= -I$(abs_top_builddir)/include \ -I$(abs_top_srcdir)/include \ @@ -7,6 +9,10 @@ @pangocairo_CFLAGS@ $(CFLAGS) mbfly_node_LDFLAGS = -L$(abs_top_builddir)/src/.libs @pangocairo_LIBS@ +if XSHM +mbfly_node_LDFLAGS += -lXext +endif + all: mbfly.node clean: clean-mbfly-node @@ -17,9 +23,10 @@ LDFLAGS="$(mbfly_node_LDFLAGS)" \ TOP_BUILDDIR="$(abs_top_builddir)" \ WAFLOCK=$(abs_builddir)/objs/.lock-wscript \ - $(NODE_WAF) configure build --blddir=$(abs_builddir)/objs + $(NODE_WAF) configure build --srcdir=$(abs_srcdir) \ + --blddir=$(abs_builddir)/objs clean-mbfly-node: - cd $(srcdir); \ - WAFLOCK=$(abs_builddir)/.lock-wscript \ + -cd $(srcdir); \ + WAFLOCK=$(abs_builddir)/objs/.lock-wscript \ $(NODE_WAF) clean
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/README.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,11 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +/*! \defgroup xnjsmb MadButterfly JS binding for V8 and nodejs + * + * This implementation of JS binding heavily relies on + * tools/gen_v8_binding.m4, a set of m4 macros. We defines binding in + * nodejs/*.m4 files and generate respective code, nodejs/*-inc.h, + * with macros defined in tools/gen_v8_binding.m4. *-inc.h files are + * included by respective *.cc files they implement functions needed + * by generated code. + */
--- a/nodejs/X_supp_njs.c Mon Jul 19 15:44:49 2010 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -/*! \brief Implement X11 backend for nodejs plugin. - * - * Since nodejs use libev to handle event loops, part of X11 backend - * code can not be used directly. The part of code should be rewrote. - * The part is about - */ -#include <stdio.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <ev.h> -#include "mb_X_supp.h" -#include "mb_tools.h" -#include "X_supp_njs.h" - -#ifndef ASSERT -#define ASSERT(x) -#endif - -static void timer_cb(EV_P_ ev_timer *tmwatcher, int revent); - -/*! \brief Register next timeout with libev. - */ -static void -set_next_timeout(njs_runtime_t *rt) { - mb_tman_t *tman; - mb_timeval_t now, tmo; - ev_tstamp tout; - int r; - - tman = X_MB_tman(rt->xrt); - get_now(&now); - r = mb_tman_next_timeout(tman, &now, &tmo); - if(r == 0) { - MB_TIMEVAL_DIFF(&tmo, &now); - tout = (ev_tstamp)MB_TIMEVAL_SEC(&tmo) + - (ev_tstamp)MB_TIMEVAL_USEC(&tmo) / 1000000; - ev_timer_init(&rt->tmwatcher, timer_cb, tout, 0); - ev_timer_start(&rt->tmwatcher); - rt->enable_timer = 1; - } else - rt->enable_timer = 0; -} - -static void -x_conn_cb(EV_P_ ev_io *iowatcher, int revent) { - njs_runtime_t *rt = MEM2OBJ(iowatcher, njs_runtime_t, iowatcher); - redraw_man_t *rdman; - extern void _X_MB_handle_x_event_for_nodejs(void *rt); - - rdman = X_MB_rdman(rt->xrt); - _X_MB_handle_x_event_for_nodejs(rt->xrt); - rdman_redraw_changed(rdman); - - if(rt->enable_timer == 0) /* no installed timeout */ - set_next_timeout(rt); -} - -static void -timer_cb(EV_P_ ev_timer *tmwatcher, int revent) { - njs_runtime_t *rt = MEM2OBJ(tmwatcher, njs_runtime_t, tmwatcher); - mb_tman_t *tman; - redraw_man_t *rdman; - mb_timeval_t now; - extern int _X_MB_flush_x_conn_for_nodejs(void *rt); - - tman = X_MB_tman(rt->xrt); - get_now(&now); - mb_tman_handle_timeout(tman, &now); - - rdman = X_MB_rdman(rt->xrt); - rdman_redraw_changed(rdman); - _X_MB_flush_x_conn_for_nodejs(rt->xrt); - - set_next_timeout(rt); -} - -/*! \brief Handle connection coming data and timeout of timers. - * - * \param rt is a runtime object for X. - */ -void -X_njs_MB_init_handle_connection(njs_runtime_t *rt) { - void *xrt = rt->xrt; - mb_tman_t *tman; - mb_timeval_t now, tmo; - ev_tstamp tout; - int fd; - int r; - extern int _X_MB_get_x_conn_for_nodejs(void *rt); - - /* - * Setup watcher for X connection. - */ - fd = _X_MB_get_x_conn_for_nodejs(xrt); - ev_io_init(&rt->iowatcher, x_conn_cb, fd, EV_READ); - ev_io_start(&rt->iowatcher); - rt->enable_io = 1; - - set_next_timeout(rt); -} - -/*! \brief Free njs_runtime_t. - */ -void -X_njs_MB_free(njs_runtime_t *rt) { - /* - * stop IO and timer watcher - */ - if(rt->enable_io) - ev_io_stop(&rt->iowatcher); - if(rt->enable_timer) - ev_timer_stop(&rt->tmwatcher); - - X_MB_free(rt->xrt); - free(rt); -} - -int -X_njs_MB_flush(njs_runtime_t *rt) { - void *xrt = rt->xrt; - int r; - extern int _X_MB_flush_x_conn_for_nodejs(void *rt); - - _X_MB_flush_x_conn_for_nodejs(xrt); - - return r; -} - -njs_runtime_t * -X_njs_MB_new(char *display_name, int w, int h) { - njs_runtime_t *rt; - void *xrt; - - rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); - ASSERT(rt != NULL); - - xrt = X_MB_new(display_name, w, h); - - rt->xrt = xrt; - rt->enable_io = 0; - rt->enable_timer = 0; /* no timer, now */ - - return rt; -} - -/*! \brief Get X runtime that is backend of this njs runtime. - */ -void * -_X_njs_MB_get_X_runtime(njs_runtime_t *rt) { - return rt->xrt; -}
--- a/nodejs/X_supp_njs.h Mon Jul 19 15:44:49 2010 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -#ifndef __X_SUPP_NJS_H_ -#define __X_SUPP_NJS_H_ - -#include <ev.h> - -typedef struct _njs_runtime { - ev_io iowatcher; - ev_timer tmwatcher; - int enable_io; - int enable_timer; - void *xrt; -} njs_runtime_t; - -extern void X_njs_MB_init_handle_connection(njs_runtime_t *rt); -extern void X_njs_MB_free(njs_runtime_t *rt); -extern njs_runtime_t *X_njs_MB_new(char *display_name, int w, int h); -extern int X_njs_MB_flush(njs_runtime_t *rt); -extern void *_X_njs_MB_get_X_runtime(njs_runtime_t *rt); - -#define X_njs_MB_kbevents(rt) X_MB_kbevents((rt)->xrt) -#define X_njs_MB_rdman(rt) X_MB_rdman((rt)->xrt) -#define X_njs_MB_tman(rt) X_MB_tman((rt)->xrt) -#define X_njs_MB_ob_factory(rt) X_MB_ob_factory((rt)->xrt) -#define X_njs_MB_img_ldr(rt) X_MB_img_ldr((rt)->xrt) - -#endif /* __X_SUPP_NJS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/animate.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,358 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var sys=require("sys"); + +/* + * This is configuration for animate module. For slower or speeder + * machines, ffs can be decreased or increased respective. + */ +var ffs = 12; +var frame_interval = 1000 / ffs; + +function shift_draw(percent) { + var x, y; + + x = (this.targetx - this.startposx) * percent + this.startposx; + y = (this.targety - this.startposy) * percent + this.startposy; + this.obj.center.move(x, y); + this._app.refresh(); +} + +function shift(app,obj,shiftx,shifty) { + obj.animated_shift = this; + this._app = app; + this.obj = obj; + this.end = 0; + this.targetx = shiftx + obj.center.x; + this.targety = shifty + obj.center.y; + this.startposx = obj.center.x; + this.startposy = obj.center.y; +} + +exports.shift = shift; +shift.prototype.draw = shift_draw; + +/* ------------------------------------------------------------ */ +function rotate(app, obj, ang, duration) { + this._app = app; + this._obj = obj; + this._ang = ang; + this._start_mtx = [obj[0], obj[1], obj[2], obj[3], obj[4], obj[5]]; +} + +function rotate_draw(percent) { + var percent; + var ang; + var sv, cv; + var obj = this._obj; + var mtx, shift; + + + ang = percent * this._ang; + sv = Math.sin(ang); + cv = Math.cos(ang); + mtx = [cv, -sv, 0, sv, cv, 0]; + shift = [1, 0, -obj.center.x, 0, 1, -obj.center.y]; + mtx = multiply(mtx, shift); + shift = [1, 0, obj.center.x, 0, 1, obj.center.y]; + mtx = multiply(shift, mtx); + mtx = multiply(mtx, this._start_mtx); + + obj[0] = mtx[0]; + obj[1] = mtx[1]; + obj[2] = mtx[2]; + obj[3] = mtx[3]; + obj[4] = mtx[4]; + obj[5] = mtx[5]; + + this._app.refresh(); +} + +rotate.prototype.draw = rotate_draw; +exports.rotate = rotate; + +function multiply(s,d) { + var m=[]; + m[0] = s[0]*d[0]+s[1]*d[3]; + m[1] = s[0]*d[1]+s[1]*d[4]; + m[2] = s[0]*d[2]+s[1]*d[5]+s[2]; + m[3] = s[3]*d[0]+s[4]*d[3]; + m[4] = s[3]*d[1]+s[4]*d[4]; + m[5] = s[3]*d[2]+s[4]*d[5]+s[5]; + return m; +} + + +function scale_draw(percent) { + if (this.end==1) { + percent = 1; + } + var sx = 1 + (this.totalsx - 1) * percent; + var sy = 1 + (this.totalsy - 1) * percent; + var sh1 = [1, 0, -this.center_x, 0, 1, -this.center_y]; + var sh2 = [1, 0, this.center_x, 0, 1, this.center_y]; + sys.puts("sc="+sx+" sy="+sy); + var scale = [sx, 0, 0, 0, sy, 0]; + var obj = this.obj; + var mtx; + + mtx = multiply(scale, sh1); + mtx = multiply(sh2, mtx); + mtx = multiply(this.orig_mtx, mtx); + obj[0] = mtx[0]; + obj[1] = mtx[1]; + obj[2] = mtx[2]; + obj[3] = mtx[3]; + obj[4] = mtx[4]; + obj[5] = mtx[5]; + + this.app.refresh(); +} + +function scale(app, obj, fact_x, fact_y, duration) { + var bbox; + + try { + if (obj.animated_scale) { + obj.animated_scale.end = 1; + } + } catch(e) { + + } + + bbox = obj.bbox; + bbox.update(); + obj.animated_scale = this; + this.app = app; + this.obj = obj; + this.end = 0; + this.starttime = Date.now(); + this.totalsx = fact_x * bbox.orig.width / bbox.width; + this.totalsy = fact_y * bbox.orig.height / bbox.height; + this.duration = duration*1000; + this.center_x = obj.center.rel.x; + this.center_y = obj.center.rel.y; + this.orig_mtx = [obj[0], obj[1], obj[2], obj[3], obj[4], obj[5]]; +} + + +exports.scale = scale; +scale.prototype.draw = scale_draw; + +function holder(app, coord) { + var mtx = [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]; + + this._mtx = mtx; + this._coord = coord; + this._app = app; +} + +holder.prototype = { + go: function(pos) { + var sx, sy; + + sx = pos.x - this._coord.center.x; + sy = pos.y - this._coord.center.y; + this.shift(sx, sy); + }, + + go_center: function(o) { + this.go(o.center); + }, + + home: function() { + this._coord[2] = this._mtx[2]; + this._coord[5] = this._mtx[5]; + this._app.refresh(); + }, + + shift: function(sx, sy) { + this._coord[2] = this._mtx[2] + sx; + this._coord[5] = this._mtx[5] + sy; + this._app.refresh(); + } +}; + +exports.holder = holder; + + + +function alpha_draw(percent) { + + if (this.end == 1) return; + var sx = (this.targetalpha-this.startalpha)*percent+this.startalpha; + this.obj.opacity=sx; + this.app.refresh(); + this.obj.animated_alpha = null; +} + +function alpha(app,obj,alpha, duration) { + try { + if (obj.animated_alpha) { + obj.animated_alpha.end = 1; + } + } catch(e) { + + } + obj.animated_alpha = this; + this.app = app; + this.obj = obj; + this.end = 0; + this.starttime = Date.now(); + this.startalpha = obj.opacity; + this.targetalpha = alpha; + this.duration = duration*1000; +} + +alpha.prototype.draw = alpha_draw; +exports.alpha = alpha; + +function linear_update() +{ + var now = Date.now(); + var i; + + if (now >= this.end) { + this.timer.stop(); + now = this.end; + if (this.callback_end) { + this.callback_end(); + this.callback_end=null; + } + } + if (now < this.startmove) return; + var per = (now-this.startmove)/this.duration/1000; + if (per > 1) per = 1; + this.action.draw(per); +} + +function linear_start() +{ + var self = this; + if (this.timer) + this.timer.stop(); + this.timer = setInterval(function() { self.update();}, frame_interval); + this.startmove = Date.now()+this.starttime*1000; + this.end = this.startmove+this.duration*1000; +} +function linear_stop() +{ + if (this.timer) { + this.timer.stop(); + this.timer = null; + } +} + +function linear_finish() +{ + this.action.draw(1); + if (this.callback_end) { + this.callback_end(); + this.callback_end=null; + } +} +function linear(action,start, duration) +{ + this.action = action; + this.duration = duration; + this.starttime = start; + this.callback_end = null; + this.timer=null; +} + +function linear_callback(cb) +{ + this.callback_end = cb; +} + +linear.prototype.update = linear_update; +linear.prototype.start = linear_start; +linear.prototype.stop = linear_stop; +linear.prototype.finish = linear_finish; +linear.prototype.callbackAtEnd = linear_callback; +exports.linear = linear; + + +function multilinear_update() +{ +} + +function multilinear_start() +{ +} + +function multilinear_stop() +{ +} + +function multilinear_finish() +{ +} +function multilinear(action,start,stages) { + sys.puts("Multilinear word is not implemented yet"); +} + +exports.multilinear = multilinear; +multilinear.prototype.update = multilinear_update; +multilinear.prototype.start = multilinear_start; +multilinear.prototype.stop = multilinear_stop; +multilinear.prototype.finish = multilinear_finish; +function exponential_update() +{ +} +function exponential_start() +{ +} +function exponential_stop() +{ +} +function exponential_finish() +{ +} +function exponential(action,start,stages) { + sys.puts("exponential word is not implemented yet"); +} + +exports.exponential = exponential; +exponential.prototype.update = exponential_update; +exponential.prototype.start = exponential_start; +exponential.prototype.stop = exponential_stop; +exponential.prototype.finish = exponential_finish; + +function program(words) +{ + this.words = wrods; +} + +program.prototype.start=function() { + for(w in this.words) { + w.start(); + } +} + +program.prototype.step=function(s) { + sys.puts("This function is not implemented yet"); +} +program.prototype.stop=function() { + for(w in this.words) { + w.stop(); + } +} +program.prototype.finish=function() { + for(w in this.words) { + w.finish(); + } +} + +exports.run = function(actions,start,duration,cb) { + var li; + for(a in actions) { + li = new linear(actions[a],start,duration); + li.start(); + } + li.callbackAtEnd(cb); +} +exports.runexp=function(actions,start,exp) { + sys.puts("This function is not implemented yet"); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/canvas.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,109 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var mbfly = require("mbfly"); +var sys=require("sys"); + + +function canvas(app,root) { + this.mb_rt = app.mb_rt; + this.parent = root; + this.root = this.mb_rt.coord_new(root); + this.bg_r = 0; + this.bg_g = 0; + this.bg_b = 0; + this.bg_a = 0; + this.stroke_r = 0; + this.stroke_g = 0; + this.stroke_b = 0; + this.stroke_a = 0; + this.stroke_w = 1; +} + +canvas.prototype.background=function(r,g,b,a) { + this.bg_r = r; + this.bg_g = g; + this.bg_b = b; + this.bg_a = a; +} + +canvas.prototype.rect=function(x,y,w,h) { + var rect = this.mb_rt.rect_new(x,y,w,h,0,0); + var paint = this.mb_rt.paint_color_new(this.bg_r,this.bg_g,this.bg_b,this.bg_a); + paint.fill(rect); + this.root.add_shape(rect); +} + +canvas.prototype.stroke=function(r,g,b,a) { + this.stroke_r = r; + this.stroke_g = g; + this.stroke_b = b; + this.stroke_a = a; +} + + +canvas.prototype.line=function(x1,y1,x2,y2) { + var s = "M "+x1+","+y1+" L "+x2+","+y2; + //sys.puts(s); + + var p = this.mb_rt.path_new(s); + this.root.add_shape(p); + var paint = this.mb_rt.paint_color_new(this.stroke_r,this.stroke_g,this.stroke_b,this.stroke_a); + paint.stroke(p); + p.stroke_width = this.stroke_w; +} + +canvas.prototype.strokeWeight=function(w) { + this.stroke_w = w; +} + +canvas.prototype.alpha=function(c) { +} + +canvas.prototype.red=function(c) { +} +canvas.prototype.green=function(c) { +} +canvas.prototype.blue=function(c) { +} + + +canvas.prototype.clear=function() { + this.root.remove(); + this.root = this.mb_rt.coord_new(this.parent); +} + +canvas.prototype.arc=function(x,y,w,h,start,end) { +} + +canvas.prototype.ellipse=function(x, y, width, height) { +} + +canvas.prototype.point=function(x,y) { +} + +canvas.prototype.quad=function(x1,y1,x2,y2,x3,y3,x4,y4) { +} + +canvas.prototype.triangle=function(x1,y1,x2,y2,x3,y3) { +} + +canvas.prototype.bezier=function(x1, y1, cx1, cy1, cx2, cy2, x2, y2) { +} + +canvas.prototype.curveTightness=function(squishy) { +} + +canvas.prototype.colorMode=function() { +} + +canvas.prototype.fill=function(color) { +} + +canvas.prototype.noFill=function() { +} + +canvas.prototype.noStroke=function() { +} + + +exports.canvas = canvas;
--- a/nodejs/coord.cc Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/coord.cc Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <v8.h> @@ -5,7 +7,7 @@ #include "mb.h" #include "mb_X_supp.h" #include "mb_tools.h" -#include "X_supp_njs.h" +#include "njs_mb_supp.h" } #include "mbfly_njs.h" @@ -14,163 +16,346 @@ #define ASSERT(x) #endif +#define OK 0 + +/*! \page jsgc How to Manage Life-cycle of Objects for Javascript. + * + * The life-cycle of MadButterfly ojects are simple. A object is live + * when it is created and dead when it is free. When a coord or shape + * is free, it is also removed from the tree. There is not way to + * remove a coord or a shape without freeing it. So, if you want to + * remove a coord or a shape object from the tree, you can only free + * it. + * + * Javascript, in conventional, does not free an object. It has GC, + * the engine, being used, will free an object if it is no more + * referenced. So, we had better provide a removing function, but + * actually free an object. In idea situation, a new MB object would + * be created for and attached on the JS object, when an object added + * back to the tree. But, it means we need to keep states of an + * object and create a new one with the same states later. It is + * complicated. So, once an object is removed, it is invalidated. + * + * I hope someone would implement a higher abstract layer, in JS, to + * implement the idea model that recreate a new object when an + * invalidated JS object being added back. + * + * An invalid object is the one with NULL internal field and obj.valid + * == false. The binding of MadButterfly hold a reference to every + * object added to the tree of a mbrt (runtime object), and remove the + * reference and invalidate it when it being removed. + * + * For coords, they are always attached to the tree when it is valid. + * So, binding hold a persistent reference to it. The reference is + * purged when a coord being removed from the tree and being + * invalidated. + * + * For any shape, it is not attached to the tree at begining, but is + * attached to a tree laterly, or is collected by GC. The binding + * hold a weak reference for a new shape, and upgrade to a strong + * reference when the shape being added to the tree. + */ + using namespace v8; -static Handle<Value> -xnjsmb_coord_get_index(uint32_t index, const AccessorInfo &info) { - HandleScope scope; - Handle<Object> self; - coord_t *coord; - co_aix v; +/*! \defgroup xnjsmb_coord JS binding for coord objects. + * \ingroup xnjsmb + * + * @{ + */ +/*! \brief Invalidate JS objects for coords and shapes in a subtree. + * + * \param self is the object of the root of subtree. + * + * \sa \ref jsgc + */ +static void +xnjsmb_coord_invalidate_subtree(coord_t *coord) { + Persistent<Object> *child_hdl; + Persistent<Object> *mem_hdl; + coord_t *child; + shape_t *mem; + Handle<Value> _false = Boolean::New(0); - if(index < 0 || index >= 6) - THROW("Invalid index"); - - self = info.This(); - coord = (coord_t *)UNWRAP(self); - v = coord_get_matrix(coord)[index]; + /* Invalidate all coords in the subtree */ + FOR_COORDS_PREORDER(coord, child) { + child_hdl = (Persistent<Object> *)mb_prop_get(&child->obj.props, + PROP_JSOBJ); + SET(*child_hdl, "valid", _false); + WRAP(*child_hdl, NULL); + child_hdl->Dispose(); + delete child_hdl; - return Number::New(v); + /* Invalidate members of a coord */ + FOR_COORD_SHAPES(child, mem) { + mem_hdl = (Persistent<Object> *)mb_prop_get(&mem->obj.props, + PROP_JSOBJ); + SET(*mem_hdl, "valid", _false); + WRAP(*mem_hdl, NULL); + mem_hdl->Dispose(); + delete mem_hdl; + } + } } -static Handle<Value> -xnjsmb_coord_set_index(uint32_t index, Local<Value> value, - const AccessorInfo &info) { - - HandleScope scope; - Handle<Object> self; +/*! \brief Free C objects for coords and shapes in a subtree. + * + * \param self is the object of the root of subtree. + * + * \sa \ref jsgc + */ +static void +xnjsmb_coord_free_subtree(redraw_man_t *rdman, coord_t *coord) { + coord_t *child, *last_child; + shape_t *mem, *last_mem; + int r; + + rdman_coord_changed(rdman, coord); + + last_child = NULL; + FOR_COORDS_POSTORDER(coord, child) { + if(last_child != NULL) { + r = rdman_coord_free(rdman, last_child); + if(r != OK) + THROW_noret("Unknown error"); + } + + /* Free members of a coord */ + last_mem = NULL; + FOR_COORD_SHAPES(child, mem) { + if(last_mem != NULL) { + r = rdman_shape_free(rdman, last_mem); + if(r != OK) + THROW_noret("Unknown error"); + } + + last_mem = mem; + } + if(last_mem != NULL) { + r = rdman_shape_free(rdman, last_mem); + if(r != OK) + THROW_noret("Unknown error"); + } + + last_child = child; + } + if(last_child != NULL) { + r = rdman_coord_free(rdman, last_child); + if(r != OK) + THROW_noret("Unknown error"); + } +} + +static void +xnjsmb_coord_mod(Handle<Object> self, coord_t *coord) { + Persistent<Object> *self_hdl; + subject_t *subject; + Handle<Value> subject_o; + + /* Keep associated js object in property store for retrieving, + * later, without create new js object. + */ + self_hdl = new Persistent<Object>(); + *self_hdl = Persistent<Object>::New(self); + mb_prop_set(&coord->obj.props, PROP_JSOBJ, self_hdl); + + subject = coord->mouse_event; + subject_o = export_xnjsmb_auto_subject_new(subject); + SET(self, "mouse_event", subject_o); + SET(self, "valid", Boolean::New(1)); +} + +static float +coord_get_index(coord_t *coord, Handle<Object> self, int idx, + const char **err) { + if(idx < 0 || idx >= 6) { + *err = "Invalid index: out of range"; + return 0; + } + + return coord_get_matrix(coord)[idx]; +} + +static float +coord_set_index(coord_t *coord, Handle<Object> self, + int idx, float v, const char **err) { Handle<Object> js_rt; redraw_man_t *rdman; - coord_t *coord; - co_aix v; - if(index < 0 || index >= 6) - THROW("Invalid Index"); - if(!value->IsNumber()) - THROW("Invalid value"); + if(idx < 0 || idx >= 6) { + *err = "Invalid index: out of range"; + return 0; + } - self = info.This(); - coord = (coord_t *)UNWRAP(self); - v = value->NumberValue(); - coord_get_matrix(coord)[index] = v; + coord_get_matrix(coord)[idx] = v; js_rt = GET(self, "mbrt")->ToObject(); rdman = xnjsmb_rt_rdman(js_rt); rdman_coord_changed(rdman, coord); - return value; + return v; } -/*! \brief Callback functio to add a shape to a coord in Javascript. - * - * coord.add_shape(shape) - */ -static Handle<Value> -xnjsmb_coord_add_shape(const Arguments &args) { - int argc = args.Length(); - Handle<Object> self = args.This(); - Handle<Object> shape_obj; - Handle<Object> rt_obj; - Handle<Value> rt_val; +static void +xnjsmb_coord_add_shape(coord_t *coord, Handle<Object> self, + shape_t *shape, const char **err) { + Handle<Object> js_rt; + Persistent<Object> *shape_hdl; redraw_man_t *rdman; - coord_t *coord; - shape_t *sh; int r; - if(argc != 1) - THROW("Invalid number of arguments (!= 1)"); - - shape_obj = args[0]->ToObject(); - sh = (shape_t *)UNWRAP(shape_obj); - ASSERT(sh != NULL); - - coord = (coord_t *)UNWRAP(self); - ASSERT(coord != NULL); + js_rt = GET(self, "mbrt")->ToObject(); + rdman = xnjsmb_rt_rdman(js_rt); + r = rdman_add_shape(rdman, shape, coord); + if(r != 0) + *err = "Unknown error"; + + /* see \ref jsgc */ + shape_hdl = (Persistent<Object> *)mb_prop_get(&shape->obj.props, + PROP_JSOBJ); + shape_hdl->ClearWeak(); + rdman_shape_changed(rdman, shape); +} - rt_val = GET(self, "mbrt"); - rt_obj = rt_val->ToObject(); - rdman = xnjsmb_rt_rdman(rt_obj); - - r = rdman_add_shape(rdman, sh, coord); - if(r != 0) - THROW("Unknown error"); +static void +xnjsmb_coord_remove(coord_t *coord, Handle<Object> self) { + Handle<Object> js_rt; + redraw_man_t *rdman; - return Null(); + if(!GET(self, "valid")->ToBoolean()->Value()) /* Invalidated object */ + THROW_noret("Invalid object"); + + js_rt = GET(self, "mbrt")->ToObject(); + rdman = xnjsmb_rt_rdman(js_rt); + + xnjsmb_coord_invalidate_subtree(coord); + xnjsmb_coord_free_subtree(rdman, coord); } -static Persistent<ObjectTemplate> coord_obj_temp; +static void +xnjsmb_coord_show(coord_t *coord, Handle<Object> self) { + Handle<Object> js_rt; + redraw_man_t *rdman; + + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + + coord_show(coord); + rdman_coord_changed(rdman, coord); +} static void -xnjsmb_init_temp(void) { - Handle<FunctionTemplate> add_shape_temp; +xnjsmb_coord_hide(coord_t *coord, Handle<Object> self) { + Handle<Object> js_rt; + redraw_man_t *rdman; + + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + + coord_hide(coord); + rdman_coord_changed(rdman, coord); +} + +static void +xnjsmb_coord_set_opacity(Handle<Object> self, coord_t *coord, Handle<Value> value, const char **str) +{ + Handle<Object> js_rt; + redraw_man_t *rdman; - coord_obj_temp = Persistent<ObjectTemplate>::New(ObjectTemplate::New()); - coord_obj_temp->SetIndexedPropertyHandler(xnjsmb_coord_get_index, - xnjsmb_coord_set_index); - coord_obj_temp->SetInternalFieldCount(1); + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); - add_shape_temp = FunctionTemplate::New(xnjsmb_coord_add_shape); - SET(coord_obj_temp, "add_shape", add_shape_temp); + + coord_set_opacity(coord, value->NumberValue()); + rdman_coord_changed(rdman, coord); } -/*! \brief Create and initialize a Javascript object for a coord. - */ -static Handle<Object> -xnjsmb_coord_new_jsobj(coord_t *coord, Handle<Object> parent_obj, - Handle<Object> js_rt) { - Handle<Object> coord_obj; - static int init_temp = 0; - - if(!init_temp) { - xnjsmb_init_temp(); - init_temp = 1; - } +static Handle<Value> +xnjsmb_coord_get_opacity(Handle<Object> self, coord_t *coord, + const char **err) { + float opacity; + + opacity = coord_get_opacity(coord); + return Number::New(opacity); +} - coord_obj = coord_obj_temp->NewInstance(); - ASSERT(coord_obj != NULL); - WRAP(coord_obj, coord); +#define cc(i) (coord_get_matrix(coord)[i]) +static void +xnjsmb_coord_set_y(Handle<Object> self, coord_t *coord, Handle<Value> value, const char **str) +{ + Handle<Object> js_rt; + redraw_man_t *rdman; + co_aix y,ty; + co_aix xx,yy; - if(!parent_obj.IsEmpty()) - SET(coord_obj, "parent", parent_obj); - SET(coord_obj, "mbrt", js_rt); + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + - return coord_obj; + ty = value->NumberValue(); + xx = GET(self,"_x")->ToNumber()->NumberValue(); + yy = GET(self,"_y")->ToNumber()->NumberValue(); + y = ty-cc(3)*xx-cc(4)*yy; + coord_get_matrix(coord)[5] = y; + rdman_coord_changed(rdman, coord); } -/*! \brief Create a coord object associated with the rdman of the runtime. - * - * Two internal fields, coord and rdman. - */ -Handle<Value> -xnjsmb_coord_new(const Arguments &args) { - HandleScope scope; - Handle<Object> js_rt; - Handle<Object> coord_obj, parent_obj; - njs_runtime_t *rt; - redraw_man_t *rdman; - coord_t *coord, *parent = NULL; - int argc; +static Handle<Value> +xnjsmb_coord_get_y(Handle<Object> self, coord_t *coord, + const char **err) { + co_aix y; + co_aix xx,yy; + + xx = GET(self,"_x")->ToNumber()->NumberValue(); + yy = GET(self,"_y")->ToNumber()->NumberValue(); - argc = args.Length(); - if(argc > 1) - THROW("Too many arguments (> 1)"); - - js_rt = args.This(); - rt = (njs_runtime_t *)UNWRAP(js_rt); - rdman = X_njs_MB_rdman(rt); + y = cc(3)*xx+cc(4)*yy+cc(5); + return Number::New(y); +} +static void +xnjsmb_coord_set_x(Handle<Object> self, coord_t *coord, Handle<Value> value, const char **str) +{ + Handle<Object> js_rt; + redraw_man_t *rdman; + co_aix x,tx; + co_aix xx,yy; + + xx = GET(self,"_x")->ToNumber()->NumberValue(); + yy = GET(self,"_y")->ToNumber()->NumberValue(); + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + + tx = value->NumberValue(); + x = tx-cc(0)*xx-cc(1)*yy; + coord_get_matrix(coord)[2] = x; + rdman_coord_changed(rdman, coord); +} - if(argc == 1) { - parent_obj = args[0]->ToObject(); - parent = (coord_t *)UNWRAP(parent_obj); - } +static Handle<Value> +xnjsmb_coord_get_x(Handle<Object> self, coord_t *coord, + const char **err) { + co_aix x; + co_aix xx,yy; - coord = rdman_coord_new(rdman, parent); - ASSERT(coord != NULL); - coord_obj = xnjsmb_coord_new_jsobj(coord, parent_obj, js_rt); + xx = GET(self,"_x")->ToNumber()->NumberValue(); + yy = GET(self,"_y")->ToNumber()->NumberValue(); - scope.Close(coord_obj); - - return coord_obj; + x = cc(0)*xx+cc(1)*yy+cc(2); + return Number::New(x); +} +#undef m + +#include "coord-inc.h" + +/*! \brief This function used by \ref xnjsmb_mb_rt to wrap coord object. + */ +Handle<Value> export_xnjsmb_auto_coord_new(coord_t *coord) { + return xnjsmb_auto_coord_new(coord); } /*! \brief Initialize Javascript object for root coord of a runtime. @@ -185,10 +370,19 @@ redraw_man_t *rdman; coord_t *root; Handle<Object> obj; - + static int init_flag = 0; + + if(!init_flag) { + xnjsmb_auto_coord_init(); + init_flag = 1; + } + rdman = xnjsmb_rt_rdman(js_rt); root = rdman_get_root(rdman); - obj = xnjsmb_coord_new_jsobj(root, Handle<Object>(NULL), js_rt); + obj = xnjsmb_auto_coord_new(root).As<Object>(); + SET(obj, "mbrt", js_rt); SET(js_rt, "root", obj); } + +/* @} */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/coord.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,15 @@ +define([PROJ_PREFIX], [xnjsmb_auto_])dnl +STRUCT([coord], [coord_t], + [ + ACCESSOR([opacity], [xnjsmb_coord_get_opacity],[xnjsmb_coord_set_opacity]), + ACCESSOR([x], [xnjsmb_coord_get_x],[xnjsmb_coord_set_x]), + ACCESSOR([y], [xnjsmb_coord_get_y],[xnjsmb_coord_set_y]), + ], + [METHOD([add_shape], [xnjsmb_coord_add_shape], + (SELF, OBJ([shape], [shape], [shape_t]), ERR), 1, []), + METHOD([remove], [xnjsmb_coord_remove], (SELF), 0, []), + METHOD([show], [xnjsmb_coord_show], (SELF), 0, []), + METHOD([hide], [xnjsmb_coord_hide], (SELF), 0, [])], + ((GET_INDEX, (coord_get_index, NUMBER)), + (SET_INDEX, (coord_set_index, NUMBER)), + ([STMOD], [xnjsmb_coord_mod])))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/desktop/desktop.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,507 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448" + height="480" + id="svg2" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="desktop.svg"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 240 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 240 : 1" + inkscape:persp3d-origin="372.04724 : 160 : 1" + id="perspective21" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3706"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3708" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3710" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3706" + id="linearGradient3712" + x1="0" + y1="240" + x2="747.27411" + y2="240" + gradientUnits="userSpaceOnUse" /> + <inkscape:perspective + id="perspective3711" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2953" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2981" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3009" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3037" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3065" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3093" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2960" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2988" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-0" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-6" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-5" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.56875" + inkscape:cx="207.9" + inkscape:cy="290.99601" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1440" + inkscape:window-height="900" + inkscape:window-x="-1" + inkscape:window-y="-1" + inkscape:window-maximized="0" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="background" + sodipodi:insensitive="true" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="0" + inkscape:bbox-y="0" + inkscape:bbox-width="747.27411" + inkscape:bbox-height="480"> + <rect + style="fill:url(#linearGradient3712);fill-opacity:1" + id="rect2928" + width="747.27411" + height="480" + x="0" + y="0" + ry="3.0304577" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="0" + inkscape:bbox-y="0" + inkscape:bbox-width="747.27411" + inkscape:bbox-height="480" /> + </g> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="35.355339" + inkscape:bbox-y="249.90203" + inkscape:bbox-width="641.44684" + inkscape:bbox-height="219.19541" + style="display:inline"> + <g + id="g2917" + transform="translate(-27.274116,-798.02051)" + mbname="video" + inkscape:transform-center-x="0" + inkscape:transform-center-y="42.294399" + inkscape:bbox-x="35.992421" + inkscape:bbox-y="383.87928" + inkscape:bbox-width="85.598946" + inkscape:bbox-height="84.588799"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/video.png" + xlink:href="video.png" + width="85.598946" + height="84.588799" + id="image2983" + x="63.266537" + y="809.55243" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="35.992421" + inkscape:bbox-y="383.87928" + inkscape:bbox-width="85.598946" + inkscape:bbox-height="84.588799" /> + </g> + <g + id="g2917-8" + transform="translate(126.77414,-798.02053)" + mbname="audio" + inkscape:transform-center-x="0" + inkscape:transform-center-y="38.464287" + inkscape:bbox-x="189.7836" + inkscape:bbox-y="386.37278" + inkscape:bbox-width="86.5" + inkscape:bbox-height="76.928574"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/music.png" + xlink:href="music.png" + width="86.5" + height="76.928574" + id="image3048" + x="63.00946" + y="814.71918" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="189.7836" + inkscape:bbox-y="386.37278" + inkscape:bbox-width="86.5" + inkscape:bbox-height="76.928574" /> + </g> + <g + id="g2917-88" + transform="translate(290.67139,-799.03067)" + mbname="picture" + inkscape:transform-center-x="0" + inkscape:transform-center-y="38.07143" + inkscape:bbox-x="354.2955" + inkscape:bbox-y="392.95458" + inkscape:bbox-width="84" + inkscape:bbox-height="76.14286"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/photo.png" + xlink:href="photo.png" + width="84" + height="76.14286" + id="image3049" + x="63.624115" + y="809.93323" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="354.2955" + inkscape:bbox-y="392.95458" + inkscape:bbox-width="84" + inkscape:bbox-height="76.14286" /> + </g> + <g + id="g2917-8-6" + transform="translate(462.9024,-794.99007)" + mbname="setting" + inkscape:transform-center-x="0" + inkscape:transform-center-y="37.57143" + inkscape:bbox-x="526.42387" + inkscape:bbox-y="389.0568" + inkscape:bbox-width="84.571426" + inkscape:bbox-height="75.14286"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/tool.png" + xlink:href="tool.png" + width="84.571426" + height="75.14286" + id="image3168" + x="63.521473" + y="810.79041" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="526.42387" + inkscape:bbox-y="389.0568" + inkscape:bbox-width="84.571426" + inkscape:bbox-height="75.14286" /> + </g> + <rect + style="fill:#dfdf49;fill-opacity:1" + id="rect2929" + width="641.44684" + height="71.720833" + x="35.355339" + y="158.37714" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + rx="10" + ry="10" + inkscape:bbox-x="35.355339" + inkscape:bbox-y="249.90203" + inkscape:bbox-width="641.44684" + inkscape:bbox-height="71.720833" + mbname="lightbar" /> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="124.96794" + y="185.925" + id="text2931" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="271.84843" + inkscape:bbox-width="488.15625" + inkscape:bbox-height="32.382812" + mbname="line1"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="185.925" + id="tspan2935" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="288.74687" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="205.925" + style="font-size:16px" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="271.84843" + inkscape:bbox-width="75.335938" + inkscape:bbox-height="12.101562" + id="tspan2941">7:00-7:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="247.75766" + id="text2931-20" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="210.01578" + inkscape:bbox-width="488.15625" + inkscape:bbox-height="32.382812" + mbname="line2"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="247.75766" + id="tspan2935-1" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="226.91422" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="267.75766" + style="font-size:16px" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="210.01578" + inkscape:bbox-width="75.335938" + inkscape:bbox-height="12.101562" + id="tspan2941-9">7:30-8:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="309.59033" + id="text2931-21" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.05388" + inkscape:bbox-y="152.18311" + inkscape:bbox-width="488.38281" + inkscape:bbox-height="32.382812" + mbname="line3"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="309.59033" + id="tspan2935-2" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="169.08154" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="329.59033" + style="font-size:16px" + inkscape:bbox-x="126.05388" + inkscape:bbox-y="152.18311" + inkscape:bbox-width="75.5625" + inkscape:bbox-height="12.101562" + id="tspan2941-0">8:30-9:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="371.423" + id="text2931-3" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="125.97575" + inkscape:bbox-y="90.350433" + inkscape:bbox-width="488.46094" + inkscape:bbox-height="32.382812" + mbname="line4"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="371.423" + id="tspan2935-11" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="107.24887" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="391.423" + style="font-size:16px" + inkscape:bbox-x="125.97575" + inkscape:bbox-y="90.350433" + inkscape:bbox-width="85.828125" + inkscape:bbox-height="12.101562" + id="tspan2941-90">9:30-10:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="433.25568" + id="text2931-6" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="28.517761" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="32.382812" + mbname="line5"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="433.25568" + id="tspan2935-7" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="45.416199" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="453.25568" + style="font-size:16px" + inkscape:bbox-x="126.72575" + inkscape:bbox-y="28.517761" + inkscape:bbox-width="95.265625" + inkscape:bbox-height="12.101562" + id="tspan2941-7">10:30-11:30</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/desktop/testdesktop.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,126 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); + +app = new mbapp.app(); +app.loadSVG("desktop.svg"); + +video = app.get("video"); +//var an = new animate.alpha(app,video,0,1); +//an.start(); +audio = app.get("audio"); +picture = app.get("picture"); +setting = app.get("setting"); + +lightbar = app.get("lightbar"); +lines = []; +for(i = 0; i < 5; i++) { + line = app.get("line" + (i + 1)); + lines.push(line); +} +line=0; + +items=[video, audio, picture, setting]; + +item = 0; + +animate.run([new animate.scale(app,items[item], 1, 1.5)], 0, 0.1); +app.refresh(); + +app.addKeyListener(mbapp.KEY_LEFT, function() { + var old = items[item]; + item = item - 1; + if (item == -1) { + item = 0; + return; + } + + var target = items[item]; + + old.bbox.update(); + target.bbox.update(); + + var an = new animate.scale(app, old, 1, 1); + animate.run([an], 0, 0.1); + an = new animate.scale(app, target, 1, 1.5); + animate.run([an], 0, 0.3); +}); + +app.addKeyListener(mbapp.KEY_RIGHT, function() { + var old = items[item]; + item = item + 1; + if (item == items.length) { + item = item - 1; + return; + } + + var target = items[item]; + + old.bbox.update(); + target.bbox.update(); + + var an = new animate.scale(app, old, 1, 1); + animate.run([an], 0, 0.1); + an = new animate.scale(app, target, 1, 1.5); + animate.run([an], 0, 0.3); +}); + +app.addKeyListener(mbapp.KEY_UP, function() { + var old = lines[line]; + line = line - 1; + if (line == -1) { + line = 0; + return; + } + var target = lines[line]; + var sy = target.center.y - lightbar.center.y; + sys.puts(sy); + var an = new animate.shift(app, lightbar, 0, sy); + animate.run([an], 0, 0.3); +}); +app.addKeyListener(mbapp.KEY_DOWN, function() { + var old = lines[line]; + line = line + 1; + if (line == lines.length) { + line = line - 1; + return; + } + var target = lines[line]; + var sy = target.center.y - lightbar.center.y; + sys.puts("line="+line); + sys.puts("sy="+sy); + sys.puts("target.y="+target.center.y); + sys.puts("lightbar.y="+lightbar.center.y); + var an = new animate.shift(app, lightbar, 0, sy); + animate.run([an], 0, 0.3); +}); + +app.addKeyListener(mbapp.KEY_ENTER, function() { + var target = items[item]; + var sx = 500 - target.center.x; + var sy = 220 - target.center.y; + sys.puts("target "+sx+','+sy); + var an = new animate.shift(app,target,sx,sy,1); + an.start(); + for(i=0;i<items.length;i++) { + if (i == item) continue; + var x = Math.random(); + var y = Math.random(); + if (x > 0.5) x = 900; + else x = -500; + if (y > 0.5) y = 900; + else y = -500; + sx = x - items[i].center.x; + sy = y - items[i].center.y; + an = new animate.shift(app,items[i], sx, sy); + animate.run([an], 0, 2); + alpha = new animate.alpha(app,items[i], 0); + animate.run([an], 0, 1); + } +}); + +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/README Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,10 @@ +Scene 1: Main category + +1. Start to load all pictures and save them in the file system. +2. Load the main screen and move all pictures to the correct positions. +3. Show the cursor and do animation to scale it. +4. After the animation, start to listent to keys and move the cursor. +5. If the key is enter, load the next scene. + + +Scene 2:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/browser.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448819" + height="1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.47+devel r9312" + sodipodi:docname="browser.svg"> + <defs + id="defs4"> + <linearGradient + inkscape:collect="always" + id="linearGradient3684"> + <stop + style="stop-color:#0000d5;stop-opacity:1;" + offset="0" + id="stop3686" /> + <stop + style="stop-color:#0000d5;stop-opacity:0;" + offset="1" + id="stop3688" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3684" + id="linearGradient3690" + x1="400" + y1="123.79076" + x2="394.28571" + y2="529.50507" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.35" + inkscape:cx="-99.285714" + inkscape:cy="634.28571" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1680" + inkscape:window-height="976" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:url(#linearGradient3690);fill-opacity:1" + id="rect2914" + width="722.85712" + height="537.14288" + x="11.428572" + y="23.790754" + rx="3.8392856" + ry="4.8275862" /> + <text + xml:space="preserve" + style="font-size:133.75950622999999950px;font-style:normal;font-weight:normal;fill:#f2f2f2;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="41.756718" + y="139.44588" + id="text2915" + transform="scale(0.74827402,1.3364088)"><tspan + sodipodi:role="line" + id="tspan2917" + x="41.756718" + y="139.44588">Loading</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/desktop.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,507 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448" + height="480" + id="svg2" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="desktop.svg"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 240 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 240 : 1" + inkscape:persp3d-origin="372.04724 : 160 : 1" + id="perspective21" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3706"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3708" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3710" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3706" + id="linearGradient3712" + x1="0" + y1="240" + x2="747.27411" + y2="240" + gradientUnits="userSpaceOnUse" /> + <inkscape:perspective + id="perspective3711" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2953" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2981" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3009" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3037" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3065" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3093" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2960" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2988" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-0" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-6" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3016-5" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.56875" + inkscape:cx="207.9" + inkscape:cy="290.99601" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1440" + inkscape:window-height="900" + inkscape:window-x="-1" + inkscape:window-y="-1" + inkscape:window-maximized="0" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="background" + sodipodi:insensitive="true" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="0" + inkscape:bbox-y="0" + inkscape:bbox-width="747.27411" + inkscape:bbox-height="480"> + <rect + style="fill:url(#linearGradient3712);fill-opacity:1" + id="rect2928" + width="747.27411" + height="480" + x="0" + y="0" + ry="3.0304577" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="0" + inkscape:bbox-y="0" + inkscape:bbox-width="747.27411" + inkscape:bbox-height="480" /> + </g> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="35.355339" + inkscape:bbox-y="249.90203" + inkscape:bbox-width="641.44684" + inkscape:bbox-height="219.19541" + style="display:inline"> + <g + id="g2917" + transform="translate(-27.274116,-798.02051)" + mbname="video" + inkscape:transform-center-x="0" + inkscape:transform-center-y="42.294399" + inkscape:bbox-x="35.992421" + inkscape:bbox-y="383.87928" + inkscape:bbox-width="85.598946" + inkscape:bbox-height="84.588799"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/video.png" + xlink:href="video.png" + width="85.598946" + height="84.588799" + id="image2983" + x="63.266537" + y="809.55243" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="35.992421" + inkscape:bbox-y="383.87928" + inkscape:bbox-width="85.598946" + inkscape:bbox-height="84.588799" /> + </g> + <g + id="g2917-8" + transform="translate(126.77414,-798.02053)" + mbname="audio" + inkscape:transform-center-x="0" + inkscape:transform-center-y="38.464287" + inkscape:bbox-x="189.7836" + inkscape:bbox-y="386.37278" + inkscape:bbox-width="86.5" + inkscape:bbox-height="76.928574"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/music.png" + xlink:href="music.png" + width="86.5" + height="76.928574" + id="image3048" + x="63.00946" + y="814.71918" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="189.7836" + inkscape:bbox-y="386.37278" + inkscape:bbox-width="86.5" + inkscape:bbox-height="76.928574" /> + </g> + <g + id="g2917-88" + transform="translate(290.67139,-799.03067)" + mbname="picture" + inkscape:transform-center-x="0" + inkscape:transform-center-y="38.07143" + inkscape:bbox-x="354.2955" + inkscape:bbox-y="392.95458" + inkscape:bbox-width="84" + inkscape:bbox-height="76.14286"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/photo.png" + xlink:href="photo.png" + width="84" + height="76.14286" + id="image3049" + x="63.624115" + y="809.93323" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="354.2955" + inkscape:bbox-y="392.95458" + inkscape:bbox-width="84" + inkscape:bbox-height="76.14286" /> + </g> + <g + id="g2917-8-6" + transform="translate(462.9024,-794.99007)" + mbname="setting" + inkscape:transform-center-x="0" + inkscape:transform-center-y="37.57143" + inkscape:bbox-x="526.42387" + inkscape:bbox-y="389.0568" + inkscape:bbox-width="84.571426" + inkscape:bbox-height="75.14286"> + <image + sodipodi:absref="/usr/home/thinker/progm/MadButterfly/nodejs/tool.png" + xlink:href="tool.png" + width="84.571426" + height="75.14286" + id="image3168" + x="63.521473" + y="810.79041" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="526.42387" + inkscape:bbox-y="389.0568" + inkscape:bbox-width="84.571426" + inkscape:bbox-height="75.14286" /> + </g> + <rect + style="fill:#dfdf49;fill-opacity:1" + id="rect2929" + width="641.44684" + height="71.720833" + x="35.355339" + y="158.37714" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + rx="10" + ry="10" + inkscape:bbox-x="35.355339" + inkscape:bbox-y="249.90203" + inkscape:bbox-width="641.44684" + inkscape:bbox-height="71.720833" + mbname="lightbar" /> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="124.96794" + y="185.925" + id="text2931" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="271.84843" + inkscape:bbox-width="488.15625" + inkscape:bbox-height="32.382812" + mbname="line1"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="185.925" + id="tspan2935" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="288.74687" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="205.925" + style="font-size:16px" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="271.84843" + inkscape:bbox-width="75.335938" + inkscape:bbox-height="12.101562" + id="tspan2941">7:00-7:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="247.75766" + id="text2931-20" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="210.01578" + inkscape:bbox-width="488.15625" + inkscape:bbox-height="32.382812" + mbname="line2"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="247.75766" + id="tspan2935-1" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="226.91422" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="267.75766" + style="font-size:16px" + inkscape:bbox-x="126.28044" + inkscape:bbox-y="210.01578" + inkscape:bbox-width="75.335938" + inkscape:bbox-height="12.101562" + id="tspan2941-9">7:30-8:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="309.59033" + id="text2931-21" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.05388" + inkscape:bbox-y="152.18311" + inkscape:bbox-width="488.38281" + inkscape:bbox-height="32.382812" + mbname="line3"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="309.59033" + id="tspan2935-2" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="169.08154" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="329.59033" + style="font-size:16px" + inkscape:bbox-x="126.05388" + inkscape:bbox-y="152.18311" + inkscape:bbox-width="75.5625" + inkscape:bbox-height="12.101562" + id="tspan2941-0">8:30-9:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="371.423" + id="text2931-3" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="125.97575" + inkscape:bbox-y="90.350433" + inkscape:bbox-width="488.46094" + inkscape:bbox-height="32.382812" + mbname="line4"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="371.423" + id="tspan2935-11" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="107.24887" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="391.423" + style="font-size:16px" + inkscape:bbox-x="125.97575" + inkscape:bbox-y="90.350433" + inkscape:bbox-width="85.828125" + inkscape:bbox-height="12.101562" + id="tspan2941-90">9:30-10:30</tspan></text> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans" + x="124.96794" + y="433.25568" + id="text2931-6" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="28.517761" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="32.382812" + mbname="line5"><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="433.25568" + id="tspan2935-7" + style="font-size:16px" + inkscape:bbox-x="126.53825" + inkscape:bbox-y="45.416199" + inkscape:bbox-width="487.89844" + inkscape:bbox-height="15.484375">Lim JeongHee (J.Lim) & JoKwon (2AM) - The Road to Break Up</tspan><tspan + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + x="124.96794" + y="453.25568" + style="font-size:16px" + inkscape:bbox-x="126.72575" + inkscape:bbox-y="28.517761" + inkscape:bbox-width="95.265625" + inkscape:bbox-height="12.101562" + id="tspan2941-7">10:30-11:30</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/epg.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,194 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var http = require('http'); +var URL = require('url'); +var sys = require("sys"); +var fs = require("fs"); +var os = require("child_process"); +function EPG() +{ + var epgsrv = http.createClient(8080, '211.23.50.144'); + var cmd = '{"Protocol":"EPG-CSP","Command":"SearchRequest","ProgramCat":"MainCat"}'; + var headers={ + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Host':'211.23.50.144:8080', + 'User-Agent':'MadButterfly', + 'Content-Type':'application/x-www-form-urlencoded' + }; + headers['Content-Length'] = cmd.length; + var request = epgsrv.request('POST', '/IPTV_EPG/EPGService.do?timestamp='+new Date().getTime(),headers); + var self = this; + sys.puts("aaaa"); + var js = ''; + request.write(cmd); + request.end(); + request.on('response', function(res) { + sys.puts("connected"); + res.on('data',function (data) { + js = js + data; + }); + res.on('end', function () { + res = JSON.parse(js); + sys.puts("parsed"); + self.onLoad(res); + + }); + }); +} + + +/** + * Check if the file has been cached. Create a symbolic to link if it is cached already. + * + */ +function isCached(cachepath,file,obj) { + var fields = cachepath.split('.'); + try { + var ext = fields.pop(); + var pngfile = cachepath; + sys.puts("ext="+ext); + if (ext != 'png') { + fields.push('png'); + pngfile = fields.join('.'); + } + var st = fs.statSync(pngfile); + try { + fs.unlinkSync(file); + } catch(e) { + } + fs.linkSync(pngfile, file); + obj.pend = obj.pend - 1; + if (obj.pend == 0) { + obj.onInitDone(); + } + return 1; + } catch(e) { + sys.puts(e); + } + return 0; +} + +/** + * Implement the mkdir -p to create the directory + */ +function CreateDirectory(cachepath) +{ + var fields = cachepath.split('/'); + var p=''; + for(i=0;i<fields.length-1;i++) { + p = p + fields[i]+'/'; + try { + fs.mkdirSync(p,0777); + } catch(e) { + } + } +} +/* + * We will check the cache directory. If the file is available, we will create a symbolic link only. Otherwise, + * we will fetch it before create the symbolic link. + */ +function httpGetFile(url,file,obj) +{ + sys.puts("fetch "+ file); + var u = URL.parse(url); + var cachepath = 'cache/'+u.pathname; + if (isCached(cachepath,file,obj)) return; + CreateDirectory(cachepath); + + // Fetch file from the server and convert it tyo PNG if it is not PNG format. + var f = fs.openSync(cachepath,'w'); + sys.puts("f="+f); + var headers={ + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Host':'211.23.50.144:8080', + 'User-Agent':'MadButterfly', + 'Content-Type':'application/x-www-form-urlencoded' + }; + sys.puts("host="+u.host+' '+u.port+' '+u.pathname); + for(k in u) { + sys.puts(k+"--->"+u[k]); + } + var c = http.createClient(8080,'211.23.50.144'); + var req = c.request('GET',u.pathname,headers); + req.end(); + req.on('response', function(res) { + res.on('data',function(data) { + fs.writeSync(f,data,0,data.length); + }); + res.on('end',function() { + fs.close(f); + var fields = cachepath.split('.'); + var ext = fields.pop(); + if (ext != "png") { + fields.push("png"); + newf = fields.join("."); + sys.puts("cachepath="+cachepath+" newf="+newf); + os.spawn("convert",[cachepath,newf]); + } else { + newf = cachepath; + } + try { + fs.unlinkSync(file); + } catch(e) { + } + sys.puts("end of "+cachepath+" to "+file); + fs.symlinkSync(newf, file); + obj.pend = obj.pend - 1; + if (obj.pend == 0) { + obj.onInitDone(); + } + + }); + + }); +} + +EPG.prototype.onLoad = function(res) { + cats = res['ProgramCat']; + this.pend = cats.length; + this.maincat = cats; + for (i in cats) { + c = cats[i]; + httpGetFile(c['ProgramPIC'],'cat'+i+'.png',this); + } +} + +EPG.prototype.getList=function(item,func) { + var epgsrv = http.createClient(8080, '211.23.50.144'); + var cmd = '{"Protocol":"EPG-CSP","Command":"SearchRequest","ProgramSub":"'+item.Category+'"}'; + var headers={ + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Host':'211.23.50.144:8080', + 'User-Agent':'MadButterfly', + 'Content-Type':'application/x-www-form-urlencoded' + }; + headers['Content-Length'] = cmd.length; + var request = epgsrv.request('POST', '/IPTV_EPG/EPGService.do?timestamp='+new Date().getTime(),headers); + var self = this; + sys.puts("aaaa"); + var js = ''; + request.write(cmd); + request.end(); + request.on('response', function(res) { + sys.puts("connected"); + res.on('data',function (data) { + js = js + data; + }); + res.on('end', function () { + res = JSON.parse(js); + sys.puts("parsed"); + func(); + + }); + }); +} +EPG.prototype.onInitDone=function() { + if (this.loadCallback) + this.loadCallback(); +} + +EPG.prototype.registerInitDone=function(cb) { + this.loadCallback = cb; +} + +exports.EPG = EPG;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/main.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,376 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:ns0="http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448819" + height="1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.48+devel r9764 custom" + sodipodi:docname="main.svg"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective13" /> + <inkscape:perspective + id="perspective2973" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2975" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2993" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.35" + inkscape:cx="206.98185" + inkscape:cy="483.73232" + inkscape:document-units="px" + inkscape:current-layer="Layer 1s235" + showgrid="false" + inkscape:window-width="1680" + inkscape:window-height="976" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + <ns0:scenes> + <ns0:scene + start="1" + ref="Layer 1s1841" /> + <ns0:scene + start="2" + ref="Layer 1s235" /> + </ns0:scenes> + </metadata> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Background"> + <image + y="-27.637817" + x="0" + inkscape:bbox-height="1080" + inkscape:bbox-width="1920" + inkscape:bbox-y="0" + inkscape:bbox-x="0" + id="image2977" + height="1080" + width="1920" + xlink:href="file:///home/wycc/devel/md6/MadButterfly/nodejs/examples/mce/background.png" /> + </g> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + id="Layer 1s1841" + inkscape:groupmode="layer" + style="display:none"> + <g + transform="translate(7.14163,8.5714057)" + id="g2999" + inkscape:label="lightbar" + inkscape:bbox-x="107.14287" + inkscape:bbox-y="49.999969" + inkscape:bbox-width="228.57144" + inkscape:bbox-height="865.71429"> + <image + xlink:href="file:///home/wycc/devel/md6/MadButterfly/nodejs/examples/mce/vod1-select.png" + width="228.57144" + height="865.71429" + id="image2995" + inkscape:bbox-x="107.14287" + inkscape:bbox-y="49.999969" + inkscape:bbox-width="228.57144" + inkscape:bbox-height="865.71429" + x="107.14287" + y="136.64792" /> + </g> + <g + transform="translate(7.14163,8.5714057)" + id="g2922" + inkscape:label="cat0" + inkscape:bbox-x="117.64285" + inkscape:bbox-y="462.7648" + inkscape:bbox-width="200" + inkscape:bbox-height="286.7168"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat0.png" + xlink:href="./cat0.png" + y="302.88058" + x="117.64285" + id="image3058" + height="286.7168" + width="200" + inkscape:label="" + inkscape:bbox-x="117.64285" + inkscape:bbox-y="462.7648" + inkscape:bbox-width="200" + inkscape:bbox-height="286.7168" /> + </g> + <g + transform="translate(7.14163,8.5714057)" + id="g2923" + inkscape:label="cat1" + inkscape:bbox-x="359.21432" + inkscape:bbox-y="455.42856" + inkscape:bbox-width="200" + inkscape:bbox-height="291.09415"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat1.png" + xlink:href="./cat1.png" + y="305.83948" + x="359.21432" + id="image3116" + height="291.09415" + width="200" + inkscape:label="" + inkscape:bbox-x="359.21432" + inkscape:bbox-y="455.42856" + inkscape:bbox-width="200" + inkscape:bbox-height="291.09415" /> + </g> + <g + transform="translate(7.14163,8.571406)" + id="g2926" + inkscape:label="cat2" + inkscape:bbox-x="599.07141" + inkscape:bbox-y="458.28571" + inkscape:bbox-width="200" + inkscape:bbox-height="286.7168"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat2.png" + xlink:href="./cat2.png" + y="307.35968" + x="599.07141" + id="image3174" + height="286.7168" + width="200" + inkscape:label="" + inkscape:bbox-x="599.07141" + inkscape:bbox-y="458.28571" + inkscape:bbox-width="200" + inkscape:bbox-height="286.7168" /> + </g> + <g + transform="translate(7.14163,8.5714057)" + id="g2929" + inkscape:label="cat3" + inkscape:bbox-x="821.35712" + inkscape:bbox-y="456.71426" + inkscape:bbox-width="200" + inkscape:bbox-height="289.10892"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat3.png" + xlink:href="./cat3.png" + y="306.539" + x="821.35712" + id="image3232" + height="289.10892" + width="200" + inkscape:label="" + inkscape:bbox-x="821.35712" + inkscape:bbox-y="456.71426" + inkscape:bbox-width="200" + inkscape:bbox-height="289.10892" /> + </g> + <path + sodipodi:type="star" + style="fill:#00c280;fill-opacity:1" + id="path3235" + sodipodi:sides="3" + sodipodi:cx="-171.42857" + sodipodi:cy="186.6479" + sodipodi:r1="48.760139" + sodipodi:r2="24.38007" + sodipodi:arg1="1.0153026" + sodipodi:arg2="2.0625001" + inkscape:flatsided="false" + inkscape:rounded="0" + inkscape:randomized="0" + d="m -145.71429,228.07648 -37.22481,-19.93682 -37.22481,-19.93682 35.87819,-22.26922 35.8782,-22.26923 1.34662,42.20604 z" + inkscape:transform-center-x="11.746635" + inkscape:transform-center-y="-0.50892793" + transform="matrix(0.9999393,0.01101845,-0.01101845,0.9999393,246.33065,273.32876)" + inkscape:label="leftarrow" + inkscape:bbox-x="16.964767" + inkscape:bbox-y="561.14775" + inkscape:bbox-width="74.005762" + inkscape:bbox-height="84.436636" /> + <path + transform="matrix(-0.99874276,-0.05012887,0.05012887,-0.99874276,1666.5721,621.61046)" + inkscape:transform-center-y="-0.445031" + inkscape:transform-center-x="-11.802598" + d="m -145.71429,228.07648 -37.22481,-19.93682 -37.22481,-19.93682 35.87819,-22.26922 35.8782,-22.26923 1.34662,42.20604 z" + inkscape:randomized="0" + inkscape:rounded="0" + inkscape:flatsided="false" + sodipodi:arg2="2.0625001" + sodipodi:arg1="1.0153026" + sodipodi:r2="24.38007" + sodipodi:r1="48.760139" + sodipodi:cy="186.6479" + sodipodi:cx="-171.42857" + sodipodi:sides="3" + id="path4005" + style="fill:#00c280;fill-opacity:1" + sodipodi:type="star" + inkscape:label="rightarrow" + inkscape:bbox-x="1814.8532" + inkscape:bbox-y="575.3674" + inkscape:bbox-width="73.898841" + inkscape:bbox-height="84.440967" /> + <g + inkscape:bbox-height="289.10892" + inkscape:bbox-width="200" + inkscape:bbox-y="456.71426" + inkscape:bbox-x="1035.3571" + inkscape:label="cat4" + id="g2931" + transform="translate(221.14163,8.5714057)"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat4.png" + xlink:href="./cat4.png" + inkscape:bbox-height="289.10892" + inkscape:bbox-width="200" + inkscape:bbox-y="456.71426" + inkscape:bbox-x="1035.3571" + inkscape:label="" + width="200" + height="289.10892" + id="image2933" + x="821.35712" + y="306.539" /> + </g> + <g + transform="translate(445.14163,8.5714057)" + id="g2935" + inkscape:label="cat5" + inkscape:bbox-x="1259.3571" + inkscape:bbox-y="456.71426" + inkscape:bbox-width="200" + inkscape:bbox-height="289.10892"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat5.png" + xlink:href="./cat5.png" + y="306.539" + x="821.35712" + id="image2937" + height="289.10892" + width="200" + inkscape:label="" + inkscape:bbox-x="1259.3571" + inkscape:bbox-y="456.71426" + inkscape:bbox-width="200" + inkscape:bbox-height="289.10892" /> + </g> + <g + inkscape:bbox-height="289.10892" + inkscape:bbox-width="200" + inkscape:bbox-y="456.71426" + inkscape:bbox-x="1475.3571" + inkscape:label="cat6" + id="g2939" + transform="translate(661.14163,8.5714057)"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat6.png" + xlink:href="./cat6.png" + inkscape:bbox-height="289.10892" + inkscape:bbox-width="200" + inkscape:bbox-y="456.71426" + inkscape:bbox-x="1475.3571" + inkscape:label="" + width="200" + height="289.10892" + id="image2941" + x="821.35712" + y="306.539" /> + </g> + </g> + <g + id="Layer 1s235" + inkscape:groupmode="layer" + style="display:inline"> + <rect + x="0" + y="0" + width="100" + height="100" + id="rect3181" /> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./background2.png" + xlink:href="./background2.png" + width="1920" + height="1080" + id="image3245" + x="0" + y="-27.637817" /> + <g + transform="matrix(1.1857143,0,0,1.2748252,-274.497,-403.36247)" + id="g29230" + inkscape:label="current" + inkscape:bbox-x="359.21432" + inkscape:bbox-y="455.42856" + inkscape:bbox-width="200" + inkscape:bbox-height="291.09415"> + <image + sodipodi:absref="/home/wycc/devel/md7/MadButterfly/nodejs/examples/mce/./cat1.png" + xlink:href="./cat1.png" + inkscape:bbox-height="291.09415" + inkscape:bbox-width="200" + inkscape:bbox-y="455.42856" + inkscape:bbox-x="359.21432" + inkscape:label="" + width="200" + height="291.09415" + id="image3116-4" + x="330.29868" + y="458.24133" /> + </g> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/mainmenu.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,163 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); +var EPG = require('./epg'); +/** + * We will fetch the EPG file from the server and fetch all images required for the main category from it. + * If these files are cached, we will not fetch it again. Otherwise, we will fetch them. The EPG class is + * responsible for the cache management. + */ +function MainMenu(app) +{ + var self = this; + var epg = new EPG.EPG(); + epg.registerInitDone(function() { self.init();}); + app.epg = epg; + //self.init(); +} +MainMenu.prototype.init=function() +{ + app.loadSVG("main.svg"); + app.changeScene(1); + + var i; + var self = this; + this.items=[]; + for(i=0;i<8;i++) { + this.items.push(app.get("cat"+i)); + } + this.app = app; + + this.lightbar = app.get("lightbar"); + this.lines = []; + for(i = 0; i < 5; i++) { + var line = app.get("line" + (i + 1)); + this.lines.push(line); + } + this.line=0; + this.item = 0; + + animate.run([new animate.scale(app,this.items[this.item], 1, 1.5)], 0, 0.1); + app.refresh(); + + app.addKeyListener(mbapp.KEY_LEFT, function() { self.key_left();}); + app.addKeyListener(mbapp.KEY_RIGHT, function() { self.key_right();}); + app.addKeyListener(mbapp.KEY_UP, function() {self.key_up();}); + app.addKeyListener(mbapp.KEY_DOWN, function() {self.key_down();}); + app.addKeyListener(mbapp.KEY_ENTER, function() {self.key_enter();}); +} + +MainMenu.prototype.key_left=function () +{ + var old = this.items[this.item]; + this.item = this.item - 1; + if (this.item == -1) { + this.item = 0; + return; + } + + var target = this.items[this.item]; + + old.bbox.update(); + target.bbox.update(); + + var an = new animate.scale(this.app, old, 1/1.1, 1/1.5); + animate.run([an], 0, 0.1); + an = new animate.scale(this.app, target, 1.1, 1.5); + animate.run([an], 0, 0.3); + var sx = target.center.x - this.lightbar.center.x; + var an = new animate.shift(this.app, this.lightbar, sx, 0); + animate.run([an], 0, 0.3); +} + +MainMenu.prototype.key_right=function() +{ + var old = this.items[this.item]; + this.item = this.item + 1; + if (this.item == this.items.length) { + this.item = this.item - 1; + return; + } + + var target = this.items[this.item]; + + old.bbox.update(); + target.bbox.update(); + + var an = new animate.scale(this.app, old, 1/1.1, 1/1.5); + animate.run([an], 0, 0.1); + an = new animate.scale(this.app, target, 1.1, 1.5); + animate.run([an], 0, 0.3); + var sx = target.center.x - this.lightbar.center.x; + var an = new animate.shift(this.app, this.lightbar, sx, 0); + animate.run([an], 0, 0.3); +} + +MainMenu.prototype.key_up=function() +{ + var old = this.lines[this.line]; + this.line = this.line - 1; + if (this.line == -1) { + this.line = 0; + return; + } + var target = this.lines[this.line]; + var sy = target.center.y - this.lightbar.center.y; + var an = new animate.shift(this.app, this.lightbar, 0, sy); + animate.run([an], 0, 0.3); +} + + +MainMenu.prototype.key_down=function () +{ + var old = this.lines[this.line]; + this.line = this.line + 1; + if (this.line == this.lines.length) { + this.line = this.line - 1; + return; + } + var target = this.lines[this.line]; + var sy = target.center.y - this.lightbar.center.y; + var an = new animate.shift(this.app, this.lightbar, 0, sy); + animate.run([an], 0, 0.3); +} + +MainMenu.prototype.key_enter=function() +{ + var self = this; + var target = this.items[this.item]; + var an = new animate.scale(this.app, target, 1/1.1, 1/1.5); + animate.run([an], 0, 0.3,function() { + var sx = 259 - target.center.x; + var sy = 355 - target.center.y; + var an1 = new animate.shift(self.app,target,sx,sy); + animate.run([an1],0,1,function() {self.changePage(self.item);}); + }); + for(i=0;i<this.items.length;i++) { + if (i == this.item) continue; + if (i > this.item) { + sx = 1920*2 - this.items[i].center.x; + sy = 0; + } else { + sx = -this.items[i].center.x*2; + sy = 0; + } + an = new animate.shift(this.app,this.items[i], sx, sy); + animate.run([an], 0, 2); + alpha = new animate.alpha(this.app,this.items[i], 0); + animate.run([an], 0, 2); + } +} + +MainMenu.prototype.onNextPage=function() { + this.app.changeScene(2); +} +MainMenu.prototype.changePage=function(item) { + this.epg.getList(item,self.onNextPage()); +} + +exports.MainMenu=MainMenu;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/mbmce.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,11 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); +var main=require("./mainmenu"); +app = new mbapp.app(":0.0",1920,1080); +scene=new main.MainMenu(app); +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/preview.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="1920" + height="1080" + id="svg2" + version="1.1" + inkscape:version="0.47 r22583" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + sodipodi:docname="New document 1"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <inkscape:perspective + id="perspective2987" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.35" + inkscape:cx="375" + inkscape:cy="520" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1680" + inkscape:window-height="976" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + transform="translate(0,27.637817)"> + <image + y="-27.637817" + x="0" + inkscape:bbox-height="1080" + inkscape:bbox-width="1920" + inkscape:bbox-y="3.8281246e-07" + inkscape:bbox-x="0" + inkscape:transform-center-y="0" + inkscape:transform-center-x="0" + id="image2989" + height="1080" + width="1920" + xlink:href="file:///home/wycc/devel/md6/MadButterfly/nodejs/examples/mce/background2.png" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/mce/test Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,4 @@ +#!/bin/sh + +export NODE_PATH=${PWD}/../../objs/default:${PWD}/../.. +node mbmce.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/phone/phone.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,61 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); + +app = new mbapp.app(":0.0", 320, 480); +app.loadSVG("phone_ui.svg"); + +var icons = []; +var r, c; +var mbname; +for(c = 0; c < 4; c++) { // 4 columns + for(r = 0; r < 5; r++) { // 5 rows + mbname = "icon" + c + "" + r; + icons.push(app.get(mbname)); + } +} + +var overhint, presshint; +var overholder, pressholder; +overhint = app.get("overhint"); +presshint = app.get("presshint"); +overholder = new animate.holder(app, overhint); +pressholder = new animate.holder(app, presshint); + +var dock; +var dockholder; +dock = app.get("dock"); +dockholder = new animate.holder(app, dock); + +var i; +var icon; +for(i = 0; i < icons.length; i++) { + icon = icons[i]; + icon.mouse_event.add_event_observer(1, function(evt) { + overholder.go_center(evt.cur_tgt); + }); + icon.mouse_event.add_event_observer(2, function(evt) { + overholder.home(); + }); + icon.mouse_event.add_event_observer(4, function(evt) { + pressholder.go_center(evt.cur_tgt); + var rotate = new animate.rotate(app, evt.cur_tgt, 2 * 3.1415); + animate.run([rotate], 0, 0.7); + }); +} + +var sw = 0; +var dock_up = new animate.shift(app, dock, 0, -300); +var dock_down = new animate.shift(app, dock, 0, 0); +dock.mouse_event.add_event_observer(4, function(evt) { + if(sw == 0) { + animate.run([dock_up], 0, 0.5); + } else { + animate.run([dock_down], 0, 0.2); + } + sw = sw ^ 1; + }); + +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/phone/phone_ui.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,491 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="320" + height="480" + id="svg2" + version="1.1" + inkscape:version="0.48+devel r9732" + sodipodi:docname="phone_ui.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.90416667" + inkscape:cx="312.60279" + inkscape:cy="186.36119" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + width="320px" + inkscape:window-width="888" + inkscape:window-height="684" + inkscape:window-x="333" + inkscape:window-y="132" + inkscape:window-maximized="0" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + inkscape:bbox-x="-1.1059908" + inkscape:bbox-y="-860.32248" + inkscape:bbox-width="415.19362" + inkscape:bbox-height="773.49026"> + <rect + mbname="icon00" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" + id="rect3599" + width="56.328701" + height="44.162804" + x="31.642097" + y="60.326893" + inkscape:bbox-x="30.603683" + inkscape:bbox-y="374.47189" + inkscape:bbox-width="58.40553" + inkscape:bbox-height="46.239633" + rx="11.071856" + ry="9.7391548" + inkscape:tile-cx="82.396311" + inkscape:tile-cy="75.207361" + inkscape:tile-w="56.328701" + inkscape:tile-h="44.162804" + inkscape:tile-x0="54.23196" + inkscape:tile-y0="53.125959" /> + <rect + mbname="icon01" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="312.64394" + inkscape:bbox-x="30.603683" + y="122.15484" + x="31.642097" + height="44.162804" + width="56.328701" + id="use3685" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon02" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="250.81607" + inkscape:bbox-x="30.603683" + y="183.98271" + x="31.642097" + height="44.162804" + width="56.328701" + id="use3687" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon03" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="188.98813" + inkscape:bbox-x="30.603683" + y="245.81065" + x="31.642097" + height="44.162804" + width="56.328701" + id="use3689" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon04" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="127.16017" + inkscape:bbox-x="30.603683" + y="307.63861" + x="31.642097" + height="44.162804" + width="56.328701" + id="use3691" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon10" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="374.47189" + inkscape:bbox-x="98.198119" + y="60.326893" + x="99.236534" + height="44.162804" + width="56.328701" + id="use3693" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon11" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="312.64394" + inkscape:bbox-x="98.198119" + y="122.15484" + x="99.236534" + height="44.162804" + width="56.328701" + id="use3695" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon12" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="250.81607" + inkscape:bbox-x="98.198119" + y="183.98271" + x="99.236534" + height="44.162804" + width="56.328701" + id="use3697" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon13" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="188.98813" + inkscape:bbox-x="98.198119" + y="245.81065" + x="99.236534" + height="44.162804" + width="56.328701" + id="use3699" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon14" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="127.16017" + inkscape:bbox-x="98.198119" + y="307.63861" + x="99.236534" + height="44.162804" + width="56.328701" + id="use3701" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon20" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="374.47189" + inkscape:bbox-x="165.79256" + y="60.326893" + x="166.83098" + height="44.162804" + width="56.328701" + id="use3703" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon21" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="312.64394" + inkscape:bbox-x="165.79256" + y="122.15484" + x="166.83098" + height="44.162804" + width="56.328701" + id="use3705" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon22" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="250.81607" + inkscape:bbox-x="165.79256" + y="183.98271" + x="166.83098" + height="44.162804" + width="56.328701" + id="use3707" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon23" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="188.98813" + inkscape:bbox-x="165.79256" + y="245.81065" + x="166.83098" + height="44.162804" + width="56.328701" + id="use3709" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon24" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="127.16017" + inkscape:bbox-x="165.79256" + y="307.63861" + x="166.83098" + height="44.162804" + width="56.328701" + id="use3711" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon30" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="374.47189" + inkscape:bbox-x="233.387" + y="60.326893" + x="234.42542" + height="44.162804" + width="56.328701" + id="use3713" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon31" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="312.64394" + inkscape:bbox-x="233.387" + y="122.15484" + x="234.42542" + height="44.162804" + width="56.328701" + id="use3715" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon32" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="250.81607" + inkscape:bbox-x="233.387" + y="183.98271" + x="234.42542" + height="44.162804" + width="56.328701" + id="use3717" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon33" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="188.98813" + inkscape:bbox-x="233.387" + y="245.81065" + x="234.42542" + height="44.162804" + width="56.328701" + id="use3719" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <rect + mbname="icon34" + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239633" + inkscape:bbox-width="58.40553" + inkscape:bbox-y="127.16017" + inkscape:bbox-x="233.387" + y="307.63861" + x="234.42542" + height="44.162804" + width="56.328701" + id="use3721" + style="fill:#ffe8e8;fill-opacity:1;stroke:#800000;stroke-width:2.07682943;stroke-miterlimit:4;stroke-dasharray:none" /> + <g + id="g3781" + inkscape:bbox-x="-2.6747894e-07" + inkscape:bbox-y="440.72538" + inkscape:bbox-width="321.84332" + inkscape:bbox-height="43.133648" + transform="translate(1.1059905,-570.69124)"> + <rect + inkscape:bbox-height="35.391705" + inkscape:bbox-width="320.73734" + inkscape:bbox-y="440.72538" + inkscape:bbox-x="-2.7016535e-07" + y="574.57416" + x="-1.1059908" + height="35.391705" + width="320.73734" + id="rect3761" + style="fill:#f2f2f2;fill-opacity:1;stroke:none" /> + <rect + inkscape:bbox-height="35.391705" + inkscape:bbox-width="320.73734" + inkscape:bbox-y="448.46732" + inkscape:bbox-x="1.1059882" + y="566.83221" + x="-2.250144e-06" + height="35.391705" + width="320.73734" + id="rect3761-7" + style="fill:#ececec;fill-opacity:1;stroke:none" /> + </g> + <rect + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + inkscape:tile-h="44.162804" + inkscape:tile-w="56.328701" + inkscape:tile-cy="75.207361" + inkscape:tile-cx="82.396311" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239804" + inkscape:bbox-width="58.405701" + inkscape:bbox-y="370.70221" + inkscape:bbox-x="356.04143" + y="64.096489" + x="357.07993" + height="44.162804" + width="56.328701" + id="rect3599-9" + style="fill:none;stroke:#ff1010;stroke-width:2.0769999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + mbname="overhint" /> + <rect + inkscape:tile-y0="53.125959" + inkscape:tile-x0="54.23196" + inkscape:tile-h="44.162804" + inkscape:tile-w="56.328701" + inkscape:tile-cy="75.207361" + inkscape:tile-cx="82.396311" + ry="9.7391548" + rx="11.071856" + inkscape:bbox-height="46.239804" + inkscape:bbox-width="58.405701" + inkscape:bbox-y="318.06628" + inkscape:bbox-x="356.78795" + y="116.73241" + x="357.82645" + height="44.162804" + width="56.328701" + id="rect3599-9-3" + style="fill:none;stroke:#000080;stroke-width:2.07699990000000012;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + mbname="presshint" /> + <g + id="g3849" + inkscape:bbox-x="2.2255181" + inkscape:bbox-y="-289.63124" + inkscape:bbox-width="317.40625" + inkscape:bbox-height="359.25593" + mbname="dock" + transform="translate(1.1059905,-570.69124)"> + <path + inkscape:bbox-height="76.31255" + inkscape:bbox-width="317.40625" + inkscape:bbox-y="-6.68786" + inkscape:bbox-x="2.2255181" + inkscape:connector-curvature="0" + id="rect2817" + d="m 163.68203,981.06655 c -63.1198,0 -120.411185,7.92804 -162.5625024,20.84375 l 0,55.4688 317.4062524,0 0,-57.7188 C 277.22165,988.08365 223.03485,981.06655 163.68203,981.06655 z" + style="fill:#4494c2;fill-opacity:0.59174314;stroke:none" /> + <path + style="fill:#6083ff;fill-opacity:1;stroke:#1033ff;stroke-width:2.0769999;stroke-miterlimit:4;stroke-opacity:1" + d="m 182.48848,1003.6866 c 0,8.2461 -9.16063,14.9309 -20.46083,14.9309 -11.3002,0 -20.46083,-6.6848 -20.46083,-14.9309 0,-8.24608 9.16063,-14.93086 20.46083,-14.93086 11.3002,0 20.46083,6.68478 20.46083,14.93086 z" + id="path3843" + inkscape:connector-curvature="0" + inkscape:bbox-x="141.63431" + inkscape:bbox-y="31.03524" + inkscape:bbox-width="42.99866" + inkscape:bbox-height="31.93876" /> + <rect + style="fill:#ececec;fill-opacity:1;stroke:#c7cfff;stroke-width:2.03777313;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="rect2838" + width="310.82263" + height="282.06689" + x="4.4043493" + y="1057.2367" + inkscape:bbox-x="4.4914533" + inkscape:bbox-y="-289.63124" + inkscape:bbox-width="312.8604" + inkscape:bbox-height="284.10467" /> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/scene/mainmenu.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,60 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); +/** + * We will fetch the EPG file from the server and fetch all images required for the main category from it. + * If these files are cached, we will not fetch it again. Otherwise, we will fetch them. The EPG class is + * responsible for the cache management. + */ +function MainMenu(app) +{ + var self = this; + this.n = 1; + this.app = app; + self.init(app); +} +MainMenu.prototype.init=function(app) +{ + var self = this; + app.loadSVG("mbtest.svg"); + + app.addKeyListener(mbapp.KEY_LEFT, function() { self.key_left();}); + app.addKeyListener(mbapp.KEY_RIGHT, function() { self.key_right();}); + app.addKeyListener(mbapp.KEY_UP, function() {self.key_up();}); + app.addKeyListener(mbapp.KEY_DOWN, function() {self.key_down();}); + app.addKeyListener(mbapp.KEY_ENTER, function() {self.key_enter();}); + app.changeScene(this.n); +} + +MainMenu.prototype.key_left=function () +{ + this.n = this.n - 1; + this.app.changeScene(this.n); + sys.puts("scene "+this.n); +} + +MainMenu.prototype.key_right=function() +{ + this.n = this.n + 1; + this.app.changeScene(this.n); + sys.puts("scene "+this.n); +} + +MainMenu.prototype.key_up=function() +{ +} + + +MainMenu.prototype.key_down=function () +{ +} + +MainMenu.prototype.key_enter=function() +{ +} + +exports.MainMenu=MainMenu;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/scene/mbtest.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,374 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:ns0="http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="640px" + height="480px" + id="svg2383" + sodipodi:version="0.32" + inkscape:version="0.48+devel r9764 custom" + sodipodi:docname="mbtest.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.1"> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.6029106" + inkscape:cx="69.206233" + inkscape:cy="290.40921" + inkscape:current-layer="layer2" + inkscape:document-units="px" + showgrid="false" + inkscape:window-width="1400" + inkscape:window-height="974" + inkscape:window-x="271" + inkscape:window-y="25" + inkscape:window-maximized="0" /> + <defs + id="defs2385"> + <linearGradient + inkscape:collect="always" + id="linearGradient3211"> + <stop + style="stop-color:#001dff;stop-opacity:1;" + offset="0" + id="stop3213" /> + <stop + style="stop-color:#001dff;stop-opacity:0;" + offset="1" + id="stop3215" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 240 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="640 : 240 : 1" + inkscape:persp3d-origin="320 : 160 : 1" + id="perspective2391" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211" + id="linearGradient3217" + x1="31.940987" + y1="28.009715" + x2="104.68548" + y2="28.009715" + gradientUnits="userSpaceOnUse" /> + <filter + inkscape:collect="always" + id="filter3295"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.67110109" + id="feGaussianBlur3297" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211" + id="linearGradient3316" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009715" + x2="104.68548" + y2="28.009715" /> + <linearGradient + y2="28.009715" + x2="104.68548" + y1="28.009715" + x1="31.940987" + gradientUnits="userSpaceOnUse" + id="linearGradient3542" + xlink:href="#linearGradient3211" + inkscape:collect="always" /> + <linearGradient + y2="28.009715" + x2="104.68548" + y1="28.009715" + x1="31.940987" + gradientUnits="userSpaceOnUse" + id="linearGradient3544" + xlink:href="#linearGradient3211" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3211-0"> + <stop + style="stop-color:#001dff;stop-opacity:1;" + offset="0" + id="stop3213-3" /> + <stop + style="stop-color:#001dff;stop-opacity:0;" + offset="1" + id="stop3215-9" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0" + id="linearGradient3316-4" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0" + id="linearGradient3217-6" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0-5" + id="linearGradient3316-4-8" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3211-0-5"> + <stop + style="stop-color:#001dff;stop-opacity:1;" + offset="0" + id="stop3213-3-8" /> + <stop + style="stop-color:#001dff;stop-opacity:0;" + offset="1" + id="stop3215-9-4" /> + </linearGradient> + <filter + color-interpolation-filters="sRGB" + inkscape:collect="always" + id="filter3295-1-3"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.67110109" + id="feGaussianBlur3297-9-7" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0-5" + id="linearGradient3217-6-1" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0-5" + id="linearGradient3237" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" /> + </defs> + <metadata + id="metadata2388"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + <ns0:scenes> + <ns0:scene + start="1" + ref="g3189" + end="15" /> + <ns0:scene + start="1" + ref="s4427" /> + <ns0:scene + start="2" + ref="s4159" /> + <ns0:scene + start="5" + ref="s9524" + end="10" /> + <ns0:scene + start="15" + ref="s6546" /> + </ns0:scenes> + </metadata> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Background" + style="display:inline"> + <g + id="g3189" + style=""> + <rect + style="fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;display:inline" + id="rect2437" + width="641.95721" + height="481.62387" + x="0.93578684" + y="-10.98185" /> + <rect + style="fill:#ffcc1d;fill-opacity:1;stroke:none" + id="rect3698" + width="624.48901" + height="46.789886" + x="6.8625164" + y="5.8625031" + rx="10" + ry="10" /> + <g + style="display:inline" + transform="translate(-11.385541,2.6514388)" + id="g3303"> + <rect + y="15.22048" + x="32.440987" + height="25.57847" + width="71.744492" + id="rect2439" + style="fill:url(#linearGradient3237);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" /> + <text + id="text3299" + y="33.312569" + x="39.927368" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:16px" + y="33.312569" + x="39.927368" + id="tspan3301" + sodipodi:role="line">Action</tspan></text> + </g> + <g + style="display:inline" + id="g3308" + transform="translate(76.891374,2.9633707)"> + <rect + y="15.22048" + x="32.440987" + height="25.57847" + width="71.744492" + id="rect3310" + style="fill:url(#linearGradient3316-4-8);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" /> + <text + id="text3312" + y="33.312569" + x="39.927368" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:16px" + y="33.312569" + x="39.927368" + id="tspan3314" + sodipodi:role="line">Select</tspan></text> + </g> + </g> + <g + id="s4393" + style="" /> + </g> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="Buton" + style="display:inline"> + <g + id="s4427" + style="display:none" /> + <g + id="s4159" + transform="translate(170.31517,0.62386544)" + style="display:none"> + <g + transform="translate(4.9909171,0.3119319)" + id="g3370"> + <rect + style="fill:url(#linearGradient3542);fill-opacity:1;stroke:none;filter:url(#filter3295)" + id="rect3372" + width="71.744492" + height="25.57847" + x="32.440987" + y="15.22048" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="35.927368" + y="33.312569" + id="text3374"><tspan + sodipodi:role="line" + id="tspan3376" + x="35.927368" + y="33.312569" + style="font-size:16px">GNOME</tspan></text> + </g> + <g + transform="translate(102.93775,-0.9357981)" + id="g3380"> + <rect + style="fill:url(#linearGradient3544);fill-opacity:1;stroke:none;filter:url(#filter3295)" + id="rect3382" + width="71.744492" + height="25.57847" + x="32.440987" + y="15.22048" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="39.927368" + y="33.312569" + id="text3384"><tspan + sodipodi:role="line" + id="tspan3386" + x="39.927368" + y="33.312569" + style="font-size:16px">AAA</tspan></text> + </g> + </g> + <g + id="s9524" + transform="translate(90.460441,64.258106)" + style="display:none"> + <rect + x="0" + y="0" + width="100" + height="100" + id="rect3118" /> + </g> + <g + id="s6546" + style="display:none"> + <rect + x="0" + y="0" + width="100" + height="100" + style="fill:#ff00" + id="rect3116" /> + </g> + </g> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer" + style="display:inline" /> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/scene/scene.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,11 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); +var main=require("./mainmenu"); +app = new mbapp.app(":0.0",800,600); +scene=new main.MainMenu(app); +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/simple/testcanvas.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,31 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var mbapp = require("mbapp"); +var sys=require("sys"); +var canvas=require("canvas"); + +app = new mbapp.app(); + +app.canvas = new canvas.canvas(app,app.mb_rt.root); + +app.canvas.background(0,0,0,1); +app.canvas.rect(0,0,400,400); +app.canvas.strokeWeight(8); +width=200; +height=200; + +setInterval(function() { + app.canvas.clear(); + + for(i=0;i<width;i++) { + x = Math.random()*255; + y = Math.random()*200; + cr = Math.random() + cg = Math.random() + cb = Math.random() + app.canvas.stroke(cr,cg,cb,1); + app.canvas.line(i,0,x,height); + } + app.update(); +},33); +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/simple/testcase.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,169 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var mbfly = require("mbfly"); +var r = mbfly.Hello(" test"); +var sys = require("sys"); +sys.puts(r); + +var display_name = ":0.0"; +if(process.argv.length == 3) + display_name = process.argv[2]; + +var mb_rt = new mbfly.mb_rt(display_name, 300, 200); +var root = mb_rt.root; +sys.puts("root matrix: " + + [root[0], root[1], root[2], root[3], root[4], root[5]]); +var coord = mb_rt.coord_new(root); +sys.puts("coord matrix: " + + [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]); + +/* Testcase for image shapes */ +var img = mb_rt.image_new(10, 10, 50, 50); +var ldr = mbfly.img_ldr_new("."); +var img_data = ldr.load("sample.png"); +var paint = mb_rt.paint_image_new(img_data); +var img_coord = mb_rt.coord_new(root); +paint.fill(img); +img_coord.add_shape(img); + +/* test linear paint and rectangle */ +var rect = mb_rt.rect_new(100, 100, 50, 50, 10, 10); +sys.puts(mb_rt.paint_linear_new); +var paint = mb_rt.paint_linear_new(100, 100, 150, 150); +paint.set_stops([[0, 0, 1, 0, 1], [1, 0, 0, 1, 1]]); +paint.fill(rect); +root.add_shape(rect); + +/* test radial paint and rectangle */ +var rect = mb_rt.rect_new(150, 100, 50, 50, 10, 10); +sys.puts(mb_rt.paint_radial_new); +var paint = mb_rt.paint_radial_new(175, 125, 25); +paint.set_stops([[0, 0, 1, 0, 1], [1, 0, 0, 1, 1]]); +paint.fill(rect); +root.add_shape(rect); + +/* test alpha blending and rectangle */ +var rect = mb_rt.rect_new(40, 40, 100, 100, 10, 10); +sys.puts(mb_rt.paint_color_new); +var paint = mb_rt.paint_color_new(1, 0.5, 0.5, 0.5); +paint.fill(rect); +root.add_shape(rect); + +/* test hide of shapes */ +var sw = 1; +setInterval(function() { + if(sw) { + rect.hide(); + sw = 0; + } else { + rect.show(); + sw = 1; + } + }, 1000); + +/* test hide of coord */ +var cw = 1; +setInterval(function() { + if(sw) { + coord.hide(); + cw = 0; + } else { + coord.show(); + cw = 1; + } + }, 3000); + +/* test removing a coord */ +var rm_coord = mb_rt.coord_new(root); +var rm_rect1 = mb_rt.rect_new(150, 150, 50, 50, 10, 10); +paint.fill(rm_rect1); +rm_coord.add_shape(rm_rect1); +var rm_rect2 = mb_rt.rect_new(100, 150, 50, 50, 10, 10); +paint.fill(rm_rect2); +rm_coord.add_shape(rm_rect2); +setTimeout(function() { + rm_coord.remove(); + mb_rt.redraw_changed(); + mb_rt.flush(); + }, 3000); + +/* test removing a shape */ +setTimeout(function() { + rm_rect1.remove(); + mb_rt.redraw_changed(); + mb_rt.flush(); + }, 2000); + +/* Moving a path */ +sys.puts(mb_rt.path_new); +var path = mb_rt.path_new("m 100,50 L 120,50 L 200,150 L 180,150 z"); +sys.puts(path); +sys.puts(coord.add_shape); +coord.add_shape(path); + +sys.puts(mb_rt.paint_color_new); +var paint = mb_rt.paint_color_new(1, 1, 1, 1); +sys.puts(paint); +paint.stroke(path); + +sys.puts(path.stroke_width); +path.stroke_width = 2; +sys.puts(path.stroke_width); + +var face = mb_rt.font_face_query("courier", 2, 100); +var blks = [[5, face, 20]]; +var stext = mb_rt.stext_new("Hello", 100, 50); +stext.set_style(blks); +paint.fill(stext); +coord.add_shape(stext); + +mb_rt.redraw_all(); +mb_rt.flush(); + +var i = 0; +setInterval(function() { + var deg = (i++) * 0.1; + coord[2] = (i % 40) * 5; + mb_rt.redraw_changed(); + mb_rt.flush(); + }, 20); +setTimeout(function() { sys.puts("timeout"); }, 1000); + +sys.puts(root.mouse_event); +var observer; +/* Mouse button pressed */ +observer = root.mouse_event.add_event_observer(4, function(evt) { + var c = 1 - (i % 40) / 40; + sys.puts(c); + + sys.puts("mouse " + evt.x + " " + evt.y); + sys.puts(c); + sys.puts(paint.set_color); + paint.set_color(c, 1, 1, 1); + mb_rt.redraw_changed(); + mb_rt.flush(); + }); + +var resize_sw = 0; +setInterval(function() { + var sz; + + resize_sw++; + + sz = (resize_sw % 20) - 10; + if(sz < 0) + sz = -sz; + sz = 2 - sz / 10; + + img_coord[0] = sz; + img_coord[4] = sz; + mb_rt.redraw_changed(); + mb_rt.flush(); + }, 50); + +var kbobserver; +/* Keyboard event */ +kbobserver = mb_rt.kbevents.add_event_observer(6, function(evt) { + sys.puts("keycode = " + evt.keycode); + sys.puts("sym = " + evt.sym); + });
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/simple/testimage.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,19 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); + +app = new mbapp.app(); + +coord = app.mb_rt.coord_new(app.mb_rt.root); +data=mbapp.ldr.load("sample.png"); +paint = app.mb_rt.paint_image_new(data); +img = app.mb_rt.image_new(10,10,50,50); +paint.fill(img); +coord.opacity = 0.9; +coord.add_shape(img); + +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/simple/testleak.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,217 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var mbfly = require("mbfly"); +var sys = require("sys"); +var cproc = require("child_process"); + +function testcase1() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var coords = []; + var coord; + var i; + + while(true) { + for(i = 0; i < 200; i++) { + coords.push(mbrt.coord_new(root)); + } + mbrt.redraw_changed(); + mbrt.flush(); + + while(coords.length > 0) { + coord = coords.pop(); + coord.remove(); + } + } +} + +function testcase2() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var coords = []; + var coord; + var i, j; + + while(true) { + for(i = 0; i < 200; i++) { + coords.push(mbrt.coord_new(root)); + for(j = 0; j < 10; j++) + coord = mbrt.coord_new(coords[i]); + } + mbrt.redraw_changed(); + mbrt.flush(); + + while(coords.length > 0) { + coord = coords.pop(); + coord.remove(); + } + } +} + +function testcase3() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var coords = []; + var coord; + var shape; + var i, j; + + while(true) { + for(i = 0; i < 200; i++) { + coords.push(mbrt.coord_new(root)); + for(j = 0; j < 10; j++) { + coord = mbrt.coord_new(coords[i]); + shape = mbrt.rect_new(15, 15, 20, 20, 0, 0); + coord.add_shape(shape); + } + } + mbrt.redraw_changed(); + mbrt.flush(); + + while(coords.length > 0) { + coord = coords.pop(); + coord.remove(); + } + } +} + +function testcase4() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var coords = []; + var coord; + var shape; + var i, j; + + while(true) { + for(i = 0; i < 200; i++) { + coords.push(mbrt.coord_new(root)); + for(j = 0; j < 10; j++) { + coord = mbrt.coord_new(coords[i]); + shape = mbrt.path_new("m 10,10 l 55,27 l -30,-3 z"); + coord.add_shape(shape); + } + } + mbrt.redraw_changed(); + mbrt.flush(); + + while(coords.length > 0) { + coord = coords.pop(); + coord.remove(); + } + } +} + +function testcase5() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var paint; + + while(true) { + paint = mbrt.paint_color_new(0.5, 0.5, 0.5, 1); + } +} + +function testcase6() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var coords = []; + var coord; + var shape; + var paint; + var i, j; + + while(true) { + for(i = 0; i < 200; i++) { + coords.push(mbrt.coord_new(root)); + /* Paint is free, but rdman is dirty */ + paint = mbrt.paint_color_new(0.5, 0.5, 0.5, 1); + for(j = 0; j < 10; j++) { + coord = mbrt.coord_new(coords[i]); + shape = mbrt.rect_new(5, 5, 20, 20, 0, 0); + coord.add_shape(shape); + } + } + mbrt.redraw_changed(); + mbrt.flush(); + + while(coords.length > 0) { + coord = coords.pop(); + coord.remove(); + } + } +} + +function testcase7() { + var mbrt = new mbfly.mb_rt(":32.0", 300, 200); + var root = mbrt.root; + var coords = []; + var coord; + var shape; + var paint; + var i, j; + + while(true) { + for(i = 0; i < 200; i++) { + coords.push(mbrt.coord_new(root)); + for(j = 0; j < 10; j++) { + /* paint is not free, and rdman is dirty */ + paint = mbrt.paint_color_new(0.5, 0.5, 0.5, 1); + coord = mbrt.coord_new(coords[i]); + shape = mbrt.path_new("M 100,100 L 30,30 L 0,30 z"); + coord.add_shape(shape); + paint.stroke(shape); + } + } + mbrt.redraw_changed(); + mbrt.flush(); + + while(coords.length > 0) { + coord = coords.pop(); + coord.remove(); + } + } +} + +cproc.exec("killall -9 Xvfb; Xvfb :32 -screen 0 800x600x24"); +setTimeout(function() { + if(process.argv.length == 1) + testcase1(); + else if(process.argv.length == 3) { + sys.puts("testcase " + process.argv[2]); + switch(process.argv[2]) { + case "1": + testcase1(); + break; + + case "2": + testcase2(); + break; + + case "3": + testcase3(); + break; + + case "4": + testcase4(); + break; + + case "5": + testcase5(); + break; + + case "6": + testcase6(); + break; + + case "7": + testcase7(); + break; + + default: + sys.puts("Usage: node testleak.js [1|2|3...7]"); + } + } else + sys.puts("Usage: node testleak.js [1|2|3...7]"); + cproc.exec("killall -9 Xvfb"); + }, 1500);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/testsvg/svgviewer.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,8 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); + +app = new mbapp.app(); +app.loadSVG("test.svg"); +app.loop();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/testsvg/test.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,538 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:ns0="http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="720" + height="480" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.47 r22583" + sodipodi:docname="test.svg" + version="1.0" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.0347223" + inkscape:cx="151.05815" + inkscape:cy="228.90269" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1347" + inkscape:window-height="894" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="0" /> + <defs + id="defs4"> + <linearGradient + id="linearGradient3183"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3185" /> + <stop + style="stop-color:#505050;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + <inkscape:perspective + id="perspective10" + inkscape:persp3d-origin="804.3173 : 267.38473 : 1" + inkscape:vp_z="1630.7262 : 376.00761 : 1" + inkscape:vp_y="0 : 619.30892 : 0" + inkscape:vp_x="-22.091594 : 376.00761 : 1" + sodipodi:type="inkscape:persp3d" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3183" + id="linearGradient3189" + x1="0" + y1="239.5" + x2="719.99998" + y2="239.5" + gradientUnits="userSpaceOnUse" /> + </defs> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + <ns0:scenes + current="1" /> + </metadata> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Background" + sodipodi:insensitive="true"> + <rect + style="opacity:1;fill:url(#linearGradient3189);fill-opacity:1;stroke:#000000;stroke-width:0.9993065;stroke-opacity:1" + id="rect3181" + width="719.00067" + height="480.0007" + x="0.49965325" + y="-0.50034672" /> + </g> + <g + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <g + transform="translate(144.04213,-2.85715)" + id="item1" + mbname="item1" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="422.51731" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"> + <text + id="text2395" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="422.51731" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"><tspan + mbname="item1text" + y="60" + x="157.14285" + id="tspan2397" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="422.51731" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(144.04213,39.689836)" + id="item2" + mbname="item2" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="379.97032" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"> + <text + id="text2421" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="379.97032" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"><tspan + mbname="item2text" + y="60" + x="157.14285" + id="tspan2423" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="379.97032" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(144.04213,82.236798)" + id="item3" + mbname="item3" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="337.42336" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"> + <text + id="item3text" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="337.42336" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"><tspan + mbname="item3text" + y="60" + x="157.14285" + id="tspan2429" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="337.42336" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(144.04213,124.7838)" + id="item4" + mbname="item4" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="294.87636" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"> + <text + id="item4text" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="294.87636" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"><tspan + mbname="item4text" + y="60" + x="157.14285" + id="tspan2435" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="294.87636" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(144.04213,167.33077)" + id="item5" + mbname="item5" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="252.32939" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"> + <text + id="item5text" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="252.32939" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"><tspan + mbname="item5text" + y="60" + x="157.14285" + id="tspan2441" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="252.32939" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(144.04213,209.87776)" + id="item6" + mbname="item6" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="209.7824" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"> + <text + id="item6text" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="209.7824" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219"><tspan + mbname="item6text" + y="60" + x="157.14285" + id="tspan2447" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="209.7824" + inkscape:bbox-width="74.0625" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(145.21401,252.42474)" + id="item7" + mbname="item7" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="167.23542" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219"> + <text + id="item7text" + y="60" + x="157.14285" + style="font-size:24px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Oblique" + xml:space="preserve" + sodipodi:linespacing="125%" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="167.23542" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219"><tspan + mbname="item7text" + y="60" + x="157.14285" + id="tspan2453" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="167.23542" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(143.79604,294.97172)" + id="item8" + mbname="item8" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="124.68844" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219"> + <text + id="item8text" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + xml:space="preserve" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="124.68844" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219"><tspan + mbname="item8text" + y="60" + x="157.14285" + id="tspan2459" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="124.68844" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <g + transform="translate(143.79604,337.5187)" + id="item9" + mbname="item9" + style="fill-opacity:1" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="82.141456" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219"> + <text + mbname="" + id="text2407" + y="60" + x="157.14285" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + xml:space="preserve" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="82.141456" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219"><tspan + mbname="item9text" + y="60" + x="157.14285" + id="tspan2409" + sodipodi:role="line" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="303.20061" + inkscape:bbox-y="82.141456" + inkscape:bbox-width="65.027344" + inkscape:bbox-height="18.574219">item1</tspan></text> + </g> + <text + id="text2416" + y="44.383541" + x="24.177626" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + mbname="title" + y="44.383541" + x="24.177626" + id="tspan2418" + sodipodi:role="line">Menu test</tspan></text> + </g> + <g + inkscape:groupmode="layer" + id="layer4" + inkscape:label="lightbar"> + <g + mbname="item_lightbar" + transform="matrix(0.9148913,0,0,1,168.41407,93.684101)" + id="item_lightbar" + style="stroke:none" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="164.66374" + inkscape:bbox-y="326.01386" + inkscape:bbox-width="409.10203" + inkscape:bbox-height="33.623234"> + <rect + style="opacity:0.3669725;fill:#001f41;fill-opacity:1;stroke:none" + id="rect3191" + width="442.8623" + height="29.190758" + x="0.19951171" + y="31.140766" + transform="matrix(0.9999958,-0.00289533,0,1,0,0)" + rx="10.000001" + ry="10" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="168.5966" + inkscape:bbox-y="326.01386" + inkscape:bbox-width="405.16917" + inkscape:bbox-height="30.41517" /> + <rect + style="opacity:0.3669725;fill:#eafbf3;fill-opacity:1;stroke:none" + id="rect2405" + width="442.86224" + height="29.190758" + x="-4.099226" + y="27.920256" + transform="matrix(0.9999958,-0.00289533,0,1,0,0)" + rx="10" + ry="10" + inkscape:transform-center-x="0" + inkscape:transform-center-y="0" + inkscape:bbox-x="164.66374" + inkscape:bbox-y="329.22193" + inkscape:bbox-width="405.16911" + inkscape:bbox-height="30.41517" /> + </g> + <image + y="78.788635" + x="34.986565" + id="image3033" + xlink:href="file:logo.png" + height="37" + width="46" /> + <g + sodipodi:type="inkscape:box3d" + style="fill:none;stroke:none" + id="g2953" + inkscape:perspectiveID="#perspective10" + inkscape:corner0="11.418244 : -1.091331 : 0 : 1" + inkscape:corner7="6.2635014 : -2.542367 : 0.25 : 1"> + <path + sodipodi:type="inkscape:box3dside" + id="path2963" + style="fill:#afafde;fill-rule:evenodd;stroke:none" + inkscape:box3dsidetype="13" + d="M 44.456373,239.52954 91.68396,335.71719 142.89318,328.00691 75.760432,236.8548 z" /> + <path + sodipodi:type="inkscape:box3dside" + id="path2955" + style="fill:#353564;fill-rule:evenodd;stroke:none" + inkscape:box3dsidetype="6" + d="m 44.456373,167.16508 0,72.36446 31.304059,-2.67474 0,-70.93639 z" /> + <path + sodipodi:type="inkscape:box3dside" + id="path2965" + style="fill:#e9e9ff;fill-rule:evenodd;stroke:none" + inkscape:box3dsidetype="11" + d="m 75.760432,165.91841 67.132748,42.48521 0,119.60329 -67.132748,-91.15211 z" /> + <path + sodipodi:type="inkscape:box3dside" + id="path2957" + style="fill:#4d4d9f;fill-rule:evenodd;stroke:none" + inkscape:box3dsidetype="5" + d="m 44.456373,167.16508 47.227587,44.83223 51.20922,-3.59369 -67.132748,-42.48521 z" /> + <path + sodipodi:type="inkscape:box3dside" + id="path2961" + style="fill:#d7d7ff;fill-rule:evenodd;stroke:none" + inkscape:box3dsidetype="14" + d="m 91.68396,211.99731 0,123.71988 51.20922,-7.71028 0,-119.60329 z" /> + <path + sodipodi:type="inkscape:box3dside" + id="path2959" + style="fill:#8686bf;fill-rule:evenodd;stroke:none" + inkscape:box3dsidetype="3" + d="m 44.456373,167.16508 47.227587,44.83223 0,123.71988 -47.227587,-96.18765 z" /> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/examples/testsvg/testsvg.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,53 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var svg = require("svg"); +var mbapp = require("mbapp"); +var sys=require("sys"); +var animate=require("animate"); +var fs = require("fs"); + +app = new mbapp.app(); +app.loadSVG("test.svg"); +lightbar = app.get("item_lightbar"); +item=1; +var target = app.get("item" + item); +lightbar.center.move_pnt(target.center); + +app.files=fs.readdirSync("/tmp/"); +for(i=1;i<10;i++) { + var o = app.get("item"+i+"text"); + o.set_text(app.files[i]); +} + + + + +app.addKeyListener(mbapp.KEY_UP, function() { + item = item - 1; + if (item == 0) + item = 1; + else { + var target = app.get("item"+item); + var shx = target.center.x - lightbar.center.x; + var shy = target.center.y - lightbar.center.y; + var action = new animate.shift(app, lightbar, shx, shy); + var an = new animate.linear(action, 0, 0.3); + an.start(); + } +}); + +app.addKeyListener(mbapp.KEY_DOWN, function() { + item = item + 1; + if (item == 10) { + item = 9; + } else { + var target = app.get("item"+item); + var shx = target.center.x - lightbar.center.x; + var shy = target.center.y - lightbar.center.y; + var action = new animate.shift(app, lightbar, shx, shy); + var an = new animate.linear(action, 0, 0.3); + an.start(); + } +}); + +app.loop();
--- a/nodejs/font.cc Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/font.cc Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <v8.h> #include "mbfly_njs.h" @@ -62,10 +64,10 @@ temp = FunctionTemplate::New(); temp->SetClassName(String::New("font_face")); - + inst_temp = temp->InstanceTemplate(); inst_temp->SetInternalFieldCount(1); - + xnjsmb_font_face_temp = Persistent<FunctionTemplate>::New(temp); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/image_ldr.cc Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,149 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +/*! \file + * This file implements Javascript binding for img_ldr_t of MadButterfly. + */ +#include <v8.h> + +extern "C" { +#include "mb.h" +} + +#include "mbfly_njs.h" + +using namespace v8; + +#ifndef ASSERT +#define ASSERT(x) +#endif + +/*! \defgroup xnjsmb_img_ldr_js Javascript binding for image loader. + * \ingroup xnjsmb + * + * @{ + */ + +static Persistent<ObjectTemplate> img_data_temp; + +/*! \brief load() method of img_ldr Javascript objects. + */ +static Handle<Value> +xnjsmb_img_ldr_load(const Arguments &args) { + HandleScope scope; + int argc = args.Length(); + Handle<Object> self = args.This(); + char *img_id; + mb_img_ldr_t *img_ldr; + mb_img_data_t *img_data; + Handle<Object> img_data_obj; + + if(argc != 1) + THROW("Invalid number of arguments (!= 1)"); + if(!args[0]->IsString()) + THROW("Invalid argument type"); + + String::Utf8Value img_id_utf8(args[0]->ToString()); + img_id = *img_id_utf8; + img_ldr = (mb_img_ldr_t *)UNWRAP(self); + + img_data_obj = img_data_temp->NewInstance(); + ASSERT(img_data_obj); + + img_data = MB_IMG_LDR_LOAD(img_ldr, img_id); + if(img_data == NULL) + THROW("Can not load an image"); + WRAP(img_data_obj, img_data); + + scope.Close(img_data_obj); + + return img_data_obj; +} + +/*! \brief Constructor function of img_ldr Javascript objects. + */ +static Handle<Value> +xnjsmb_img_ldr(const Arguments &args) { + HandleScope scope; + int argc = args.Length(); + Handle<Object> self = args.This(); + char *path; + mb_img_ldr_t *img_ldr; + + if(argc != 1) + THROW("Invalid number of arguments (!= 1)"); + if(!args[0]->IsString()) + THROW("Invalid argument type"); + + String::Utf8Value pathutf8(args[0]->ToString()); + path = *pathutf8; + + img_ldr = simple_mb_img_ldr_new(path); + if(img_ldr == NULL) + THROW("Can not create an image loader"); + WRAP(self, img_ldr); + + return Null(); +} + +static Persistent<FunctionTemplate> xnjsmb_img_ldr_temp; + +static Handle<Value> +xnjsmb_img_ldr_new(const Arguments &args) { + HandleScope scope; + int argc = args.Length(); + Handle<Value> il_args[1]; + Handle<Object> img_ldr; + Handle<Function> func; + + if(argc != 1) + THROW("Invalid number of arguments (!= 1)"); + if(!args[0]->IsString()) + THROW("Invalid argument type"); + + il_args[0] = args[0]; + func = xnjsmb_img_ldr_temp->GetFunction(); + img_ldr = func->NewInstance(1, il_args); + + scope.Close(img_ldr); + return img_ldr; +} + +/* @} */ + +/*! \brief Initialize image loader. + * + * This function is called by init() in mbfly_njs.cc when the module + * being loaded. + */ +void +xnjsmb_img_ldr_init_mb_rt_temp(Handle<Object> rt_temp) { + HandleScope scope; + Handle<FunctionTemplate> img_ldr_temp; + Handle<FunctionTemplate> img_ldr_new_temp; + Handle<ObjectTemplate> ldr_inst_temp; + Handle<ObjectTemplate> ldr_proto_temp; + Handle<FunctionTemplate> img_ldr_load_temp; + Handle<ObjectTemplate> _img_data_temp; + + /* Setup object template for img_data_t object for Javascript */ + _img_data_temp = ObjectTemplate::New(); + _img_data_temp->SetInternalFieldCount(1); + img_data_temp = Persistent<ObjectTemplate>::New(_img_data_temp); + + /* Setup img_ldr class */ + img_ldr_temp = FunctionTemplate::New(xnjsmb_img_ldr); + img_ldr_temp->SetClassName(String::New("img_ldr")); + ldr_inst_temp = img_ldr_temp->InstanceTemplate(); + ldr_inst_temp->SetInternalFieldCount(1); + + /* Set method load() for img_ldr */ + ldr_proto_temp = img_ldr_temp->PrototypeTemplate(); + img_ldr_load_temp = FunctionTemplate::New(xnjsmb_img_ldr_load); + SET(ldr_proto_temp, "load", img_ldr_load_temp); + + xnjsmb_img_ldr_temp = Persistent<FunctionTemplate>::New(img_ldr_temp); + + /* Initialize img_ldr_new function */ + img_ldr_new_temp = FunctionTemplate::New(xnjsmb_img_ldr_new); + SET(rt_temp, "img_ldr_new", img_ldr_new_temp->GetFunction()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/mbapp.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,224 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var mbfly = require("mbfly"); +var svg = require("./svg"); +var sys = require("sys"); +var ldr = mbfly.img_ldr_new("."); + +function _reverse(m1) { + var rev = new Array(1, 0, 0, 0, 1, 0); + var m = new Array(m1[0], m1[1], m1[2], m1[3], m1[4], m1[5]); + + rev[3] = -m[3] / m[0]; + m[3] = 0; + m[4] += rev[3] * m[1]; + m[5] += rev[3] * m[2]; + + rev[1] = -m[1] / m[4]; + rev[0] += rev[1] * rev[3]; + m[1] = 0; + m[2] += rev[1] * m[5]; + + rev[2] = -m[2]; + rev[5] = -m[5]; + + rev[0] = rev[0] / m[0]; + rev[1] = rev[1] / m[0]; + rev[2] = rev[2] / m[0]; + + rev[3] = rev[3] / m[4]; + rev[4] = rev[4] / m[4]; + rev[5] = rev[5] / m[4]; + + return rev; +} + +function _decorate_mb_rt(mb_rt) { + var coord; + + mb_rt._mbapp_saved_coord_new = mb_rt.coord_new; + mb_rt.coord_new = function(parent) { + var coord; + + coord = this._mbapp_saved_coord_new(parent); + coord.type = "coord"; + coord.children = []; + coord._mbapp_saved_mtx = [coord[0], coord[1], coord[2], + coord[3], coord[4], coord[5]]; + coord._mbapp_saved_rev_mtx = _reverse(coord._mbapp_saved_mtx); + coord.parent = parent; + coord._mbapp_saved_add_shape = coord.add_shape; + coord.add_shape = function(shape) { + var coord; + + this._mbapp_saved_add_shape(shape); + shape.parent = this; + this.children.push(shape); + } + + parent.children.push(coord); + + return coord; + }; + + /* + * Decorate root coord + */ + coord = mb_rt.root; + coord.type = "coord"; + coord.children = []; + coord._mbapp_saved_mtx = [coord[0], coord[1], coord[2], + coord[3], coord[4], coord[5]]; + coord._mbapp_saved_rev_mtx = _reverse(coord._mbapp_saved_mtx); + coord._mbapp_saved_add_shape = coord.add_shape; + coord.add_shape = function(shape) { + var coord; + + this._mbapp_saved_add_shape(shape); + shape.parent = this; + } +} + +app=function(display, w, h) { + var self = this; + var mb_rt; + + if(typeof display == "undefined") + display = ":0.0"; + if(typeof w == "undefined") + w = 720; + if(typeof h == "undefined") + h = 480; + + mb_rt = this.mb_rt = new mbfly.mb_rt(display, w, h); + _decorate_mb_rt(mb_rt); + var background = mb_rt.rect_new(0, 0, 720, 480, 0, 0); + var paint = mb_rt.paint_color_new(1, 1, 1, 1); + paint.fill(background); + mb_rt.root.add_shape(background); + + this.mb_rt.kbevents.add_event_observer(exports.EVT_KB_PRESS, function(evt) { self.KeyPress(evt);}); + this.keymap={}; + this.onKeyPress = null; + this.svg = new svg.loadSVG(this.mb_rt,this.mb_rt.root,null); +} +app.prototype.loadSVG=function(fname) { + this.svg.load(this.mb_rt,this.mb_rt.root,fname) +} + +app.prototype.KeyPress = function(evt) { + if (this.onKeyPress) this.onKeyPress(evt.sym); + if (evt.sym in this.keymap) { + this.keymap[evt.sym](); + } +} + +app.prototype.loop=function() { + this.mb_rt.redraw_all(); + this.mb_rt.flush(); +} +app.prototype.update=function() { + this.mb_rt.redraw_all(); + this.mb_rt.flush(); +} +app.prototype.get=function(name) { + return this.mb_rt.mbnames[name]; +} +app.prototype.addKeyboardListener=function(type,f) { + return this.mb_rt.kbevents.add_event_observer(type,f); +} +app.prototype.refresh=function() { + this.mb_rt.redraw_changed(); + this.mb_rt.flush(); +} +app.prototype.dump=function() { + sys.puts(this.onKeyPress); +} + +app.prototype.addKeyListener=function(key,f) { + if (typeof(key) == 'number') + this.keymap[key] = f; + else { + for(k in key) { + this.keymap[k] = f; + } + } +} + + +app.prototype.changeScene=function(s) { + var nth; + if (typeof(s)=='number') { + var i; + nth = s; + } else { + nth = this.svg.getFrameNumber(s); + if (nth == -1) return; + } + var scenes = this.svg.scenes; + for(i=0;i<scenes.length;i++) { + try { + if (nth >=scenes[i].start && nth <=scenes[i].end) { + this.get(scenes[i].ref).show(); + } else { + this.get(scenes[i].ref).hide(); + } + } catch(e) { + sys.puts(e); + sys.puts(scenes[i].ref); + } + } +} +app.prototype.addSceneListener=function(n, cb) { + sys.puts("This is not implemented yet") +} + +var app_with_win = function(display, win) { + var self = this; + var mb_rt; + var background; + var paint; + + if(typeof display == "undefined" || typeof win == "undefined") + throw "Invalid argument"; + + mb_rt = this.mb_rt = new mbfly.mb_rt_with_win(display, win); + _decorate_mb_rt(mb_rt); + background = mb_rt.rect_new(0, 0, 720, 480, 0, 0); + paint = mb_rt.paint_color_new(1, 1, 1, 1); + paint.fill(background); + mb_rt.root.add_shape(background); + + this.mb_rt.kbevents. + add_event_observer(exports.EVT_KB_PRESS, + function(evt) { self.KeyPress(evt); }); + this.keymap = {}; + this.onKeyPress = null; +} + +app_with_win.prototype = app.prototype; + +exports.app=app; +exports.app_with_win = app_with_win; + +// Put all key definition here +exports.KEY_LEFT = 0xff51; +exports.KEY_UP = 0xff52; +exports.KEY_RIGHT = 0xff53; +exports.KEY_DOWN = 0xff54; +exports.KEY_ENTER = 0xff0d; +exports.EVT_ANY=0; +exports.EVT_MOUSE_OVER=1; +exports.EVT_MOUSE_OUT=2; +exports.EVT_MOUSE_MOVE=3; +exports.EVT_MOUSE_BUT_PRESS4; +exports.EVT_MOUSE_BUT_RELEASE=5 +exports.EVT_KB_PRESS=6; +exports.EVT_KB_RELEASE=7; +exports.EVT_PROGM_COMPLETE=8; +exports.EVT_RDMAN_REDRAW=9; +exports.EVT_MONITOR_ADD=10; +exports.EVT_MONITOR_REMOVE=11; +exports.EVT_MONITOR_FREE=12; +exports.EVT_MOUSE_MOVE_RAW=13; +exports.ldr = ldr;
--- a/nodejs/mbfly_njs.cc Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/mbfly_njs.cc Wed Dec 01 12:25:56 2010 +0800 @@ -1,95 +1,136 @@ +// -*- 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 <v8.h> extern "C" { -#include "X_supp_njs.h" +#include "njs_mb_supp.h" } #include "mbfly_njs.h" using namespace v8; +/*! \defgroup xnjsmb_mb_rt JS binding for MB runtime. + * \ingroup xnjsmb + * + * @{ + */ +static coord_t * +xnjsmb_coord_new(njs_runtime_t *rt, coord_t *parent, const char **err) { + coord_t *coord; + redraw_man_t *rdman; + + rdman = njs_mb_rdman(rt); + coord = rdman_coord_new(rdman, parent); + if(coord == NULL) { + *err = "Can not allocate a redraw_man_t"; + return NULL; + } + rdman_coord_changed(rdman, coord); + + return coord; +} + +static void +xnjsmb_mb_rt_objs_mod(Handle<Object> mbrt, Handle<Value> ret) { + Handle<Object> ret_obj = ret->ToObject(); + + SET(ret_obj, "mbrt", mbrt); +} + +#define xnjsmb_auto_coord_new export_xnjsmb_auto_coord_new + +static void +xnjsmb_redraw_changed(njs_runtime_t *rt) { + redraw_man_t *rdman; + + rdman = njs_mb_rdman(rt); + rdman_redraw_changed(rdman); +} + +static void +xnjsmb_redraw_all(njs_runtime_t *rt) { + redraw_man_t *rdman; + + rdman = njs_mb_rdman(rt); + rdman_redraw_all(rdman); +} + +static void +xnjsmb_handle_single_event(njs_runtime_t *rt, void *evt) { + njs_mb_handle_single_event(rt, evt); +} + +static void +xnjsmb_no_more_event(njs_runtime_t *rt) { + njs_mb_no_more_event(rt); +} + +static njs_runtime_t * +_njs_mb_new(Handle<Object> self, char *display_name, + int width, int height) { + njs_runtime_t *obj; + subject_t *subject; + Handle<Value> subject_o; + + obj = njs_mb_new(display_name, width, height); + WRAP(self, obj); /* mkroot need a wrapped object, but + * it is wrapped after returning of + * this function. So, we wrap it + * here. */ + xnjsmb_coord_mkroot(self); + + subject = njs_mb_kbevents(obj); + subject_o = export_xnjsmb_auto_subject_new(subject); + SET(self, "kbevents", subject_o); + + return obj; +} + +static njs_runtime_t * +_njs_mb_new_with_win(Handle<Object> self, void *display, + long win) { + njs_runtime_t *obj; + subject_t *subject; + Handle<Value> subject_o; + + obj = njs_mb_new_with_win(display, win); + WRAP(self, obj); /* mkroot need a wrapped object, but + * it is wrapped after returning of + * this function. So, we wrap it + * here. */ + xnjsmb_coord_mkroot(self); + + subject = njs_mb_kbevents(obj); + subject_o = export_xnjsmb_auto_subject_new(subject); + SET(self, "kbevents", subject_o); + + return obj; +} + /*! \defgroup njs_template_cb Callback functions for v8 engine and nodejs. * * @{ */ -/*! \brief to Create a njs runtime object for MadButterfly. - * - * Three arguments are requried. They are - * - display name, - * - width, and - * - height. +/* + * Redirect following function to respective exported version from + * other modules. Since gen_v8_binding.m4 make all functions static, + * we need a exported version to call them indrectly from other + * modules. */ -static Handle<Value> -xnjsmb_new(const Arguments &args) { - HandleScope scope; - int argc; - Handle<Value> exc; - njs_runtime_t *rt; - char *display_name; - int width, height; - Handle<Object> self; - - argc = args.Length(); - if(argc != 3) { - exc = Exception::Error(String::New("Need 3 arguments.")); - return ThrowException(exc); - } - - if(!args[0]->IsString() || !args[1]->IsInt32() || !args[2]->IsInt32()) { - exc = Exception::Error(String::New("Invalid argument type.")); - return ThrowException(exc); - } - - String::Utf8Value disp_utf8(args[0]->ToString()); - display_name = *disp_utf8; - width = args[1]->Int32Value(); - height = args[2]->Int32Value(); - rt = X_njs_MB_new(display_name, width, height); +#define xnjsmb_auto_path_new export_xnjsmb_auto_path_new +#define xnjsmb_auto_stext_new export_xnjsmb_auto_stext_new +#define xnjsmb_auto_image_new export_xnjsmb_auto_image_new +#define xnjsmb_auto_rect_new export_xnjsmb_auto_rect_new +#define xnjsmb_auto_paint_color_new export_xnjsmb_auto_paint_color_new +#define xnjsmb_auto_paint_image_new export_xnjsmb_auto_paint_image_new +#define xnjsmb_auto_paint_linear_new export_xnjsmb_auto_paint_linear_new +#define xnjsmb_auto_paint_radial_new export_xnjsmb_auto_paint_radial_new - self = args.This(); - WRAP(self, rt); - xnjsmb_coord_mkroot(self); - - X_njs_MB_init_handle_connection(rt); - - return Null(); -} - -static Handle<Value> -xnjsmb_handle_connection(const Arguments &args) { -} - -static Handle<Value> -xnjsmb_rt_redraw_changed(const Arguments &args) { - Handle<Object> self = args.This(); - njs_runtime_t *rt; - redraw_man_t *rdman; - - rdman = xnjsmb_rt_rdman(self); - rdman_redraw_changed(rdman); - - rt = (njs_runtime_t *)UNWRAP(self); - X_njs_MB_flush(rt); - - return Null(); -} - -static Handle<Value> -xnjsmb_rt_redraw_all(const Arguments &args) { - Handle<Object> self = args.This(); - njs_runtime_t *rt; - redraw_man_t *rdman; - - rdman = xnjsmb_rt_rdman(self); - rdman_redraw_all(rdman); - - rt = (njs_runtime_t *)UNWRAP(self); - X_njs_MB_flush(rt); - - return Null(); -} +#include "mbfly_njs-inc.h" /* @} */ @@ -102,8 +143,8 @@ redraw_man_t *rdman; rt = (njs_runtime_t *)UNWRAP(mbrt); - rdman = X_njs_MB_rdman(rt); - + rdman = njs_mb_rdman(rt); + return rdman; } @@ -126,28 +167,25 @@ /* * Initialize template for MadButterfly runtime objects. */ - mb_rt_func = FunctionTemplate::New(xnjsmb_new); - mb_rt_func->SetClassName(String::New("mb_rt")); - - rt_instance_temp = mb_rt_func->InstanceTemplate(); - rt_instance_temp->SetInternalFieldCount(1); - - rt_proto_temp = mb_rt_func->PrototypeTemplate(); - func = FunctionTemplate::New(xnjsmb_coord_new); - SET(rt_proto_temp, "coord_new", func); - - func = FunctionTemplate::New(xnjsmb_rt_redraw_changed); - SET(rt_proto_temp, "redraw_changed", func); - - func = FunctionTemplate::New(xnjsmb_rt_redraw_all); - SET(rt_proto_temp, "redraw_all", func); + xnjsmb_auto_mb_rt_init(); + xnjsmb_auto_mb_rt_display_init(); + xnjsmb_auto_mb_rt_with_win_init(); + njs_mb_reg_timer_man(); + njs_mb_reg_IO_man(); /* * Add properties to mb_rt templates for other modules. */ - xnjsmb_shapes_init_mb_rt_temp(mb_rt_func); - xnjsmb_paints_init_mb_rt_temp(mb_rt_func); - xnjsmb_font_init_mb_rt_temp(mb_rt_func); - - target->Set(String::New("mb_rt"), mb_rt_func->GetFunction()); + xnjsmb_shapes_init_mb_rt_temp(xnjsmb_auto_mb_rt_temp); + xnjsmb_paints_init_mb_rt_temp(xnjsmb_auto_mb_rt_temp); + xnjsmb_font_init_mb_rt_temp(xnjsmb_auto_mb_rt_temp); + xnjsmb_img_ldr_init_mb_rt_temp(target); + xnjsmb_observer_init(); + + target->Set(String::New("mb_rt"), + xnjsmb_auto_mb_rt_temp->GetFunction()); + target->Set(String::New("mb_rt_with_win"), + xnjsmb_auto_mb_rt_with_win_temp->GetFunction()); } + +/* @} */
--- a/nodejs/mbfly_njs.h Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/mbfly_njs.h Wed Dec 01 12:25:56 2010 +0800 @@ -1,9 +1,12 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #ifndef __MBFLY_NJS_H_ #define __MBFLY_NJS_H_ #include <v8.h> extern "C" { #include <mb.h> +#include "njs_mb_supp.h" } #define THROW(x) \ @@ -12,6 +15,13 @@ exc = v8::Exception::Error(v8::String::New(x)); \ return v8::ThrowException(exc); \ } while(0) +#define THROW_noret(x) \ + do { \ + v8::Handle<v8::Value> exc; \ + exc = v8::Exception::Error(v8::String::New(x)); \ + v8::ThrowException(exc); \ + return; \ + } while(0) #define UNWRAP(o) v8::External::Unwrap((o)->GetInternalField(0)) #define WRAP(o, v) (o)->SetInternalField(0, v8::External::Wrap(v)) #define SET(o, n, v) (o)->Set(v8::String::New(n), v) @@ -20,16 +30,51 @@ redraw_man_t *xnjsmb_rt_rdman(v8::Handle<v8::Object> mbrt); /* From coord.cc */ -v8::Handle<v8::Value> xnjsmb_coord_new(const v8::Arguments &args); void xnjsmb_coord_mkroot(v8::Handle<v8::Object> js_rt); +v8::Handle<v8::Value> export_xnjsmb_auto_coord_new(coord_t *coord); /* From shapes.cc */ void xnjsmb_shapes_init_mb_rt_temp(v8::Handle<v8::FunctionTemplate> rt_temp); +shape_t *xnjsmb_path_new(njs_runtime_t *rt, const char *d); +shape_t *xnjsmb_stext_new(njs_runtime_t *rt, const char *txt, + float x, float y); +shape_t *xnjsmb_image_new(njs_runtime_t *rt, float x, float y, + float w, float h); +shape_t *xnjsmb_rect_new(njs_runtime_t *rt, float x, float y, + float w, float h, + float rx, float ry, const char **err); +v8::Handle<v8::Value> export_xnjsmb_auto_path_new(shape_t *sh); +v8::Handle<v8::Value> export_xnjsmb_auto_stext_new(shape_t *sh); +v8::Handle<v8::Value> export_xnjsmb_auto_image_new(shape_t *sh); +v8::Handle<v8::Value> export_xnjsmb_auto_rect_new(shape_t *sh); /* From paints.cc */ void xnjsmb_paints_init_mb_rt_temp(v8::Handle<v8::FunctionTemplate> rt_temp); +paint_t *xnjsmb_paint_color_new(njs_runtime_t *rt, + float r, float g, float b, float a, + const char **err); +paint_t *xnjsmb_paint_image_new(njs_runtime_t *rt, mb_img_data_t *img, + const char **err); +paint_t *xnjsmb_paint_linear_new(njs_runtime_t *rt, + float x1, float y1, float x2, float y2, + const char **err); +paint_t *xnjsmb_paint_radial_new(njs_runtime_t *rt, + float cx, float cy, float r, + const char **err); +v8::Handle<v8::Value> export_xnjsmb_auto_paint_color_new(paint_t *paint); +v8::Handle<v8::Value> export_xnjsmb_auto_paint_image_new(paint_t *paint); +v8::Handle<v8::Value> export_xnjsmb_auto_paint_linear_new(paint_t *sh); +v8::Handle<v8::Value> export_xnjsmb_auto_paint_radial_new(paint_t *sh); /* From font.cc */ void xnjsmb_font_init_mb_rt_temp(v8::Handle<v8::FunctionTemplate> mb_rt_temp); +/* From image_ldr.cc */ +void +xnjsmb_img_ldr_init_mb_rt_temp(v8::Handle<v8::Object> mb_rt_temp); + +/* From observer.cc */ +v8::Handle<v8::Value> export_xnjsmb_auto_subject_new(subject_t *subject); +void xnjsmb_observer_init(void); + #endif /* __MBFLY_NJS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/mbfly_njs.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,65 @@ +dnl +define([PROJ_PREFIX], [xnjsmb_auto_])dnl +dnl +STRUCT([mb_rt], [njs_runtime_t], [], + [METHOD([coord_new], [xnjsmb_coord_new], + (OBJ([parent], [coord], [coord_t]), ERR), 1, + [OBJ([coord], [coord_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([redraw_changed], [xnjsmb_redraw_changed], (), 0, []), + METHOD([redraw_all], [xnjsmb_redraw_all], (), 0, []), + METHOD([flush], [njs_mb_flush], (), 0, []), + METHOD([path_new], [xnjsmb_path_new], (STR(txt)), 1, + [OBJ([path], [shape_t])], (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([stext_new], [xnjsmb_stext_new], + (STR(txt), NUMBER(x), NUMBER(y)), 3, + [OBJ([stext], [shape_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([image_new], [xnjsmb_image_new], + (NUMBER(x), NUMBER(y), NUMBER(w), NUMBER(h)), 4, + [OBJ([image], [shape_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([rect_new], [xnjsmb_rect_new], + (NUMBER(x), NUMBER(y), NUMBER(w), NUMBER(h), + NUMBER(rx), NUMBER(ry), ERR), 6, + [OBJ([rect], [shape_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([paint_color_new], [xnjsmb_paint_color_new], + (NUMBER(r), NUMBER(g), NUMBER(b), NUMBER(a), ERR), 4, + [OBJ([paint_color], [paint_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([paint_image_new], [xnjsmb_paint_image_new], + (OBJ([img], [img_data], [mb_img_data_t]), ERR), 1, + [OBJ([paint_image], [paint_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([paint_linear_new], [xnjsmb_paint_linear_new], + (NUMBER(x1), NUMBER(y1), NUMBER(x2), NUMBER(y2), ERR), 4, + [OBJ([paint_linear], [paint_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([paint_radial_new], [xnjsmb_paint_radial_new], + (NUMBER(cx), NUMBER(cy), NUMBER(r), ERR), 3, + [OBJ([paint_radial], [paint_t])], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([handle_single_event], [xnjsmb_handle_single_event], + (OBJ([evt], [event], [void])), 1, []), + METHOD([no_more_event], [xnjsmb_no_more_event], + (), 0, [])], + ((CTOR, ([_njs_mb_new], (SELF, STR(display_name), INT(width), INT(height)), 3)))dnl +) +dnl +dnl +dnl +STRUCT([mb_rt_display], [void], [], + [], + ())dnl +dnl +dnl Function to create mb_rt for an existed window. +dnl +STRUCT([mb_rt_with_win], [njs_runtime_t], [], + [], + ((CTOR, ([_njs_mb_new_with_win],dnl + (SELF, OBJ([display], [mb_rt_display], [void]),dnl + INT([window])),dnl + 2)),dnl + ([INHERIT], [mb_rt]))dnl +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/njs_mb_supp.c Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,317 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +/*! \brief Implement X11 backend for nodejs plugin. + * + * Since nodejs use libev to handle event loops, part of X11 backend + * code can not be used directly. The part of code should be rewrote. + * The part is about + */ +#include <stdio.h> +#include <string.h> +#include <ev.h> +#include "mb_tools.h" +#include <mb_backend.h> +#include "njs_mb_supp.h" + +#ifndef ASSERT +#define ASSERT(x) +#endif + +#define OK 0 +#define ERR -1 + + +/*! \defgroup njs_timer_man Timer manager for nodejs. + * @{ + */ +struct _njs_timer_timeout { + ev_timer tmwatcher; + mb_timer_cb_t cb; + mb_timeval_t *timeout; + void *data; +}; + +static int njs_timer_man_timeout(mb_timer_man_t *tm_man, + mb_timeval_t *tm_out, + mb_timer_cb_t cb, void *data); +static void njs_timer_man_remove(mb_timer_man_t *tm_man, int tm_hdl); +static mb_timer_man_t *njs_timer_man_new(void); +static void njs_timer_man_free(mb_timer_man_t *timer_man); + +static mb_timer_man_t njs_timer_man = { + njs_timer_man_timeout, + njs_timer_man_remove +}; + +static mb_timer_factory_t njs_timer_factory = { + njs_timer_man_new, + njs_timer_man_free +}; + +static void +njs_timer_man_cb(EV_P_ ev_timer *tmwatcher, int revent) { + struct _njs_timer_timeout *timer_timeout = + MEM2OBJ(tmwatcher, struct _njs_timer_timeout, tmwatcher); + mb_timeval_t now; + + get_now(&now); + timer_timeout->cb((int)timer_timeout, timer_timeout->timeout, &now, + timer_timeout->data); +} + +static int +njs_timer_man_timeout(mb_timer_man_t *tm_man, + mb_timeval_t *timeout, + mb_timer_cb_t cb, void *data) { + struct _njs_timer_timeout *timer_timeout; + mb_timeval_t now, timeout_diff; + ev_tstamp timeout_stamp; + + timer_timeout = O_ALLOC(struct _njs_timer_timeout); + if(timer_timeout == NULL) + return ERR; + + timer_timeout->cb = cb; + timer_timeout->timeout = timeout; + + get_now(&now); + + memcpy(&timeout_diff, timeout, sizeof(mb_timeval_t)); + MB_TIMEVAL_DIFF(&timeout_diff, &now); + timeout_stamp = (ev_tstamp)MB_TIMEVAL_SEC(&timeout_diff) + + (ev_tstamp)MB_TIMEVAL_USEC(&timeout_diff) / 1000000; + ev_timer_init(&timer_timeout->tmwatcher, njs_timer_man_cb, + timeout_stamp, 0); + ev_timer_start(&timer_timeout->tmwatcher); + + return (int)timer_timeout; +} + +static void +njs_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl) { + struct _njs_timer_timeout *timer_timeout = + (struct _njs_timer_timeout *)tm_hdl; + + ev_timer_stop(&timer_timeout->tmwatcher); + free(timer_timeout); +} + +static mb_timer_man_t * +njs_timer_man_new(void) { + return &njs_timer_man; +} + +static void +njs_timer_man_free(mb_timer_man_t *timer_man) { +} + +void +njs_mb_reg_timer_man(void) { + mb_reg_timer_factory(&njs_timer_factory); +} + +/* @} */ + + +/*! \defgroup njs_io_man IO manager for nodejs. + * @{ + */ +struct _njs_io_reg { + ev_io iowatcher; + int fd; + mb_IO_cb_t cb; + void *data; +}; + +static int njs_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data); +static void njs_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl); +static mb_IO_man_t *njs_io_man_new(void); +static void njs_io_man_free(mb_IO_man_t *io_man); + +static mb_IO_man_t njs_io_man = { + njs_io_man_reg, + njs_io_man_unreg +}; + +/*! \brief IO factory to integrate MadButterfly to event loop of nodejs. + */ +static mb_IO_factory_t njs_io_factory = { + njs_io_man_new, + njs_io_man_free +}; + +/*! \brief Bridge libev callback to IO manager callback. + */ +static void +njs_io_man_cb(EV_P_ ev_io *iowatcher, int revent) { + struct _njs_io_reg *io_reg = + MEM2OBJ(iowatcher, struct _njs_io_reg, iowatcher); + MB_IO_TYPE type; + + switch(revent & (EV_READ | EV_WRITE)) { + case EV_READ: + type = MB_IO_R; + break; + case EV_WRITE: + type = MB_IO_W; + break; + case EV_READ | EV_WRITE: + type = MB_IO_RW; + break; + } + + io_reg->cb((int)io_reg, io_reg->fd, type, io_reg->data); +} + +static int +njs_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) { + int _type; + struct _njs_io_reg *io_reg; + + if(type == MB_IO_R) + _type = EV_READ; + else if(type == MB_IO_W) + _type = EV_WRITE; + else if(type == MB_IO_RW) + _type = EV_READ | EV_WRITE; + else + return ERR; + + io_reg = O_ALLOC(struct _njs_io_reg); + if(io_reg == NULL) + return ERR; + + io_reg->fd = fd; + io_reg->cb = cb; + io_reg->data = data; + + ev_io_init(&io_reg->iowatcher, njs_io_man_cb, fd, _type); + ev_io_start(&io_reg->iowatcher); + + return (int)io_reg; +} + +static void +njs_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) { + struct _njs_io_reg *io_reg = (struct _njs_io_reg *)io_hdl; + + ev_io_stop(&io_reg->iowatcher); + free(io_reg); +} + +static mb_IO_man_t * +njs_io_man_new(void) { + return &njs_io_man; +} + +static void +njs_io_man_free(mb_IO_man_t *io_man) { +} + +/*! \brief Register an IO factory with MadButterfly backend. + */ +void +njs_mb_reg_IO_man(void) { + mb_reg_IO_factory(&njs_io_factory); +} + +/* @} */ + +/*! \brief Free njs_runtime_t. + */ +void +njs_mb_free(njs_runtime_t *rt) { + /*! + * TODO: Release all IO and timer request. + */ + mb_runtime_free(rt->mb_rt); + free(rt); +} + +/*! \brief Free njs_runtime_t. + */ +void +njs_mb_free_keep_win(njs_runtime_t *rt) { + /* + * TODO: Release all IO and timer request. + */ + mb_runtime_free_keep_win(rt->mb_rt); + free(rt); +} + +int +njs_mb_flush(njs_runtime_t *rt) { + mb_rt_t *mb_rt = rt->mb_rt; + int r; + + r = mb_runtime_flush(mb_rt); + return r; +} + +njs_runtime_t * +njs_mb_new(char *display_name, int w, int h) { + njs_runtime_t *rt; + mb_rt_t *mb_rt; + + rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); + ASSERT(rt != NULL); + + mb_rt = mb_runtime_new(display_name, w, h); + + rt->mb_rt = mb_rt; + + return rt; +} + +/*! \brief Create a njs_runtime_t for an existed window. + * + * The njs_runtime_t created by this function must be free by + * njs_mb_free_keep_win(). + */ +njs_runtime_t * +njs_mb_new_with_win(void *display, long win) { + njs_runtime_t *rt; + mb_rt_t *mb_rt; + + rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); + ASSERT(rt != NULL); + + mb_rt = mb_runtime_new_with_win((Display *)display, win); + + rt->mb_rt = mb_rt; + + return rt; +} + +/*! \brief Pass a X event to X runtime. + */ +void +njs_mb_handle_single_event(njs_runtime_t *rt, void *evt) { +#if 0 + void *mb_rt = rt->mb_rt; + extern void _X_MB_handle_single_event(void *rt, void *evt); + + _X_MB_handle_single_event(mb_rt, evt); +#endif +} + +/*! \brief Called at end of an iteration of event loop. + */ +void +njs_mb_no_more_event(njs_runtime_t *rt) { +#if 0 + mb_rt_t *mb_rt = rt->mb_rt; + extern void _X_MB_no_more_event(mb_rt_t *rt); + + _X_MB_no_more_event(mb_rt); +#endif +} + +/*! \brief Get X runtime that is backend of this njs runtime. + */ +mb_rt_t * +_njs_mb_get_runtime(njs_runtime_t *rt) { + return rt->mb_rt; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/njs_mb_supp.h Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,31 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +#ifndef __NJS_MB_SUPP_H_ +#define __NJS_MB_SUPP_H_ + +#include <ev.h> +#include <mb_backend.h> + +typedef struct _njs_runtime { + mb_rt_t *mb_rt; +} njs_runtime_t; + +extern void njs_mb_reg_timer_man(void); +extern void njs_mb_reg_IO_man(void); +/* extern void njs_mb_init_handle_connection(njs_runtime_t *rt); */ +extern void njs_mb_free(njs_runtime_t *rt); +extern njs_runtime_t *njs_mb_new(char *display_name, int w, int h); +extern void njs_mb_free_keep_win(njs_runtime_t *rt); +extern njs_runtime_t *njs_mb_new_with_win(void *display, long win); +extern int njs_mb_flush(njs_runtime_t *rt); +extern void njs_mb_handle_single_event(njs_runtime_t *rt, void *evt); +extern void njs_mb_no_more_event(njs_runtime_t *rt); +extern mb_rt_t *_njs_mb_get_runtime(njs_runtime_t *rt); + +#define njs_mb_kbevents(rt) mb_runtime_kbevents((rt)->mb_rt) +#define njs_mb_rdman(rt) mb_runtime_rdman((rt)->mb_rt) +#define njs_mb_timer_man(rt) mb_runtime_timer_man((rt)->mb_rt) +#define njs_mb_observer_factory(rt) mb_runtime_observer_factory((rt)->mb_rt) +#define njs_mb_img_ldr(rt) mb_runtime_img_ldr((rt)->mb_rt) + +#endif /* __NJS_MB_SUPP_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/observer.cc Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,169 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +#include <v8.h> +#include "mbfly_njs.h" + +extern "C" { +#include <mb.h> +#include <string.h> +} + +#ifndef ASSERT +#define ASSERT(x) +#endif + +using namespace v8; + +/*! \defgroup xnjsmb_observer JS binding for observer, subject and events + * \ingroup xnjsmb + * + * @{ + */ + +struct xnjsmb_observer_data { + Persistent<Function> func; + Persistent<Context> ctx; +}; + +static void +event_handler(event_t *evt, void *arg); + +static void +xnjsmb_event_mod(Handle<Object> self, event_t *evt) { + mouse_event_t *mevt; + X_kb_event_t *xkbevt; + + switch(evt->type) { + case EVT_ANY: + case EVT_MOUSE_OVER: + case EVT_MOUSE_OUT: + case EVT_MOUSE_MOVE: + case EVT_MOUSE_BUT_PRESS: + case EVT_MOUSE_BUT_RELEASE: + mevt = (mouse_event_t *)evt; + SET(self, "x", Integer::New(mevt->x)); + SET(self, "y", Integer::New(mevt->y)); + SET(self, "but_state", Integer::New(mevt->but_state)); + SET(self, "button", Integer::New(mevt->button)); + break; + + case EVT_KB_PRESS: + case EVT_KB_RELEASE: + xkbevt = (X_kb_event_t *)evt; + SET(self, "keycode", Integer::New(xkbevt->keycode)); + SET(self, "sym", Integer::New(xkbevt->sym)); + break; + + case EVT_PROGM_COMPLETE: + case EVT_RDMAN_REDRAW: + case EVT_MONITOR_ADD: + case EVT_MONITOR_REMOVE: + case EVT_MONITOR_FREE: + case EVT_MOUSE_MOVE_RAW: + default: + /* Not implemented. Do nothing. */ + break; + } +} + +static observer_t * +_subject_add_event_observer(subject_t *subject, int type, + Handle<Function> func) { + observer_t *observer; + xnjsmb_observer_data *data; + Handle<Context> ctx; + + data = new xnjsmb_observer_data; + if(data == NULL) + return NULL; + data->func = Persistent<Function>::New(func); + ctx = Context::GetCurrent(); + data->ctx = Persistent<Context>::New(ctx); + observer = subject_add_event_observer(subject, type, + event_handler, + data); + + return observer; +} + +static void +_subject_remove_observer(subject_t *subject, observer_t *observer) { + xnjsmb_observer_data *data; + + subject_remove_observer(subject, observer); + data = (xnjsmb_observer_data *)observer->arg; + delete data; +} + +static Handle<Value> +xnjsmb_event_tgt_getter(Handle<Object> self, event_t *evt, const char **err) { + Persistent<Object> *hdl; + + hdl = (Persistent<Object> *) + mb_prop_get(&((mb_obj_t *)evt->tgt->obj)->props, + PROP_JSOBJ); + return Local<Object>::New(*hdl); +} + +static void +xnjsmb_event_tgt_setter(Handle<Object> self, event_t *evt, + Handle<Value> value, const char **err) { + *err = "Not implemented"; +} + +static Handle<Value> +xnjsmb_event_cur_tgt_getter(Handle<Object> self, event_t *evt, + const char **err) { + Persistent<Object> *hdl; + + hdl = (Persistent<Object> *) + mb_prop_get(&((mb_obj_t *)evt->cur_tgt->obj)->props, + PROP_JSOBJ); + return Local<Object>::New(*hdl); +} + +static void +xnjsmb_event_cur_tgt_setter(Handle<Object> self, event_t *evt, + Handle<Value> value, const char **err) { + *err = "Not implemented"; +} + +/* This is the part of the code generated by gen_v8_binding.m4 */ +#include "observer-inc.h" + +static void +event_handler(event_t *evt, void *arg) { + xnjsmb_observer_data *data = (xnjsmb_observer_data *)arg; + Handle<Value> evt_obj; + Handle<Value> func_args[1]; + Handle<Value> r; + Context::Scope context_scope(data->ctx); + TryCatch trycatch; + + evt_obj = xnjsmb_auto_event_new(evt); + ASSERT(!evt_obj.IsEmpty()); + func_args[0] = evt_obj; + r = data->func->Call(data->ctx->Global(), 1, func_args); + if(r.IsEmpty()) { + Handle<Value> exception = trycatch.Exception(); + String::AsciiValue exc_str(exception); + fprintf(stderr, "Exception: %s\n", *exc_str); + } +} + +Handle<Value> +export_xnjsmb_auto_subject_new(subject_t *subject) { + Handle<Value> val; + + val = xnjsmb_auto_subject_new(subject); + return val; +} + +void +xnjsmb_observer_init(void) { + xnjsmb_auto_observer_init(); + xnjsmb_auto_subject_init(); + xnjsmb_auto_event_init(); +} + +/* @} */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/observer.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,18 @@ +define([PROJ_PREFIX], [xnjsmb_auto_])dnl +dnl +STRUCT([observer], [observer_t], + [INT([type])], []) + +STRUCT([subject], [subject_t], [], + [METHOD([add_event_observer], [_subject_add_event_observer], + (INT([type]), FUNC([handler])), 2, + [OBJ([observer], [observer_t])]), + METHOD([remove_observer], [_subject_remove_observer], + (OBJ([observer], [observer], [observer_t])), 1, [])]) + +STRUCT([event], [event_t], + [INT([type]), + ACCESSOR([tgt], [xnjsmb_event_tgt_getter], [xnjsmb_event_tgt_setter]), + ACCESSOR([cur_tgt], [xnjsmb_event_cur_tgt_getter], + [xnjsmb_event_cur_tgt_setter]), + INT([flags])], [], (([STMOD], [xnjsmb_event_mod])))
--- a/nodejs/paints.cc Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/paints.cc Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <v8.h> extern "C" { @@ -12,197 +14,311 @@ #define ASSERT(x) #endif - -/*! \brief Fill a shape with the paint. - */ -static Handle<Value> -xnjsmb_paint_fill(const Arguments &args) { - int argc = args.Length(); - Handle<Object> self = args.This(); - Handle<Object> sh_obj; - Handle<Object> rt; - Handle<Value> rt_val; - paint_t *paint; - shape_t *sh; - redraw_man_t *rdman; - - if(argc != 1) - THROW("Invalid number of arguments (!= 1)"); - if(!args[0]->IsObject()) - THROW("Invalid argument type (shape)"); - - paint = (paint_t *)UNWRAP(self); - - sh_obj = args[0]->ToObject(); - sh = (shape_t *)UNWRAP(sh_obj); - - rt_val = GET(self, "mbrt"); - rt = rt_val->ToObject(); - rdman = xnjsmb_rt_rdman(rt); - - rdman_paint_fill(rdman, paint, sh); - - if(sh_get_coord(sh)) - rdman_shape_changed(rdman, sh); - - return Null(); -} - -/*! \brief Stroke a shape with the paint. +/*! \defgroup xnjsmb_paints JS binding for paints + * \ingroup xnjsmb + * + * @{ */ -static Handle<Value> -xnjsmb_paint_stroke(const Arguments &args) { - int argc = args.Length(); - Handle<Object> self = args.This(); - Handle<Object> sh_obj; - Handle<Object> rt; - Handle<Value> rt_val, sh_val; + +/*! \page paint_gc How to manage life-cycle of paints? + * + * A paint is used to fill and stroke shapes. It should keep live + * before all shapes being stroked/or filled by it are dead or + * filled/stroked by other paints. So, every shape that uses a paint + * should keep a reference to the paint. The reference are removed + * when a shape is filled/or stroked by other paints. + * + * A paint should keep a weak reference to itself. It is used to free + * resource before it being collected. + */ +static void +xnjsmb_paint_recycle(Persistent<Value> obj, void *parameter) { + Persistent<Object> *paint_hdl = (Persistent<Object> *)parameter; paint_t *paint; - shape_t *sh; - redraw_man_t *rdman; - - if(argc != 1) - THROW("Invalid number of arguments (!= 1)"); - if(!args[0]->IsObject()) - THROW("Invalid argument type (shape)"); - - paint = (paint_t *)UNWRAP(self); - - sh_val = args[0]; - sh_obj = sh_val->ToObject(); - sh = (shape_t *)UNWRAP(sh_obj); - - rt_val = GET(self, "mbrt"); - rt = rt_val->ToObject(); - rdman = xnjsmb_rt_rdman(rt); - - rdman_paint_stroke(rdman, paint, sh); - - if(sh_get_coord(sh)) - rdman_shape_changed(rdman, sh); - - return Null(); -} - -/*! \brief Constructor of color paint_color_t object for Javascript. - */ -static Handle<Value> -xnjsmb_paint_color(const Arguments &args) { - int argc = args.Length(); - Handle<Object> self = args.This(); Handle<Object> rt; redraw_man_t *rdman; - paint_t *paint; - float r, g, b, a; + int r; + + paint = (paint_t *)UNWRAP(*paint_hdl); + rt = GET(*paint_hdl, "mbrt")->ToObject(); + rdman = xnjsmb_rt_rdman(rt); + + r = rdman_paint_free(rdman, paint); + ASSERT(r == 0); - if(argc != 5) - THROW("Invalid number of arguments (!= 5)"); - if(!args[0]->IsObject() || !args[1]->IsNumber() || - !args[2]->IsNumber() || !args[3]->IsNumber() || - !args[4]->IsNumber()) - THROW("Invalid argument type"); + paint_hdl->Dispose(); + delete paint_hdl; +} + +static void +xnjsmb_paint_mod(Handle<Object> self, void *paint) { + Persistent<Object> *paint_hdl; + + paint_hdl = new Persistent<Object>(); + *paint_hdl = Persistent<Object>::New(self); - rt = args[0]->ToObject(); - r = args[1]->ToNumber()->Value(); - g = args[2]->ToNumber()->Value(); - b = args[3]->ToNumber()->Value(); - a = args[4]->ToNumber()->Value(); + paint_hdl->MakeWeak(paint_hdl, xnjsmb_paint_recycle); +} + +static void +xnjsmb_paint_fill(paint_t *paint, Handle<Object> self, shape_t *sh) { + Handle<Value> rt_v; + Handle<Object> rt_o; + Handle<Object> sh_o; + redraw_man_t *rdman; - rdman = xnjsmb_rt_rdman(rt); - paint = rdman_paint_color_new(rdman, r, g, b, a); - ASSERT(sh != NULL); + rt_v = GET(self, "mbrt"); + rt_o = rt_v->ToObject(); + rdman = xnjsmb_rt_rdman(rt_o); + + rdman_paint_fill(rdman, paint, sh); - WRAP(self, paint); - SET(self, "mbrt", rt); + if(sh_get_coord(sh)) + rdman_shape_changed(rdman, sh); - return Null(); + sh_o = *(Persistent<Object> *)mb_prop_get(&sh->obj.props, PROP_JSOBJ); + SET(sh_o, "_fill_by", self); } -static Persistent<FunctionTemplate> xnjsmb_paint_temp; -static Persistent<FunctionTemplate> xnjsmb_paint_color_temp; +static void +xnjsmb_paint_stroke(paint_t *paint, Handle<Object> self, shape_t *sh) { + Handle<Value> rt_v; + Handle<Object> rt_o; + Handle<Object> sh_o; + redraw_man_t *rdman; + + rt_v = GET(self, "mbrt"); + rt_o = rt_v->ToObject(); + rdman = xnjsmb_rt_rdman(rt_o); + + rdman_paint_stroke(rdman, paint, sh); + + if(sh_get_coord(sh)) + rdman_shape_changed(rdman, sh); -/*! \brief Create and return a paint_color object. + sh_o = *(Persistent<Object> *)mb_prop_get(&sh->obj.props, PROP_JSOBJ); + SET(sh_o, "_stroke_by", self); +} + +static void +xnjsmb_paint_color_set_color(paint_t *paint, Handle<Object> self, + float r, float g, float b, float a) { + Handle<Value> rt_v; + Handle<Object> rt_o; + redraw_man_t *rdman; + + rt_v = GET(self, "mbrt"); + rt_o = rt_v->ToObject(); + rdman = xnjsmb_rt_rdman(rt_o); + + paint_color_set(paint, r, g, b, a); + + rdman_paint_changed(rdman, paint); +} + +/*! \brief Set stops for linear paint for Javascript code. */ -static Handle<Value> -xnjsmb_paint_color_new(const Arguments &args) { - HandleScope scope; - Handle<Object> rt = args.This(); - Handle<Object> paint_color_obj; - Handle<Function> paint_color_func; - Handle<Value> pc_args[5]; - int argc; +static void +xnjsmb_paint_linear_set_stops(paint_t *paint, Handle<Value> stops) { + Array *stops_o; + Array *stop_o; + int nstops; + grad_stop_t *grad_stops, *old_grad_stops; + int i; + + stops_o = Array::Cast(*stops); + nstops = stops_o->Length(); + grad_stops = (grad_stop_t *)malloc(sizeof(grad_stop_t) * nstops); + ASSERT(grad_stops != NULL); + + for(i = 0; i < nstops; i++) { + stop_o = Array::Cast(*stops_o->Get(i)); + ASSERT(stop_o->Length() == 5); + grad_stop_init(grad_stops + i, + stop_o->Get(0)->ToNumber()->Value(), /* off */ + stop_o->Get(1)->ToNumber()->Value(), /* r */ + stop_o->Get(2)->ToNumber()->Value(), /* g */ + stop_o->Get(3)->ToNumber()->Value(), /* b */ + stop_o->Get(4)->ToNumber()->Value()); /* a */ + } + + old_grad_stops = paint_linear_stops(paint, nstops, grad_stops); + if(old_grad_stops) + free(old_grad_stops); /* The stops, here, were allocated for + * previous calling of this + * function. */ +} + +/*! \brief Set stops for radial paint for Javascript code. + */ +static void +xnjsmb_paint_radial_set_stops(paint_t *paint, Handle<Value> stops) { + Array *stops_o; + Array *stop_o; + int nstops; + grad_stop_t *grad_stops, *old_grad_stops; int i; - argc = args.Length(); - if(argc != 4) - THROW("Invalid number of arguments (r, g, b, a)"); - for(i = 0; i < 4; i++) - if(!args[i]->IsNumber()) - THROW("Invalid argument type"); - - pc_args[0] = rt; - pc_args[1] = args[0]; // r - pc_args[2] = args[1]; // g - pc_args[3] = args[2]; // b - pc_args[4] = args[3]; // a - paint_color_func = xnjsmb_paint_color_temp->GetFunction(); - paint_color_obj = paint_color_func->NewInstance(5, pc_args); + stops_o = Array::Cast(*stops); + nstops = stops_o->Length(); + grad_stops = (grad_stop_t *)malloc(sizeof(grad_stop_t) * nstops); + ASSERT(grad_stops != NULL); + + for(i = 0; i < nstops; i++) { + stop_o = Array::Cast(*stops_o->Get(i)); + ASSERT(stop_o->Length() == 5); + grad_stop_init(grad_stops + i, + stop_o->Get(0)->ToNumber()->Value(), /* off */ + stop_o->Get(1)->ToNumber()->Value(), /* r */ + stop_o->Get(2)->ToNumber()->Value(), /* g */ + stop_o->Get(3)->ToNumber()->Value(), /* b */ + stop_o->Get(4)->ToNumber()->Value()); /* a */ + } + + old_grad_stops = paint_radial_stops(paint, nstops, grad_stops); + if(old_grad_stops) + free(old_grad_stops); /* The stops, here, were allocated for + * previous calling of this + * function. */ +} + +#include "paints-inc.h" - scope.Close(paint_color_obj); - return paint_color_obj; +/*! \defgroup xnjsmb_paints_cons Constructor of paints + * + * @{ + */ +paint_t * +xnjsmb_paint_color_new(njs_runtime_t *rt, + float r, float g, float b, float a, + const char **err) { + paint_t *paint; + redraw_man_t *rdman; + + rdman = njs_mb_rdman(rt); + paint = rdman_paint_color_new(rdman, r, g, b, a); + if(paint == NULL) { + *err = "can not allocate a paint_color_t"; + return NULL; + } + + return paint; +} + +paint_t * +xnjsmb_paint_image_new(njs_runtime_t *rt, mb_img_data_t *img, + const char **err) { + paint_t *paint; + redraw_man_t *rdman; + + rdman = njs_mb_rdman(rt); + paint = rdman_paint_image_new(rdman, img); + if(paint == NULL) { + *err = "can not allocate a paint_image_t"; + return NULL; + } + + return paint; } -static Persistent<FunctionTemplate> xnjsmb_paint_color_new_temp; +paint_t * +xnjsmb_paint_linear_new(njs_runtime_t *rt, + float x1, float y1, float x2, float y2, + const char **err) { + paint_t *paint; + redraw_man_t *rdman; + + rdman = njs_mb_rdman(rt); + paint = rdman_paint_linear_new(rdman, x1, y1, x2, y2); + if(paint == NULL) { + *err = "can not allocate a paint_linear_t"; + return NULL; + } -/*! \brief Create templates for paint types. - * - * This function is only called one time for every execution. - */ -static void -xnjsmb_init_paints(void) { - Handle<FunctionTemplate> temp, meth; - Handle<ObjectTemplate> inst_temp; - Handle<ObjectTemplate> proto_temp; - - /* - * Base type of paint types. - */ - temp = FunctionTemplate::New(); - xnjsmb_paint_temp = Persistent<FunctionTemplate>::New(temp); - xnjsmb_paint_temp->SetClassName(String::New("paint")); - - meth = FunctionTemplate::New(xnjsmb_paint_fill); - proto_temp = xnjsmb_paint_temp->PrototypeTemplate(); - SET(proto_temp, "fill", meth); + return paint; +} - meth = FunctionTemplate::New(xnjsmb_paint_stroke); - proto_temp = xnjsmb_paint_temp->PrototypeTemplate(); - SET(proto_temp, "stroke", meth); +paint_t * +xnjsmb_paint_radial_new(njs_runtime_t *rt, + float cx, float cy, float r, + const char **err) { + paint_t *paint; + redraw_man_t *rdman; - /* - * Paint color - */ - temp = FunctionTemplate::New(xnjsmb_paint_color); - xnjsmb_paint_color_temp = Persistent<FunctionTemplate>::New(temp); - xnjsmb_paint_color_temp->SetClassName(String::New("paint_color")); - xnjsmb_paint_color_temp->Inherit(xnjsmb_paint_temp); - - inst_temp = xnjsmb_paint_color_temp->InstanceTemplate(); - inst_temp->SetInternalFieldCount(1); + rdman = njs_mb_rdman(rt); + paint = rdman_paint_radial_new(rdman, cx, cy, r); + if(paint == NULL) { + *err = "can not allocate a paint_radial_t"; + return NULL; + } - temp = FunctionTemplate::New(xnjsmb_paint_color_new); - xnjsmb_paint_color_new_temp = Persistent<FunctionTemplate>::New(temp); + return paint; } +/* @} */ + +/*! \defgroup xnjsmb_paints_export Exported wrapper maker for paints + * + * These functions are used by MB runtime to wrap C paints to JS + * objects. + * + * @{ + */ +Handle<Value> +export_xnjsmb_auto_paint_color_new(paint_t *paint) { + Handle<Value> ret; + + ret = xnjsmb_auto_paint_color_new(paint); + + return ret; +} + +Handle<Value> +export_xnjsmb_auto_paint_image_new(paint_t *paint) { + Handle<Value> ret; + + ret = xnjsmb_auto_paint_image_new(paint); + + return ret; +} + +Handle<Value> +export_xnjsmb_auto_paint_linear_new(paint_t *paint) { + Handle<Value> ret; + + ret = xnjsmb_auto_paint_linear_new(paint); + + return ret; +} + +Handle<Value> +export_xnjsmb_auto_paint_radial_new(paint_t *paint) { + Handle<Value> ret; + + ret = xnjsmb_auto_paint_radial_new(paint); + + return ret; +} +/* @} */ + +/*! \brief Initialize paints for mbfly. + * + * This function is called by init() in mbfly_njs.cc when the module + * being loaded. + */ void xnjsmb_paints_init_mb_rt_temp(Handle<FunctionTemplate> rt_temp) { static int init_flag = 0; Handle<ObjectTemplate> rt_proto_temp; if(!init_flag) { - xnjsmb_init_paints(); + xnjsmb_auto_paint_init(); + xnjsmb_auto_paint_color_init(); + xnjsmb_auto_paint_image_init(); + xnjsmb_auto_paint_linear_init(); + xnjsmb_auto_paint_radial_init(); + init_flag = 1; } +} - rt_proto_temp = rt_temp->PrototypeTemplate(); - SET(rt_proto_temp, "paint_color_new", xnjsmb_paint_color_new_temp); -} +/* @} */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/paints.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,31 @@ +define([PROJ_PREFIX], [xnjsmb_auto_])dnl +dnl +STRUCT([paint], [paint_t], [], + [METHOD([fill], [xnjsmb_paint_fill], + (SELF, OBJ([sh], [shape], [shape_t])), 1, []), + METHOD([stroke], [xnjsmb_paint_stroke], + (SELF, OBJ([sh], [shape], [shape_t])), 1, [])]) + +STRUCT([paint_color], [paint_t], [], + [METHOD([set_color], [xnjsmb_paint_color_set_color], + (SELF, NUMBER([r]), NUMBER([g]), NUMBER([b]), NUMBER([a])), + 4, [])], + (([INHERIT], [paint]), + ([STMOD], [xnjsmb_paint_mod]))) + +STRUCT([paint_image], [paint_t], [], + [], + (([INHERIT], [paint]), + ([STMOD], [xnjsmb_paint_mod]))) + +STRUCT([paint_linear], [paint_t], [], + [METHOD([set_stops], [xnjsmb_paint_linear_set_stops], + (ARRAY([stops])), 1, [])], + (([INHERIT], [paint]), + ([STMOD], [xnjsmb_paint_mod]))) + +STRUCT([paint_radial], [paint_t], [], + [METHOD([set_stops], [xnjsmb_paint_radial_set_stops], + (ARRAY([stops])), 1, [])], + (([INHERIT], [paint]), + ([STMOD], [xnjsmb_paint_mod])))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/run.sh Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,11 @@ +#!/bin/sh + +ABS=`realpath $0` +BASE=`dirname $ABS` +NODE_PATH=$BASE:$BASE/objs/default:$NODE_PATH +export NODE_PATH + +DIR=`dirname $1` +FNAME=`basename $1` + +cd $DIR; node $FNAME
--- a/nodejs/shapes.cc Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/shapes.cc Wed Dec 01 12:25:56 2010 +0800 @@ -1,6 +1,10 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <v8.h> #include "mbfly_njs.h" +#include <string.h> + extern "C" { #include <mb.h> } @@ -9,73 +13,148 @@ #define ASSERT(x) #endif +#define OK 0 + using namespace v8; -/*! \defgroup shape_temp Templates for shape and derivations. +/*! \defgroup xnjsmb_shapes JS binding for shapes. + * \ingroup xnjsmb * * @{ */ -static Persistent<FunctionTemplate> xnjsmb_shape_temp; +/*! \brief This function is called when GC collecting a shape. + * + * It was installed by Persistent<Object>::MakeWeak(). + */ +static void +xnjsmb_shape_recycled(Persistent<Value> obj, void *parameter) { + Persistent<Object> *self_hdl = (Persistent<Object> *)parameter; + Handle<Object> js_rt; + redraw_man_t *rdman; + shape_t *shape; + + shape = (shape_t *)UNWRAP(*self_hdl); + if(shape == NULL) + return; + + WRAP(*self_hdl, NULL); + + js_rt = GET(*self_hdl, "mbrt")->ToObject(); + rdman = xnjsmb_rt_rdman(js_rt); + rdman_shape_changed(rdman, shape); + rdman_shape_free(rdman, shape); + + self_hdl->Dispose(); + delete self_hdl; +} + +static void +xnjsmb_shape_mod(Handle<Object> self, shape_t *sh) { + Persistent<Object> *self_hdl; + static int count = 0; + + /* Keep associated js object in property store for retrieving, + * later, without create new js object. + */ + self_hdl = new Persistent<Object>(); + *self_hdl = Persistent<Object>::New(self); + mb_prop_set(&sh->obj.props, PROP_JSOBJ, self_hdl); + + self_hdl->MakeWeak(self_hdl, xnjsmb_shape_recycled); + + /* XXX: should be remove. It is for trace recycle of shape */ + count++; + if(count > 10000) { + V8::LowMemoryNotification(); + count = 0; + } +} -static Handle<Value> -xnjsmb_shape_show(const Arguments &args) { - shape_t *sh; - Handle<Object> self; +static void +xnjsmb_sh_stext_set_text(shape_t *sh, Handle<Object> self, + const char *txt) { + Handle<Object> rt; + redraw_man_t *rdman; + + sh_stext_set_text(sh, txt); + + /* + * Mark changed. + */ + rt = GET(self, "mbrt")->ToObject(); + ASSERT(rt != NULL); + rdman = xnjsmb_rt_rdman(rt); + + if(sh_get_coord(sh)) + rdman_shape_changed(rdman, sh); +} - self = args.This(); - sh = (shape_t *)UNWRAP(self); - sh_show(sh); - - return Null(); +/*! \brief Set style blocks for a stext object from JS. + * + * A style block is style setting of a chip of text. It is a 3-tuple, + * includes number of charaters, a font face, and font size. This + * function need a list of 3-tuples to set style of text chips of the + * stext. + */ +static void +xnjsmb_sh_stext_set_style(shape_t *sh, Handle<Object> self, + Handle<Value> blks, const char **err) { + Array *blksobj; + Array *blkobj; + mb_style_blk_t *mb_blks; + int nblks; + Handle<Object> rt; + redraw_man_t *rdman; + int r; + int i; + + blksobj = Array::Cast(*blks); + nblks = blksobj->Length(); + mb_blks = new mb_style_blk_t[nblks]; + for(i = 0; i < nblks; i++) { + blkobj = Array::Cast(*blksobj->Get(i)); + mb_blks[i].n_chars = blkobj->Get(0)->ToInt32()->Value(); + mb_blks[i].face = (mb_font_face_t *)UNWRAP(blkobj->Get(1)->ToObject()); + mb_blks[i].font_sz = blkobj->Get(2)->ToNumber()->Value(); + } + + r = sh_stext_set_style(sh, mb_blks, nblks); + if(r != 0) { + *err = "Unknown error"; + return; + } + + /* + * Mark changed. + */ + rt = GET(self, "mbrt")->ToObject(); + ASSERT(rt != NULL); + rdman = xnjsmb_rt_rdman(rt); + + if(sh_get_coord(sh)) + rdman_shape_changed(rdman, sh); + + delete mb_blks; } static Handle<Value> -xnjsmb_shape_hide(const Arguments &args) { - shape_t *sh; - Handle<Object> self; +xnjsmb_shape_stroke_width_get(Handle<Object> self, shape_t *sh, + const char **err) { + float stroke_width; - self = args.This(); - sh = (shape_t *)UNWRAP(self); - sh_hide(sh); - - return Null(); + stroke_width = sh_get_stroke_width(sh); + return Number::New(stroke_width); } -/*! \brief Get stroke width of a shape. - */ -static Handle<Value> -xnjsmb_shape_stroke_width_getter(Local<String> property, - const AccessorInfo &info) { - Handle<Object> self = info.This(); - shape_t *sh; - float w; - Handle<Value> w_val; - - sh = (shape_t *)UNWRAP(self); - w = sh_get_stroke_width(sh); - w_val = Number::New(w); - - return w_val; -} +static void +xnjsmb_shape_stroke_width_set(Handle<Object> self, shape_t *sh, + Handle<Value> value, const char **err) { + float stroke_width; + Handle<Object> rt; + redraw_man_t *rdman; -/*! \brief Set stroke width of a shape. - */ -static void -xnjsmb_shape_stroke_width_setter(Local<String> property, - Local<Value> value, - const AccessorInfo &info) { - Handle<Object> self = info.This(); - Handle<Object> rt; - shape_t *sh; - redraw_man_t *rdman; - float w; - Handle<Number> w_num; - - sh = (shape_t *)UNWRAP(self); - w_num = value->ToNumber(); - w = w_num->Value(); - - sh_set_stroke_width(sh, w); + stroke_width = value->Int32Value(); + sh_set_stroke_width(sh, stroke_width); /* * Mark changed. @@ -83,280 +162,194 @@ rt = GET(self, "mbrt")->ToObject(); ASSERT(rt != NULL); rdman = xnjsmb_rt_rdman(rt); - + if(sh_get_coord(sh)) rdman_shape_changed(rdman, sh); } static void -xnjsmb_init_shape_temp(void) { - Handle<FunctionTemplate> temp; - Handle<ObjectTemplate> proto_temp; - Handle<FunctionTemplate> method_temp; +xnjsmb_shape_show(shape_t *sh, Handle<Object> self) { + Handle<Object> js_rt; + redraw_man_t *rdman; + + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + + sh_show(sh); + rdman_shape_changed(rdman, sh); +} - temp = FunctionTemplate::New(); - temp->SetClassName(String::New("shape")); - xnjsmb_shape_temp = Persistent<FunctionTemplate>::New(temp); - proto_temp = temp->PrototypeTemplate(); - - method_temp = FunctionTemplate::New(xnjsmb_shape_show); - SET(proto_temp, "show", method_temp); - method_temp = FunctionTemplate::New(xnjsmb_shape_hide); - SET(proto_temp, "hide", method_temp); +static void +xnjsmb_shape_hide(shape_t *sh, Handle<Object> self) { + Handle<Object> js_rt; + redraw_man_t *rdman; - proto_temp->SetAccessor(String::New("stroke_width"), - xnjsmb_shape_stroke_width_getter, - xnjsmb_shape_stroke_width_setter); + js_rt = GET(self, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); + + sh_hide(sh); + rdman_shape_changed(rdman, sh); } -/* @} */ - -/*! \defgroup path_temp Templates for path objects. - * - * @{ - */ -static Persistent<FunctionTemplate> xnjsmb_path_temp; +static void +xnjsmb_shape_remove(shape_t *sh, Handle<Object> self) { + Handle<Object> js_rt; + redraw_man_t *rdman; + Persistent<Object> *self_hdl; + int r; -/*! \brief Callback of constructor of path objects for Javascript. - */ -static Handle<Value> -xnjsmb_shape_path(const Arguments &args) { - shape_t *sh; - redraw_man_t *rdman; - Handle<Object> self = args.This(); // path object - Handle<Object> rt; - char *dstr; - int argc; + self_hdl = (Persistent<Object> *)mb_prop_get(&sh->obj.props, + PROP_JSOBJ); - argc = args.Length(); - if(argc != 2) - THROW("Invalid number of arugments (!= 1)"); - if(!args[0]->IsString()) - THROW("Invalid argument type (should be a string)"); - if(!args[1]->IsObject()) - THROW("Invalid argument type (should be an object)"); + SET(*self_hdl, "valid", Boolean::New(0)); + WRAP(*self_hdl, NULL); + + js_rt = GET(*self_hdl, "mbrt")->ToObject(); + ASSERT(js_rt != NULL); + rdman = xnjsmb_rt_rdman(js_rt); - String::Utf8Value dutf8(args[0]->ToString()); - dstr = *dutf8; + rdman_shape_changed(rdman, sh); + r = rdman_shape_free(rdman, sh); + if(r != OK) + THROW_noret("Can not free a shape for unknown reason"); - rt = args[1]->ToObject(); - rdman = xnjsmb_rt_rdman(rt); - sh = rdman_shape_path_new(rdman, dstr); - - WRAP(self, sh); - SET(self, "mbrt", rt); - - return Null(); + self_hdl->Dispose(); + delete self_hdl; } -/*! \brief Initial function template for constructor of path objects. - */ static void -xnjsmb_init_path_temp(void) { - Handle<FunctionTemplate> temp; - Handle<ObjectTemplate> inst_temp; +xnjsmb_sh_rect_set(shape_t *sh, Handle<Object> self, float x, float y, + float w, float h, float rx, float ry) { + Handle<Object> rt; + redraw_man_t *rdman; - temp = FunctionTemplate::New(xnjsmb_shape_path); - temp->Inherit(xnjsmb_shape_temp); - temp->SetClassName(String::New("path")); - - inst_temp = temp->InstanceTemplate(); - inst_temp->SetInternalFieldCount(1); - - xnjsmb_path_temp = Persistent<FunctionTemplate>::New(temp); -} + sh_rect_set(sh, x, y, w, h, rx, ry); -/*! \brief Callback function of mb_rt.path_new(). - */ -static Handle<Value> -xnjsmb_shape_path_new(const Arguments &args) { - HandleScope scope; - Handle<Object> self = args.This(); // runtime object - Handle<Object> path_obj; - Handle<Value> path_args[2]; - int argc; + /* + * Mark changed. + */ + rt = GET(self, "mbrt")->ToObject(); + ASSERT(rt != NULL); + rdman = xnjsmb_rt_rdman(rt); - argc = args.Length(); - if(argc != 1) - THROW("Invalid number of arugments (!= 1)"); - if(!args[0]->IsString()) - THROW("Invalid argument type (shoud be a string)"); - - path_args[0] = args[0]; - path_args[1] = self; - - path_obj = xnjsmb_path_temp->GetFunction()->NewInstance(2, path_args); - - scope.Close(path_obj); - return path_obj; + if(sh_get_coord(sh)) + rdman_shape_changed(rdman, sh); } /* @} */ -/*! \defgroup stext_path Template for stext objects. +#include "shapes-inc.h" + +/*! \defgroup xnjsmb_shapes_wraps Exported wrapper makers for shapes + * \ingroup xnjsmb_shapes + * + * These functions are used by methods of mb_rt to wrap shape objects + * as Javascript objects. + * + * @{ + */ +Handle<Value> +export_xnjsmb_auto_path_new(shape_t *sh) { + return xnjsmb_auto_path_new(sh); +} + +Handle<Value> +export_xnjsmb_auto_stext_new(shape_t *sh) { + return xnjsmb_auto_stext_new(sh); +} + +Handle<Value> +export_xnjsmb_auto_image_new(shape_t *sh) { + return xnjsmb_auto_image_new(sh); +} + +Handle<Value> +export_xnjsmb_auto_rect_new(shape_t *sh) { + return xnjsmb_auto_rect_new(sh); +} + +/* @} */ + +/*! \defgroup xnjsmb_shapes_cons Constructor of shapes + * \ingroup xnjsmb_shapes * * @{ */ - -/*! \brief Constructor for stext objects. - * - * 4 arguments - * \param rt is a runtime object. - * \param data is a text to be showed. - * \param x is postion in x-axis. - * \param y is position in y-axis. - */ -static Handle<Value> -xnjsmb_shape_stext(const Arguments &args) { - int argc = args.Length(); - Handle<Object> self = args.This(); - Handle<Object> rt; - float x, y; - char *data; +shape_t * +xnjsmb_path_new(njs_runtime_t *rt, const char *d) { redraw_man_t *rdman; - shape_t *stext; - - if(argc != 4) - THROW("Invalid number of arguments (!= 4)"); - if(!args[0]->IsObject() || !args[1]->IsString() || - !args[2]->IsNumber() || !args[3]->IsNumber()) - THROW("Invalid argument type"); + shape_t *sh; + + rdman = njs_mb_rdman(rt); + sh = rdman_shape_path_new(rdman, d); + /* Code generator supposes that callee should free the memory */ + free((void *)d); + + return sh; +} - rt = args[0]->ToObject(); - String::Utf8Value data_utf8(args[1]); - data = *data_utf8; - x = args[2]->ToNumber()->Value(); - y = args[3]->ToNumber()->Value(); +shape_t * +xnjsmb_stext_new(njs_runtime_t *rt, const char *txt, float x, float y) { + redraw_man_t *rdman; + shape_t *sh; - rdman = xnjsmb_rt_rdman(rt); - ASSERT(rdman != NULL); - - stext = rdman_shape_stext_new(rdman, data, x, y); + rdman = njs_mb_rdman(rt); + sh = rdman_shape_stext_new(rdman, txt, x, y); + /* Code generator supposes that callee should free the memory */ + free((void *)txt); - WRAP(self, stext); - SET(self, "mbrt", rt); - - return Null(); + return sh; } -static Persistent<FunctionTemplate> xnjsmb_shape_stext_temp; - -/*! \brief Create a stext and return it. - */ -static Handle<Value> -xnjsmb_shape_stext_new(const Arguments &args) { - HandleScope scope; - int argc = args.Length(); - Handle<Object> self = args.This(); - Handle<Value> stext_args[4]; - Handle<Object> stext_obj; - Handle<Function> func; +shape_t * +xnjsmb_image_new(njs_runtime_t *rt, float x, float y, float w, float h) { + redraw_man_t *rdman; + shape_t *sh; - if(argc != 3) - THROW("Invalid number of arguments (!= 3)"); + rdman = njs_mb_rdman(rt); + sh = rdman_shape_image_new(rdman, x, y, w, h); - stext_args[0] = self; - stext_args[1] = args[0]; - stext_args[2] = args[1]; - stext_args[3] = args[2]; - - func = xnjsmb_shape_stext_temp->GetFunction(); - stext_obj = func->NewInstance(4, stext_args); - ASSERT(stext_obj != NULL); - - return stext_obj; + return sh; } -/*! \brief Setup style blocks for a stext. - * - * It defines font style and size for blocks of text message. - * - * \param blks is a list (n_char, face, font size) tuples. - */ -static Handle<Value> -xnjsmb_shape_stext_set_style(const Arguments &args) { - HandleScope scope; - int argc = args.Length(); - Handle<Object> self = args.This(); +shape_t * +xnjsmb_rect_new(njs_runtime_t *rt, float x, float y, float w, float h, + float rx, float ry, const char **err) { + redraw_man_t *rdman; shape_t *sh; - Array *blksobj; - Array *blkobj; - mb_style_blk_t *blks; - int nblks; - int i; - int r; - if(argc != 1) - THROW("Invalid number of arguments (!= 1)"); - if(!args[0]->IsArray()) - THROW("Invalid type of the argument"); - - blksobj = Array::Cast(*args[0]); - nblks = blksobj->Length(); - blks = new mb_style_blk_t[nblks]; - for(i = 0; i < nblks; i++) { - blkobj = Array::Cast(*blksobj->Get(i)); - blks[i].n_chars = blkobj->Get(0)->ToInt32()->Value(); - blks[i].face = (mb_font_face_t *)UNWRAP(blkobj->Get(1)->ToObject()); - blks[i].font_sz = blkobj->Get(2)->ToNumber()->Value(); + rdman = njs_mb_rdman(rt); + sh = rdman_shape_rect_new(rdman, x, y, w, h, rx, ry); + if(sh == NULL) { + *err = "Can not create a sh_rect_t"; + return NULL; } - - sh = (shape_t *)UNWRAP(self); - r = sh_stext_set_style(sh, blks, nblks); - if(r != 0) - THROW("Unknown error"); - - delete blks; - - return Null(); -} -/*! \brief Initialize function template for stext objects. - */ -void -xnjsmb_init_stext_temp(void) { - Handle<FunctionTemplate> func_temp; - Handle<FunctionTemplate> meth_temp; - Handle<ObjectTemplate> inst_temp; - Handle<ObjectTemplate> proto_temp; - - func_temp = FunctionTemplate::New(xnjsmb_shape_stext); - func_temp->Inherit(xnjsmb_shape_temp); - func_temp->SetClassName(String::New("stext")); - - inst_temp = func_temp->InstanceTemplate(); - inst_temp->SetInternalFieldCount(1); - - proto_temp = func_temp->PrototypeTemplate(); - meth_temp = FunctionTemplate::New(xnjsmb_shape_stext_set_style); - SET(proto_temp, "set_style", meth_temp); - - xnjsmb_shape_stext_temp = Persistent<FunctionTemplate>::New(func_temp); + return sh; } /* @} */ /*! \brief Set properties of template of mb_rt. + * \ingroup xnjsmb_shapes */ void xnjsmb_shapes_init_mb_rt_temp(Handle<FunctionTemplate> rt_temp) { HandleScope scope; Handle<FunctionTemplate> path_new_temp, stext_new_temp; + Handle<FunctionTemplate> image_new_temp; Handle<ObjectTemplate> rt_proto_temp; static int temp_init_flag = 0; if(temp_init_flag == 0) { - xnjsmb_init_shape_temp(); - xnjsmb_init_path_temp(); - xnjsmb_init_stext_temp(); + xnjsmb_auto_shape_init(); + xnjsmb_auto_path_init(); + xnjsmb_auto_stext_init(); + xnjsmb_auto_image_init(); + xnjsmb_auto_rect_init(); temp_init_flag = 1; } - - rt_proto_temp = rt_temp->PrototypeTemplate(); - - path_new_temp = FunctionTemplate::New(xnjsmb_shape_path_new); - SET(rt_proto_temp, "path_new", path_new_temp); - - stext_new_temp = FunctionTemplate::New(xnjsmb_shape_stext_new); - SET(rt_proto_temp, "stext_new", stext_new_temp); + return; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/shapes.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,28 @@ +define([PROJ_PREFIX], [xnjsmb_auto_])dnl +dnl +STRUCT([shape], [shape_t], + [ACCESSOR([stroke_width], + [xnjsmb_shape_stroke_width_get], + [xnjsmb_shape_stroke_width_set])], + [METHOD([show], [xnjsmb_shape_show], (SELF), 0, []), + METHOD([hide], [xnjsmb_shape_hide], (SELF), 0, []), + METHOD([remove], [xnjsmb_shape_remove], (SELF), 0, [])]) + +STRUCT([path], [shape_t], [], [], + (([INHERIT], [shape]), ([STMOD], [xnjsmb_shape_mod]))) + +STRUCT([stext], [shape_t], [], + [METHOD([set_text], [xnjsmb_sh_stext_set_text], + (SELF, STR([txt])), 1, []), + METHOD([set_style], [xnjsmb_sh_stext_set_style], + (SELF, ARRAY([blks]), ERR), 1, [])], + (([INHERIT], [shape]), ([STMOD], [xnjsmb_shape_mod]))) + +STRUCT([image], [shape_t], [], [], + (([INHERIT], [shape]), ([STMOD], [xnjsmb_shape_mod]))) + +STRUCT([rect], [shape_t], [], + [METHOD([set], [xnjsmb_sh_rect_set], + (SELF, NUMBER(x), NUMBER(y), NUMBER(w), NUMBER(h), + NUMBER(rx), NUMBER(ry)), 6, [])], + (([INHERIT], [shape]), ([STMOD], [xnjsmb_shape_mod])))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/svg.js Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,1258 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +var libxml = require('libxmljs'); +var sys=require('sys'); +var mbfly = require("mbfly"); +var ldr = mbfly.img_ldr_new("."); + + +var _std_colors = { + "white": [1, 1, 1], + "black": [0, 0, 0], + "red": [1, 0, 0] +}; + +function parse_color(color) { + var r, g, b; + var c; + + if (color[0] == "#") { + r = parseInt(color.substring(1, 3), 16) / 255; + g = parseInt(color.substring(3, 5), 16) / 255; + b = parseInt(color.substring(5, 7), 16) / 255; + } else if(_std_colors[color]) { + c = _std_colors[color]; + r = c[0]; + g = c[1]; + b = c[2]; + } else { + r = g = b = 0; + } + + return [r, g, b]; +} + +exports.loadSVG=loadSVG; + +function loadSVG(mb_rt, root, filename) { + this.pgstack=[]; + if (filename) + this.load(mb_rt,root,filename); +} + +loadSVG.prototype.load=function(mb_rt, root, filename) { + var doc = libxml.parseXmlFile(filename); + var _root = doc.root(); + var nodes = _root.childNodes(); + var coord = mb_rt.coord_new(root); + var k; + var accu=[1,0,0,0,1,0]; + this.mb_rt = mb_rt; + this.stop_ref={}; + this.gradients={}; + this.radials = {}; + coord.center=new Object(); + coord.center.x = 10000; + coord.center.y = 10000; + if (this.pgstack.length > 0) + this.pgstack[this.pgstack.length-1].hide(); + this.pgstack.push(coord); + + + if(_root.attr("width")) { + k = _root.attr("width").value(); + this.width = parseFloat(k); + } + if(_root.attr("height")) { + k = _root.attr("height").value(); + this.height = parseFloat(k); + } + + for(k in nodes) { + var n = nodes[k].name(); + if (n == "defs") { + this.parseDefs(coord,nodes[k]); + } else if (n == "metadata") { + this.parseMetadata(coord,nodes[k]); + } else if (n == "g") { + this.parseGroup(accu,coord,'root_coord',nodes[k]); + } + } +} + + + +loadSVG.prototype.leaveSVG=function() +{ + var p = this.pgstack.pop(); + p.hide(); + if (this.pgstack.length > 0) + this.pgstack[this.pgstack.length-1].show(); +} + +function make_mbnames(mb_rt, n, obj) { + var mbname; + var name; + + if(!mb_rt.mbnames) + mb_rt.mbnames = {}; + + mbname = n.attr("mbname"); + if(mbname) { + name = mbname.value(); + mb_rt.mbnames[name] = obj; + return; + } + mbname = n.attr("label"); + if(mbname&&(mbname.value()!="")) { + name = mbname.value(); + mb_rt.mbnames[name] = obj; + } + try { + var gname = n.attr('id').value(); + sys.puts(gname); + mb_rt.mbnames[gname] = obj; + } catch(e) { + } +} + +function getInteger(n,name) +{ + if (n == null) return 0; + var a = n.attr(name); + if (a==null) return 0; + return parseInt(a.value()); +} + +function parsePointSize(s) +{ + var fs=0; + var i; + + for(i=0;i<s.length;i++) { + if (s[i]<'0' || s[i] > '9') break; + fs = fs*10 + (s[i]-'0'); + } + return fs; + +} + +function parse_style(node) { + var style_attr; + var style; + var parts, part; + var kv, key, value; + var content = {}; + var i; + + style_attr = node.attr('style'); + if(!style_attr) + return content; + + style = style_attr.value(); + parts = style.split(';'); + for(i = 0; i < parts.length; i++) { + part = parts[i].trim(); + if(part) { + kv = part.split(':'); + key = kv[0].trim(); + value = kv[1].trim(); + content[key] = value; + } + } + + return content; +} + +function parseColor(c) +{ + if (c[0] == '#') { + return parseInt(c.substring(1,3),16)<<16 | parseInt(c.substring(3,5),16)<<8 | parseInt(c.substring(5,7),16); + } +} + +function parseTextStyle(style,n) +{ + var attr; + if (n) { + attr = n.attr('style'); + } else { + attr = null; + } + if (attr == null) { + return; + } + var f = attr.value().split(';'); + + for(i in f) { + var kv = f[i].split(':'); + if (kv[0] == 'font-size') { + style.fs = parsePointSize(kv[1]); + } else if (kv[0] == "font-style") { + } else if (kv[0] == "font-weight") { + } else if (kv[0] == "fill") { + style.color = parseColor(kv[1]); + } else if (kv[0] == "fill-opacity") { + } else if (kv[0] == "stroke-opacity") { + } else if (kv[0] == "stroke") { + } else if (kv[0] == "stroke-width") { + } else if (kv[0] == "stroke-linecap") { + } else if (kv[0] == "stroke-linejoin") { + } else if (kv[0] == "stroke-lineopacity") { + } else if (kv[0] == "font-family") { + style.family = kv[1]; + } else if (kv[0] == "font-stretch") { + } else if (kv[0] == "font-variant") { + } else if (kv[0] == "text-anchor") { + } else if (kv[0] == "text-align") { + } else if (kv[0] == "writing-mode") { + } else if (kv[0] == "line-height") { + } else { + sys.puts("Unknown style: "+kv[0]); + } + } +} +function tspan_set_text(text) +{ + this.text.set_text(text); +} + +function _parse_font_size(fn_sz_str) { + var pos; + + pos = fn_sz_str.search("px"); + if(pos >= 0) + fn_sz_str = fn_sz_str.substring(0, pos); + pos = fn_sz_str.search("pt"); + if(pos >= 0) + fn_sz_str = fn_sz_str.substring(0, pos); + + return parseFloat(fn_sz_str); +} + +loadSVG.prototype.parseTSpan = function(coord, n, pstyle) { + var x = getInteger(n,'x'); + var y = getInteger(n,'y'); + var tcoord = this.mb_rt.coord_new(coord); + var style; + var family = "Courier"; + var weight = 80; + var slant = 0; + var sz = 10; + var face; + var k; + var obj = this.mb_rt.stext_new(n.text(),x,y); + + style = parse_style(n); + for(k in pstyle) { + if(k in style) + continue; + style[k] = pstyle[k]; + } + + if("font-family" in style) + family = style["font-family"]; + if("font-size" in style) + sz = _parse_font_size(style["font-size"]); + if("font-weight" in style) { + if(style["font-weight"] == "bold") + weight = 200; + } + if("font-style" in style) { + if(style["font-style"] == "oblique") + slant = 110; + } + + face = this.mb_rt.font_face_query(family, slant, weight); + obj.set_style([[n.text().length, face, sz]]); + + tcoord.add_shape(obj); + tcoord.set_text = tspan_set_text; + tcoord.text = obj; + + this._set_paint_style(style, obj); + this._set_bbox(n, obj); + + make_mbnames(this.mb_rt, n, tcoord); +}; + +loadSVG.prototype._prepare_paint_color = function(color, alpha) { + var paint; + var c; + + if (color[0]=='#') { + var r,g,b; + r = parseInt(color.substring(1,3),16)/255; + g = parseInt(color.substring(3,5),16)/255; + b = parseInt(color.substring(5,7),16)/255; + paint = this.mb_rt.paint_color_new(r, g, b, alpha); + } else if(_std_colors[color]) { + c = _std_colors[color]; + paint = this.mb_rt.paint_color_new(c[0], c[1], c[2], alpha); + } else if (color.substring(0,3) == 'url') { + var id = color.substring(5, color.length-1); + if(id in this.gradients) { + var gr = this.gradients[id]; + paint = this.mb_rt.paint_linear_new(gr[0],gr[1],gr[2],gr[3]); + } else { + var radial = this.radials[id]; + paint = this.mb_rt.paint_radial_new(radial[0], + radial[1], + radial[2]); + } + paint.set_stops(this.stop_ref[id]); + } else { + paint = this.mb_rt.paint_color_new(0,0,0,1); + } + return paint; +}; + +function guessPathBoundingBox(coord,d) +{ + return; + var items = d.split(' '); + var len = items.length; + var pair; + var i; + var minx,miny; + + minx = 10000; + miny = 10000; + + for(i=0;i<len;i++) { + var type = items[i].toLowerCase(); + x = minx;y = miny; + switch(type) { + case 'm': + case 'l': + case 'a': + case 'x': + pair = items[i+1].split(','); + if (pair.length==2) { + x = parseFloat(pair[0]); + y = parseFloat(pair[1]); + i++; + } else { + x = parseFloat(items[i+1]); + y = parseFloat(items[i+2]); + i+=2; + } + break; + case 'q': + // Implement this latter + break; + case 'c': + // Implement this latter + break; + case 's': + // Implement this latter + break; + case 'h': + x = parseFloat(items[i+1]); + break; + case 'v': + y = parseFloat(items[i+1]); + break; + default: + continue; + } + if (x < minx) minx = x; + if (y < miny) miny = y; + } + if (coord.center.x > minx) + coord.center.x = minx; + if (coord.center.y > miny) + coord.center.y = miny; +}; + +function _mul(m1, m2) { + var res = new Array(); + + res.push(m1[0] * m2[0] + m1[1] * m2[3]); + res.push(m1[0] * m2[1] + m1[1] * m2[4]); + res.push(m1[0] * m2[2] + m1[1] * m2[5] + m1[2]); + res.push(m1[3] * m2[0] + m1[4] * m2[3]); + res.push(m1[3] * m2[1] + m1[4] * m2[4]); + res.push(m1[3] * m2[2] + m1[4] * m2[5] + m1[5]); + + return res; +} + +function _pnt_transform(x, y, matrix) { + var rx, ry; + + rx = x * matrix[0] + y * matrix[1] + matrix[2]; + ry = x * matrix[3] + y * matrix[4] + matrix[5]; + return new Array(rx, ry); +} + +function _shift_transform(x, y, matrix) { + var rx, ry; + + rx = x * matrix[0] + y * matrix[1]; + ry = x * matrix[3] + y * matrix[4]; + return new Array(rx, ry); +} + +function _transform_bbox(bbox, matrix) { + var min_x, min_y, max_x, max_y; + var x, y; + var pnt; + var pnts = new Array(); + var i; + + pnt = _pnt_transform(bbox.x, bbox.y, matrix); + pnts.push(pnt); + pnt = _pnt_transform(bbox.x + bbox.width, bbox.y, matrix); + pnts.push(pnt); + pnt = _pnt_transform(bbox.x, bbox.y + bbox.height, matrix); + pnts.push(pnt); + pnt = _pnt_transform(bbox.x + bbox.width, bbox.y + bbox.height, matrix); + pnts.push(pnt); + + min_x = max_x = pnts[0][0]; + min_y = max_y = pnts[0][1]; + for(i = 1; i < pnts.length; i++) { + pnt = pnts[i]; + if(pnt[0] < min_x) + min_x = pnt[0]; + if(pnt[1] < min_y) + min_y = pnt[1]; + if(pnt[0] > max_x) + max_x = pnt[0]; + if(pnt[1] > max_y) + max_y = pnt[1]; + } + + bbox.x = min_x; + bbox.y = min_y; + bbox.width = max_x - min_x; + bbox.height = max_y - min_y; +} + +function _reverse(m1) { + var rev = new Array(1, 0, 0, 0, 1, 0); + var m = new Array(m1[0], m1[1], m1[2], m1[3], m1[4], m1[5]); + + rev[3] = -m[3] / m[0]; + m[3] = 0; + m[4] += rev[3] * m[1]; + m[5] += rev[3] * m[2]; + + rev[1] = -m[1] / m[4]; + rev[0] += rev[1] * rev[3]; + m[1] = 0; + m[2] += rev[1] * m[5]; + + rev[2] = -m[2]; + rev[5] = -m[5]; + + rev[0] = rev[0] / m[0]; + rev[1] = rev[1] / m[0]; + rev[2] = rev[2] / m[0]; + + rev[3] = rev[3] / m[4]; + rev[4] = rev[4] / m[4]; + rev[5] = rev[5] / m[4]; + + return rev; +} + +var _bbox_proto = { + _get_ac_saved_rev: function() { + var c = this.owner; + var mtx; + + c = c.parent; + + mtx = c._mbapp_saved_rev_mtx; + while(c.parent && typeof c.parent != "undefined") { + c = c.parent; + mtx = _mul(mtx, c._mbapp_saved_rev_mtx); + } + + return mtx; + }, + + _get_ac_mtx: function() { + var c = this.owner; + var mtx; + + c = c.parent; + + mtx = [c[0], c[1], c[2], c[3], c[4], c[5]]; + while(c.parent) { + c = c.parent; + mtx = _mul(c, mtx); + } + + return mtx; + }, + + _saved_to_current: function() { + var r; + + r = _mul(this._get_ac_mtx(), this._get_ac_saved_rev()); + + return r; + }, + + /*! \brief Update x, y, width, and height of the bbox. + */ + update: function() { + var mtx; + + this.x = this.orig.x; + this.y = this.orig.y; + this.width = this.orig.width; + this.height = this.orig.height; + + mtx = this._saved_to_current(); + _transform_bbox(this, mtx); + }, +}; + +var _center_proto = { + _get_ac_saved_rev: function() { + var c = this.owner; + var mtx; + + c = c.parent; + + mtx = c._mbapp_saved_rev_mtx; + while(c.parent && typeof c.parent != "undefined") { + c = c.parent; + mtx = _mul(mtx, c._mbapp_saved_rev_mtx); + } + + return mtx; + }, + + _get_ac_mtx: function() { + var c = this.owner; + var mtx; + + c = c.parent; + + mtx = [c[0], c[1], c[2], c[3], c[4], c[5]]; + while(c.parent) { + c = c.parent; + mtx = _mul(c, mtx); + } + + return mtx; + }, + + _get_ac_rev: function() { + var c = this.owner; + var mtx; + + if(c.type != "coord") + c = c.parent; // is a shape! + + mtx = _reverse([c[0], c[1], c[2], c[3], c[4], c[5]]); + while(c.parent) { + c = c.parent; + mtx = _mul(mtx, _reverse([c[0], c[1], c[2], c[3], c[4], c[5]])); + } + + return mtx; + }, + + _saved_to_current: function() { + var r; + + r = _mul(this._get_ac_mtx(), this._get_ac_saved_rev()); + + return r; + }, + + /*! \brief Update x, y of center point of an object. + */ + update: function() { + var mtx; + var xy; + + mtx = this._saved_to_current(); + xy = _pnt_transform(this.orig.x, this.orig.y, mtx); + + this._x = xy[0]; + this._y = xy[1]; + }, + + /*! \brief Move owner object to make center at (x, y). + */ + move: function(x, y) { + var mtx; + var xdiff = x - this._x; + var ydiff = y - this._y; + var shiftxy; + var c; + + mtx = this._get_ac_rev(); + shiftxy = _shift_transform(xdiff, ydiff, mtx); + + c = this.owner; + if(c.type != "coord") + c = c.parent; + + c[2] += shiftxy[0]; + c[5] += shiftxy[1]; + + this._x = x; + this._y = y; + }, + + /*! \brief Move owner object to make center at position specified by pnt. + */ + move_pnt: function(pnt) { + this.move(pnt.x, pnt.y); + }, + + /*! \brief Prevent user to modify value. + */ + get x() { return this._x; }, + + /*! \brief Prevent user to modify value. + */ + get y() { return this._y; }, + + /*! \brief Center position in the relative space defined by parent. + */ + get rel() { + var rev; + var xy; + + rev = this._get_ac_rev(); + xy = _pnt_transform(this.orig.x, this.orig.y, rev); + + return {x: xy[0], y: xy[1]}; + }, +}; + +loadSVG.prototype._set_bbox = function(node, tgt) { + var a; + var vstr; + var bbox, center; + var orig; + + a = node.attr("bbox-x"); + if(!a) + return 0; + + /* bbox.orig is initial values of bbox. The bbox is recomputed + * according bbox.orig and current matrix. See bbox.update(). + */ + tgt.bbox = bbox = new Object(); + bbox.orig = orig = new Object(); + bbox.owner = tgt; + bbox.__proto__ = _bbox_proto; + vstr = a.value(); + orig.x = parseFloat(vstr); + + a = node.attr("bbox-y"); + vstr = a.value(); + orig.y = this.height - parseFloat(vstr); + + a = node.attr("bbox-width"); + vstr = a.value(); + orig.width = parseFloat(vstr); + + a = node.attr("bbox-height"); + vstr = a.value(); + orig.height = parseFloat(vstr); + orig.y -= orig.height; + + bbox.update(); + + /* center.orig is initial values of center. The center is + * recomputed according center.orig and current matrix. See + * center.update(). + */ + tgt.center = center = new Object(); + center.orig = orig = new Object(); + + orig.x = bbox.orig.width / 2 + bbox.orig.x; + orig.y = bbox.orig.height / 2 + bbox.orig.y; + a = node.attr("transform-center-x"); + if(a) { + vstr = a.value(); + orig.x += parseFloat(vstr); + a = node.attr("transform-center-y"); + vstr = a.value(); + orig.y -= parseFloat(vstr); + } + center.__proto__ = _center_proto; + center.owner = tgt; + center.update(); + + return 1; +} + +loadSVG.prototype._set_paint_style = function(style, tgt) { + var paint; + var fill_alpha = 1; + var stroke_alpha = 1; + var alpha = 1; + var fill_color; + var stroke_color; + var stroke_width = 1; + var i; + + if(style) { + if('opacity' in style) + alpha = parseFloat(style['opacity']); + if('fill' in style) + fill_color = style['fill']; + if('fill-opacity' in style) + fill_alpha = parseFloat(style['fill-opacity']); + if('stroke' in style) + stroke_color = style['stroke']; + if('stroke-width' in style) + stroke_width = parseFloat(style['stroke-width']); + if('stroke-opacity' in style) + stroke_alpha = parseFloat(style['stroke-opacity']); + if('display' in style && style['display'] == 'none') + return; + } + + if(fill_color) { + if(fill_color != "none") { + paint = this._prepare_paint_color(fill_color, fill_alpha); + paint.fill(tgt); + } + } + if(stroke_color) { + if(stroke_color != "none") { + paint = this._prepare_paint_color(stroke_color, stroke_alpha); + paint.stroke(tgt); + } + } + + tgt.stroke_width = stroke_width; + + if(alpha < 1) + tgt.parent.opacity = alpha; +}; + +loadSVG.prototype._set_paint = function(node, tgt) { + var style; + + style = parse_style(node); + this._set_paint_style(style, tgt); +}; + +function formalize_path_data(d) { + var posM, posm; + var pos; + var nums = "0123456789+-."; + var rel = false; + var cmd; + + posM = d.search("M"); + posm = d.search("m"); + pos = posm < posM? posm: posM; + if(pos == -1) + pos = posM == -1? posm: posM; + if(pos == -1) + return d; + + if(posm == pos) + rel = true; + + pos = pos + 1; + while(pos < d.length && " ,".search(d[pos]) >= 0) + pos++; + while(pos < d.length && nums.search(d[pos]) >= 0) + pos++; + while(pos < d.length && " ,".search(d[pos]) >= 0) + pos++; + while(pos < d.length && nums.search(d[pos]) >= 0) + pos++; + while(pos < d.length && " ,".search(d[pos]) >= 0) + pos++; + if(nums.search(d[pos]) >= 0) { + if(rel) + cmd = "l"; + else + cmd = "L"; + d = d.substring(0, pos) + cmd + formalize_path_data(d.substring(pos)); + } + return d; +} + +loadSVG.prototype.parsePath=function(accu, coord,id, n) +{ + var d = formalize_path_data(n.attr('d').value()); + var style = n.attr('style'); + var path = this.mb_rt.path_new(d); + var pcoord = this.mb_rt.coord_new(coord); + + guessPathBoundingBox(pcoord,d); + pcoord.add_shape(path); + this._set_paint(n, path); + this._set_bbox(n, path); + + make_mbnames(this.mb_rt, n, pcoord); +}; + +loadSVG.prototype.parseText=function(accu,coord,id, n) +{ + var x = getInteger(n,'x'); + var y = getInteger(n,'y'); + var tcoord = this.mb_rt.coord_new(coord); + var style; + + if (n.attr('x')) { + var nx = coord[0]*x+coord[1]*y+coord[2]; + if (coord.center.x > nx) + coord.center.x = nx; + } + if (n.attr('y')) { + var ny = coord[3]*x+coord[4]*y+coord[5]; + if (coord.center.y > ny) + coord.center.y = ny; + } + style = parse_style(n); + var nodes = n.childNodes(); + var k; + for(k in nodes) { + var c= nodes[k].name(); + if (c == "tspan") { + this.parseTSpan(tcoord,nodes[k],style); + } else { + } + } + this._set_bbox(n, tcoord); + + make_mbnames(this.mb_rt, n, tcoord); +}; + + +function multiply(s,d) { + var m=[]; + m[0] = s[0]*d[0]+s[1]*d[3]; + m[1] = s[0]*d[1]+s[1]*d[4]; + m[2] = s[0]*d[2]+s[1]*d[5]+s[2]; + m[3] = s[3]*d[0]+s[4]*d[3]; + m[4] = s[3]*d[1]+s[4]*d[4]; + m[5] = s[3]*d[2]+s[4]*d[5]+s[5]; + s[0] = m[0]; + s[1] = m[1]; + s[2] = m[2]; + s[3] = m[3]; + s[4] = m[4]; + s[5] = m[5]; +}; + +function parseTransform(coord, s) +{ + var off = s.indexOf('translate'); + if (off != -1) { + var ss = s.substring(off+9); + for(i=0;i<ss.length;i++) { + if (ss[i] == '(') break; + } + ss = ss.substring(i+1); + for(i=0;i<ss.length;i++) { + if (ss[i] == ')') { + ss = ss.substring(0,i); + break; + } + } + var f = ss.split(','); + var x,y; + x = parseFloat(f[0]); + y = parseFloat(f[1]); + coord[2] += x; + coord[5] += y; + } + off = s.indexOf('matrix'); + if (off != -1) { + var end = s.indexOf(')'); + var m = s.substring(7,end); + var fields = m.split(','); + var newm=[]; + newm[0] = parseFloat(fields[0]); + newm[1] = parseFloat(fields[2]); + newm[2] = parseFloat(fields[4]); + newm[3] = parseFloat(fields[1]); + newm[4] = parseFloat(fields[3]); + newm[5] = parseFloat(fields[5]); + multiply(coord,newm); + } +} + +loadSVG.prototype.parseRect=function(accu_matrix,coord, id, n) +{ + var x = getInteger(n,'x'); + var y = getInteger(n,'y'); + var rx,ry; + var w = getInteger(n,'width'); + var h = getInteger(n,'height'); + var trans = n.attr('transform'); + var paint; + var tcoord = this.mb_rt.coord_new(coord); + + var style = n.attr('style'); + + if (trans) + parseTransform(tcoord,trans.value()); + + var rect = this.mb_rt.rect_new(x,y,w,h,10, 10); + tcoord.add_shape(rect); + this._set_paint(n, rect); + this._set_bbox(n, tcoord); + + make_mbnames(this.mb_rt, n, tcoord); +}; + +// When we parse a group, we need to calculate the origin of the group +// so that we can resize the group without changing its origin point. +// This must be done recursively. For text/rect/image, we can get its +// origin point directly by using the (x,y) and apply their +// transformation matrix. For group, we need to send the acculumated +// matrix so that each group can get their origin correctly. +// +// Each element must be responsible to calculate its absolute origin +// point and update the origin of its parent. + +function parseGroupStyle(style,n) +{ + var attr; + if (n) { + attr = n.attr('style'); + } else { + attr = null; + } + if (attr == null) { + return; + } + var f = attr.value().split(';'); + + for(i in f) { + var kv = f[i].split(':'); + if (kv[0] == 'opacity') { + style.opacity = parseFloat(kv[1]); + } else { + sys.puts("Unknown style: "+kv[0]); + } + } +} + +loadSVG.prototype.parseGroup=function(accu_matrix,root, group_id, n) { + var k; + var nodes = n.childNodes(); + var coord = this.mb_rt.coord_new(root); + // Parse the transform and style here + var trans = n.attr('transform'); + var accu=[1,0,0,0,1,0]; + var style; + + coord.center= new Object(); + coord.center.x = 10000; + coord.center.y = 10000; + if (trans!=null) { + parseTransform(coord, trans.value()); + } + multiply(accu,accu_matrix); + multiply(accu,coord); + + style = {}; + parseGroupStyle(style, n); + if(style.opacity) { + sys.puts("opacity=" + style.opacity); + coord.opacity=style.opacity; + } + + for(k in nodes) { + var c = nodes[k].name(); + var attr = nodes[k].attr('id'); + var id; + if (attr) { + id = attr.value(); + } + if (c == "g") { + this.parseGroup(accu,coord, id, nodes[k]); + } else if (c == "path") { + this.parsePath(accu,coord, id, nodes[k]); + } else if (c == "text") { + this.parseText(accu,coord, id, nodes[k]); + } else if (c == "rect") { + this.parseRect(accu_matrix,coord, id, nodes[k]); + } else if (c == "image") { + this.parseImage(accu_matrix,coord, id, nodes[k]); + } + } + if (root.center.x > coord.center.x) + root.center.x = coord.center.x; + if (root.center.y > coord.center.y) + root.center.y = coord.center.y; + + this._set_bbox(n, coord); + + make_mbnames(this.mb_rt, n, coord); +}; + +loadSVG.prototype.parseImage=function(accu,coord,id, n) +{ + var ref = n.attr('href').value(); + var tcoord = this.mb_rt.coord_new(coord); + var trans = n.attr('transform'); + + if (ref == null) return; + if (ref.substr(0,7) == "file://") { + ref = ref.substring(7); + } else if (ref.substr(0,5)=="file:") { + ref = ref.substring(5); + } else { + } + var w; + var h; + var x,y,nx,ny; + coord.center= new Object(); + coord.center.x = 10000; + coord.center.y = 10000; + if (trans!=null) { + parseTransform(coord, trans.value()); + } + + w = n.attr("width"); + if (w == null) return; + w = parseFloat(w.value()); + h = n.attr("height"); + if (h == null) return; + h = parseFloat(h.value()); + x = n.attr("x"); + if (x == null) return; + x = parseFloat(x.value()); + y = n.attr("y"); + if (y == null) return; + y = parseFloat(y.value()); + nx = tcoord[0]*x+tcoord[1]*y+tcoord[2]; + ny = tcoord[3]*x+tcoord[4]*y+tcoord[5]; + if (coord.center.x > nx) + coord.center.x = nx; + if (coord.center.y > ny) + coord.center.y = ny; + var img = this.mb_rt.image_new(x,y,w,h); + var img_data = ldr.load(ref); + var paint = this.mb_rt.paint_image_new(img_data); + paint.fill(img); + tcoord.add_shape(img); + + this._set_bbox(n, img); + + make_mbnames(this.mb_rt, n, img); +}; + +function _parse_stops(n) { + var children; + var child; + var style; + var color; + var rgb; + var opacity; + var r, g, b, a; + var offset_atr, offset; + var stops = []; + var i; + + children = n.childNodes(); + for(i = 0; i < children.length; i++) { + child = children[i]; + if(child.name() == "stop") { + style = parse_style(child); + + color = style["stop-color"]; + if(color) { + rgb = parse_color(color); + r = rgb[0]; + g = rgb[1]; + b = rgb[2]; + } + + opacity = style["stop-opacity"]; + if(opacity) + a = parseFloat(opacity); + else + a = 1; + + offset_attr = child.attr("offset"); + if(offset_attr) + offset = parseFloat(offset_attr.value()); + else + offset = 0; + + stops.push([offset, r, g, b, a]); + } + } + + return stops; +}; + +loadSVG.prototype._MB_parseLinearGradient=function(root,n) +{ + var id = n.attr('id'); + var k; + var nodes = n.childNodes(); + var mtx = [1, 0, 0, 0, 1, 0]; + + if (id == null) return; + id = id.value(); + + var x1 = n.attr("x1"); + var y1 = n.attr("y1"); + var x2 = n.attr("x2"); + var y2 = n.attr("y2"); + var xy; + var gr; + var color, opacity; + var stops; + var r,g,b; + + if(x1) + x1 = parseFloat(x1.value()); + if(x2) + x2 = parseFloat(x2.value()); + if(y1) + y1 = parseFloat(y1.value()); + if(y2) + y2 = parseFloat(y2.value()); + + stops = _parse_stops(n); + + var href = n.attr('href'); + if(href != null) { + href = href.value(); + var hrefid = href.substring(1); + pstops = this.stop_ref[hrefid]; + if (pstops) + stops = pstops.concat(stops); + + var hrefgr = this.gradients[hrefid]; + if(typeof x1 == "undefined") + x1 = hrefgr[0]; + if(typeof y1 == "undefined") + y1 = hrefgr[1]; + if(typeof x2 == "undefined") + x2 = hrefgr[2]; + if(typeof y2 == "undefined") + y2 = hrefgr[3]; + } + + if(n.attr("gradientTransform")) { + parseTransform(mtx, n.attr("gradientTransform").value()); + xy = _pnt_transform(x1, y1, mtx); + x1 = xy[0]; + y1 = xy[1]; + xy = _pnt_transform(x2, y2, mtx); + x2 = xy[0]; + y2 = xy[1]; + } + + this.stop_ref[id] = stops; + this.gradients[id] = [x1,y1,x2,y2]; +}; + +loadSVG.prototype._MB_parseRadialGradient = function(root,n) { + var stops; + var cx, cy; + var xy; + var mtx = [1, 0, 0, 0, 1, 0]; + var id; + var href; + var r; + + id = n.attr("id"); + if(!id) + throw "Require an id"; + id = id.value(); + + stops = _parse_stops(n); + + cx = n.attr("cx"); + if(!cx) + throw "Miss cx attribute"; + cy = n.attr("cy"); + if(!cy) + throw "Miss cy attribute"; + cx = parseFloat(cx.value()); + cy = parseFloat(cy.value()); + + r = n.attr("r"); + if(!r) + throw "Miss r attribute"; + r = parseFloat(r.value()); + + href = n.attr("href"); + if(href) { + href = href.value().substring(1); + stops = this.stop_ref[href]; + } + + if(n.attr("gradientTransform")) { + parseTransform(mtx, n.attr("gradientTransform").value()); + xy = _pnt_transform(cx, cy, mtx); + cx = xy[0]; + cy = xy[1]; + } + + this.radials[id] = [cx, cy, r]; + this.stop_ref[id] = stops; +} + +loadSVG.prototype.parseScenes=function(coord,node) { + var nodes = node.childNodes(); + + for(k in nodes) { + var name = nodes[k].name(); + if (name == 'scene') { + var node = nodes[k]; + + scene = new Object(); + scene.start = parseInt(node.attr('start').value()); + try { + scene.end = parseInt(node.attr('end').value()); + } catch(e) { + scene.end = scene.start; + } + scene.ref = node.attr('ref').value(); + + try { + this.scenenames[node.attr('name').value()] = scene.start; + } catch(e) { + } + this.scenes.push(scene); + } + } +} + +loadSVG.prototype.parseMetadata=function(coord,node) { + var nodes = node.childNodes(); + + for(k in nodes) { + var name = nodes[k].name(); + if (name == 'scenes') { + this.scenes=[]; + this.scenenames={}; + this.parseScenes(coord,nodes[k]); + } + } +} +loadSVG.prototype.parseDefs=function(root,n) +{ + var k; + var nodes = n.childNodes(); + + for(k in nodes) { + var name = nodes[k].name(); + if (name == "linearGradient") { + this._MB_parseLinearGradient(root,nodes[k]); + } else if(name == "radialGradient") { + this._MB_parseRadialGradient(root,nodes[k]); + } + } +}; + +
--- a/nodejs/testcase.js Mon Jul 19 15:44:49 2010 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -var mbfly = require("mbfly"); -var r = mbfly.Hello(" test"); -var sys = require("sys"); -sys.puts(r); - -var mb_rt = new mbfly.mb_rt(":0.0", 300, 200); -var root = mb_rt.root; -sys.puts("root matrix: " + - [root[0], root[1], root[2], root[3], root[4], root[5]]); -var coord = mb_rt.coord_new(root); -sys.puts("coord matrix: " + - [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]); - -sys.puts(mb_rt.path_new); -var path = mb_rt.path_new("m 100,50 L 120,50 L 200,150 L 180,150 z"); -sys.puts(path); -sys.puts(coord.add_shape); -coord.add_shape(path); - -sys.puts(mb_rt.paint_color_new); -var paint = mb_rt.paint_color_new(1, 1, 1, 1); -sys.puts(paint); -paint.stroke(path); - -sys.puts(path.stroke_width); -path.stroke_width = 2; -sys.puts(path.stroke_width); - -var face = mb_rt.font_face_query("courier", 2, 100); -var blks = [[5, face, 20]]; -var stext = mb_rt.stext_new("Hello", 100, 50); -stext.set_style(blks); -paint.fill(stext); -coord.add_shape(stext); - -mb_rt.redraw_all(); - -var i = 0; -setInterval(function() { - var deg = (i++) * 0.1; - coord[2] = (i % 20) * 10; - mb_rt.redraw_changed(); - }, 50); -setTimeout(function() { sys.puts("timeout"); }, 1000);
--- a/nodejs/wscript Mon Jul 19 15:44:49 2010 +0800 +++ b/nodejs/wscript Wed Dec 01 12:25:56 2010 +0800 @@ -15,19 +15,33 @@ conf.check_tool('compiler_cc') conf.check_tool('node_addon') conf.env.SRCDIR = Options.options.srcdir - conf.env.TOP_BUILDDIR = os.environ['TOP_BUILDDIR'] + conf.env.TOP_BUILDDIR = os.environ['TOP_BUILDDIR'] pass def build(conf): import Utils + for m in 'observer coord mbfly_njs shapes paints'.split(): + conf(rule='m4 -I ${SRCDIR}/../tools gen_v8_binding.m4 ${SRC} > ${TGT}', + source=m+'.m4', target=m+'-inc.h', + name=m+'-inc', shell=True, always=True, before=['cxx']) + pass + obj = conf.new_task_gen('cxx', 'shlib', 'node_addon') obj.target = 'mbfly' - obj.source = 'mbfly_njs.cc coord.cc shapes.cc paints.cc font.cc' - obj.add_objects = 'X_supp_njs.o' + 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' + + for src in 'observer.cc coord.cc mbfly_njs.cc shapes.cc paints.cc'.split(): + obj = conf.new_task_gen('cxx', 'shlib', 'node_addon') + obj.target = src[:-3] + '.o' + obj.source = src + obj.includes = '.' + pass obj = conf.new_task_gen('cc', 'shlib', 'node_addon') - obj.target = 'X_supp_njs.o' - obj.source = 'X_supp_njs.c' + obj.target = 'njs_mb_supp.o' + obj.source = 'njs_mb_supp.c' pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyink/MBScene.py Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,598 @@ +#!/usr/bin/python +# -*- indent-tabs-mode: t; tab-width: 8; python-indent: 4; -*- +# vim: sw=4:ts=8:sts=4 +import pygtk +import gtk +import glib +from copy import deepcopy +from lxml import etree +import random +import traceback +import time +import pybInkscape + +# Please refer to +# http://www.assembla.com/wiki/show/MadButterfly/Inkscape_extention +# for the designed document. + + +# Algorithm: +# +# We will parse the first two level of the SVG DOM. collect a table of +# layer and scene. +# - 1. Collect the layer table which will be displayed as the first +# column of the grid. +# - 2. Get the maximum scene number. This will decide the size of the +# grid. +# - 3. When F6 is pressed, we will check if this scene has been +# defined. This can be done by scan all second level group and +# check if the current scene number is within the range specified +# by scene field. The function IsSceneDefined(scene) can be used +# for this purpose. +# - 4. If this is a new scene, we will append a new group which +# duplication the content of the last scene in the same +# group. The scene field will contain the number from the last +# scene number of the last scene to the current scenen +# number. For example, if the last scene is from 4-7 and the new +# scene is 10, we will set the scene field as "8-10". +# - 5. If this scene are filled screne, we will split the existing +# scene into two scenes with the same content. +# + +class Layer: + def __init__(self,node): + self.scenes = [] + self.node = node + self.nodes=[] + pass + pass + +class Scene: + def __init__(self, node, start,end): + self.node = node + self.start = int(start) + self.end = int(end) + pass + pass + +_scenes = '{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scenes' +_scene = '{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scene' +class LayerAttributeWatcher(pybInkscape.PYNodeObserver): + def __init__(self,ui): + self.ui = ui + def notifyChildAdded(self,node,child,prev): + pass + def notifyChildRemoved(self,node,child,prev): + pass + def notifyChildOrderChanged(self,node,child,prev): + pass + def notifyContentChanged(self,node,old_content,new_content): + pass + def notifyAttributeChanged(self,node, name, old_value, new_value): + self.ui.updateUI() +class LayerAddRemoveWatcher(pybInkscape.PYNodeObserver): + def __init__(self,ui): + self.ui = ui + def notifyChildAdded(self,node,child,prev): + self.ui.updateUI() + def notifyChildRemoved(self,node,child,prev): + self.ui.updateUI() + def notifyChildOrderChanged(self,node,child,prev): + self.ui.updateUI() + def notifyContentChanged(self,node,old_content,new_content): + self.ui.updateUI() + def notifyAttributeChanged(self,node, name, old_value, new_value): + self.ui.updateUI() +class MBScene(): + def __init__(self,desktop,win): + self.desktop = desktop + self.window = win + self.layers = [] + self.layers.append(Layer(None)) + self.scenemap = None + self.top = None + self.last_update = None + pass + + def confirm(self,msg): + vbox = gtk.VBox() + vbox.pack_start(gtk.Label(msg)) + self.button = gtk.Button('OK') + vbox.pack_start(self.button) + self.button.connect("clicked", self.onQuit) + self.window.add(vbox) + pass + + def dumpattr(self,n): + s = "" + for a,v in n.attrib.items(): + s = s + ("%s=%s" % (a,v)) + pass + return s + + def dump(self,node,l=0): + print " " * l*2,"<", node.tag, self.dumpattr(node),">" + for n in node: + self.dump(n,l+1) + pass + print " " * l * 2,"/>" + pass + + def parseMetadata(self,node): + self.current = 1 + for n in node.childList(): + if n.repr.name() == 'ns0:scenes': + self.scenemap={} + try: + cur = int(n.repr.attribute("current")) + except: + cur = 1 + self.current = cur + + for s in n.childList(): + if s.repr.name() == 'ns0:scene': + try: + start = int(s.repr.attribute("start")) + except: + traceback.print_exc() + continue + try: + end = s.repr.attribute("end") + if end == None: + end = start + pass + except: + end = start + pass + link = s.repr.attribute("ref") + self.scenemap[link] = [int(start),int(end)] + print "scene %d to %d" % (self.scenemap[link][0], + self.scenemap[link][1]) + if cur >= start and cur <= end: + self.currentscene = link + pass + pass + pass + pass + pass + pass + if self.scenemap==None: + self.desktop.doc().root().repr.setAttribute("xmlns:ns0","http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd",True) + scenes = self.desktop.doc().rdoc.createElement("ns0:scenes") + node.repr.appendChild(scenes) + def update(self): + doc = self.desktop.doc().root() + rdoc = self.desktop.doc().rdoc + for node in doc.childList(): + if node.repr.name() == 'svg:metadata': + for t in node.childList(): + if t.repr.name() == "ns0:scenes": + node.repr.removeChild(t.repr) + ns = rdoc.createElement("ns0:scenes") + node.repr.appendChild(ns) + for layer in range(0,len(self._framelines)): + lobj = self._framelines[layer] + lobj.addScenes(rdoc,ns) + + + def parseScene(self): + """ + In this function, we will collect all items for the current + scene and then relocate them back to the appropriate scene + object. + """ + self.layers = [] + self.scenemap = None + doc = self.desktop.doc().root() + + #obs = pybInkscape.PYNodeObserver() + obs = LayerAddRemoveWatcher(self) + doc.repr.addObserver(obs) + for node in doc.childList(): + if node.repr.name() == 'svg:metadata': + self.parseMetadata(node) + pass + elif node.repr.name() == 'svg:g': + oldscene = None + obs = LayerAttributeWatcher(self) + node.repr.addObserver(obs) + lyobj = Layer(node) + self.layers.append(lyobj) + lyobj.current_scene = [] + for scene in node.childList(): + if scene.repr.name() == 'svg:g': + try: + scmap = self.scenemap[scene.getId()] + if scmap == None: + lyobj.current_scene.append(scene) + continue + except: + lyobj.current_scene.append(scene) + continue + + lyobj.scenes.append(Scene(scene,scmap[0],scmap[1])) + pass + else: + lyobj.current_scene.append(scene) + pass + pass + pass + pass + + + self.collectID() + self.dumpID() + pass + + def collectID(self): + self.ID = {} + root = self.desktop.doc().root() + for n in root.childList(): + self.collectID_recursive(n) + pass + pass + + def collectID_recursive(self,node): + self.ID[node.getId()] = 1 + for n in node.childList(): + self.collectID_recursive(n) + pass + pass + + def newID(self): + while True: + n = 's%d' % int(random.random()*10000) + #print "try %s" % n + if self.ID.has_key(n) == False: + return n + pass + pass + + def dumpID(self): + for a,v in self.ID.items(): + pass + pass + + def getLayer(self, layer): + for l in self.layers: + if l.node.getId() == layer: + return l + pass + return None + + + def insertKeyScene(self): + """ + Insert a new key scene into the stage. If the nth is always a + key scene, we will return without changing anything. If the + nth is a filled scene, we will break the original scene into + two parts. If the nth is out of any scene, we will append a + new scene. + + """ + x = self.last_frame + y = self.last_line + rdoc = self.desktop.doc().rdoc + ns = rdoc.createElement("svg:g") + txt = rdoc.createElement("svg:rect") + txt.setAttribute("x","0",True) + txt.setAttribute("y","0",True) + txt.setAttribute("width","100",True) + txt.setAttribute("height","100",True) + txt.setAttribute("style","fill:#ff00",True) + ns.appendChild(txt) + gid = self.last_line.node.label()+self.newID() + self.ID[gid]=1 + ns.setAttribute("id",gid,True) + ns.setAttribute("inkscape:groupmode","layer",True) + self.last_line.node.repr.appendChild(ns) + print 'Add key ', x + self.last_line.add_keyframe(x,ns) + self.update() + self.last_line.update() + + + def removeKeyScene(self): + nth = self.last_frame + y = self.last_line + rdoc = self.desktop.doc().rdoc + i = 0 + layer = self.last_line + while i < len(layer._keys): + s = layer._keys[i] + print "nth:%d idx %d" % (nth,s.idx) + if nth > s.idx: + if i == len(layer._keys)-1: + return + if nth == s.idx: + if s.left_tween: + # This is left tween, we move the keyframe one frame ahead + if s.idx == layer._keys[i-1].idx: + layer._keys[i].ref.parent().removeChild(layer._keys[i].ref) + self.last_line.rm_keyframe(nth) + self.last_line.rm_keyframe(nth-1) + else: + s.idx = s.idx-1 + else: + layer._keys[i].ref.parent().removeChild(layer._keys[i].ref) + if s.right_tween: + self.last_line.rm_keyframe(layer._keys[i+1].idx) + self.last_line.rm_keyframe(nth) + else: + self.last_line.rm_keyframe(nth) + + self.update() + self.last_line._draw_all_frames() + self.last_line.update() + return + i = i + 1 + def extendScene(self): + nth = self.last_frame + layer = self.last_line + i = 0 + while i < len(layer._keys): + s = layer._keys[i] + if s.right_tween: + if nth > s.idx: + if nth <= layer._keys[i+1].idx: + return + try: + if nth <= layer._keys[i+2].idx: + layer._keys[i+1].idx = nth + layer.draw_all_frames() + self.update() + self.setCurrentScene(nth) + self.last_line.update() + return + else: + # We may in the next scene + i = i + 2 + pass + except: + # This is the last keyframe, extend the keyframe by + # relocate the location of the keyframe + layer._keys[i+1].idx = nth + layer._draw_all_frames() + self.update() + self.last_line.update() + self.setCurrentScene(nth) + return + else: + # We are in the front of all keyframes + return + else: + # This is a single keyframe + if nth < s.idx: + return + if nth == s.idx: + return + try: + if nth < layer._keys[i+1].idx: + # We are after a single keyframe and no scene is + # available here. Create a new tween here + idx = layer._keys[i].idx + layer.add_keyframe(nth,layer._keys[i].ref) + layer.tween(idx) + layer._draw_all_frames() + self.update() + self.setCurrentScene(nth) + self.last_line.update() + return + else: + # We may in the next scene + i = i + 1 + pass + pass + except: + # This is the last scene, create a new one + idx = layer._keys[i].idx + layer.add_keyframe(nth,layer._keys[i].ref) + layer.tween(idx) + layer._draw_all_frames() + self.update() + self.setCurrentScene(nth) + self.last_line.update() + return + pass + pass + pass + + + def setCurrentScene(self,nth): + self.current = nth + for layer in self._framelines: + i=0 + while i < len(layer._keys): + s = layer._keys[i] + print s.ref.attribute("id"),s.idx,s.left_tween,s.right_tween + if s.right_tween is False: + if nth == s.idx+1: + s.ref.setAttribute("style","",True) + else: + s.ref.setAttribute("style","display:none",True) + i = i + 1 + continue + + if nth >= (s.idx+1) and nth <= (layer._keys[i+1].idx+1): + s.ref.setAttribute("style","",True) + else: + s.ref.setAttribute("style","display:none",True) + i = i + 2 + pass + pass + pass + + + def newCell(self,file): + img = gtk.Image() + img.set_from_file(file) + btn = gtk.EventBox() + btn.add(img) + btn.connect("button_press_event", self.cellSelect) + btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray")) + return btn + + def onCellClick(self,line,frame,but): + self.last_line = line + self.last_frame = frame + self.last_line.active_frame(frame) + self.doEditScene(frame) + + + def _remove_active_frame(self,widget,event): + """ + Hide all hover frames. This is a hack. We should use the lost focus event + instead in the future to reduce the overhead. + """ + for f in self._framelines: + if f != widget: + f.hide_hover() + + def _create_framelines(self): + import frameline + self.scrollwin = gtk.ScrolledWindow() + self.scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.scrollwin.set_size_request(-1,150) + + nframes = 100 + + vbox = gtk.VBox() + vbox.show() + self.scrollwin.add_with_viewport(vbox) + + ruler = frameline.frameruler(nframes) + ruler.set_size_request(nframes * 10, 20) + ruler.show() + hbox = gtk.HBox() + label=gtk.Label('') + label.set_size_request(100,0) + hbox.pack_start(label,expand=False,fill=True) + hbox.pack_start(ruler) + vbox.pack_start(hbox, False) + + # + # Add a frameline for each layer + # + self._framelines = [] + for i in range(len(self.layers)-1,-1,-1): + line = frameline.frameline(nframes) + hbox = gtk.HBox() + label = gtk.Label(self.layers[i].node.label()) + label.set_size_request(100,0) + hbox.pack_start(label,expand=False,fill=True) + hbox.pack_start(line) + line.set_size_request(nframes * 10, 20) + vbox.pack_start(hbox, False) + line.label = label + self._framelines.append(line) + line.connect(line.FRAME_BUT_PRESS, self.onCellClick) + line.nLayer = i + line.node = self.layers[i].node + line.layer = self.layers[i] + line.connect('motion-notify-event', self._remove_active_frame) + pass + pass + + ## \brief Update conetent of frameliens according layers. + # + def _update_framelines(self): + for frameline in self._framelines: + layer = frameline.layer + if frameline.node.label()==None: + frameline.label.set_text('???') + else: + frameline.label.set_text(frameline.node.label()) + for scene in layer.scenes: + frameline.add_keyframe(scene.start-1,scene.node.repr) + if scene.start != scene.end: + frameline.add_keyframe(scene.end-1,scene.node.repr) + frameline.tween(scene.start-1) + pass + pass + pass + + def cellSelect(self, cell, data): + if self.last_cell: + color = self.last_cell.get_colormap().alloc_color("gray") + self.last_cell.modify_bg(gtk.STATE_NORMAL, color) + pass + + self.last_cell = cell + color = cell.get_colormap().alloc_color("green") + cell.modify_bg(gtk.STATE_NORMAL, color) + pass + + def doEditScene(self,w): + self.setCurrentScene(self.last_frame+1) + pass + + def doInsertKeyScene(self,w): + self.insertKeyScene() + # self.grid.show_all() + return + + def doRemoveScene(self,w): + self.removeKeyScene() + return + + + def doExtendScene(self,w): + self.extendScene() + #self.grid.show_all() + pass + + def addButtons(self,hbox): + #btn = gtk.Button('Edit') + #btn.connect('clicked', self.doEditScene) + #hbox.pack_start(btn,expand=False,fill=False) + btn = gtk.Button('Insert Key') + btn.connect('clicked',self.doInsertKeyScene) + hbox.pack_start(btn,expand=False,fill=False) + btn=gtk.Button('Remove Key') + btn.connect('clicked', self.doRemoveScene) + hbox.pack_start(btn,expand=False,fill=False) + btn=gtk.Button('Extend scene') + btn.connect('clicked', self.doExtendScene) + hbox.pack_start(btn,expand=False,fill=False) + pass + + def onQuit(self, event): + self.OK = False + gtk.main_quit() + pass + + def onOK(self,event): + self.OK = True + gtk.main_quit() + pass + + def updateUI(self): + if self.last_update!= None: + glib.source_remove(self.last_update) + self.last_update = glib.timeout_add(300,self.show) + def show(self): + self.OK = True + self.parseScene() + self._create_framelines() + self._update_framelines() + if self.top == None: + self.top = gtk.VBox(False,0) + self.desktop.getToplevel().child.child.pack_end(self.top,expand=False) + else: + self.top.remove(self.startWindow) + vbox = gtk.VBox(False,0) + self.startWindow = vbox + self.top.pack_start(vbox,expand=False) + vbox.pack_start(self.scrollwin,expand=False) + hbox=gtk.HBox(False,0) + self.addButtons(hbox) + vbox.pack_start(hbox,expand=False) + + # self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + # self.window.connect("destroy", gtk.main_quit) + # self.window.set_position(gtk.WIN_POS_MOUSE) + + self.top.show_all() + self.last_update = None + return False + pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyink/frameline.py Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,689 @@ +import pygtk +pygtk.require("2.0") +import gtk +import gtk.gdk +import pango +import gobject + +def color_to_rgb(v): + return (((v >> 16) & 0xff) * 65535 / 0xff, + ((v >> 8) & 0xff) * 65535 / 0xff, + (v & 0xff) * 65535 / 0xff) + +class keyframe(object): + def __init__(self, frame_idx): + self.idx = frame_idx + self.left_tween = False + self.right_tween = False + self.right_tween_type = 0 + self.ref='' + pass + pass + +class frameruler(gtk.DrawingArea): + _type = 0 + _frame_width = 10 # Width for each frame is 10 pixels + _mark_color = 0x808080 # color of mark lines + _number_color = 0x000000 # color of frame number + _number_sz = 8 # font size of frame number + + def __new__(clz, *args): + if not frameruler._type: + frameruler._type = gobject.type_register(frameruler) + pass + fr = gobject.new(frameruler._type) + return fr + + def __init__(self, num_frames=20): + self.connect('expose_event', self._fr_expose) + self._num_frames = num_frames + pass + + def _fr_expose(self, widget, event): + self.update() + pass + + def queue_draw(self): + print 'queue_draw' + self.update() + pass + + def queue_draw_area(self, x, y, w, h): + print 'queue_draw_area' + pass + + def update(self): + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + + gc = gtk.gdk.GC(win) + + # + # Set color of mark lines + # + color_rgb = color_to_rgb(self._mark_color) + color = gtk.gdk.Color(*color_rgb) + gc.set_rgb_fg_color(color) + + # + # Mark mark lines + # + mark_h = w_h / 10 + for i in range(self._num_frames): + mark_x = (i + 1) * self._frame_width + win.draw_line(gc, mark_x, 0, mark_x, mark_h) + win.draw_line(gc, mark_x, w_h - mark_h - 1, mark_x, w_h - 1) + pass + + win.draw_line(gc, 0, w_h - 1, w_w, w_h -1) + + # + # Set color of frame number + # + color_rgb = color_to_rgb(self._number_color) + color = gtk.gdk.Color(*color_rgb) + gc.set_rgb_fg_color(color) + + font_desc = pango.FontDescription() + font_desc.set_size(self._number_sz * pango.SCALE) + + number_y = (w_h - self._number_sz) / 2 + + # + # Draw frame number + # + layout = self.create_pango_layout('1') + layout.set_font_description(font_desc) + win.draw_layout(gc, 0, number_y, layout) + for i in range(4, self._num_frames, 5): + mark_x = i * self._frame_width + layout.set_text(str(i + 1)) + win.draw_layout(gc, mark_x, number_y, layout) + pass + pass + pass + +## Show frame status of a layer +# +# \section frameline_sigs Signals +# - 'frame-button-pree' for user press on a frame. +# - callback(widget, frame_idx, button) +# +class frameline(gtk.DrawingArea): + _type = 0 + _frame_width = 10 # Width for each frame is 10 pixels + _select_color = 0xee2222 # color of border of selected frame + _key_mark_color = 0x000000 # color of marks for key frames. + _key_mark_sz = 4 # width and height of a key frame mark + _tween_color = 0x808080 # color of tween line + _tween_bgcolors = [0x80ff80, 0xff8080] # bg colors of tween frames + # Colors for normal frames + _normal_bgcolors = [0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xcccccc] + _normal_border = 0xaaaaaa # border color of normal frames. + _active_border = 0xff3030 # border color of an active frame + _hover_border_color = 0xa0a0a0 # border when the pointer over a frame + # tween types + _tween_type_none=0 + _tween_type_shape=3 + + + FRAME_BUT_PRESS = 'frame-button-press' + + def __new__(clz, *args): + if not frameline._type: + frameline._type = gobject.type_register(frameline) + but_press = gobject.signal_new(frameline.FRAME_BUT_PRESS, + frameline._type, + gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + (gobject.TYPE_INT, + gobject.TYPE_INT)) + frameline._sig_frame_but_press = but_press + pass + fl_obj = gobject.new(frameline._type) + return fl_obj + + def __init__(self, num_frames=20): + self.connect('button-press-event', self._press_hdl) + self.connect('expose-event', self._fl_expose) + self.connect('motion-notify-event', self._motion_hdl) + self._num_frames = num_frames + self._keys = [] + self._active_frame = -1 + self._last_hover = -1 # frame index of last hover + self._drawing = False + pass + + def _press_hdl(self, widget, event): + frame = event.x / self._frame_width + but = event.button + self.emit(frameline.FRAME_BUT_PRESS, frame, but) + pass + def hide_hover(self): + if self._active_frame != self._last_hover: + self._draw_normal_frame(self._last_hover) + + def _motion_hdl(self, widget, event): + frame = int(event.x / self._frame_width) + + if frame < self._num_frames and frame >= 0: + self._draw_hover(frame) + pass + + def _fl_expose(self, widget, event): + win = self.window + x, y, w, h, depth = win.get_geometry() + if not hasattr(self, '_gc'): + self._gc = gtk.gdk.GC(win) + # + # register for button press event + # + emask = win.get_events() + emask = emask | gtk.gdk.BUTTON_PRESS_MASK | \ + gtk.gdk.POINTER_MOTION_MASK + win.set_events(emask) + self._drawing = True + pass + self.update() + pass + + def _draw_tween(self, first_key, last_key): + if not self._drawing: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + + # + # Get background color of a tween + # + bg_idx = first_key.right_tween_type + bg_color_v = self._tween_bgcolors[bg_idx] + bg_color_rgb = color_to_rgb(bg_color_v) + bg_color = gtk.gdk.Color(*bg_color_rgb) + + gc = self._gc + gc.set_rgb_fg_color(bg_color) + + draw_x = first_key.idx * self._frame_width + 1 + draw_w = (last_key.idx - first_key.idx + 1) * self._frame_width - 1 + + win.draw_rectangle(gc, True, draw_x, 0, draw_w, w_h) + + # + # Set color of tween line + # + line_v = self._tween_color + line_rgb = color_to_rgb(line_v) + line_color = gtk.gdk.Color(*line_rgb) + gc.set_rgb_fg_color(line_color) + + # + # Draw tween line + # + line_x1 = int((first_key.idx + 0.5) * self._frame_width) + line_x2 = line_x1 + (last_key.idx - first_key.idx) * self._frame_width + line_y = int(w_h * 2 / 3) + win.draw_line(gc, line_x1, line_y, line_x2, line_y) + pass + + def _draw_normal_frame(self, idx): + if not self._drawing: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + + gc = self._gc + bg_idx = idx % len(self._normal_bgcolors) + rgb = color_to_rgb(self._normal_bgcolors[bg_idx]) + color = gtk.gdk.Color(*rgb) + gc.set_rgb_fg_color(color) + + f_x = self._frame_width * idx + win.draw_rectangle(gc, True, f_x + 1, 0, self._frame_width - 1, w_h) + next_f_x = f_x + self._frame_width + + border_rgb = color_to_rgb(self._normal_border) + border_color = gtk.gdk.Color(*border_rgb) + gc.set_rgb_fg_color(border_color) + gc.set_line_attributes(1, gtk.gdk.LINE_SOLID, + gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER) + win.draw_line(gc, next_f_x, 0, next_f_x, w_h) + pass + + ## \brief Draw a bottom line from start to the point before stop frame. + # + def _draw_bottom_line(self, start, stop): + if not self._drawing: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + gc = self._gc + + border_rgb = color_to_rgb(self._normal_border) + border_color = gtk.gdk.Color(*border_rgb) + gc.set_rgb_fg_color(border_color) + start_x = start * self._frame_width + stop_x = stop * self._frame_width + win.draw_line(gc, start_x, w_h - 1, stop_x, w_h - 1) + pass + + def _draw_all_frames(self): + if not self._drawing: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + gc = self._gc + + i = 0 + key_i = 0 + try: + key = self._keys[key_i] + except IndexError: + key = keyframe(self._num_frames) + pass + num_frames = self._num_frames + while i < num_frames: + if key.idx == i and key.right_tween: + # + # Skip tween keys + # + first_tween_key = key + while key.idx == i or key.left_tween: + last_tween_key = key + key_i = key_i + 1 + try: + key = self._keys[key_i] + except IndexError: + key = keyframe(self._num_frames) + pass + pass + + if first_tween_key != last_tween_key: + self._draw_tween(first_tween_key, last_tween_key) + + i = last_tween_key.idx + 1 + pass + else: + if key.idx == i: + key_i=key_i+1 + try: + key = self._keys[key_i] + except: + key = keyframe(self._num_frames) + self._draw_normal_frame(i) + i = i + 1 + pass + pass + + self._draw_bottom_line(0, num_frames) + pass + + def _draw_keyframe(self, frame_idx): + if not self._drawing: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + + color_v = self._key_mark_color + color_rgb = color_to_rgb(color_v) + color = gtk.gdk.Color(*color_rgb) + + gc = self._gc + gc.set_rgb_fg_color(color) + + mark_sz = self._key_mark_sz + mark_x = int((frame_idx + 0.5) * self._frame_width - mark_sz / 2) + mark_y = w_h * 2 / 3 - mark_sz / 2 + + win.draw_rectangle(gc, True, mark_x, mark_y, mark_sz, mark_sz) + pass + + def _draw_keyframes(self): + if not self._drawing: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + + color_v = self._key_mark_color + color_rgb = color_to_rgb(color_v) + color = gtk.gdk.Color(*color_rgb) + + gc = self._gc + gc.set_rgb_fg_color(color) + + for key in self._keys: + if key.left_tween is True and lastkey.right_tween_type == frameline._tween_type_none: + continue + + mark_sz = self._key_mark_sz + mark_x = int((key.idx + 0.5) * self._frame_width - mark_sz / 2) + mark_y = w_h * 2 / 3 - mark_sz / 2 + + win.draw_rectangle(gc, True, mark_x, mark_y, mark_sz, mark_sz) + lastkey = key + pass + pass + + def _draw_active(self): + if not self._drawing: + return + + if self._active_frame == -1: + return + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + + color_v = self._active_border + color_rgb = color_to_rgb(color_v) + color = gtk.gdk.Color(*color_rgb) + + gc = self._gc + gc.set_rgb_fg_color(color) + + idx = self._active_frame + line_x1 = idx * self._frame_width + line_x2 = line_x1 + self._frame_width + + win.draw_line(gc, line_x1, 0, line_x1, w_h) + win.draw_line(gc, line_x2, 0, line_x2, w_h) + win.draw_line(gc, line_x1, w_h - 1, line_x2, w_h - 1) + win.draw_line(gc, line_x1, 0, line_x2, 0) + pass + + ## \brief Find the range a continous tween. + # + def _find_tween_range(self, key_pos): + first_pos = key_pos + while first_pos and self._keys[first_pos].left_tween: + first_pos = first_pos - 1 + pass + + max_pos = len(self._keys) - 1 + + last_pos = key_pos + while last_pos < max_pos and self._keys[last_pos].right_tween: + last_pos = last_pos + 1 + pass + + return first_pos, last_pos + + ## \brief Redraw a frame specified by an index. + # + def _redraw_frame(self, frame_idx): + if not self._drawing: + return + + keys = [key.idx for key in self._keys] + if len(keys): + try: + pos = keys.index(frame_idx) + except ValueError: + keys.append(frame_idx) + keys.sort() + pos = keys.index(frame_idx) - 1 + pass + if pos < 0: + pos = 0 + pass + key = self._keys[pos] + else: + key = None + pass + + if key and (key.right_tween or \ + (key.left_tween and key.idx == frame_idx)): + # + # in tween + # + first_pos, last_pos = self._find_tween_range(pos) + first_key = self._keys[first_pos] + last_key = self._keys[last_pos] + + self._draw_tween(first_key, last_key) + self._draw_bottom_line(first_key.idx, last_key.idx + 1) + + for i in range(first_pos, last_pos + 1): + key = self._keys[i] + if key.left_tween is False or lastkey.right_tween_type != frameline._tween_type_none: + self._draw_keyframe(key.idx) + lastkey = key + pass + pass + else: # not in tween + self._draw_normal_frame(frame_idx) + self._draw_bottom_line(frame_idx, frame_idx + 1) + if key and (key.idx == frame_idx): + self._draw_keyframe(frame_idx) + pass + pass + pass + + ## \brief Show a mark for the pointer for a frame. + # + def _draw_hover(self, frame_idx): + if not self._drawing: + return + + if self._last_hover != -1: + self._redraw_frame(self._last_hover) + pass + + self._draw_active() + + win = self.window + w_x, w_y, w_w, w_h, depth = win.get_geometry() + gc = self._gc + + color_rgb = color_to_rgb(self._hover_border_color) + color = gtk.gdk.Color(*color_rgb) + gc.set_rgb_fg_color(color) + + line_x1 = frame_idx * self._frame_width + 1 + line_x2 = line_x1 + self._frame_width - 2 + + win.draw_line(gc, line_x1, 1, line_x1, w_h - 2) + win.draw_line(gc, line_x2, 1, line_x2, w_h - 2) + win.draw_line(gc, line_x1, 1, line_x2, 1) + win.draw_line(gc, line_x1, w_h - 2, line_x2, w_h - 2) + + self._last_hover = frame_idx + pass + + def update(self): + if not self._drawing: + return + + win = self.window + x, y, w, h, depth = win.get_geometry() + self._draw_all_frames() + self._draw_keyframes() + if self._active_frame != -1: + self._draw_active() + pass + pass + + ## Add a key frame + # + # A key frame is the frame that user specify actions. For + # example, move a object or add new objects at the frame. + def add_keyframe(self, idx,ref=None): + key_indic = [key.idx for key in self._keys] + if idx in key_indic: + return + + key_indic.append(idx) + key_indic.sort() + insert_pos = key_indic.index(idx) + + key = keyframe(idx) + key.ref = ref + self._keys[insert_pos:insert_pos] = [key] + if insert_pos > 0 and self._keys[insert_pos - 1].right_tween: + key.left_tween = True + pass + if insert_pos < (len(self._keys) - 1) and \ + self._keys[insert_pos + 1].left_tween: + key.right_tween = True + pass + + self._draw_keyframe(idx) + pass + + def rm_keyframe(self, idx): + found=False + for i in range(0,len(self._keys)): + if self._keys[i].idx == idx: + idx = i + found = True + break + if not found: return + key = self._keys[idx] + + if key.right_tween ^ key.left_tween: + # + # tween in one side + # + if key.right_tween: + right_key = self._keys[idx] + right_key.left_tween = False + redraw_range = (right_key.idx, idx + 1) + else: + left_key = self._keys[idx - 1] + left_key.right_key = False + redraw_range = (idx, left_key.idx + 1) + pass + for i in range(*redraw_range): + self._redraw_frame(i) + pass + else: + self._redraw_frame(idx) + pass + + del self._keys[idx] + self._draw_active() + pass + + ## Tween the key frame specified by an index and the key frame at right. + # + # \see http://www.entheosweb.com/Flash/shape_tween.asp + def tween(self, idx, _type=0): + key_indic = [key.idx for key in self._keys] + pos = key_indic.index(idx) + key = self._keys[pos] + + try: + right_key = self._keys[pos + 1] + except IndexError: + raise ValueError, 'No right key frame' + + key.right_tween = True + right_key.left_tween = True + key.right_tween_type = _type + pass + + ## Set active frame + # + # The active frame is the frame that is working on. + # + def active_frame(self, idx): + if idx < 0 or idx >= self._num_frames: + raise IndexError, 'value of index (%d) is out of range' % (idx) + + if self._active_frame != -1: + self._redraw_frame(self._active_frame) + pass + self._active_frame = idx + self._draw_active() + pass + + def deactive(self): + self._redraw_frame(self._active_frame) + self._active_frame = -1 + pass + + def set_num_frames(self, num): + self._num_frames = num + pass + + def reset(self): + self._keys = [] + pass + + def addScenes(self,rdoc,node): + for i in range(0,len(self._keys)): + key = self._keys[i] + if key.left_tween is True: continue + if key.right_tween is True: + ss = rdoc.createElement("ns0:scene") + node.appendChild(ss) + ss.setAttribute("start", str(key.idx+1),True) + ss.setAttribute("ref",key.ref.attribute("id"),True) + ss.setAttribute("end", str(self._keys[i+1].idx+1),True) + else: + ss = rdoc.createElement("ns0:scene") + node.appendChild(ss) + ss.setAttribute("start", str(key.idx+1),True) + ss.setAttribute("ref",key.ref.attribute("id"),True) + + + ## \brief Start future drawing actions + # + def start_drawing(self): + self._drawing = True + pass + + ## \brief Stop any future drawing actions + # + # When doing massive udpate, to stop drawing the screen make + # application more effecient. The screen is updated by calling + # update() method after massive update and calliing start_drawing(). + # + def stop_drawing(self): + self._drawing = False + pass + + def __len__(self): + return self._num_frames + pass + +if __name__ == '__main__': + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + fr = frameruler(40) + fr.set_size_request(300, 20) + + fl = frameline(40) + fl.set_size_request(300, 20) + fl.add_keyframe(15) + fl.add_keyframe(3) + fl.tween(3) + fl.add_keyframe(9) + fl.add_keyframe(20) + fl.tween(9) + fl.active_frame(1) + fl.rm_keyframe(15) + print 'num of frames: %d' % (len(fl)) + + def press_sig(fl, frame, but): + print 'press_sig button %d for frame %d' % (but, frame) + pass + fl.connect(frameline.FRAME_BUT_PRESS, press_sig) + + box = gtk.VBox() + + box.pack_start(fr, False) + box.pack_start(fl, False) + window.add(box) + + fr.show() + fl.show() + box.show() + window.show() + gtk.main() + pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyink/mbtest.svg Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,374 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:ns0="http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="640px" + height="480px" + id="svg2383" + sodipodi:version="0.32" + inkscape:version="0.48+devel r9764 custom" + sodipodi:docname="mbtest.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.1"> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.6029106" + inkscape:cx="69.206233" + inkscape:cy="290.40921" + inkscape:current-layer="layer2" + inkscape:document-units="px" + showgrid="false" + inkscape:window-width="1400" + inkscape:window-height="974" + inkscape:window-x="271" + inkscape:window-y="25" + inkscape:window-maximized="0" /> + <defs + id="defs2385"> + <linearGradient + inkscape:collect="always" + id="linearGradient3211"> + <stop + style="stop-color:#001dff;stop-opacity:1;" + offset="0" + id="stop3213" /> + <stop + style="stop-color:#001dff;stop-opacity:0;" + offset="1" + id="stop3215" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 240 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="640 : 240 : 1" + inkscape:persp3d-origin="320 : 160 : 1" + id="perspective2391" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211" + id="linearGradient3217" + x1="31.940987" + y1="28.009715" + x2="104.68548" + y2="28.009715" + gradientUnits="userSpaceOnUse" /> + <filter + inkscape:collect="always" + id="filter3295"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.67110109" + id="feGaussianBlur3297" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211" + id="linearGradient3316" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009715" + x2="104.68548" + y2="28.009715" /> + <linearGradient + y2="28.009715" + x2="104.68548" + y1="28.009715" + x1="31.940987" + gradientUnits="userSpaceOnUse" + id="linearGradient3542" + xlink:href="#linearGradient3211" + inkscape:collect="always" /> + <linearGradient + y2="28.009715" + x2="104.68548" + y1="28.009715" + x1="31.940987" + gradientUnits="userSpaceOnUse" + id="linearGradient3544" + xlink:href="#linearGradient3211" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0" + id="linearGradient3316-4" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3211-0"> + <stop + style="stop-color:#001dff;stop-opacity:1;" + offset="0" + id="stop3213-3" /> + <stop + style="stop-color:#001dff;stop-opacity:0;" + offset="1" + id="stop3215-9" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0" + id="linearGradient3217-6" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0-5" + id="linearGradient3316-4-8" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3211-0-5"> + <stop + style="stop-color:#001dff;stop-opacity:1;" + offset="0" + id="stop3213-3-8" /> + <stop + style="stop-color:#001dff;stop-opacity:0;" + offset="1" + id="stop3215-9-4" /> + </linearGradient> + <filter + color-interpolation-filters="sRGB" + inkscape:collect="always" + id="filter3295-1-3"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.67110109" + id="feGaussianBlur3297-9-7" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0-5" + id="linearGradient3217-6-1" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3211-0-5" + id="linearGradient3237" + gradientUnits="userSpaceOnUse" + x1="31.940987" + y1="28.009714" + x2="104.68548" + y2="28.009714" /> + </defs> + <metadata + id="metadata2388"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + <ns0:scenes> + <ns0:scene + start="1" + ref="g3189" + end="15" /> + <ns0:scene + start="1" + ref="s4427" /> + <ns0:scene + start="2" + ref="s4159" /> + <ns0:scene + start="5" + ref="s9524" + end="10" /> + <ns0:scene + start="15" + ref="s6546" /> + </ns0:scenes> + </metadata> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Background" + style="display:inline"> + <g + id="g3189" + style=""> + <rect + style="fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;display:inline" + id="rect2437" + width="641.95721" + height="481.62387" + x="0.93578684" + y="-10.98185" /> + <rect + style="fill:#ffcc1d;fill-opacity:1;stroke:none" + id="rect3698" + width="624.48901" + height="46.789886" + x="6.8625164" + y="5.8625031" + rx="10" + ry="10" /> + <g + style="display:inline" + transform="translate(-11.385541,2.6514388)" + id="g3303"> + <rect + y="15.22048" + x="32.440987" + height="25.57847" + width="71.744492" + id="rect2439" + style="fill:url(#linearGradient3237);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" /> + <text + id="text3299" + y="33.312569" + x="39.927368" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:16px" + y="33.312569" + x="39.927368" + id="tspan3301" + sodipodi:role="line">Action</tspan></text> + </g> + <g + style="display:inline" + id="g3308" + transform="translate(76.891374,2.9633707)"> + <rect + y="15.22048" + x="32.440987" + height="25.57847" + width="71.744492" + id="rect3310" + style="fill:url(#linearGradient3316-4-8);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" /> + <text + id="text3312" + y="33.312569" + x="39.927368" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + style="font-size:16px" + y="33.312569" + x="39.927368" + id="tspan3314" + sodipodi:role="line">Select</tspan></text> + </g> + </g> + <g + id="s4393" + style="" /> + </g> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="Buton" + style="display:inline"> + <g + id="s4427" + style="display:none" /> + <g + id="s4159" + transform="translate(170.31517,0.62386544)" + style="display:none"> + <g + transform="translate(4.9909171,0.3119319)" + id="g3370"> + <rect + style="fill:url(#linearGradient3542);fill-opacity:1;stroke:none;filter:url(#filter3295)" + id="rect3372" + width="71.744492" + height="25.57847" + x="32.440987" + y="15.22048" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="35.927368" + y="33.312569" + id="text3374"><tspan + sodipodi:role="line" + id="tspan3376" + x="35.927368" + y="33.312569" + style="font-size:16px">GNOME</tspan></text> + </g> + <g + transform="translate(102.93775,-0.9357981)" + id="g3380"> + <rect + style="fill:url(#linearGradient3544);fill-opacity:1;stroke:none;filter:url(#filter3295)" + id="rect3382" + width="71.744492" + height="25.57847" + x="32.440987" + y="15.22048" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="39.927368" + y="33.312569" + id="text3384"><tspan + sodipodi:role="line" + id="tspan3386" + x="39.927368" + y="33.312569" + style="font-size:16px">AAA</tspan></text> + </g> + </g> + <g + id="s9524" + transform="translate(90.460441,64.258106)" + style="display:none"> + <rect + x="0" + y="0" + width="100" + height="100" + id="rect3118" /> + </g> + <g + id="s6546" + style="display:none"> + <rect + x="0" + y="0" + width="100" + height="100" + style="fill:#ff00" + id="rect3116" /> + </g> + </g> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer" + style="display:inline" /> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyink/pyink.py Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,25 @@ +import pybInkscape +import pygtk +import gtk +from MBScene import * +global ink_inited +ink_inited=0 +def start_desktop(inkscape,ptr): + global ink_inited + if ink_inited == 1: + desktop = pybInkscape.GPointer_2_PYSPDesktop(ptr) + top = desktop.getToplevel() + #dock = desktop.getDock() + #item = dock.new_item("scene", "scene", "feBlend-icon", dock.ITEM_ST_DOCKED_STATE) + scene = MBScene(desktop,top) + scene.show() + return + + + ink_inited = 1 + + +def pyink_start(): + print 'pyink_start()' + pybInkscape.inkscape.connect('activate_desktop', start_desktop) + pass
--- a/src/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/src/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 include $(top_srcdir)/config.mk lib_LTLIBRARIES = libmbfly.la @@ -22,7 +24,7 @@ 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@ @@ -34,10 +36,24 @@ libmbfly_la_SOURCES += shape_stext.c endif -if X_SUPP +if X_BACKEND libmbfly_la_SOURCES += X_supp.c endif +if DFB_BACKEND +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 @@ -45,10 +61,18 @@ libmbfly_la_LDFLAGS += @cairo_LIBS@ @pangocairo_LIBS@ endif +if XSHM +libmbfly_la_LDFLAGS += -lXext +endif + if SKIA_GRAPH_ENGINE 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
--- a/src/Makefile.pmake Mon Jul 19 15:44:49 2010 +0800 +++ b/src/Makefile.pmake Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 SRCS = coord.c geo.c shape_path.c shape_text.c shape_rect.c \ shape_image.c \ redraw_man.c timer.c animate.c paint.c event.c observer.c \
--- a/src/X_main.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/X_main.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <unistd.h> #include <sys/time.h> @@ -13,6 +15,7 @@ #include "mb_paint.h" #include "mb_timer.h" #include "mb_animate.h" +#include "mb_backend_utils.h" #define OK 0 #define ERR -1 @@ -67,15 +70,18 @@ XFlush(display); } -void handle_connection(Display *display, mb_tman_t *tman, +void handle_connection(Display *display, mb_timer_man_t *timer_man, redraw_man_t *rdman, int w, int h) { int xcon; fd_set rds; int nfds; struct timeval tmo; mb_timeval_t mb_tmo, next_mb_tmo; + mb_tman_t *tman; int r; + tman = tman_timer_man_get_tman(timer_man); + XSelectInput(display, win, PointerMotionMask | ExposureMask); XFlush(display); @@ -134,7 +140,7 @@ grad_stop_t fill3_stops[3]; mbe_font_face_t *face; struct timeval tv; - mb_tman_t *tman; + mb_timer_man_t *timer_man; mb_timeval_t mbtv, start, playing; mb_progm_t *progm; mb_word_t *word; @@ -191,7 +197,7 @@ rdman_add_shape(&rdman, (shape_t *)path1, coord1); rdman_add_shape(&rdman, (shape_t *)path2, coord2); - + fill3 = rdman_paint_linear_new(&rdman, 50, 50, 150, 150); grad_stop_init(fill3_stops, 0, 1, 0, 0, 0.5); grad_stop_init(fill3_stops + 1, 0.5, 0, 1, 0, 0.5); @@ -205,11 +211,11 @@ XFlush(display); - tman = mb_tman_new(); - if(tman) { + timer_man = mb_timer_man_new(&tman_timer_factory); + if(timer_man) { /* Prepare an animation program. */ - progm = mb_progm_new(10, &rdman); - + progm = mb_progm_new(30, &rdman); + MB_TIMEVAL_SET(&start, 0, 0); MB_TIMEVAL_SET(&playing, 1, 0); word = mb_progm_next_word(progm, &start, &playing); @@ -224,7 +230,7 @@ act = mb_shift_new(0, 20, coord1, word); act = mb_shift_new(0, -20, coord2, word); act = mb_visibility_new(VIS_HIDDEN, coord3, word); - + MB_TIMEVAL_SET(&start, 3, 0); MB_TIMEVAL_SET(&playing, 2, 0); word = mb_progm_next_word(progm, &start, &playing); @@ -234,16 +240,176 @@ act = mb_chgcolor_new(0, 0, 1, 0.5, fill1, word); act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); act = mb_visibility_new(VIS_VISIBLE, coord3, word); - + + MB_TIMEVAL_SET(&start, 5, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill1, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 7, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 9, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 11, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 13, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 15, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 17, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 19, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 21, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 23, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 25, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 27, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 29, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 31, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 33, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 35, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + /* Start playing the program. */ gettimeofday(&tv, NULL); MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); - mb_progm_start(progm, tman, &mbtv); + mb_progm_start(progm, timer_man, &mbtv); - handle_connection(display, tman, &rdman, w, h); + handle_connection(display, timer_man, &rdman, w, h); mb_progm_free(progm); - mb_tman_free(tman); + mb_timer_man_free(&tman_timer_factory, timer_man); } rdman_paint_free(&rdman, fill1);
--- a/src/X_supp.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/X_supp.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,18 +1,36 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #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" #include "mb_X_supp.h" +#include "mb_backend.h" +#include "mb_backend_utils.h" +#include "config.h" + +#ifdef XSHM +/* \sa http://www.xfree86.org/current/mit-shm.html */ +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +static void XSHM_update(X_supp_runtime_t *xmb_rt); +#endif #define ERR -1 #define OK 0 +#define ASSERT(x) + #define ONLY_MOUSE_MOVE_RAW 1 +static mb_timer_factory_t *_timer_factory = &tman_timer_factory; + /*! \ingroup xkb * @{ */ @@ -21,18 +39,12 @@ int ksym_per_code; KeySym *syms; subject_t *kbevents; - ob_factory_t *ob_factory; + observer_factory_t *observer_factory; }; /* @} */ -#define MAX_MONITORS 200 -typedef struct { - int type; - int fd; - mb_eventcb_t f; - void *arg; -} monitor_t; -struct _X_MB_runtime { + +struct _X_supp_runtime { Display *display; Window win; Visual *visual; @@ -40,20 +52,221 @@ mbe_pattern_t *surface_ptn; mbe_t *cr, *backend_cr; redraw_man_t *rdman; - mb_tman_t *tman; mb_img_ldr_t *img_ldr; int w, h; X_kb_info_t kbinfo; - monitor_t monitors[MAX_MONITORS]; - int n_monitor; + mb_IO_man_t *io_man; + mb_timer_man_t *timer_man; #ifndef ONLY_MOUSE_MOVE_RAW /* States */ shape_t *last; #endif + +#ifdef XSHM + XImage *ximage; + XShmSegmentInfo shminfo; +#endif + + /* For handle connection */ + int io_hdl; + + /* + * Following variables are used by handle_single_x_event() + */ + int last_evt_type; /* Type of last event */ + int eflag; + int ex1, ey1, ex2, ey2; /* Aggregate expose events */ + int mflag; + int mx, my; /* Position of last motion event */ + int mbut_state; /* Button state of last motion event */ }; +static void _x_supp_handle_x_event(X_supp_runtime_t *rt); + +/*! \defgroup x_supp_io IO manager for X. + * @{ + */ +#define MAX_MONITORS 200 + +typedef struct { + int type; + int fd; + mb_IO_cb_t cb; + void *data; +} monitor_t; + +struct _X_supp_IO_man { + mb_IO_man_t io_man; + monitor_t monitors[MAX_MONITORS]; + int n_monitor; +}; + +static int _x_supp_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, + mb_IO_cb_t cb, void *data); +static void _x_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl); +static mb_IO_man_t *_x_supp_io_man_new(void); +static void _x_supp_io_man_free(mb_IO_man_t *io_man); + +static mb_IO_factory_t _X_supp_default_io_factory = { + _x_supp_io_man_new, + _x_supp_io_man_free +}; +static mb_IO_factory_t *_io_factory = &_X_supp_default_io_factory; + +static struct _X_supp_IO_man _default_io_man = { + {_x_supp_io_man_reg, _x_supp_io_man_unreg}, + {}, /* monitors */ + 0 /* n_monitor */ +}; + +static mb_IO_man_t * +_x_supp_io_man_new(void) { + return (mb_IO_man_t *)&_default_io_man; +} + +static void +_x_supp_io_man_free(mb_IO_man_t *io_man) { +} + +static int +_x_supp_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) { + struct _X_supp_IO_man *xmb_io_man = (struct _X_supp_IO_man *)io_man; + int i; + + for(i = 0; i < xmb_io_man->n_monitor; i++) { + if (xmb_io_man->monitors[i].type == MB_IO_DUMMY) + break; + } + if (i == MAX_MONITORS) + return ERR; + + xmb_io_man->monitors[i].type = type; + xmb_io_man->monitors[i].fd = fd; + xmb_io_man->monitors[i].cb = cb; + xmb_io_man->monitors[i].data = data; + i++; + if(i > xmb_io_man->n_monitor) + xmb_io_man->n_monitor = i; + return i - 1; +} + +static void +_x_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) { + struct _X_supp_IO_man *xmb_io_man = (struct _X_supp_IO_man *)io_man; + + ASSERT(io_hdl < xmb_io_man->n_monitor); + xmb_io_man->monitors[io_hdl].type = MB_IO_DUMMY; +} + +/*! \brief Handle connection coming data and timeout of timers. + * + * \param display is a Display returned by XOpenDisplay(). + * \param rdman is a redraw manager. + * \param tman is a timer manager. + * + * The display is managed by specified rdman and tman. rdman draws + * on the display, and tman trigger actions according timers. + */ +static void +_x_supp_event_loop(mb_rt_t *rt) { + struct _X_supp_runtime *xmb_rt = (struct _X_supp_runtime *)rt; + struct _X_supp_IO_man *io_man = (struct _X_supp_IO_man *)xmb_rt->io_man; + mb_timer_man_t *timer_man = (mb_timer_man_t *)xmb_rt->timer_man; + redraw_man_t *rdman; + mb_tman_t *tman = tman_timer_man_get_tman(timer_man); + mb_timeval_t now, tmo; + struct timeval tv; + fd_set rfds, wfds; + int nfds = 0; + int r, r1,i; + + rdman = mb_runtime_rdman(rt); + + _x_supp_handle_x_event(xmb_rt); + + while(1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + for(i = 0; i < io_man->n_monitor; i++) { + if(io_man->monitors[i].type == MB_IO_R || + io_man->monitors[i].type == MB_IO_RW) { + FD_SET(io_man->monitors[i].fd, &rfds); + nfds = MB_MAX(nfds, io_man->monitors[i].fd + 1); + } + if(io_man->monitors[i].type == MB_IO_W || + io_man->monitors[i].type == MB_IO_RW) { + FD_SET(io_man->monitors[i].fd, &wfds); + nfds = MB_MAX(nfds, io_man->monitors[i].fd + 1); + } + } + + get_now(&now); + r = mb_tman_next_timeout(tman, &now, &tmo); + + if(r == 0) { + tv.tv_sec = MB_TIMEVAL_SEC(&tmo); + tv.tv_usec = MB_TIMEVAL_USEC(&tmo); + r1 = select(nfds, &rfds, NULL, NULL, &tv); + } else + r1 = select(nfds, &rfds, NULL, NULL, NULL); + + if(r1 == -1) { + perror("select"); + break; + } + + if(r1 == 0) { + get_now(&now); + mb_tman_handle_timeout(tman, &now); + rdman_redraw_changed(rdman); +#ifdef XSHM + XSHM_update(xmb_rt); +#endif + XFlush(xmb_rt->display); + } else { + for(i = 0; i < io_man->n_monitor; i++) { + if(io_man->monitors[i].type == MB_IO_R || + io_man->monitors[i].type == MB_IO_RW) { + if(FD_ISSET(io_man->monitors[i].fd, &rfds)) + io_man->monitors[i].cb(i, io_man->monitors[i].fd, + MB_IO_R, + io_man->monitors[i].data); + } + if(io_man->monitors[i].type == MB_IO_W || + io_man->monitors[i].type == MB_IO_RW) { + if(FD_ISSET(io_man->monitors[i].fd, &wfds)) + io_man->monitors[i].cb(i, io_man->monitors[i].fd, + MB_IO_W, + io_man->monitors[i].data); + } + } + } + } +} + +/* @} */ + +#ifdef XSHM +static void +XSHM_update(X_supp_runtime_t *xmb_rt) { + GC gc; + + gc = DefaultGC(xmb_rt->display, DefaultScreen(xmb_rt->display)); + if(xmb_rt->ximage) { /* support XSHM */ + XShmPutImage(xmb_rt->display, + xmb_rt->win, + gc, + xmb_rt->ximage, + 0, 0, 0, 0, + xmb_rt->w, xmb_rt->h, 0); + } +} +#endif + /*! \defgroup xkb X Keyboard Handling * * Accept keyboard events from X server and delivery it to @@ -73,7 +286,7 @@ static int X_kb_init(X_kb_info_t *kbinfo, Display *display, redraw_man_t *rdman) { int n_syms; - ob_factory_t *factory; + observer_factory_t *factory; int r; r = XDisplayKeycodes(display, @@ -89,12 +302,12 @@ if(kbinfo->syms == NULL) return ERR; - factory = rdman_get_ob_factory(rdman); + factory = rdman_get_observer_factory(rdman); kbinfo->kbevents = subject_new(factory, kbinfo, OBJT_KB); if(kbinfo->kbevents == NULL) return ERR; - /*! \todo Make sure ob_factory is still need. */ - kbinfo->ob_factory = factory; + /*! \todo Make sure observer_factory is still need. */ + kbinfo->observer_factory = factory; return OK; } @@ -104,7 +317,8 @@ XFree(kbinfo->syms); } -/*! \brief Accept X keyboard events from handle_x_event() and dispatch it. +/*! \brief Accept X keyboard events from _x_supp_handle_x_event() and + * dispatch it. */ static void X_kb_handle_event(X_kb_info_t *kbinfo, XKeyEvent *xkey) { unsigned int code; @@ -123,7 +337,6 @@ subject_notify(kbinfo->kbevents, &event.event); } - /* @} */ static unsigned int get_button_state(unsigned int state) { @@ -135,7 +348,7 @@ but |= MOUSE_BUT2; if(state & Button3Mask) but |= MOUSE_BUT3; - + return but; } @@ -171,35 +384,193 @@ mouse_event.y = y; mouse_event.but_state = state; mouse_event.button = button; - + if(IS_MBO_SHAPES(obj)) subject = sh_get_mouse_event_subject((shape_t *)obj); else subject = coord_get_mouse_event((coord_t *)obj); + + subject_notify(subject, (event_t *)&mouse_event); +} + +/*! \brief Handle motion event. + */ +static void +handle_motion_event(X_supp_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int x, y; + int state; + shape_t *shape; + coord_t *root; + int in_stroke; - subject_notify(subject, (event_t *)&mouse_event); + x = rt->mx; + y = rt->my; + state = rt->mbut_state; + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); +#ifdef ONLY_MOUSE_MOVE_RAW + if(shape != NULL) { + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } else { + root = rdman_get_root(rdman); + notify_coord_or_shape(rdman, (mb_obj_t *)root, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } +#else + if(shape != NULL) { + if(rt->last != shape) { + if(rt->last) + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_OVER, state, 0); + rt->last = shape; + } else + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_MOVE, state, 0); + } else { + if(rt->last) { + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + rt->last = NULL; + } + } +#endif + + rt->mflag = 0; +} + +/*! \brief Redraw exposed area. + */ +static void +handle_expose_event(X_supp_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int ex1, ey1, ex2, ey2; + + ex1 = rt->ex1; + ey1 = rt->ey1; + ex2 = rt->ex2; + ey2 = rt->ey2; + + rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1)); + + rt->eflag = 0; +} + +/*! \brief Handle single X event and maintain internal states. + * + * It keeps internal state in rt to improve performance. + */ +static void +handle_single_x_event(X_supp_runtime_t *rt, XEvent *evt) { + redraw_man_t *rdman = rt->rdman; + XMotionEvent *mevt; + XButtonEvent *bevt; + XExposeEvent *eevt; + XKeyEvent *xkey; + int x, y, w, h; + + shape_t *shape; + + unsigned int state, button; + int in_stroke; + + if(evt->type != MotionNotify && rt->mflag) + handle_motion_event(rt); + + switch(evt->type) { + case ButtonPress: + bevt = (XButtonEvent *)evt; + x = bevt->x; + y = bevt->y; + state = get_button_state(bevt->state); + button = get_button(bevt->button); + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); + if(shape) + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_BUT_PRESS, + state, button); + break; + + case ButtonRelease: + bevt = (XButtonEvent *)evt; + x = bevt->x; + y = bevt->y; + state = get_button_state(bevt->state); + button = get_button(bevt->button); + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); + if(shape) + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_BUT_RELEASE, + state, button); + break; + + case MotionNotify: + mevt = (XMotionEvent *)evt; + rt->mx = mevt->x; + rt->my = mevt->y; + rt->mbut_state = get_button_state(mevt->state); + rt->mflag = 1; + break; + + case KeyPress: + case KeyRelease: + xkey = &evt->xkey; + X_kb_handle_event(&rt->kbinfo, xkey); + break; + + case Expose: + eevt = &evt->xexpose; + x = eevt->x; + y = eevt->y; + w = eevt->width; + h = eevt->height; + + if(rt->eflag) { + if(x < rt->ex1) + rt->ex1 = x; + if(y < rt->ey1) + rt->ey1 = y; + if((x + w) > rt->ex2) + rt->ex2 = x + w; + if((y + h) > rt->ey2) + rt->ey2 = y + h; + } else { + rt->ex1 = x; + rt->ey1 = y; + rt->ex2 = x + w; + rt->ey2 = y + h; + rt->eflag = 1; + } + break; + } +} + +/*! \brief Call when no more event in an event iteration. + * + * No more event means event queue is emplty. This function will + * perform some actions according current internal state. + */ +static void +no_more_event(X_supp_runtime_t *rt) { + if(rt->mflag) + handle_motion_event(rt); + if(rt->eflag) + handle_expose_event(rt); } /*! \brief Dispatch all X events in the queue. */ -static void handle_x_event(X_MB_runtime_t *rt) { +static void _x_supp_handle_x_event(X_supp_runtime_t *rt) { Display *display = rt->display; - redraw_man_t *rdman = rt->rdman; - XEvent evt, peek_evt; - XMotionEvent *mevt; - XButtonEvent *bevt; - XExposeEvent *eevt; - XKeyEvent *xkey; - co_aix x, y, w, h; - - int eflag = 0; - int ex1=0, ey1=0, ex2=0, ey2=0; - - shape_t *shape; - coord_t *root; - - unsigned int state, button; - int in_stroke; + XEvent evt; int r; /* XXX: For some unknown reason, it causes a segmentation fault to @@ -211,200 +582,23 @@ if(r == -1) break; - switch(evt.type) { - case ButtonPress: - bevt = (XButtonEvent *)&evt; - x = bevt->x; - y = bevt->y; - state = get_button_state(bevt->state); - button = get_button(bevt->button); - - shape = find_shape_at_pos(rdman, x, y, - &in_stroke); - if(shape) - notify_coord_or_shape(rdman, (mb_obj_t *)shape, - x, y, EVT_MOUSE_BUT_PRESS, - state, button); - break; - - case ButtonRelease: - bevt = (XButtonEvent *)&evt; - x = bevt->x; - y = bevt->y; - state = get_button_state(bevt->state); - button = get_button(bevt->button); - - shape = find_shape_at_pos(rdman, x, y, - &in_stroke); - if(shape) - notify_coord_or_shape(rdman, (mb_obj_t *)shape, - x, y, EVT_MOUSE_BUT_RELEASE, - state, button); - break; - - case MotionNotify: - while(XEventsQueued(display, QueuedAfterReading) > 0) { - r = XPeekEvent(display, &peek_evt); - if(r == -1) - break; - if(peek_evt.type != MotionNotify) - break; - XNextEvent(display, &evt); - } - if(r == -1) - break; - - mevt = (XMotionEvent *)&evt; - x = mevt->x; - y = mevt->y; - state = get_button_state(mevt->state); - - shape = find_shape_at_pos(rdman, x, y, - &in_stroke); -#ifdef ONLY_MOUSE_MOVE_RAW - if(shape != NULL) { - notify_coord_or_shape(rdman, (mb_obj_t *)shape, - x, y, EVT_MOUSE_MOVE_RAW, state, 0); - } else { - root = rdman_get_root(rdman); - notify_coord_or_shape(rdman, (mb_obj_t *)root, - x, y, EVT_MOUSE_MOVE_RAW, state, 0); - } -#else - if(shape != NULL) { - if(rt->last != shape) { - if(rt->last) - notify_coord_or_shape(rdman, rt->last, x, y, - EVT_MOUSE_OUT, state, 0); - notify_coord_or_shape(rdman, shape, x, y, - EVT_MOUSE_OVER, state, 0); - rt->last = shape; - } else - notify_coord_or_shape(rdman, shape, x, y, - EVT_MOUSE_MOVE, state, 0); - } else { - if(rt->last) { - notify_coord_or_shape(rdman, rt->last, x, y, - EVT_MOUSE_OUT, state, 0); - rt->last = NULL; - } - } + handle_single_x_event(rt, &evt); + } + no_more_event(rt); + +#ifdef XSHM + XSHM_update(rt); #endif - break; - - case KeyPress: - case KeyRelease: - xkey = &evt.xkey; - X_kb_handle_event(&rt->kbinfo, xkey); - break; - - case Expose: - eevt = &evt.xexpose; - x = eevt->x; - y = eevt->y; - w = eevt->width; - h = eevt->height; - - if(eflag) { - if(x < ex1) - ex1 = x; - if(y < ey1) - ey1 = y; - if((x + w) > ex2) - ex2 = x + w; - if((y + h) > ey2) - ey2 = y + h; - } else { - ex1 = x; - ey1 = y; - ex2 = x + w; - ey2 = y + h; - eflag = 1; - } - break; - } - } - if(eflag) { - rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1)); - eflag = 0; - } XFlush(display); } -/*! \brief Handle connection coming data and timeout of timers. - * - * \param display is a Display returned by XOpenDisplay(). - * \param rdman is a redraw manager. - * \param tman is a timer manager. - * - * The display is managed by specified rdman and tman. rdman draws - * on the display, and tman trigger actions according timers. - */ -void X_MB_handle_connection(void *be) { - X_MB_runtime_t *rt = (X_MB_runtime_t *) be; - Display *display = rt->display; - redraw_man_t *rdman = rt->rdman; - mb_tman_t *tman = rt->tman; - int fd; - mb_timeval_t now, tmo; - struct timeval tv; - fd_set rfds,wfds; - int nfds; - int r, r1,i; - - handle_x_event(rt); +static void +_x_supp_handle_connection(int hdl, int fd, MB_IO_TYPE type, void *data) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *)data; - fd = XConnectionNumber(display); - nfds = fd + 1; - while(1) { - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_SET(fd, &rfds); - for(i=0;i<rt->n_monitor;i++) { - if (rt->monitors[i].type == MONITOR_READ) - FD_SET(rt->monitors[i].fd, &rfds); - else if (rt->monitors[i].type == MONITOR_WRITE) - FD_SET(rt->monitors[i].fd, &wfds); - } - - get_now(&now); - r = mb_tman_next_timeout(tman, &now, &tmo); - - if(r == 0) { - tv.tv_sec = MB_TIMEVAL_SEC(&tmo); - tv.tv_usec = MB_TIMEVAL_USEC(&tmo); - r1 = select(nfds, &rfds, NULL, NULL, &tv); - } else - r1 = select(nfds, &rfds, NULL, NULL, NULL); - - if(r1 == -1) { - perror("select"); - break; - } - - if(r1 == 0) { - get_now(&now); - mb_tman_handle_timeout(tman, &now); - rdman_redraw_changed(rdman); - XFlush(display); - } else if(FD_ISSET(fd, &rfds)){ - handle_x_event(rt); - } else { - for(i=0;i<rt->n_monitor;i++) { - if (rt->monitors[i].type == MONITOR_READ) - if (FD_ISSET(rt->monitors[i].fd, &rfds)) - rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); - else if (rt->monitors[i].type == MONITOR_WRITE) - if (FD_ISSET(rt->monitors[i].fd, &wfds)) - rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); - } - } - } + _x_supp_handle_x_event(xmb_rt); } -#define ERR -1 -#define OK 0 - static int X_init_connection(const char *display_name, int w, int h, Display **displayp, @@ -417,9 +611,27 @@ XSetWindowAttributes wattr; int depth; int x, y; + int draw_root = 0; + const char *disp_name; + char disp_buf[32]; + int cp; int r; - display = XOpenDisplay(display_name); + /* + * Support drawing on the root window. + */ + disp_name = display_name; + if(strstr(display_name, ":root") != NULL) { + draw_root = 1; + cp = strlen(display_name) - 5; + if(cp >= 32) + cp = 31; + memcpy(disp_buf, display_name, cp); + disp_buf[cp] = 0; + disp_name = disp_buf; + } + + display = XOpenDisplay(disp_name); if(display == NULL) return ERR; @@ -430,15 +642,19 @@ wattr.override_redirect = False; x = 10; y = 10; - win = XCreateWindow(display, root, - x, y, - w, h, - 1, depth, InputOutput, visual, - CWOverrideRedirect, &wattr); - r = XMapWindow(display, win); - if(r == -1) { - XCloseDisplay(display); - return ERR; + if(draw_root) + win = RootWindowOfScreen(ScreenOfDisplay(display, screen)); + else { + win = XCreateWindow(display, root, + x, y, + w, h, + 1, depth, InputOutput, visual, + CWOverrideRedirect, &wattr); + r = XMapWindow(display, win); + if(r == -1) { + XCloseDisplay(display); + return ERR; + } } XSelectInput(display, win, PointerMotionMask | ExposureMask | @@ -453,89 +669,231 @@ return OK; } +#ifdef XSHM +static void +xshm_destroy(X_supp_runtime_t *xmb_rt) { + XShmSegmentInfo *shminfo; + + shminfo = &xmb_rt->shminfo; + + if(xmb_rt->shminfo.shmaddr) { + XShmDetach(xmb_rt->display, shminfo); + } + + if(xmb_rt->ximage) { + XDestroyImage(xmb_rt->ximage); + xmb_rt->ximage = NULL; + } + + if(shminfo->shmaddr) { + shmdt(shminfo->shmaddr); + shminfo->shmaddr = NULL; + } + + if(shminfo->shmid) { + shmctl(shminfo->shmid, IPC_RMID, 0); + shminfo->shmid = 0; + } +} + +static void +xshm_init(X_supp_runtime_t *xmb_rt) { + Display *display; + Visual *visual; + XImage *ximage; + int screen; + int depth; + int support_shm; + int mem_sz; + XShmSegmentInfo *shminfo; + int surf_fmt; + + display = xmb_rt->display; + visual = xmb_rt->visual; + shminfo = &xmb_rt->shminfo; + + support_shm = XShmQueryExtension(display); + if(!support_shm) + return; + + screen = DefaultScreen(display); + depth = DefaultDepth(display, screen); + + if(depth != 24 && depth != 32) + return; + + xmb_rt->ximage = XShmCreateImage(display, visual, depth, + ZPixmap, NULL, shminfo, + xmb_rt->w, xmb_rt->h); + ximage = xmb_rt->ximage; + + mem_sz = ximage->bytes_per_line * ximage->height; + shminfo->shmid = shmget(IPC_PRIVATE, mem_sz, IPC_CREAT | 0777); + if(shminfo->shmid == -1) { + xshm_destroy(xmb_rt); + return; + } + + shminfo->shmaddr = shmat(shminfo->shmid, 0, 0); + ximage->data = shminfo->shmaddr; + + shminfo->readOnly = 0; + + XShmAttach(display, shminfo); + + switch(depth) { + case 24: surf_fmt = CAIRO_FORMAT_RGB24; break; + case 32: surf_fmt = CAIRO_FORMAT_ARGB32; break; + } + + xmb_rt->backend_surface = + mbe_image_surface_create_for_data((unsigned char *)ximage->data, + surf_fmt, + xmb_rt->w, + xmb_rt->h, + ximage->bytes_per_line); + if(xmb_rt->backend_surface == NULL) + xshm_destroy(xmb_rt); +} +#endif /* XSHM */ + /*! \brief Initialize a MadButterfy runtime for Xlib. * - * It setups a runtime environment to run MadButterfly with Xlib. - * Users should specify width and height of the opening window. + * This one is very like _x_supp_init(), except it accepts a + * X_supp_runtime_t object initialized with a display connected to a X + * server and an opened window. + * + * Following field of the X_supp_runtime_t object should be initialized. + * - w, h + * - win + * - display + * - visual */ -static int X_MB_init(const char *display_name, - int w, int h, X_MB_runtime_t *xmb_rt) { +static int +_x_supp_init_with_win_internal(X_supp_runtime_t *xmb_rt) { mb_img_ldr_t *img_ldr; - - memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + int w, h; + int disp_fd; - xmb_rt->w = w; - xmb_rt->h = h; - X_init_connection(display_name, w, h, &xmb_rt->display, - &xmb_rt->visual, &xmb_rt->win); -#ifdef OPENVG_GRAPH_ENGINE - _ge_openvg_disp_id = xmb_rt->display; + w = xmb_rt->w; + h = xmb_rt->h; + +#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); - -#ifdef OPENVG_GRAPH_ENGINE - xmb_rt->backend_surface = - mbe_vg_win_surface_create(xmb_rt->display, - xmb_rt->win, - xmb_rt->visual, - w, h); -#else - xmb_rt->backend_surface = - mbe_xlib_surface_create(xmb_rt->display, - xmb_rt->win, - xmb_rt->visual, - w, h); -#endif + + 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); xmb_rt->cr = mbe_create(xmb_rt->surface); xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface); - /* TODO: Remove this line. Since we use mbe_copy_source(), it - * will set source for the backend. So, this line is redundants. - * It can be removed. sourface_ptn can be removed, too. - */ 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 + // 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->rdman->w = w; - xmb_rt->rdman->h = h; - xmb_rt->tman = mb_tman_new(); + xmb_rt->io_man = mb_io_man_new(_io_factory); + xmb_rt->timer_man = mb_timer_man_new(_timer_factory); img_ldr = simple_mb_img_ldr_new(""); xmb_rt->img_ldr = img_ldr; - rdman_set_img_ldr(xmb_rt->rdman, img_ldr); - memset(xmb_rt->monitors,0,sizeof(xmb_rt->monitors)); - + /*! \todo Remove rdman_set_img_ldr() */ + rdman_set_img_ldr(xmb_rt->rdman, img_ldr); /* this is ncessary? */ + #ifndef ONLY_MOUSE_MOVE_RAW xmb_rt->last = NULL; #endif X_kb_init(&xmb_rt->kbinfo, xmb_rt->display, xmb_rt->rdman); + disp_fd = XConnectionNumber(xmb_rt->display); + xmb_rt->io_hdl = mb_io_man_reg(xmb_rt->io_man, disp_fd, + MB_IO_R, + _x_supp_handle_connection, + xmb_rt); + return OK; } -static void X_MB_destroy(X_MB_runtime_t *xmb_rt) { +/*! \brief Initialize a MadButterfy runtime for Xlib. + * + * It setups a runtime environment to run MadButterfly with Xlib. + * Users should specify width and height of the opening window. + */ +static int _x_supp_init(X_supp_runtime_t *xmb_rt, const char *display_name, + int w, int h) { + int r; + + memset(xmb_rt, 0, sizeof(X_supp_runtime_t)); + + xmb_rt->w = w; + xmb_rt->h = h; + r = X_init_connection(display_name, w, h, &xmb_rt->display, + &xmb_rt->visual, &xmb_rt->win); + if(r != OK) + return ERR; + + r = _x_supp_init_with_win_internal(xmb_rt); + + return r; +} + +/*! \brief Initialize a MadButterfly runtime for a window of X. + * + * Runtimes initialized with this function should be destroyed with + * x_supp_destroy_keep_win(). + */ +static int +_x_supp_init_with_win(X_supp_runtime_t *xmb_rt, + Display *display, Window win) { + XWindowAttributes attrs; + int r; + + r = XGetWindowAttributes(display, win, &attrs); + if(r == 0) + return ERR; + + memset(xmb_rt, 0, sizeof(X_supp_runtime_t)); + + xmb_rt->display = display; + xmb_rt->win = win; + xmb_rt->visual = attrs.visual; + xmb_rt->w = attrs.width; + xmb_rt->h = attrs.height; + + r = _x_supp_init_with_win_internal(xmb_rt); + + return r; +} + +static void x_supp_destroy(X_supp_runtime_t *xmb_rt) { if(xmb_rt->rdman) { redraw_man_destroy(xmb_rt->rdman); free(xmb_rt->rdman); } - if(xmb_rt->tman) - mb_tman_free(xmb_rt->tman); + if(xmb_rt->io_hdl) + mb_io_man_unreg(xmb_rt->io_man, xmb_rt->io_hdl); + + if(xmb_rt->io_man) + mb_io_man_free(_io_factory, xmb_rt->io_man); + if(xmb_rt->timer_man) + mb_timer_man_free(_timer_factory, xmb_rt->timer_man); if(xmb_rt->img_ldr) MB_IMG_LDR_FREE(xmb_rt->img_ldr); @@ -558,133 +916,179 @@ X_kb_destroy(&xmb_rt->kbinfo); } -void *X_MB_new(const char *display_name, int w, int h) { - X_MB_runtime_t *rt; +/*! \brief Destroy a MadButterfly runtime initialized with + * _x_supp_init_with_win(). + * + * Destroying a runtime with this function prevent the window and + * display associated with the runtime being closed. + */ +static void +x_supp_destroy_keep_win(X_supp_runtime_t *xmb_rt) { + Display *display; + Window win; + + display = xmb_rt->display; + xmb_rt->display = NULL; + win = xmb_rt->win; + xmb_rt->win = 0; + + x_supp_destroy(xmb_rt); + + xmb_rt->display = display; + xmb_rt->win = win; +} + +static mb_rt_t * +_x_supp_new(const char *display_name, int w, int h) { + X_supp_runtime_t *rt; int r; - rt = O_ALLOC(X_MB_runtime_t); + rt = O_ALLOC(X_supp_runtime_t); if(rt == NULL) return NULL; - r = X_MB_init(display_name, w, h, rt); + r = _x_supp_init(rt, display_name, w, h); if(r != OK) { free(rt); return NULL; } - return rt; + return (mb_rt_t *)rt; } -void X_MB_free(void *rt) { - X_MB_destroy((X_MB_runtime_t *) rt); +/*! \brief Create a new runtime for existed window for X. + * + * The object returned by this function must be free with + * _x_supp_free_keep_win() to prevent the window from closed. + */ +static mb_rt_t * +_x_supp_new_with_win(MB_DISPLAY display, MB_WINDOW win) { + X_supp_runtime_t *rt; + int r; + + rt = O_ALLOC(X_supp_runtime_t); + if(rt == NULL) + return NULL; + + r = _x_supp_init_with_win(rt, display, win); + if(r != OK) { + free(rt); + return NULL; + } + + return (mb_rt_t *)rt; +} + +static void +_x_supp_free(mb_rt_t *rt) { + x_supp_destroy((X_supp_runtime_t *) rt); free(rt); } -subject_t *X_MB_kbevents(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; +/*! \brief Free runtime created with _x_supp_new_with_win(). + */ +static void +_x_supp_free_keep_win(mb_rt_t *rt) { + x_supp_destroy_keep_win((X_supp_runtime_t *) rt); + free(rt); +} + +static subject_t * +_x_supp_kbevents(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; return xmb_rt->kbinfo.kbevents; } -redraw_man_t *X_MB_rdman(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; +static redraw_man_t * +_x_supp_rdman(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; return xmb_rt->rdman; } -mb_tman_t *X_MB_tman(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - return xmb_rt->tman; +static mb_timer_man_t * +_x_supp_timer_man(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + return xmb_rt->timer_man; } -ob_factory_t *X_MB_ob_factory(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - ob_factory_t *factory; +static observer_factory_t * +_x_supp_observer_factory(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + observer_factory_t *factory; - factory = rdman_get_ob_factory(xmb_rt->rdman); + factory = rdman_get_observer_factory(xmb_rt->rdman); return factory; } -mb_img_ldr_t *X_MB_img_ldr(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - X_MB_runtime_t *img_ldr; +static mb_img_ldr_t * +_x_supp_img_ldr(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + mb_img_ldr_t *img_ldr; img_ldr = xmb_rt->img_ldr; return img_ldr; } -void X_MB_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) +static int +_x_supp_add_event(mb_rt_t *rt, int fd, MB_IO_TYPE type, + mb_IO_cb_t cb, void *data) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - int i; + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + mb_IO_man_t *io_man = xmb_rt->io_man; + int hdl; - for(i=0;i<xmb_rt->n_monitor;i++) { - if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { - xmb_rt->monitors[i].f = f; - xmb_rt->monitors[i].arg = arg; - return; - } - } - for(i=0;i<xmb_rt->n_monitor;i++) { - if (xmb_rt->monitors[i].type == 0) { - xmb_rt->monitors[i].type = type; - xmb_rt->monitors[i].fd = fd; - xmb_rt->monitors[i].f = f; - xmb_rt->monitors[i].arg = arg; - return; - } - } - if (i == MAX_MONITORS) return; - xmb_rt->monitors[i].type = type; - xmb_rt->monitors[i].fd = fd; - xmb_rt->monitors[i].f = f; - xmb_rt->monitors[i].arg = arg; - i++; - xmb_rt->n_monitor=i; + hdl = mb_io_man_reg(io_man, fd, type, cb, data); + return hdl; +} + +static void +_x_supp_remove_event(mb_rt_t *rt, int hdl) +{ + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + mb_IO_man_t *io_man = xmb_rt->io_man; + + mb_io_man_unreg(io_man, hdl); } -void X_MB_remove_event(void *rt, int type, int fd) -{ - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - int i; - for(i=0;i<xmb_rt->n_monitor;i++) { - if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { - xmb_rt->monitors[i].type = 0; - return; - } - } +static int +_x_supp_flush(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + int r; + +#ifdef XSHM + XSHM_update(xmb_rt); +#endif + r = XFlush(xmb_rt->display); + return r == 0? ERR: OK; } -mb_backend_t backend = { X_MB_new, - X_MB_free, - X_MB_add_event, - X_MB_remove_event, - X_MB_handle_connection, - X_MB_kbevents, - X_MB_rdman, - X_MB_tman, - X_MB_ob_factory, - X_MB_img_ldr - }; -/*! \defgroup x_supp_nodejs_sup Export functions for supporting nodejs plugin. - * - * These functions are for internal using. - * @{ - */ -/*! \brief Exported for nodejs plugin to call handle_x_event. - */ -void _X_MB_handle_x_event_for_nodejs(void *rt) { - handle_x_event((X_MB_runtime_t *)rt); + +static void +_x_supp_reg_IO_factory(mb_IO_factory_t *io_factory) { + _io_factory = io_factory; } -/*! \brief Get X connect for nodejs plugin. - */ -int _X_MB_get_x_conn_for_nodejs(void *rt) { - return XConnectionNumber(((X_MB_runtime_t *)rt)->display); +static void +_x_supp_reg_timer_factory(mb_timer_factory_t *timer_factory) { + _timer_factory = timer_factory; } -/*! \brief Flush buffer for the X connection of a runtime object. - */ -int _X_MB_flush_x_conn_for_nodejs(void *rt) { - return XFlush(((X_MB_runtime_t *)rt)->display); -} +mb_backend_t mb_dfl_backend = { _x_supp_new, + _x_supp_new_with_win, + + _x_supp_free, + _x_supp_free_keep_win, + _x_supp_add_event, + _x_supp_remove_event, + _x_supp_event_loop, + _x_supp_flush, + + _x_supp_kbevents, + _x_supp_rdman, + _x_supp_timer_man, + _x_supp_observer_factory, + _x_supp_img_ldr, -/* @} */ + _x_supp_reg_IO_factory, + _x_supp_reg_timer_factory, +};
--- a/src/animate.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/animate.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \file * \brief Animation tools. * @@ -24,7 +26,7 @@ * a word, it call stop of actions in the word. * * A program is driven by a timer. Once a program is started, it registers - * with timer for periodic running. \ref mb_tman_t is timer of + * with timer for periodic running. \ref mb_timer_man_t is timer of * MadButterfly. The update frequence is 10fps by default, now. * * \section use_progm How to Use Animation Program? @@ -41,7 +43,7 @@ * * \code * progm = mb_progm_new(10, &rdman); - * + * * MB_TIMEVAL_SET(&start, 0, 0); * MB_TIMEVAL_SET(&playing, 1, 0); * word = mb_progm_next_word(progm, &start, &playing); @@ -59,7 +61,7 @@ * * gettimeofday(&tv, NULL); * MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); - * mb_progm_start(progm, tman, &mbtv); + * mb_progm_start(progm, timer_man, &mbtv); * \endcode * * @@ -96,9 +98,9 @@ mb_timeval_t start_time; int first_playing; /*!< first playing word. */ - mb_tman_t *tman; + mb_timer_man_t *timer_man; subject_t *complete; /*!< notify when a program is completed. */ - mb_timer_t *cur_timer; + int cur_timer; int n_words; int max_words; @@ -113,7 +115,7 @@ mb_progm_t *mb_progm_new(int max_words, redraw_man_t *rdman) { mb_progm_t *progm; #ifndef UNITTEST - ob_factory_t *factory; + observer_factory_t *factory; #endif /* UNITTEST */ int i; @@ -125,7 +127,7 @@ progm->rdman = rdman; #ifndef UNITTEST - factory = rdman_get_ob_factory(rdman); + factory = rdman_get_observer_factory(rdman); progm->complete = subject_new(factory, progm, OBJT_PROGM); if(progm->complete == NULL) { free(progm); @@ -137,6 +139,7 @@ progm->max_words = max_words; for(i = 0; i < max_words; i++) STAILQ_INIT(progm->words[i].actions); + progm->cur_timer = -1; return progm; } @@ -231,7 +234,8 @@ * between now and next_tmo. It is not obviously if time stepping * small. */ -static void mb_progm_step(const mb_timeval_t *tmo, +static void mb_progm_step(int timer_hdl, + const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg) { mb_progm_t *progm = (mb_progm_t *)arg; @@ -287,8 +291,8 @@ word = progm->words + progm->first_playing; if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo)) MB_TIMEVAL_CP(&next_tmo, &word->abs_start); - timer = mb_tman_timeout(progm->tman, &next_tmo, - mb_progm_step, progm); + timer = mb_timer_man_timeout(progm->timer_man, &next_tmo, + mb_progm_step, progm); progm->cur_timer = timer; } else { /* Make program to complete. */ @@ -298,20 +302,20 @@ comp_evt.progm = progm; subject_notify(progm->complete, &comp_evt.event); #endif /* UNITTEST */ - progm->cur_timer = NULL; + progm->cur_timer = -1; } } -void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, +void mb_progm_start(mb_progm_t *progm, mb_timer_man_t *timer_man, mb_timeval_t *now) { - mb_timer_t *timer; + int timer; mb_word_t *word; int i; if(progm->n_words == 0) return; - progm->tman = tman; + progm->timer_man = timer_man; MB_TIMEVAL_CP(&progm->start_time, now); progm->first_playing = 0; @@ -324,13 +328,13 @@ } if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) { - mb_progm_step(now, now, progm); + mb_progm_step(-1, now, now, progm); return; } - - timer = mb_tman_timeout(tman, &progm->words[0].abs_start, - mb_progm_step, progm); - ASSERT(timer != NULL); + + timer = mb_timer_man_timeout(timer_man, &progm->words[0].abs_start, + mb_progm_step, progm); + ASSERT(timer != -1); /* We need timer to abort it. */ progm->cur_timer = timer; @@ -341,13 +345,13 @@ mb_progm_abort(progm); MB_TIMEVAL_SET(&infi, 0x7fffffff,0); - mb_progm_step(&progm->start_time, &infi,progm); + mb_progm_step(-1, &progm->start_time, &infi,progm); } void mb_progm_abort(mb_progm_t *progm) { /*! \todo Make sure abort release resources. */ - if(progm->cur_timer) { - mb_tman_remove(progm->tman, progm->cur_timer); - progm->cur_timer = NULL; + if(progm->cur_timer != -1) { + mb_timer_man_remove(progm->timer_man, progm->cur_timer); + progm->cur_timer = -1; } } @@ -373,6 +377,7 @@ #ifdef UNITTEST +#include "mb_backend_utils.h" #include <CUnit/Basic.h> typedef struct _mb_dummy mb_dummy_t; @@ -439,14 +444,17 @@ mb_progm_t *progm; mb_word_t *word; mb_action_t *acts[4]; + mb_timer_man_t *timer_man; mb_tman_t *tman; mb_timeval_t tv1, tv2, now, tmo_after; int logcnt = 0; int logs[256]; int r; - tman = mb_tman_new(); - CU_ASSERT(tman != NULL); + timer_man = mb_timer_man_new(&tman_timer_factory); + CU_ASSERT(timer_man != -1); + + tman = tman_timer_man_get_tman(timer_man); progm = mb_progm_new(3, NULL); CU_ASSERT(progm != NULL); @@ -473,7 +481,7 @@ CU_ASSERT(acts[2] != NULL); MB_TIMEVAL_SET(&now, 0, 0); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); r = mb_tman_next_timeout(tman, &now, &tmo_after); CU_ASSERT(r == 0); @@ -489,7 +497,7 @@ CU_ASSERT(r == 0); CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); - + /* 1.1s */ MB_TIMEVAL_ADD(&now, &tmo_after); mb_tman_handle_timeout(tman, &now); @@ -499,7 +507,7 @@ CU_ASSERT(r == 0); CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); - + /* 1.2s */ MB_TIMEVAL_ADD(&now, &tmo_after); mb_tman_handle_timeout(tman, &now); @@ -509,7 +517,7 @@ CU_ASSERT(r == 0); CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); - + /* 1.3s */ MB_TIMEVAL_ADD(&now, &tmo_after); mb_tman_handle_timeout(tman, &now); @@ -519,7 +527,7 @@ CU_ASSERT(r == 0); CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); - + /* 1.4s */ MB_TIMEVAL_ADD(&now, &tmo_after); mb_tman_handle_timeout(tman, &now); @@ -529,7 +537,7 @@ CU_ASSERT(r == 0); CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); - + /* 1.5s */ MB_TIMEVAL_ADD(&now, &tmo_after); mb_tman_handle_timeout(tman, &now); @@ -539,7 +547,7 @@ CU_ASSERT(r == -1); mb_progm_free(progm); - mb_tman_free(tman); + mb_timer_man_free(&tman_timer_factory, timer_man); } CU_pSuite get_animate_suite(void) { @@ -550,7 +558,7 @@ return NULL; CU_ADD_TEST(suite, test_animate_words); - + return suite; }
--- a/src/chgcolor.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/chgcolor.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include "mb_animate.h"
--- a/src/coord.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/coord.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \brief Implement coordination tranform mechanism. * \file * This file implements coordination transforming for containers. @@ -28,10 +30,10 @@ void matrix_mul(co_aix *m1, co_aix *m2, co_aix *dst) { co_aix *_dst = dst; co_aix fake_dst[6]; - + if(m1 == dst || m2 == dst) _dst = fake_dst; - + mul_matrix(m1, m2, _dst); if(m1 == dst || m2 == dst) { @@ -60,7 +62,7 @@ /*! \brief Compute aggregated transform matrix. * * Base on parent's aggregated matrix if it is existed, or use transform - * matrix as aggregated matrix. + * matrix as aggregated matrix. */ static void compute_transform_function(coord_t *visit) { if(!coord_is_root(visit)) @@ -82,7 +84,7 @@ co_aix *p_matrix; co_aix cache_p_matrix[6]; co_aix cache_scale_x, cache_scale_y; - + if(!coord_is_root(visit)) { p_matrix = coord_get_aggr_matrix(visit->parent); cache_scale_x = @@ -116,7 +118,7 @@ void compute_reverse(co_aix *orig, co_aix *reverse) { co_aix working[6]; co_aix factor; - + #define VEC_MAC(src, factor, dst) \ do { \ (dst)[0] += (src)[0] * (factor); \ @@ -130,7 +132,7 @@ reverse[3] = 0; reverse[4] = 1; reverse[5] = 0; - + memcpy(working, orig, sizeof(co_aix) * 6); factor = -working[3] / working[0]; @@ -144,12 +146,14 @@ reverse[2] = -working[2]; reverse[5] = -working[5]; - reverse[0] /= working[0]; - reverse[1] /= working[0]; - reverse[2] /= working[0]; - reverse[3] /= working[4]; - reverse[4] /= working[4]; - reverse[5] /= working[4]; + factor = 1 / working[0]; + reverse[0] *= factor; + reverse[1] *= factor; + reverse[2] *= factor; + factor = 1 / working[4]; + reverse[3] *= factor; + reverse[4] *= factor; + reverse[5] *= factor; } /*! \brief Update aggregate matrices of elements under a sub-tree. @@ -243,7 +247,7 @@ coord_t *next = NULL; ASSERT(last != NULL); - + if((!(last->flags & COF_SKIP_TRIVAL)) && STAILQ_HEAD(last->children)) { next = STAILQ_HEAD(last->children); @@ -270,7 +274,7 @@ if(root == last) return NULL; - + if(last == NULL) { /* Go most left leaf. */ next = root; @@ -323,7 +327,7 @@ update_aggr_matrix(elms); /* | -3 5 0 | - * | 5 1 0 | + * | 5 1 0 | * | 0 0 1 | */ CU_ASSERT(elms[3].aggr_matrix[0] == -3);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dfb_supp.c Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,552 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <directfb.h> +#include <cairo/cairo.h> +#include <cairo-directfb.h> +#include "mb_graph_engine.h" +#include "mb_redraw_man.h" +#include "mb_timer.h" +#include "mb_dfb_supp.h" +#include "config.h" + +#define ERR -1 +#define OK 0 + +#define ONLY_MOUSE_MOVE_RAW 1 + +/*! \ingroup xkb + * @{ + */ +struct _X_kb_info { + int keycode_min, keycode_max; + int ksym_per_code; + subject_t *kbevents; + observer_factory_t *observer_factory; +}; + +/* @} */ +#define MAX_MONITORS 200 +typedef struct { + int type; + int fd; + mb_eventcb_t f; + void *arg; +} monitor_t; + +struct _X_MB_runtime { + IDirectFB *dfb; + IDirectFBSurface *primary; + mbe_surface_t *surface, *backend_surface; + mbe_pattern_t *surface_ptn; + mbe_t *cr, *backend_cr; + redraw_man_t *rdman; + mb_tman_t *tman; + mb_img_ldr_t *img_ldr; + int w, h; + + X_kb_info_t kbinfo; + monitor_t monitors[MAX_MONITORS]; + int n_monitor; + +#ifndef ONLY_MOUSE_MOVE_RAW + /* States */ + shape_t *last; +#endif + + /* + * Following variables are used by handle_single_x_event() + */ + int last_evt_type; /* Type of last event */ + int eflag; + int ex1, ey1, ex2, ey2; /* Aggregate expose events */ + int mflag; + int mx, my; /* Position of last motion event */ + int mbut_state; /* Button state of last motion event */ +}; + +/*! \defgroup xkb X Keyboard Handling + * + * Accept keyboard events from X server and delivery it to + * application through observer pattern. There is a subject, + * per X-connection, for that. + * @{ + */ +static int keycode2sym(X_kb_info_t *kbinfo, unsigned int keycode) { + int sym_idx; + int sym; + + sym_idx = kbinfo->ksym_per_code * (keycode - kbinfo->keycode_min); +/* sym = kbinfo->syms[sym_idx];*/ + return sym; +} + +static void X_kb_destroy(X_kb_info_t *kbinfo) { + subject_free(kbinfo->kbevents); +} + +/* @} */ + +static unsigned int get_button_state(unsigned int state) { + return 0; +} + +static unsigned int get_button(unsigned int button) { + return 0; +} + +/*! \brief Notify observers of the shape at specified + * position for mouse event. + * + * Observers of parent shapes may be called if the subject is not + * with SUBF_STOP_PROPAGATE flag. The subject of mouse event + * for a shape is returned by sh_get_mouse_event_subject(). + */ +static void notify_coord_or_shape(redraw_man_t *rdman, + mb_obj_t *obj, + co_aix x, co_aix y, int etype, + unsigned int state, + unsigned int button) { + mouse_event_t mouse_event; + subject_t *subject; + + mouse_event.event.type = etype; + mouse_event.x = x; + mouse_event.y = y; + mouse_event.but_state = state; + mouse_event.button = button; + + if(IS_MBO_SHAPES(obj)) + subject = sh_get_mouse_event_subject((shape_t *)obj); + else + subject = coord_get_mouse_event((coord_t *)obj); + + subject_notify(subject, (event_t *)&mouse_event); +} + +/*! \brief Handle motion event. + */ +static void +handle_motion_event(X_MB_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int x, y; + int state; + shape_t *shape; + coord_t *root; + int in_stroke; + + x = rt->mx; + y = rt->my; + state = rt->mbut_state; + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); +#ifdef ONLY_MOUSE_MOVE_RAW + if(shape != NULL) { + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } else { + root = rdman_get_root(rdman); + notify_coord_or_shape(rdman, (mb_obj_t *)root, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } +#else + if(shape != NULL) { + if(rt->last != shape) { + if(rt->last) + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_OVER, state, 0); + rt->last = shape; + } else + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_MOVE, state, 0); + } else { + if(rt->last) { + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + rt->last = NULL; + } + } +#endif + + rt->mflag = 0; +} + +/*! \brief Redraw exposed area. + */ +static void +handle_expose_event(X_MB_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int ex1, ey1, ex2, ey2; + + ex1 = rt->ex1; + ey1 = rt->ey1; + ex2 = rt->ex2; + ey2 = rt->ey2; + + rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1)); + + rt->eflag = 0; +} + +/*! \brief Call when no more event in an event iteration. + * + * No more event means event queue is emplty. This function will + * perform some actions according current internal state. + */ +static void +no_more_event(X_MB_runtime_t *rt) { + if(rt->mflag) + handle_motion_event(rt); + if(rt->eflag) + handle_expose_event(rt); +} + +/*! \brief Handle connection coming data and timeout of timers. + * + * \param display is a Display returned by XOpenDisplay(). + * \param rdman is a redraw manager. + * \param tman is a timer manager. + * + * The display is managed by specified rdman and tman. rdman draws + * on the display, and tman trigger actions according timers. + */ +void X_MB_handle_connection(void *be) { + X_MB_runtime_t *rt = (X_MB_runtime_t *) be; + redraw_man_t *rdman = rt->rdman; + mb_tman_t *tman = rt->tman; + int fd = 0; + mb_timeval_t now, tmo; + struct timeval tv; + fd_set rfds,wfds; + int nfds; + int r, r1,i; + + handle_x_event(rt); + +/* fd = XConnectionNumber(display);*/ + nfds = fd + 1; + while(1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_SET(fd, &rfds); + for(i=0;i<rt->n_monitor;i++) { + if (rt->monitors[i].type == MONITOR_READ) + FD_SET(rt->monitors[i].fd, &rfds); + else if (rt->monitors[i].type == MONITOR_WRITE) + FD_SET(rt->monitors[i].fd, &wfds); + } + + get_now(&now); + r = mb_tman_next_timeout(tman, &now, &tmo); + + if(r == 0) { + tv.tv_sec = MB_TIMEVAL_SEC(&tmo); + tv.tv_usec = MB_TIMEVAL_USEC(&tmo); + r1 = select(nfds, &rfds, NULL, NULL, &tv); + } else + r1 = select(nfds, &rfds, NULL, NULL, NULL); + + if(r1 == -1) { + perror("select"); + break; + } + + if(r1 == 0) { + get_now(&now); + mb_tman_handle_timeout(tman, &now); + rdman_redraw_changed(rdman); + } else if(FD_ISSET(fd, &rfds)){ + handle_x_event(rt); + } else { + for(i=0;i<rt->n_monitor;i++) { + if (rt->monitors[i].type == MONITOR_READ) { + if (FD_ISSET(rt->monitors[i].fd, &rfds)) + rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); + } else if (rt->monitors[i].type == MONITOR_WRITE) { + if (FD_ISSET(rt->monitors[i].fd, &wfds)) + rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); + } + } + } + } +} + +#define ERR -1 +#define OK 0 + +static int dfb_init_connection(int w, int h, + IDirectFB **dfb, + IDirectFBSurface **primary) { + DFBSurfaceDescription dsc; + + DirectFBInit(NULL, NULL); + DirectFBCreate(dfb); + (*dfb)->SetCooperativeLevel(*dfb, DFSCL_FULLSCREEN); + dsc.flags = DSDESC_CAPS; + dsc.caps = DSCAPS_PRIMARY; + (*dfb)->CreateSurface(*dfb, &dsc, primary); + (*primary)->GetSize(*primary, &w, &h); + (*primary)->SetColor(*primary, 0xff, 0xff, 0xff, 0xff); + (*primary)->FillRectangle(*primary, 0, 0, w, h); + + return OK; +} + +/*! \brief Initialize a MadButterfy runtime for DirectFB. + * + * This one is very like X_MB_init(), except it accepts a + * X_MB_runtime_t object initialized with a display connected to a DirectFB + * server and an opened window. + * + * Following field of the X_MB_runtime_t object should be initialized. + * - w, h + * - win + * - dfb + * - primary + */ +static int X_MB_init_with_win_internal(X_MB_runtime_t *xmb_rt) { + mb_img_ldr_t *img_ldr; + int w, h; + + w = xmb_rt->w; + h = xmb_rt->h; + + 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) + xmb_rt->backend_surface = + mbe_directfb_surface_create(xmb_rt->dfb, xmb_rt->primary); + + 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. + xmb_rt->rdman->rt = xmb_rt; + + xmb_rt->tman = mb_tman_new(); + + img_ldr = simple_mb_img_ldr_new(""); + xmb_rt->img_ldr = img_ldr; + rdman_set_img_ldr(xmb_rt->rdman, img_ldr); + memset(xmb_rt->monitors,0,sizeof(xmb_rt->monitors)); + +#ifndef ONLY_MOUSE_MOVE_RAW + xmb_rt->last = NULL; +#endif + +/* X_kb_init(&xmb_rt->kbinfo, xmb_rt->display, xmb_rt->rdman);*/ + + return OK; +} + +/*! \brief Initialize a MadButterfy runtime for DirectFB. + * + * It setups a runtime environment to run MadButterfly with DirectFB. + * Users should specify width and height of the opening window. + */ +static int X_MB_init(X_MB_runtime_t *xmb_rt, const char *display_name, + int w, int h) { + int r; + + memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + + xmb_rt->w = w; + xmb_rt->h = h; + r = dfb_init_connection(w, h, &xmb_rt->dfb, &xmb_rt->primary); + + if(r != OK) + return ERR; + + r = X_MB_init_with_win_internal(xmb_rt); + + return r; +} + +static void X_MB_destroy(X_MB_runtime_t *xmb_rt) { + if (xmb_rt->rdman) { + redraw_man_destroy(xmb_rt->rdman); + free(xmb_rt->rdman); + } + + if (xmb_rt->tman) + mb_tman_free(xmb_rt->tman); + + if (xmb_rt->img_ldr) + MB_IMG_LDR_FREE(xmb_rt->img_ldr); + + if (xmb_rt->cr) + mbe_destroy(xmb_rt->cr); + + if (xmb_rt->backend_cr) + mbe_destroy(xmb_rt->backend_cr); + + 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); + + if (xmb_rt->primary) + xmb_rt->primary->Release(xmb_rt->primary); + + if (xmb_rt->dfb) + xmb_rt->dfb->Release(xmb_rt->dfb); +} + +void *X_MB_new(const char *display_name, int w, int h) { + X_MB_runtime_t *rt; + int r; + + rt = O_ALLOC(X_MB_runtime_t); + + if (rt == NULL) + return NULL; + + r = X_MB_init(rt, display_name, w, h); + + if (r != OK) { + free(rt); + return NULL; + } + + return rt; +} + +void X_MB_free(void *rt) { + X_MB_destroy((X_MB_runtime_t *) rt); + free(rt); +} + +/*! \brief Free runtime created with X_MB_new_with_win(). + */ +void +X_MB_free_keep_win(void *rt) { + X_MB_destroy_keep_win((X_MB_runtime_t *) rt); + free(rt); +} + +subject_t *X_MB_kbevents(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + return xmb_rt->kbinfo.kbevents; +} + +redraw_man_t *X_MB_rdman(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + return xmb_rt->rdman; +} + +mb_tman_t *X_MB_tman(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + return xmb_rt->tman; +} + +observer_factory_t *X_MB_observer_factory(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + observer_factory_t *factory; + + factory = rdman_get_observer_factory(xmb_rt->rdman); + return factory; +} + +mb_img_ldr_t *X_MB_img_ldr(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + mb_img_ldr_t *img_ldr; + + img_ldr = xmb_rt->img_ldr; + + return img_ldr; +} + +void X_MB_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) +{ + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + int i; + + for(i=0;i<xmb_rt->n_monitor;i++) { + if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { + xmb_rt->monitors[i].f = f; + xmb_rt->monitors[i].arg = arg; + return; + } + } + for(i=0;i<xmb_rt->n_monitor;i++) { + if (xmb_rt->monitors[i].type == 0) { + xmb_rt->monitors[i].type = type; + xmb_rt->monitors[i].fd = fd; + xmb_rt->monitors[i].f = f; + xmb_rt->monitors[i].arg = arg; + return; + } + } + if (i == MAX_MONITORS) return; + xmb_rt->monitors[i].type = type; + xmb_rt->monitors[i].fd = fd; + xmb_rt->monitors[i].f = f; + xmb_rt->monitors[i].arg = arg; + i++; + xmb_rt->n_monitor=i; +} + +void X_MB_remove_event(void *rt, int type, int fd) +{ + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + int i; + for(i=0;i<xmb_rt->n_monitor;i++) { + if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { + xmb_rt->monitors[i].type = 0; + return; + } + } +} + +mb_backend_t backend = { X_MB_new, + X_MB_free, + X_MB_add_event, + X_MB_remove_event, + X_MB_handle_connection, + X_MB_kbevents, + X_MB_rdman, + X_MB_tman, + X_MB_observer_factory, + X_MB_img_ldr + }; + +/*! \defgroup x_supp_nodejs_sup Export functions for supporting nodejs plugin. + * + * These functions are for internal using. + * @{ + */ +/*! \brief Exported for nodejs plugin to call handle_x_event. + */ +void _X_MB_handle_x_event_for_nodejs(void *rt) { + handle_x_event((X_MB_runtime_t *)rt); +} + +/*! \brief Called at end of an iteration of X event loop. + */ +void +_X_MB_no_more_event(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt; + + no_more_event(xmb_rt); +} + +/* @} */
--- a/src/event.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/event.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \file * \brief Convenience functions for event relative work. */ @@ -135,11 +137,11 @@ #define MB_OBJ_INIT(obj, type) do { (obj)->obj_type = type; } while(0) #define GEF_OV_DRAW 0x1 -#define GEF_HIDDEN 0x2 +#define GEF_NOT_SHOWED 0x20 struct shape { mb_obj_t obj; - + coord_t *coord; area_t area; shape_t *all_next; @@ -148,7 +150,7 @@ void *fill, *stroke; struct shape *sibling; int flags; - + int num_points; co_aix points[32][2]; }; @@ -179,7 +181,7 @@ struct coord { mb_obj_t obj; - + area_t area; int flags; coord_t *parent; @@ -208,7 +210,7 @@ void _areas_merge(area_t *area1, area_t *area2) { co_aix lu_x, lu_y; co_aix rb_x, rb_y; - + lu_x = area2->x; lu_y = area2->y; rb_x = lu_x + area2->w - 1; @@ -225,7 +227,7 @@ area_t *cur_area; area = coord_get_area(coord); - + shape = STAILQ_HEAD(coord->shapes); if(shape != NULL) { cur_area = sh_get_area(shape); @@ -236,7 +238,7 @@ cur_area = coord_get_area(child); } memcpy(area, cur_area, sizeof(area_t)); - + FOR_COORD_SHAPES(coord, shape) { cur_area = sh_get_area(shape); _areas_merge(area, cur_area); @@ -261,9 +263,9 @@ coord_t *preorder_coord_subtree(coord_t *root, coord_t *last) { if(STAILQ_HEAD(last->children) && !(last->flags & COF_SKIP)) return STAILQ_HEAD(last->children); - + last->flags &= ~COF_SKIP; - + if(last == root) return NULL; while(STAILQ_NEXT(coord_t, sibling, last) == NULL) { @@ -282,7 +284,7 @@ static coord_t *postorder_coord_subtree(coord_t *root, coord_t *last) { coord_t *cur; - + if(last != NULL) { if(STAILQ_NEXT(coord_t, sibling, last) == NULL) { if(cur == root) @@ -445,7 +447,7 @@ memset(shape, 0, sizeof(shape_t)); MB_OBJ_INIT(&shape->obj, MBO_PATH); STAILQ_INS(rdman->all_shapes, shape_t, all_next, shape); - + return shape; } @@ -482,7 +484,7 @@ int i, j; cr = surf->cr; - + STAILQ_FOR_EACH(cr->drawed, shape_t, sibling, shape1) { for(i = 0; i < shape1->num_points; i++) { x1 = shape1->points[i][0]; @@ -510,7 +512,7 @@ co_aix x, co_aix y) { shape_t *shape; int r; - + r = rdman_force_clean(rdman); if(r != OK) return ERR; @@ -611,7 +613,7 @@ cr = rdman_get_cr(rdman); for(i = rdman_shape_gl_len(rdman) - 1; i >= 0; i--) { shape = rdman_get_shape_gl(rdman, i); - if(sh_get_flags(shape, GEF_HIDDEN)) + if(sh_get_flags(shape, GEF_NOT_SHOWED)) continue; r = _shape_pos_is_in(shape, x, y, in_stroke, cr); if(r) @@ -676,7 +678,7 @@ rdman_surface = mbe_get_target(rdman_get_cr(rdman)); w = mbe_image_surface_get_width(rdman_surface); h = mbe_image_surface_get_height(rdman_surface); - + surface = mbe_image_surface_create(MB_IFMT_A1, w, h); if(surface == NULL) return NULL; @@ -684,7 +686,7 @@ cr = mbe_create(surface); if(cr == NULL) mbe_surface_destroy(surface); - + return cr; } @@ -693,20 +695,14 @@ mbe_destroy(cr); } -#ifdef OVERLAY_DRAW_TEST -/* - * Since we remove mbe_clip(), mb_objs_are_overlay() should not use - * clip for testing overlay anymore. - */ - static void _draw_to_mask(shape_t *shape, mbe_t *cr) { if(sh_get_flags(shape, GEF_OV_DRAW)) return; - + draw_shape_path(shape, cr); mbe_clip(cr); - + sh_set_flags(shape, GEF_OV_DRAW); } @@ -734,7 +730,6 @@ return FALSE; } -#endif /*! \brief Is a mb_obj_t overlaid with another mb_obj_t and * descendants. @@ -752,9 +747,9 @@ shape_t *shape, *candi_shape; int obj_is_shape; int r; - + obj_is_shape = IS_MBO_SHAPES(obj); - + if(obj_is_shape) { shape = (shape_t *)obj; area = sh_get_area(shape); @@ -763,30 +758,26 @@ area = coord_get_area(coord); shape = NULL; } - + if(IS_MBO_SHAPES(others_root)) { candi_shape = (shape_t *)others_root; candi_area = sh_get_area(candi_shape); - + r = areas_are_overlay(area, candi_area); if(!r) return FALSE; - -#ifdef OVERLAY_DRAW_TEST + if(!obj_is_shape) return TRUE; _draw_to_mask(candi_shape, cr); r = _fill_and_check(shape, cr); - + return r; -#else - return TRUE; -#endif } - + ASSERT(IS_MBO_COORD(others_root)); - + root = (coord_t *)others_root; FOR_COORDS_PREORDER(root, candi_coord) { candi_area = coord_get_area(candi_coord); @@ -795,27 +786,23 @@ preorder_coord_skip_subtree(candi_coord); continue; } - + FOR_COORD_SHAPES(candi_coord, candi_shape) { candi_area = sh_get_area(candi_shape); r = areas_are_overlay(area, candi_area); if(!r) continue; -#ifdef OVERLAY_DRAW_TEST if(!obj_is_shape) return TRUE; - + _draw_to_mask(candi_shape, cr); r = _fill_and_check(shape, cr); if(r) return TRUE; -#else - return TRUE; -#endif } } - + return FALSE; } @@ -858,7 +845,7 @@ r = _is_obj_objs_overlay(obj1, obj2, cr); goto out; } - + root = (coord_t *)obj1; FOR_COORDS_PREORDER(root, coord) { area = coord_get_area(coord); @@ -875,7 +862,7 @@ } } r = FALSE; - + out: _clear_ov_draw(obj2); /* marked by _is_obj_objs_overlay() */ _release_mbe_for_testing(cr); @@ -896,7 +883,7 @@ cr = mbe_create(surf); backend = mbe_create(surf); rdman = redraw_man_new(cr, backend); - + return rdman; } @@ -949,7 +936,6 @@ _free_fake_rdman(rdman); } -#ifdef OVERLAY_DRAW_TEST static void test_is_obj_objs_overlay(void) { redraw_man_t *rdman; @@ -978,7 +964,7 @@ shape_add_point(shape1, 3, 2); shape_add_point(shape2, 5, 5); shape_add_point(shape3, 4, 3); - + surf = mbe_image_surface_create(MB_IFMT_A1, 100, 100); cr = mbe_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)coord2, cr); @@ -1026,7 +1012,7 @@ mbe_destroy(cr); mbe_surface_destroy(surf); sh_clear_flags(shape3, GEF_OV_DRAW); - + shape_add_point(shape1, 5, 5); surf = mbe_image_surface_create(MB_IFMT_A1, 100, 100); @@ -1113,55 +1099,52 @@ r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)coord2); CU_ASSERT(!r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)coord2); CU_ASSERT(!r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape2); CU_ASSERT(!r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape2); CU_ASSERT(!r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape3); CU_ASSERT(!r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape3); CU_ASSERT(!r); shape_add_point(shape1, 5, 5); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)coord2); CU_ASSERT(r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)coord2); CU_ASSERT(r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape2); CU_ASSERT(r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape2); CU_ASSERT(r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape3); CU_ASSERT(!r); - + r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape3); CU_ASSERT(!r); _free_fake_rdman(rdman); } -#endif CU_pSuite get_event_suite(void) { CU_pSuite suite; suite = CU_add_suite("Suite_event", NULL, NULL); CU_ADD_TEST(suite, test_mb_obj_pos_is_in); -#ifdef OVERLAY_DRAW_TEST CU_ADD_TEST(suite, test_is_obj_objs_overlay); CU_ADD_TEST(suite, test_mb_objs_are_overlay); -#endif return suite; }
--- a/src/geo.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/geo.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \brief Determine who should be re-drawed. * \file * When part of graphic are chagned, not mater size, shape, or position, @@ -23,7 +25,7 @@ if(is_scale_overlay(r1->x, r1->w, r2->x, r2->w) && is_scale_overlay(r1->y, r1->h, r2->y, r2->h)) return 1; - + return 0; } @@ -36,7 +38,7 @@ co_aix min_y, max_y; co_aix x, y; int i; - + /*! \note {x=0, y=0, w=0, h=0} geometry value for a n_pos=0 request * can prevent cursor flasing for Cairo XLib. * (see changeset 21db69d46835) @@ -102,7 +104,7 @@ {33, 25}, {49, 12}, {14, 28}, {39, 56}}; geo_t g; - + geo_init(&g); geo_from_positions(&g, 4, data); CU_ASSERT(g.cur_area->x == 14);
--- a/src/graph_engine_cairo.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/graph_engine_cairo.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <fontconfig/fontconfig.h> #include <cairo-ft.h> #include "mb_graph_engine_cairo.h" @@ -17,7 +19,7 @@ */ static FcPattern *query_font_pattern(const char *family, int slant, int weight) { - FcPattern *ptn, *p, *fn_ptn; + FcPattern *ptn, *fn_ptn; FcValue val; FcConfig *cfg; FcBool r; @@ -30,33 +32,32 @@ cfg = FcConfigGetCurrent(); ptn = FcPatternCreate(); - p = FcPatternCreate(); - if(ptn == NULL || p == NULL) + if(ptn == NULL) goto err; val.type = FcTypeString; val.u.s = family; FcPatternAdd(ptn, "family", val, FcTrue); - + val.type = FcTypeInteger; val.u.i = slant_map[slant]; FcPatternAdd(ptn, "slant", val, FcTrue); - + val.type = FcTypeInteger; val.u.i = weight; FcPatternAdd(ptn, "weight", val, FcTrue); - r = FcConfigSubstituteWithPat(cfg, ptn, NULL, FcMatchPattern); - if(!r) - goto err; - - r = FcConfigSubstituteWithPat(cfg, p, ptn, FcMatchFont); + FcDefaultSubstitute(ptn); + + r = FcConfigSubstituteWithPat(cfg, ptn, ptn, FcMatchPattern); if(!r) goto err; - FcDefaultSubstitute(p); + r = FcConfigSubstituteWithPat(cfg, ptn, ptn, FcMatchFont); + if(!r) + goto err; - fn_ptn = FcFontMatch(cfg, p, &result); + fn_ptn = FcFontMatch(cfg, ptn, &result); /* It is supposed to return FcResultMatch. But, it is no, now. * I don't know why. Someone should figure out the issue. @@ -71,15 +72,12 @@ goto err; FcPatternDestroy(ptn); - FcPatternDestroy(p); - + return fn_ptn; - + err: if(ptn) FcPatternDestroy(ptn); - if(p) - FcPatternDestroy(p); return NULL; } @@ -94,11 +92,11 @@ mbe_query_font_face(const char *family, int slant, int weight) { mbe_font_face_t *cface; FcPattern *ptn; - + ptn = query_font_pattern(family, slant, weight); cface = cairo_ft_font_face_create_for_pattern(ptn); FcPatternDestroy(ptn); - + return cface; } @@ -121,7 +119,7 @@ cx1, cy1, radius1); if(ptn == NULL) return NULL; - + stop = stops; for(i = 0; i < stop_cnt; i++) { cairo_pattern_add_color_stop_rgba(ptn, stop->offset, @@ -152,57 +150,3 @@ 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 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,1 @@ +/* Keep Me */
--- a/src/graph_engine_skia.cpp Mon Jul 19 15:44:49 2010 +0800 +++ b/src/graph_engine_skia.cpp Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 /*! \page ge_layer Graphic Engine Layer * * Graphic Engine Layer is an abstract of graphic engine; likes Cairo @@ -81,7 +83,7 @@ SkPath *path, *subpath; SkPaint *paint; SkRegion *saved_region; - + struct _mbe_states_t *states; }; @@ -135,9 +137,9 @@ SkPath path; co_aix x, y; co_aix reverse[6]; - + *mbe->saved_region = canvas->getTotalClip(); - + compute_reverse(ptn->matrix, reverse); x = 0; y = 0; matrix_trans_pos(reverse, &x, &y); @@ -149,14 +151,14 @@ matrix_trans_pos(reverse, &x, &y); path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); path.close(); - + canvas->clipPath(path, SkRegion::kIntersect_Op); } static void _finish_sized_pattern(mbe_t *mbe) { SkCanvas *canvas = mbe->canvas; - + canvas->setClipRegion(*mbe->saved_region); } @@ -180,7 +182,7 @@ MB_MATRIX_2_SKMATRIX(canvas_matrix, mbe->states->matrix); path->addPath(*subpath, canvas_matrix); - + subpath->getLastPt(&point); subpath->rewind(); subpath->moveTo(point); @@ -200,7 +202,7 @@ SkMatrix skmatrix; paint->setStyle(style); - + if(ptn != NULL) { /* Local matrix of SkShader is a mapping from source pattern to * user space. Unlikely, for Cairo is a mapping from user space @@ -223,7 +225,7 @@ static void _finish_paint(mbe_t *mbe) { mbe_pattern_t *ptn = mbe->states->ptn; - + mbe->paint->reset(); if(ptn != NULL && ptn->has_size) _finish_sized_pattern(mbe); @@ -241,13 +243,13 @@ free(ptn); return NULL; } - + ptn->has_size = 1; ptn->w = bitmap->width(); ptn->h = bitmap->height(); memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); - + return ptn; } @@ -269,7 +271,7 @@ goto fail; center.set(CO_AIX_2_SKSCALAR(cx1), CO_AIX_2_SKSCALAR(cy1)); - + stop = stops; for(i = 0; i < stop_cnt; i++) { colors[i] = MBSTOP_2_SKCOLOR(stop); @@ -289,11 +291,11 @@ goto fail; memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); - + delete colors; delete poses; return ptn; - + fail: if(ptn) free(ptn); if(colors) delete colors; @@ -320,7 +322,7 @@ points[0].set(CO_AIX_2_SKSCALAR(x0), CO_AIX_2_SKSCALAR(y0)); points[1].set(CO_AIX_2_SKSCALAR(x1), CO_AIX_2_SKSCALAR(y1)); - + stop = stops; for(i = 0; i < stop_cnt; i++) { colors[i] = MBSTOP_2_SKCOLOR(stop); @@ -339,11 +341,11 @@ goto fail; memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); - + delete colors; delete poses; return ptn; - + fail: if(ptn) free(ptn); if(colors) delete colors; @@ -351,11 +353,6 @@ return NULL; } -mbe_pattern_t * -mbe_pattern_create_image(mb_img_data_t *img) { - return NULL; -} - void mbe_pattern_set_matrix(mbe_pattern_t *ptn, const co_aix matrix[6]) { SkMatrix skmatrix; @@ -386,11 +383,49 @@ return (unsigned char *)((SkBitmap *)surface)->getPixels(); } +mbe_surface_t *mbe_image_surface_create_from_png(const char *filename) {} + +mbe_surface_t * +mbe_image_surface_create_for_data(unsigned char *data, + mb_img_fmt_t fmt, + int width, int height, + int stride) { + SkBitmap *bitmap; + SkBitmap::Config cfg; + + switch(fmt) { + case MB_IFMT_ARGB32: + cfg = SkBitmap::kARGB_8888_Config; break; + + case MB_IFMT_A8: + cfg = SkBitmap::kA8_Config; break; + + case MB_IFMT_A1: + cfg = SkBitmap::kA1_Config; break; + + case MB_IFMT_RGB16_565: + cfg = SkBitmap::kRGB_565_Config; break; + + case MB_IFMT_RGB24: + default: + return NULL; + } + + bitmap = new SkBitmap(); + if(bitmap == NULL) + return NULL; + + bitmap->setConfig(cfg, width, height, stride); + bitmap->setPixels(data); + + return (mbe_surface_t *)bitmap; +} + mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface) { SkBitmap *bitmap = (SkBitmap *)surface; mb_img_fmt_t fmt; SkBitmap::Config cfg; - + cfg = bitmap->getConfig(); switch(cfg) { case SkBitmap::kARGB_8888_Config: @@ -420,25 +455,25 @@ switch(fmt) { case MB_IFMT_ARGB32: cfg = SkBitmap::kARGB_8888_Config; break; - + case MB_IFMT_A8: cfg = SkBitmap::kA8_Config; break; - + case MB_IFMT_A1: cfg = SkBitmap::kA1_Config; break; - + case MB_IFMT_RGB16_565: cfg = SkBitmap::kRGB_565_Config; break; - + case MB_IFMT_RGB24: default: return NULL; } - + bitmap = new SkBitmap(); if(bitmap == NULL) return NULL; - + bitmap->setConfig(cfg, width, height); bitmap->allocPixels(); @@ -470,12 +505,12 @@ SkColorFilter::CreatePorterDuffFilter(color, SkPorterDuff::kSrcOver_Mode); mbe_paint(canvas); - + } void mbe_surface_destroy(mbe_surface_t *surface) { SkBitmap *bmap = (SkBitmap *)surface; - + delete bmap; } @@ -511,7 +546,7 @@ if(!canvas->subpath->isEmpty()) _update_path(canvas); - + _prepare_paint(canvas, SkPaint::kFill_Style); canvas->canvas->drawPath(*path, *paint); @@ -523,7 +558,7 @@ canvas->states->ptn = source; } -void mbe_reset_scissoring(mbe_t *canvas) { +void mbe_reset_clip(mbe_t *canvas) { SkRegion clip; _canvas_device_region(canvas->canvas, &clip); @@ -543,7 +578,7 @@ void mbe_rectangle(mbe_t *canvas, co_aix x, co_aix y, co_aix width, co_aix height) { SkPath *subpath = canvas->subpath; - + subpath->addRect(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y), CO_AIX_2_SKSCALAR(x + width), CO_AIX_2_SKSCALAR(y + height)); @@ -572,7 +607,7 @@ struct _mbe_states_t *states; _update_path(canvas); - + states = canvas->states; ASSERT(states->next); canvas->states = states->next; @@ -595,10 +630,10 @@ if(!canvas->subpath->isEmpty()) _update_path(canvas); - + _canvas_device_region(canvas->canvas, &dev_region); region.setPath(*canvas->path, dev_region); - + in_fill = region.contains(x, y); return in_fill; @@ -637,7 +672,7 @@ mbe = (mbe_t *)malloc(sizeof(mbe_t)); if(mbe == NULL) return NULL; - + mbe->states = (struct _mbe_states_t *) malloc(sizeof(struct _mbe_states_t)); states = mbe->states; @@ -645,7 +680,7 @@ free(mbe); return NULL; } - + canvas->ref(); mbe->canvas = canvas; mbe->path = new SkPath(); @@ -663,7 +698,7 @@ goto fail; memcpy(states->matrix, id_matrix, sizeof(co_aix) * 6); - + return mbe; fail: @@ -674,7 +709,7 @@ if(mbe->saved_region) delete mbe->saved_region; free(states); free(mbe); - + return NULL; } @@ -688,20 +723,20 @@ delete bitmap; return NULL; } - + mbe = skia_mbe_create_by_canvas(canvas); canvas->unref(); - + if(mbe == NULL) { delete bitmap; } - + return mbe; } void mbe_destroy(mbe_t *canvas) { struct _mbe_states_t *states; - + canvas->canvas->unref(); delete canvas->path; delete canvas->subpath; @@ -710,7 +745,7 @@ while(canvas->states) { states = canvas->states; canvas->states = states->next; - + if(states->ptn && states->ptn_owned) mbe_pattern_destroy(states->ptn); free(states); @@ -722,9 +757,9 @@ SkPaint *paint = canvas->paint; ASSERT(paint); - + _prepare_paint(canvas, SkPaint::kFill_Style); - + canvas->canvas->drawPaint(*paint); _finish_paint(canvas); @@ -735,7 +770,7 @@ states = (struct _mbe_states_t *)malloc(sizeof(struct _mbe_states_t)); ASSERT(states); - + memcpy(states, canvas->states, sizeof(struct _mbe_states_t)); states->next = canvas->states; canvas->states = states; @@ -747,23 +782,13 @@ canvas->subpath->rewind(); } -void mbe_scissoring(mbe_t *canvas, int n_areas, area_t **areas) { - int i; - area_t *area; - SkPath *path; +void mbe_clip(mbe_t *canvas) { + if(!canvas->subpath->isEmpty()) + _update_path(canvas); - mbe_new_path(canvas); - - path = canvas->path; - for(i = 0; i < n_areas; i++) { - area = areas[i]; - path->addRect(CO_AIX_2_SKSCALAR(area->x), CO_AIX_2_SKSCALAR(area->y), - CO_AIX_2_SKSCALAR(area->x + area->width), - CO_AIX_2_SKSCALAR(area->y + area->height)); - } - - canvas->canvas->clipPath(*path, SkRegion::kIntersect_Op); - path->rewind(); + canvas->canvas->clipPath(*canvas->path, SkRegion::kIntersect_Op); + canvas->path->rewind(); + canvas->subpath->rewind(); } mbe_font_face_t * mbe_query_font_face(const char *family, @@ -787,7 +812,7 @@ bmap = &src->canvas->getDevice()->accessBitmap(false); dst->canvas->drawBitmap(*bmap, 0, 0, paint); - + paint->reset(); mode->unref(); /* _finish_paint(dst); */ @@ -795,7 +820,7 @@ void mbe_transform(mbe_t *mbe, co_aix matrix[6]) { _update_path(mbe); - + matrix_mul(matrix, mbe->states->matrix, mbe->states->matrix); } @@ -815,7 +840,7 @@ r = CO_AIX_2_SKSCALAR(radius); ang_start = CO_AIX_2_SKSCALAR(angle_start * 180 / PI); ang_stop = CO_AIX_2_SKSCALAR(angle_stop * 180 / PI); - + /* Skia can only draw an arc in clockwise directly. We negative * start and stop point to draw the arc in the mirror along x-axis * in a sub-path. Then, the sub-path are reflected along x-axis, @@ -826,7 +851,7 @@ SkMatrix matrix; co_aix reflect[6] = { 1, 0, 0, 0, -1, 0}; - + rect.set(-r, -r, r, r); sweep = ang_start - ang_stop; tmppath.arcTo(rect, -ang_start, sweep, false);
--- a/src/img_ldr.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/img_ldr.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,6 +1,7 @@ +// -*- 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" @@ -17,7 +18,7 @@ struct _simple_mb_img_data { mb_img_data_t img; - Imlib_Image img_hdl; + mbe_surface_t *surf; }; typedef struct _simple_mb_img_data simple_mb_img_data_t; @@ -27,38 +28,35 @@ 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; + mbe_surface_t *surf; char *fname; int sz; sz = strlen(sldr->repo); sz += strlen(img_id); fname = (char *)malloc(sz + 2); - strcpy(fname, sldr->repo); + 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) + + surf = mbe_image_surface_create_from_png(fname); + if(surf == NULL) 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(); + mbe_surface_destroy(surf); 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.content = mbe_image_surface_get_data(surf); + img->img.w = mbe_image_surface_get_width(surf); + img->img.h = mbe_image_surface_get_height(surf); + img->img.stride = mbe_image_surface_get_stride(surf); + img->img.fmt = mbe_image_surface_get_format(surf); img->img.free = simple_mb_img_ldr_img_free; - img->img_hdl = img_hdl; + img->surf = surf; return (mb_img_data_t *)img; } @@ -66,9 +64,7 @@ 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(); + mbe_surface_destroy((mbe_surface_t *)simg->surf); free(img); } @@ -104,9 +100,9 @@ ((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; }
--- /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; +}
--- a/src/mbaf/animated_menu.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/mbaf/animated_menu.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <mb.h> #include <string.h> @@ -12,9 +14,11 @@ FOR_COORD_MEMBERS(g, geo) { shape = geo_get_shape(geo); +#ifdef SH_TEXT if(shape->obj.obj_type == MBO_TEXT) { sh_text_set_text(shape, text); } +#endif } } @@ -22,13 +26,8 @@ { int i; coord_t *textgroup; - shape_t *text; coord_t *group; coord_t *lightbar; - int tmp; - mb_timeval_t start, playing, now; - mb_progm_t *progm; - mb_word_t *word; // fill new item for(i=0;i<8;i++) { @@ -63,7 +62,6 @@ { int i; coord_t *textgroup; - shape_t *text; coord_t *group; coord_t *lightbar; int tmp; @@ -100,7 +98,7 @@ lightbar = (coord_t *) m->lightbar; mb_shift_new(0,m->menus_y[m->cur]-coord_y(lightbar),lightbar,word); - + MB_TIMEVAL_SET(&start, 0, m->speed); MB_TIMEVAL_SET(&playing, 0, 0); word = mb_progm_next_word(progm, &start, &playing); @@ -110,7 +108,7 @@ mb_progm_free_completed(progm); m->ready--; subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m); - mb_progm_start(progm, X_MB_tman(MBAF_RDMAN(m->app)->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(MBAF_RDMAN(m->app)->rt), &now); rdman_redraw_changed(MBAF_RDMAN(m->app)); tmp = m->items[8]; for(i=8;i>0;i--) { @@ -123,11 +121,6 @@ static void mb_animated_menu_fillMenuContentDown(mb_animated_menu_t *m) { int i; - coord_t *textgroup; - shape_t *text; - coord_t *group; - coord_t *lightbar; - char name[255]; int tmp; mb_timeval_t start, playing, now; mb_progm_t *progm; @@ -165,7 +158,7 @@ mb_progm_free_completed(progm); m->ready--; subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m); - mb_progm_start(progm, X_MB_tman(MBAF_RDMAN(m->app)->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(MBAF_RDMAN(m->app)->rt), &now); rdman_redraw_changed(MBAF_RDMAN(m->app)); tmp = m->items[0]; for(i=0;i<8;i++) { @@ -179,7 +172,6 @@ mb_timeval_t start, playing, now; mb_progm_t *progm; mb_word_t *word; - coord_t *group; coord_t *lightbar; m->progm = progm = mb_progm_new(1, MBAF_RDMAN(m->app)); @@ -193,7 +185,7 @@ mb_progm_free_completed(progm); m->ready--; subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m); - mb_progm_start(progm, X_MB_tman(MBAF_RDMAN(m->app)->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(MBAF_RDMAN(m->app)->rt), &now); rdman_redraw_changed(MBAF_RDMAN(m->app)); } @@ -209,7 +201,7 @@ mb_animated_menu_fillMenuContentUp(m); mb_animated_menu_update(m); } else { - if (m->cur == 0) + if (m->cur == 0) return; m->cur--; mb_animated_menu_moveLightBar(m); @@ -268,7 +260,7 @@ { mb_animated_menu_t *m = (mb_animated_menu_t *) arg; X_kb_event_t *xkey; - + xkey = &m->pending_keys[m->pending_pos]; m->pending_pos = (m->pending_pos + 1) & 0xf; mb_animated_menu_keyHandler((event_t *) xkey, m); @@ -314,9 +306,9 @@ } } -/** \brief Create an instace of animated menu. +/** \brief Create an instace of animated menu. * - * The objectnames is used to extract symbols from the SVG file. + * The objectnames is used to extract symbols from the SVG file. * ${objectnames}0 - ${objectnames}8 is the text object. * ${objectnames}_lightbar is the lightbar. * @@ -324,7 +316,7 @@ mb_animated_menu_t *mb_animated_menu_new(mbaf_t *app,mb_sprite_t *sp,char *objnames,char *menus[]) { mb_animated_menu_t *m; - int i,len; + int i; char name[255]; mb_obj_t *l; int ii; @@ -334,7 +326,7 @@ else for(i=0;menus[i];i++); ii=9; - + m = (mb_animated_menu_t *) malloc(sizeof(mb_animated_menu_t)); m->items = (int *) malloc(sizeof(int)*ii*2+sizeof(mb_obj_t *)*ii); m->app = app;
--- a/src/mbaf/mbapp.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/mbaf/mbapp.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,31 +1,34 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <mb.h> #include <mb_af.h> +#include <mb_backend.h> mbaf_t *mbaf_init(const char *module, const char *module_dir) { mbaf_t *app = (mbaf_t *) malloc(sizeof(mbaf_t)); - void *rt; + mb_rt_t *rt; - rt = backend.init(":0.0", 800, 600); + rt = mb_runtime_new(":0.0", 800, 600); if(rt == NULL) return NULL; sprite_set_search_path(module_dir); app->rt = rt; - app->rdman = backend.rdman(rt); - app->kbevents = backend.kbevents(rt); - + app->rdman = mb_runtime_rdman(rt); + app->kbevents = mb_runtime_kbevents(rt); + app->rootsprite= sprite_load(module,app->rdman, app->rdman->root_coord); if(app->rootsprite == NULL) { - backend.free(rt); + mb_runtime_free(rt); free(app); return NULL; } - + rdman_attach_backend(app->rdman, rt); MB_SPRITE_GOTO_SCENE(app->rootsprite, 1); - + return app; } @@ -34,9 +37,9 @@ app->private = (void *) data; } -mb_tman_t *mbaf_get_timer(mbaf_t *app) +mb_timer_man_t *mbaf_get_timer(mbaf_t *app) { - return backend.tman(app->rt); + return mb_runtime_timer_man(app->rt); } void mbaf_loop(mbaf_t *app) @@ -45,11 +48,11 @@ * Start handle connections, includes one to X server. * User start to interact with the application. */ - backend.loop(app->rt); + mb_runtime_event_loop(app->rt); /* * Clean */ - backend.free(app->rt); + mb_runtime_free(app->rt); free(app); }
--- a/src/mbaf/mbbutton.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/mbaf/mbbutton.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <mb.h> @@ -24,16 +26,16 @@ rdman_redraw_changed(btn->rdman); } -static void mb_button_move(event_t *evt, void *arg) +static void mb_button_move(event_t *evt, void *arg) { mb_button_t *btn = (mb_button_t *) arg; - + printf("Mouse move\n"); coord_show(btn->active); mb_button_refresh(btn); } -static void mb_button_out(event_t *evt, void *arg) +static void mb_button_out(event_t *evt, void *arg) { mb_button_t *btn = (mb_button_t *) arg; @@ -61,7 +63,7 @@ mb_button_t *btn = (mb_button_t *) arg; btn->progm = NULL; - + } static void mb_button_pressed(event_t *evt, void *arg) @@ -91,7 +93,7 @@ subject_add_observer(mb_progm_get_complete(btn->progm), mb_button_end_animated_cb,btn); get_now(&now); printf("rt = %x\n", btn->rdman->rt); - mb_progm_start(progm, X_MB_tman(btn->rdman->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(btn->rdman->rt), &now); if (btn->press) btn->press(btn->arg); }
--- a/src/mbaf/mbobject.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/mbaf/mbobject.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,5 +1,8 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include "mb_types.h" #include "mb_obj.h" +#include "mb_config.h" void mb_obj_set_pos(mb_obj_t *obj, co_aix x, co_aix y) @@ -7,12 +10,14 @@ if (MBO_TYPE(obj) == MBO_COORD) { coord_x(((coord_t *) obj)) = x; coord_y(((coord_t *) obj)) = y; +#ifdef SH_TEXT } else if (MBO_TYPE(obj) == MBO_TEXT) { sh_text_set_pos((shape_t *) obj, x, y); +#endif } else { return; } - + } void mb_obj_get_pos(mb_obj_t *obj, co_aix *x, co_aix *y) @@ -20,12 +25,14 @@ if (MBO_TYPE(obj) == MBO_COORD) { *x = coord_x((coord_t *) obj); *y = coord_y((coord_t *) obj); +#ifdef SH_TEXT } else if (MBO_TYPE(obj) == MBO_TEXT) { sh_text_get_pos((shape_t *) obj, x, y); +#endif } else { return; } - + } void mb_obj_set_text(mb_obj_t *obj, const char *text) @@ -37,17 +44,21 @@ FOR_COORD_MEMBERS(g, geo) { shape = geo_get_shape(geo); +#ifdef SH_TEXT if(shape->obj.obj_type == MBO_TEXT) { sh_text_set_text(shape, text); return; } +#endif } +#ifdef SH_TEXT } else if (MBO_TYPE(obj) == MBO_TEXT) { sh_text_set_text((shape_t *) obj,text); +#endif } else { return; } - + } @@ -60,13 +71,17 @@ FOR_COORD_MEMBERS(g, geo) { shape = geo_get_shape(geo); +#ifdef SH_TEXT if(shape->obj.obj_type == MBO_TEXT) { sh_text_get_text(shape, text,size); return; } +#endif } +#ifdef SH_TEXT } else if (MBO_TYPE(obj) == MBO_TEXT) { sh_text_get_text((shape_t *) obj,text,size); +#endif } else { *text = 0; return;
--- a/src/mouse.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/mouse.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include "mb_types.h" #include "mb_redraw_man.h" @@ -10,20 +12,20 @@ mouse_event_t new_evt; coord_t *coord; shape_t *shape; - + ASSERT(evt->type == EVT_MOUSE_MOVE_RAW); - + obj = (mb_obj_t *)subject_get_object(evt->cur_tgt); if(rdman->last_mouse_over == obj) { evt->type = EVT_MOUSE_MOVE; return; } - + new_evt.x = mevt->x; new_evt.y = mevt->y; new_evt.but_state = mevt->but_state; new_evt.button = mevt->button; - + if(rdman->last_mouse_over != NULL) { new_evt.event.type = EVT_MOUSE_OUT; if(IS_MBO_COORD(rdman->last_mouse_over)) { @@ -33,14 +35,14 @@ shape = (shape_t *)rdman->last_mouse_over; ASSERT(shape->geo != NULL); subject_notify(sh_get_mouse_event_subject(shape), - (event_t *)&new_evt); + (event_t *)&new_evt); } } new_evt.event.type = EVT_MOUSE_OVER; subject_notify(evt->cur_tgt, (event_t *)&new_evt); rdman->last_mouse_over = obj; - + evt->flags |= EVTF_STOP_NOTIFY; } @@ -61,7 +63,7 @@ mb_prop_store_t *props; observer_t *observer; int cnt = 0; - + mevt = (monitor_event_t *)evt; rdman = (redraw_man_t *)arg; obj = (mb_obj_t *)subject_get_object(mevt->subject); @@ -73,7 +75,7 @@ cnt = 0; else cnt = (int)mb_prop_get(props, PROP_MEVT_OB_CNT); - + cnt++; mb_prop_set(props, PROP_MEVT_OB_CNT, (void *)cnt); if(cnt == 1) { @@ -86,7 +88,7 @@ mb_prop_set(props, PROP_MEVT_OBSERVER, observer); } break; - + case EVT_MONITOR_REMOVE: cnt = (int)mb_prop_get(props, PROP_MEVT_OB_CNT); cnt--; @@ -97,7 +99,7 @@ mb_prop_del(props, PROP_MEVT_OBSERVER); } break; - + case EVT_MONITOR_FREE: break; }
--- a/src/observer.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/observer.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include "mb_redraw_man.h" #include "mb_observer.h" @@ -7,7 +9,7 @@ #define ASSERT(x) #endif -subject_t *subject_new(ob_factory_t *factory, void *obj, int obj_type) { +subject_t *subject_new(observer_factory_t *factory, void *obj, int obj_type) { subject_t *subject; subject = factory->subject_alloc(factory); @@ -26,10 +28,10 @@ } /*! - * \todo Keep ob_factory following subject objects. + * \todo Keep observer_factory following subject objects. */ void subject_free(subject_t *subject) { - ob_factory_t *factory = subject->factory; + observer_factory_t *factory = subject->factory; observer_t *observer; monitor_event_t mevt; @@ -41,7 +43,7 @@ subject->flags |= SUBF_FREE; return; } - + if(subject->monitor_sub) { mevt.event.type = EVT_MONITOR_FREE; mevt.subject = subject; @@ -58,7 +60,7 @@ void subject_notify(subject_t *subject, event_t *evt) { - ob_factory_t *factory = subject->factory; + observer_factory_t *factory = subject->factory; observer_t *observer; subject_t *old_subject; int stop_propagate = 0; @@ -81,7 +83,7 @@ observer = STAILQ_NEXT(observer_t, next, observer)) { if (observer->type == EVT_ANY || observer->type == evt->type) { observer->hdr(evt, observer->arg); - + if(evt->flags & EVTF_STOP_NOTIFY) { stop_propagate = 1; break; @@ -112,7 +114,7 @@ */ observer_t *subject_add_event_observer(subject_t *subject, int type, evt_handler hdr, void *arg) { - ob_factory_t *factory = subject->factory; + observer_factory_t *factory = subject->factory; observer_t *observer; monitor_event_t mevt; @@ -139,7 +141,7 @@ */ observer_t *subject_add_event_observer_head(subject_t *subject, int type, evt_handler hdr, void *arg) { - ob_factory_t *factory = subject->factory; + observer_factory_t *factory = subject->factory; observer_t *observer; monitor_event_t mevt; @@ -164,11 +166,11 @@ void subject_remove_observer(subject_t *subject, observer_t *observer) { - ob_factory_t *factory = subject->factory; + observer_factory_t *factory = subject->factory; monitor_event_t mevt; STAILQ_REMOVE(subject->observers, observer_t, next, observer); - + if(subject->monitor_sub) { mevt.event.type = EVT_MONITOR_REMOVE; mevt.subject = subject; @@ -184,34 +186,36 @@ #include <CUnit/Basic.h> #include <stdlib.h> -static subject_t *test_subject_alloc(ob_factory_t *factory) { +static subject_t *test_subject_alloc(observer_factory_t *factory) { subject_t *subject; subject = (subject_t *)malloc(sizeof(subject_t)); return subject; } -static void test_subject_free(ob_factory_t *factory, subject_t *subject) { +static void +test_subject_free(observer_factory_t *factory, subject_t *subject) { free(subject); } -static observer_t *test_observer_alloc(ob_factory_t *factory) { +static observer_t *test_observer_alloc(observer_factory_t *factory) { observer_t *observer; observer = (observer_t *)malloc(sizeof(observer_t)); return observer; } -static void test_observer_free(ob_factory_t *factory, observer_t *observer) { +static void +test_observer_free(observer_factory_t *factory, observer_t *observer) { free(observer); } -static subject_t *test_get_parent_subject(ob_factory_t *factory, +static subject_t *test_get_parent_subject(observer_factory_t *factory, subject_t *subject) { return NULL; } -static ob_factory_t test_factory = { +static observer_factory_t test_factory = { test_subject_alloc, test_subject_free, test_observer_alloc,
--- a/src/paint.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/paint.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include "mb_graph_engine.h" @@ -15,7 +17,7 @@ int _paint_color_size = sizeof(paint_color_t); -static void paint_color_prepare(paint_t *paint, mbe_t *cr) { +static void paint_color_prepare(paint_t *paint, mbe_t *cr, shape_t *sh) { paint_color_t *color = (paint_color_t *)paint; mbe_set_source_rgba(cr, color->r, color->g, color->b, color->a); @@ -80,19 +82,29 @@ #define LIF_DIRTY 0x1 -static void paint_linear_prepare(paint_t *paint, mbe_t *cr) { +int _paint_linear_size = sizeof(paint_linear_t); + +static void paint_linear_prepare(paint_t *paint, mbe_t *cr, shape_t *sh) { paint_linear_t *linear = (paint_linear_t *)paint; mbe_pattern_t *ptn; - grad_stop_t *stop; - int i; + co_aix x1, y1; + co_aix x2, y2; + co_aix *mtx; ptn = linear->ptn; if(linear->flags & LIF_DIRTY) { + mtx = sh_get_aggr_matrix(sh); + x1 = linear->x1; + y1 = linear->y1; + matrix_trans_pos(mtx, &x1, &y1); + x2 = linear->x2; + y2 = linear->y2; + matrix_trans_pos(mtx, &x2, &y2); + if(ptn) mbe_pattern_destroy(ptn); linear->flags &= ~LIF_DIRTY; - ptn = mbe_pattern_create_linear(linear->x1, linear->y1, - linear->x2, linear->y2, + ptn = mbe_pattern_create_linear(x1, y1, x2, y2, linear->stops, linear->n_stops); ASSERT(ptn != NULL); linear->ptn = ptn; @@ -107,7 +119,7 @@ if(linear->ptn) mbe_pattern_destroy(linear->ptn); paint_destroy(paint); - free(paint); + elmpool_elm_free(rdman->paint_linear_pool, linear); } paint_t *rdman_paint_linear_new(redraw_man_t *rdman, @@ -115,7 +127,7 @@ co_aix x2, co_aix y2) { paint_linear_t *linear; - linear = (paint_linear_t *)malloc(sizeof(paint_linear_t)); + linear = (paint_linear_t *)elmpool_elm_alloc(rdman->paint_linear_pool); if(linear == NULL) return NULL; @@ -145,7 +157,7 @@ grad_stop_t *stops) { paint_linear_t *linear = (paint_linear_t *)paint; grad_stop_t *old_stops; - + old_stops = linear->stops; linear->n_stops = n_stops; linear->stops = stops; @@ -170,14 +182,22 @@ #define RDF_DIRTY 0x1 -static void paint_radial_prepare(paint_t *paint, mbe_t *cr) { +int _paint_radial_size = sizeof(paint_radial_t); + +static void paint_radial_prepare(paint_t *paint, mbe_t *cr, shape_t *sh) { paint_radial_t *radial = (paint_radial_t *)paint; mbe_pattern_t *ptn; - int i; + co_aix cx, cy; + co_aix *mtx; if(radial->flags & RDF_DIRTY) { - ptn = mbe_pattern_create_radial(radial->cx, radial->cy, 0, - radial->cx, radial->cy, + mtx = sh_get_aggr_matrix(sh); + cx = radial->cx; + cy = radial->cy; + matrix_trans_pos(mtx, &cx, &cy); + + ptn = mbe_pattern_create_radial(cx, cy, 0, + cx, cy, radial->r, radial->stops, radial->n_stops); @@ -194,14 +214,14 @@ if(radial->ptn) mbe_pattern_destroy(radial->ptn); paint_destroy(paint); - free(paint); + elmpool_elm_free(rdman->paint_radial_pool, radial); } paint_t *rdman_paint_radial_new(redraw_man_t *rdman, co_aix cx, co_aix cy, co_aix r) { paint_radial_t *radial; - radial = O_ALLOC(paint_radial_t); + radial = elmpool_elm_alloc(rdman->paint_radial_pool); if(radial == NULL) return NULL; @@ -229,7 +249,7 @@ grad_stop_t *stops) { paint_radial_t *radial = (paint_radial_t *)paint; grad_stop_t *old_stops; - + old_stops = radial->stops; radial->n_stops = n_stops; radial->stops = stops; @@ -246,11 +266,14 @@ typedef struct _paint_image { paint_t paint; mb_img_data_t *img; + mbe_surface_t *surf; mbe_pattern_t *ptn; } paint_image_t; +int _paint_image_size = sizeof(paint_image_t); + static -void paint_image_prepare(paint_t *paint, mbe_t *cr) { +void paint_image_prepare(paint_t *paint, mbe_t *cr, shape_t *sh) { paint_image_t *paint_img = (paint_image_t *)paint; mb_img_data_t *img_data; @@ -262,11 +285,12 @@ void paint_image_free(redraw_man_t *rdman, paint_t *paint) { 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); - free(paint); + elmpool_elm_free(rdman->paint_image_pool, paint_img); } /*! \brief Create an image painter. @@ -280,18 +304,29 @@ mb_img_data_t *img) { paint_image_t *paint; - paint = O_ALLOC(paint_image_t); + paint = elmpool_elm_alloc(rdman->paint_image_pool); if(paint == NULL) return NULL; - + paint_init(&paint->paint, MBP_IMAGE, paint_image_prepare, paint_image_free); paint->img = img; - - paint->ptn = mbe_pattern_create_image(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); if(paint->ptn == NULL) { paint_destroy(&paint->paint); - free(paint); + mbe_surface_destroy(paint->surf); + elmpool_elm_free(rdman->paint_image_pool, paint); return NULL; } @@ -306,13 +341,13 @@ */ void paint_image_set_matrix(paint_t *paint, co_aix matrix[6]) { paint_image_t *img_paint = (paint_image_t *)paint; - + mbe_pattern_set_matrix(img_paint->ptn, matrix); } void paint_image_get_size(paint_t *paint, int *w, int *h) { paint_image_t *ipaint = (paint_image_t *)paint; - + ASSERT(paint->pnt_type == MBP_IMAGE); *w = ipaint->img->w; *h = ipaint->img->h;
--- a/src/prop.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/prop.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include "mb_prop.h" #define ASSERT(x) @@ -13,7 +15,7 @@ if(entry->id == id) return entry; } - + return NULL; } @@ -79,6 +81,6 @@ entry = _mb_prop_find(prop_store, id); if(entry) return 1; - + return 0; }
--- a/src/redraw_man.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/redraw_man.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -158,7 +160,7 @@ * - areas of descendants of cached coord are in space defined * by aggr_matrix of cached coord. * - descendants are marked with \ref COF_ANCESTOR_CACHE - * + * * Since *_transform of shapes compute area with aggr_matrix that is * derived from aggr_matrix of a cached ancestor, area of * \ref COF_ANCESTOR_CACHE ones should be transformed to device space in @@ -237,7 +239,7 @@ * process of adjusting left-top of bounding box is zeroing. * * Following is rules. - * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix + * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix * of the cached coord and descendnats. * - Clean coords works just like before without change. * - in preorder @@ -302,6 +304,38 @@ #define ASSERT(x) #endif +/* + * Conitions for coords. + */ +#define coord_is_cached(co) ((co)->flags & COF_OWN_CANVAS) +#define coord_is_always_cached(co) ((co)->flags & COF_ALWAYS_CACHE) +#define coord_is_fast_cached(co) ((co)->flags & COF_FAST_MASK) +#define coord_is_precise_cached(co) ((co)->flags & COF_PRECISE_MASK) +#define coord_is_zeroing(co) ((co)->flags & COF_MUST_ZEROING) +#define coord_set_zeroing(co) \ + do { (co)->flags |= COF_MUST_ZEROING; } while(0) +#define coord_clear_zeroing(co) \ + do { (co)->flags &= ~COF_MUST_ZEROING; } while(0) +#define coord_set_flags(co, _flags) \ + do { (co)->flags |= (_flags); } while(0) +#define coord_get_parent(co) ((co)->parent) +#define coord_get_flags(co, _flags) ((co)->flags & (_flags)) +#define coord_clear_flags(co, _flags) \ + do { (co)->flags &= ~(_flags); } while(0) + +#define coord_get_pcache_area(coord) ((coord)->canvas_info->pcache_cur_area) +#define coord_get_pcache_last_area(coord) \ + ((coord)->canvas_info->pcache_last_area) +#define coord_get_cached(coord) ((coord)->canvas_info->owner) +#define _coord_get_dirty_areas(coord) (&(coord)->canvas_info->dirty_areas) +#define _coord_get_aggr_dirty_areas(coord) \ + ((coord)->canvas_info->aggr_dirty_areas) +#define coord_get_2pdev(coord) ((coord)->canvas_info->cache_2_pdev) +#define coord_get_2pdev_rev(coord) ((coord)->canvas_info->cache_2_pdev_rev) +#define coord_get_aggr2pdev(coord) ((coord)->canvas_info->aggr_2_pdev) +#define coord_get_aggr2pdev_rev(coord) ((coord)->canvas_info->aggr_2_pdev_rev) + + /* NOTE: bounding box should also consider width of stroke. */ @@ -336,12 +370,14 @@ extern void sh_dummy_fill(shape_t *, mbe_t *); #endif /* UNITTEST */ -static subject_t *ob_subject_alloc(ob_factory_t *factory); -static void ob_subject_free(ob_factory_t *factory, subject_t *subject); -static observer_t *ob_observer_alloc(ob_factory_t *factory); -static void ob_observer_free(ob_factory_t *factory, observer_t *observer); -static subject_t *ob_get_parent_subject(ob_factory_t *factory, - subject_t *cur_subject); +static subject_t *observer_subject_alloc(observer_factory_t *factory); +static void observer_subject_free(observer_factory_t *factory, + subject_t *subject); +static observer_t *observer_observer_alloc(observer_factory_t *factory); +static void observer_observer_free(observer_factory_t *factory, + observer_t *observer); +static subject_t *observer_get_parent_subject(observer_factory_t *factory, + subject_t *cur_subject); /* Functions for children. */ #define FORCHILDREN(coord, child) \ for((child) = STAILQ_HEAD((coord)->children); \ @@ -456,10 +492,10 @@ static int add_dirty_area(redraw_man_t *rdman, coord_t *coord, area_t *area) { int r; - + if(area->w < 0.01 || area->h < 0.01) return OK; - + rdman->n_dirty_areas++; r = areas_add(_coord_get_dirty_areas(coord), area); return r == 0? OK: ERR; @@ -472,8 +508,10 @@ } static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) { - coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); - ADD_DATA(coords, dirty_pcache_area_coords, coord); + if(!coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) { + coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); + ADD_DATA(coords, zeroing_coords, coord); + } return OK; } @@ -515,26 +553,41 @@ free(rdman->free_objs.objs); } - +#ifdef UNITTEST +/*! \brief This is only used for unittest. + */ +typedef struct { + co_aix parent_2_cache[6]; + int w, h; +} mock_mbe_t; +#endif static mbe_t *canvas_new(int w, int h) { #ifndef UNITTEST mbe_surface_t *surface; mbe_t *cr; - + surface = mbe_image_surface_create(MB_IFMT_ARGB32, w, h); cr = mbe_create(surface); return cr; #else - return NULL; + mock_mbe_t *mbe; + + mbe = malloc(sizeof(mock_mbe_t)); + mbe->w = w; + mbe->h = h; + + return (mbe_t *)mbe; #endif } static void canvas_free(mbe_t *canvas) { #ifndef UNITTEST mbe_destroy(canvas); +#else + free(canvas); #endif } @@ -546,8 +599,11 @@ *w = mbe_image_surface_get_width(surface); *h = mbe_image_surface_get_height(surface); #else - *w = 0; - *h = 0; + mock_mbe_t *mbe; + + mbe = (mock_mbe_t *)canvas; + *w = mbe->w; + *h = mbe->h; #endif } @@ -584,22 +640,29 @@ coord->num_members--; } -static coord_canvas_info_t *coord_canvas_info_new(redraw_man_t *rdman, - coord_t *coord, - mbe_t *canvas) { +/*! \brief Create a new canvas and respective info struct for a coord. + */ +static coord_canvas_info_t * +coord_canvas_info_new(redraw_man_t *rdman, coord_t *coord, + mbe_t *canvas) { coord_canvas_info_t *info; + static co_aix id[6] = {1, 0, 0, 0, 1, 0}; info = (coord_canvas_info_t *)elmpool_elm_alloc(rdman->coord_canvas_pool); if(info == NULL) return info; - + info->owner = coord; info->canvas = canvas; DARRAY_INIT(&info->dirty_areas); - + bzero(info->pcache_areas, sizeof(area_t) * 2); info->pcache_cur_area = &info->pcache_areas[0]; info->pcache_last_area = &info->pcache_areas[1]; + memcpy(info->cache_2_pdev, id, sizeof(co_aix) * 6); + memcpy(info->cache_2_pdev_rev, id, sizeof(co_aix) * 6); + memcpy(info->aggr_2_pdev, id, sizeof(co_aix) * 6); + memcpy(info->aggr_2_pdev_rev, id, sizeof(co_aix) * 6); return info; } @@ -615,24 +678,33 @@ int redraw_man_init(redraw_man_t *rdman, mbe_t *cr, mbe_t *backend) { extern void redraw_man_destroy(redraw_man_t *rdman); + extern int _sh_path_size; + extern int _sh_rect_size; extern int _paint_color_size; + extern int _paint_linear_size; + extern int _paint_radial_size; + extern int _paint_image_size; observer_t *addrm_ob; extern void addrm_monitor_hdlr(event_t *evt, void *arg); memset(rdman, 0, sizeof(redraw_man_t)); DARRAY_INIT(&rdman->dirty_coords); - DARRAY_INIT(&rdman->dirty_pcache_area_coords); DARRAY_INIT(&rdman->dirty_geos); DARRAY_INIT(&rdman->gen_geos); DARRAY_INIT(&rdman->zeroing_coords); - + rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); + rdman->sh_path_pool = elmpool_new(_sh_path_size, 16); + rdman->sh_rect_pool = elmpool_new(_sh_rect_size, 16); rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); + rdman->paint_linear_pool = elmpool_new(_paint_linear_size, 64); + rdman->paint_radial_pool = elmpool_new(_paint_radial_size, 64); + rdman->paint_image_pool = elmpool_new(_paint_image_size, 64); rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); rdman->coord_canvas_pool = elmpool_new(sizeof(coord_canvas_info_t), 16); if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && @@ -640,16 +712,16 @@ rdman->paint_color_pool && rdman->coord_canvas_pool)) goto err; - rdman->ob_factory.subject_alloc = ob_subject_alloc; - rdman->ob_factory.subject_free = ob_subject_free; - rdman->ob_factory.observer_alloc = ob_observer_alloc; - rdman->ob_factory.observer_free = ob_observer_free; - rdman->ob_factory.get_parent_subject = ob_get_parent_subject; + rdman->observer_factory.subject_alloc = observer_subject_alloc; + rdman->observer_factory.subject_free = observer_subject_free; + rdman->observer_factory.observer_alloc = observer_observer_alloc; + rdman->observer_factory.observer_free = observer_observer_free; + rdman->observer_factory.get_parent_subject = observer_get_parent_subject; rdman->redraw = - subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); + subject_new(&rdman->observer_factory, rdman, OBJT_RDMAN); rdman->addrm_monitor = - subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); + subject_new(&rdman->observer_factory, rdman, OBJT_RDMAN); if(!(rdman->redraw && rdman->addrm_monitor)) goto err; @@ -666,7 +738,7 @@ rdman->n_coords = 1; coord_init(rdman->root_coord, NULL); mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool); - rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, + rdman->root_coord->mouse_event = subject_new(&rdman->observer_factory, rdman->root_coord, OBJT_COORD); coord_set_flags(rdman->root_coord, COF_OWN_CANVAS); @@ -678,7 +750,7 @@ rdman->backend = backend; STAILQ_INIT(rdman->shapes); - + /* \note To make root coord always have at leat one observer. * It triggers mouse interpreter to be installed on root. */ @@ -697,18 +769,27 @@ elmpool_free(rdman->coord_pool); if(rdman->shnode_pool) elmpool_free(rdman->shnode_pool); + if(rdman->sh_path_pool) + elmpool_free(rdman->sh_path_pool); + if(rdman->sh_rect_pool) + elmpool_free(rdman->sh_rect_pool); if(rdman->observer_pool) elmpool_free(rdman->observer_pool); if(rdman->subject_pool) elmpool_free(rdman->subject_pool); if(rdman->paint_color_pool) elmpool_free(rdman->paint_color_pool); + if(rdman->paint_linear_pool) + elmpool_free(rdman->paint_linear_pool); + if(rdman->paint_radial_pool) + elmpool_free(rdman->paint_radial_pool); + if(rdman->paint_image_pool) + elmpool_free(rdman->paint_image_pool); if(rdman->pent_pool) elmpool_free(rdman->pent_pool); if(rdman->coord_canvas_pool) elmpool_free(rdman->coord_canvas_pool); DARRAY_DESTROY(&rdman->dirty_coords); - DARRAY_DESTROY(&rdman->dirty_pcache_area_coords); DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->gen_geos); DARRAY_DESTROY(&rdman->zeroing_coords); @@ -717,7 +798,7 @@ void redraw_man_destroy(redraw_man_t *rdman) { coord_t *coord, *saved_coord; - shape_t *shape, *saved_shape; + shape_t *shape; geo_t *member; mb_prop_store_destroy(&rdman->props); @@ -729,7 +810,6 @@ * successfully. */ DARRAY_CLEAN(&rdman->dirty_coords); - DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); DARRAY_CLEAN(&rdman->dirty_geos); coord = postorder_coord_subtree(rdman->root_coord, NULL); @@ -748,24 +828,28 @@ while((shape = STAILQ_HEAD(rdman->shapes)) != NULL) { rdman_shape_free(rdman, shape); } - + coord_canvas_info_free(rdman, rdman->root_coord->canvas_info); /* XXX: paints are not freed, here. All resources of paints would * be reclaimed by freeing elmpools. */ - + elmpool_free(rdman->coord_pool); elmpool_free(rdman->geo_pool); elmpool_free(rdman->shnode_pool); + elmpool_free(rdman->sh_path_pool); + elmpool_free(rdman->sh_rect_pool); elmpool_free(rdman->observer_pool); elmpool_free(rdman->subject_pool); elmpool_free(rdman->paint_color_pool); + elmpool_free(rdman->paint_linear_pool); + elmpool_free(rdman->paint_radial_pool); + elmpool_free(rdman->paint_image_pool); elmpool_free(rdman->pent_pool); elmpool_free(rdman->coord_canvas_pool); DARRAY_DESTROY(&rdman->dirty_coords); - DARRAY_DESTROY(&rdman->dirty_pcache_area_coords); DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->gen_geos); DARRAY_DESTROY(&rdman->zeroing_coords); @@ -802,9 +886,9 @@ geo = elmpool_elm_alloc(rdman->geo_pool); if(geo == NULL) return ERR; - + geo_init(geo); - geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); + geo->mouse_event = subject_new(&rdman->observer_factory, geo, OBJT_GEO); subject_set_monitor(geo->mouse_event, rdman->addrm_monitor); geo_attach_coord(geo, coord); @@ -854,7 +938,7 @@ rdman_paint_stroke(rdman, (paint_t *)NULL, shape); if(shape->fill != NULL) rdman_paint_fill(rdman, (paint_t *)NULL, shape); - + if(geo != NULL) { subject_free(geo->mouse_event); geo_detach_coord(geo, shape->coord); @@ -869,7 +953,7 @@ if(rdman->last_mouse_over == (mb_obj_t *)shape) rdman->last_mouse_over = NULL; - + return OK; } @@ -889,7 +973,7 @@ shape_t *shape; if(rdman_is_dirty(rdman)) { - if(!(paint->flags & PNTF_FREE)) + if(paint->flags & PNTF_FREE) return ERR; add_free_obj(rdman, paint, (free_func_t)rdman_paint_free); paint->flags |= PNTF_FREE; @@ -901,26 +985,26 @@ FORPAINTMEMBERS(paint, shnode) { if(saved_shnode) { RM_PAINTMEMBER(paint, saved_shnode); - + shape = saved_shnode->shape; if(shape->stroke == paint) rdman_paint_stroke(rdman, (paint_t *)NULL, shape); if(shape->fill == paint) rdman_paint_fill(rdman, (paint_t *)NULL, shape); - + shnode_free(rdman, saved_shnode); } saved_shnode = shnode; } if(saved_shnode) { RM_PAINTMEMBER(paint, saved_shnode); - + shape = saved_shnode->shape; if(shape->stroke == paint) rdman_paint_stroke(rdman, (paint_t *)NULL, shape); if(shape->fill == paint) rdman_paint_fill(rdman, (paint_t *)NULL, shape); - + shnode_free(rdman, saved_shnode); } @@ -952,7 +1036,7 @@ coord_init(coord, parent); mb_prop_store_init(&coord->obj.props, rdman->pent_pool); - coord->mouse_event = subject_new(&rdman->ob_factory, + coord->mouse_event = subject_new(&rdman->observer_factory, coord, OBJT_COORD); subject_set_monitor(coord->mouse_event, rdman->addrm_monitor); @@ -988,7 +1072,7 @@ if(coord->flags & COF_FREE) return ERR; - + coord->flags |= COF_FREE; coord_hide(coord); if(!(coord->flags & COF_DIRTY)) { @@ -1033,7 +1117,7 @@ if(!(member->flags & GEF_FREE)) return ERR; } - + if(cm_cnt || rdman_is_dirty(rdman)) return rdman_coord_free_postponse(rdman, coord); @@ -1226,10 +1310,11 @@ } shape->geo->flags &= ~GEF_DIRTY; - if(is_coord_subtree_hidden(shape->coord)) - sh_hide(shape); + if(sh_get_flags(shape, GEF_HIDDEN) || + is_coord_subtree_hidden(shape->coord)) + sh_set_flags(shape, GEF_NOT_SHOWED); else - sh_show(shape); + sh_clear_flags(shape, GEF_NOT_SHOWED); } /*! \brief Setup canvas_info for the coord. @@ -1242,7 +1327,7 @@ if(coord->parent == NULL) return; - if(coord->opacity != 1 || coord_is_cached(coord)) { + if(coord->opacity != 1 || coord_is_always_cached(coord)) { if(!coord_is_cached(coord)) { /* canvas is assigned latter, in zeroing_coord() */ coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); @@ -1264,8 +1349,8 @@ /* \brief Compute matrix from cached canvas to parent device space. */ -static void compute_cached_2_pdev_matrix(coord_t *coord, - co_aix canvas2pdev_matrix[6]) { +static void compute_cached_2_pdev_matrix(coord_t *coord) { + co_aix *canvas2pdev_matrix = coord_get_2pdev(coord); coord_t *parent; co_aix *aggr; co_aix *matrix, *paggr; @@ -1277,9 +1362,9 @@ matrix = coord->matrix; parent = coord->parent; paggr = coord_get_aggr_matrix(parent); - + scale_x = matrix[0] / aggr[0]; - scale_y = matrix[3] / aggr[3]; + scale_y = matrix[4] / aggr[4]; shift_x = matrix[2] - scale_x * aggr[2]; shift_y = matrix[5] - scale_y * aggr[5]; @@ -1291,6 +1376,8 @@ canvas2p[5] = shift_y; matrix_mul(paggr, canvas2p, canvas2pdev_matrix); + + compute_reverse(canvas2pdev_matrix, coord_get_2pdev_rev(coord)); } /*! \brief Compute area in parent cached coord for a cached coord. @@ -1303,22 +1390,21 @@ * ancestral cached coord can be retreived by shifting and resizing * canvas box in reverse and transform to coordination system of * ancestral cached coord. - */ + */ static void compute_pcache_area(coord_t *coord) { - co_aix cached2pdev[6]; + co_aix *cached2pdev = coord_get_2pdev(coord); int c_w, c_h; canvas_t *canvas; coord_canvas_info_t *canvas_info; co_aix poses[4][2]; - + canvas_info = coord->canvas_info; SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area, area_t *); - compute_cached_2_pdev_matrix(coord, cached2pdev); - + canvas = _coord_get_canvas(coord); canvas_get_size(canvas, &c_w, &c_h); - + poses[0][0] = 0; poses[0][1] = 0; poses[1][0] = c_w; @@ -1331,28 +1417,29 @@ matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); - + area_init(coord_get_pcache_area(coord), 4, poses); - coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); + coord_clear_flags(coord, COF_DIRTY_PCACHE_AREA); } /*! \brief Compute area of a coord. */ static int compute_area(coord_t *coord) { - static co_aix (*poses)[2]; + static co_aix (*poses)[2] = NULL; static int max_poses = 0; geo_t *geo; int cnt, pos_cnt; - + cnt = 0; FORMEMBERS(coord, geo) { cnt++; } - + if(max_poses < (cnt * 2)) { - free(poses); + if(poses) + free(poses); max_poses = cnt * 2; poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses); if(poses == NULL) @@ -1374,7 +1461,7 @@ geo_t *geo; int r; /*! \note poses is shared by invokings, it is not support reentrying. */ - + /* Clean member shapes. */ FORMEMBERS(coord, geo) { clean_shape(geo->shape); @@ -1396,9 +1483,8 @@ * \note coords their opacity != 1 are also traded as cached ones. */ static int clean_coord(redraw_man_t *rdman, coord_t *coord) { - coord_t *child; int r; - + setup_canvas_info(rdman, coord); compute_aggr(coord); @@ -1412,17 +1498,14 @@ if(r != OK) return ERR; + /* Dirty areas of cached one is added after update pcache_areas. + */ add_dirty_area(rdman, coord, coord->cur_area); add_dirty_area(rdman, coord, coord->last_area); - + coord_clear_flags(coord, COF_DIRTY); coord_set_flags(coord, COF_JUST_CLEAN); - - FORCHILDREN(coord, child) { - if(coord_is_cached(child)) - add_dirty_pcache_area_coord(rdman, child); - } - + return OK; } @@ -1434,7 +1517,7 @@ * coord, coord_canvas_info_t::pcache_cur_area, for its cached children. */ static int clean_rdman_coords(redraw_man_t *rdman) { - coord_t *coord, *child; + coord_t *coord; coord_t **dirty_coords; int n_dirty_coords; int i, r; @@ -1476,7 +1559,7 @@ add_dirty_area(rdman, coord, visit_geo->cur_area); add_dirty_area(rdman, coord, visit_geo->last_area); } - } + } return OK; } @@ -1489,7 +1572,7 @@ static void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { coord_t *cur; - area_t *area, *saved_area; + area_t *area; geo_t *geo; co_aix min_x, min_y; co_aix max_x, max_y; @@ -1498,7 +1581,6 @@ int c_w, c_h; mbe_t *canvas; co_aix *aggr; - co_aix poses[4][2]; if(coord->parent == NULL) /*! \note Should not zeroing root coord */ abort(); @@ -1519,26 +1601,44 @@ for(cur = preorder_coord_subtree(coord, coord); cur != NULL; cur = preorder_coord_subtree(coord, cur)) { - area = coord_get_area(cur); + if(coord_is_cached(cur)) { + preorder_coord_skip_subtree(cur); + /* This means pcache_area of descendants must be computed + * before zeroing ancestor cached one. + * (See add_rdman_zeroing_n_pcache_coords()) + */ + area = coord_get_pcache_area(cur); + } else + area = coord_get_area(cur); + + if(area->w == 0 && area->h == 0) + continue; + + if(min_x == max_x && min_y == max_y) { + min_x = area->x; + max_x = area->x + area->w; + min_y = area->y; + max_y = area->y + area->h; + continue; + } + if(area->x < min_x) min_x = area->x; if(area->y < min_y) min_y = area->y; - + x = area->x + area->w; y = area->y + area->h; - + if(x > max_x) max_x = x; if(y > max_y) max_y = y; - if(coord_is_cached(cur)) - preorder_coord_skip_subtree(cur); } w = max_x - min_x; h = max_y - min_y; - + canvas = _coord_get_canvas(coord); if(canvas) canvas_get_size(canvas, &c_w, &c_h); @@ -1560,7 +1660,7 @@ coord_set_flags(coord, COF_SKIP_ZERO); return; } - + /* * Adjust matrics of descendants to align left-top corner of * minimum covering area with origin of space defined by @@ -1577,9 +1677,9 @@ } /* Shift space */ aggr = coord_get_aggr_matrix(cur); - aggr[3] -= min_x; + aggr[2] -= min_x; aggr[5] -= min_y; - + FOR_COORD_MEMBERS(coord, geo) { /* \see GEO_SWAP() */ if(!geo_get_flags(geo, GEF_SWAP)) @@ -1587,7 +1687,7 @@ } coord_clean_members_n_compute_area(cur); } - + /* * Setup canvas * @@ -1604,16 +1704,29 @@ coord_set_flags(coord, COF_JUST_ZERO); } -/*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. +/*! \brief Add coords that need to perform zeroing or re-compute pcache_area. + * + * A coord that need to perform zeroing has one or more dirty members + * in its descendants. * - * All possible coords that need a zeroing have at least one dirty geo. + * To zeroing a coord, pcache_area of first level cached descendants + * must be updated. To update the pcache_area of a cached coord, the + * cached coord also need to perform zeroing. So, zeroing and + * re-computing pcache_area are interleaved. + * + * The pcache_area of a cached coord must be re-computed if its + * parent/ancestors is dirty/just cleaned, or it must be zeroed. It + * means cached coord with jsut cleaned parent should also re-compute + * pcache_area. So, this function also check and add coords for this + * situation. */ -static int add_rdman_zeroing_coords(redraw_man_t *rdman) { +static int add_rdman_zeroing_n_pcache_coords(redraw_man_t *rdman) { int i; int n_dirty_geos; geo_t **dirty_geos, *geo; int n_dirty_coords; coord_t **dirty_coords, *coord; + coord_t *parent_coord; /* Mark all cached ancestral coords of dirty geos */ n_dirty_geos = rdman->dirty_geos.num; @@ -1628,7 +1741,7 @@ coord = coord_get_cached(coord_get_parent(coord)); } } - + /* Mark all cached ancestral coords of dirty coords */ n_dirty_coords = rdman->dirty_coords.num; dirty_coords = rdman->dirty_coords.ds; @@ -1641,23 +1754,28 @@ coord = coord_get_cached(coord_get_parent(coord)); } } - + /* Add all marked coords into redraw_man_t::zeroing_coords list */ FOR_COORDS_PREORDER(rdman->root_coord, coord) { - if(!coord_is_cached(coord)) + if(!coord_is_cached(coord) || coord_is_root(coord)) continue; /* skip coords that is not cached */ - + if(!coord_get_flags(coord, COF_TEMP_MARK)) { - if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) + parent_coord = coord_get_parent(coord); + /* The pcache_area of a cached coord that is a child of a + * just cleaned one must be recomputed. + */ + if(coord_get_flags(parent_coord, COF_JUST_CLEAN)) add_dirty_pcache_area_coord(rdman, coord); + preorder_coord_skip_subtree(coord); continue; } add_zeroing_coord(rdman, coord); - + coord_clear_flags(coord, COF_TEMP_MARK); } - + return OK; } @@ -1671,7 +1789,7 @@ int i; coords_t *all_zeroing; coord_t *coord; - + all_zeroing = &rdman->zeroing_coords; /*! Zeroing is performed from leaves to root. * @@ -1686,34 +1804,43 @@ */ for(i = all_zeroing->num - 1; i >= 0; i--) { coord = all_zeroing->ds[i]; - zeroing_coord(rdman, coord); + if(coord_is_zeroing(coord)) + zeroing_coord(rdman, coord); + compute_cached_2_pdev_matrix(coord); + /* This is required by ancester cached ones to perform + * zeroing. + */ compute_pcache_area(coord); } - + return OK; } -/*! \brief Compute pcache_area for coords whoes pcache_area is dirty. +/*! \brief Update aggregated cache_2_pdev matrix for cached coords. * - * coord_t::dirty_pcache_area_coords also includes part of coords in - * coord_t::zeroing_coords. The pcache_area of coords that is in - * coord_t::dirty_pcache_area_coords, but is not in - * coord_t::zeroing_coords should be computed here. - * zeroing_rdman_coords() is responsible for computing pcache_area for - * zeroing ones. + * This is perfromed from root to leaves. Aggregated cache_2_pdev is + * named as aggr_2_pdev field of canvas_info_t. It is the matrix to + * transform a point from space of a cached coord to the space of root + * coord. */ static int -compute_rdman_coords_pcache_area(redraw_man_t *rdman) { - coords_t *all_coords; - coord_t *coord; +update_aggr_pdev(redraw_man_t *rdman) { int i; - - all_coords = &rdman->dirty_pcache_area_coords; - for(i = 0; i < all_coords->num; i++) { - coord = all_coords->ds[i]; - if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) - compute_pcache_area(coord); + coords_t *all_zeroing; + coord_t *coord, *parent_cached; + + all_zeroing = &rdman->zeroing_coords; + for(i = 0; i < all_zeroing->num; i++) { + coord = all_zeroing->ds[i]; + parent_cached = coord_get_cached(coord_get_parent(coord)); + matrix_mul(coord_get_2pdev(parent_cached), + coord_get_2pdev(coord), + coord_get_aggr2pdev(coord)); + matrix_mul(coord_get_2pdev_rev(coord), + coord_get_2pdev_rev(parent_cached), + coord_get_aggr2pdev_rev(coord)); } + return OK; } @@ -1727,19 +1854,31 @@ coord_t *coord) { int i; int n_areas; - int enable_poses1 = 0; co_aix poses0[2][2], poses1[2][2]; - co_aix reverse[6]; - co_aix canvas2pdev_matrix[6]; + co_aix *canvas2pdev_matrix; area_t **areas, *area; area_t *area0, *area1; coord_t *parent, *pcached_coord; n_areas = _coord_get_dirty_areas(coord)->num; areas = _coord_get_dirty_areas(coord)->ds; - if(n_areas == 0) - abort(); /* should not happen! */ - + if(n_areas == 0) { + /* Go here for cached one that is descendant of another zeroed + * one, but itself is not zeroed. It is here for recomputing + * pcache areas. + */ + if(coord_get_flags(coord, COF_JUST_CLEAN | COF_JUST_ZERO)) + abort(); /* should not happen! */ + + parent = coord_get_parent(coord); + pcached_coord = coord_get_cached(parent); + area = coord_get_pcache_area(coord); + add_dirty_area(rdman, pcached_coord, area); + area = coord_get_pcache_last_area(coord); + add_dirty_area(rdman, pcached_coord, area); + return; + } + area0 = _coord_get_aggr_dirty_areas(coord); area1 = area0 + 1; @@ -1755,13 +1894,13 @@ if(i >= n_areas) return; - + area = areas[i++]; poses0[0][0] = area->x; poses0[0][1] = area->y; poses0[1][0] = area->x + area->w; poses0[1][1] = area->y + area->h; - + if(i < n_areas) { area = areas[i++]; poses1[0][0] = area->x; @@ -1774,7 +1913,7 @@ poses1[1][0] = 0; poses1[1][1] = 0; } - + for(; i < n_areas - 1;) { /* Even areas */ area = areas[i++]; @@ -1793,7 +1932,7 @@ poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h); } } - + if(i < n_areas) { area = areas[i]; if(area->w != 0 || area->h != 0) { @@ -1803,18 +1942,18 @@ poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h); } } - + parent = coord_get_parent(coord); pcached_coord = coord_get_cached(parent); - - compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); + + canvas2pdev_matrix = coord_get_2pdev(coord); /* Add dirty areas to parent cached coord. */ matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1); matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1); area_init(area0, 2, poses0); add_dirty_area(rdman, pcached_coord, area0); - + matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1); matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1); area_init(area1, 2, poses1); @@ -1840,29 +1979,18 @@ */ static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { int i; - int n_zeroing; - coord_t **zeroings; - coord_t *coord, *pcached_coord; - int n_dpca_coords; /* number of dirty pcache area coords */ - coord_t **dpca_coords; /* dirty pcache area coords */ - - /* Add aggregated areas to parent cached one for coords in zeroing - * list - */ - n_zeroing = rdman->zeroing_coords.num; - zeroings = rdman->zeroing_coords.ds; - for(i = 0; i < n_zeroing; i++) { - if(coord_get_flags(coord, COF_TEMP_MARK)) - continue; - coord_set_flags(coord, COF_TEMP_MARK); - - coord = zeroings[i]; - pcached_coord = coord_get_cached(coord_get_parent(coord)); - - if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) - continue; - + coord_t *coord, *parent_coord, *pcached_coord; + int n_zeroing_coords; /* number of dirty pcache area coords */ + coord_t **zeroing_coords; /* dirty pcache area coords */ + + n_zeroing_coords = rdman->zeroing_coords.num; + zeroing_coords = rdman->zeroing_coords.ds; + for(i = n_zeroing_coords - 1; i >= 0; i--) { + coord = zeroing_coords[i]; if(IS_CACHE_REDRAW_ALL(coord)) { + parent_coord = coord_get_parent(coord); + pcached_coord = coord_get_cached(parent_coord); + add_dirty_area(rdman, pcached_coord, coord_get_pcache_area(coord)); add_dirty_area(rdman, pcached_coord, @@ -1871,36 +1999,6 @@ add_aggr_dirty_areas_to_ancestor(rdman, coord); } } - - /* Add pcache_areas to parent cached one for coord that is - * non-zeroing and its parent is changed. - */ - n_dpca_coords = rdman->dirty_pcache_area_coords.num; - dpca_coords = rdman->dirty_pcache_area_coords.ds; - for(i = 0; i < n_dpca_coords; i++) { - if(coord_get_flags(coord, COF_TEMP_MARK)) - continue; - coord_set_flags(coord, COF_TEMP_MARK); - - coord = dpca_coords[i]; - pcached_coord = coord_get_cached(coord_get_parent(coord)); - - if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) - continue; - - add_dirty_area(rdman, pcached_coord, - coord_get_pcache_area(coord)); - add_dirty_area(rdman, pcached_coord, - coord_get_pcache_last_area(coord)); - } - - /* Remove temporary mark */ - for(i = 0; i < n_zeroing; i++) { - coord_clear_flags(zeroings[i], COF_TEMP_MARK); - } - for(i = 0; i < n_dpca_coords; i++) { - coord_clear_flags(dpca_coords[i], COF_TEMP_MARK); - } return OK; } @@ -1981,13 +2079,15 @@ GEO_SWAP(geo); } } - + + /* XXX: some geo may swap two times. Should avoid it. + */ geos = rdman->dirty_geos.ds; for(i = 0; i < rdman->dirty_geos.num; i++) { geo = geos[i]; GEO_SWAP(geo); } - + r = clean_rdman_coords(rdman); if(r != OK) return ERR; @@ -2003,7 +2103,7 @@ /* Zeroing must be performed after clearing to get latest position * of shapes for computing new bounding box */ - r = add_rdman_zeroing_coords(rdman); + r = add_rdman_zeroing_n_pcache_coords(rdman); if(r != OK) return ERR; @@ -2011,11 +2111,11 @@ if(r != OK) return ERR; - r = compute_rdman_coords_pcache_area(rdman); + r = add_rdman_aggr_dirty_areas(rdman); if(r != OK) return ERR; - - r = add_rdman_aggr_dirty_areas(rdman); + + r = update_aggr_pdev(rdman); if(r != OK) return ERR; @@ -2035,17 +2135,13 @@ for(i = 0; i < rdman->zeroing_coords.num; i++) coord_clear_flags(coords[i], COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); - coords = rdman->dirty_pcache_area_coords.ds; - for(i = 0; i < rdman->dirty_pcache_area_coords.num; i++) - coord_clear_flags(coords[i], - COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); /* \see GEO_SWAP() */ for(i = 0; i < rdman->dirty_geos.num; i++) { geo = geos[i]; geo_clear_flags(geo, GEF_SWAP); } - + return OK; } @@ -2059,28 +2155,28 @@ mbe_set_line_width(cr, shape->stroke_width); } -static void fill_path_preserve(redraw_man_t *rdman) { - mbe_fill_preserve(rdman->cr); +static void fill_path_preserve(redraw_man_t *rdman, mbe_t *cr) { + mbe_fill_preserve(cr); } -static void fill_path(redraw_man_t *rdman) { - mbe_fill(rdman->cr); +static void fill_path(redraw_man_t *rdman, mbe_t *cr) { + mbe_fill(cr); } -static void stroke_path(redraw_man_t *rdman) { - mbe_stroke(rdman->cr); +static void stroke_path(redraw_man_t *rdman, mbe_t *cr) { + mbe_stroke(cr); } #else static void set_shape_stroke_param(shape_t *shape, mbe_t *cr) { } -static void fill_path_preserve(redraw_man_t *rdman) { +static void fill_path_preserve(redraw_man_t *rdman, mbe_t *cr) { } -static void fill_path(redraw_man_t *rdman) { +static void fill_path(redraw_man_t *rdman, mbe_t *cr) { } -static void stroke_path(redraw_man_t *rdman) { +static void stroke_path(redraw_man_t *rdman, mbe_t *cr) { } #endif @@ -2120,20 +2216,20 @@ fill = shape->fill; if(shape->fill) { - fill->prepare(fill, cr); + fill->prepare(fill, cr, shape); if(shape->stroke) - fill_path_preserve(rdman); + fill_path_preserve(rdman, cr); else - fill_path(rdman); + fill_path(rdman, cr); } stroke = shape->stroke; if(stroke) { - stroke->prepare(stroke, cr); + stroke->prepare(stroke, cr, shape); set_shape_stroke_param(shape, cr); - stroke_path(rdman); + stroke_path(rdman, cr); } - } + } } #ifndef UNITTEST @@ -2141,22 +2237,36 @@ mbe_clear(canvas); } -#define make_clip(canvas, n_dirty_areas, dirty_areas) \ - mbe_scissoring(canvas, n_dirty_areas, dirty_areas) +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); +} static void reset_clip(canvas_t *cr) { - mbe_reset_scissoring(cr); + mbe_reset_clip(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); - + mbe_copy_source(rdman->cr, rdman->backend); } #else /* UNITTEST */ -#define make_clip(canvas, n_dirty_areas, dirty_areas) +static void make_clip(mbe_t *cr, int n_dirty_areas, + area_t **dirty_areas) { +} static void clear_canvas(canvas_t *canvas) { } @@ -2169,27 +2279,39 @@ } #endif /* UNITTEST */ -static void update_cached_canvas_2_parent(redraw_man_t *rdman, - coord_t *coord) { - mbe_t *pcanvas, *canvas; +static void +_update_cached_canvas_2_parent(redraw_man_t *rdman, co_aix reverse[6], + mbe_t *canvas, mbe_t *pcanvas, + co_aix opacity) { mbe_surface_t *surface; mbe_pattern_t *pattern; - co_aix reverse[6]; - co_aix canvas2pdev_matrix[6]; - - if(coord_is_root(coord)) - return; - - compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); - compute_reverse(canvas2pdev_matrix, reverse); - canvas = _coord_get_canvas(coord); - pcanvas = _coord_get_canvas(coord->parent); surface = mbe_get_target(canvas); pattern = mbe_pattern_create_for_surface(surface); mbe_pattern_set_matrix(pattern, reverse); mbe_set_source(pcanvas, pattern); - mbe_paint_with_alpha(pcanvas, coord->opacity); + mbe_paint_with_alpha(pcanvas, opacity); +} + +static void update_cached_canvas_2_parent(redraw_man_t *rdman, + coord_t *coord) { + mbe_t *pcanvas, *canvas; + co_aix *c2pdev_reverse; + + if(coord_is_root(coord)) + return; + + c2pdev_reverse = coord_get_2pdev_rev(coord); + + canvas = _coord_get_canvas(coord); + pcanvas = _coord_get_canvas(coord->parent); +#ifndef UNITTEST + _update_cached_canvas_2_parent(rdman, c2pdev_reverse, canvas, pcanvas, + coord->opacity); +#else + memcpy(((mock_mbe_t *)canvas)->parent_2_cache, c2pdev_reverse, + sizeof(co_aix) * 6); +#endif } static int draw_coord_shapes_in_dirty_areas(redraw_man_t *rdman, @@ -2205,11 +2327,11 @@ if(coord->flags & COF_HIDDEN) return OK; - + areas = _coord_get_dirty_areas(coord)->ds; n_areas = _coord_get_dirty_areas(coord)->num; canvas = _coord_get_canvas(coord); - + member = FIRST_MEMBER(coord); mem_idx = 0; child = FIRST_CHILD(coord); @@ -2217,7 +2339,8 @@ if(child && child->before_pmem == mem_idx) { if(coord_is_cached(child)) { if(!(child->flags & COF_HIDDEN) && - is_area_in_areas(coord_get_area(child), n_areas, areas)) { + is_area_in_areas(coord_get_pcache_area(child), + n_areas, areas)) { update_cached_canvas_2_parent(rdman, child); dirty = 1; } @@ -2228,7 +2351,7 @@ child = NEXT_CHILD(child); } else { ASSERT(member != NULL); - if((!(member->flags & GEF_HIDDEN)) && + if((!(member->flags & GEF_NOT_SHOWED)) && is_geo_in_areas(member, n_areas, areas)) { draw_shape(rdman, canvas, member->shape); dirty = 1; @@ -2251,9 +2374,9 @@ mbe_surface_t *surface; int i; int r; - + canvas = _coord_get_canvas(coord); - + if(IS_CACHE_REDRAW_ALL(coord)) { /* * full_area covers all dirty areas of the cached coord. @@ -2269,7 +2392,7 @@ areas = _coord_get_dirty_areas(coord)->ds; n_areas = _coord_get_dirty_areas(coord)->num; - + for(i = 0; i < n_areas; i++) { area = areas[i]; area->x = floorf(area->x); @@ -2282,7 +2405,7 @@ clear_canvas(canvas); r = draw_coord_shapes_in_dirty_areas(rdman, coord); - + reset_clip(canvas); return OK; @@ -2306,8 +2429,10 @@ draw_dirty_cached_coord(rdman, coord); coord_set_flags(coord, COF_TEMP_MARK); } - for(i = 0; i < num; i++) + for(i = 0; i < num; i++) { + coord = zeroings[i]; coord_clear_flags(coord, COF_TEMP_MARK); + } draw_dirty_cached_coord(rdman, rdman->root_coord); } @@ -2350,10 +2475,10 @@ event_t event; subject_t *redraw; int i; - coord_t *coord, **coords; + coord_t *coord; int n_areas; area_t **areas; - + r = rdman_clean_dirties(rdman); if(r != OK) return ERR; @@ -2378,8 +2503,7 @@ DARRAY_CLEAN(&rdman->dirty_coords); DARRAY_CLEAN(&rdman->dirty_geos); DARRAY_CLEAN(&rdman->zeroing_coords); - DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); - + /* Free postponsed removing */ free_free_objs(rdman); @@ -2441,7 +2565,7 @@ geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) { geo_t *next; coord_t *coord; - + if(last == NULL) { coord = rdman->root_coord; while(coord != NULL && FIRST_MEMBER(coord) == NULL) @@ -2497,48 +2621,51 @@ * Implment factory and strategy functions for observers and subjects. * @{ */ -static subject_t *ob_subject_alloc(ob_factory_t *factory) { +static subject_t *observer_subject_alloc(observer_factory_t *factory) { redraw_man_t *rdman; subject_t *subject; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); subject = elmpool_elm_alloc(rdman->subject_pool); return subject; } -static void ob_subject_free(ob_factory_t *factory, subject_t *subject) { +static void +observer_subject_free(observer_factory_t *factory, subject_t *subject) { redraw_man_t *rdman; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); elmpool_elm_free(rdman->subject_pool, subject); } -static observer_t *ob_observer_alloc(ob_factory_t *factory) { +static observer_t *observer_observer_alloc(observer_factory_t *factory) { redraw_man_t *rdman; observer_t *observer; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); observer = elmpool_elm_alloc(rdman->observer_pool); return observer; } -static void ob_observer_free(ob_factory_t *factory, observer_t *observer) { +static void +observer_observer_free(observer_factory_t *factory, observer_t *observer) { redraw_man_t *rdman; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); elmpool_elm_free(rdman->observer_pool, observer); } -static subject_t *ob_get_parent_subject(ob_factory_t *factory, - subject_t *cur_subject) { +static subject_t * +observer_get_parent_subject(observer_factory_t *factory, + subject_t *cur_subject) { redraw_man_t *rdman; coord_t *coord, *parent_coord; geo_t *geo; subject_t *parent; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); switch(cur_subject->obj_type) { case OBJT_GEO: geo = (geo_t *)cur_subject->obj; @@ -2570,15 +2697,15 @@ mb_img_data_t *img_data; paint_t *paint; mb_img_ldr_t *ldr = rdman_img_ldr(rdman); - + img_data = MB_IMG_LDR_LOAD(ldr, img_id); if(img_data == NULL) return NULL; - + paint = rdman_paint_image_new(rdman, img_data); if(paint == NULL) MB_IMG_DATA_FREE(img_data); - + return paint; } @@ -2593,6 +2720,7 @@ co_aix w, h; int trans_cnt; int draw_cnt; + mbe_t *last_draw; }; void sh_dummy_free(shape_t *sh) { @@ -2616,8 +2744,8 @@ dummy->trans_cnt = 0; dummy->draw_cnt = 0; dummy->shape.free = sh_dummy_free; - - rdman_shape_man(rdman, (shape_t *)dummy); + + rdman_man_shape(rdman, (shape_t *)dummy); return (shape_t *)dummy; } @@ -2626,7 +2754,7 @@ sh_dummy_t *dummy = (sh_dummy_t *)shape; co_aix poses[2][2]; co_aix x1, y1, x2, y2; - + if(shape->geo && shape->coord) { x1 = dummy->x; y1 = dummy->y; @@ -2639,7 +2767,7 @@ poses[0][1] = y1; poses[1][0] = x2; poses[1][1] = y2; - + if(shape->geo) geo_from_positions(shape->geo, 2, poses); } @@ -2651,6 +2779,7 @@ dummy = (sh_dummy_t *)shape; dummy->draw_cnt++; + dummy->last_draw = cr; } static void dummy_paint_prepare(paint_t *paint, mbe_t *cr) { @@ -2703,7 +2832,7 @@ CU_ASSERT(dummys[0]->draw_cnt == 1); CU_ASSERT(dummys[1]->draw_cnt == 1); CU_ASSERT(dummys[2]->draw_cnt == 1); - + coords[2]->matrix[2] = 100; coords[2]->matrix[5] = 100; rdman_coord_changed(rdman, coords[0]); @@ -2741,12 +2870,168 @@ CU_ASSERT(test_free_pass == 4); } +static void +test_setup_canvas_info(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord->parent == rdman->root_coord); + + coord_set_opacity(coord, 0.9); + setup_canvas_info(rdman, coord); + + CU_ASSERT(coord->canvas_info != rdman->root_coord->canvas_info); + + coord_set_opacity(coord, 1); + setup_canvas_info(rdman, coord); + + CU_ASSERT(coord->canvas_info == rdman->root_coord->canvas_info); +} + +static void +test_own_canvas_area(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord1, *coord2; + sh_dummy_t *sh; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord1 = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord1->parent == rdman->root_coord); + + coord2 = rdman_coord_new(rdman, coord1); + CU_ASSERT(coord2->parent == coord1); + + coord_set_opacity(coord2, 0.9); + rdman_coord_changed(rdman, coord2); + + sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20); + rdman_add_shape(rdman, (shape_t *)sh, coord2); + rdman_shape_changed(rdman, (shape_t *)sh); + + clean_coord(rdman, coord2); + + /* Parent cached coord must be updated */ + CU_ASSERT(geo_get_area(coord2)->x == 100); + CU_ASSERT(geo_get_area(coord2)->y == 100); + CU_ASSERT(geo_get_area(coord2)->w <= 22 && geo_get_area(coord2)->w >= 19); + CU_ASSERT(geo_get_area(coord2)->h <= 22 && geo_get_area(coord2)->h >= 19); + + redraw_man_destroy(rdman); +} + +static void +test_own_canvas(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord1, *coord2; + sh_dummy_t *sh; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord1 = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord1->parent == rdman->root_coord); + + coord2 = rdman_coord_new(rdman, coord1); + CU_ASSERT(coord2->parent == coord1); + + coord_set_opacity(coord2, 0.9); + rdman_coord_changed(rdman, coord2); + + sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20); + rdman_add_shape(rdman, (shape_t *)sh, coord2); + rdman_shape_changed(rdman, (shape_t *)sh); + + rdman_clean_dirties(rdman); + + /* Parent cached coord must be updated */ + CU_ASSERT(_coord_get_dirty_areas(rdman->root_coord)->num == 1); + + CU_ASSERT(geo_get_area(coord2)->x == 0); + CU_ASSERT(geo_get_area(coord2)->y == 0); + CU_ASSERT(geo_get_area(coord2)->w <= 22 && geo_get_area(coord2)->w >= 19); + CU_ASSERT(geo_get_area(coord2)->h <= 22 && geo_get_area(coord2)->h >= 19); + + redraw_man_destroy(rdman); +} + +static void +test_own_canvas_redraw(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord1, *coord2; + sh_dummy_t *sh; + paint_t *paint; + co_aix *parent_2_cache; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord1 = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord1->parent == rdman->root_coord); + + coord2 = rdman_coord_new(rdman, coord1); + CU_ASSERT(coord2->parent == coord1); + + coord_set_opacity(coord2, 0.9); + rdman_coord_changed(rdman, coord2); + + sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20); + rdman_add_shape(rdman, (shape_t *)sh, coord2); + rdman_shape_changed(rdman, (shape_t *)sh); + + paint = dummy_paint_new(rdman); + rdman_paint_fill(rdman, paint, (shape_t *)sh); + + rdman_redraw_all(rdman); + + CU_ASSERT(sh->draw_cnt == 1); + CU_ASSERT(sh->last_draw == _coord_get_canvas(coord2)); + + parent_2_cache = ((mock_mbe_t *)_coord_get_canvas(coord2))->parent_2_cache; + CU_ASSERT(parent_2_cache[0] == 1); + CU_ASSERT(parent_2_cache[1] == 0); + CU_ASSERT(parent_2_cache[2] == -100); + CU_ASSERT(parent_2_cache[3] == 0); + CU_ASSERT(parent_2_cache[4] == 1); + CU_ASSERT(parent_2_cache[5] == -100); + + coord2->matrix[2] = 20; + coord2->matrix[5] = 30; + rdman_coord_changed(rdman, coord2); + rdman_redraw_changed(rdman); + + /* To test if transform matrix of cached coord working */ + parent_2_cache = ((mock_mbe_t *)_coord_get_canvas(coord2))->parent_2_cache; + CU_ASSERT(parent_2_cache[0] == 1); + CU_ASSERT(parent_2_cache[1] == 0); + CU_ASSERT(parent_2_cache[2] == -120); + CU_ASSERT(parent_2_cache[3] == 0); + CU_ASSERT(parent_2_cache[4] == 1); + CU_ASSERT(parent_2_cache[5] == -130); + + rdman_paint_free(rdman, paint); + redraw_man_destroy(rdman); +} + CU_pSuite get_redraw_man_suite(void) { CU_pSuite suite; suite = CU_add_suite("Suite_redraw_man", NULL, NULL); CU_ADD_TEST(suite, test_rdman_redraw_changed); CU_ADD_TEST(suite, test_rdman_free_objs); + CU_ADD_TEST(suite, test_setup_canvas_info); + CU_ADD_TEST(suite, test_own_canvas_area); + CU_ADD_TEST(suite, test_own_canvas); + CU_ADD_TEST(suite, test_own_canvas_redraw); return suite; }
--- a/src/rotate.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/rotate.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h>
--- a/src/shape_image.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/shape_image.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- 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 "mb_graph_engine.h" @@ -53,11 +55,11 @@ */ typedef struct _sh_image { shape_t shape; - + co_aix x, y; co_aix w, h; co_aix poses[4][2]; - + redraw_man_t *rdman; } sh_image_t; @@ -70,8 +72,6 @@ shape_t *rdman_shape_image_new(redraw_man_t *rdman, co_aix x, co_aix y, co_aix w, co_aix h) { sh_image_t *img; - mb_img_fmt_t fmt; - int r; img = O_ALLOC(sh_image_t); if(img == NULL) @@ -86,7 +86,9 @@ img->y = y; img->w = w; img->h = h; - + + rdman_man_shape(rdman, (shape_t *)img); + return (shape_t *)img; } @@ -102,10 +104,11 @@ paint_t *paint; co_aix (*poses)[2]; co_aix img_matrix[6]; + co_aix rev_matrix[6]; co_aix x_factor, y_factor; int img_w, img_h; int i; - + poses = img->poses; poses[0][0] = img->x; poses[0][1] = img->y; @@ -117,7 +120,7 @@ poses[3][1] = img->y + img->h; for(i = 0; i < 4; i++) coord_trans_pos(img->shape.coord, &poses[i][0], &poses[i][1]); - + geo_from_positions(sh_get_geo(shape), 4, poses); paint = sh_get_fill(shape); @@ -125,29 +128,28 @@ return; ASSERT(paint.pnt_type == MBP_IMAGE); - + paint_image_get_size(paint, &img_w, &img_h); - - /* Transformation from user space to image space */ + + /* Transformation from image space to user space */ img_matrix[0] = (poses[1][0] - poses[0][0]) / img->w; - img_matrix[1] = (poses[1][1] - poses[0][1]) / img->w; - img_matrix[2] = -poses[0][0]; - img_matrix[3] = (poses[3][0] - poses[0][0]) / img->h; + img_matrix[1] = (poses[3][0] - poses[3][0]) / img->h; + img_matrix[2] = poses[0][0]; + img_matrix[3] = (poses[1][1] - poses[0][1]) / img->w; img_matrix[4] = (poses[3][1] - poses[0][1]) / img->h; - img_matrix[5] = -poses[0][1]; + img_matrix[5] = poses[0][1]; if(img->w != img_w || img->h != img_h) { /* Resize image */ - x_factor = img_w / img->w; + x_factor = img->w / img_w; img_matrix[0] *= x_factor; img_matrix[1] *= x_factor; - img_matrix[2] *= x_factor; - y_factor = img_h / img->h; + y_factor = img->h / img_h; img_matrix[3] *= y_factor; img_matrix[4] *= y_factor; - img_matrix[5] *= y_factor; } - paint_image_set_matrix(sh_get_fill(shape), img_matrix); + compute_reverse(img_matrix, rev_matrix); + paint_image_set_matrix(sh_get_fill(shape), rev_matrix); } /*! \brief Draw image for an image shape. @@ -156,9 +158,7 @@ */ void sh_image_draw(shape_t *shape, mbe_t *cr) { sh_image_t *img = (sh_image_t *)shape; - mbe_pattern_t *saved_source; - co_aix *aggr; - + mbe_move_to(cr, img->poses[0][0], img->poses[0][1]); mbe_line_to(cr, img->poses[1][0], img->poses[1][1]); mbe_line_to(cr, img->poses[2][0], img->poses[2][1]);
--- a/src/shape_path.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/shape_path.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <ctype.h> @@ -23,9 +25,13 @@ int float_arg_len; char *user_data; char *dev_data; /* device space data */ + + redraw_man_t *rdman; /*!< \brief This is used by sh_path_free() */ } sh_path_t; #define RESERVED_AIXS sizeof(co_aix[2]) +int _sh_path_size = sizeof(sh_path_t); + #define ASSERT(x) #define SKIP_SPACE(x) while(*(x) && (isspace(*(x)) || *(x) == ',')) { (x)++; } #define SKIP_NUM(x) \ @@ -35,7 +41,7 @@ *(x) == 'E' || \ *(x) == '-' || \ *(x) == '+' || \ - *(x) == '.')) { \ + *(x) == '.')) { \ (x)++; \ } #define OK 0 @@ -43,8 +49,22 @@ #define PI 3.1415926535897931 #ifdef UNITTEST -#undef rdman_shape_man -#define rdman_shape_man(x, y) +#undef rdman_man_shape +#define rdman_man_shape(x, y) + +#undef elmpool_elm_alloc +#define elmpool_elm_alloc(pool) _elmpool_elm_alloc(pool) +static void * +_elmpool_elm_alloc(void *dummy) { + return malloc(sizeof(sh_path_t)); +} + +#undef elmpool_elm_free +#define elmpool_elm_free(pool, elm) _elmpool_elm_free(pool, elm) +static void +_elmpool_elm_free(void *pool, void *elm) { + free(elm); +} #endif /* ============================================================ @@ -108,13 +128,13 @@ float _sin = sinf(x_rotate); float _cos = cosf(x_rotate); int reflect; - + /* Compute center of the ellipse */ nrx = x * _cos + y * _sin; nry = x * -_sin + y * _cos; nrx0 = x0 * _cos + y0 * _sin; nry0 = x0 * -_sin + y0 * _cos; - + udx = (nrx - nrx0) / 2 / rx; /* ux - umx */ udy = (nry - nry0) / 2 / ry; /* uy - umy */ umx = (nrx + nrx0) / 2 / rx; @@ -168,12 +188,12 @@ nrx = (x * _cos + y * _sin) / rx; nry = (-x * _sin + y * _cos) / ry; xy_tan = nry / nrx; - + angle = atan(xy_tan); if(nrx < 0) angle = PI + angle; - + return angle; } @@ -261,7 +281,7 @@ *pnts++ = corners[i][0] + cx; *pnts++ = corners[i][1] + cy; } - + *(pnts++) = x; *(pnts++) = y; @@ -274,7 +294,7 @@ angle_stop += 2 * PI; else if((!sweep) && angle_start < angle_stop) angle_start += 2 * PI; - + *float_args++ = cx; *float_args++ = cy; *float_args++ = rx; @@ -282,7 +302,7 @@ *float_args++ = angle_start; *float_args++ = angle_stop; *float_args++ = x_rotate; - + *cmds++ = toupper(cmd); } @@ -308,7 +328,7 @@ rd2 = distance_pow2(dx, dy); rd = sqrtf(rd2); - + inner = INNER(sx, sy, dx, dy); cross = CROSS(sx, sy, dx, dy); angle = acos(inner / rd); @@ -352,7 +372,7 @@ _sin = sinf(x_rotate); _cos = cosf(x_rotate); - + xyratio = ry / rx; aggr = sh_get_aggr_matrix((shape_t *)path); matrix[0] = _cos; @@ -365,7 +385,7 @@ matrix_mul(aggr, matrix, dev_matrix); mbe_save(cr); mbe_transform(cr, dev_matrix); - mbe_arc(cr, 0, 0, rx, angle_start, angle_stop); + mbe_arc(cr, 0, 0, rx, angle_start, angle_stop); mbe_restore(cr); *pnts_p = pnts; @@ -376,9 +396,11 @@ static void sh_path_free(shape_t *shape) { sh_path_t *path = (sh_path_t *)shape; + + mb_obj_destroy(path); if(path->user_data) free(path->user_data); - free(path); + elmpool_elm_free(path->rdman->sh_path_pool, path); } /*! \brief Count number of arguments. @@ -529,7 +551,7 @@ SKIP_NUM(p); if(p == old) break; - + for(i = 0; i < 6; i++) { SKIP_SPACE(p); old = p; @@ -570,6 +592,7 @@ char cmd; co_aix *pnts; co_aix *float_args; + co_aix sx = 0, sy = 0; co_aix x, y; int r; @@ -626,6 +649,7 @@ if(p == old) return ERR; *pnts = TO_ABSX; + x = *pnts; pnts++; SKIP_SPACE(p); @@ -634,6 +658,7 @@ if(p == old) return ERR; *pnts = TO_ABSY; + y = *pnts; pnts++; *cmds++ = toupper(cmd); @@ -667,6 +692,7 @@ if(p == old) return ERR; *pnts = TO_ABSX; + x = *pnts; pnts++; SKIP_SPACE(p); @@ -675,13 +701,43 @@ if(p == old) return ERR; *pnts = TO_ABSY; + y = *pnts; pnts++; *cmds++ = toupper(cmd); } break; + case 'm': case 'M': + while(*p) { + old = p; + SKIP_SPACE(p); + old = p; + SKIP_NUM(p); + if(p == old) + break; + *pnts = TO_ABSX; + x = *pnts; + pnts++; + + SKIP_SPACE(p); + old = p; + SKIP_NUM(p); + if(p == old) + return ERR; + *pnts = TO_ABSY; + y = *pnts; + pnts++; + + *cmds++ = toupper(cmd); + + /* save initial point of a subpath */ + sx = x; + sy = y; + } + break; + case 'l': case 'L': case 't': @@ -694,6 +750,7 @@ if(p == old) break; *pnts = TO_ABSX; + x = *pnts; pnts++; SKIP_SPACE(p); @@ -702,6 +759,7 @@ if(p == old) return ERR; *pnts = TO_ABSY; + y = *pnts; pnts++; *cmds++ = toupper(cmd); @@ -726,6 +784,9 @@ case 'z': case 'Z': *cmds++ = toupper(cmd); + /* Go back to initial point of a subpath */ + x = sx; + y = sy; break; default: return ERR; @@ -757,7 +818,7 @@ cmd_cnt = (cmd_cnt + 3) & ~0x3; /*! \todo Use elmpool to manage sh_path_t objects. */ - path = (sh_path_t *)malloc(sizeof(sh_path_t)); + path = (sh_path_t *)elmpool_elm_alloc(rdman->sh_path_pool); /*! \todo Remove this memset()? */ memset(&path->shape, 0, sizeof(shape_t)); mb_obj_init(path, MBO_PATH); @@ -769,7 +830,7 @@ sizeof(co_aix) * float_arg_cnt; path->user_data = (char *)malloc(msz * 2); if(path->user_data == NULL) { - free(path); + elmpool_elm_free(rdman->sh_path_pool, path); return NULL; } @@ -778,14 +839,15 @@ r = sh_path_cmd_arg_fill(data, path); if(r == ERR) { free(path->user_data); - free(path); + elmpool_elm_free(rdman->sh_path_pool, path); return NULL; } memcpy(path->dev_data, path->user_data, msz); path->shape.free = sh_path_free; + path->rdman = rdman; - rdman_shape_man(rdman, (shape_t *)path); + rdman_man_shape(rdman, (shape_t *)path); return (shape_t *)path; } @@ -800,7 +862,7 @@ int cmd_cnt = strlen(commands); /*! \todo Use elmpool to manage sh_path_t objects. */ - path = (sh_path_t *)malloc(sizeof(sh_path_t)); + path = (sh_path_t *)elmpool_elm_alloc(rdman->sh_path_pool); /*! \todo Remove this memset()? */ memset(&path->shape, 0, sizeof(shape_t)); mb_obj_init(path, MBO_PATH); @@ -812,7 +874,7 @@ sizeof(co_aix) * float_arg_cnt; path->user_data = (char *)malloc(msz * 2); if(path->user_data == NULL) { - free(path); + elmpool_elm_free(rdman->sh_path_pool, path); return NULL; } @@ -822,10 +884,11 @@ memcpy(path->user_data + cmd_cnt + pnt_cnt * sizeof(co_aix), float_args, sizeof(co_aix) * float_arg_cnt); memcpy(path->dev_data, path->user_data, msz); - + path->shape.free = sh_path_free; - - rdman_shape_man(rdman, (shape_t *)path); + path->rdman = rdman; + + rdman_man_shape(rdman, (shape_t *)path); return (shape_t *)path; } @@ -960,8 +1023,9 @@ void test_rdman_shape_path_new(void) { sh_path_t *path; co_aix *pnts; + redraw_man_t rdman; - path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55c 33 87 44 22 55 99L33 77z"); + path = (sh_path_t *)rdman_shape_path_new(&rdman, "M 33 25l33 55c 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); CU_ASSERT(path->pnt_len == 12); @@ -989,8 +1053,9 @@ co_aix *pnts; coord_t coord; geo_t geo; + redraw_man_t rdman; - path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55C 33 87 44 22 55 99L33 77z"); + path = (sh_path_t *)rdman_shape_path_new(&rdman, "M 33 25l33 55C 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); CU_ASSERT(path->pnt_len == 12); @@ -1029,9 +1094,10 @@ void test_spaces_head_tail(void) { sh_path_t *path; + redraw_man_t rdman; path = (sh_path_t *) - rdman_shape_path_new(NULL, + rdman_shape_path_new(&rdman, " M 33 25l33 55C 33 87 44 22 55 99L33 77z "); CU_ASSERT(path != NULL); sh_path_free((shape_t *)path);
--- a/src/shape_rect.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/shape_rect.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -10,10 +12,16 @@ co_aix w, h; co_aix rx, ry; co_aix poses[12][2]; + + redraw_man_t *rdman; /*!< \brief This is used by sh_rect_free() */ } sh_rect_t; +int _sh_rect_size = sizeof(sh_rect_t); + static void sh_rect_free(shape_t *shape) { - free(shape); + sh_rect_t *rect = (sh_rect_t *)shape; + + elmpool_elm_free(rect->rdman->sh_rect_pool, rect); } shape_t *rdman_shape_rect_new(redraw_man_t *rdman, @@ -21,7 +29,7 @@ co_aix rx, co_aix ry) { sh_rect_t *rect; - rect = (sh_rect_t *)malloc(sizeof(sh_rect_t)); + rect = (sh_rect_t *)elmpool_elm_alloc(rdman->sh_rect_pool); if(rect == NULL) return NULL; @@ -35,8 +43,9 @@ rect->rx = rx; rect->ry = ry; rect->shape.free = sh_rect_free; + rect->rdman = rdman; - rdman_shape_man(rdman, (shape_t *)rect); + rdman_man_shape(rdman, (shape_t *)rect); return (shape_t *)rect; } @@ -77,21 +86,21 @@ poses[1][1] = y; poses[2][0] = x + w; poses[2][1] = y + ry; - + poses[3][0] = x + w; poses[3][1] = y + h - ry; poses[4][0] = x + w; poses[4][1] = y + h; poses[5][0] = x + w - rx; poses[5][1] = y + h; - + poses[6][0] = x + rx; poses[6][1] = y + h; poses[7][0] = x; poses[7][1] = y + h; poses[8][0] = x; poses[8][1] = y + h - ry; - + poses[9][0] = x; poses[9][1] = y + ry; poses[10][0] = x;
--- a/src/shape_stext.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/shape_stext.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- 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 "mb_graph_engine.h" @@ -34,8 +36,8 @@ #undef mb_obj_init #define mb_obj_init(o, t) -#undef rdman_shape_man -#define rdman_shape_man(rdman, sh) +#undef rdman_man_shape +#define rdman_man_shape(rdman, sh) #define rdman_shape_stext_new ut_rdman_shape_stext_new #define sh_stext_transform ut_sh_stext_transform @@ -100,7 +102,7 @@ * * Although, mb_text_extents_t is defined as a mbe_scaled_font_t, but * programmers should assume it is opague. - * + * * An extents is the span of showing a fragement of text on the output device. * It includes x and y advance of cursor after showinng the text. * The cursor maybe not really existed. But, the advance is computed as @@ -151,9 +153,9 @@ mbe_scaled_font_t *scaled_font; static co_aix id[6] = { 1, 0, 0, 0, 1, 0 }; - + ASSERT(matrix != NULL); - + scaled_font = mbe_scaled_font_create((mbe_font_face_t *)face, matrix, &id); @@ -198,14 +200,14 @@ buf = strndup(txt, tlen); else buf = txt; - + saved_scaled = mbe_get_scaled_font(cr); mbe_scaled_font_reference(saved_scaled); mbe_set_scaled_font(cr, (mbe_scaled_font_t *)scaled); - + mbe_move_to(cr, x, y); mbe_text_path(cr, buf); - + mbe_set_scaled_font(cr, saved_scaled); mbe_scaled_font_destroy(saved_scaled); @@ -265,12 +267,12 @@ int i; DARRAY_DESTROY(&txt_o->style_blks); - + for(i = 0; i < txt_o->scaled_fonts.num; i++) scaled_font_free(txt_o->scaled_fonts.ds[i]); DARRAY_DESTROY(&txt_o->scaled_fonts); DARRAY_DESTROY(&txt_o->sub_exts); - + if(txt_o->txt) free((void *)txt_o->txt); @@ -282,14 +284,14 @@ sh_stext_t *txt_o; ASSERT(txt != NULL); - + txt_o = (sh_stext_t *)malloc(sizeof(sh_stext_t)); if(txt_o == NULL) return NULL; memset(&txt_o->shape, 0, sizeof(shape_t)); mb_obj_init(txt_o, MBO_STEXT); - + txt_o->txt = strdup(txt); DARRAY_INIT(&txt_o->style_blks); txt_o->x = x; @@ -303,9 +305,9 @@ } txt_o->shape.free = _rdman_shape_stext_free; - - rdman_shape_man(rdman, (shape_t *)txt_o); - + + rdman_man_shape(rdman, (shape_t *)txt_o); + return (shape_t *)txt_o; } @@ -314,7 +316,7 @@ int i; const char *p = txt; const char *v; - + for(i = 0; i < n_chars && *p; i++) { if(!(*p & 0x80)) /* single byte */ p++; @@ -333,7 +335,7 @@ for(v = txt; v != p; v++) if(*v == '\x0') return ERR; - + return p - txt; } @@ -351,15 +353,15 @@ memcpy(noshift_aggr, aggr, sizeof(co_aix) * 6); noshift_aggr[2] = 0; noshift_aggr[5] = 0; - + matrix[0] = font_sz; matrix[1] = 0; matrix[2] = shift_x; matrix[3] = 0; matrix[4] = font_sz; - matrix[5] += shift_y; + matrix[5] = shift_y; matrix_mul(noshift_aggr, matrix, scaled_matrix); - + scaled = make_scaled_font_face_matrix(face, scaled_matrix); return scaled; @@ -384,13 +386,13 @@ s_ybr = MBE_GET_Y_BEARING(sub) + MBE_GET_Y_ADV(full); s_rbx = s_xbr + MBE_GET_WIDTH(sub); s_rby = s_ybr + MBE_GET_HEIGHT(sub); - + /* set bearing */ if(MBE_GET_X_BEARING(full) > s_xbr) MBE_SET_X_BEARING(full, s_xbr); if(MBE_GET_Y_BEARING(full) > s_ybr) MBE_SET_Y_BEARING(full, s_ybr); - + /* set width/height */ if(f_rbx < s_rbx) MBE_SET_WIDTH(full, s_rbx - MBE_GET_X_BEARING(full)); @@ -435,19 +437,19 @@ mb_text_extents_t *sub; char *txt, saved; int i, nscaled; - + scaled_fonts = &txt_o->scaled_fonts; for(i = 0; i < scaled_fonts->num; i++) scaled_font_free(scaled_fonts->ds[i]); DARRAY_CLEAN(scaled_fonts); - + style_blks = &txt_o->style_blks; blk = style_blks->ds; sub_exts = &txt_o->sub_exts; DARRAY_CLEAN(sub_exts); extents_lst_adv(sub_exts, style_blks->num); - + txt = (char *)txt_o->txt; for(i = 0; i < style_blks->num; i++) { scaled = make_scaled_font_face(txt_o, blk->face, @@ -455,10 +457,10 @@ ASSERT(scaled != NULL); scaled_fonts_lst_add(scaled_fonts, scaled); sub = sub_exts->ds + i; - + blk_txt_len = compute_utf8_chars_sz(txt, blk->n_chars); ASSERT(blk_txt_len != ERR); - + saved = txt[blk_txt_len]; txt[blk_txt_len] = 0; compute_text_extents(scaled, txt, sub); @@ -467,7 +469,7 @@ blk++; txt += blk_txt_len; } - + if(style_blks->num > 0) { sub = sub_exts->ds; memcpy(&txt_o->extents, sub, sizeof(mb_text_extents_t)); @@ -476,7 +478,7 @@ extent_extents(&txt_o->extents, sub); } } else - memset(&txt_o->extents, sizeof(mb_text_extents_t), 0); + memset(&txt_o->extents, sizeof(mb_text_extents_t), 0); } /* @@ -499,14 +501,14 @@ ASSERT(txt_o != NULL); aggr = sh_get_aggr_matrix(shape); - + txt_o->dx = txt_o->x; txt_o->dy = txt_o->y; matrix_trans_pos(aggr, &txt_o->dx, &txt_o->dy); - + compute_styled_extents_n_scaled_font(txt_o); ext = &txt_o->extents; - + area = sh_get_area(shape); area->x = MBE_GET_X_BEARING(ext) + txt_o->dx; area->y = MBE_GET_Y_BEARING(ext) + txt_o->dy; @@ -527,20 +529,20 @@ int i; ASSERT(txt_o != NULL); - + x = txt_o->dx; y = txt_o->dy; txt = txt_o->txt; scaled_fonts = &txt_o->scaled_fonts; style_blks = &txt_o->style_blks; ext = txt_o->sub_exts.ds; - + for(i = 0; i < scaled_fonts->num; i++) { scaled = scaled_fonts->ds[i]; blk = style_blks->ds + i; blk_txt_len = compute_utf8_chars_sz(txt, blk->n_chars); draw_text_scaled(cr, txt, blk_txt_len, scaled, x, y); - + x += MBE_GET_X_ADV(ext); y += MBE_GET_Y_ADV(ext); txt += blk_txt_len; @@ -554,15 +556,15 @@ ASSERT(txt_o != NULL); ASSERT(txt != NULL); - + sz = strlen(txt) + 1; new_txt = (char *)realloc((void *)txt_o->txt, sz); if(new_txt == NULL) return ERR; - + memcpy(new_txt, txt, sz); txt_o->txt = new_txt; - + return OK; } @@ -576,14 +578,14 @@ ASSERT(txt_o != NULL); ASSERT(nblks >= 0); - + style_blks = &txt_o->style_blks; DARRAY_CLEAN(style_blks); style_blks_lst_adv(style_blks, nblks); - + memcpy(style_blks->ds, blks, nblks * sizeof(mb_style_blk_t)); - + return OK; } @@ -597,7 +599,7 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + free_font_face(face); } @@ -609,10 +611,10 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + scaled = make_scaled_font_face_matrix(face, matrix); CU_ASSERT(scaled != NULL); - + scaled_font_free(scaled); free_font_face(face); } @@ -665,14 +667,14 @@ MBE_SET_Y_BEARING(&ext1, -8); MBE_SET_X_ADV(&ext1, 21); MBE_SET_Y_ADV(&ext1, -3); - + MBE_SET_WIDTH(&ext2, 30); MBE_SET_HEIGHT(&ext2, 11); MBE_SET_X_BEARING(&ext2, 2); MBE_SET_Y_BEARING(&ext2, -11); MBE_SET_X_ADV(&ext2, 32); MBE_SET_Y_ADV(&ext2, -5); - + extent_extents(&ext1, &ext2); CU_ASSERT(MBE_GET_WIDTH(&ext1) == 52); @@ -687,7 +689,7 @@ void test_compute_utf8_chars_sz(void) { const char *str = "\xe4\xb8\xad\xe6\x96\x87test\xe6\xb8\xac\xe8\xa9\xa6"; int sz; - + sz = compute_utf8_chars_sz(str, 4); CU_ASSERT(sz == 8); @@ -718,15 +720,15 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + blks[0].n_chars = 5; blks[0].face = face; blks[0].font_sz = 10; - + blks[1].n_chars = 4; blks[1].face = face; blks[1].font_sz = 15.5; - + r = sh_stext_set_style((shape_t *)txt_o, blks, 2); CU_ASSERT(r == OK); @@ -740,7 +742,7 @@ CU_ASSERT(MBE_GET_X_ADV(ext) > 36); CU_ASSERT(MBE_GET_X_ADV(ext) < 72); CU_ASSERT(MBE_GET_Y_ADV(ext) == 0); - + _rdman_shape_stext_free((shape_t *)txt_o); free_font_face(face); } @@ -768,15 +770,15 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + blks[0].n_chars = 5; blks[0].face = face; blks[0].font_sz = 10; - + blks[1].n_chars = 4; blks[1].face = face; blks[1].font_sz = 15.5; - + r = sh_stext_set_style((shape_t *)txt_o, blks, 2); CU_ASSERT(r == OK); @@ -791,7 +793,7 @@ CU_ASSERT(MBE_GET_X_ADV(ext) < 72); CU_ASSERT(MBE_GET_Y_ADV(ext) > 36); CU_ASSERT(MBE_GET_Y_ADV(ext) < 72); - + _rdman_shape_stext_free((shape_t *)txt_o); free_font_face(face); } @@ -818,15 +820,15 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + blks[0].n_chars = 5; blks[0].face = face; blks[0].font_sz = 10; - + blks[1].n_chars = 4; blks[1].face = face; blks[1].font_sz = 15.5; - + r = sh_stext_set_style((shape_t *)txt_o, blks, 2); CU_ASSERT(r == OK); @@ -837,7 +839,7 @@ CU_ASSERT(area->y >= 40 && area->y < 50); CU_ASSERT(area->w >= 80 && area->w < 120); CU_ASSERT(area->h >= 8 && area->h < 12); - + _rdman_shape_stext_free((shape_t *)txt_o); free_font_face(face); } @@ -853,7 +855,7 @@ txt_o = (sh_stext_t *)rdman_shape_stext_new(NULL, "hello world", 100, 50); CU_ASSERT(txt_o != NULL); - + aggr = txt_o->shape.aggr; aggr[0] = 2; aggr[1] = 0; @@ -864,15 +866,15 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + blks[0].n_chars = 5; blks[0].face = face; blks[0].font_sz = 10; - + blks[1].n_chars = 6; blks[1].face = face; blks[1].font_sz = 15.5; - + r = sh_stext_set_style((shape_t *)txt_o, blks, 2); CU_ASSERT(r == OK); @@ -901,7 +903,7 @@ txt_o = (sh_stext_t *)rdman_shape_stext_new(NULL, "hello world", 100, 50); CU_ASSERT(txt_o != NULL); - + aggr = txt_o->shape.aggr; aggr[0] = 2; aggr[1] = 0; @@ -912,15 +914,15 @@ face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - + blks[0].n_chars = 5; blks[0].face = face; blks[0].font_sz = 10; - + blks[1].n_chars = 6; blks[1].face = face; blks[1].font_sz = 15.5; - + r = sh_stext_set_style((shape_t *)txt_o, blks, 2); CU_ASSERT(r == OK);
--- a/src/shape_text.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/shape_text.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -65,8 +67,8 @@ text->attrs = attrs; text->align = TEXTALIGN_START; text->w = text->h = 0; - - rdman_shape_man(rdman, (shape_t *)text); + + rdman_man_shape(rdman, (shape_t *)text); return (shape_t *)text; } @@ -222,9 +224,9 @@ int r; text = (sh_text_t *)shape; - + text->d_font_size = coord_trans_size(shape->coord, text->font_size); - + coord = sh_get_coord(shape); canvas = _coord_get_canvas(coord); sh_text_P_generate_layout(text, (mbe_t *)canvas);
--- a/src/shift.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/shift.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -45,7 +47,7 @@ coord_t *coord; float ratio; - + MB_TIMEVAL_CP(&diff, now); MB_TIMEVAL_DIFF(&diff, &shift->start_time); ratio = comp_mb_timeval_ratio(&diff, shift->playing_time);
--- a/src/sprite.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/sprite.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,15 +1,13 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "mb_graph_engine.h" #include <dlfcn.h> #include <sys/stat.h> #include "mb_types.h" -#include "mb_shapes.h" -#include "mb_tools.h" #include "mb_redraw_man.h" -#include "mb_observer.h" -#include "mb_prop.h" +#include "mb_sprite.h" #define ASSERT(x) #define OK 0 @@ -22,10 +20,10 @@ int fsz; char *fullname; int r; - + if(sprite_search_path == NULL) sprite_search_path = strdup("/usr/share/madbutterffly"); - + fsz = strlen(sprite_search_path) + strlen(name) + 5; fullname = (char *)malloc(fsz); @@ -39,14 +37,14 @@ return fullname; } -void sprite_set_search_path(char *path) { +void sprite_set_search_path(const char *path) { int sz; - + if (sprite_search_path) free(sprite_search_path); - + sprite_search_path = strdup(path); - + sz = strlen(sprite_search_path); if(sprite_search_path[sz - 1] == '/') sprite_search_path[sz - 1] = 0; @@ -61,33 +59,31 @@ mb_sprite_t *(*cnstr)(redraw_man_t *, coord_t *); mb_sprite_t *obj; int r; - + so_path = sprite_search_so(name); if(so_path == NULL) return NULL; - + handle = dlopen(so_path, RTLD_LAZY); free(so_path); if (handle == NULL) return NULL; - + bname = strrchr(name, '/'); if(bname != NULL && strlen(bname) > 250) return NULL; - + if(bname == NULL) bname = name; else bname++; - + snprintf(cnstr_name, sizeof(cnstr_name), "%s_new", bname); cnstr = dlsym(handle, cnstr_name); if (cnstr == NULL) return NULL; - + obj = cnstr(rdman, root); - + return obj; } - -/* vim: set ts=4 */
--- a/src/subtree_free.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/subtree_free.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include "mb_redraw_man.h" #include "mb_animate.h"
--- a/src/testcase.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/testcase.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <CUnit/Basic.h> extern CU_pSuite get_tools_suite(void);
--- a/src/timer.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/timer.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,9 +1,12 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include "mb_timer.h" #include "mb_tools.h" +#include "mb_backend.h" #define OK 0 @@ -23,7 +26,7 @@ mb_tman_t *mb_tman_new(void) { mb_tman_t *tman; - + tman = (mb_tman_t *)malloc(sizeof(mb_tman_t)); if(tman == NULL) return NULL; @@ -76,7 +79,7 @@ return timer; } - + int mb_tman_remove(mb_tman_t *tman, mb_timer_t *timer) { STAILQ_REMOVE(tman->timers, mb_timer_t, next, timer); elmpool_elm_free(tman->timer_pool, timer); @@ -120,3 +123,101 @@ return OK; } + +/*! \defgroup tman_timer_man Timer manager based on mb_tman_t. + * + * This implmentation of timer manager is based on mb_tman_t. + * @{ + */ +struct _tman_timer_man { + mb_timer_man_t timer_man; + mb_tman_t *tman; +}; + +static int _tman_timer_man_timeout(struct _mb_timer_man *tm_man, + mb_timeval_t *tmout, + mb_timer_cb_t cb, void *data); +static void _tman_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl); +static mb_timer_man_t *_tman_timer_fact_new(void); +static void _tman_timer_fact_free(mb_timer_man_t *timer_man); + +static struct _tman_timer_man _tman_default_timer_man = { + {_tman_timer_man_timeout, _tman_timer_man_remove}, + NULL +}; + +mb_timer_factory_t tman_timer_factory = { + _tman_timer_fact_new, + _tman_timer_fact_free +}; + +/*! \brief Content of a timeout request. + * + * This is only used by internal of X support. This data structure + * carry information to adopt mb_tman_t to mb_timer_man_t. + */ +struct _tman_timeout_data { + mb_timer_t *timer; /*!< Handle returned by mb_tman_timeout() */ + mb_timer_cb_t cb; /*!< Real callback function */ + void *data; /*!< data for real callback */ +}; + +static void +_tman_tmo_hdlr(const mb_timeval_t *tmo, + const mb_timeval_t *now, + void *arg) { + struct _tman_timeout_data *data = (struct _tman_timeout_data *)arg; + + data->cb((int)data, tmo, now, data->data); +} + +static int +_tman_timer_man_timeout(struct _mb_timer_man *tm_man, + mb_timeval_t *tmout, /* timeout (wall time) */ + mb_timer_cb_t cb, void *data) { + struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; + mb_timer_t *timer; + struct _tman_timeout_data *tmout_data; + + tmout_data = O_ALLOC(struct _tman_timeout_data); + tmout_data->cb = cb; + tmout_data->data = data; + timer = mb_tman_timeout(timer_man->tman, tmout, + _tman_tmo_hdlr, tmout_data); + if(timer == NULL) + return ERR; + tmout_data->timer = timer; + + return (int)tmout_data; +} + +static void +_tman_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl) { + struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; + struct _tman_timeout_data *tmout_data = + (struct _tman_timeout_data *)tm_hdl; + + mb_tman_remove(timer_man->tman, tmout_data->timer); + free(tmout_data); +} + +static mb_timer_man_t * +_tman_timer_fact_new(void) { + if(_tman_default_timer_man.tman == NULL) + _tman_default_timer_man.tman = mb_tman_new(); + return (mb_timer_man_t *)&_tman_default_timer_man; +} + +static void +_tman_timer_fact_free(mb_timer_man_t *timer_man) { +} + +mb_tman_t * +tman_timer_man_get_tman(mb_timer_man_t *tm_man) { + struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; + + return timer_man->tman; +} + + +/* @} */
--- a/src/timertool.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/timertool.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <sys/time.h> #ifdef __FreeBSD__
--- a/src/tools.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/tools.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdlib.h> #include "mb_tools.h"
--- a/src/visibility.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/visibility.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include "mb_animate.h"
--- a/tools/Makefile.am Mon Jul 19 15:44:49 2010 +0800 +++ b/tools/Makefile.am Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 m4datadir = $(datadir)/mb dist_m4data_DATA = foreach.m4 mb_c_header.m4 mb_c_source.m4 dist_bin_SCRIPTS = svg2code.py
--- a/tools/Makefile.pmake Mon Jul 19 15:44:49 2010 +0800 +++ b/tools/Makefile.pmake Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 BINS= svg2code.py M4SCRIPTS= mb_c_header.m4 mb_c_source.m4 foreach.m4 PREFIX?= /usr/local/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/gen_v8_binding.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -0,0 +1,718 @@ +dnl +dnl Developers should provide SET, WRAP, UNWRAP, and THROW C macros. +dnl +changequote(`[', `]')dnl +include([foreach.m4])dnl +divert([-1])dnl + +define([UNQUOTE], [$*]) + +define([QUOTE], [[[$*]]]) + +define([VARFRAME], [dnl +pushdef([_FRAME_VARS], [])dnl +]) + +define([UNVARFRAME], [dnl +EXPAND(_FRAME_VARS)dnl +popdef([_FRAME_VARS])dnl +]) + +define([fdefine], [dnl +pushdef([$1], [$2])dnl +define([_FRAME_VARS], QUOTE(_FRAME_VARS[popdef([$1])]))dnl +]) + +define([COUNT],[ifelse([$*],[],0,[$#])]) + +define([IMPORT],[define([$1],[$2$1(]$[]@[)])]) + +define([EXPAND], [$1]) + +define([PROJ_PREFIX], [xnjsmb_]) + +define([START_ACCESSOR], [dnl +divert([-1])dnl +VARFRAME[]dnl + fdefine([INT], [ +static Handle<Value> +]PROJ_PREFIX[]STRUCT_NAME[_get_$][1(Local<String> property, const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW("Invalid object"); + return Integer::New(data->$][1); +} + +static void +]PROJ_PREFIX[]STRUCT_NAME[_set_$][1(Local<String> property, + Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW_noret("Invalid object"); + data->$][1 = value->Int32Value(); +} +]) + fdefine([NUMBER], [ +static Handle<Value> +]PROJ_PREFIX[]STRUCT_NAME[_get_$][1(Local<String> property, const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW("Invalid object"); + return Number::New(data->$][1); +} + +static void +]PROJ_PREFIX[]STRUCT_NAME[_set_$][1(Local<String> property, + Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW_noret("Invalid object"); + data->$][1 = value->NumberValue(); +} +]) + fdefine([OBJ], [ +static Handle<Value> +]PROJ_PREFIX[]STRUCT_NAME[_get_$][1(Local<String> property, const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW("Invalid object"); + return ]PROJ_PREFIX[$][2_new(($][3 *)data->$][1); +} + +static void +]PROJ_PREFIX[]STRUCT_NAME[_set_$][1(Local<String> property, + Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + Handle<Object> obj; + $][3 *v; + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW_noret("Invalid object"); + obj = value->ToObject(); + v = ($][3 *)UNWRAP(obj); + if(v == NULL) + THROW_noret("Invalid object"); + data->$][1 = v; +} +]) + fdefine([ARRAY], [ +static Handle<Value> +]PROJ_PREFIX[]STRUCT_NAME[_get_$][1(Local<String> property, const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW("Invalid object"); + return data->$][1; +} + +static void +]PROJ_PREFIX[]STRUCT_NAME[_set_$][1(Local<String> property, + Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + Handle<Object> obj; + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW_noret("Invalid object"); + data->$][1 = value; +} +]) + fdefine([STR], [ +static Handle<Value> +]PROJ_PREFIX[]STRUCT_NAME[_get_$][1(Local<String> property, const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW("Invalid object"); + return String::New(data->$][1); +} + +static void +]PROJ_PREFIX[]STRUCT_NAME[_set_$][1(Local<String> property, + Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW_noret("Invalid object"); + String::Utf8Value utf8(value->ToString()); + free(data->$][1); + data->$][1 = strdup(*utf8); +} +]) +dnl +dnl ACCESSOR(name, getter, setter) +dnl + fdefine([ACCESSOR], [ +static Handle<Value> +]PROJ_PREFIX[]STRUCT_NAME[_get_$][1(Local<String> property, const AccessorInfo &info) { + Handle<Object> self = info.This(); + Handle<Value> _ret; + STRUCT_TYPE *data; + const char *err = NULL; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW("Invalid object"); + _ret = $][2(self, data, &err); + if(err) + THROW(err); + return _ret; +} + +static void +]PROJ_PREFIX[]STRUCT_NAME[_set_$][1(Local<String> property, + Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *data; + const char *err = NULL; + + data = (STRUCT_TYPE *)UNWRAP(self); + if(data == NULL) + THROW_noret("Invalid object"); + $][3(self, data, value, &err); + if(err) + THROW_noret(err); +} +]) +divert([])dnl +]) + +define([STOP_ACCESSOR], [dnl +divert([-1])dnl +UNVARFRAME[]dnl +divert([])dnl +]) + +define([SET_ACCESSOR], [dnl +VARFRAME[]dnl +fdefine([INT], [$][1])dnl +fdefine([NUMBER], [$][1])dnl +fdefine([OBJ], [$][1])dnl +fdefine([ARRAY], [$][1])dnl +fdefine([STR], [$][1])dnl +fdefine([ACCESSOR], [$][1])dnl + inst_temp->SetAccessor(String::New("$1"), + PROJ_PREFIX[]STRUCT_NAME[]_get_[]$1, + PROJ_PREFIX[]STRUCT_NAME[]_set_[]$1); +UNVARFRAME[]dnl +]) + +define([START_METHOD_ARG_VAR], [dnl +VARFRAME[]dnl +fdefine([INT], [dnl + int arg_$][1; +])dnl +fdefine([NUMBER], [dnl + double arg_$][1; +])dnl +fdefine([OBJ], [dnl + $][3 *arg_$][1; +])dnl +fdefine([ARRAY], [dnl + Handle<Value> arg_$][1; +])dnl +fdefine([STR], [dnl + char *arg_$][1; +])dnl +fdefine([FUNC], [dnl + Handle<Function> arg_$][1; +])dnl +fdefine([SELF], [])dnl +fdefine([ERR], [])dnl +]) + +define([START_METHOD_ARG_TYPE_CHK], [dnl +VARFRAME[]dnl +fdefine([INT], [ || + !args[[i++]]->IsInt32()])dnl +fdefine([NUMBER], [ || + !args[[i++]]->IsNumber()])dnl +fdefine([OBJ], [ || + !args[[i++]]->IsObject()])dnl +fdefine([ARRAY], [ || + !args[[i++]]->IsArray()])dnl +fdefine([STR], [ || + !args[[i++]]->IsString()])dnl +fdefine([FUNC], [ || + !args[[i++]]->IsFunction()])dnl +fdefine([SELF], [])dnl +fdefine([ERR], [])dnl +]) + +define([START_TYPE_CHK], [dnl +VARFRAME[]dnl +fdefine([INT], [$1->IsInt32()])dnl +fdefine([NUMBER], [$1->IsNumber()])dnl +fdefine([OBJ], [$1->IsObject()])dnl +fdefine([ARRAY], [$1->IsArray()])dnl +fdefine([STR], [$1->IsString()])dnl +fdefine([FUNC], [$1->IsFunction()])dnl +]) + +define([START_METHOD_ARG_ASSIGN], [dnl +VARFRAME[]dnl +fdefine([INT], [dnl + arg_$][1 = args[[i++]]->Int32Value(); +])dnl +fdefine([NUMBER], [dnl + arg_$][1 = args[[i++]]->NumberValue(); +])dnl +fdefine([OBJ], [dnl + arg_$][1 = ($][3 *)UNWRAP(args[[i++]]->ToObject()); + if(arg_$][1 == NULL) + THROW("Invalid argument"); +])dnl +fdefine([ARRAY], [dnl + arg_$][1 = args[[i++]]; +])dnl +fdefine([STR], [dnl + arg_$][1 = strdup(*String::Utf8Value(args[[i++]]->ToString())); +])dnl +fdefine([FUNC], [dnl + arg_$][1 = args[[i++]].As<Function>(); +])dnl +fdefine([SELF], [])dnl +fdefine([ERR], [])dnl +]) + +define([START_VALUE_ASSIGN], [dnl +VARFRAME[]dnl +fdefine([INT], [dnl + $1 = $2->Int32Value(); +])dnl +fdefine([NUMBER], [dnl + $1 = $2->NumberValue(); +])dnl +fdefine([OBJ], [dnl + $1 = ($][2 *)UNWRAP($2->ToObject()); + if($1 == NULL) + THROW("Invalid argument"); +])dnl +fdefine([ARRAY], [dnl + $1 = $2; +])dnl +fdefine([STR], [dnl + $1 = strdup(*String::Utf8Value($2->ToString())); +])dnl +fdefine([FUNC], [dnl + $1 = $2.As<Function>(); +])dnl +]) + +define([START_METHOD_ARG_PASS], [dnl +VARFRAME[]dnl +fdefine([INT], [arg_$][1])dnl +fdefine([NUMBER], [arg_$][1])dnl +fdefine([OBJ], [arg_$][1])dnl +fdefine([ARRAY], [arg_$][1])dnl +fdefine([STR], [arg_$][1])dnl +fdefine([FUNC], [arg_$][1])dnl +fdefine([SELF], [self])dnl +fdefine([ERR], [&_err])dnl +fdefine([VAL], [&_err])dnl +]) + +define([START_METHOD_RET_VAL], [dnl +VARFRAME[]dnl +fdefine([INT], [dnl + int _ret; +])dnl +fdefine([NUMBER], [dnl + double _ret; +])dnl +fdefine([OBJ], [dnl + $][2 *_ret; +])dnl +fdefine([ARRAY], [dnl + Handle<Value> _ret; +])dnl +fdefine([STR], [dnl + char *_ret; +])dnl +fdefine([FUNC], [dnl + Handle<Function> _ret; +])dnl +fdefine([VAL], [dnl + Handle<Value> _ret; +])dnl +]) + +define([START_VAR], [dnl +VARFRAME[]dnl +fdefine([INT], [dnl + int $1; +])dnl +fdefine([NUMBER], [dnl + double $1; +])dnl +fdefine([OBJ], [dnl + $][2 *$1; +])dnl +fdefine([ARRAY], [dnl + Handle<Value> *$1; +])dnl +fdefine([STR], [dnl + char *$1; +])dnl +fdefine([FUNC], [dnl + Handle<Function> $1; +])dnl +]) + +define([START_METHOD_RET_ASSIGN], [dnl +VARFRAME[]dnl +fdefine([INT], [_ret = (int)])dnl +fdefine([NUMBER], [_ret = (double)])dnl +fdefine([OBJ], [_ret = ($][2 *)])dnl +fdefine([ARRAY], [_ret = ])dnl +fdefine([STR], [_ret = (char *)])dnl +fdefine([FUNC], [_ret = ])dnl +fdefine([VAL], [_ret = ])dnl +]) + +define([START_METHOD_RET], [dnl +VARFRAME[]dnl +fdefine([INT], [ + _ret_val = Integer::New(_ret); +])dnl +fdefine([NUMBER], [ + _ret_val = Number::New(_ret); +])dnl +fdefine([OBJ], [ + _ret_val = PROJ_PREFIX[]$][1[]_new(_ret); +])dnl +fdefine([ARRAY], [ + _ret_val = _ret; +])dnl +fdefine([STR], [ + _ret_val = String::New(_ret); +])dnl +fdefine([FUNC], [ + _rt_val = _ret; +])dnl +fdefine([VAL], [ + _rt_val = _ret; +])dnl +]) + +define([STOP_METHOD_ARG], [dnl +UNVARFRAME[]dnl +]) + +define([START_METHOD], [dnl +dnl +dnl METHOD(name, func, arguments, cnt, ret_type, options) +dnl +define([METHOD], [ +VARFRAME[]dnl +dnl +ifelse($][6, [], [], [dnl +foreach([ITER], ]$][6[, [EXPAND([fdefine]ITER)])dnl +])dnl +dnl +static Handle<Value> +PROJ_PREFIX[]STRUCT_NAME[]_$][1(const Arguments &args) { + HandleScope scope; + int i; + int argc = args.Length(); + Handle<Object> self = args.This(); + STRUCT_TYPE *_self = (STRUCT_TYPE *)UNWRAP(self); + const char *_err = NULL; +foreach([ITER], $][3, [START_METHOD_ARG_VAR[]ITER[]STOP_METHOD_ARG])dnl +START_METHOD_RET_VAL[]$][5[]STOP_METHOD_ARG + Handle<Value> _ret_val; + + if(_self == NULL) + THROW("Invalid object"); + if(argc != $][4) + THROW("Invalid number of arguments (!=$][4)"); + i = 0; + if(0[]dnl +foreach([ITER], $][3, [START_METHOD_ARG_TYPE_CHK[]ITER[]STOP_METHOD_ARG])) + THROW("Invalid argument type"); + + i = 0; +foreach([ITER], $][3, [START_METHOD_ARG_ASSIGN[]ITER[]STOP_METHOD_ARG])dnl + + START_METHOD_RET_ASSIGN[]$][5[]STOP_METHOD_ARG[]$][2(_self[]foreach([ITER], $][3, [START_METHOD_ARG_PASS[], ITER[]STOP_METHOD_ARG])); + if(_err) + THROW(_err); +START_METHOD_RET[]$][5[]STOP_METHOD_ARG[]dnl +ifelse($][5, [], [ + return Null(); +], [dnl +dnl +dnl Modify returned object +dnl +ifdef([MOD], [ + MOD[](self, _ret_val); +])dnl + scope.Close(_ret_val); + return _ret_val; +])dnl +} +UNVARFRAME[]dnl +])dnl +]) + +define([STOP_METHOD], [undefine([METHOD])]) + +define([SET_METHOD], [dnl +define([METHOD], [dnl + SET(proto_temp, "$][1", + FunctionTemplate::New(PROJ_PREFIX[]STRUCT_NAME[]_$][1)); +])dnl +$1[]dnl +undefine([METHOD])dnl +]) + +define([DEF_GET_INDEX], [ +static Handle<Value> +PROJ_PREFIX[]STRUCT_NAME[]_get_index(uint32_t index, const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *obj = (STRUCT_TYPE *)UNWRAP(self); + const char *_err = NULL; +START_METHOD_RET_VAL[]$2[]STOP_METHOD_ARG[]dnl + Handle<Value> _ret_val; + + if(obj == NULL) + THROW("Invalid object"); + _ret = $1(obj, self, index, &_err); + if(_err) + THROW(_err); +START_METHOD_RET[]$2[]STOP_METHOD_ARG[]dnl + return _ret_val; +} +]) + +define([DEF_SET_INDEX], [ +static Handle<Value> +PROJ_PREFIX[]STRUCT_NAME[]_set_index(uint32_t index, Local<Value> value, + const AccessorInfo &info) { + Handle<Object> self = info.This(); + STRUCT_TYPE *obj = (STRUCT_TYPE *)UNWRAP(self); + const char *_err = NULL; +START_VAR([in_value])[]$2[]STOP_METHOD_ARG[]dnl +START_METHOD_RET_VAL[]$2[]STOP_METHOD_ARG[]dnl + Handle<Value> _ret_val; + + if(obj == NULL) + THROW("Invalid object"); + if(START_TYPE_CHK(value)[]![]$2[]STOP_METHOD_ARG) + THROW("Invalid value type"); + +START_VALUE_ASSIGN(in_value, value)[]$2[]STOP_METHOD_ARG[]dnl + _ret = $1(obj, self, index, in_value, &_err); + if(_err) THROW(_err); +START_METHOD_RET[]$2[]STOP_METHOD_ARG[]dnl + return _ret_val; +} +]) + +define([INSTALL_INDEX_FUNCTIONS],[dnl +define([FIRST], [$][1])dnl +ifdef([GET_INDEX], [ifdef([SET_INDEX], [dnl + inst_temp->SetIndexedPropertyHandler(PROJ_PREFIX[]STRUCT_NAME[]_get_index, + PROJ_PREFIX[]STRUCT_NAME[]_set_index); +], [dnl + inst_temp->SetIndexedPropertyHandler(PROJ_PREFIX[]STRUCT_NAME[]_get_index); +])])dnl +undefine([FIRST])dnl +]) + +define([CTOR_INTERNAL], [dnl + int argc = args.Length(); + Handle<Object> self = args.This(); + $4 *obj; +foreach([ITER], $2, [START_METHOD_ARG_VAR[]ITER[]STOP_METHOD_ARG])dnl + int i; + + if(argc != $3) + THROW("Invalid number of arguments (!=$][4)"); + i = 0; + if(0]dnl +[foreach([ITER], $2, [START_METHOD_ARG_TYPE_CHK[]ITER[]STOP_METHOD_ARG])) + THROW("Invalid argument type"); + + i = 0; +foreach([ITER], $2, [START_METHOD_ARG_ASSIGN[]ITER[]STOP_METHOD_ARG])dnl + +define([SEP], [])dnl + obj = ($4 *)$1(foreach([ITER], $2, [START_METHOD_ARG_PASS[]SEP[]ITER[]STOP_METHOD_ARG[]define([SEP], [, ])]));[]undefine([SEP]) + + WRAP(self, obj);] +ifdef([STMOD], [ + STMOD(self, obj); +])dnl +) + +dnl +dnl STRUCT(struct_name, struct_type, member_vars, methods, options) +dnl +define([STRUCT], [dnl +define([STRUCT_NAME], [$1])dnl +define([STRUCT_TYPE], [$2])dnl +dnl +VARFRAME[]dnl +ifelse([$5], [], [], [dnl +foreach([ITER], $5, [dnl +EXPAND([fdefine]ITER)[]dnl +])dnl +])dnl +dnl +[ +/* ************************************************** + * STRUCT: $1 + * Generated by gen_v8_binding.m4 + */ +static Handle<Value> +]PROJ_PREFIX[$1(const Arguments &args) { +]ifdef([CTOR], [EXPAND([CTOR_INTERNAL](EXPAND([UNQUOTE]CTOR), [$2]))])dnl + return Null(); +[} + +static Persistent<FunctionTemplate> ]PROJ_PREFIX[$1][_temp; + +static Handle<Value> +]PROJ_PREFIX[$1][_new($2 *data) { + Handle<Object> obj; + Handle<Function> func; + + func = ]PROJ_PREFIX[$1][_temp->GetFunction(); + obj = func->NewInstance(); + WRAP(obj, data);] +ifdef([STMOD], [ + STMOD[(obj, data)]; +])dnl +[ return obj; +} +]dnl +foreach([ITER], ($3), [START_ACCESSOR ITER STOP_ACCESSOR])dnl +foreach([ITER], ($4), [START_METHOD ITER STOP_METHOD])dnl +ifdef([GET_INDEX], [EXPAND([DEF_GET_INDEX]GET_INDEX)])dnl +ifdef([SET_INDEX], [EXPAND([DEF_SET_INDEX]SET_INDEX)])dnl +[ +static void +]PROJ_PREFIX[$1][_init(void) { + Handle<FunctionTemplate> func_temp; + Handle<ObjectTemplate> inst_temp; + Handle<ObjectTemplate> proto_temp; + + func_temp = FunctionTemplate::New(]PROJ_PREFIX[$1); + func_temp->SetClassName(String::New("]STRUCT_NAME[")); +]ifdef([INHERIT], [dnl + func_temp->Inherit(]PROJ_PREFIX[]INHERIT[_temp); +])dnl +[ inst_temp = func_temp->InstanceTemplate(); + inst_temp->SetInternalFieldCount(1); +]foreach([ITER], ($3), [SET_ACCESSOR(ITER)])dnl +INSTALL_INDEX_FUNCTIONS[]dnl + + proto_temp = func_temp->PrototypeTemplate(); +foreach([ITER], ($4), [SET_METHOD(ITER)])dnl + + PROJ_PREFIX[$1][_temp = Persistent<FunctionTemplate>::New(func_temp); +}]dnl +dnl +UNVARFRAME[]dnl +dnl +]) + +dnl +dnl FUNCTION(func_name, real_func, arguments, arguement_count, +dnl return_type, options) +dnl +define([FUNCTION], [dnl +dnl +VARFRAME[]dnl +ifelse($6, [], [], [dnl +foreach([ITER], $6, [EXPAND([fdefine]ITER)])dnl +])dnl +dnl +/* ************************************************** + * [FUNCTION]: $1 + * Generated by gen_v8_binding.m4 + */ +static Handle<Value> +PROJ_PREFIX[]$1(const Arguments &args) { + HandleScope scope; + int argc = args.Length(); + int i; + const char *_err = NULL; +foreach([ITER], ($3), [START_METHOD_ARG_VAR[]ITER[]STOP_METHOD_ARG])dnl +START_METHOD_RET_VAL[]$5[]STOP_METHOD_ARG[]dnl + Handle<Value> _ret_val; + + if(argc != $4) + THROW("Invalid number of arguments (!=$][4)"); + i = 0; + if(0]dnl +[foreach([ITER], ($3), [START_METHOD_ARG_TYPE_CHK[]ITER[]STOP_METHOD_ARG])) + THROW("Invalid argument type"); + + i = 0; +foreach([ITER], ($3), [START_METHOD_ARG_ASSIGN[]ITER[]STOP_METHOD_ARG])dnl + +define([SEP], [])dnl + START_METHOD_RET_ASSIGN[]$5[]STOP_METHOD_ARG[]$2(foreach([ITER], ($3), [START_METHOD_ARG_PASS[]SEP[]ITER[]STOP_METHOD_ARG[]define([SEP], [, ])]));[]undefine([SEP]) + if(_err) + THROW(_err); +START_METHOD_RET[]$][5[]STOP_METHOD_ARG[]dnl +ifelse($][5, [], [ + return Null(); +], [dnl +dnl +dnl Modify returned object +dnl +ifdef([MOD], [ + MOD[](self, _ret_val); +])dnl + scope.Close(_ret_val); + return _ret_val; +])dnl +} +static Persistent<FunctionTemplate> PROJ_PREFIX[]$1[]_temp; + +static void +PROJ_PREFIX[]$1[]_init(void) { + Handle<FunctionTemplate> func_temp; + + func_temp = FunctionTemplate::New(PROJ_PREFIX[]$1); + PROJ_PREFIX[]$1[]_temp = Persistent<FunctionTemplate>::New(func_temp); +} +dnl +UNVARFRAME[]dnl +dnl +]) + +divert([])dnl
--- a/tools/mb_c_source.m4 Mon Jul 19 15:44:49 2010 +0800 +++ b/tools/mb_c_source.m4 Wed Dec 01 12:25:56 2010 +0800 @@ -475,6 +475,7 @@ #include <mb_redraw_man.h> #include <mb_shapes.h> #include <mb_paint.h> +#include <mb_sprite.h> #include "$1.h" #ifdef MB_SPRITE_OFFSET
--- a/tools/svg2code.py Mon Jul 19 15:44:49 2010 +0800 +++ b/tools/svg2code.py Wed Dec 01 12:25:56 2010 +0800 @@ -1,4 +1,6 @@ #! /usr/bin/env python +# -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +# vim: sw=4:ts=8:sts=4 from xml.dom.minidom import parse import sys import re @@ -131,7 +133,7 @@ style_str = node.getAttribute('style') prop_map = get_style_map(style_str) pass - + if node.hasAttribute('fill-opacity'): opacity = float(node.getAttribute('fill-opacity')) elif node.hasAttribute('opacity'): @@ -234,15 +236,15 @@ # \see calc_center_and_x_aix() def _calc_ellipse_of_arc(x0, y0, rx, ry, x_rotate, large, sweep, x, y): import math - + _sin = math.sin(x_rotate) _cos = math.cos(x_rotate) - + nrx = x * _cos + y * _sin # Not Rotated X nry = x * -_sin + y * _cos nrx0 = x0 * _cos + y0 * _sin nry0 = x0 * -_sin + y0 * _cos - + udx = (nrx - nrx0) / 2 / rx # ux - umx udy = (nry - nry0) / 2 / ry # uy - umy umx = (nrx + nrx0) / 2 / rx @@ -279,10 +281,10 @@ nrcx = rx * (udcx + umx) nrcy = ry * (udcy + umy) - + cx = nrcx * _cos - nrcy * _sin cy = nrcx * _sin + nrcy * _cos - + return cx, cy # M x y : Move to (x,y) @@ -313,20 +315,20 @@ def _angle_rotated_ellipse(x, y, rx, ry, x_rotate): import math - + _cos = math.cos(x_rotate) _sin = math.sin(x_rotate) nrx = (x * _cos + y * _sin) / rx nry = (-x * _sin + y * _cos) / ry - + xy_tan = nry / nrx xy_angle = math.atan(xy_tan) if nrx < 0: xy_angle = math.pi + xy_angle pass - + return xy_angle def rotate(x, y, angle): @@ -340,7 +342,7 @@ def translate_path_data(data, codefo): import string import math - + temp = data.split() fields=[] for f in temp: @@ -385,7 +387,7 @@ pnts.append(pnts[-2]) pnts.append(arg + pnts[-2]) continue - + arg = float(f) if (cmd not in 'am') and (cmd in string.lowercase): # relative and not arc or moveto @@ -424,14 +426,14 @@ c3x, c3y = rotate(-rx, ry, x_rotate) c3x, c3y = c3x + cx, c3y + cy - + pnts[-7:] = [c0x, c0y, c1x, c1y, c2x, c2y, c3x, c3y, abs_x, abs_y] - + start_angle = _angle_rotated_ellipse(x0 - cx, y0 - cy, rx, ry, x_rotate) stop_angle = _angle_rotated_ellipse(x - cx, y - cy, rx, ry, x_rotate) - + # sweep == 1 for positive-angle direction # sweep == 0 for negative-angle direction if start_angle > stop_angle and sweep: @@ -439,7 +441,7 @@ elif start_angle < stop_angle and not sweep: start_angle = math.pi * 2 + start_angle pass - + float_args.extend([cx, cy, rx, ry, start_angle, stop_angle, x_rotate]) pass @@ -548,7 +550,7 @@ pass if tspan.hasAttribute('x'): # Render the tspan as an independent text if the x - # attribute is defined. All elements inside + # attribute is defined. All elements inside # the tspan will be ignore by the outter text or tspan elements. # FIXME: We need to apply the style map recursively. merge_style(tspan, text) @@ -585,7 +587,7 @@ print >> codefo, 'PANGO_SIZE(%d,%d,%d)dnl' % (font_sz*1024,start,end) pass pass - + if style_map.has_key('font-style'): font_style = style_map['font-style'].lower() if font_style == 'normal': @@ -674,10 +676,10 @@ def stext_generate_font_attributes(text, attrs, coord_id, codefo, doc): text_id = _get_id(text) - + for start, end, node in attrs: style_map = node.style_map - + font_sz = 10 if style_map.has_key('font-size'): fsz = style_map['font-size'] @@ -687,13 +689,13 @@ font_sz = float(fsz) pass pass - + if style_map.has_key('font-family'): font_family = style_map['font-family'] else: font_family = 'serif' pass - + font_slant = 0 if style_map.has_key('font-style'): fn_style = style_map['font-style'] @@ -706,7 +708,7 @@ else: raise ValueError, '%s is not a valid font-style' % (fn_style) pass - + font_weight = 80 if style_map.has_key('font-weight'): fn_weight = style_map['font-weight'] @@ -726,7 +728,7 @@ font_weight = int(fn_weight) pass pass - + print >> codefo, 'STYLE_BLOCK([%s], %d, [%s], %f, %d, %d)dnl' % ( text_id, end - start, font_family, font_sz, font_slant, font_weight) @@ -736,7 +738,7 @@ def stext_gen_text(text, coord_id, codefo, doc, txt_strs, attrs): if not txt_strs: return - + text_id = _get_id(text) x = float(text.getAttribute('x')) y = float(text.getAttribute('y')) @@ -757,7 +759,7 @@ coord_id = translate_shape_transform(text, coord_id, codefo) try: map = text.style_map - except: + except: map = translate_font_style(text, codefo) text.style_map = map pass @@ -781,7 +783,7 @@ @check_mbname def translate_image(image, coord_id, codefo, doc): coord_id = translate_shape_transform(image, coord_id, codefo) - + image_id = _get_id(image) if not image.hasAttributeNS(xlinkns, 'href'): raise ValueError, 'image %s must has a href attribute.' % (image_id) @@ -815,7 +817,7 @@ 'ADD_IMAGE([%s], [%s], %f, %f, %f, %f, [%s])dnl' % ( image_id, href, x, y, width, height, coord_id) pass - + reo_func = re.compile('([a-zA-Z]+)\\([^\\)]*\\)') reo_translate = re.compile('translate\\(([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)\\)') @@ -889,7 +891,7 @@ not scene.hasAttribute('ref') or \ not scene.hasAttribute('start'): continue - + start_str = scene.getAttribute('start') start = end = int(start_str) if scene.hasAttribute('end'): @@ -897,11 +899,11 @@ end = int(end_str) pass ref = scene.getAttribute('ref') - + while len(scenes) <= end: scenes.append([]) pass - + for i in range(start, end + 1): scenes[i].append(ref) pass @@ -925,7 +927,7 @@ pass else: raise ValueErr, 'no any svg tag node.' - + svg = node for node in svg.childNodes: if node.localName == 'defs' and node.namespaceURI == svgns: @@ -946,14 +948,14 @@ if __name__ == '__main__': from os import path import optparse - + usage='usage: %prog [options] <SVG file> [<output>]' parser = optparse.OptionParser(usage=usage) parser.add_option('-s', '--stext', dest='stext', action='store_true', default=False, help='Use sh_stext instead of sh_text'); options, args = parser.parse_args() - + if len(args) == 2: svgfn = args[0] codefn = args[1] @@ -964,7 +966,7 @@ parser.print_help() sys.exit(1) pass - + struct_name = path.basename(codefn).split('.')[0] if options.stext: