comparison src/redraw_man.c @ 17:41f0907b27ac

Unittest for rdman_redraw_changed(). geo_init() is seperated into geo_init() and geo_from_positions().
author Thinker K.F. Li <thinker@branda.to>
date Fri, 01 Aug 2008 23:32:22 +0800
parents e17e12b112c4
children 0f3baa488a62
comparison
equal deleted inserted replaced
16:e17e12b112c4 17:41f0907b27ac
10 #define OK 0 10 #define OK 0
11 #define ERR -1 11 #define ERR -1
12 12
13 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) 13 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL)
14 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) 14 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0)
15
16 #ifdef UNITTEST
17 typedef struct _sh_dummy sh_dummy_t;
18
19 extern void sh_dummy_transform(shape_t *shape);
20 extern void sh_dummy_draw(shape_t *, cairo_t *);
21 #endif /* UNITTEST */
15 22
16 /*! \brief Sort a list of element by a unsigned integer. 23 /*! \brief Sort a list of element by a unsigned integer.
17 * 24 *
18 * The result is in ascend order. The unsigned integers is 25 * The result is in ascend order. The unsigned integers is
19 * at offset specified by 'off' from start address of elemnts. 26 * at offset specified by 'off' from start address of elemnts.
81 88
82 rdman->dirty_areas[rdman->n_dirty_areas++] = area; 89 rdman->dirty_areas[rdman->n_dirty_areas++] = area;
83 return OK; 90 return OK;
84 } 91 }
85 92
86 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) {
87 extern void redraw_man_destroy(redraw_man_t *rdman);
88
89 memset(rdman, 0, sizeof(redraw_man_t));
90
91 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128);
92 if(rdman->geo_pool == NULL)
93 return ERR;
94
95 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16);
96 if(rdman->coord_pool == NULL) {
97 elmpool_free(rdman->geo_pool);
98 return ERR;
99 }
100
101 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool);
102 if(rdman->root_coord == NULL)
103 redraw_man_destroy(rdman);
104 rdman->n_coords = 1;
105 coord_init(rdman->root_coord, NULL);
106
107 rdman->cr = cr;
108
109 return OK;
110 }
111
112 void redraw_man_destroy(redraw_man_t *rdman) {
113 elmpool_free(rdman->coord_pool);
114 elmpool_free(rdman->geo_pool);
115 if(rdman->dirty_coords)
116 free(rdman->dirty_coords);
117 if(rdman->dirty_geos)
118 free(rdman->dirty_geos);
119 }
120
121
122 #define ASSERT(x)
123 /*
124 * Change transformation matrix
125 * - update aggregated transformation matrix
126 * - of coord_t object been changed.
127 * - of children coord_t objects.
128 * - redraw members of coord_t objects.
129 * - redraw shape objects they are overlaid with members.
130 * - find out overlaid shape objects.
131 * - geo_t of a coord_t object
132 * - can make finding more efficiency.
133 * - fill overlay geo_t objects of members.
134 *
135 * Change a shape object
136 * - redraw changed object.
137 * - redraw shape objects they are overlaid with changed object.
138 * - find out overlaid shape objects.
139 *
140 * That coord and geo of shape objects are setted by user code
141 * give user code a chance to collect coord and geo objects together
142 * and gain interest of higher cache hit rate.
143 */
144
145 /*! \brief Find out all affected shape objects.
146 *
147 * Find out all shape objects that are overalid with geo_t of
148 * a geometry changed object.
149 *
150 * Linear scan geo_t objects of all shape objects in all_shapes
151 * list of a redraw_man_t object.
152 */
153 int rdman_find_overlaid_shapes(redraw_man_t *rdman, geo_t *geo,
154 geo_t ***overlays) {
155 int n_geos;
156 geo_t **geos;
157 geo_t *geo_cur;
158 int n_overlays;
159 geo_t **_overlays;
160 int i;
161
162 n_geos = rdman->n_geos;
163
164 geos = (geo_t **)malloc(sizeof(geo_t *) * n_geos);
165 if(geos == NULL)
166 return -1;
167
168 _overlays = (geo_t **)malloc(sizeof(geo_t *) * n_geos);
169 if(geos == NULL) {
170 free(geos);
171 return -1;
172 }
173
174 geo_cur = STAILQ_HEAD(rdman->all_geos);
175 for(i = 0; i < n_geos; i++) {
176 geos[i] = geo_cur;
177 geo_cur = STAILQ_NEXT(geo_t, next, geo_cur);
178 }
179 geo_mark_overlay(geo, n_geos, geos, &n_overlays, _overlays);
180
181 free(geos);
182 *overlays = _overlays;
183
184 return n_overlays;
185 }
186
187 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord) {
188 geo_t *geo;
189 #ifdef GEO_ORDER
190 geo_t *visit;
191 unsigned int next_order;
192 #endif
193 int r;
194
195 geo = elmpool_elm_alloc(rdman->geo_pool);
196 if(geo == NULL)
197 return ERR;
198 sh_attach_geo(shape, geo);
199 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo);
200 rdman->n_geos++;
201
202 #ifdef GEO_ORDER
203 /* TODO: remove order number. */
204 geo->order = ++rdman->next_geo_order;
205 if(geo->order == 0) {
206 next_order = 0;
207 for(visit = STAILQ_HEAD(rdman->all_geos);
208 visit != NULL;
209 visit = STAILQ_NEXT(geo_t, next, visit))
210 visit->order = ++next_order;
211 rdman->next_geo_order = next_order;
212 }
213 #endif
214
215 /* New one should be dirty to recompute it when drawing. */
216 geo->flags |= GEF_DIRTY;
217 r = add_dirty_geo(rdman, geo);
218 if(r != OK)
219 return ERR;
220
221 sh_attach_coord(shape, coord);
222
223 return OK;
224 }
225
226 int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) {
227 STAILQ_REMOVE(rdman->all_geos, geo_t, next, shape->geo);
228 elmpool_elm_free(rdman->geo_pool, shape->geo);
229 sh_detach_geo(shape);
230 rdman->n_geos--;
231 sh_detach_coord(shape);
232 return OK;
233 }
234
235 coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) {
236 coord_t *coord, *root_coord;
237 coord_t *visit;
238
239 coord = elmpool_elm_alloc(rdman->coord_pool);
240 if(coord == NULL)
241 return NULL;
242
243 coord_init(coord, parent);
244 rdman->n_coords++;
245
246 coord->order = ++rdman->next_coord_order;
247 if(coord->order == 0) {
248 rdman->next_coord_order = 0;
249 root_coord = visit = rdman->root_coord;
250 /* skip root coord. */
251 visit = preorder_coord_subtree(root_coord, visit);
252 while(visit) {
253 visit->order = ++rdman->next_coord_order;
254 visit = preorder_coord_subtree(root_coord, visit);
255 }
256 }
257
258 return coord;
259 }
260
261 /*! \brief Free a coord of a redraw_man_t object.
262 *
263 * \param coord is a coord_t without children and members.
264 * \return 0 for successful, -1 for error.
265 */
266 int rdman_coord_free(redraw_man_t *rdman, coord_t *coord) {
267 coord_t *parent;
268
269 parent = coord->parent;
270 if(parent == NULL)
271 return ERR;
272
273 if(STAILQ_HEAD(coord->members) != NULL)
274 return ERR;
275
276 if(STAILQ_HEAD(coord->children) != NULL)
277 return ERR;
278
279 STAILQ_REMOVE(parent->children, coord_t, sibling, coord);
280 elmpool_elm_free(rdman->coord_pool, coord);
281 rdman->n_coords--;
282
283 return OK;
284 }
285
286 /*! \brief Mark a coord is changed.
287 *
288 * A changed coord_t object is marked as dirty and put
289 * into dirty_coords list.
290 */
291 int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) {
292 coord_t *child;
293 int max_dirty_coords;
294 int r;
295
296 if(coord->flags & COF_DIRTY)
297 return OK;
298
299 if(rdman->n_dirty_coords >= rdman->max_dirty_coords) {
300 /* Max of dirty_coords is not big enough. */
301 max_dirty_coords = rdman->max_dirty_coords + 16;
302
303 r = extend_memblk((void **)&rdman->dirty_coords,
304 sizeof(coord_t *) * rdman->n_dirty_coords,
305 sizeof(coord_t *) * max_dirty_coords);
306 rdman->max_dirty_coords = max_dirty_coords;
307 }
308
309 /* Make the coord and child coords dirty. */
310 for(child = coord;
311 child != NULL;
312 child = preorder_coord_subtree(coord, child)) {
313 rdman->dirty_coords[rdman->n_dirty_coords++] = coord;
314 coord->flags |= COF_DIRTY;
315 }
316
317 return OK;
318 }
319
320 /*! \brief Mark a shape is changed.
321 *
322 * The geo_t object of a changed shape is mark as dirty and
323 * put into dirty_geos list.
324 */
325 int rdman_shape_changed(redraw_man_t *rdman, shape_t *shape) {
326 geo_t *geo;
327 int r;
328
329 geo = shape->geo;
330
331 if(geo->flags & GEF_DIRTY)
332 return OK;
333
334 r = add_dirty_geo(rdman, geo);
335 if(r == ERR)
336 return ERR;
337 geo->flags |= GEF_DIRTY;
338
339 return OK;
340 }
341
342 static void clean_shape(shape_t *shape) { 93 static void clean_shape(shape_t *shape) {
343 switch(shape->sh_type) { 94 switch(shape->sh_type) {
344 case SHT_PATH: 95 case SHT_PATH:
345 sh_path_transform(shape); 96 sh_path_transform(shape);
346 break; 97 break;
98 #ifdef UNITTEST
99 default:
100 sh_dummy_transform(shape);
101 break;
102 #endif /* UNITTEST */
347 } 103 }
348 shape->geo->flags &= ~GEF_DIRTY; 104 shape->geo->flags &= ~GEF_DIRTY;
349 } 105 }
350 106
351 static void area_to_positions(area_t *area, co_aix (*poses)[2]) { 107 static void area_to_positions(area_t *area, co_aix (*poses)[2]) {
358 static int clean_coord(coord_t *coord) { 114 static int clean_coord(coord_t *coord) {
359 shape_t *shape; 115 shape_t *shape;
360 geo_t *geo; 116 geo_t *geo;
361 co_aix (*poses)[2]; 117 co_aix (*poses)[2];
362 int cnt, pos_cnt; 118 int cnt, pos_cnt;
363 int i;
364 119
365 compute_aggr_of_coord(coord); 120 compute_aggr_of_coord(coord);
366 121
367 /* Clean member shapes. */ 122 /* Clean member shapes. */
368 cnt = 0; 123 cnt = 0;
384 for(shape = STAILQ_HEAD(coord->members); 139 for(shape = STAILQ_HEAD(coord->members);
385 shape != NULL; 140 shape != NULL;
386 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { 141 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) {
387 geo = shape->geo; 142 geo = shape->geo;
388 143
389 area_to_positions(&geo->areas[0], poses + pos_cnt); 144 area_to_positions(geo->cur_area, poses + pos_cnt);
390 pos_cnt += 2; 145 pos_cnt += 2;
391 area_to_positions(&geo->areas[1], poses + pos_cnt); 146 }
392 pos_cnt += 2;
393 }
394
395 #if 0
396 for(i = 0; i < pos_cnt; i++)
397 coord_trans_pos(coord, &poses[i][0], &poses[i][1]);
398 #endif
399 147
400 SWAP(coord->cur_area, coord->last_area, area_t *); 148 SWAP(coord->cur_area, coord->last_area, area_t *);
401 area_init(coord->cur_area, pos_cnt, poses); 149 area_init(coord->cur_area, pos_cnt, poses);
402 free(poses); 150 free(poses);
403 151
431 rdman->n_dirty_coords = 0; 179 rdman->n_dirty_coords = 0;
432 } 180 }
433 return OK; 181 return OK;
434 } 182 }
435 183
184 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) {
185 extern void redraw_man_destroy(redraw_man_t *rdman);
186
187 memset(rdman, 0, sizeof(redraw_man_t));
188
189 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128);
190 if(rdman->geo_pool == NULL)
191 return ERR;
192
193 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16);
194 if(rdman->coord_pool == NULL) {
195 elmpool_free(rdman->geo_pool);
196 return ERR;
197 }
198
199 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool);
200 if(rdman->root_coord == NULL)
201 redraw_man_destroy(rdman);
202 rdman->n_coords = 1;
203 coord_init(rdman->root_coord, NULL);
204
205 rdman->cr = cr;
206
207 return OK;
208 }
209
210 void redraw_man_destroy(redraw_man_t *rdman) {
211 elmpool_free(rdman->coord_pool);
212 elmpool_free(rdman->geo_pool);
213 if(rdman->dirty_coords)
214 free(rdman->dirty_coords);
215 if(rdman->dirty_geos)
216 free(rdman->dirty_geos);
217 }
218
219
220 #define ASSERT(x)
221 /*
222 * Change transformation matrix
223 * - update aggregated transformation matrix
224 * - of coord_t object been changed.
225 * - of children coord_t objects.
226 * - redraw members of coord_t objects.
227 * - redraw shape objects they are overlaid with members.
228 * - find out overlaid shape objects.
229 * - geo_t of a coord_t object
230 * - can make finding more efficiency.
231 * - fill overlay geo_t objects of members.
232 *
233 * Change a shape object
234 * - redraw changed object.
235 * - redraw shape objects they are overlaid with changed object.
236 * - find out overlaid shape objects.
237 *
238 * That coord and geo of shape objects are setted by user code
239 * give user code a chance to collect coord and geo objects together
240 * and gain interest of higher cache hit rate.
241 */
242
243 /*! \brief Find out all affected shape objects.
244 *
245 * Find out all shape objects that are overalid with geo_t of
246 * a geometry changed object.
247 *
248 * Linear scan geo_t objects of all shape objects in all_shapes
249 * list of a redraw_man_t object.
250 */
251 int rdman_find_overlaid_shapes(redraw_man_t *rdman, geo_t *geo,
252 geo_t ***overlays) {
253 int n_geos;
254 geo_t **geos;
255 geo_t *geo_cur;
256 int n_overlays;
257 geo_t **_overlays;
258 int i;
259
260 n_geos = rdman->n_geos;
261
262 geos = (geo_t **)malloc(sizeof(geo_t *) * n_geos);
263 if(geos == NULL)
264 return -1;
265
266 _overlays = (geo_t **)malloc(sizeof(geo_t *) * n_geos);
267 if(geos == NULL) {
268 free(geos);
269 return -1;
270 }
271
272 geo_cur = STAILQ_HEAD(rdman->all_geos);
273 for(i = 0; i < n_geos; i++) {
274 geos[i] = geo_cur;
275 geo_cur = STAILQ_NEXT(geo_t, next, geo_cur);
276 }
277 geo_mark_overlay(geo, n_geos, geos, &n_overlays, _overlays);
278
279 free(geos);
280 *overlays = _overlays;
281
282 return n_overlays;
283 }
284
285 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord) {
286 geo_t *geo;
287 #ifdef GEO_ORDER
288 geo_t *visit;
289 unsigned int next_order;
290 #endif
291 int r;
292
293 geo = elmpool_elm_alloc(rdman->geo_pool);
294 if(geo == NULL)
295 return ERR;
296
297 geo_init(geo);
298
299 sh_attach_geo(shape, geo);
300 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo);
301 rdman->n_geos++;
302
303 #ifdef GEO_ORDER
304 /* TODO: remove order number. */
305 geo->order = ++rdman->next_geo_order;
306 if(geo->order == 0) {
307 next_order = 0;
308 for(visit = STAILQ_HEAD(rdman->all_geos);
309 visit != NULL;
310 visit = STAILQ_NEXT(geo_t, next, visit))
311 visit->order = ++next_order;
312 rdman->next_geo_order = next_order;
313 }
314 #endif
315
316 /* New one should be dirty to recompute it when drawing. */
317 geo->flags |= GEF_DIRTY;
318 r = add_dirty_geo(rdman, geo);
319 if(r != OK)
320 return ERR;
321
322 sh_attach_coord(shape, coord);
323
324 return OK;
325 }
326
327 /*! \brief Remove a shape object from redraw manager.
328 *
329 * TODO: redraw shape objects that overlaid with removed one.
330 */
331 int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) {
332 STAILQ_REMOVE(rdman->all_geos, geo_t, next, shape->geo);
333 elmpool_elm_free(rdman->geo_pool, shape->geo);
334 sh_detach_geo(shape);
335 rdman->n_geos--;
336 sh_detach_coord(shape);
337 return OK;
338 }
339
340 coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) {
341 coord_t *coord, *root_coord;
342 coord_t *visit;
343
344 coord = elmpool_elm_alloc(rdman->coord_pool);
345 if(coord == NULL)
346 return NULL;
347
348 coord_init(coord, parent);
349 rdman->n_coords++;
350
351 coord->order = ++rdman->next_coord_order;
352 if(coord->order == 0) {
353 rdman->next_coord_order = 0;
354 root_coord = visit = rdman->root_coord;
355 /* skip root coord. */
356 visit = preorder_coord_subtree(root_coord, visit);
357 while(visit) {
358 visit->order = ++rdman->next_coord_order;
359 visit = preorder_coord_subtree(root_coord, visit);
360 }
361 }
362
363 return coord;
364 }
365
366 /*! \brief Free a coord of a redraw_man_t object.
367 *
368 * \param coord is a coord_t without children and members.
369 * \return 0 for successful, -1 for error.
370 */
371 int rdman_coord_free(redraw_man_t *rdman, coord_t *coord) {
372 coord_t *parent;
373
374 parent = coord->parent;
375 if(parent == NULL)
376 return ERR;
377
378 if(STAILQ_HEAD(coord->members) != NULL)
379 return ERR;
380
381 if(STAILQ_HEAD(coord->children) != NULL)
382 return ERR;
383
384 STAILQ_REMOVE(parent->children, coord_t, sibling, coord);
385 elmpool_elm_free(rdman->coord_pool, coord);
386 rdman->n_coords--;
387
388 return OK;
389 }
390
391 /*! \brief Mark a coord is changed.
392 *
393 * A changed coord_t object is marked as dirty and put
394 * into dirty_coords list.
395 */
396 int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) {
397 coord_t *child;
398 int max_dirty_coords;
399 int r;
400
401 if(coord->flags & COF_DIRTY)
402 return OK;
403
404 if(rdman->n_dirty_coords >= rdman->max_dirty_coords) {
405 /* Max of dirty_coords is not big enough. */
406 max_dirty_coords = rdman->max_dirty_coords + 16;
407
408 r = extend_memblk((void **)&rdman->dirty_coords,
409 sizeof(coord_t *) * rdman->n_dirty_coords,
410 sizeof(coord_t *) * max_dirty_coords);
411 rdman->max_dirty_coords = max_dirty_coords;
412 }
413
414 /* Make the coord and child coords dirty. */
415 for(child = coord;
416 child != NULL;
417 child = preorder_coord_subtree(coord, child)) {
418 rdman->dirty_coords[rdman->n_dirty_coords++] = coord;
419 coord->flags |= COF_DIRTY;
420 }
421
422 return OK;
423 }
424
425 /*! \brief Mark a shape is changed.
426 *
427 * The geo_t object of a changed shape is mark as dirty and
428 * put into dirty_geos list.
429 */
430 int rdman_shape_changed(redraw_man_t *rdman, shape_t *shape) {
431 geo_t *geo;
432 int r;
433
434 geo = shape->geo;
435
436 if(geo->flags & GEF_DIRTY)
437 return OK;
438
439 r = add_dirty_geo(rdman, geo);
440 if(r == ERR)
441 return ERR;
442 geo->flags |= GEF_DIRTY;
443
444 return OK;
445 }
446
447 /* Drawing and Redrawing
448 * ============================================================
449 */
450
436 static void draw_shape(redraw_man_t *rdman, shape_t *shape) { 451 static void draw_shape(redraw_man_t *rdman, shape_t *shape) {
437 switch(shape->sh_type) { 452 switch(shape->sh_type) {
438 case SHT_PATH: 453 case SHT_PATH:
439 sh_path_draw(shape, rdman->cr); 454 sh_path_draw(shape, rdman->cr);
440 break; 455 break;
441 } 456 #ifdef UNITTEST
442 } 457 default:
443 458 sh_dummy_draw(shape, rdman->cr);
459 break;
460 #endif /* UNITTEST */
461 }
462 }
463
464 #ifndef UNITTEST
444 static void clean_clip(cairo_t *cr) { 465 static void clean_clip(cairo_t *cr) {
445 cairo_pattern_t *pt; 466 cairo_pattern_t *pt;
446 467
447 pt = cairo_get_source(cr); 468 pt = cairo_get_source(cr);
448 cairo_pattern_reference(pt); 469 cairo_pattern_reference(pt);
459 area_t *area; 480 area_t *area;
460 cairo_t *cr; 481 cairo_t *cr;
461 482
462 cr = rdman->cr; 483 cr = rdman->cr;
463 484
464 cairo_reset_clip(cr);
465 for(i = 0; i < n_dirty_areas; i++) { 485 for(i = 0; i < n_dirty_areas; i++) {
466 area = dirty_areas[i]; 486 area = dirty_areas[i];
467 cairo_rectangle(cr, area->x, area->y, area->w, area->h); 487 cairo_rectangle(cr, area->x, area->y, area->w, area->h);
468 } 488 }
469 clean_clip(cr); 489 clean_clip(cr);
470 cairo_clip(cr); 490 cairo_clip(cr);
471 } 491 }
492
493 static void reset_clip(redraw_man_t *rdman) {
494 cairo_reset_clip(rdman->cr);
495 }
496 #else /* UNITTEST */
497 static void make_clip(redraw_man_t *rdman, int n_dirty_areas,
498 area_t **dirty_areas) {
499 }
500
501 static void reset_clip(redraw_man_t *rdman) {
502 }
503 #endif /* UNITTEST */
472 504
473 static void draw_shapes_in_areas(redraw_man_t *rdman, 505 static void draw_shapes_in_areas(redraw_man_t *rdman,
474 int n_areas, 506 int n_areas,
475 area_t **areas) { 507 area_t **areas) {
476 geo_t *visit_geo; 508 geo_t *visit_geo;
553 dirty_areas = rdman->dirty_areas; 585 dirty_areas = rdman->dirty_areas;
554 if(n_dirty_areas > 0) { 586 if(n_dirty_areas > 0) {
555 make_clip(rdman, n_dirty_areas, dirty_areas); 587 make_clip(rdman, n_dirty_areas, dirty_areas);
556 draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas); 588 draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas);
557 rdman->n_dirty_areas = 0; 589 rdman->n_dirty_areas = 0;
590 reset_clip(rdman);
558 } 591 }
559 rdman->n_dirty_areas = 0; 592 rdman->n_dirty_areas = 0;
560
561 cairo_reset_clip(rdman->cr);
562 593
563 return OK; 594 return OK;
564 } 595 }
565 596
566 int rdman_redraw_all(redraw_man_t *rdman) { 597 int rdman_redraw_all(redraw_man_t *rdman) {
567 geo_t *geo; 598 geo_t *geo;
568 599
569 clean_rdman_coords(rdman); 600 clean_rdman_coords(rdman);
570 rdman->n_dirty_areas = 0; 601 rdman->n_dirty_areas = 0;
571 602
572 cairo_reset_clip(rdman->cr);
573 for(geo = STAILQ_HEAD(rdman->all_geos); 603 for(geo = STAILQ_HEAD(rdman->all_geos);
574 geo != NULL; 604 geo != NULL;
575 geo = STAILQ_NEXT(geo_t, next, geo)) { 605 geo = STAILQ_NEXT(geo_t, next, geo)) {
576 if(geo->flags & GEF_DIRTY) 606 if(geo->flags & GEF_DIRTY)
577 clean_shape(geo->shape); 607 clean_shape(geo->shape);
578 draw_shape(rdman, geo->shape); 608 draw_shape(rdman, geo->shape);
579 } 609 }
580 cairo_reset_clip(rdman->cr);
581 610
582 return OK; 611 return OK;
583 } 612 }
584 613
585 /* 614 /*
651 680
652 struct _sh_dummy { 681 struct _sh_dummy {
653 shape_t shape; 682 shape_t shape;
654 co_aix x, y; 683 co_aix x, y;
655 co_aix w, h; 684 co_aix w, h;
685 int draw_cnt;
656 }; 686 };
657 typedef struct _sh_dummy sh_dummy_t;
658 687
659 shape_t *sh_dummy_new(co_aix x, co_aix y, co_aix w, co_aix h) { 688 shape_t *sh_dummy_new(co_aix x, co_aix y, co_aix w, co_aix h) {
660 sh_dummy_t *dummy; 689 sh_dummy_t *dummy;
661 690
662 dummy = (sh_dummy_t *)malloc(sizeof(sh_dummy_t)); 691 dummy = (sh_dummy_t *)malloc(sizeof(sh_dummy_t));
663 if(dummy == NULL) 692 if(dummy == NULL)
664 return NULL; 693 return NULL;
694
695 memset(dummy, 0, sizeof(sh_dummy_t));
665 696
666 dummy->x = x; 697 dummy->x = x;
667 dummy->y = y; 698 dummy->y = y;
668 dummy->w = w; 699 dummy->w = w;
669 dummy->h = h; 700 dummy->h = h;
701 dummy->draw_cnt = 0;
670 702
671 return (shape_t *)dummy; 703 return (shape_t *)dummy;
672 } 704 }
673 705
674 void sh_dummy_free(shape_t *sh) { 706 void sh_dummy_free(shape_t *sh) {
691 poses[0][0] = x1; 723 poses[0][0] = x1;
692 poses[0][1] = y1; 724 poses[0][1] = y1;
693 poses[1][0] = x2; 725 poses[1][0] = x2;
694 poses[1][1] = y2; 726 poses[1][1] = y2;
695 727
696 geo_init(shape->geo, 2, poses); 728 if(shape->geo)
697 } 729 geo_from_positions(shape->geo, 2, poses);
730 }
731 }
732
733 void sh_dummy_draw(shape_t *shape, cairo_t *cr) {
734 sh_dummy_t *dummy;
735
736 dummy = (sh_dummy_t *)shape;
737 dummy->draw_cnt++;
698 } 738 }
699 739
700 void test_rdman_find_overlaid_shapes(void) { 740 void test_rdman_find_overlaid_shapes(void) {
701 redraw_man_t rdman; 741 redraw_man_t rdman;
702 geo_t geo; 742 geo_t geo;
730 770
731 pos[0][0] = 100; 771 pos[0][0] = 100;
732 pos[0][1] = 120; 772 pos[0][1] = 120;
733 pos[1][0] = 100 + 140; 773 pos[1][0] = 100 + 140;
734 pos[1][1] = 120 + 40; 774 pos[1][1] = 120 + 40;
735 geo_init(&geo, 2, pos); 775 geo_init(&geo);
776 geo_from_positions(&geo, 2, pos);
736 777
737 n = rdman_find_overlaid_shapes(&rdman, &geo, &overlays); 778 n = rdman_find_overlaid_shapes(&rdman, &geo, &overlays);
738 CU_ASSERT(n == 2); 779 CU_ASSERT(n == 2);
739 CU_ASSERT(overlays != NULL); 780 CU_ASSERT(overlays != NULL);
740 CU_ASSERT(overlays[0] == shapes[2]->geo); 781 CU_ASSERT(overlays[0] == shapes[2]->geo);
745 sh_dummy_free(shapes[i]); 786 sh_dummy_free(shapes[i]);
746 787
747 redraw_man_destroy(&rdman); 788 redraw_man_destroy(&rdman);
748 } 789 }
749 790
791 void test_rdman_redraw_changed(void) {
792 coord_t *coords[3];
793 shape_t *shapes[3];
794 sh_dummy_t **dummys;
795 redraw_man_t *rdman;
796 redraw_man_t _rdman;
797 int i;
798
799 dummys = (sh_dummy_t **)shapes;
800
801 rdman = &_rdman;
802 redraw_man_init(rdman, NULL);
803 for(i = 0; i < 3; i++) {
804 shapes[i] = sh_dummy_new(0, 0, 50, 50);
805 coords[i] = rdman_coord_new(rdman, rdman->root_coord);
806 coords[i]->matrix[2] = 10 + i * 100;
807 coords[i]->matrix[5] = 10 + i * 100;
808 rdman_coord_changed(rdman, coords[i]);
809 rdman_add_shape(rdman, shapes[i], coords[i]);
810 }
811 rdman_redraw_all(rdman);
812 CU_ASSERT(dummys[0]->draw_cnt == 1);
813 CU_ASSERT(dummys[1]->draw_cnt == 1);
814 CU_ASSERT(dummys[2]->draw_cnt == 1);
815
816 coords[2]->matrix[2] = 100;
817 coords[2]->matrix[5] = 100;
818 rdman_coord_changed(rdman, coords[2]);
819 rdman_redraw_changed(rdman);
820
821 CU_ASSERT(dummys[0]->draw_cnt == 1);
822 CU_ASSERT(dummys[1]->draw_cnt == 2);
823 CU_ASSERT(dummys[2]->draw_cnt == 2);
824 }
825
750 CU_pSuite get_redraw_man_suite(void) { 826 CU_pSuite get_redraw_man_suite(void) {
751 CU_pSuite suite; 827 CU_pSuite suite;
752 828
753 suite = CU_add_suite("Suite_redraw_man", NULL, NULL); 829 suite = CU_add_suite("Suite_redraw_man", NULL, NULL);
754 CU_ADD_TEST(suite, test_rdman_find_overlaid_shapes); 830 CU_ADD_TEST(suite, test_rdman_find_overlaid_shapes);
831 CU_ADD_TEST(suite, test_rdman_redraw_changed);
755 832
756 return suite; 833 return suite;
757 } 834 }
758 835
759 #endif /* UNITTEST */ 836 #endif /* UNITTEST */