Mercurial > MadButterfly
changeset 257:50d253d0fcba
Simple image loader and image shape.
- img_ldr.c is a simple image loader that rooted on a directory
specified when a loader instance been created.
- sh_image_t is corresponding shape of image tag in SVG.
- This changeset is still buggy. It need more testing.
- svg2code.py is not ready for image tag.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Thu, 15 Jan 2009 16:46:47 +0800 |
parents | cac9ad3df633 |
children | f24129d4f0f9 |
files | include/Makefile.am include/mb_img_ldr.h include/mb_prop.h include/mb_redraw_man.h include/mb_shapes.h include/mb_types.h src/Makefile.am src/Makefile.pmake src/img_ldr.c src/redraw_man.c src/shape_image.c tools/mb_c_header.m4 tools/mb_c_source.m4 tools/svg2code.py |
diffstat | 14 files changed, 425 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/include/Makefile.am Thu Jan 15 02:15:35 2009 +0800 +++ b/include/Makefile.am Thu Jan 15 16:46:47 2009 +0800 @@ -9,4 +9,5 @@ mb_shapes.h \ mb_tools.h \ mb_prop.h \ - mb_X_supp.h + mb_X_supp.h \ + mb_so.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_img_ldr.h Thu Jan 15 16:46:47 2009 +0800 @@ -0,0 +1,57 @@ +#ifndef __MB_IMG_LDR_H_ +#define __MB_IMG_LDR_H_ + +typedef struct _mb_img_data mb_img_data_t; +typedef struct _mb_img_ldr mb_img_ldr_t; + +typedef enum _mb_img_fmt { + MB_IFMT_DUMMY, + MB_IFMT_ARGB32, + MB_IFMT_RGB24, + MB_IFMT_A8, + MB_IFMT_A1, + MB_IFMT_RGB16_565 +} mb_img_fmt_t; + +/*! \brief Encapsulate image. + * + * The format and content of an image is encapsulated by imag_data_t. + * We hope someday, we can create an abstract backend layer that + * can deal with image data. + */ +struct _mb_img_data { + /*! \brief Content of the image. */ + void *content; + int width, height; + int stride; /*!< \brief Number of bytes a row */ + mb_img_fmt_t fmt; + /*! \brief Release the image that was loaded by the loader. */ + void (*free)(mb_img_data_t *img); +}; +#define MB_IMG_DATA_FREE(img) (img)->free(img) + +/*! \brief Image loader. + * + * An image loader take a ID and find out the corresponding + * image from filesystem or somewhere. Image ID is a hierachical + * structured path. It is relative to the root of image database. + * Users of a loader do not need to know where the database is. + * The location can be configured when a loader been instantiated. + * But, it is invisible when loading images by an image loader. + */ +struct _mb_img_ldr { + /*! \brief Load a image with specified ID. */ + mb_img_data_t *(*load)(mb_img_ldr_t *ldr, const char *img_id); + /*! \brief Free the loader. */ + void (*free)(mb_img_ldr_t *ldr); +}; +#define MB_IMG_LDR_FREE(ldr) (ldr)->free(ldr) + +/*! \brief Create a simple image loader. + * + * \param img_repository is a repository where images are loaded from. + * \return NULL for error. + */ +extern mb_img_ldr_t *simple_mb_img_ldr_new(const char *img_repository); + +#endif /* __MB_IMG_LDR_H_ */
--- a/include/mb_prop.h Thu Jan 15 02:15:35 2009 +0800 +++ b/include/mb_prop.h Thu Jan 15 16:46:47 2009 +0800 @@ -11,6 +11,10 @@ * to keep property values. Every property is identified by a ID; an * integer. Programmer can use a ID to set/get value to/from a property * store. The ID should be unique in a property store. + * + * \todo Add a free function pointer on entries to release resources when + * the store is destroy. (See: \ref mouse.c) + * * @{ */
--- a/include/mb_redraw_man.h Thu Jan 15 02:15:35 2009 +0800 +++ b/include/mb_redraw_man.h Thu Jan 15 16:46:47 2009 +0800 @@ -78,6 +78,7 @@ * graphic backend. * \see rdman_attach_backend() */ + mb_prop_store_t props; }; extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr,
--- a/include/mb_shapes.h Thu Jan 15 02:15:35 2009 +0800 +++ b/include/mb_shapes.h Thu Jan 15 16:46:47 2009 +0800 @@ -10,6 +10,7 @@ #include <cairo.h> #include "mb_types.h" #include "mb_redraw_man.h" +#include "mb_img_ldr.h" /*! \page define_shape How to Define Shapes * @@ -29,6 +30,14 @@ * - event.c::draw_shape_path() * - redraw_man.c::clean_shape() * - redraw_man.c::draw_shape() + * + * \section shape_transform Shape Transform + * + * All shape types must have a shape transform function. It is invoked by + * redraw_man.c::clean_shape(). It's task is to update \ref geo_t of the + * shape object. In most situtation, it call geo_from_positions() to + * update geo_t. + * */ /*! \defgroup shapes Shapes @@ -68,6 +77,19 @@ extern void sh_rect_set(shape_t *shape, co_aix x, co_aix y, co_aix w, co_aix h, co_aix rx, co_aix ry); /* @} */ + +/*! \defgroup shape_image Shape of Image + * @{ + */ +extern shape_t *rdman_shape_image_new(redraw_man_t *rdman, + mb_img_data_t *img_data, + co_aix x, co_aix y, + co_aix w, co_aix h); +extern void sh_image_transform(shape_t *shape); +extern void sh_image_draw(shape_t *shape, cairo_t *cr); +extern void sh_image_set(shape_t *shape, co_aix x, co_aix y, + co_aix w, co_aix h); +/* @} */ /* @} */ #endif /* __SHAPES_H_ */
--- a/include/mb_types.h Thu Jan 15 02:15:35 2009 +0800 +++ b/include/mb_types.h Thu Jan 15 16:46:47 2009 +0800 @@ -40,7 +40,8 @@ MBO_SHAPES=0x1000, /*! \note Don't touch this. */ MBO_PATH, MBO_TEXT, - MBO_RECT + MBO_RECT, + MBO_IMAGE }; #define MBO_CLASS_MASK 0xf000 #define MBO_CLASS(x) (((mb_obj_t *)(x))->obj_type & MBO_CLASS_MASK) @@ -197,6 +198,7 @@ } while(0) #define coord_show(co) do { co->flags &= ~COF_HIDDEN; } while(0) #define coord_get_mouse_event(coord) ((coord)->mouse_event) +#define coord_get_aggr_matrix(coord) ((coord)->aggr_matrix) #define FOR_COORDS_POSTORDER(coord, cur) \ for((cur) = postorder_coord_subtree((coord), NULL); \ (cur) != NULL; \ @@ -270,6 +272,7 @@ #define sh_clear_flags(sh, mask) geo_clear_flags(sh_get_geo(sh), mask) #define sh_pos_is_in(sh, x, y) geo_pos_is_in(sh_get_geo(sh), x, y) #define sh_get_area(sh) geo_get_area(sh_get_geo(sh)) +#define sh_get_coord(sh) ((sh)->coord) /*! \brief A sprite is a set of graphics that being an object in animation.
--- a/src/Makefile.am Thu Jan 15 02:15:35 2009 +0800 +++ b/src/Makefile.am Thu Jan 15 16:46:47 2009 +0800 @@ -8,7 +8,7 @@ observer.c paint.c redraw_man.c rotate.c shape_path.c \ shape_rect.c shape_text.c shift.c subtree_free.c timer.c \ timertool.c tools.c visibility.c X_supp.c prop.c sprite.c \ - mouse.c + mouse.c shape_image.c img_ldr.c libmbfly_la_CPPFLAGS = @cairo_CFLAGS@ libmbfly_la_LDFLAGS = @cairo_LIBS@
--- a/src/Makefile.pmake Thu Jan 15 02:15:35 2009 +0800 +++ b/src/Makefile.pmake Thu Jan 15 16:46:47 2009 +0800 @@ -1,7 +1,8 @@ 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 \ X_supp.c timertool.c tools.c shift.c chgcolor.c \ - visibility.c rotate.c prop.c mouse.c + visibility.c rotate.c prop.c mouse.c img_ldr.c OBJS = ${SRCS:C/(.*)\.c/\1.o/g} TESTCASE_SRCS = ${SRCS:C/X_supp\.c//} TESTCASE_OBJS = ${TESTCASE_SRCS:C/(.*)\.c/testcase-\1.o/g}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/img_ldr.c Thu Jan 15 16:46:47 2009 +0800 @@ -0,0 +1,125 @@ +#include <stdio.h> +#include <string.h> +#include <cairo.h> +#include "mb_tools.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; + cairo_surface_t *surf; +}; +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; + cairo_surface_t *surf; + char *fname; + cairo_format_t fmt; + int sz; + + sz = strlen(sldr->repo); + sz += strlen(img_id); + fname = (char *)malloc(sz + 2); + strcpy(fname, sldr->repo); + strcat(fname, img_id); + + surf = cairo_image_surface_create_from_png(fname); + if(surf == NULL) + return NULL; + + img = O_ALLOC(simple_mb_img_data_t); + if(img == NULL) { + cairo_surface_destroy(surf); + return NULL; + } + img->img.content = cairo_image_surface_get_data(surf); + img->img.width = cairo_image_surface_get_width(surf); + img->img.height = cairo_image_surface_get_height(surf); + img->img.stride = cairo_image_surface_get_stride(surf); + fmt = cairo_image_surface_get_format(surf); + switch(fmt) { + case CAIRO_FORMAT_ARGB32: + img->img.fmt = MB_IFMT_ARGB32; + break; + + case CAIRO_FORMAT_RGB24: + img->img.fmt = MB_IFMT_RGB24; + break; + + case CAIRO_FORMAT_A8: + img->img.fmt = MB_IFMT_A8; + break; + + case CAIRO_FORMAT_A1: + img->img.fmt = MB_IFMT_A1; + break; + + default: + cairo_surface_destroy(surf); + free(img); + return NULL; + } + img->img.free = simple_mb_img_ldr_img_free; + img->surf = surf; + + 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; + cairo_surface_destroy((cairo_surface_t *)simg->surf); + 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] != '/') { + ((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/redraw_man.c Thu Jan 15 02:15:35 2009 +0800 +++ b/src/redraw_man.c Thu Jan 15 16:46:47 2009 +0800 @@ -316,6 +316,7 @@ subject_add_observer(rdman->root_coord->mouse_event, mouse_event_root_dummy, NULL); + mb_prop_store_init(&rdman->props, rdman->pent_pool); return OK; err: @@ -341,6 +342,8 @@ shape_t *shape, *saved_shape; geo_t *member; + mb_prop_store_destroy(&rdman->props); + free_free_objs(rdman); free_objs_destroy(rdman);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shape_image.c Thu Jan 15 16:46:47 2009 +0800 @@ -0,0 +1,161 @@ +#include <stdio.h> +#include <string.h> +#include <cairo.h> +#include "mb_types.h" +#include "mb_shapes.h" +#include "mb_img_ldr.h" +#include "mb_tools.h" + +#define ASSERT(x) +#define OK 0 +#define ERR -1 + +typedef struct _sh_image { + shape_t shape; + + co_aix x, y; + co_aix w, h; + + mb_img_data_t *img_data; + cairo_surface_t *surf; +} sh_image_t; + +static void sh_image_free(shape_t *shape); + +/*! \brief Creae a new image shape. + * + * \param img_data is image data whose owner-ship is transfered. + */ +shape_t *rdman_shape_image_new(redraw_man_t *rdman, mb_img_data_t *img_data, + co_aix x, co_aix y, co_aix w, co_aix h) { + sh_image_t *img; + cairo_format_t fmt; + + img = O_ALLOC(sh_image_t); + if(img == NULL) + return NULL; + + memset(img, 0, sizeof(sh_image_t)); + + img->shape.free = sh_image_free; + mb_obj_init((mb_obj_t *)img, MBO_IMAGE); + img->x = x; + img->y = y; + img->w = w; + img->h = h; + img->img_data = img_data; + + switch(img_data->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: + mb_obj_destroy(img); + free(img); + return NULL; + } + + img->surf = cairo_image_surface_create_for_data(img_data->content, + fmt, + img_data->width, + img_data->height, + img_data->stride); + if(img->surf == NULL) { + mb_obj_destroy(img); + free(img); + return NULL; + } + + return (shape_t *)img; +} + +void sh_image_free(shape_t *shape) { + sh_image_t *img = (sh_image_t *)shape; + + mb_obj_destroy(shape); + MB_IMG_DATA_FREE(img->img_data); + cairo_surface_destroy(img->surf); + free(img); +} + +void sh_image_transform(shape_t *shape) { + sh_image_t *img = (sh_image_t *)shape; + co_aix poses[4][2]; + int i; + + poses[0][0] = img->x; + poses[0][1] = img->y; + poses[1][0] = img->x + img->w; + poses[1][1] = img->y; + poses[2][0] = img->x + img->w; + poses[2][1] = img->y + img->h; + poses[3][0] = img->x; + 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); +} + +/*! \brief Draw image for an image shape. + * + * \note Image is not rescaled for size of the shape. + */ +void sh_image_draw(shape_t *shape, cairo_t *cr) { + sh_image_t *img = (sh_image_t *)shape; + cairo_pattern_t *saved_source; + cairo_matrix_t matrix, saved_matrix; + co_aix *aggr; + + aggr = coord_get_aggr_matrix(sh_get_coord(shape)); + cairo_matrix_init(&matrix, + aggr[0], aggr[3], + aggr[1], aggr[4], + aggr[2], aggr[5]); + + /* set matrix */ + cairo_get_matrix(cr, &saved_matrix); + cairo_set_matrix(cr, &matrix); + + /* set source */ + saved_source = cairo_get_source(cr); + cairo_pattern_reference(saved_source); + + /* draw image */ + cairo_set_source_surface(cr, img->surf, 0, 0); + cairo_paint(cr); + + /* restore source */ + cairo_set_source(cr, saved_source); + cairo_pattern_destroy(saved_source); + + /* restore matrix */ + cairo_set_matrix(cr, &saved_matrix); +} + +void sh_image_set(shape_t *shape, co_aix x, co_aix y, + co_aix w, co_aix h) { + sh_image_t *img = (sh_image_t *)shape; + + img->x = x; + img->y = y; + img->w = w; + img->h = h; +}
--- a/tools/mb_c_header.m4 Thu Jan 15 02:15:35 2009 +0800 +++ b/tools/mb_c_header.m4 Thu Jan 15 16:46:47 2009 +0800 @@ -20,6 +20,9 @@ define([ADD_TEXT],[ [ shape_t *$1; ]]) +define([ADD_IMAGE],[ +[ shape_t *$1; +]]) define([COLOR_STOP],[ ]) define([REF_STOPS_RADIAL],)
--- a/tools/mb_c_source.m4 Thu Jan 15 02:15:35 2009 +0800 +++ b/tools/mb_c_source.m4 Thu Jan 15 16:46:47 2009 +0800 @@ -20,6 +20,7 @@ define([ADD_RECT]) define([ADD_COORD]) define([ADD_TEXT],) +define([ADD_IMAGE],) define([FILL_SHAPE]) define([STROKE_SHAPE]) define([FILL_SHAPE_WITH_PAINT])
--- a/tools/svg2code.py Thu Jan 15 02:15:35 2009 +0800 +++ b/tools/svg2code.py Thu Jan 15 16:46:47 2009 +0800 @@ -369,6 +369,7 @@ pass pass +@check_mbname def translate_text(text, coord_id, codefo, doc): translate_font_style(text, codefo) @@ -394,6 +395,42 @@ pass pass +@check_mbname +def translate_image(image, coord_id, codefo, doc): + image_id = _get_id(image) + if not image.hasAttribute('href'): + raise ValueError, 'image %s must has a href attribute.' % (image_id) + href = image.getAttribute('href') + if image.hasAttribute('x'): + x_str = image.getAttribute('x') + x = int(x_str) + else: + x = 0 + pass + if image.hasAttribute('y'): + y_str = image.getAttribute('y') + y = int(y_str) + else: + y = 0 + pass + if image.hasAttribute('width'): + width_str = image.getAttribute('width') + width = int(width_str) + else: + width = -1 + pass + if image.hasAttribute('height'): + height_str = image.getAttribute('height') + height = int(height_str) + else: + height = -1 + pass + print >> codefo, 'dnl' + print >> codefo, \ + 'ADD_IMAGE([%s], [%s], %f, %f, %f, %f)dnl' % ( + image_id, href, x, y, width, height) + pass + reo_func = re.compile('([a-zA-Z]+)\\([^\\)]*\\)') reo_translate = re.compile('translate\\(([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)\\)') reo_matrix = re.compile('matrix\\(([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)\\)') @@ -448,6 +485,8 @@ translate_rect(node, group_id, codefo, doc) elif node.localName == 'text': translate_text(node, group_id, codefo, doc) + elif node.localName == 'image': + translate_image(node, group_id, codefo, doc) pass pass pass