Mercurial > MadButterfly
view src/event.c @ 386:12464f1138ae
[MadBuilder] Install template and configuration to mozpluggerrc
author | Ben Lau <xbenlau@gmail.com> |
---|---|
date | Fri, 10 Apr 2009 03:14:49 +0800 |
parents | 6c350fc92ae3 |
children | 7f7855df2af0 |
line wrap: on
line source
/*! \file * \brief Convenience functions for event relative work. */ #include <stdio.h> #include <stdlib.h> #ifndef UNITTEST #include <cairo.h> #include "mb_types.h" #include "mb_redraw_man.h" #include "mb_shapes.h" #endif #define OK 0 #define ERR -1 #define FALSE 0 #define TRUE 1 #define ARRAY_EXT_SZ 64 #define ASSERT(x) #ifdef UNITTEST /* ============================================================ */ #include <string.h> #include "mb_tools.h" typedef float co_aix; typedef struct shape shape_t; typedef struct cairo_surface cairo_surface_t; typedef struct coord coord_t; typedef struct cairo cairo_t; struct cairo { STAILQ(shape_t) drawed; STAILQ(shape_t) clip_pathes; cairo_surface_t *tgt; }; struct cairo_surface { cairo_t *cr; int w, h; unsigned char *data; }; #define cairo_new_path(cr) do { STAILQ_CLEAN((cr)->drawed); } while(0) #define cairo_get_target(cr) (cr)->tgt static cairo_t *cairo_create(cairo_surface_t *target) { cairo_t *cr; cr = (cairo_t *)malloc(sizeof(cairo_t)); STAILQ_INIT(cr->drawed); STAILQ_INIT(cr->clip_pathes); cr->tgt = target; target->cr = cr; return cr; } #define cairo_destroy(cr) do { free(cr); } while(0) #define cairo_clip(cr) \ do { \ memcpy(&(cr)->clip_pathes, \ &(cr)->drawed, \ sizeof((cr)->drawed)); \ STAILQ_CLEAN((cr)->drawed); \ } while(0) #define cairo_fill(cr) #define cairo_image_surface_get_width(surface) (surface)->w #define cairo_image_surface_get_height(surface) (surface)->h static cairo_surface_t *cairo_image_surface_create(int format, int w, int h) { cairo_surface_t *surf; surf = (cairo_surface_t *)malloc(sizeof(cairo_surface_t)); surf->w = w; surf->h = h; surf->data = (unsigned char *)malloc(h); memset(surf->data, 0, h); return surf; } #define cairo_surface_destroy(surface) \ do { free((surface)->data); free(surface); } while(0) #define cairo_image_surface_get_stride(surface) 1 #define CAIRO_FORMAT_A1 1 typedef struct _area area_t; struct _area { co_aix x, y; co_aix w, h; }; #define area_set(area, _x, _y, _w, _h) \ do { \ (area)->x = (_x); \ (area)->y = (_y); \ (area)->w = (_w); \ (area)->h = (_h); \ } while(0) #define _in_range(a, s, w) ((a) >= (s) && (a) < ((s) + (w))) #define _range_overlay(as, aw, bs, bw) \ (_in_range(as, bs, bw) || _in_range(bs, as, aw)) #define areas_are_overlay(a1, a2) \ (_range_overlay((a1)->x, (a1)->w, \ (a2)->x, (a2)->w) && \ _range_overlay((a1)->y, (a1)->h, \ (a2)->y, (a2)->h)) #define area_pos_is_in(area, _x, _y) \ (_in_range(_x, (area)->x, (area)->w) && \ _in_range(_y, (area)->y, (area)->h)) #define _range_extent(a, s, w) \ do { \ if((a) < (s)) { \ (w) += (s) - (a); \ (s) = (a); \ } else { \ (w) = MAX(w, (a) - (s) + 1); \ } \ } while(0) static void area_extent(area_t *area, co_aix x, co_aix y) { _range_extent(x, area->x, area->w); _range_extent(y, area->y, area->h); } struct mb_obj { int obj_type; }; typedef struct mb_obj mb_obj_t; #define MB_OBJ_INIT(obj, type) do { (obj)->obj_type = type; } while(0) #define GEF_OV_DRAW 0x1 #define GEF_HIDDEN 0x2 struct shape { mb_obj_t obj; coord_t *coord; area_t area; shape_t *all_next; shape_t *drawed_next; void *fill, *stroke; struct shape *sibling; int flags; int num_points; co_aix points[32][2]; }; enum { MBO_DUMMY, MBO_COORD, MBO_SHAPES=0x1000, MBO_PATH, MBO_TEXT, MBO_RECT }; #define MBO_TYPE(x) (((mb_obj_t *)(x))->obj_type) #define IS_MBO_SHAPES(x) (((mb_obj_t *)(x))->obj_type & MBO_SHAPES) #define sh_get_geo(x) ((x)->geo) static int sh_pos_is_in(shape_t *shape, co_aix x, co_aix y) { int i; for(i = 0; i < shape->num_points; i++) if(shape->points[i][0] == x && shape->points[i][1] == y) return TRUE; return FALSE; } #define sh_get_flags(shape, mask) ((shape)->flags & mask) #define sh_set_flags(shape, mask) do { (shape)->flags |= mask; } while(0) #define sh_clear_flags(shape, mask) do { (shape)->flags &= ~(mask); } while(0) #define sh_get_area(shape) (&(shape)->area) struct coord { mb_obj_t obj; area_t area; int flags; coord_t *parent; STAILQ(coord_t) children; coord_t *sibling; STAILQ(shape_t) shapes; }; #define COF_SKIP 0x1 #define coord_get_area(coord) (&(coord)->area) #define FOR_COORD_SHAPES(coord, shape) \ for((shape) = STAILQ_HEAD((coord)->shapes); \ (shape) != NULL; \ (shape) = STAILQ_NEXT(shape_t, sibling, shape)) #define FOR_COORDS_PREORDER(root, last) \ for((last) = (root); \ (last) != NULL; \ (last) = preorder_coord_subtree(root, last)) #define FOR_COORD_CHILDREN(parent, child) \ for((child) = STAILQ_HEAD((parent)->children); \ (child) != NULL; \ (child) = STAILQ_NEXT(coord_t, sibling, child)) static 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; rb_y = lu_y + area2->h - 1; area_extent(area1, lu_x, lu_y); area_extent(area1, rb_x, rb_y); } static void coord_update_area(coord_t *coord) { area_t *area; shape_t *shape; coord_t *child; area_t *cur_area; area = coord_get_area(coord); shape = STAILQ_HEAD(coord->shapes); if(shape != NULL) { cur_area = sh_get_area(shape); } else { child = STAILQ_HEAD(coord->children); if(child == NULL) return; 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); } FOR_COORD_CHILDREN(coord, child) { cur_area = coord_get_area(child); _areas_merge(area, cur_area); } } static void coord_update_area_ancestors(coord_t *coord) { coord_t *cur; for(cur = coord; cur != NULL; cur = cur->parent) { coord_update_area(cur); } } static 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) { if(last == root) return NULL; last = last->parent; } return STAILQ_NEXT(coord_t, sibling, last); } static void preorder_coord_skip_subtree(coord_t *coord) { coord->flags |= COF_SKIP; } 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) return NULL; cur = last->parent; return cur; } cur = STAILQ_NEXT(coord_t, sibling, last); } cur = root; while(STAILQ_HEAD(cur->children)) { cur = STAILQ_HEAD(cur->children); } return cur; } static void shape_draw(shape_t *sh, cairo_t *cr) { STAILQ_INS_TAIL(cr->drawed, shape_t, drawed_next, sh); } #define sh_path_draw(path, cr) shape_draw((shape_t *)path, cr) #define sh_text_draw(text, cr) shape_draw((shape_t *)text, cr) #define sh_rect_draw(rect, cr) shape_draw((shape_t *)rect, cr) static void sh_update_area(shape_t *sh) { int i; co_aix x, y; area_t *area = &sh->area; if(sh->num_points == 0) { area_set(area, 0, 0, 0, 0); return; } area_set(area, sh->points[0][0], sh->points[0][1], 1, 1); for(i = 1; i < sh->num_points; i++) { x = sh->points[i][0]; y = sh->points[i][1]; area_extent(area, x, y); } } struct redraw_man { cairo_t *cr; coord_t *root_coord; int shape_gl_sz; shape_t *shape_gl[32]; STAILQ(shape_t) all_shapes; }; typedef struct redraw_man redraw_man_t; #define rdman_get_cr(rdman) ((rdman)->cr) #define rdman_force_clean(rdman) OK #define rdman_clear_shape_gl(rdman) do {(rdman)->shape_gl_sz = 0; } while(0) static int rdman_add_shape_gl(redraw_man_t *rdman, shape_t *shape) { (rdman)->shape_gl[(rdman)->shape_gl_sz++] = shape; return OK; } #define rdman_get_shape_gl(rdman, idx) \ (rdman)->shape_gl[idx] #define rdman_shape_gl_len(rdman) (rdman)->shape_gl_sz static shape_t *rdman_shapes(redraw_man_t *rdman, shape_t *last_shape) { if(last_shape == NULL) return STAILQ_HEAD(rdman->all_shapes); return STAILQ_NEXT(shape_t, all_next, last_shape); } #define redraw_man_init(rdman, cr, backend) \ do { \ memset(rdman, 0, sizeof(redraw_man_t)); \ (rdman)->cr = cr; \ (rdman)->root_coord = rdman_coord_new_noparent(rdman); \ } while(0) #define redraw_man_destroy(rdman) \ do { \ free(rdman); \ } while(0) #define rdman_get_root(rdman) ((rdman)->root_coord) static coord_t *rdman_coord_new_noparent(redraw_man_t *rdman); static redraw_man_t *redraw_man_new(cairo_t *cr, cairo_t *backend) { redraw_man_t *rdman; rdman = O_ALLOC(redraw_man_t); redraw_man_init(rdman, cr, backend); return rdman; } #define redraw_man_free(rdman) \ do { \ redraw_man_destroy(rdman); \ free(rdman); \ } while(0) static int cairo_in_fill(cairo_t *cr, int x, int y) { shape_t *shape; int i; for(shape = STAILQ_HEAD(cr->drawed); shape != NULL; shape = STAILQ_NEXT(shape_t, drawed_next, shape)) { for(i = 0; i < shape->num_points; i++) if(shape->points[i][0] == x && shape->points[i][1] == y) return 1; } return 0; } #define cairo_in_stroke cairo_in_fill static void rdman_coord_init_noparent(redraw_man_t *rdman, coord_t *co) { memset(co, 0, sizeof(coord_t)); MB_OBJ_INIT(&co->obj, MBO_COORD); STAILQ_INIT(co->children); STAILQ_INIT(co->shapes); } static void rdman_coord_init(redraw_man_t *rdman, coord_t *co, coord_t *parent) { rdman_coord_init_noparent(rdman, co); STAILQ_INS_TAIL(parent->children, coord_t, sibling, co); co->parent = parent; } static coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) { coord_t *coord; coord = O_ALLOC(coord_t); rdman_coord_init(rdman, coord, parent); return coord; } coord_t *rdman_coord_new_noparent(redraw_man_t *rdman) { coord_t *coord; coord = O_ALLOC(coord_t); rdman_coord_init_noparent(rdman, coord); return coord; } static void rdman_coord_free(redraw_man_t *rdman, coord_t *coord) { free(coord); } static shape_t *rdman_shape_new(redraw_man_t *rdman) { shape_t *shape; shape = O_ALLOC(shape_t); 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; } static void rdman_shape_free(redraw_man_t *rdman, shape_t *shape) { STAILQ_REMOVE(rdman->all_shapes, shape_t, all_next, shape); free(shape); } #define shape_add_point(shape, x, y) \ do { \ (shape)->points[(shape)->num_points][0] = x; \ (shape)->points[(shape)->num_points][1] = y; \ (shape)->num_points++; \ sh_update_area(shape); \ if((shape)->coord) \ coord_update_area_ancestors((shape)->coord); \ } while(0) static int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *parent) { STAILQ_INS_TAIL(parent->shapes, shape_t, sibling, shape); shape->coord = parent; return OK; } static void *cairo_image_surface_get_data(cairo_surface_t *surf) { cairo_t *cr; shape_t *shape1, *shape2; co_aix x1, y1, x2, y2; 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]; y1 = shape1->points[i][1]; STAILQ_FOR_EACH(cr->clip_pathes, shape_t, sibling, shape2) { for(j = 0; j < shape2->num_points; j++) { x2 = shape2->points[j][0]; y2 = shape2->points[j][1]; if(x1 == x2 && y1 == y2) { surf->data[0] = 1; return surf->data; } } } } } surf->data[0] = 0; return surf->data; } /* ============================================================ */ #endif /* UNITTEST */ static int _collect_shapes_at_point(redraw_man_t *rdman, co_aix x, co_aix y) { shape_t *shape; int r; r = rdman_force_clean(rdman); if(r != OK) return ERR; rdman_clear_shape_gl(rdman); for(shape = rdman_shapes(rdman, (shape_t *)NULL); shape != NULL; shape = rdman_shapes(rdman, shape)) { if(sh_pos_is_in(shape, x, y)) { r = rdman_add_shape_gl(rdman, shape); if(r != 0) return ERR; } } return OK; } static void draw_shape_path(shape_t *shape, cairo_t *cr) { switch(MBO_TYPE(shape)) { case MBO_PATH: sh_path_draw(shape, cr); break; case MBO_TEXT: sh_text_draw(shape, cr); break; case MBO_RECT: sh_rect_draw(shape, cr); break; case MBO_IMAGE: sh_image_draw(shape, cr); break; } } static int _shape_pos_is_in_cairo(shape_t *shape, co_aix x, co_aix y, int *in_stroke, cairo_t *cr) { draw_shape_path(shape, cr); if(shape->fill) { if(cairo_in_fill(cr, x, y)) { *in_stroke = 0; return TRUE; } } if(shape->stroke) { if(cairo_in_stroke(cr, x, y)) { *in_stroke = 1; return TRUE; } } return FALSE; } static int _shape_pos_is_in(shape_t *shape, co_aix x, co_aix y, int *in_stroke, cairo_t *cr) { int r; r = sh_pos_is_in(shape, x, y); if(!r) return FALSE; r = _shape_pos_is_in_cairo(shape, x, y, in_stroke, cr); cairo_new_path(cr); if(!r) return FALSE; return TRUE; } static shape_t *_find_shape_in_pos(redraw_man_t *rdman, co_aix x, co_aix y, int *in_stroke) { shape_t *shape; cairo_t *cr; int i, r; 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)) continue; r = _shape_pos_is_in_cairo(shape, x, y, in_stroke, cr); if(r) return shape; } return NULL; } shape_t *find_shape_at_pos(redraw_man_t *rdman, co_aix x, co_aix y, int *in_stroke) { shape_t *shape; int r; r = _collect_shapes_at_point(rdman, x, y); if(r != OK) return NULL; shape = _find_shape_in_pos(rdman, x, y, in_stroke); return shape; } /*! \brief Test if an object and descendants cover the position * specified by x,y. * * \param in_stroke is x, y is on a stroke. */ int mb_obj_pos_is_in(redraw_man_t *rdman, mb_obj_t *obj, co_aix x, co_aix y, int *in_stroke) { coord_t *cur_coord, *root; shape_t *shape; area_t *area; int r; if(IS_MBO_SHAPES(obj)) { shape = (shape_t *)obj; r = _shape_pos_is_in(shape, x, y, in_stroke, rdman_get_cr(rdman)); return r; } root = (coord_t *)obj; FOR_COORDS_PREORDER(root, cur_coord) { area = coord_get_area(cur_coord); if(!area_pos_is_in(area, x, y)) { preorder_coord_skip_subtree(cur_coord); continue; } FOR_COORD_SHAPES(cur_coord, shape) { r = _shape_pos_is_in(shape, x, y, in_stroke, rdman_get_cr(rdman)); if(r) return TRUE; } } return FALSE; } static cairo_t * _prepare_cairo_for_testing(redraw_man_t *rdman) { cairo_surface_t *surface, *rdman_surface; cairo_t *cr; int w, h; rdman_surface = cairo_get_target(rdman_get_cr(rdman)); w = cairo_image_surface_get_width(rdman_surface); h = cairo_image_surface_get_height(rdman_surface); surface = cairo_image_surface_create(CAIRO_FORMAT_A1, w, h); if(surface == NULL) return NULL; cr = cairo_create(surface); if(cr == NULL) cairo_surface_destroy(surface); return cr; } static void _release_cairo_for_testing(cairo_t *cr) { cairo_destroy(cr); } static void _draw_to_mask(shape_t *shape, cairo_t *cr) { if(sh_get_flags(shape, GEF_OV_DRAW)) return; draw_shape_path(shape, cr); cairo_clip(cr); sh_set_flags(shape, GEF_OV_DRAW); } static int _fill_and_check(shape_t *shape, cairo_t *cr) { int h, stride; cairo_surface_t *surface; unsigned char *data; int i, sz; draw_shape_path(shape, cr); cairo_fill(cr); surface = cairo_get_target(cr); data = cairo_image_surface_get_data(surface); h = cairo_image_surface_get_height(surface); stride = cairo_image_surface_get_stride(surface); sz = stride * h; for(i = 0; i < sz; i++) { if(data[i]) return TRUE; } return FALSE; } /*! \brief Is a mb_obj_t overlaid with another mb_obj_t and * descendants. * * coord is relative less than shapes. Check areas of coord can * skip sub-trees and avoid useless heavy computation. For shapes, * it not only check overlay of area. It also check overlay by * actually drawing on a cairo surface. */ static int _is_obj_objs_overlay(mb_obj_t *obj, mb_obj_t *others_root, cairo_t *cr) { area_t *area, *candi_area; coord_t *coord, *candi_coord, *root; 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); } else { coord = (coord_t *)obj; 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; if(!obj_is_shape) return TRUE; _draw_to_mask(candi_shape, cr); r = _fill_and_check(shape, cr); return r; } ASSERT(IS_MBO_COORD(others_root)); root = (coord_t *)others_root; FOR_COORDS_PREORDER(root, candi_coord) { candi_area = coord_get_area(candi_coord); r = areas_are_overlay(area, candi_area); if(!r) { 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; if(!obj_is_shape) return TRUE; _draw_to_mask(candi_shape, cr); r = _fill_and_check(shape, cr); if(r) return TRUE; } } return FALSE; } static void _clear_ov_draw(mb_obj_t *obj) { coord_t *coord, *root; shape_t *shape; if(IS_MBO_SHAPES(obj)) { shape = (shape_t *)obj; sh_clear_flags(shape, GEF_OV_DRAW); return; } root = (coord_t *)obj; FOR_COORDS_PREORDER(root, coord) { FOR_COORD_SHAPES(coord, shape) { sh_clear_flags(shape, GEF_OV_DRAW); } } } /*! \brief Test if two objects are overlaid. * * \todo Detect overlay in better way with cairo. * \note This function cost heavy on CPU power. */ int mb_objs_are_overlay(redraw_man_t *rdman, mb_obj_t *obj1, mb_obj_t *obj2) { cairo_t *cr; area_t *area; shape_t *shape; coord_t *coord, *root; int r; cr = _prepare_cairo_for_testing(rdman); if(IS_MBO_SHAPES(obj1)) { shape = (shape_t *)obj1; r = _is_obj_objs_overlay(obj1, obj2, cr); goto out; } root = (coord_t *)obj1; FOR_COORDS_PREORDER(root, coord) { area = coord_get_area(coord); r = _is_obj_objs_overlay((mb_obj_t *)coord, obj2, cr); if(!r) { preorder_coord_skip_subtree(coord); continue; } FOR_COORD_SHAPES(coord, shape) { r = _is_obj_objs_overlay((mb_obj_t *)shape, obj2, cr); if(r) goto out; } } r = FALSE; out: _clear_ov_draw(obj2); /* marked by _is_obj_objs_overlay() */ _release_cairo_for_testing(cr); return r; } #ifdef UNITTEST #include <CUnit/Basic.h> static redraw_man_t *_fake_rdman(void) { redraw_man_t *rdman; cairo_t *cr, *backend; cairo_surface_t *surf; surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); backend = cairo_create(surf); rdman = redraw_man_new(cr, backend); return rdman; } static void _free_fake_rdman(redraw_man_t *rdman) { cairo_surface_destroy(rdman->cr->tgt); cairo_destroy(rdman->cr); free(rdman); } static void test_mb_obj_pos_is_in(void) { redraw_man_t *rdman; shape_t *shape; coord_t *root, *child_coord; int in_stroke = 0; int r; rdman = _fake_rdman(); CU_ASSERT(rdman != NULL); root = rdman_get_root(rdman); child_coord = rdman_coord_new(rdman, root); CU_ASSERT(child_coord != NULL); shape = rdman_shape_new(rdman); CU_ASSERT(shape != NULL); rdman_add_shape(rdman, shape, child_coord); shape_add_point(shape, 3, 12); shape->fill = shape; shape->stroke = shape; r = mb_obj_pos_is_in(rdman, (mb_obj_t *)shape, 3, 12, &in_stroke); CU_ASSERT(r == TRUE); r = mb_obj_pos_is_in(rdman, (mb_obj_t *)shape, 3, 13, &in_stroke); CU_ASSERT(r == FALSE); r = mb_obj_pos_is_in(rdman, (mb_obj_t *)root, 3, 12, &in_stroke); CU_ASSERT(r == TRUE); r = mb_obj_pos_is_in(rdman, (mb_obj_t *)root, 4, 12, &in_stroke); CU_ASSERT(r == FALSE); rdman_shape_free(rdman, shape); _free_fake_rdman(rdman); } static void test_is_obj_objs_overlay(void) { redraw_man_t *rdman; coord_t *root, *coord1, *coord2; shape_t *shape1, *shape2, *shape3; cairo_t *cr; cairo_surface_t *surf; int r; rdman = _fake_rdman(); CU_ASSERT(rdman != NULL); root = rdman_get_root(rdman); coord1 = rdman_coord_new(rdman, root); shape1 = rdman_shape_new(rdman); rdman_add_shape(rdman, shape1, coord1); coord2 = rdman_coord_new(rdman, root); shape2 = rdman_shape_new(rdman); rdman_add_shape(rdman, shape2, coord2); shape3 = rdman_shape_new(rdman); rdman_add_shape(rdman, shape3, coord2); shape_add_point(shape1, 3, 2); shape_add_point(shape2, 5, 5); shape_add_point(shape3, 4, 3); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)coord2, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(coord2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)coord2, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(coord2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape2, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape2, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape3, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape3, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape3, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape3, GEF_OV_DRAW); shape_add_point(shape1, 5, 5); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)coord2, cr); CU_ASSERT(r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(coord2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)coord2, cr); CU_ASSERT(r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(coord2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape2, cr); CU_ASSERT(r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape2, cr); CU_ASSERT(r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape2, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape3, cr); CU_ASSERT(!r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape3, GEF_OV_DRAW); surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); cr = cairo_create(surf); r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape3, cr); CU_ASSERT(r); cairo_destroy(cr); cairo_surface_destroy(surf); sh_clear_flags(shape3, GEF_OV_DRAW); rdman_shape_free(rdman, shape1); rdman_shape_free(rdman, shape2); rdman_shape_free(rdman, shape3); rdman_coord_free(rdman, coord1); rdman_coord_free(rdman, coord2); _free_fake_rdman(rdman); } static void test_mb_objs_are_overlay(void) { redraw_man_t *rdman; coord_t *root, *coord1, *coord2; shape_t *shape1, *shape2, *shape3; int r; rdman = _fake_rdman(); root = rdman_get_root(rdman); coord1 = rdman_coord_new(rdman, root); shape1 = rdman_shape_new(rdman); rdman_add_shape(rdman, shape1, coord1); coord2 = rdman_coord_new(rdman, root); shape2 = rdman_shape_new(rdman); rdman_add_shape(rdman, shape2, coord2); shape3 = rdman_shape_new(rdman); rdman_add_shape(rdman, shape3, coord2); shape_add_point(shape1, 3, 2); shape_add_point(shape2, 5, 5); shape_add_point(shape3, 4, 3); 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); } 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); CU_ADD_TEST(suite, test_is_obj_objs_overlay); CU_ADD_TEST(suite, test_mb_objs_are_overlay); return suite; } #endif /* UNITTEST */