Mercurial > MadButterfly
comparison src/redraw_man.c @ 139:1695a4b02b14
Members of coords are geos instead of shapes, now.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 22 Sep 2008 19:22:57 +0800 |
parents | 9f4fc9ecfd1f |
children | 0de8fd11271e |
comparison
equal
deleted
inserted
replaced
138:9f4fc9ecfd1f | 139:1695a4b02b14 |
---|---|
13 */ | 13 */ |
14 | 14 |
15 #define OK 0 | 15 #define OK 0 |
16 #define ERR -1 | 16 #define ERR -1 |
17 | 17 |
18 #define ARRAY_EXT_SZ 64 | |
19 | |
18 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) | 20 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) |
19 | 21 |
20 #ifdef UNITTEST | 22 #ifdef UNITTEST |
21 typedef struct _sh_dummy sh_dummy_t; | 23 typedef struct _sh_dummy sh_dummy_t; |
22 | 24 |
69 static int add_dirty_geo(redraw_man_t *rdman, geo_t *geo) { | 71 static int add_dirty_geo(redraw_man_t *rdman, geo_t *geo) { |
70 int max_dirty_geos; | 72 int max_dirty_geos; |
71 int r; | 73 int r; |
72 | 74 |
73 if(rdman->n_dirty_geos >= rdman->max_dirty_geos) { | 75 if(rdman->n_dirty_geos >= rdman->max_dirty_geos) { |
74 max_dirty_geos = rdman->n_geos; | 76 max_dirty_geos = rdman->max_dirty_geos + ARRAY_EXT_SZ; |
75 r = extend_memblk((void **)&rdman->dirty_geos, | 77 r = extend_memblk((void **)&rdman->dirty_geos, |
76 sizeof(geo_t *) * rdman->n_dirty_geos, | 78 sizeof(geo_t *) * rdman->n_dirty_geos, |
77 sizeof(geo_t *) * max_dirty_geos); | 79 sizeof(geo_t *) * max_dirty_geos); |
78 if(r != OK) | 80 if(r != OK) |
79 return ERR; | 81 return ERR; |
90 | 92 |
91 if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { | 93 if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { |
92 /* every geo object and coord object can contribute 2 areas. | 94 /* every geo object and coord object can contribute 2 areas. |
93 * rdman_draw_area() may also contribute 1 area. | 95 * rdman_draw_area() may also contribute 1 area. |
94 */ | 96 */ |
95 max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2 + 1; | 97 max_dirty_areas = rdman->max_dirty_areas + ARRAY_EXT_SZ; |
96 r = extend_memblk((void **)&rdman->dirty_areas, | 98 r = extend_memblk((void **)&rdman->dirty_areas, |
97 sizeof(area_t *) * rdman->n_dirty_areas, | 99 sizeof(area_t *) * rdman->n_dirty_areas, |
98 sizeof(area_t *) * max_dirty_areas); | 100 sizeof(area_t *) * max_dirty_areas); |
99 if(r != OK) | 101 if(r != OK) |
100 return ERR; | 102 return ERR; |
245 * That coord and geo of shape objects are setted by user code | 247 * That coord and geo of shape objects are setted by user code |
246 * give user code a chance to collect coord and geo objects together | 248 * give user code a chance to collect coord and geo objects together |
247 * and gain interest of higher cache hit rate. | 249 * and gain interest of higher cache hit rate. |
248 */ | 250 */ |
249 | 251 |
250 /*! \brief Find out all affected shape objects. | |
251 * | |
252 * Find out all shape objects that are overalid with geo_t of | |
253 * a geometry changed object. | |
254 * | |
255 * Linear scan geo_t objects of all shape objects in all_shapes | |
256 * list of a redraw_man_t object. | |
257 */ | |
258 int rdman_find_overlaid_shapes(redraw_man_t *rdman, geo_t *geo, | |
259 geo_t ***overlays) { | |
260 int n_geos; | |
261 geo_t **geos; | |
262 geo_t *geo_cur; | |
263 int n_overlays; | |
264 geo_t **_overlays; | |
265 int i; | |
266 | |
267 n_geos = rdman->n_geos; | |
268 | |
269 geos = (geo_t **)malloc(sizeof(geo_t *) * n_geos); | |
270 if(geos == NULL) | |
271 return -1; | |
272 | |
273 _overlays = (geo_t **)malloc(sizeof(geo_t *) * n_geos); | |
274 if(geos == NULL) { | |
275 free(geos); | |
276 return -1; | |
277 } | |
278 | |
279 geo_cur = STAILQ_HEAD(rdman->all_geos); | |
280 for(i = 0; i < n_geos; i++) { | |
281 geos[i] = geo_cur; | |
282 geo_cur = STAILQ_NEXT(geo_t, next, geo_cur); | |
283 } | |
284 geo_mark_overlay(geo, n_geos, geos, &n_overlays, _overlays); | |
285 | |
286 free(geos); | |
287 *overlays = _overlays; | |
288 | |
289 return n_overlays; | |
290 } | |
291 | |
292 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord) { | 252 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord) { |
293 geo_t *geo; | 253 geo_t *geo; |
294 #ifdef GEO_ORDER | |
295 geo_t *visit; | |
296 unsigned int next_order; | |
297 #endif | |
298 int r; | 254 int r; |
299 | 255 |
300 geo = elmpool_elm_alloc(rdman->geo_pool); | 256 geo = elmpool_elm_alloc(rdman->geo_pool); |
301 if(geo == NULL) | 257 if(geo == NULL) |
302 return ERR; | 258 return ERR; |
303 | 259 |
304 geo_init(geo); | 260 geo_init(geo); |
305 geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); | 261 geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); |
306 | 262 |
307 sh_attach_geo(shape, geo); | 263 STAILQ_INS_TAIL(coord->members, geo_t, coord_next, geo); |
308 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo); | 264 coord->num_members++; |
309 rdman->n_geos++; | |
310 | |
311 /*! \todo remove order number. */ | |
312 #ifdef GEO_ORDER | |
313 geo->order = ++rdman->next_geo_order; | |
314 if(geo->order == 0) { | |
315 next_order = 0; | |
316 for(visit = STAILQ_HEAD(rdman->all_geos); | |
317 visit != NULL; | |
318 visit = STAILQ_NEXT(geo_t, next, visit)) | |
319 visit->order = ++next_order; | |
320 rdman->next_geo_order = next_order; | |
321 } | |
322 #endif | |
323 | 265 |
324 /* New one should be dirty to recompute it when drawing. */ | 266 /* New one should be dirty to recompute it when drawing. */ |
325 geo->flags |= GEF_DIRTY; | 267 geo->flags |= GEF_DIRTY; |
326 r = add_dirty_geo(rdman, geo); | 268 r = add_dirty_geo(rdman, geo); |
327 if(r != OK) | 269 if(r != OK) |
328 return ERR; | 270 return ERR; |
329 | 271 |
330 sh_attach_coord(shape, coord); | 272 sh_attach_coord(shape, coord); |
273 sh_attach_geo(shape, geo); | |
331 | 274 |
332 return OK; | 275 return OK; |
333 } | 276 } |
334 | 277 |
335 /*! \brief Remove a shape object from redraw manager. | 278 /*! \brief Remove a shape object from redraw manager. |
336 * | 279 * |
337 * \todo redraw shape objects that overlaid with removed one. | 280 * \todo redraw shape objects that overlaid with removed one. |
338 */ | 281 */ |
339 int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) { | 282 int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) { |
340 STAILQ_REMOVE(rdman->all_geos, geo_t, next, shape->geo); | 283 geo_t *geo; |
341 subject_free(&rdman->ob_factory, shape->geo->mouse_event); | 284 coord_t *coord; |
285 | |
286 geo = shape->geo; | |
287 coord = shape->coord; | |
288 STAILQ_REMOVE(coord->members, geo_t, coord_next, geo); | |
289 subject_free(&rdman->ob_factory, geo->mouse_event); | |
342 sh_detach_geo(shape); | 290 sh_detach_geo(shape); |
343 elmpool_elm_free(rdman->geo_pool, shape->geo); | 291 elmpool_elm_free(rdman->geo_pool, shape->geo); |
344 rdman->n_geos--; | |
345 sh_detach_coord(shape); | 292 sh_detach_coord(shape); |
346 return OK; | 293 return OK; |
347 } | 294 } |
348 | 295 |
349 coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) { | 296 coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) { |
373 while(visit) { | 320 while(visit) { |
374 visit->order = ++rdman->next_coord_order; | 321 visit->order = ++rdman->next_coord_order; |
375 visit = preorder_coord_subtree(root_coord, visit); | 322 visit = preorder_coord_subtree(root_coord, visit); |
376 } | 323 } |
377 } | 324 } |
325 | |
326 coord->before_pmem = parent->num_members; | |
378 | 327 |
379 return coord; | 328 return coord; |
380 } | 329 } |
381 | 330 |
382 /*! \brief Free a coord of a redraw_man_t object. | 331 /*! \brief Free a coord of a redraw_man_t object. |
549 coord->canvas = coord->parent->canvas; | 498 coord->canvas = coord->parent->canvas; |
550 } | 499 } |
551 } | 500 } |
552 | 501 |
553 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { | 502 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { |
554 shape_t *shape; | |
555 geo_t *geo; | 503 geo_t *geo; |
556 co_aix (*poses)[2]; | 504 co_aix (*poses)[2]; |
557 int cnt, pos_cnt; | 505 int cnt, pos_cnt; |
558 | 506 |
559 setup_canvas(rdman, coord); | 507 setup_canvas(rdman, coord); |
560 | 508 |
561 compute_aggr_of_coord(coord); | 509 compute_aggr_of_coord(coord); |
562 | 510 |
563 /* Clean member shapes. */ | 511 /* Clean member shapes. */ |
564 cnt = 0; | 512 cnt = 0; |
565 for(shape = STAILQ_HEAD(coord->members); | 513 for(geo = STAILQ_HEAD(coord->members); |
566 shape != NULL; | 514 geo != NULL; |
567 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { | 515 geo = STAILQ_NEXT(geo_t, coord_next, geo)) { |
568 geo = shape->geo; | |
569 SWAP(geo->cur_area, geo->last_area, area_t *); | 516 SWAP(geo->cur_area, geo->last_area, area_t *); |
570 clean_shape(shape); | 517 clean_shape(geo->shape); |
571 cnt++; | 518 cnt++; |
572 } | 519 } |
573 | 520 |
574 /* Compute area of the coord. */ | 521 /* Compute area of the coord. */ |
575 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt); | 522 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt); |
576 if(poses == NULL) | 523 if(poses == NULL) |
577 return ERR; | 524 return ERR; |
578 | 525 |
579 pos_cnt = 0; | 526 pos_cnt = 0; |
580 for(shape = STAILQ_HEAD(coord->members); | 527 for(geo = STAILQ_HEAD(coord->members); |
581 shape != NULL; | 528 geo != NULL; |
582 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { | 529 geo = STAILQ_NEXT(geo_t, coord_next, geo)) { |
583 geo = shape->geo; | |
584 | |
585 area_to_positions(geo->cur_area, poses + pos_cnt); | 530 area_to_positions(geo->cur_area, poses + pos_cnt); |
586 pos_cnt += 2; | 531 pos_cnt += 2; |
587 } | 532 } |
588 | 533 |
589 SWAP(coord->cur_area, coord->last_area, area_t *); | 534 SWAP(coord->cur_area, coord->last_area, area_t *); |
786 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, | 731 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, |
787 area_t **dirty_areas) { | 732 area_t **dirty_areas) { |
788 } | 733 } |
789 #endif /* UNITTEST */ | 734 #endif /* UNITTEST */ |
790 | 735 |
791 static int is_shape_in_areas(shape_t *shape, | 736 static int is_geo_in_areas(geo_t *geo, |
792 int n_areas, | 737 int n_areas, |
793 area_t **areas) { | 738 area_t **areas) { |
794 int i; | 739 int i; |
795 geo_t *geo; | 740 |
796 | |
797 geo = shape->geo; | |
798 for(i = 0; i < n_areas; i++) { | 741 for(i = 0; i < n_areas; i++) { |
799 if(is_overlay(geo->cur_area, areas[i])) | 742 if(is_overlay(geo->cur_area, areas[i])) |
800 return 1; | 743 return 1; |
801 } | 744 } |
802 return 0; | 745 return 0; |
820 coord_t *coord, | 763 coord_t *coord, |
821 int n_areas, | 764 int n_areas, |
822 area_t **areas) { | 765 area_t **areas) { |
823 int dirty = 0; | 766 int dirty = 0; |
824 int r; | 767 int r; |
825 shape_t *member; | 768 geo_t *member; |
826 coord_t *child; | 769 coord_t *child; |
827 cairo_t *canvas; | 770 cairo_t *canvas; |
828 int mem_idx; | 771 int mem_idx; |
829 | 772 |
830 canvas = coord->canvas; | 773 canvas = coord->canvas; |
836 r = draw_coord_shapes_in_areas(rdman, child, n_areas, areas); | 779 r = draw_coord_shapes_in_areas(rdman, child, n_areas, areas); |
837 dirty |= r; | 780 dirty |= r; |
838 child = STAILQ_NEXT(coord_t, sibling, child); | 781 child = STAILQ_NEXT(coord_t, sibling, child); |
839 } else { | 782 } else { |
840 ASSERT(member != NULL); | 783 ASSERT(member != NULL); |
841 if(is_shape_in_areas(member, n_areas, areas)) { | 784 if(is_geo_in_areas(member, n_areas, areas)) { |
842 draw_shape(rdman, canvas, member); | 785 draw_shape(rdman, canvas, member->shape); |
843 dirty = 1; | 786 dirty = 1; |
844 } | 787 } |
845 member = STAILQ_NEXT(shape_t, coord_mem_next, member); | 788 member = STAILQ_NEXT(geo_t, coord_next, member); |
789 mem_idx++; | |
846 } | 790 } |
847 } | 791 } |
848 | 792 |
849 if(dirty && coord->flags & COF_OWN_CANVAS) { | 793 if(dirty && coord->flags & COF_OWN_CANVAS) { |
850 update_canvas_2_parent(rdman, coord); | 794 update_canvas_2_parent(rdman, coord); |
959 * - rdman_redraw_changed() | 903 * - rdman_redraw_changed() |
960 * = draw_shapes_in_areas() | 904 * = draw_shapes_in_areas() |
961 */ | 905 */ |
962 | 906 |
963 int rdman_redraw_all(redraw_man_t *rdman) { | 907 int rdman_redraw_all(redraw_man_t *rdman) { |
964 geo_t *geo; | |
965 cairo_surface_t *surface; | 908 cairo_surface_t *surface; |
966 area_t area; | 909 area_t area; |
967 int r; | 910 int r; |
968 | 911 |
969 area.x = area.y = 0; | 912 area.x = area.y = 0; |
996 add_dirty_area(rdman, &area); | 939 add_dirty_area(rdman, &area); |
997 | 940 |
998 r = rdman_redraw_changed(rdman); | 941 r = rdman_redraw_changed(rdman); |
999 | 942 |
1000 return r; | 943 return r; |
944 } | |
945 | |
946 geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) { | |
947 geo_t *next; | |
948 coord_t *coord; | |
949 | |
950 if(last == NULL) { | |
951 coord = rdman->root_coord; | |
952 while(coord != NULL && STAILQ_HEAD(coord->members) == NULL) | |
953 coord = preorder_coord_subtree(rdman->root_coord, coord); | |
954 if(coord == NULL) | |
955 return NULL; | |
956 return STAILQ_HEAD(coord->members); | |
957 } | |
958 | |
959 coord = last->shape->coord; | |
960 next = STAILQ_NEXT(geo_t, coord_next, last); | |
961 while(next == NULL) { | |
962 coord = preorder_coord_subtree(rdman->root_coord, coord); | |
963 if(coord == NULL) | |
964 return NULL; | |
965 next = STAILQ_HEAD(coord->members); | |
966 } | |
967 return next; | |
1001 } | 968 } |
1002 | 969 |
1003 int rdman_force_clean(redraw_man_t *rdman) { | 970 int rdman_force_clean(redraw_man_t *rdman) { |
1004 int r; | 971 int r; |
1005 | 972 |
1236 paint_init(paint, dummy_paint_prepare, dummy_paint_free); | 1203 paint_init(paint, dummy_paint_prepare, dummy_paint_free); |
1237 | 1204 |
1238 return paint; | 1205 return paint; |
1239 } | 1206 } |
1240 | 1207 |
1241 void test_rdman_find_overlaid_shapes(void) { | |
1242 redraw_man_t rdman; | |
1243 geo_t geo; | |
1244 coord_t *coords[3]; | |
1245 shape_t *shapes[5]; | |
1246 geo_t **overlays; | |
1247 co_aix pos[2][2]; | |
1248 int n; | |
1249 int i; | |
1250 | |
1251 redraw_man_init(&rdman, NULL, NULL); | |
1252 coords[0] = rdman.root_coord; | |
1253 for(i = 1; i < 3; i++) { | |
1254 coords[i] = rdman_coord_new(&rdman, rdman.root_coord); | |
1255 } | |
1256 for(i = 0; i < 5; i++) { | |
1257 shapes[i] = sh_dummy_new(10 + i * 30, 10 + i * 20, 25, 15); | |
1258 CU_ASSERT(shapes[i] != NULL); | |
1259 } | |
1260 for(i = 0; i < 3; i++) | |
1261 rdman_add_shape(&rdman, shapes[i], coords[1]); | |
1262 for(i = 3; i < 5; i++) | |
1263 rdman_add_shape(&rdman, shapes[i], coords[2]); | |
1264 | |
1265 coords[1]->matrix[0] = 2; | |
1266 coords[0]->matrix[4] = 2; | |
1267 | |
1268 update_aggr_matrix(coords[0]); | |
1269 for(i = 0; i < 5; i++) | |
1270 sh_dummy_transform(shapes[i]); | |
1271 | |
1272 pos[0][0] = 100; | |
1273 pos[0][1] = 120; | |
1274 pos[1][0] = 100 + 140; | |
1275 pos[1][1] = 120 + 40; | |
1276 geo_init(&geo); | |
1277 geo_from_positions(&geo, 2, pos); | |
1278 | |
1279 n = rdman_find_overlaid_shapes(&rdman, &geo, &overlays); | |
1280 CU_ASSERT(n == 2); | |
1281 CU_ASSERT(overlays != NULL); | |
1282 CU_ASSERT(overlays[0] == shapes[2]->geo); | |
1283 CU_ASSERT(overlays[1] == shapes[3]->geo); | |
1284 | |
1285 free(overlays); | |
1286 for(i = 0; i < 5; i++) | |
1287 sh_dummy_free(shapes[i]); | |
1288 | |
1289 redraw_man_destroy(&rdman); | |
1290 } | |
1291 | |
1292 void test_rdman_redraw_changed(void) { | 1208 void test_rdman_redraw_changed(void) { |
1293 coord_t *coords[3]; | 1209 coord_t *coords[3]; |
1294 shape_t *shapes[3]; | 1210 shape_t *shapes[3]; |
1295 sh_dummy_t **dummys; | 1211 sh_dummy_t **dummys; |
1296 paint_t *paint; | 1212 paint_t *paint; |
1336 | 1252 |
1337 CU_pSuite get_redraw_man_suite(void) { | 1253 CU_pSuite get_redraw_man_suite(void) { |
1338 CU_pSuite suite; | 1254 CU_pSuite suite; |
1339 | 1255 |
1340 suite = CU_add_suite("Suite_redraw_man", NULL, NULL); | 1256 suite = CU_add_suite("Suite_redraw_man", NULL, NULL); |
1341 CU_ADD_TEST(suite, test_rdman_find_overlaid_shapes); | |
1342 CU_ADD_TEST(suite, test_rdman_redraw_changed); | 1257 CU_ADD_TEST(suite, test_rdman_redraw_changed); |
1343 | 1258 |
1344 return suite; | 1259 return suite; |
1345 } | 1260 } |
1346 | 1261 |