Mercurial > MadButterfly
comparison src/redraw_man.c @ 314:6c350fc92ae3
Cache rednering result is now workable.
- Know issues
- For unknow issue, CAIRO_OPERATOR_CLEAR will not be limited by clipping.
Image will be cleaned in a strange way. Maybe, it is a bug of Cairo.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Thu, 05 Mar 2009 00:54:42 +0800 |
parents | 13ce87b6dbf5 |
children | d0f8642d3508 |
comparison
equal
deleted
inserted
replaced
313:5737548e922f | 314:6c350fc92ae3 |
---|---|
1 #include <stdio.h> | 1 #include <stdio.h> |
2 #include <stdlib.h> | 2 #include <stdlib.h> |
3 #include <string.h> | 3 #include <string.h> |
4 #include <math.h> | |
4 #include <cairo.h> | 5 #include <cairo.h> |
5 #include "mb_types.h" | 6 #include "mb_types.h" |
6 #include "mb_shapes.h" | 7 #include "mb_shapes.h" |
7 #include "mb_tools.h" | 8 #include "mb_tools.h" |
8 #include "mb_redraw_man.h" | 9 #include "mb_redraw_man.h" |
29 #define sh_get_geo(sh) ((sh)->geo) | 30 #define sh_get_geo(sh) ((sh)->geo) |
30 #define sh_attach_coord(sh, coord) do { (sh)->coord = coord; } while(0) | 31 #define sh_attach_coord(sh, coord) do { (sh)->coord = coord; } while(0) |
31 #define sh_detach_coord(sh) do { (sh)->coord = NULL; } while(0) | 32 #define sh_detach_coord(sh) do { (sh)->coord = NULL; } while(0) |
32 #define rdman_is_dirty(rdman) \ | 33 #define rdman_is_dirty(rdman) \ |
33 ((rdman)->dirty_coords.num != 0 || \ | 34 ((rdman)->dirty_coords.num != 0 || \ |
34 (rdman)->dirty_geos.num != 0 || \ | 35 (rdman)->dirty_geos.num != 0) |
35 (rdman)->dirty_areas.num != 0) | |
36 | 36 |
37 #define OK 0 | 37 #define OK 0 |
38 #define ERR -1 | 38 #define ERR -1 |
39 | 39 |
40 #define ARRAY_EXT_SZ 64 | 40 #define ARRAY_EXT_SZ 64 |
130 | 130 |
131 | 131 |
132 static int add_dirty_coord(redraw_man_t *rdman, coord_t *coord) { | 132 static int add_dirty_coord(redraw_man_t *rdman, coord_t *coord) { |
133 coord->flags |= COF_DIRTY; | 133 coord->flags |= COF_DIRTY; |
134 ADD_DATA(coords, dirty_coords, coord); | 134 ADD_DATA(coords, dirty_coords, coord); |
135 return OK; | |
135 } | 136 } |
136 | 137 |
137 static int add_dirty_geo(redraw_man_t *rdman, geo_t *geo) { | 138 static int add_dirty_geo(redraw_man_t *rdman, geo_t *geo) { |
138 geo->flags |= GEF_DIRTY; | 139 geo->flags |= GEF_DIRTY; |
139 ADD_DATA(geos, dirty_geos, geo); | 140 ADD_DATA(geos, dirty_geos, geo); |
140 } | 141 return OK; |
141 | 142 } |
142 static int add_dirty_area(redraw_man_t *rdman, area_t *area) { | 143 |
143 ADD_DATA(areas, dirty_areas, area); | 144 static int add_dirty_area(redraw_man_t *rdman, coord_t *coord, area_t *area) { |
145 int r; | |
146 | |
147 rdman->n_dirty_areas++; | |
148 r = areas_add(_coord_get_dirty_areas(coord), area); | |
149 return r == 0? OK: ERR; | |
150 } | |
151 | |
152 static int add_zeroing_coord(redraw_man_t *rdman, coord_t *coord) { | |
153 coord_set_zeroing(coord); | |
154 ADD_DATA(coords, zeroing_coords, coord); | |
155 return OK; | |
144 } | 156 } |
145 | 157 |
146 static int add_free_obj(redraw_man_t *rdman, void *obj, | 158 static int add_free_obj(redraw_man_t *rdman, void *obj, |
147 free_func_t free_func) { | 159 free_func_t free_func) { |
148 int max; | 160 int max; |
186 poses[0][1] = area->y; | 198 poses[0][1] = area->y; |
187 poses[1][0] = area->x + area->w; | 199 poses[1][0] = area->x + area->w; |
188 poses[1][1] = area->y + area->h;; | 200 poses[1][1] = area->y + area->h;; |
189 } | 201 } |
190 | 202 |
191 static cairo_t *new_canvas(redraw_man_t *rdman) { | 203 static cairo_t *canvas_new(int w, int h) { |
192 #ifndef UNITTEST | 204 #ifndef UNITTEST |
205 cairo_surface_t *surface; | |
193 cairo_t *cr; | 206 cairo_t *cr; |
194 cairo_surface_t *surface, *cr_surface; | 207 |
195 int w, h; | |
196 | |
197 cr_surface = cairo_get_target(rdman->cr); | |
198 w = cairo_image_surface_get_width(cr_surface); | |
199 h = cairo_image_surface_get_height(cr_surface); | |
200 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, | 208 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, |
201 w, h); | 209 w, h); |
202 cr = cairo_create(surface); | 210 cr = cairo_create(surface); |
203 | 211 |
204 return cr; | 212 return cr; |
205 #else | 213 #else |
206 return NULL; | 214 return NULL; |
207 #endif | 215 #endif |
208 } | 216 } |
209 | 217 |
210 static void free_canvas(cairo_t *canvas) { | 218 static void canvas_free(cairo_t *canvas) { |
211 #ifndef UNITTEST | 219 #ifndef UNITTEST |
212 cairo_destroy(canvas); | 220 cairo_destroy(canvas); |
221 #endif | |
222 } | |
223 | |
224 static void canvas_get_size(cairo_t *canvas, int *w, int *h) { | |
225 #ifndef UNITTEST | |
226 cairo_surface_t *surface; | |
227 | |
228 surface = cairo_get_target(canvas); | |
229 *w = cairo_image_surface_get_width(surface); | |
230 *h = cairo_image_surface_get_height(surface); | |
231 #else | |
232 *w = 0; | |
233 *h = 0; | |
213 #endif | 234 #endif |
214 } | 235 } |
215 | 236 |
216 static int geo_off_in_coord(geo_t *geo, coord_t *coord) { | 237 static int geo_off_in_coord(geo_t *geo, coord_t *coord) { |
217 int off = 0; | 238 int off = 0; |
244 | 265 |
245 RM_MEMBER(coord, geo); | 266 RM_MEMBER(coord, geo); |
246 coord->num_members--; | 267 coord->num_members--; |
247 } | 268 } |
248 | 269 |
270 static coord_canvas_info_t *coord_canvas_info_new(redraw_man_t *rdman, | |
271 coord_t *coord, | |
272 cairo_t *canvas) { | |
273 coord_canvas_info_t *info; | |
274 | |
275 info = (coord_canvas_info_t *)elmpool_elm_alloc(rdman->coord_canvas_pool); | |
276 if(info == NULL) | |
277 return info; | |
278 | |
279 info->owner = coord; | |
280 info->canvas = canvas; | |
281 DARRAY_INIT(&info->dirty_areas); | |
282 | |
283 return info; | |
284 } | |
285 | |
286 static void coord_canvas_info_free(redraw_man_t *rdman, | |
287 coord_canvas_info_t *info) { | |
288 DARRAY_DESTROY(&info->dirty_areas); | |
289 elmpool_elm_free(rdman->coord_canvas_pool, info); | |
290 } | |
291 | |
249 static void mouse_event_root_dummy(event_t *evt, void *arg) { | 292 static void mouse_event_root_dummy(event_t *evt, void *arg) { |
250 } | 293 } |
251 | 294 |
252 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend) { | 295 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend) { |
253 extern void redraw_man_destroy(redraw_man_t *rdman); | 296 extern void redraw_man_destroy(redraw_man_t *rdman); |
255 observer_t *addrm_ob; | 298 observer_t *addrm_ob; |
256 extern void addrm_monitor_hdlr(event_t *evt, void *arg); | 299 extern void addrm_monitor_hdlr(event_t *evt, void *arg); |
257 | 300 |
258 memset(rdman, 0, sizeof(redraw_man_t)); | 301 memset(rdman, 0, sizeof(redraw_man_t)); |
259 | 302 |
303 DARRAY_INIT(&rdman->dirty_coords); | |
304 DARRAY_INIT(&rdman->dirty_geos); | |
305 DARRAY_INIT(&rdman->gen_geos); | |
306 DARRAY_INIT(&rdman->zeroing_coords); | |
307 | |
260 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); | 308 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); |
261 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); | 309 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); |
262 rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); | 310 rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); |
263 rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); | 311 rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); |
264 rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); | 312 rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); |
265 rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); | 313 rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); |
266 rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); | 314 rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); |
315 rdman->coord_canvas_pool = elmpool_new(sizeof(coord_canvas_info_t), 16); | |
267 if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && | 316 if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && |
268 rdman->observer_pool && rdman->subject_pool && | 317 rdman->observer_pool && rdman->subject_pool && |
269 rdman->paint_color_pool)) | 318 rdman->paint_color_pool && rdman->coord_canvas_pool)) |
270 goto err; | 319 goto err; |
271 | 320 |
272 rdman->ob_factory.subject_alloc = ob_subject_alloc; | 321 rdman->ob_factory.subject_alloc = ob_subject_alloc; |
273 rdman->ob_factory.subject_free = ob_subject_free; | 322 rdman->ob_factory.subject_free = ob_subject_free; |
274 rdman->ob_factory.observer_alloc = ob_observer_alloc; | 323 rdman->ob_factory.observer_alloc = ob_observer_alloc; |
281 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); | 330 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); |
282 if(!(rdman->redraw && rdman->addrm_monitor)) | 331 if(!(rdman->redraw && rdman->addrm_monitor)) |
283 goto err; | 332 goto err; |
284 | 333 |
285 addrm_ob = subject_add_observer(rdman->addrm_monitor, | 334 addrm_ob = subject_add_observer(rdman->addrm_monitor, |
286 addrm_monitor_hdlr, NULL); | 335 addrm_monitor_hdlr, rdman); |
287 if(addrm_ob == NULL) | 336 if(addrm_ob == NULL) |
288 goto err; | 337 goto err; |
289 | 338 |
290 rdman->last_mouse_over = NULL; | 339 rdman->last_mouse_over = NULL; |
291 | 340 |
297 mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool); | 346 mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool); |
298 rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, | 347 rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, |
299 rdman->root_coord, | 348 rdman->root_coord, |
300 OBJT_COORD); | 349 OBJT_COORD); |
301 rdman->root_coord->flags |= COF_OWN_CANVAS; | 350 rdman->root_coord->flags |= COF_OWN_CANVAS; |
302 rdman->root_coord->canvas = cr; | 351 rdman->root_coord->canvas_info = |
352 coord_canvas_info_new(rdman, rdman->root_coord, cr); | |
303 rdman->root_coord->opacity = 1; | 353 rdman->root_coord->opacity = 1; |
304 | 354 |
305 rdman->cr = cr; | 355 rdman->cr = cr; |
306 rdman->backend = backend; | 356 rdman->backend = backend; |
307 | 357 |
332 elmpool_free(rdman->subject_pool); | 382 elmpool_free(rdman->subject_pool); |
333 if(rdman->paint_color_pool) | 383 if(rdman->paint_color_pool) |
334 elmpool_free(rdman->paint_color_pool); | 384 elmpool_free(rdman->paint_color_pool); |
335 if(rdman->pent_pool) | 385 if(rdman->pent_pool) |
336 elmpool_free(rdman->pent_pool); | 386 elmpool_free(rdman->pent_pool); |
387 if(rdman->coord_canvas_pool) | |
388 elmpool_free(rdman->coord_canvas_pool); | |
389 DARRAY_DESTROY(&rdman->dirty_coords); | |
390 DARRAY_DESTROY(&rdman->dirty_geos); | |
391 DARRAY_DESTROY(&rdman->gen_geos); | |
392 DARRAY_DESTROY(&rdman->zeroing_coords); | |
337 return ERR; | 393 return ERR; |
338 } | 394 } |
339 | 395 |
340 void redraw_man_destroy(redraw_man_t *rdman) { | 396 void redraw_man_destroy(redraw_man_t *rdman) { |
341 coord_t *coord, *saved_coord; | 397 coord_t *coord, *saved_coord; |
373 #endif | 429 #endif |
374 saved_shape = shape; | 430 saved_shape = shape; |
375 } | 431 } |
376 if(saved_shape != NULL) | 432 if(saved_shape != NULL) |
377 rdman_shape_free(rdman, saved_shape); | 433 rdman_shape_free(rdman, saved_shape); |
378 | 434 |
435 coord_canvas_info_free(rdman, rdman->root_coord->canvas_info); | |
436 | |
379 elmpool_free(rdman->coord_pool); | 437 elmpool_free(rdman->coord_pool); |
380 elmpool_free(rdman->geo_pool); | 438 elmpool_free(rdman->geo_pool); |
381 elmpool_free(rdman->shnode_pool); | 439 elmpool_free(rdman->shnode_pool); |
382 elmpool_free(rdman->observer_pool); | 440 elmpool_free(rdman->observer_pool); |
383 elmpool_free(rdman->subject_pool); | 441 elmpool_free(rdman->subject_pool); |
384 elmpool_free(rdman->paint_color_pool); | 442 elmpool_free(rdman->paint_color_pool); |
385 elmpool_free(rdman->pent_pool); | 443 elmpool_free(rdman->pent_pool); |
444 elmpool_free(rdman->coord_canvas_pool); | |
386 | 445 |
387 DARRAY_DESTROY(&rdman->dirty_coords); | 446 DARRAY_DESTROY(&rdman->dirty_coords); |
388 DARRAY_DESTROY(&rdman->dirty_geos); | 447 DARRAY_DESTROY(&rdman->dirty_geos); |
389 DARRAY_DESTROY(&rdman->dirty_areas); | |
390 DARRAY_DESTROY(&rdman->gen_geos); | 448 DARRAY_DESTROY(&rdman->gen_geos); |
449 DARRAY_DESTROY(&rdman->zeroing_coords); | |
391 } | 450 } |
392 | 451 |
393 | 452 |
394 #define ASSERT(x) | 453 #define ASSERT(x) |
395 /* | 454 /* |
556 OBJT_COORD); | 615 OBJT_COORD); |
557 subject_set_monitor(coord->mouse_event, rdman->addrm_monitor); | 616 subject_set_monitor(coord->mouse_event, rdman->addrm_monitor); |
558 /*! \note default opacity == 1 */ | 617 /*! \note default opacity == 1 */ |
559 coord->opacity = 1; | 618 coord->opacity = 1; |
560 if(parent) | 619 if(parent) |
561 coord->canvas = parent->canvas; | 620 coord->canvas_info = parent->canvas_info; |
562 rdman->n_coords++; | 621 rdman->n_coords++; |
563 | 622 |
564 coord->order = ++rdman->next_coord_order; | 623 coord->order = ++rdman->next_coord_order; |
565 if(coord->order == 0) { | 624 if(coord->order == 0) { |
566 rdman->next_coord_order = 0; | 625 rdman->next_coord_order = 0; |
634 } | 693 } |
635 | 694 |
636 if(cm_cnt || rdman_is_dirty(rdman)) | 695 if(cm_cnt || rdman_is_dirty(rdman)) |
637 return rdman_coord_free_postponse(rdman, coord); | 696 return rdman_coord_free_postponse(rdman, coord); |
638 | 697 |
639 /* Free canvas (\ref redraw) */ | 698 /* Free canvas and canvas_info (\ref redraw) */ |
640 if(coord->flags & COF_OWN_CANVAS) | 699 if(coord->flags & COF_OWN_CANVAS) { |
641 free_canvas(coord->canvas); | 700 canvas_free(_coord_get_canvas(coord)); |
701 coord_canvas_info_free(rdman, coord->canvas_info); | |
702 } | |
642 | 703 |
643 RM_CHILD(parent, coord); | 704 RM_CHILD(parent, coord); |
644 subject_free(coord->mouse_event); | 705 subject_free(coord->mouse_event); |
645 mb_prop_store_destroy(&coord->obj.props); | 706 mb_prop_store_destroy(&coord->obj.props); |
646 elmpool_elm_free(rdman->coord_pool, coord); | 707 elmpool_elm_free(rdman->coord_pool, coord); |
730 preorder_coord_skip_subtree(child); | 791 preorder_coord_skip_subtree(child); |
731 continue; | 792 continue; |
732 } | 793 } |
733 | 794 |
734 add_dirty_coord(rdman, child); | 795 add_dirty_coord(rdman, child); |
796 | |
797 if(child->flags & COF_OWN_CANVAS) { | |
798 preorder_coord_skip_subtree(child); | |
799 continue; | |
800 } | |
735 } | 801 } |
736 | 802 |
737 return OK; | 803 return OK; |
738 } | 804 } |
739 | 805 |
811 sh_hide(shape); | 877 sh_hide(shape); |
812 else | 878 else |
813 sh_show(shape); | 879 sh_show(shape); |
814 } | 880 } |
815 | 881 |
816 /*! \brief Setup canvas for the coord. | 882 /*! \brief Setup canvas_info for the coord. |
817 * | 883 * |
818 * Own a canvas or inherit it from parent. | 884 * Own a canvas or inherit it from parent. |
819 * \sa | 885 * \sa |
820 * - \ref redraw | 886 * - \ref redraw |
821 */ | 887 */ |
822 static void setup_canvas(redraw_man_t *rdman, coord_t *coord) { | 888 static void setup_canvas_info(redraw_man_t *rdman, coord_t *coord) { |
823 if(coord->parent == NULL) | 889 if(coord->parent == NULL) |
824 return; | 890 return; |
825 | 891 |
826 if(coord->opacity != 1) { | 892 if(coord->opacity != 1 || coord_is_cached(coord)) { |
827 if(!(coord->flags & COF_OWN_CANVAS)) { | 893 if(!(coord->flags & COF_OWN_CANVAS)) { |
828 coord->canvas = new_canvas(rdman); | 894 /* canvas is assigned latter, in zeroing_coord() */ |
895 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); | |
829 coord->flags |= COF_OWN_CANVAS; | 896 coord->flags |= COF_OWN_CANVAS; |
830 } | 897 } |
831 } else { | 898 } else { |
832 if(coord->flags & COF_OWN_CANVAS) { | 899 if(coord->flags & COF_OWN_CANVAS) { |
833 free_canvas(coord->canvas); | 900 canvas_free(_coord_get_canvas(coord)); |
901 coord_canvas_info_free(rdman, coord->canvas_info); | |
834 coord->flags &= ~COF_OWN_CANVAS; | 902 coord->flags &= ~COF_OWN_CANVAS; |
835 } | 903 } |
836 coord->canvas = coord->parent->canvas; | 904 /* This must here to keep coords that do not own canvas |
837 } | 905 * can always point to right canvas_info. Since, they |
838 } | 906 * don't know when will parent change it's canvas_info. |
839 | 907 */ |
840 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { | 908 coord->canvas_info = coord->parent->canvas_info; |
909 } | |
910 } | |
911 | |
912 static int coord_clean_members_n_compute_area(coord_t *coord) { | |
841 geo_t *geo; | 913 geo_t *geo; |
842 /*! \note poses is shared by invokings, it is not support reentrying. */ | 914 /*! \note poses is shared by invokings, it is not support reentrying. */ |
843 static co_aix (*poses)[2]; | 915 static co_aix (*poses)[2]; |
844 static int max_poses = 0; | 916 static int max_poses = 0; |
845 int cnt, pos_cnt; | 917 int cnt, pos_cnt; |
846 | 918 |
847 setup_canvas(rdman, coord); | |
848 | |
849 compute_aggr_of_coord(coord); | |
850 | |
851 /* Clean member shapes. */ | 919 /* Clean member shapes. */ |
852 cnt = 0; | 920 cnt = 0; |
853 FORMEMBERS(coord, geo) { | 921 FORMEMBERS(coord, geo) { |
854 SWAP(geo->cur_area, geo->last_area, area_t *); | |
855 clean_shape(geo->shape); | 922 clean_shape(geo->shape); |
856 cnt++; | 923 cnt++; |
857 } | 924 } |
858 | 925 |
859 if(max_poses < (cnt * 2)) { | 926 if(max_poses < (cnt * 2)) { |
869 FORMEMBERS(coord, geo) { | 936 FORMEMBERS(coord, geo) { |
870 area_to_positions(geo->cur_area, poses + pos_cnt); | 937 area_to_positions(geo->cur_area, poses + pos_cnt); |
871 pos_cnt += 2; | 938 pos_cnt += 2; |
872 } | 939 } |
873 | 940 |
874 SWAP(coord->cur_area, coord->last_area, area_t *); | |
875 area_init(coord->cur_area, pos_cnt, poses); | 941 area_init(coord->cur_area, pos_cnt, poses); |
876 | 942 |
943 return OK; | |
944 } | |
945 | |
946 /*! \brief Shift space of coord to align left-top of minimum covering. | |
947 * | |
948 * Align left-top of minimum rectangle covering occupied area of | |
949 * sub-graphic to origin of the space. | |
950 */ | |
951 static | |
952 void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { | |
953 coord_t *cur; | |
954 area_t *area; | |
955 co_aix min_x, min_y; | |
956 co_aix max_x, max_y; | |
957 co_aix x, y; | |
958 int w, h; | |
959 int c_w, c_h; | |
960 cairo_t *canvas; | |
961 co_aix *aggr; | |
962 co_aix poses[2][2]; | |
963 | |
964 if(coord->parent == NULL) /*! \note Should not zeroing root coord */ | |
965 abort(); | |
966 if(!(coord_is_zeroing(coord))) | |
967 abort(); | |
968 | |
969 coord_clear_zeroing(coord); | |
970 | |
971 /* | |
972 * Compute minimum overing area of sub-graphic | |
973 */ | |
974 area = coord_get_area(coord); | |
975 min_x = area->x; | |
976 min_y = area->y; | |
977 max_x = min_x + area->w; | |
978 max_y = min_y + area->h; | |
979 | |
980 FOR_COORDS_PREORDER(coord, cur) { | |
981 area = coord_get_area(cur); | |
982 if(area->x < min_x) | |
983 min_x = area->x; | |
984 if(area->y < min_y) | |
985 min_y = area->y; | |
986 | |
987 x = area->x + area->w; | |
988 y = area->y + area->h; | |
989 | |
990 if(x > max_x) | |
991 max_x = x; | |
992 if(y > max_y) | |
993 max_y = y; | |
994 if(cur->flags & COF_OWN_CANVAS) | |
995 preorder_coord_skip_subtree(cur); | |
996 } | |
997 | |
998 w = max_x - min_x; | |
999 h = max_y - min_y; | |
1000 | |
1001 /* | |
1002 * Setup area of the coord | |
1003 */ | |
1004 aggr = coord_get_aggr_matrix(coord); | |
1005 x = y = 0; | |
1006 coord_trans_pos(coord->parent, &x, &y); | |
1007 poses[0][0] = x; | |
1008 poses[0][1] = y; | |
1009 x = w; | |
1010 y = h; | |
1011 coord_trans_pos(coord->parent, &x, &y); | |
1012 poses[1][0] = x; | |
1013 poses[1][1] = y; | |
1014 | |
1015 area_init(coord_get_area(coord), 2, poses); | |
1016 | |
1017 canvas = _coord_get_canvas(coord); | |
1018 if(canvas) | |
1019 canvas_get_size(canvas, &c_w, &c_h); | |
1020 else | |
1021 c_w = c_h = 0; | |
1022 | |
1023 if(!coord_get_flags(coord, COF_JUST_CLEAN) && | |
1024 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h) | |
1025 /* Canvas fully cover sub-graphic. */ | |
1026 return; | |
1027 | |
1028 /* | |
1029 * Adjust matrics of descendants to align left-top corner of | |
1030 * minimum covering area with origin of space defined by | |
1031 * zeroing coord. | |
1032 */ | |
1033 FOR_COORDS_PREORDER(coord, cur) { | |
1034 aggr = coord_get_aggr_matrix(cur); | |
1035 aggr[3] -= min_x; | |
1036 aggr[5] -= min_y; | |
1037 if(coord_get_flags(cur, COF_OWN_CANVAS)) { | |
1038 /* | |
1039 * Coords, zeroing, is zeroed in preorder of tree. | |
1040 * So, they are zeroed after ancesters with correctly | |
1041 * coord_t::aggr_matrix of parent coord to zeroing. | |
1042 */ | |
1043 preorder_coord_skip_subtree(cur); | |
1044 area = coord_get_area(cur); | |
1045 area->x -= min_x; | |
1046 area->y -= min_y; | |
1047 } else | |
1048 coord_clean_members_n_compute_area(cur); | |
1049 } | |
1050 | |
1051 /* | |
1052 * Setup canvas | |
1053 */ | |
1054 if(canvas == NULL || w > c_w || h > c_w) { | |
1055 if(canvas) | |
1056 canvas_free(canvas); | |
1057 canvas = canvas_new(w, h); | |
1058 _coord_set_canvas(coord, canvas); | |
1059 } | |
1060 | |
1061 area = &coord->canvas_info->cached_dirty_area; | |
1062 area->x = 0; | |
1063 area->y = 0; | |
1064 area->w = w; | |
1065 area->h = h; | |
1066 DARRAY_CLEAN(_coord_get_dirty_areas(coord)); | |
1067 add_dirty_area(rdman, coord, area); | |
1068 } | |
1069 | |
1070 /*! \brief Clean dirty coords. | |
1071 * | |
1072 * \note coords their opacity != 1 are also traded as cached ones. | |
1073 */ | |
1074 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { | |
1075 int r; | |
1076 | |
1077 setup_canvas_info(rdman, coord); | |
1078 | |
1079 if(coord->flags & COF_OWN_CANVAS) | |
1080 compute_aggr_of_cached_coord(coord); | |
1081 else | |
1082 compute_aggr_of_coord(coord); | |
1083 | |
1084 r = coord_clean_members_n_compute_area(coord); | |
1085 if(r != OK) | |
1086 return ERR; | |
1087 | |
877 coord->flags &= ~COF_DIRTY; | 1088 coord->flags &= ~COF_DIRTY; |
878 | 1089 |
879 return OK; | 1090 return OK; |
880 } | 1091 } |
881 | 1092 |
898 continue; | 1109 continue; |
899 r = clean_coord(rdman, coord); | 1110 r = clean_coord(rdman, coord); |
900 if(r != OK) | 1111 if(r != OK) |
901 return ERR; | 1112 return ERR; |
902 /* These two steps can be avoided for drawing all. */ | 1113 /* These two steps can be avoided for drawing all. */ |
903 add_dirty_area(rdman, &coord->areas[0]); | 1114 add_dirty_area(rdman, coord, &coord->areas[0]); |
904 add_dirty_area(rdman, &coord->areas[1]); | 1115 add_dirty_area(rdman, coord, &coord->areas[1]); |
905 } | 1116 } |
906 rdman->dirty_coords.num = 0; | |
907 } | 1117 } |
908 return OK; | 1118 return OK; |
909 } | 1119 } |
910 | 1120 |
911 static int clean_rdman_geos(redraw_man_t *rdman) { | 1121 static int clean_rdman_geos(redraw_man_t *rdman) { |
912 int i; | 1122 int i; |
913 int n_dirty_geos; | 1123 int n_dirty_geos; |
914 geo_t **dirty_geos; | 1124 geo_t **dirty_geos; |
915 geo_t *visit_geo; | 1125 geo_t *visit_geo; |
1126 coord_t *coord; | |
916 | 1127 |
917 n_dirty_geos = rdman->dirty_geos.num; | 1128 n_dirty_geos = rdman->dirty_geos.num; |
918 if(n_dirty_geos > 0) { | 1129 if(n_dirty_geos > 0) { |
919 dirty_geos = rdman->dirty_geos.ds; | 1130 dirty_geos = rdman->dirty_geos.ds; |
920 for(i = 0; i < n_dirty_geos; i++) { | 1131 for(i = 0; i < n_dirty_geos; i++) { |
921 visit_geo = dirty_geos[i]; | 1132 visit_geo = dirty_geos[i]; |
922 if(!(visit_geo->flags & GEF_DIRTY)) | 1133 if(!(visit_geo->flags & GEF_DIRTY)) |
923 continue; | 1134 continue; |
924 | 1135 |
925 SWAP(visit_geo->cur_area, visit_geo->last_area, area_t *); | |
926 clean_shape(visit_geo->shape); | 1136 clean_shape(visit_geo->shape); |
927 add_dirty_area(rdman, visit_geo->cur_area); | 1137 coord = geo_get_coord(visit_geo); |
928 add_dirty_area(rdman, visit_geo->last_area); | 1138 add_dirty_area(rdman, coord, visit_geo->cur_area); |
929 } | 1139 add_dirty_area(rdman, coord, visit_geo->last_area); |
930 rdman->dirty_geos.num = 0; | 1140 } |
931 } | 1141 } |
1142 | |
1143 return OK; | |
1144 } | |
1145 | |
1146 /*! \brief Add canvas owner of dirty geos to coord_t::zeroing_coords. | |
1147 * | |
1148 * All possible coords that need a zeroing have at least one dirty geo. | |
1149 */ | |
1150 static int add_rdman_zeroing_coords(redraw_man_t *rdman) { | |
1151 int i; | |
1152 int n_dirty_geos; | |
1153 geo_t **dirty_geos, *geo; | |
1154 int n_dirty_coords; | |
1155 coord_t **dirty_coords, *coord; | |
1156 | |
1157 n_dirty_geos = rdman->dirty_geos.num; | |
1158 dirty_geos = rdman->dirty_geos.ds; | |
1159 for(i = 0; i < n_dirty_geos; i++) { | |
1160 geo = dirty_geos[i]; | |
1161 coord = geo_get_coord(geo)->canvas_info->owner; | |
1162 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { | |
1163 coord_set_flags(coord, COF_TEMP_MARK); | |
1164 if(coord_is_root(coord)) | |
1165 break; | |
1166 coord = coord->parent->canvas_info->owner; | |
1167 } | |
1168 } | |
1169 | |
1170 n_dirty_coords = rdman->dirty_coords.num; | |
1171 dirty_coords = rdman->dirty_coords.ds; | |
1172 for(i = 0; i < n_dirty_coords; i++) { | |
1173 coord = dirty_coords[i]->canvas_info->owner; | |
1174 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { | |
1175 coord_set_flags(coord, COF_TEMP_MARK); | |
1176 if(coord_is_root(coord)) | |
1177 break; | |
1178 coord = coord->parent->canvas_info->owner; | |
1179 } | |
1180 } | |
1181 | |
1182 FOR_COORDS_PREORDER(rdman->root_coord, coord) { | |
1183 if(!coord_get_flags(coord, COF_TEMP_MARK)) { | |
1184 preorder_coord_skip_subtree(coord); | |
1185 continue; | |
1186 } | |
1187 add_zeroing_coord(rdman, coord); | |
1188 coord_clear_flags(coord, COF_TEMP_MARK); | |
1189 } | |
1190 | |
1191 return OK; | |
1192 } | |
1193 | |
1194 /*! \brief Zeroing coords in redraw_man_t::zeroing_coords. | |
1195 * | |
1196 * \note redraw_man_t::zeroing_coords must in ascent partial order of tree. | |
1197 */ | |
1198 static int zeroing_rdman_coords(redraw_man_t *rdman) { | |
1199 int i; | |
1200 coords_t *all_zeroing; | |
1201 coord_t *coord; | |
1202 | |
1203 all_zeroing = &rdman->zeroing_coords; | |
1204 for(i = all_zeroing->num - 1; i >= 0; i--) { | |
1205 coord = all_zeroing->ds[i]; | |
1206 if(coord_is_root(coord)) | |
1207 continue; | |
1208 zeroing_coord(rdman, coord); | |
1209 } | |
1210 | |
1211 return OK; | |
1212 } | |
1213 | |
1214 /* \brief Compute matrix from cached canvas to parent device space. | |
1215 */ | |
1216 static void compute_cached_2_pdev_matrix(coord_t *coord, | |
1217 co_aix canvas2pdev_matrix[6]) { | |
1218 coord_t *parent; | |
1219 co_aix *aggr; | |
1220 co_aix *matrix, *paggr; | |
1221 co_aix scale_x, scale_y; | |
1222 co_aix shift_x, shift_y; | |
1223 co_aix canvas2p[6]; | |
1224 | |
1225 aggr = coord_get_aggr_matrix(coord); | |
1226 matrix = coord->matrix; | |
1227 parent = coord->parent; | |
1228 paggr = coord_get_aggr_matrix(parent); | |
1229 | |
1230 scale_x = matrix[0] / aggr[0]; | |
1231 scale_y = matrix[3] / aggr[3]; | |
1232 shift_x = matrix[2] - scale_x * aggr[2]; | |
1233 shift_y = matrix[5] - scale_y * aggr[5]; | |
1234 | |
1235 canvas2p[0] = scale_x; | |
1236 canvas2p[1] = 0; | |
1237 canvas2p[2] = shift_x; | |
1238 canvas2p[3] = 0; | |
1239 canvas2p[4] = scale_y; | |
1240 canvas2p[5] = shift_y; | |
1241 | |
1242 matrix_mul(paggr, canvas2p, canvas2pdev_matrix); | |
1243 } | |
1244 | |
1245 /*! \brief Add aggregated dirty areas to ancestor. | |
1246 * | |
1247 * Dirty areas are aggregated into two areas. It assumes that even or odd | |
1248 * ones are old areas or new areas repsective. So, all even ones are | |
1249 * aggregated in an area, and odd ones are in another. | |
1250 */ | |
1251 static void add_aggr_dirty_areas_to_ancestor(redraw_man_t *rdman, | |
1252 coord_t *coord) { | |
1253 int i; | |
1254 int n_areas; | |
1255 co_aix poses0[2][2], poses1[2][2]; | |
1256 co_aix reverse[6]; | |
1257 co_aix canvas2pdev_matrix[6]; | |
1258 area_t **areas, *area; | |
1259 area_t *area0, *area1; | |
1260 coord_t *parent, *pcached_coord; | |
1261 | |
1262 n_areas = _coord_get_dirty_areas(coord)->num; | |
1263 areas = _coord_get_dirty_areas(coord)->ds; | |
1264 if(n_areas == 0) | |
1265 abort(); /* should not happen! */ | |
1266 | |
1267 area0 = coord->canvas_info->aggr_dirty_areas; | |
1268 area1 = area0 + 1; | |
1269 | |
1270 for(i = 0; i < n_areas; i++) { | |
1271 area = areas[i]; | |
1272 if(area->w != 0 || area->h != 0) | |
1273 break; | |
1274 } | |
1275 | |
1276 if(i < n_areas) { | |
1277 area = areas[i++]; | |
1278 poses0[0][0] = area->x; | |
1279 poses0[0][1] = area->y; | |
1280 poses0[1][0] = area->x + area->w; | |
1281 poses0[1][1] = area->y + area->h; | |
1282 } else { | |
1283 poses0[0][0] = 0; | |
1284 poses0[0][1] = 0; | |
1285 poses0[1][0] = 0; | |
1286 poses0[1][1] = 0; | |
1287 } | |
1288 | |
1289 if(i < n_areas) { | |
1290 area = areas[i++]; | |
1291 poses1[0][0] = area->x; | |
1292 poses1[0][1] = area->y; | |
1293 poses1[1][0] = area->x + area->w; | |
1294 poses1[1][1] = area->y + area->h; | |
1295 } else { | |
1296 poses1[0][0] = 0; | |
1297 poses1[0][1] = 0; | |
1298 poses1[1][0] = 0; | |
1299 poses1[1][1] = 0; | |
1300 } | |
1301 | |
1302 for(; i < n_areas - 1;) { | |
1303 /* Even areas */ | |
1304 area = areas[i++]; | |
1305 if(area->w != 0 || area->h != 0) { | |
1306 poses0[0][0] = MIN(poses0[0][0], area->x); | |
1307 poses0[0][1] = MIN(poses0[0][1], area->y); | |
1308 poses0[1][0] = MAX(poses0[1][0], area->x + area->w); | |
1309 poses0[1][1] = MAX(poses0[1][1], area->y + area->h); | |
1310 } | |
1311 /* Odd areas */ | |
1312 area = areas[i++]; | |
1313 if(area->w != 0 || area->h != 0) { | |
1314 poses1[0][0] = MIN(poses1[0][0], area->x); | |
1315 poses1[0][1] = MIN(poses1[0][1], area->y); | |
1316 poses1[1][0] = MAX(poses1[1][0], area->x + area->w); | |
1317 poses1[1][1] = MAX(poses1[1][1], area->y + area->h); | |
1318 } | |
1319 } | |
1320 | |
1321 if(i < n_areas) { | |
1322 area = areas[i]; | |
1323 if(area->w != 0 || area->h != 0) { | |
1324 poses0[0][0] = MIN(poses0[0][0], area->x); | |
1325 poses0[0][1] = MIN(poses0[0][1], area->y); | |
1326 poses0[1][0] = MAX(poses0[1][0], area->x + area->w); | |
1327 poses0[1][1] = MAX(poses0[1][1], area->y + area->h); | |
1328 } | |
1329 } | |
1330 | |
1331 parent = coord->parent; | |
1332 pcached_coord = parent->canvas_info->owner; | |
1333 | |
1334 compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); | |
1335 | |
1336 matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1); | |
1337 matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1); | |
1338 area_init(area0, 2, poses0); | |
1339 add_dirty_area(rdman, pcached_coord, area0); | |
1340 | |
1341 matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1); | |
1342 matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1); | |
1343 area_init(area1, 2, poses1); | |
1344 if(area1->w != 0 || area1->h != 0) | |
1345 add_dirty_area(rdman, pcached_coord, area1); | |
1346 | |
1347 if(coord_get_flags(coord, COF_JUST_CLEAN) && | |
1348 !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) | |
1349 add_dirty_area(rdman, pcached_coord, coord->last_area); | |
1350 } | |
1351 | |
1352 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { | |
1353 int i; | |
1354 int n_zeroing; | |
1355 coord_t **zeroings; | |
1356 coord_t *coord; | |
1357 | |
1358 n_zeroing = rdman->zeroing_coords.num; | |
1359 zeroings = rdman->zeroing_coords.ds; | |
1360 for(i = n_zeroing - 1; i >= 0; i--) { | |
1361 coord = zeroings[i]; | |
1362 if(!coord_is_root(coord)) | |
1363 add_aggr_dirty_areas_to_ancestor(rdman, coord); | |
1364 } | |
1365 | |
1366 return OK; | |
1367 } | |
1368 | |
1369 static int add_rdman_cached_dirty_areas(redraw_man_t *rdman) { | |
1370 int i; | |
1371 coord_t *coord, **dirty_coords; | |
1372 int n_dirty_coords; | |
1373 | |
1374 n_dirty_coords = rdman->dirty_coords.num; | |
1375 dirty_coords = rdman->dirty_coords.ds; | |
1376 for(i = 0; i < n_dirty_coords; i++) { | |
1377 coord = dirty_coords[i]; | |
1378 if(coord_get_flags(coord, COF_OWN_CANVAS)) { | |
1379 add_dirty_area(rdman, coord, coord->cur_area); | |
1380 add_dirty_area(rdman, coord, coord->last_area); | |
1381 } | |
1382 } | |
932 | 1383 |
933 return OK; | 1384 return OK; |
934 } | 1385 } |
935 | 1386 |
936 static int clean_rdman_dirties(redraw_man_t *rdman) { | 1387 static int clean_rdman_dirties(redraw_man_t *rdman) { |
937 int r; | 1388 int r; |
1389 int i; | |
1390 coord_t **coords; | |
1391 geo_t **geos; | |
1392 | |
1393 coords = rdman->dirty_coords.ds; | |
1394 for(i = 0; i < rdman->dirty_coords.num; i++) | |
1395 if(coords[i]->flags & COF_DIRTY) | |
1396 SWAP(coords[i]->cur_area, coords[i]->last_area, area_t *); | |
1397 | |
1398 geos = rdman->dirty_geos.ds; | |
1399 for(i = 0; i < rdman->dirty_geos.num; i++) | |
1400 if(geos[i]->flags & GEF_DIRTY) | |
1401 SWAP(geos[i]->cur_area, geos[i]->last_area, area_t *); | |
938 | 1402 |
939 r = clean_rdman_coords(rdman); | 1403 r = clean_rdman_coords(rdman); |
940 if(r != OK) | 1404 if(r != OK) |
941 return ERR; | 1405 return ERR; |
1406 | |
1407 for(i = 0; i < rdman->dirty_coords.num; i++) | |
1408 coord_set_flags(rdman->dirty_coords.ds[i], COF_JUST_CLEAN); | |
942 | 1409 |
943 r = clean_rdman_geos(rdman); | 1410 r = clean_rdman_geos(rdman); |
944 if(r != OK) | 1411 if(r != OK) |
945 return ERR; | 1412 return ERR; |
946 | 1413 |
1414 r = add_rdman_zeroing_coords(rdman); | |
1415 if(r != OK) | |
1416 return ERR; | |
1417 | |
1418 r = zeroing_rdman_coords(rdman); | |
1419 if(r != OK) | |
1420 return ERR; | |
1421 | |
1422 r = add_rdman_aggr_dirty_areas(rdman); | |
1423 if(r != OK) | |
1424 return ERR; | |
1425 | |
1426 r = add_rdman_cached_dirty_areas(rdman); | |
1427 if(r != OK) | |
1428 return ERR; | |
1429 | |
1430 for(i = 0; i < rdman->dirty_coords.num; i++) | |
1431 coord_clear_flags(rdman->dirty_coords.ds[i], COF_JUST_CLEAN); | |
1432 | |
947 return OK; | 1433 return OK; |
948 } | 1434 } |
949 | 1435 |
950 | 1436 |
951 /* Drawing and Redrawing | 1437 /* Drawing and Redrawing |
1026 } | 1512 } |
1027 } | 1513 } |
1028 } | 1514 } |
1029 | 1515 |
1030 #ifndef UNITTEST | 1516 #ifndef UNITTEST |
1517 static void clear_canvas(canvas_t *canvas) { | |
1518 cairo_operator_t old_op; | |
1519 | |
1520 #if 1 | |
1521 old_op = cairo_get_operator(canvas); | |
1522 cairo_set_operator(canvas, CAIRO_OPERATOR_CLEAR); | |
1523 cairo_paint(canvas); | |
1524 cairo_set_operator(canvas, old_op); | |
1525 #else | |
1526 cairo_set_source_rgba(canvas, 0, 0, 0, 0); | |
1527 cairo_paint(canvas); | |
1528 #endif | |
1529 } | |
1530 | |
1031 static void clean_canvas(cairo_t *cr, co_aix w, co_aix h) { | 1531 static void clean_canvas(cairo_t *cr, co_aix w, co_aix h) { |
1532 cairo_operator_t saved_op; | |
1533 | |
1534 saved_op = cairo_get_operator(cr); | |
1535 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); | |
1536 | |
1032 /*! \todo clean to background color. */ | 1537 /*! \todo clean to background color. */ |
1033 cairo_set_source_rgb(cr, 1, 1, 1); | 1538 cairo_set_source_rgba(cr, 1, 1, 1, 1); |
1034 #if 1 | 1539 |
1035 /* For some unknown reasons, cairo_paint() can not erease | 1540 /* For some unknown reasons, cairo_paint() can not erease |
1036 * painted graphic cleanly. So, cairo_fill() are used to | 1541 * painted graphic cleanly. So, cairo_fill() are used to |
1037 * replace it. | 1542 * replace it. |
1038 */ | 1543 */ |
1039 cairo_rectangle(cr, 0, 0, w, h); | 1544 cairo_rectangle(cr, 0, 0, w, h); |
1040 cairo_fill(cr); | 1545 cairo_fill(cr); |
1041 #else | 1546 |
1042 cairo_paint(cr); | 1547 cairo_set_operator(cr, saved_op); |
1043 #endif | |
1044 } | 1548 } |
1045 | 1549 |
1046 static void clean_canvas_black(cairo_t *cr, co_aix w, co_aix h) { | 1550 static void clean_canvas_black(cairo_t *cr, co_aix w, co_aix h) { |
1551 clear_canvas(cr); | |
1552 | |
1047 /*! \todo clean to background color. */ | 1553 /*! \todo clean to background color. */ |
1048 cairo_set_source_rgba(cr, 0, 0, 0, 0); | 1554 cairo_set_source_rgba(cr, 0, 0, 0, 0); |
1049 cairo_paint(cr); | 1555 cairo_paint(cr); |
1050 } | 1556 } |
1051 | 1557 |
1059 cairo_rectangle(cr, area->x, area->y, area->w, area->h); | 1565 cairo_rectangle(cr, area->x, area->y, area->w, area->h); |
1060 } | 1566 } |
1061 cairo_clip(cr); | 1567 cairo_clip(cr); |
1062 } | 1568 } |
1063 | 1569 |
1064 static void reset_clip(redraw_man_t *rdman) { | 1570 static void reset_clip(canvas_t *cr) { |
1065 cairo_reset_clip(rdman->backend); | 1571 cairo_reset_clip(cr); |
1066 } | 1572 } |
1067 | 1573 |
1068 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, | 1574 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, |
1069 area_t **dirty_areas) { | 1575 area_t **dirty_areas) { |
1576 cairo_operator_t saved_op; | |
1577 | |
1070 if(n_dirty_areas) | 1578 if(n_dirty_areas) |
1071 make_clip(rdman->backend, n_dirty_areas, dirty_areas); | 1579 make_clip(rdman->backend, n_dirty_areas, dirty_areas); |
1072 | 1580 |
1581 saved_op = cairo_get_operator(rdman->backend); | |
1582 cairo_set_operator(rdman->backend, CAIRO_OPERATOR_SOURCE); | |
1073 cairo_paint(rdman->backend); | 1583 cairo_paint(rdman->backend); |
1584 cairo_set_operator(rdman->backend, saved_op); | |
1074 } | 1585 } |
1075 #else /* UNITTEST */ | 1586 #else /* UNITTEST */ |
1076 static void clean_canvas(cairo_t *cr, co_aix w, co_aix h) { | 1587 static void clean_canvas(cairo_t *cr, co_aix w, co_aix h) { |
1077 } | 1588 } |
1078 | 1589 |
1079 static void clean_canvas_black(cairo_t *cr, co_aix w, co_aix h) { | 1590 static void clean_canvas_black(cairo_t *cr, co_aix w, co_aix h) { |
1080 } | 1591 } |
1081 | 1592 |
1082 static void reset_clip(redraw_man_t *rdman) { | 1593 static void reset_clip(canvas_t *cr) { |
1083 } | 1594 } |
1084 | 1595 |
1085 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, | 1596 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, |
1086 area_t **dirty_areas) { | 1597 area_t **dirty_areas) { |
1087 } | 1598 } |
1088 #endif /* UNITTEST */ | 1599 #endif /* UNITTEST */ |
1600 | |
1601 static int is_area_in_areas(area_t *area, | |
1602 int n_areas, | |
1603 area_t **areas) { | |
1604 int i; | |
1605 | |
1606 for(i = 0; i < n_areas; i++) { | |
1607 if(areas_are_overlay(area, areas[i])) | |
1608 return 1; | |
1609 } | |
1610 return 0; | |
1611 } | |
1089 | 1612 |
1090 static int is_geo_in_areas(geo_t *geo, | 1613 static int is_geo_in_areas(geo_t *geo, |
1091 int n_areas, | 1614 int n_areas, |
1092 area_t **areas) { | 1615 area_t **areas) { |
1093 int i; | 1616 return is_area_in_areas(geo->cur_area, n_areas, areas); |
1094 | 1617 } |
1095 for(i = 0; i < n_areas; i++) { | 1618 |
1096 if(areas_are_overlay(geo->cur_area, areas[i])) | 1619 static void update_cached_canvas_2_parent(redraw_man_t *rdman, |
1097 return 1; | 1620 coord_t *coord) { |
1098 } | |
1099 return 0; | |
1100 } | |
1101 | |
1102 static void update_canvas_2_parent(redraw_man_t *rdman, coord_t *coord) { | |
1103 cairo_t *pcanvas, *canvas; | 1621 cairo_t *pcanvas, *canvas; |
1104 cairo_surface_t *surface; | 1622 cairo_surface_t *surface; |
1105 | 1623 cairo_pattern_t *pattern; |
1106 if(coord == rdman->root_coord) | 1624 cairo_matrix_t cr_matrix; |
1625 co_aix reverse[6]; | |
1626 co_aix canvas2pdev_matrix[6]; | |
1627 | |
1628 if(coord_is_root(coord)) | |
1107 return; | 1629 return; |
1108 | 1630 |
1109 canvas = coord->canvas; | 1631 compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); |
1110 pcanvas = coord->parent->canvas; | 1632 compute_reverse(canvas2pdev_matrix, reverse); |
1633 | |
1634 cr_matrix.xx = reverse[0]; | |
1635 cr_matrix.xy = reverse[1]; | |
1636 cr_matrix.x0 = reverse[2]; | |
1637 cr_matrix.yx = reverse[3]; | |
1638 cr_matrix.yy = reverse[4]; | |
1639 cr_matrix.y0 = reverse[5]; | |
1640 | |
1641 canvas = _coord_get_canvas(coord); | |
1642 pcanvas = _coord_get_canvas(coord->parent); | |
1111 surface = cairo_get_target(canvas); | 1643 surface = cairo_get_target(canvas); |
1112 cairo_set_source_surface(pcanvas, surface, 0, 0); | 1644 pattern = cairo_pattern_create_for_surface(surface); |
1645 cairo_pattern_set_matrix(pattern, &cr_matrix); | |
1646 cairo_set_source(pcanvas, pattern); | |
1113 cairo_paint_with_alpha(pcanvas, coord->opacity); | 1647 cairo_paint_with_alpha(pcanvas, coord->opacity); |
1114 } | 1648 } |
1115 | 1649 |
1116 static int draw_coord_shapes_in_areas(redraw_man_t *rdman, | 1650 static int draw_coord_shapes_in_dirty_areas(redraw_man_t *rdman, |
1117 coord_t *coord, | 1651 coord_t *coord) { |
1118 int n_areas, | |
1119 area_t **areas) { | |
1120 int dirty = 0; | 1652 int dirty = 0; |
1121 int r; | 1653 int r; |
1654 area_t **areas; | |
1655 int n_areas; | |
1656 cairo_t *canvas; | |
1122 geo_t *member; | 1657 geo_t *member; |
1123 coord_t *child; | 1658 coord_t *child; |
1124 cairo_t *canvas; | |
1125 int mem_idx; | 1659 int mem_idx; |
1126 | 1660 |
1127 if(coord->flags & COF_HIDDEN) | 1661 if(coord->flags & COF_HIDDEN) |
1128 return OK; | 1662 return OK; |
1129 | 1663 |
1130 canvas = coord->canvas; | 1664 areas = _coord_get_dirty_areas(coord)->ds; |
1665 n_areas = _coord_get_dirty_areas(coord)->num; | |
1666 canvas = _coord_get_canvas(coord); | |
1667 | |
1131 member = FIRST_MEMBER(coord); | 1668 member = FIRST_MEMBER(coord); |
1132 mem_idx = 0; | 1669 mem_idx = 0; |
1133 child = FIRST_CHILD(coord); | 1670 child = FIRST_CHILD(coord); |
1134 while(child != NULL || member != NULL) { | 1671 while(child != NULL || member != NULL) { |
1135 if(child && child->before_pmem == mem_idx) { | 1672 if(child && child->before_pmem == mem_idx) { |
1136 r = draw_coord_shapes_in_areas(rdman, child, n_areas, areas); | 1673 if(child->flags & COF_OWN_CANVAS) { |
1137 dirty |= r; | 1674 if(!(child->flags & COF_HIDDEN) && |
1675 is_area_in_areas(coord_get_area(child), n_areas, areas)) { | |
1676 update_cached_canvas_2_parent(rdman, child); | |
1677 dirty = 1; | |
1678 } | |
1679 } else { | |
1680 r = draw_coord_shapes_in_dirty_areas(rdman, child); | |
1681 dirty |= r; | |
1682 } | |
1138 child = NEXT_CHILD(child); | 1683 child = NEXT_CHILD(child); |
1139 } else { | 1684 } else { |
1140 ASSERT(member != NULL); | 1685 ASSERT(member != NULL); |
1141 if((!(member->flags & GEF_HIDDEN)) && | 1686 if((!(member->flags & GEF_HIDDEN)) && |
1142 is_geo_in_areas(member, n_areas, areas)) { | 1687 is_geo_in_areas(member, n_areas, areas)) { |
1147 member = NEXT_MEMBER(member); | 1692 member = NEXT_MEMBER(member); |
1148 mem_idx++; | 1693 mem_idx++; |
1149 } | 1694 } |
1150 } | 1695 } |
1151 | 1696 |
1152 if(dirty && coord->flags & COF_OWN_CANVAS) { | |
1153 update_canvas_2_parent(rdman, coord); | |
1154 clean_canvas_black(coord->canvas, rdman->w, rdman->h); | |
1155 } | |
1156 | |
1157 return dirty; | 1697 return dirty; |
1158 } | 1698 } |
1159 | 1699 |
1160 static void draw_shapes_in_areas(redraw_man_t *rdman, | 1700 static int draw_dirty_cached_coord(redraw_man_t *rdman, |
1161 int n_areas, | 1701 coord_t *coord) { |
1162 area_t **areas) { | 1702 area_t **areas, *area; |
1163 draw_coord_shapes_in_areas(rdman, rdman->root_coord, n_areas, areas); | 1703 int n_areas; |
1704 cairo_t *canvas; | |
1705 int i; | |
1706 int r; | |
1707 | |
1708 areas = _coord_get_dirty_areas(coord)->ds; | |
1709 n_areas = _coord_get_dirty_areas(coord)->num; | |
1710 | |
1711 for(i = 0; i < n_areas; i++) { | |
1712 area = areas[i]; | |
1713 area->x = floorf(area->x); | |
1714 area->y = floorf(area->y); | |
1715 area->w = ceilf(area->w); | |
1716 area->h = ceilf(area->h); | |
1717 } | |
1718 | |
1719 canvas = _coord_get_canvas(coord); | |
1720 make_clip(canvas, n_areas, areas); | |
1721 clear_canvas(canvas); | |
1722 | |
1723 r = draw_coord_shapes_in_dirty_areas(rdman, coord); | |
1724 | |
1725 reset_clip(canvas); | |
1726 } | |
1727 | |
1728 static void draw_shapes_in_dirty_areas(redraw_man_t *rdman) { | |
1729 int i; | |
1730 coord_t *coord; | |
1731 | |
1732 for(i = rdman->zeroing_coords.num - 1; i >= 0; i--) { | |
1733 coord = rdman->zeroing_coords.ds[i]; | |
1734 draw_dirty_cached_coord(rdman, coord); | |
1735 } | |
1164 } | 1736 } |
1165 | 1737 |
1166 | 1738 |
1167 /*! \brief Re-draw all changed shapes or shapes affected by changed coords. | 1739 /*! \brief Re-draw all changed shapes or shapes affected by changed coords. |
1168 * | 1740 * |
1196 * corod objects. | 1768 * corod objects. |
1197 * | 1769 * |
1198 */ | 1770 */ |
1199 int rdman_redraw_changed(redraw_man_t *rdman) { | 1771 int rdman_redraw_changed(redraw_man_t *rdman) { |
1200 int r; | 1772 int r; |
1201 int n_dirty_areas; | |
1202 area_t **dirty_areas; | |
1203 event_t event; | 1773 event_t event; |
1204 subject_t *redraw; | 1774 subject_t *redraw; |
1205 | 1775 int i; |
1776 coord_t *coord, **coords; | |
1777 int n_areas; | |
1778 area_t **areas; | |
1779 | |
1206 r = clean_rdman_dirties(rdman); | 1780 r = clean_rdman_dirties(rdman); |
1207 if(r != OK) | 1781 if(r != OK) |
1208 return ERR; | 1782 return ERR; |
1209 | 1783 |
1210 n_dirty_areas = rdman->dirty_areas.num; | 1784 if(rdman->n_dirty_areas > 0) { |
1211 dirty_areas = rdman->dirty_areas.ds; | |
1212 if(n_dirty_areas > 0) { | |
1213 /*! \brief Draw shapes in preorder of coord tree and support opacity | 1785 /*! \brief Draw shapes in preorder of coord tree and support opacity |
1214 * rules. | 1786 * rules. |
1215 */ | 1787 */ |
1216 clean_canvas(rdman->cr, rdman->w, rdman->h); | 1788 draw_shapes_in_dirty_areas(rdman); |
1217 draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas); | 1789 n_areas = _coord_get_dirty_areas(rdman->root_coord)->num; |
1218 copy_cr_2_backend(rdman, rdman->dirty_areas.num, | 1790 areas = _coord_get_dirty_areas(rdman->root_coord)->ds; |
1219 rdman->dirty_areas.ds); | 1791 copy_cr_2_backend(rdman, n_areas, areas); |
1220 reset_clip(rdman); | 1792 reset_clip(rdman->backend); |
1221 } | 1793 for(i = 0; i < rdman->zeroing_coords.num; i++) { |
1222 rdman->dirty_areas.num = 0; | 1794 coord = rdman->zeroing_coords.ds[i]; |
1223 | 1795 DARRAY_CLEAN(_coord_get_dirty_areas(coord)); |
1796 } | |
1797 rdman->n_dirty_areas = 0; | |
1798 } | |
1799 | |
1800 coords = rdman->zeroing_coords.ds; | |
1801 for(i = 0; i < rdman->zeroing_coords.num; i++) { | |
1802 coord = coords[i]; | |
1803 coord_clear_flags(coord, COF_MUST_ZEROING); | |
1804 } | |
1805 | |
1806 DARRAY_CLEAN(&rdman->dirty_coords); | |
1807 DARRAY_CLEAN(&rdman->dirty_geos); | |
1808 DARRAY_CLEAN(&rdman->zeroing_coords); | |
1809 | |
1224 /* Free postponsed removing */ | 1810 /* Free postponsed removing */ |
1225 free_free_objs(rdman); | 1811 free_free_objs(rdman); |
1226 | 1812 |
1227 redraw = rdman_get_redraw_subject(rdman); | 1813 redraw = rdman_get_redraw_subject(rdman); |
1228 event.type = EVT_RDMAN_REDRAW; | 1814 event.type = EVT_RDMAN_REDRAW; |
1254 * | 1840 * |
1255 * \sa | 1841 * \sa |
1256 * - rdman_redraw_all() | 1842 * - rdman_redraw_all() |
1257 * - rdman_redraw_changed() | 1843 * - rdman_redraw_changed() |
1258 * - draw_shapes_in_areas() | 1844 * - draw_shapes_in_areas() |
1845 * | |
1846 * \section img_cache Image Cache | |
1847 * It costs time to redraw every component in a complete graphic. | |
1848 * Image cache try to cache result of prviously rendering, and reusing it | |
1849 * to avoid wasting CPU time on repeatitive and redundant rendering. | |
1850 * | |
1851 * \ref COF_FAST_CACHE and \ref COF_PRECISE_CACHE are used to tag a | |
1852 * coord that it's | |
1853 * rendering result is cached in fast way or precise way. With fast cache, | |
1854 * MB renders descendants of a coord in once, and reuse the result until it | |
1855 * being dirty. With precise cache, it alike fast cache, but it also | |
1856 * performs rendering when an ancester of the coord transform it to larger | |
1857 * size, in width or height. | |
1858 * | |
1859 * coord_t::aggr_matrix of a cached coord is computed from aggr_matrix of | |
1860 * parent. But, it does not use one from parent directly. parent one is | |
1861 * transformed as | |
1862 * \code | |
1863 * cache_scale_x = sqrt(p_matrix[0]**2 + p_matrix[3]**2); | |
1864 * cache_scale_y = sqrt(p_matrix[1]**2 + p_matrix[4]**2); | |
1865 * cache_p_matrix[0] = cache_scale_x; | |
1866 * cache_p_matrix[1] = 0; | |
1867 * cache_p_matrix[2] = range_shift_x; | |
1868 * cache_p_matrix[3] = 0; | |
1869 * cache_p_matrix[4] = cache_scale_y; | |
1870 * cache_p_matrix[5] = range_shift_y; | |
1871 * \endcode | |
1872 * where p_matrix is parent one, and cache_p_matrix is one derived from | |
1873 * parent one. coord_t::aggr_matrix of a cached coord is | |
1874 * \code | |
1875 * aggr_matrix = cache_p_matrix * matrix | |
1876 * \endcode | |
1877 * where matrix is the transform being installed on the cached coord. | |
1878 * range_shift_x and range_shift_y are defined above. | |
1879 * | |
1880 * cache_p_matrix rescales sub-graphic to an appropriately size | |
1881 * (cache_scale_x, cache_scale_y) and aligns left-top of the minimum | |
1882 * rectangle (range_shift_x, range_shift_y) that cover the area occupied | |
1883 * by sub-graphic with origin of the space. | |
1884 * | |
1885 * The sub-graphic should be rendered on space defined by cache_p_matrix of | |
1886 * cached one. But rendering result are transformed to the space defined | |
1887 * by parent with following matrix. | |
1888 * \code | |
1889 * draw_matrix = reverse(p_matrix * reverse(cache_p_matrix)) | |
1890 * \endcode | |
1891 * With Cairo, draw_matrix is applied on source surface (canvas) | |
1892 * to draw image to parent's surface (canvas). draw_matrix is a function | |
1893 * map points from parent space to the space of cached one. | |
1894 * | |
1895 * Cached coords are marked for changing transformation of ancestors only if | |
1896 * following condition is true. | |
1897 * \code | |
1898 * cache_scale_x < sqrt(p_matrix[0]**2 + p_matrix[3]**2) || | |
1899 * cache_scale_y < sqrt(p_matrix[1]**2 + p_matrix[4]**2) | |
1900 * \endcode | |
1901 * where p_matrix is latest aggr_matrix of parent after changing | |
1902 * transformation, and where cache_scale_* are ones mention above and computed | |
1903 * before changing transformation of ancestors. | |
1904 * | |
1905 * Cache_scale_* can be recovered by following instructions. | |
1906 * \code | |
1907 * cache_scale_x = aggr_matrix[0] / matrix[0]; | |
1908 * cache_scale_y = aggr_matrix[4] / matrix[4]; | |
1909 * \endcode | |
1910 * | |
1911 * \section cache_area Area of cached coord | |
1912 * - *_transform of shapes works as normal | |
1913 * - areas of descendants of cached coord are in space defined | |
1914 * by aggr_matrix of cached coord. | |
1915 * - descendants are marked with \ref COF_ANCESTOR_CACHE | |
1916 * | |
1917 * Since *_transform of shapes compute area with aggr_matrix that is | |
1918 * derived from aggr_matrix of a cached ancestor, area of | |
1919 * \ref COF_ANCESTOR_CACHE ones should be transformed to device space in | |
1920 * find_shape_at_pos() with following statement. | |
1921 * \code | |
1922 * area_matrix = p_matrix * reverse(cache_p_matrix) | |
1923 * \endcode | |
1924 * where cache_p_matrix and p_matrix are corresponding matrix of | |
1925 * cached ancestor. We can also perform transforming in reversed | |
1926 * direction to transform point to space defined by aggr_matrix of cached | |
1927 * coord. | |
1928 * | |
1929 * Since it is costly to transform area of \ref COF_ANCESTOR_CACHE ones to | |
1930 * device space if more than one ancestor are cached, no ancestor of | |
1931 * cached coord can be set to cached. | |
1932 * | |
1933 * \section cached_bounding Bounding box of cached coord and descendants | |
1934 * Bounding box of a cached coord and it's descendants is the range that | |
1935 * cached coord and descendants are rendered on canvas. It is also called | |
1936 * cached-bounding. | |
1937 * | |
1938 * range_shift_x and range_shift_y are computed by initailizing cache_p_matrix | |
1939 * with range_shift_x == range_shift_y == 0 at first. cache_p_matrix is | |
1940 * used to compute aggr_matrix and cached-bounding in turn. Then, | |
1941 * range_shift_x and range_shift_y are initialized to negative of | |
1942 * x-axis and y-axis, repectively, of left-top of cached-bounding. Then, | |
1943 * aggr_matrix of cached coord and descendants are updated by | |
1944 * following statements. | |
1945 * \code | |
1946 * aggr_matrix[2] += range_shift_x; | |
1947 * aggr_matrix[5] += range_shift_y; | |
1948 * \endcode | |
1949 * The statements shift the spaces to make cached-bounding | |
1950 * aligned to origin of coordinate system. | |
1951 * The purpose of range_shift_* is to reduce size of canvas used to cache | |
1952 * rendering result. The canvas are shrink to size the same as bounding | |
1953 * box. | |
1954 * | |
1955 * \section cache_redraw How cache and redraw work together? | |
1956 * When a coord and descedants are cached, the coord is flaged with | |
1957 * COF_FAST_CACHE or COF_PRECISE_CACHE. When a coord is marked dirty, all | |
1958 * descendants are also marked dirty by rdman except descendants of cached | |
1959 * ones. But, cached ones are also marked dirty as normal ones. The | |
1960 * reason to mark cached ones is giving them a chance to update their | |
1961 * area. | |
1962 * | |
1963 * For precise cached descendants, above rule has an exception. They should | |
1964 * also be marked dirty if cached coord should be rendered in a larger | |
1965 * resize factor to get better output. | |
1966 * | |
1967 * coord_t::aggr_matrix and cached-bounding of cached coord must be computed | |
1968 * in the way described in \ref cached_bounding. Propagating range_shift_* | |
1969 * to descendants must skip cached ones and their descendants. | |
1970 * Range_shift_* are computed after updating descendants. So, procedure | |
1971 * of clean descendants of a cached one must performed in two phases. | |
1972 * One for computing areas of descendants and one for propagating | |
1973 * range_shift_*. | |
1974 * | |
1975 * A cached coord or/and descendants are dirty only for cached coord or | |
1976 * descendants being marked dirty by application. Once a cached coord or | |
1977 * descendant is marked dirty, all descendants of marked one are also | |
1978 * marked. redraw_man_t::dirty_areas collects areas, in device space, | |
1979 * that should be updated. All shapes overlaid with any area in | |
1980 * redraw_man_t::dirty_areas should be redraw. Since descendants of cached | |
1981 * coord compute their areas in spaces other than device space. | |
1982 * Separated lists should be maintained for each cached coord and it's | |
1983 * descendants. | |
1984 * | |
1985 * \section cache_imp Implementation of Cache | |
1986 * Both cached coords and coords that opacity != 1 need a canvas to | |
1987 * draw descendants on. Both cases are traded in the same way. | |
1988 * Every of them own a canvas_info to describe canvas and related | |
1989 * information. aggr_matrix of descendants must be adjusted to make | |
1990 * left-top of range just at origin of canvas. It can save space by setting | |
1991 * just large enough to hold rendering result of descendants. The process | |
1992 * of adjusting is zeroing. | |
1993 * | |
1994 * Following is rules. | |
1995 * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix | |
1996 * of the cached coord and descendnats. | |
1997 * - Clean coords works just like before without change. | |
1998 * - in preorder | |
1999 * - never perform zeroing on root_coord. | |
2000 * - zeroing on cached coords marked with \ref COF_MUST_ZEROING. | |
2001 * - when clean a descendant that moves out-side of it's canvas, | |
2002 * respective cached coord is marked with \ref COF_MUST_ZEROING. | |
2003 * - zeroing is performed immediately after clean coords. | |
2004 * - zeroing will not propagate acrossing boundary of cached coord. | |
2005 * - It will be stopped at descendants which are cached coords. | |
2006 * - coord_t::cur_area and coord_t::aggr_matrix of cached coords | |
2007 * must be ajdusted. | |
2008 * - the area of a cached coord is defined in parent space. | |
2009 * - areas of descendants are defined in space defined by aggr_matrix of | |
2010 * cached coord. | |
2011 * - parent know the area in where cached coord and descendnats will | |
2012 * be draw. | |
2013 * - cached coords keep their private dirty area list. | |
2014 * - private dirty areas of a cached coord are transformed and added to | |
2015 * parent cached coord. | |
2016 * - aggregates areas before adding to parent. | |
2017 * - canvas of a cached coord is updated if | |
2018 * - descendants are dirty, or | |
2019 * - it-self is dirty. | |
2020 * - change of a canvas must copy to canvas of parent space. | |
2021 * - a cached is updated if canvas of descendant cached coord is updated. | |
2022 * - updating canvas is performed by redraw dirty areas. | |
2023 * - since dirty areas of cached ones would be aggregated and added to | |
2024 * parent, parent cached coord would copy it from cache of descedants. | |
2025 * - descendant cached coords must be updated before ancestor cached coords. | |
2026 * - add dirty areas to parent immediately after updating canvas. | |
2027 * - Making dirty coords is not propagated through cached ones. | |
2028 * - cached ones are also made dirty, but stop after that. | |
2029 * | |
2030 * Steps: | |
2031 * - SWAP coord_t::cur_area of dirty coords. | |
2032 * - SWAP geo_t::cur_area of dirty geos. | |
2033 * - clean coords | |
2034 * - coord_t::aggr_matrix of cached coord is not the same as non-cached. | |
2035 * - see \ref img_cache | |
2036 * - clean geos | |
2037 * - Add canvas owner of dirty geos to redraw_man_t::zeroing_coords | |
2038 * - Cached ancestors of redraw_man_t::dirty_geos | |
2039 * - Cached ancestors of redraw_man_t::dirty_coords | |
2040 * - Cached ancestors of zeroed ones should also be zeroed. | |
2041 * - zeroing | |
2042 * - Add more dirty areas if canvas should be fully redrawed. | |
2043 * - From leaf to root. | |
2044 * - add aggregated dirty areas from descendant cached coords to ancestors. | |
2045 * - Must include old area of cached coords if it is just clean and | |
2046 * parent cached one is not just clean. | |
2047 * - Just clean is a coord cleaned in last time of cleaning coords. | |
2048 * - draw dirty areas | |
2049 * - areas are rounded to N at first. | |
2050 * - from leaf to root. | |
1259 */ | 2051 */ |
1260 | 2052 |
1261 int rdman_redraw_all(redraw_man_t *rdman) { | 2053 int rdman_redraw_all(redraw_man_t *rdman) { |
1262 area_t area; | 2054 area_t area; |
1263 #ifndef UNITTEST | 2055 #ifndef UNITTEST |
1272 area.h = cairo_image_surface_get_height(surface); | 2064 area.h = cairo_image_surface_get_height(surface); |
1273 #else | 2065 #else |
1274 area.w = 1024; | 2066 area.w = 1024; |
1275 area.h = 1024; | 2067 area.h = 1024; |
1276 #endif | 2068 #endif |
1277 add_dirty_area(rdman, &area); | 2069 add_dirty_area(rdman, rdman->root_coord, &area); |
1278 | 2070 |
1279 r = rdman_redraw_changed(rdman); | 2071 r = rdman_redraw_changed(rdman); |
1280 if(r != OK) | 2072 if(r != OK) |
1281 return ERR; | 2073 return ERR; |
1282 | 2074 |
1290 | 2082 |
1291 area.x = x; | 2083 area.x = x; |
1292 area.y = y; | 2084 area.y = y; |
1293 area.w = w; | 2085 area.w = w; |
1294 area.h = h; | 2086 area.h = h; |
1295 add_dirty_area(rdman, &area); | 2087 add_dirty_area(rdman, rdman->root_coord, &area); |
1296 | 2088 |
1297 r = rdman_redraw_changed(rdman); | 2089 r = rdman_redraw_changed(rdman); |
1298 | 2090 |
1299 return r; | 2091 return r; |
1300 } | 2092 } |
1301 | 2093 |
2094 /*! \brief Helping function to travel descendant shapes of a coord. | |
2095 */ | |
1302 geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) { | 2096 geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) { |
1303 geo_t *next; | 2097 geo_t *next; |
1304 coord_t *coord; | 2098 coord_t *coord; |
1305 | 2099 |
1306 if(last == NULL) { | 2100 if(last == NULL) { |