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