Mercurial > MadButterfly
view include/mb_types.h @ 439:254854ed479c
Fix bug of _find_shape_in_pos().
It can not find a correct shape for a specified point.
Since it call _shape_pos_is_in_cairo() directly, cairo_new_path() is
not called to clear path after each calling for a shape. So, old path
would interference later testing. It should call _shape_pos_is_in()
instead of _shape_pos_is_in_cairo().
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Thu, 30 Jul 2009 15:42:47 +0800 |
parents | 27774b93521e |
children | 16116d84bc5e |
line wrap: on
line source
#ifndef __MB_TYPES_H_ #define __MB_TYPES_H_ #include <cairo.h> #include "mb_tools.h" #include "mb_observer.h" #include "mb_prop.h" typedef float co_aix; 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; typedef struct _mb_sprite mb_sprite_t; /*! \todo Replace cairo_t with canvas_t. */ typedef cairo_t canvas_t; struct _redraw_man; /* \defgroup mb_obj_grp Object type * @{ */ /*! \brief MadButterfly object. * * All objects (coord and shapes) should have mb_obj_t as first member * variable. obj_type is used to identify type of an object. Please, * use MBO_TYPE() to return this value. MBO_TYPE() will type-casting the * object to mb_obj_t and return obj_type. * * 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 * checking its type. */ struct _mb_obj { int obj_type; /*!< \brief Type of a MadButterfly object. */ mb_prop_store_t props; /*!< Initialized by rdman. */ }; enum { MBO_DUMMY, MBO_COORD, MBO_SHAPES=0x1000, /*! \note Don't touch this. */ MBO_PATH, MBO_TEXT, MBO_RECT, MBO_IMAGE, MBO_STEXT }; #define MBO_CLASS_MASK 0xf000 #define MBO_CLASS(x) (((mb_obj_t *)(x))->obj_type & MBO_CLASS_MASK) /*! \brief Return type of a MadBufferly object. */ #define MBO_TYPE(x) (((mb_obj_t *)(x))->obj_type) #define IS_MBO_SHAPES(obj) (MBO_CLASS(obj) == MBO_SHAPES) #define IS_MBO_COORD(obj) (MBO_TYPE(obj) == MBO_COORD) #define mb_obj_init(obj, type) \ do { \ ((mb_obj_t *)(obj))->obj_type = type; \ } while(0) #define mb_obj_destroy(obj) #define mb_obj_prop_store(obj) (&(obj)->props) /* @} */ /*! \brief Base of paint types. * * Paints should be freed by users by calling rdman_paint_free() of * the paint. * * To define a foo paint, it should define a rdman_paint_foo_new() * function. It return a paint object. * * \todo move member functions to a seperate structure and setup a * singleton for each paint type. */ struct _paint { int pnt_type; int flags; void (*prepare)(paint_t *paint, cairo_t *cr); void (*free)(struct _redraw_man *rdman, paint_t *paint); STAILQ(shnode_t) members; paint_t *pnt_next; /*!< \brief Collect all paints of a rdman. */ }; enum { MBP_DUMMY, MBP_COLOR, MBP_LINEAR, MBP_RADIAL, MBP_IMAGE }; #define PNTF_FREE 0x1 struct _shnode { shape_t *shape; 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 { #ifdef GEO_ORDER unsigned int order; #endif unsigned int flags; shape_t *shape; geo_t *coord_next; /*!< \brief Link all member geos together. */ area_t *cur_area, *last_area; area_t areas[2]; subject_t *mouse_event; }; #define GEF_DIRTY 0x1 #define GEF_HIDDEN 0x2 /*!< The geo is hidden. */ #define GEF_FREE 0x4 #define GEF_OV_DRAW 0x8 /*!< To flag drawed for a overlay testing. */ 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]); #define _in_range(a, s, w) ((a) >= (s) && (a) < ((s) + (w))) #define area_pos_is_in(area, _x, _y) \ (_in_range(_x, (area)->x, (area)->w) && \ _in_range(_y, (area)->y, (area)->h)) extern void geo_init(geo_t *g); extern void geo_from_positions(geo_t *g, int n_pos, co_aix pos[][2]); extern void geo_mark_overlay(geo_t *g, int n_others, geo_t **others, int *n_overlays, geo_t **overlays); #define geo_get_shape(g) ((g)->shape) #define geo_get_shape_safe(g) ((g)? (g)->shape: NULL) #define geo_set_shape(g, sh) do {(g)->shape = sh;} while(0) #define geo_pos_is_in(g, _x, _y) area_pos_is_in((g)->cur_area, _x, _y) #define geo_get_area(g) ((g)->cur_area) #define geo_get_flags(g, mask) ((g)->flags & (mask)) #define geo_set_flags(g, mask) do {(g)->flags |= mask;} while(0) #define geo_clear_flags(g, mask) do {(g)->flags &= ~(mask);} while(0) #define geo_get_coord(g) sh_get_coord(geo_get_shape(g)) /*! \defgroup coord Coordination * @{ */ typedef struct _coord coord_t; DARRAY(areas, area_t *); /*! \brief Canvas information for a coord. */ typedef struct _coord_canvas_info { coord_t *owner; /*!< Cached one or opacity == 1 */ canvas_t *canvas; areas_t dirty_areas; /*!< \brief Areas should be updated * in canvas. */ area_t aggr_dirty_areas[2]; /*!< Used to aggregate updates to parent. */ area_t cached_dirty_area; /*!< Used to dirty an area in cached space. */ area_t owner_mems_area; /*!< \brief The area is covered by members * of owner. */ } coord_canvas_info_t; /*! \brief A coordination system. * * It have a transform function defined by matrix to transform * coordination from source space to target space. * Source space is where the contained is drawed, and target space * is where the coordination of parent container of the element * represented by this coord object. * * \dot * digraph G { * graph [rankdir=LR]; * root -> child00 -> child10 -> child20 [label="children" color="blue"]; * child00 -> child01 -> child02 [label="sibling"]; * child10 -> child11 [label="sibling"]; * } * \enddot */ struct _coord { mb_obj_t obj; unsigned int order; unsigned int flags; /*!< \sa \ref coord_flags */ co_aix opacity; /*! Own one or inherit from an ancestor. * Setup it when clean coords. * \sa * - \ref COF_OWN_CANVAS * - \ref redraw */ coord_canvas_info_t *canvas_info; area_t *cur_area, *last_area; area_t areas[2]; co_aix matrix[6]; co_aix aggr_matrix[6]; struct _coord *parent; STAILQ(struct _coord) children; struct _coord *sibling; unsigned int before_pmem; /*!< \brief The coord is before nth member * of parent. */ int num_members; STAILQ(geo_t) members; /*!< \brief All geo_t members in this coord. */ subject_t *mouse_event; }; /*! \defgroup coord_flags Coord Flags * @{ */ #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. */ #define COF_SKIP_TRIVAL 0x8 /*!< temporary skip descendants * when trivaling. */ #define COF_FREE 0x10 #define COF_FAST_CACHE 0x20 /*!< \brief Cache raster image in fast way. * \sa \ref img_cache */ #define COF_PRECISE_CACHE 0x40 /*!< \brief Cache raster image in * precise way. * \sa \ref img_cache */ #define COF_CACHE_MASK 0x60 #define COF_ANCESTOR_CACHE 0x80 /*!< \brief One ancestor is cached. * \sa \ref img_cache */ #define COF_MUST_ZEROING 0x100 /*!< \sa \ref cache_imp */ #define COF_JUST_CLEAN 0x200 /*!< \brief This coord is just cleaned by * last clean. * It is used by clean_rdman_dirties(). */ #define COF_TEMP_MARK 0x400 /*!< \brief Temporary mark a coord. */ /* @} */ extern void matrix_mul(co_aix *m1, co_aix *m2, co_aix *dst); extern void matrix_trans_pos(co_aix *matrix, co_aix *x, co_aix *y); extern void coord_init(coord_t *co, coord_t *parent); extern void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y); extern co_aix coord_trans_size(coord_t *co, co_aix size); extern void compute_aggr_of_coord(coord_t *coord); extern void compute_aggr_of_cached_coord(coord_t *coord); extern void compute_reverse(co_aix *orig, co_aix *reverse); extern void update_aggr_matrix(coord_t *start); extern coord_t *preorder_coord_subtree(coord_t *root, coord_t *last); extern coord_t *postorder_coord_subtree(coord_t *root, coord_t *last); #define preorder_coord_skip_subtree(sub) \ do { (sub)->flags |= COF_SKIP_TRIVAL; } while(0) #define coord_hide(co) \ do { \ (co)->flags |= COF_HIDDEN; \ } while(0) #define coord_show(co) do { co->flags &= ~COF_HIDDEN; } while(0) #define coord_fast_cache(co) \ do { \ (co)->flags = \ ((co)->flags & ~COF_CACHE_MASK) | COF_FAST_CACHE; \ } while(0) #define coord_precise_cache(co) \ do { \ (co)->flags = \ ((co)->flags & ~COF_CACHE_MASK) | COF_PRECISE_CACHE; \ } while(0) #define coord_nocache(co) \ do { \ (co)->flags &= ~COF_CACHE_MASK; \ } while(0) #define coord_is_root(co) ((co)->parent == NULL) #define coord_is_cached(co) ((co)->flags & COF_CACHE_MASK) #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_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_aggr_matrix(coord) ((coord)->aggr_matrix) #define FOR_COORDS_POSTORDER(coord, cur) \ for((cur) = postorder_coord_subtree((coord), NULL); \ (cur) != NULL; \ (cur) = postorder_coord_subtree((coord), (cur))) #define FOR_COORDS_PREORDER(coord, cur) \ for((cur) = (coord); \ (cur) != NULL; \ (cur) = preorder_coord_subtree((coord), (cur))) /*! \brief Coord operation function * These functions are used to move and scale the coord_t. Programmers should use these functions instead of using the matrix directly. * The x,y,sx,sy are all in co_aix type. * */ #define coord_move(co,x,y) do {(co)->matrix[2] = (x); (co)->matrix[5] = (y);} while(0) #define coord_set_scalex(co,sx) do {(co)->matrix[0] = sx;} while(0) #define coord_set_scaley(co,sy) do {(co)->matrix[3] = sy;} while(0) #define coord_scalex(co) ((co)->matrix[0]) #define coord_scaley(co) ((co)->matrix[3]) #define coord_x(co) ((co)->matrix[2]) #define coord_y(co) ((co)->matrix[5]) #define FOR_COORD_MEMBERS(coord, geo) \ for(geo = STAILQ_HEAD((coord)->members); \ geo != NULL; \ geo = STAILQ_NEXT(geo_t, coord_next, geo)) #define FOR_COORD_SHAPES(coord, shape) \ for(shape = geo_get_shape_safe(STAILQ_HEAD((coord)->members)); \ shape != NULL; \ shape = geo_get_shape_safe(STAILQ_NEXT(geo_t, coord_next, \ sh_get_geo(shape)))) #define coord_get_area(coord) ((coord)->cur_area) #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) /* @} */ /*! \brief A grahpic shape. * * \dot * digraph G { * "shape" -> "coord"; * "shape" -> "geo"; * "geo" -> "shape"; * "coord" -> "shape" [label="members"] * "shape" -> "shape" [label="sibling"]; * } * \enddot */ struct _shape { mb_obj_t obj; geo_t *geo; coord_t *coord; paint_t *fill, *stroke; co_aix stroke_width; int stroke_linecap:2; int stroke_linejoin:2; struct _shape *sh_next; /*!< Link all shapes of a rdman together. */ void (*free)(shape_t *shape); }; /* enum { SHT_UNKNOW, SHT_PATH, SHT_TEXT, SHT_RECT }; */ #define sh_get_mouse_event_subject(sh) ((sh)->geo->mouse_event) #define sh_hide(sh) \ do { \ (sh)->geo->flags |= GEF_HIDDEN; \ } while(0) #define sh_show(sh) \ do { \ (sh)->geo->flags &= ~GEF_HIDDEN; \ } while(0) #define sh_get_geo(sh) ((sh)->geo) #define sh_get_geo_safe(sh) ((sh)? (sh)->geo: NULL) #define sh_get_flags(sh, mask) geo_get_flags(sh_get_geo(sh), mask) #define sh_set_flags(sh, mask) geo_set_flags(sh_get_geo(sh), mask) #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) #define sh_get_aggr_matrix(sh) (coord_get_aggr_matrix(sh_get_coord(sh))) #define sh_get_fill(sh) ((sh)->fill) #define sh_get_stroke(sh) ((sh)->stroke) /*! \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_ */