Mercurial > MadButterfly
comparison src/event.c @ 250:bd8ea44b421e
Fix bug and finish unit test for collision testing in event.c.
- mock for cairo, rdman, coord, and shape should be refactoried to a module.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Sun, 04 Jan 2009 11:42:32 +0800 |
parents | 104d83378582 |
children | f08b3ba9c1d8 |
comparison
equal
deleted
inserted
replaced
245:81458bb0bf34 | 250:bd8ea44b421e |
---|---|
19 | 19 |
20 #define ASSERT(x) | 20 #define ASSERT(x) |
21 | 21 |
22 #ifdef UNITTEST | 22 #ifdef UNITTEST |
23 /* ============================================================ */ | 23 /* ============================================================ */ |
24 #include <string.h> | |
25 #include "mb_tools.h" | |
26 | |
27 typedef float co_aix; | |
24 | 28 |
25 typedef struct shape shape_t; | 29 typedef struct shape shape_t; |
30 typedef struct cairo_surface cairo_surface_t; | |
31 typedef struct coord coord_t; | |
26 | 32 |
27 typedef struct cairo cairo_t; | 33 typedef struct cairo cairo_t; |
28 struct cairo { | 34 struct cairo { |
29 shape_t *drawed; | 35 STAILQ(shape_t) drawed; |
36 STAILQ(shape_t) clip_pathes; | |
37 cairo_surface_t *tgt; | |
30 }; | 38 }; |
31 #define cairo_in_fill(cr, x, y) 0 | 39 |
32 #define cairo_in_stroke(cr, x, y) 0 | 40 struct cairo_surface { |
33 #define cairo_new_path(cr) | 41 cairo_t *cr; |
34 #define cairo_get_target(cr) NULL | 42 int w, h; |
35 #define cairo_create(target) NULL | 43 unsigned char *data; |
36 #define cairo_destroy(cr) | 44 }; |
37 #define cairo_clip(cr) | 45 |
46 #define cairo_new_path(cr) do { STAILQ_CLEAN((cr)->drawed); } while(0) | |
47 #define cairo_get_target(cr) (cr)->tgt | |
48 static | |
49 cairo_t *cairo_create(cairo_surface_t *target) { | |
50 cairo_t *cr; | |
51 | |
52 cr = (cairo_t *)malloc(sizeof(cairo_t)); | |
53 STAILQ_INIT(cr->drawed); | |
54 STAILQ_INIT(cr->clip_pathes); | |
55 cr->tgt = target; | |
56 target->cr = cr; | |
57 | |
58 return cr; | |
59 } | |
60 #define cairo_destroy(cr) do { free(cr); } while(0) | |
61 #define cairo_clip(cr) \ | |
62 do { \ | |
63 memcpy(&(cr)->clip_pathes, \ | |
64 &(cr)->drawed, \ | |
65 sizeof((cr)->drawed)); \ | |
66 STAILQ_CLEAN((cr)->drawed); \ | |
67 } while(0) | |
38 #define cairo_fill(cr) | 68 #define cairo_fill(cr) |
39 #define cairo_image_surface_get_data(cr) NULL | 69 |
40 #define cairo_image_surface_get_stride(cr) 1 | 70 #define cairo_image_surface_get_width(surface) (surface)->w |
41 | 71 #define cairo_image_surface_get_height(surface) (surface)->h |
42 struct cairo_surface { | 72 static |
43 }; | 73 cairo_surface_t *cairo_image_surface_create(int format, int w, int h) { |
44 typedef struct cairo_surface cairo_surface_t; | 74 cairo_surface_t *surf; |
45 #define cairo_image_surface_get_width(surface) 0 | 75 |
46 #define cairo_image_surface_get_height(surface) 0 | 76 surf = (cairo_surface_t *)malloc(sizeof(cairo_surface_t)); |
47 #define cairo_image_surface_create(surface, w, h) NULL | 77 surf->w = w; |
48 #define cairo_surface_destroy(surface) | 78 surf->h = h; |
49 | 79 surf->data = (unsigned char *)malloc(h); |
50 | 80 memset(surf->data, 0, h); |
51 typedef float co_aix; | 81 |
82 return surf; | |
83 } | |
84 #define cairo_surface_destroy(surface) \ | |
85 do { free((surface)->data); free(surface); } while(0) | |
86 #define cairo_image_surface_get_stride(surface) 1 | |
87 #define CAIRO_FORMAT_A1 1 | |
88 | |
52 | 89 |
53 typedef struct _area area_t; | 90 typedef struct _area area_t; |
54 struct _area { | 91 struct _area { |
55 co_aix x, y; | 92 co_aix x, y; |
56 co_aix w, h; | 93 co_aix w, h; |
57 }; | 94 }; |
58 #define range_overlay(as, aw, bs, bw) \ | 95 #define area_set(area, _x, _y, _w, _h) \ |
59 (((bs) - (as)) <= (aw) || ((as) - (bs)) <= (bw)) | 96 do { \ |
97 (area)->x = (_x); \ | |
98 (area)->y = (_y); \ | |
99 (area)->w = (_w); \ | |
100 (area)->h = (_h); \ | |
101 } while(0) | |
102 #define _in_range(a, s, w) ((a) >= (s) && (a) < ((s) + (w))) | |
103 #define _range_overlay(as, aw, bs, bw) \ | |
104 (_in_range(as, bs, bw) || _in_range(bs, as, aw)) | |
60 #define areas_are_overlay(a1, a2) \ | 105 #define areas_are_overlay(a1, a2) \ |
61 (range_overlay((a1)->x, (a1)->w, \ | 106 (_range_overlay((a1)->x, (a1)->w, \ |
62 (a2)->x, (a2)->w) && \ | 107 (a2)->x, (a2)->w) && \ |
63 range_overlay((a1)->y, (a1)->h, \ | 108 _range_overlay((a1)->y, (a1)->h, \ |
64 (a2)->y, (a2)->h)) | 109 (a2)->y, (a2)->h)) |
110 #define area_pos_is_in(area, _x, _y) \ | |
111 (_in_range(_x, (area)->x, (area)->w) && \ | |
112 _in_range(_y, (area)->y, (area)->h)) | |
113 #define _range_extent(a, s, w) \ | |
114 do { \ | |
115 if((a) < (s)) { \ | |
116 (w) += (s) - (a); \ | |
117 (s) = (a); \ | |
118 } else { \ | |
119 (w) = MAX(w, (a) - (s) + 1); \ | |
120 } \ | |
121 } while(0) | |
122 | |
123 static | |
124 void area_extent(area_t *area, co_aix x, co_aix y) { | |
125 _range_extent(x, area->x, area->w); | |
126 _range_extent(y, area->y, area->h); | |
127 } | |
65 | 128 |
66 struct mb_obj { | 129 struct mb_obj { |
67 int obj_type; | 130 int obj_type; |
68 }; | 131 }; |
69 typedef struct mb_obj mb_obj_t; | 132 typedef struct mb_obj mb_obj_t; |
133 #define MB_OBJ_INIT(obj, type) do { (obj)->obj_type = type; } while(0) | |
70 | 134 |
71 #define GEF_OV_DRAW 0x1 | 135 #define GEF_OV_DRAW 0x1 |
72 #define GEF_HIDDEN 0x2 | 136 #define GEF_HIDDEN 0x2 |
73 | 137 |
74 struct shape { | 138 struct shape { |
75 mb_obj_t obj; | 139 mb_obj_t obj; |
76 | 140 |
141 coord_t *coord; | |
77 area_t area; | 142 area_t area; |
143 shape_t *all_next; | |
144 shape_t *drawed_next; | |
78 | 145 |
79 void *fill, *stroke; | 146 void *fill, *stroke; |
80 struct shape *sibling; | 147 struct shape *sibling; |
81 int flags; | 148 int flags; |
82 | 149 |
104 #define sh_get_flags(shape, mask) ((shape)->flags & mask) | 171 #define sh_get_flags(shape, mask) ((shape)->flags & mask) |
105 #define sh_set_flags(shape, mask) do { (shape)->flags |= mask; } while(0) | 172 #define sh_set_flags(shape, mask) do { (shape)->flags |= mask; } while(0) |
106 #define sh_clear_flags(shape, mask) do { (shape)->flags &= ~(mask); } while(0) | 173 #define sh_clear_flags(shape, mask) do { (shape)->flags &= ~(mask); } while(0) |
107 #define sh_get_area(shape) (&(shape)->area) | 174 #define sh_get_area(shape) (&(shape)->area) |
108 | 175 |
109 typedef struct coord coord_t; | |
110 struct coord { | 176 struct coord { |
111 mb_obj_t obj; | 177 mb_obj_t obj; |
112 | 178 |
113 area_t area; | 179 area_t area; |
114 int flags; | 180 int flags; |
115 coord_t *parent; | 181 coord_t *parent; |
116 coord_t *children; | 182 STAILQ(coord_t) children; |
117 coord_t *sibling; | 183 coord_t *sibling; |
118 shape_t *shapes; | 184 STAILQ(shape_t) shapes; |
119 }; | 185 }; |
120 | 186 |
121 #define COF_SKIP 0x1 | 187 #define COF_SKIP 0x1 |
122 | 188 |
123 #define coord_get_area(coord) (&(coord)->area) | 189 #define coord_get_area(coord) (&(coord)->area) |
124 #define FOR_COORD_SHAPES(coord, shape) \ | 190 #define FOR_COORD_SHAPES(coord, shape) \ |
125 for(shape = (coord)->shapes; \ | 191 for((shape) = STAILQ_HEAD((coord)->shapes); \ |
126 shape != NULL; \ | 192 (shape) != NULL; \ |
127 shape = (shape)->sibling) | 193 (shape) = STAILQ_NEXT(shape_t, sibling, shape)) |
128 #define FOR_COORDS_PREORDER(root, last) \ | 194 #define FOR_COORDS_PREORDER(root, last) \ |
129 for(last = root; \ | 195 for((last) = (root); \ |
130 last != NULL; \ | 196 (last) != NULL; \ |
131 last = preorder_coord_subtree(root, last)) | 197 (last) = preorder_coord_subtree(root, last)) |
198 #define FOR_COORD_CHILDREN(parent, child) \ | |
199 for((child) = STAILQ_HEAD((parent)->children); \ | |
200 (child) != NULL; \ | |
201 (child) = STAILQ_NEXT(coord_t, sibling, child)) | |
202 | |
203 static | |
204 void _areas_merge(area_t *area1, area_t *area2) { | |
205 co_aix lu_x, lu_y; | |
206 co_aix rb_x, rb_y; | |
207 | |
208 lu_x = area2->x; | |
209 lu_y = area2->y; | |
210 rb_x = lu_x + area2->w - 1; | |
211 rb_y = lu_y + area2->h - 1; | |
212 area_extent(area1, lu_x, lu_y); | |
213 area_extent(area1, rb_x, rb_y); | |
214 } | |
215 | |
216 static | |
217 void coord_update_area(coord_t *coord) { | |
218 area_t *area; | |
219 shape_t *shape; | |
220 coord_t *child; | |
221 area_t *cur_area; | |
222 | |
223 area = coord_get_area(coord); | |
224 | |
225 shape = STAILQ_HEAD(coord->shapes); | |
226 if(shape != NULL) { | |
227 cur_area = sh_get_area(shape); | |
228 } else { | |
229 child = STAILQ_HEAD(coord->children); | |
230 if(child == NULL) | |
231 return; | |
232 cur_area = coord_get_area(child); | |
233 } | |
234 memcpy(area, cur_area, sizeof(area_t)); | |
235 | |
236 FOR_COORD_SHAPES(coord, shape) { | |
237 cur_area = sh_get_area(shape); | |
238 _areas_merge(area, cur_area); | |
239 } | |
240 | |
241 FOR_COORD_CHILDREN(coord, child) { | |
242 cur_area = coord_get_area(child); | |
243 _areas_merge(area, cur_area); | |
244 } | |
245 } | |
246 | |
247 static | |
248 void coord_update_area_ancestors(coord_t *coord) { | |
249 coord_t *cur; | |
250 | |
251 for(cur = coord; cur != NULL; cur = cur->parent) { | |
252 coord_update_area(cur); | |
253 } | |
254 } | |
132 | 255 |
133 static | 256 static |
134 coord_t *preorder_coord_subtree(coord_t *root, coord_t *last) { | 257 coord_t *preorder_coord_subtree(coord_t *root, coord_t *last) { |
135 if(last->children) | 258 if(STAILQ_HEAD(last->children) && !(last->flags & COF_SKIP)) |
136 return last->children; | 259 return STAILQ_HEAD(last->children); |
137 while(last->sibling == NULL) | 260 if(last == root) |
261 return NULL; | |
262 while(STAILQ_NEXT(coord_t, sibling, last) == NULL) { | |
263 if(last == root) | |
264 return NULL; | |
138 last = last->parent; | 265 last = last->parent; |
139 return last->sibling; | 266 } |
267 return STAILQ_NEXT(coord_t, sibling, last); | |
268 } | |
269 | |
270 static | |
271 void preorder_coord_skip_subtree(coord_t *coord) { | |
272 coord->flags &= ~COF_SKIP; | |
140 } | 273 } |
141 | 274 |
142 static | 275 static |
143 coord_t *postorder_coord_subtree(coord_t *root, coord_t *last) { | 276 coord_t *postorder_coord_subtree(coord_t *root, coord_t *last) { |
144 coord_t *cur; | 277 coord_t *cur; |
145 | 278 |
146 if(last != NULL) { | 279 if(last != NULL) { |
147 if(last->sibling == NULL) { | 280 if(STAILQ_NEXT(coord_t, sibling, last) == NULL) { |
281 if(cur == root) | |
282 return NULL; | |
148 cur = last->parent; | 283 cur = last->parent; |
149 return cur; | 284 return cur; |
150 } | 285 } |
151 cur = last->sibling; | 286 cur = STAILQ_NEXT(coord_t, sibling, last); |
152 } | 287 } |
153 | 288 |
154 cur = last; | 289 cur = root; |
155 while(cur->children) { | 290 while(STAILQ_HEAD(cur->children)) { |
156 cur = cur->children; | 291 cur = STAILQ_HEAD(cur->children); |
157 } | 292 } |
158 return cur; | 293 return cur; |
159 } | 294 } |
160 | 295 |
161 #define sh_path_draw(path, cr) | 296 static |
162 #define sh_text_draw(path, cr) | 297 void shape_draw(shape_t *sh, cairo_t *cr) { |
163 #define sh_rect_draw(path, cr) | 298 STAILQ_INS_TAIL(cr->drawed, shape_t, drawed_next, sh); |
299 } | |
300 | |
301 #define sh_path_draw(path, cr) shape_draw((shape_t *)path, cr) | |
302 #define sh_text_draw(text, cr) shape_draw((shape_t *)text, cr) | |
303 #define sh_rect_draw(rect, cr) shape_draw((shape_t *)rect, cr) | |
304 static | |
305 void sh_update_area(shape_t *sh) { | |
306 int i; | |
307 co_aix x, y; | |
308 area_t *area = &sh->area; | |
309 | |
310 if(sh->num_points == 0) { | |
311 area_set(area, 0, 0, 0, 0); | |
312 return; | |
313 } | |
314 | |
315 area_set(area, sh->points[0][0], sh->points[0][1], 1, 1); | |
316 for(i = 1; i < sh->num_points; i++) { | |
317 x = sh->points[i][0]; | |
318 y = sh->points[i][1]; | |
319 area_extent(area, x, y); | |
320 } | |
321 } | |
164 | 322 |
165 | 323 |
166 struct redraw_man { | 324 struct redraw_man { |
167 cairo_t *cr; | 325 cairo_t *cr; |
326 coord_t *root_coord; | |
168 int shape_gl_sz; | 327 int shape_gl_sz; |
169 shape_t *shape_gl[32]; | 328 shape_t *shape_gl[32]; |
329 STAILQ(shape_t) all_shapes; | |
170 }; | 330 }; |
171 typedef struct redraw_man redraw_man_t; | 331 typedef struct redraw_man redraw_man_t; |
172 #define rdman_get_cr(rdman) ((rdman)->cr) | 332 #define rdman_get_cr(rdman) ((rdman)->cr) |
173 #define rdman_get_gen_geos(rdman) (&(rdman)->gen_geos) | |
174 #define rdman_force_clean(rdman) OK | 333 #define rdman_force_clean(rdman) OK |
175 #define rdman_geos(rdman, geo) NULL | 334 #define rdman_clear_shape_gl(rdman) do {(rdman)->shape_gl_sz = 0; } while(0) |
176 #define rdman_clear_shape_gl(rdman) \ | |
177 do {(rdman)->shape_gl_sz = 0; } while(0) | |
178 static int rdman_add_shape_gl(redraw_man_t *rdman, shape_t *shape) { | 335 static int rdman_add_shape_gl(redraw_man_t *rdman, shape_t *shape) { |
179 (rdman)->shape_gl[(rdman)->shape_gl_sz++] = shape; | 336 (rdman)->shape_gl[(rdman)->shape_gl_sz++] = shape; |
180 return OK; | 337 return OK; |
181 } | 338 } |
182 #define rdman_get_shape_gl(rdman, idx) \ | 339 #define rdman_get_shape_gl(rdman, idx) \ |
183 (rdman)->shape_gl[idx] | 340 (rdman)->shape_gl[idx] |
184 #define rdman_shape_gl_len(rdman) (rdman)->shape_gl_sz | 341 #define rdman_shape_gl_len(rdman) (rdman)->shape_gl_sz |
185 static shape_t *rdman_shapes(redraw_man_t *rdman, shape_t *last_shape); | 342 static shape_t *rdman_shapes(redraw_man_t *rdman, shape_t *last_shape) { |
186 | 343 if(last_shape == NULL) |
187 | 344 return STAILQ_HEAD(rdman->all_shapes); |
345 | |
346 return STAILQ_NEXT(shape_t, all_next, last_shape); | |
347 } | |
348 #define redraw_man_init(rdman, cr, backend) \ | |
349 do { \ | |
350 memset(rdman, 0, sizeof(redraw_man_t)); \ | |
351 (rdman)->cr = cr; \ | |
352 (rdman)->root_coord = rdman_coord_new_noparent(rdman); \ | |
353 } while(0) | |
354 #define redraw_man_destroy(rdman) \ | |
355 do { \ | |
356 free(rdman); \ | |
357 } while(0) | |
358 #define rdman_get_root(rdman) ((rdman)->root_coord) | |
359 | |
360 static coord_t *rdman_coord_new_noparent(redraw_man_t *rdman); | |
361 | |
362 static | |
363 redraw_man_t *redraw_man_new(cairo_t *cr, cairo_t *backend) { | |
364 redraw_man_t *rdman; | |
365 | |
366 rdman = O_ALLOC(redraw_man_t); | |
367 redraw_man_init(rdman, cr, backend); | |
368 return rdman; | |
369 } | |
370 #define redraw_man_free(rdman) \ | |
371 do { \ | |
372 redraw_man_destroy(rdman); \ | |
373 free(rdman); \ | |
374 } while(0) | |
375 | |
376 static | |
377 int cairo_in_fill(cairo_t *cr, int x, int y) { | |
378 shape_t *shape; | |
379 int i; | |
380 | |
381 for(shape = STAILQ_HEAD(cr->drawed); | |
382 shape != NULL; | |
383 shape = STAILQ_NEXT(shape_t, drawed_next, shape)) { | |
384 for(i = 0; i < shape->num_points; i++) | |
385 if(shape->points[i][0] == x && | |
386 shape->points[i][1] == y) | |
387 return 1; | |
388 } | |
389 return 0; | |
390 } | |
391 | |
392 #define cairo_in_stroke cairo_in_fill | |
393 | |
394 static | |
395 void rdman_coord_init_noparent(redraw_man_t *rdman, coord_t *co) { | |
396 memset(co, 0, sizeof(coord_t)); | |
397 MB_OBJ_INIT(&co->obj, MBO_COORD); | |
398 STAILQ_INIT(co->children); | |
399 STAILQ_INIT(co->shapes); | |
400 } | |
401 | |
402 static | |
403 void rdman_coord_init(redraw_man_t *rdman, coord_t *co, coord_t *parent) { | |
404 rdman_coord_init_noparent(rdman, co); | |
405 STAILQ_INS_TAIL(parent->children, coord_t, sibling, co); | |
406 co->parent = parent; | |
407 } | |
408 | |
409 static | |
410 coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) { | |
411 coord_t *coord; | |
412 | |
413 coord = O_ALLOC(coord_t); | |
414 rdman_coord_init(rdman, coord, parent); | |
415 | |
416 return coord; | |
417 } | |
418 | |
419 coord_t *rdman_coord_new_noparent(redraw_man_t *rdman) { | |
420 coord_t *coord; | |
421 | |
422 coord = O_ALLOC(coord_t); | |
423 rdman_coord_init_noparent(rdman, coord); | |
424 | |
425 return coord; | |
426 } | |
427 | |
428 static | |
429 void rdman_coord_free(redraw_man_t *rdman, coord_t *coord) { | |
430 free(coord); | |
431 } | |
432 | |
433 static | |
434 shape_t *rdman_shape_new(redraw_man_t *rdman) { | |
435 shape_t *shape; | |
436 | |
437 shape = O_ALLOC(shape_t); | |
438 memset(shape, 0, sizeof(shape_t)); | |
439 MB_OBJ_INIT(&shape->obj, MBO_PATH); | |
440 STAILQ_INS(rdman->all_shapes, shape_t, all_next, shape); | |
441 | |
442 return shape; | |
443 } | |
444 | |
445 static | |
446 void rdman_shape_free(redraw_man_t *rdman, shape_t *shape) { | |
447 STAILQ_REMOVE(rdman->all_shapes, shape_t, all_next, shape); | |
448 free(shape); | |
449 } | |
450 | |
451 #define shape_add_point(shape, x, y) \ | |
452 do { \ | |
453 (shape)->points[(shape)->num_points][0] = x; \ | |
454 (shape)->points[(shape)->num_points][1] = y; \ | |
455 (shape)->num_points++; \ | |
456 sh_update_area(shape); \ | |
457 if((shape)->coord) \ | |
458 coord_update_area_ancestors((shape)->coord); \ | |
459 } while(0) | |
460 | |
461 static | |
462 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, | |
463 coord_t *parent) { | |
464 STAILQ_INS_TAIL(parent->shapes, shape_t, sibling, shape); | |
465 shape->coord = parent; | |
466 | |
467 return OK; | |
468 } | |
469 | |
470 static | |
471 void *cairo_image_surface_get_data(cairo_surface_t *surf) { | |
472 cairo_t *cr; | |
473 shape_t *shape1, *shape2; | |
474 co_aix x1, y1, x2, y2; | |
475 int i, j; | |
476 | |
477 cr = surf->cr; | |
478 | |
479 STAILQ_FOR_EACH(cr->drawed, shape_t, sibling, shape1) { | |
480 for(i = 0; i < shape1->num_points; i++) { | |
481 x1 = shape1->points[i][0]; | |
482 y1 = shape1->points[i][1]; | |
483 STAILQ_FOR_EACH(cr->clip_pathes, shape_t, sibling, shape2) { | |
484 for(j = 0; j < shape2->num_points; j++) { | |
485 x2 = shape2->points[j][0]; | |
486 y2 = shape2->points[j][1]; | |
487 if(x1 == x2 && y1 == y2) { | |
488 surf->data[0] = 1; | |
489 return surf->data; | |
490 } | |
491 } | |
492 } | |
493 } | |
494 } | |
495 surf->data[0] = 0; | |
496 return surf->data; | |
497 } | |
188 /* ============================================================ */ | 498 /* ============================================================ */ |
189 #endif /* UNITTEST */ | 499 #endif /* UNITTEST */ |
190 | 500 |
191 | 501 |
192 static int _collect_shapes_at_point(redraw_man_t *rdman, | 502 static int _collect_shapes_at_point(redraw_man_t *rdman, |
301 */ | 611 */ |
302 int mb_obj_pos_is_in(redraw_man_t *rdman, mb_obj_t *obj, | 612 int mb_obj_pos_is_in(redraw_man_t *rdman, mb_obj_t *obj, |
303 co_aix x, co_aix y, int *in_stroke) { | 613 co_aix x, co_aix y, int *in_stroke) { |
304 coord_t *cur_coord, *root; | 614 coord_t *cur_coord, *root; |
305 shape_t *shape; | 615 shape_t *shape; |
616 area_t *area; | |
306 int r; | 617 int r; |
307 | 618 |
308 if(IS_MBO_SHAPES(obj)) { | 619 if(IS_MBO_SHAPES(obj)) { |
309 shape = (shape_t *)obj; | 620 shape = (shape_t *)obj; |
310 r = _shape_pos_is_in(shape, x, y, in_stroke, rdman_get_cr(rdman)); | 621 r = _shape_pos_is_in(shape, x, y, in_stroke, rdman_get_cr(rdman)); |
311 return r; | 622 return r; |
312 } | 623 } |
313 root = (coord_t *)obj; | 624 root = (coord_t *)obj; |
314 for(cur_coord = postorder_coord_subtree(root, NULL); | 625 FOR_COORDS_PREORDER(root, cur_coord) { |
315 cur_coord != NULL; | 626 area = coord_get_area(cur_coord); |
316 cur_coord = postorder_coord_subtree(root, cur_coord)) { | 627 if(!area_pos_is_in(area, x, y)) { |
628 preorder_coord_skip_subtree(cur_coord); | |
629 continue; | |
630 } | |
317 FOR_COORD_SHAPES(cur_coord, shape) { | 631 FOR_COORD_SHAPES(cur_coord, shape) { |
318 r = _shape_pos_is_in(shape, x, y, in_stroke, rdman_get_cr(rdman)); | 632 r = _shape_pos_is_in(shape, x, y, in_stroke, rdman_get_cr(rdman)); |
319 if(r) | 633 if(r) |
320 return TRUE; | 634 return TRUE; |
321 } | 635 } |
527 #include <CUnit/Basic.h> | 841 #include <CUnit/Basic.h> |
528 | 842 |
529 static | 843 static |
530 redraw_man_t *_fake_rdman(void) { | 844 redraw_man_t *_fake_rdman(void) { |
531 redraw_man_t *rdman; | 845 redraw_man_t *rdman; |
532 cairo_surface_t *surface; | 846 cairo_t *cr, *backend; |
533 | 847 cairo_surface_t *surf; |
534 rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t)); | 848 |
535 surface = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | 849 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); |
536 rdman->cr = cairo_create(surface); | 850 cr = cairo_create(surf); |
537 DARRAY_INIT(&rdman->gen_geos); | 851 backend = cairo_create(surf); |
852 rdman = redraw_man_new(cr, backend); | |
853 | |
538 return rdman; | 854 return rdman; |
539 } | 855 } |
540 | 856 |
541 static | 857 static |
542 void _free_fake_rdman(redraw_man_t *rdman) { | 858 void _free_fake_rdman(redraw_man_t *rdman) { |
859 cairo_surface_destroy(rdman->cr->tgt); | |
543 cairo_destroy(rdman->cr); | 860 cairo_destroy(rdman->cr); |
544 DARRAY_DESTROY(&rdman->gen_geos); | |
545 free(rdman); | 861 free(rdman); |
546 } | 862 } |
547 | 863 |
548 static | 864 static |
549 void test_mb_obj_pos_is_in(void) { | 865 void test_mb_obj_pos_is_in(void) { |
550 redraw_man_t *rdman; | 866 redraw_man_t *rdman; |
551 mb_obj_t *obj; | 867 shape_t *shape; |
868 coord_t *root, *child_coord; | |
869 int in_stroke = 0; | |
870 int r; | |
552 | 871 |
553 rdman = _fake_rdman(); | 872 rdman = _fake_rdman(); |
554 CU_ASSERT(rdman != NULL); | 873 CU_ASSERT(rdman != NULL); |
555 | 874 |
875 root = rdman_get_root(rdman); | |
876 | |
877 child_coord = rdman_coord_new(rdman, root); | |
878 CU_ASSERT(child_coord != NULL); | |
879 | |
880 shape = rdman_shape_new(rdman); | |
881 CU_ASSERT(shape != NULL); | |
882 | |
883 rdman_add_shape(rdman, shape, child_coord); | |
884 | |
885 shape_add_point(shape, 3, 12); | |
886 | |
887 shape->fill = shape; | |
888 shape->stroke = shape; | |
889 | |
890 r = mb_obj_pos_is_in(rdman, (mb_obj_t *)shape, 3, 12, &in_stroke); | |
891 CU_ASSERT(r == TRUE); | |
892 | |
893 r = mb_obj_pos_is_in(rdman, (mb_obj_t *)shape, 3, 13, &in_stroke); | |
894 CU_ASSERT(r == FALSE); | |
895 | |
896 r = mb_obj_pos_is_in(rdman, (mb_obj_t *)root, 3, 12, &in_stroke); | |
897 CU_ASSERT(r == TRUE); | |
898 | |
899 r = mb_obj_pos_is_in(rdman, (mb_obj_t *)root, 4, 12, &in_stroke); | |
900 CU_ASSERT(r == FALSE); | |
901 | |
902 rdman_shape_free(rdman, shape); | |
556 _free_fake_rdman(rdman); | 903 _free_fake_rdman(rdman); |
557 } | 904 } |
558 | 905 |
559 static | 906 static |
560 void test_is_obj_objs_overlay(void) { | 907 void test_is_obj_objs_overlay(void) { |
908 redraw_man_t *rdman; | |
909 coord_t *root, *coord1, *coord2; | |
910 shape_t *shape1, *shape2, *shape3; | |
911 cairo_t *cr; | |
912 cairo_surface_t *surf; | |
913 int r; | |
914 | |
915 rdman = _fake_rdman(); | |
916 CU_ASSERT(rdman != NULL); | |
917 | |
918 root = rdman_get_root(rdman); | |
919 | |
920 coord1 = rdman_coord_new(rdman, root); | |
921 shape1 = rdman_shape_new(rdman); | |
922 rdman_add_shape(rdman, shape1, coord1); | |
923 | |
924 coord2 = rdman_coord_new(rdman, root); | |
925 shape2 = rdman_shape_new(rdman); | |
926 rdman_add_shape(rdman, shape2, coord2); | |
927 | |
928 shape3 = rdman_shape_new(rdman); | |
929 rdman_add_shape(rdman, shape3, coord2); | |
930 | |
931 shape_add_point(shape1, 3, 2); | |
932 shape_add_point(shape2, 5, 5); | |
933 shape_add_point(shape3, 4, 3); | |
934 | |
935 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
936 cr = cairo_create(surf); | |
937 r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)coord2, cr); | |
938 CU_ASSERT(!r); | |
939 cairo_destroy(cr); | |
940 cairo_surface_destroy(surf); | |
941 sh_clear_flags(coord2, GEF_OV_DRAW); | |
942 | |
943 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
944 cr = cairo_create(surf); | |
945 r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)coord2, cr); | |
946 CU_ASSERT(!r); | |
947 cairo_destroy(cr); | |
948 cairo_surface_destroy(surf); | |
949 sh_clear_flags(coord2, GEF_OV_DRAW); | |
950 | |
951 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
952 cr = cairo_create(surf); | |
953 r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape2, cr); | |
954 CU_ASSERT(!r); | |
955 cairo_destroy(cr); | |
956 cairo_surface_destroy(surf); | |
957 sh_clear_flags(shape2, GEF_OV_DRAW); | |
958 | |
959 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
960 cr = cairo_create(surf); | |
961 r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape2, cr); | |
962 CU_ASSERT(!r); | |
963 cairo_destroy(cr); | |
964 cairo_surface_destroy(surf); | |
965 sh_clear_flags(shape2, GEF_OV_DRAW); | |
966 | |
967 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
968 cr = cairo_create(surf); | |
969 r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape3, cr); | |
970 CU_ASSERT(!r); | |
971 cairo_destroy(cr); | |
972 cairo_surface_destroy(surf); | |
973 sh_clear_flags(shape3, GEF_OV_DRAW); | |
974 | |
975 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
976 cr = cairo_create(surf); | |
977 r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape3, cr); | |
978 CU_ASSERT(!r); | |
979 cairo_destroy(cr); | |
980 cairo_surface_destroy(surf); | |
981 sh_clear_flags(shape3, GEF_OV_DRAW); | |
982 | |
983 shape_add_point(shape1, 5, 5); | |
984 | |
985 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
986 cr = cairo_create(surf); | |
987 r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)coord2, cr); | |
988 CU_ASSERT(r); | |
989 cairo_destroy(cr); | |
990 cairo_surface_destroy(surf); | |
991 sh_clear_flags(coord2, GEF_OV_DRAW); | |
992 | |
993 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
994 cr = cairo_create(surf); | |
995 r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)coord2, cr); | |
996 CU_ASSERT(r); | |
997 cairo_destroy(cr); | |
998 cairo_surface_destroy(surf); | |
999 sh_clear_flags(coord2, GEF_OV_DRAW); | |
1000 | |
1001 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
1002 cr = cairo_create(surf); | |
1003 r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape2, cr); | |
1004 CU_ASSERT(r); | |
1005 cairo_destroy(cr); | |
1006 cairo_surface_destroy(surf); | |
1007 sh_clear_flags(shape2, GEF_OV_DRAW); | |
1008 | |
1009 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
1010 cr = cairo_create(surf); | |
1011 r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape2, cr); | |
1012 CU_ASSERT(r); | |
1013 cairo_destroy(cr); | |
1014 cairo_surface_destroy(surf); | |
1015 sh_clear_flags(shape2, GEF_OV_DRAW); | |
1016 | |
1017 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
1018 cr = cairo_create(surf); | |
1019 r = _is_obj_objs_overlay((mb_obj_t *)shape1, (mb_obj_t *)shape3, cr); | |
1020 CU_ASSERT(!r); | |
1021 cairo_destroy(cr); | |
1022 cairo_surface_destroy(surf); | |
1023 sh_clear_flags(shape3, GEF_OV_DRAW); | |
1024 | |
1025 surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 100, 100); | |
1026 cr = cairo_create(surf); | |
1027 r = _is_obj_objs_overlay((mb_obj_t *)coord1, (mb_obj_t *)shape3, cr); | |
1028 CU_ASSERT(r); | |
1029 cairo_destroy(cr); | |
1030 cairo_surface_destroy(surf); | |
1031 sh_clear_flags(shape3, GEF_OV_DRAW); | |
1032 | |
1033 rdman_shape_free(rdman, shape1); | |
1034 rdman_shape_free(rdman, shape2); | |
1035 rdman_shape_free(rdman, shape3); | |
1036 rdman_coord_free(rdman, coord1); | |
1037 rdman_coord_free(rdman, coord2); | |
1038 _free_fake_rdman(rdman); | |
561 } | 1039 } |
562 | 1040 |
563 static | 1041 static |
564 void test_mb_objs_are_overlay(void) { | 1042 void test_mb_objs_are_overlay(void) { |
1043 redraw_man_t *rdman; | |
1044 coord_t *root, *coord1, *coord2; | |
1045 shape_t *shape1, *shape2, *shape3; | |
1046 int r; | |
1047 | |
1048 rdman = _fake_rdman(); | |
1049 | |
1050 root = rdman_get_root(rdman); | |
1051 | |
1052 coord1 = rdman_coord_new(rdman, root); | |
1053 shape1 = rdman_shape_new(rdman); | |
1054 rdman_add_shape(rdman, shape1, coord1); | |
1055 | |
1056 coord2 = rdman_coord_new(rdman, root); | |
1057 shape2 = rdman_shape_new(rdman); | |
1058 rdman_add_shape(rdman, shape2, coord2); | |
1059 | |
1060 shape3 = rdman_shape_new(rdman); | |
1061 rdman_add_shape(rdman, shape3, coord2); | |
1062 | |
1063 shape_add_point(shape1, 3, 2); | |
1064 shape_add_point(shape2, 5, 5); | |
1065 shape_add_point(shape3, 4, 3); | |
1066 | |
1067 r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)coord2); | |
1068 CU_ASSERT(!r); | |
1069 | |
1070 r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)coord2); | |
1071 CU_ASSERT(!r); | |
1072 | |
1073 r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape2); | |
1074 CU_ASSERT(!r); | |
1075 | |
1076 r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape2); | |
1077 CU_ASSERT(!r); | |
1078 | |
1079 r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape3); | |
1080 CU_ASSERT(!r); | |
1081 | |
1082 r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape3); | |
1083 CU_ASSERT(!r); | |
1084 | |
1085 shape_add_point(shape1, 5, 5); | |
1086 | |
1087 r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)coord2); | |
1088 CU_ASSERT(r); | |
1089 | |
1090 r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)coord2); | |
1091 CU_ASSERT(r); | |
1092 | |
1093 r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape2); | |
1094 CU_ASSERT(r); | |
1095 | |
1096 r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape2); | |
1097 CU_ASSERT(r); | |
1098 | |
1099 r = mb_objs_are_overlay(rdman, (mb_obj_t *)shape1, (mb_obj_t *)shape3); | |
1100 CU_ASSERT(!r); | |
1101 | |
1102 r = mb_objs_are_overlay(rdman, (mb_obj_t *)coord1, (mb_obj_t *)shape3); | |
1103 CU_ASSERT(!r); | |
1104 | |
1105 _free_fake_rdman(rdman); | |
565 } | 1106 } |
566 | 1107 |
567 CU_pSuite get_event_suite(void) { | 1108 CU_pSuite get_event_suite(void) { |
568 CU_pSuite suite; | 1109 CU_pSuite suite; |
569 | 1110 |