comparison src/redraw_man.c @ 1067:7b4e80ab671a openvg

merge from default branch
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 01 Dec 2010 12:25:56 +0800
parents b42d69ab8857 a8d20bc8ce40
children d09f603438d8
comparison
equal deleted inserted replaced
630:bd18951b51d5 1067:7b4e80ab671a
1 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
2 // vim: sw=4:ts=8:sts=4
1 #include <stdio.h> 3 #include <stdio.h>
2 #include <stdlib.h> 4 #include <stdlib.h>
3 #include <string.h> 5 #include <string.h>
4 #include <math.h> 6 #include <math.h>
5 #include "mb_graph_engine.h" 7 #include "mb_graph_engine.h"
156 * \section cache_area Area of cached coord 158 * \section cache_area Area of cached coord
157 * - *_transform of shapes works as normal 159 * - *_transform of shapes works as normal
158 * - areas of descendants of cached coord are in space defined 160 * - areas of descendants of cached coord are in space defined
159 * by aggr_matrix of cached coord. 161 * by aggr_matrix of cached coord.
160 * - descendants are marked with \ref COF_ANCESTOR_CACHE 162 * - descendants are marked with \ref COF_ANCESTOR_CACHE
161 * 163 *
162 * Since *_transform of shapes compute area with aggr_matrix that is 164 * Since *_transform of shapes compute area with aggr_matrix that is
163 * derived from aggr_matrix of a cached ancestor, area of 165 * derived from aggr_matrix of a cached ancestor, area of
164 * \ref COF_ANCESTOR_CACHE ones should be transformed to device space in 166 * \ref COF_ANCESTOR_CACHE ones should be transformed to device space in
165 * find_shape_at_pos() with following statement. 167 * find_shape_at_pos() with following statement.
166 * \code 168 * \code
235 * left-top of bounding box just at origin (0, 0) of canvas. It saves 237 * left-top of bounding box just at origin (0, 0) of canvas. It saves
236 * space to give a canvas just enough for rending descadants. The 238 * space to give a canvas just enough for rending descadants. The
237 * process of adjusting left-top of bounding box is zeroing. 239 * process of adjusting left-top of bounding box is zeroing.
238 * 240 *
239 * Following is rules. 241 * Following is rules.
240 * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix 242 * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix
241 * of the cached coord and descendnats. 243 * of the cached coord and descendnats.
242 * - Clean coords works just like before without change. 244 * - Clean coords works just like before without change.
243 * - in preorder 245 * - in preorder
244 * - never perform zeroing on root_coord. 246 * - never perform zeroing on root_coord.
245 * - do zeroing on cached coords marked with \ref COF_MUST_ZEROING. 247 * - do zeroing on cached coords marked with \ref COF_MUST_ZEROING.
300 302
301 #ifndef ASSERT 303 #ifndef ASSERT
302 #define ASSERT(x) 304 #define ASSERT(x)
303 #endif 305 #endif
304 306
307 /*
308 * Conitions for coords.
309 */
310 #define coord_is_cached(co) ((co)->flags & COF_OWN_CANVAS)
311 #define coord_is_always_cached(co) ((co)->flags & COF_ALWAYS_CACHE)
312 #define coord_is_fast_cached(co) ((co)->flags & COF_FAST_MASK)
313 #define coord_is_precise_cached(co) ((co)->flags & COF_PRECISE_MASK)
314 #define coord_is_zeroing(co) ((co)->flags & COF_MUST_ZEROING)
315 #define coord_set_zeroing(co) \
316 do { (co)->flags |= COF_MUST_ZEROING; } while(0)
317 #define coord_clear_zeroing(co) \
318 do { (co)->flags &= ~COF_MUST_ZEROING; } while(0)
319 #define coord_set_flags(co, _flags) \
320 do { (co)->flags |= (_flags); } while(0)
321 #define coord_get_parent(co) ((co)->parent)
322 #define coord_get_flags(co, _flags) ((co)->flags & (_flags))
323 #define coord_clear_flags(co, _flags) \
324 do { (co)->flags &= ~(_flags); } while(0)
325
326 #define coord_get_pcache_area(coord) ((coord)->canvas_info->pcache_cur_area)
327 #define coord_get_pcache_last_area(coord) \
328 ((coord)->canvas_info->pcache_last_area)
329 #define coord_get_cached(coord) ((coord)->canvas_info->owner)
330 #define _coord_get_dirty_areas(coord) (&(coord)->canvas_info->dirty_areas)
331 #define _coord_get_aggr_dirty_areas(coord) \
332 ((coord)->canvas_info->aggr_dirty_areas)
333 #define coord_get_2pdev(coord) ((coord)->canvas_info->cache_2_pdev)
334 #define coord_get_2pdev_rev(coord) ((coord)->canvas_info->cache_2_pdev_rev)
335 #define coord_get_aggr2pdev(coord) ((coord)->canvas_info->aggr_2_pdev)
336 #define coord_get_aggr2pdev_rev(coord) ((coord)->canvas_info->aggr_2_pdev_rev)
337
338
305 /* NOTE: bounding box should also consider width of stroke. 339 /* NOTE: bounding box should also consider width of stroke.
306 */ 340 */
307 341
308 #define sh_attach_geo(sh, g) \ 342 #define sh_attach_geo(sh, g) \
309 do { \ 343 do { \
334 368
335 extern void sh_dummy_transform(shape_t *shape); 369 extern void sh_dummy_transform(shape_t *shape);
336 extern void sh_dummy_fill(shape_t *, mbe_t *); 370 extern void sh_dummy_fill(shape_t *, mbe_t *);
337 #endif /* UNITTEST */ 371 #endif /* UNITTEST */
338 372
339 static subject_t *ob_subject_alloc(ob_factory_t *factory); 373 static subject_t *observer_subject_alloc(observer_factory_t *factory);
340 static void ob_subject_free(ob_factory_t *factory, subject_t *subject); 374 static void observer_subject_free(observer_factory_t *factory,
341 static observer_t *ob_observer_alloc(ob_factory_t *factory); 375 subject_t *subject);
342 static void ob_observer_free(ob_factory_t *factory, observer_t *observer); 376 static observer_t *observer_observer_alloc(observer_factory_t *factory);
343 static subject_t *ob_get_parent_subject(ob_factory_t *factory, 377 static void observer_observer_free(observer_factory_t *factory,
344 subject_t *cur_subject); 378 observer_t *observer);
379 static subject_t *observer_get_parent_subject(observer_factory_t *factory,
380 subject_t *cur_subject);
345 /* Functions for children. */ 381 /* Functions for children. */
346 #define FORCHILDREN(coord, child) \ 382 #define FORCHILDREN(coord, child) \
347 for((child) = STAILQ_HEAD((coord)->children); \ 383 for((child) = STAILQ_HEAD((coord)->children); \
348 (child) != NULL; \ 384 (child) != NULL; \
349 (child) = STAILQ_NEXT(coord_t, sibling, (child))) 385 (child) = STAILQ_NEXT(coord_t, sibling, (child)))
454 return OK; 490 return OK;
455 } 491 }
456 492
457 static int add_dirty_area(redraw_man_t *rdman, coord_t *coord, area_t *area) { 493 static int add_dirty_area(redraw_man_t *rdman, coord_t *coord, area_t *area) {
458 int r; 494 int r;
459 495
460 if(area->w < 0.01 || area->h < 0.01) 496 if(area->w < 0.01 || area->h < 0.01)
461 return OK; 497 return OK;
462 498
463 rdman->n_dirty_areas++; 499 rdman->n_dirty_areas++;
464 r = areas_add(_coord_get_dirty_areas(coord), area); 500 r = areas_add(_coord_get_dirty_areas(coord), area);
465 return r == 0? OK: ERR; 501 return r == 0? OK: ERR;
466 } 502 }
467 503
470 ADD_DATA(coords, zeroing_coords, coord); 506 ADD_DATA(coords, zeroing_coords, coord);
471 return OK; 507 return OK;
472 } 508 }
473 509
474 static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) { 510 static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) {
475 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); 511 if(!coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) {
476 ADD_DATA(coords, dirty_pcache_area_coords, coord); 512 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA);
513 ADD_DATA(coords, zeroing_coords, coord);
514 }
477 return OK; 515 return OK;
478 } 516 }
479 517
480 static int add_free_obj(redraw_man_t *rdman, void *obj, 518 static int add_free_obj(redraw_man_t *rdman, void *obj,
481 free_func_t free_func) { 519 free_func_t free_func) {
513 static void free_objs_destroy(redraw_man_t *rdman) { 551 static void free_objs_destroy(redraw_man_t *rdman) {
514 if(rdman->free_objs.objs != NULL) 552 if(rdman->free_objs.objs != NULL)
515 free(rdman->free_objs.objs); 553 free(rdman->free_objs.objs);
516 } 554 }
517 555
518 556 #ifdef UNITTEST
557 /*! \brief This is only used for unittest.
558 */
559 typedef struct {
560 co_aix parent_2_cache[6];
561 int w, h;
562 } mock_mbe_t;
563 #endif
519 564
520 static mbe_t *canvas_new(int w, int h) { 565 static mbe_t *canvas_new(int w, int h) {
521 #ifndef UNITTEST 566 #ifndef UNITTEST
522 mbe_surface_t *surface; 567 mbe_surface_t *surface;
523 mbe_t *cr; 568 mbe_t *cr;
524 569
525 surface = mbe_image_surface_create(MB_IFMT_ARGB32, 570 surface = mbe_image_surface_create(MB_IFMT_ARGB32,
526 w, h); 571 w, h);
527 cr = mbe_create(surface); 572 cr = mbe_create(surface);
528 573
529 return cr; 574 return cr;
530 #else 575 #else
531 return NULL; 576 mock_mbe_t *mbe;
577
578 mbe = malloc(sizeof(mock_mbe_t));
579 mbe->w = w;
580 mbe->h = h;
581
582 return (mbe_t *)mbe;
532 #endif 583 #endif
533 } 584 }
534 585
535 static void canvas_free(mbe_t *canvas) { 586 static void canvas_free(mbe_t *canvas) {
536 #ifndef UNITTEST 587 #ifndef UNITTEST
537 mbe_destroy(canvas); 588 mbe_destroy(canvas);
589 #else
590 free(canvas);
538 #endif 591 #endif
539 } 592 }
540 593
541 static void canvas_get_size(mbe_t *canvas, int *w, int *h) { 594 static void canvas_get_size(mbe_t *canvas, int *w, int *h) {
542 #ifndef UNITTEST 595 #ifndef UNITTEST
544 597
545 surface = mbe_get_target(canvas); 598 surface = mbe_get_target(canvas);
546 *w = mbe_image_surface_get_width(surface); 599 *w = mbe_image_surface_get_width(surface);
547 *h = mbe_image_surface_get_height(surface); 600 *h = mbe_image_surface_get_height(surface);
548 #else 601 #else
549 *w = 0; 602 mock_mbe_t *mbe;
550 *h = 0; 603
604 mbe = (mock_mbe_t *)canvas;
605 *w = mbe->w;
606 *h = mbe->h;
551 #endif 607 #endif
552 } 608 }
553 609
554 static int geo_off_in_coord(geo_t *geo, coord_t *coord) { 610 static int geo_off_in_coord(geo_t *geo, coord_t *coord) {
555 int off = 0; 611 int off = 0;
582 638
583 RM_MEMBER(coord, geo); 639 RM_MEMBER(coord, geo);
584 coord->num_members--; 640 coord->num_members--;
585 } 641 }
586 642
587 static coord_canvas_info_t *coord_canvas_info_new(redraw_man_t *rdman, 643 /*! \brief Create a new canvas and respective info struct for a coord.
588 coord_t *coord, 644 */
589 mbe_t *canvas) { 645 static coord_canvas_info_t *
646 coord_canvas_info_new(redraw_man_t *rdman, coord_t *coord,
647 mbe_t *canvas) {
590 coord_canvas_info_t *info; 648 coord_canvas_info_t *info;
649 static co_aix id[6] = {1, 0, 0, 0, 1, 0};
591 650
592 info = (coord_canvas_info_t *)elmpool_elm_alloc(rdman->coord_canvas_pool); 651 info = (coord_canvas_info_t *)elmpool_elm_alloc(rdman->coord_canvas_pool);
593 if(info == NULL) 652 if(info == NULL)
594 return info; 653 return info;
595 654
596 info->owner = coord; 655 info->owner = coord;
597 info->canvas = canvas; 656 info->canvas = canvas;
598 DARRAY_INIT(&info->dirty_areas); 657 DARRAY_INIT(&info->dirty_areas);
599 658
600 bzero(info->pcache_areas, sizeof(area_t) * 2); 659 bzero(info->pcache_areas, sizeof(area_t) * 2);
601 info->pcache_cur_area = &info->pcache_areas[0]; 660 info->pcache_cur_area = &info->pcache_areas[0];
602 info->pcache_last_area = &info->pcache_areas[1]; 661 info->pcache_last_area = &info->pcache_areas[1];
662 memcpy(info->cache_2_pdev, id, sizeof(co_aix) * 6);
663 memcpy(info->cache_2_pdev_rev, id, sizeof(co_aix) * 6);
664 memcpy(info->aggr_2_pdev, id, sizeof(co_aix) * 6);
665 memcpy(info->aggr_2_pdev_rev, id, sizeof(co_aix) * 6);
603 666
604 return info; 667 return info;
605 } 668 }
606 669
607 static void coord_canvas_info_free(redraw_man_t *rdman, 670 static void coord_canvas_info_free(redraw_man_t *rdman,
613 static void mouse_event_root_dummy(event_t *evt, void *arg) { 676 static void mouse_event_root_dummy(event_t *evt, void *arg) {
614 } 677 }
615 678
616 int redraw_man_init(redraw_man_t *rdman, mbe_t *cr, mbe_t *backend) { 679 int redraw_man_init(redraw_man_t *rdman, mbe_t *cr, mbe_t *backend) {
617 extern void redraw_man_destroy(redraw_man_t *rdman); 680 extern void redraw_man_destroy(redraw_man_t *rdman);
681 extern int _sh_path_size;
682 extern int _sh_rect_size;
618 extern int _paint_color_size; 683 extern int _paint_color_size;
684 extern int _paint_linear_size;
685 extern int _paint_radial_size;
686 extern int _paint_image_size;
619 observer_t *addrm_ob; 687 observer_t *addrm_ob;
620 extern void addrm_monitor_hdlr(event_t *evt, void *arg); 688 extern void addrm_monitor_hdlr(event_t *evt, void *arg);
621 689
622 memset(rdman, 0, sizeof(redraw_man_t)); 690 memset(rdman, 0, sizeof(redraw_man_t));
623 691
624 DARRAY_INIT(&rdman->dirty_coords); 692 DARRAY_INIT(&rdman->dirty_coords);
625 DARRAY_INIT(&rdman->dirty_pcache_area_coords);
626 DARRAY_INIT(&rdman->dirty_geos); 693 DARRAY_INIT(&rdman->dirty_geos);
627 DARRAY_INIT(&rdman->gen_geos); 694 DARRAY_INIT(&rdman->gen_geos);
628 DARRAY_INIT(&rdman->zeroing_coords); 695 DARRAY_INIT(&rdman->zeroing_coords);
629 696
630 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); 697 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128);
631 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); 698 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16);
632 rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); 699 rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16);
700 rdman->sh_path_pool = elmpool_new(_sh_path_size, 16);
701 rdman->sh_rect_pool = elmpool_new(_sh_rect_size, 16);
633 rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); 702 rdman->observer_pool = elmpool_new(sizeof(observer_t), 32);
634 rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); 703 rdman->subject_pool = elmpool_new(sizeof(subject_t), 32);
635 rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); 704 rdman->paint_color_pool = elmpool_new(_paint_color_size, 64);
705 rdman->paint_linear_pool = elmpool_new(_paint_linear_size, 64);
706 rdman->paint_radial_pool = elmpool_new(_paint_radial_size, 64);
707 rdman->paint_image_pool = elmpool_new(_paint_image_size, 64);
636 rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); 708 rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128);
637 rdman->coord_canvas_pool = elmpool_new(sizeof(coord_canvas_info_t), 16); 709 rdman->coord_canvas_pool = elmpool_new(sizeof(coord_canvas_info_t), 16);
638 if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && 710 if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool &&
639 rdman->observer_pool && rdman->subject_pool && 711 rdman->observer_pool && rdman->subject_pool &&
640 rdman->paint_color_pool && rdman->coord_canvas_pool)) 712 rdman->paint_color_pool && rdman->coord_canvas_pool))
641 goto err; 713 goto err;
642 714
643 rdman->ob_factory.subject_alloc = ob_subject_alloc; 715 rdman->observer_factory.subject_alloc = observer_subject_alloc;
644 rdman->ob_factory.subject_free = ob_subject_free; 716 rdman->observer_factory.subject_free = observer_subject_free;
645 rdman->ob_factory.observer_alloc = ob_observer_alloc; 717 rdman->observer_factory.observer_alloc = observer_observer_alloc;
646 rdman->ob_factory.observer_free = ob_observer_free; 718 rdman->observer_factory.observer_free = observer_observer_free;
647 rdman->ob_factory.get_parent_subject = ob_get_parent_subject; 719 rdman->observer_factory.get_parent_subject = observer_get_parent_subject;
648 720
649 rdman->redraw = 721 rdman->redraw =
650 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); 722 subject_new(&rdman->observer_factory, rdman, OBJT_RDMAN);
651 rdman->addrm_monitor = 723 rdman->addrm_monitor =
652 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); 724 subject_new(&rdman->observer_factory, rdman, OBJT_RDMAN);
653 if(!(rdman->redraw && rdman->addrm_monitor)) 725 if(!(rdman->redraw && rdman->addrm_monitor))
654 goto err; 726 goto err;
655 727
656 addrm_ob = subject_add_observer(rdman->addrm_monitor, 728 addrm_ob = subject_add_observer(rdman->addrm_monitor,
657 addrm_monitor_hdlr, rdman); 729 addrm_monitor_hdlr, rdman);
664 if(rdman->root_coord == NULL) 736 if(rdman->root_coord == NULL)
665 redraw_man_destroy(rdman); 737 redraw_man_destroy(rdman);
666 rdman->n_coords = 1; 738 rdman->n_coords = 1;
667 coord_init(rdman->root_coord, NULL); 739 coord_init(rdman->root_coord, NULL);
668 mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool); 740 mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool);
669 rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, 741 rdman->root_coord->mouse_event = subject_new(&rdman->observer_factory,
670 rdman->root_coord, 742 rdman->root_coord,
671 OBJT_COORD); 743 OBJT_COORD);
672 coord_set_flags(rdman->root_coord, COF_OWN_CANVAS); 744 coord_set_flags(rdman->root_coord, COF_OWN_CANVAS);
673 rdman->root_coord->canvas_info = 745 rdman->root_coord->canvas_info =
674 coord_canvas_info_new(rdman, rdman->root_coord, cr); 746 coord_canvas_info_new(rdman, rdman->root_coord, cr);
676 748
677 rdman->cr = cr; 749 rdman->cr = cr;
678 rdman->backend = backend; 750 rdman->backend = backend;
679 751
680 STAILQ_INIT(rdman->shapes); 752 STAILQ_INIT(rdman->shapes);
681 753
682 /* \note To make root coord always have at leat one observer. 754 /* \note To make root coord always have at leat one observer.
683 * It triggers mouse interpreter to be installed on root. 755 * It triggers mouse interpreter to be installed on root.
684 */ 756 */
685 subject_set_monitor(rdman->root_coord->mouse_event, 757 subject_set_monitor(rdman->root_coord->mouse_event,
686 rdman->addrm_monitor); 758 rdman->addrm_monitor);
695 elmpool_free(rdman->geo_pool); 767 elmpool_free(rdman->geo_pool);
696 if(rdman->coord_pool) 768 if(rdman->coord_pool)
697 elmpool_free(rdman->coord_pool); 769 elmpool_free(rdman->coord_pool);
698 if(rdman->shnode_pool) 770 if(rdman->shnode_pool)
699 elmpool_free(rdman->shnode_pool); 771 elmpool_free(rdman->shnode_pool);
772 if(rdman->sh_path_pool)
773 elmpool_free(rdman->sh_path_pool);
774 if(rdman->sh_rect_pool)
775 elmpool_free(rdman->sh_rect_pool);
700 if(rdman->observer_pool) 776 if(rdman->observer_pool)
701 elmpool_free(rdman->observer_pool); 777 elmpool_free(rdman->observer_pool);
702 if(rdman->subject_pool) 778 if(rdman->subject_pool)
703 elmpool_free(rdman->subject_pool); 779 elmpool_free(rdman->subject_pool);
704 if(rdman->paint_color_pool) 780 if(rdman->paint_color_pool)
705 elmpool_free(rdman->paint_color_pool); 781 elmpool_free(rdman->paint_color_pool);
782 if(rdman->paint_linear_pool)
783 elmpool_free(rdman->paint_linear_pool);
784 if(rdman->paint_radial_pool)
785 elmpool_free(rdman->paint_radial_pool);
786 if(rdman->paint_image_pool)
787 elmpool_free(rdman->paint_image_pool);
706 if(rdman->pent_pool) 788 if(rdman->pent_pool)
707 elmpool_free(rdman->pent_pool); 789 elmpool_free(rdman->pent_pool);
708 if(rdman->coord_canvas_pool) 790 if(rdman->coord_canvas_pool)
709 elmpool_free(rdman->coord_canvas_pool); 791 elmpool_free(rdman->coord_canvas_pool);
710 DARRAY_DESTROY(&rdman->dirty_coords); 792 DARRAY_DESTROY(&rdman->dirty_coords);
711 DARRAY_DESTROY(&rdman->dirty_pcache_area_coords);
712 DARRAY_DESTROY(&rdman->dirty_geos); 793 DARRAY_DESTROY(&rdman->dirty_geos);
713 DARRAY_DESTROY(&rdman->gen_geos); 794 DARRAY_DESTROY(&rdman->gen_geos);
714 DARRAY_DESTROY(&rdman->zeroing_coords); 795 DARRAY_DESTROY(&rdman->zeroing_coords);
715 return ERR; 796 return ERR;
716 } 797 }
717 798
718 void redraw_man_destroy(redraw_man_t *rdman) { 799 void redraw_man_destroy(redraw_man_t *rdman) {
719 coord_t *coord, *saved_coord; 800 coord_t *coord, *saved_coord;
720 shape_t *shape, *saved_shape; 801 shape_t *shape;
721 geo_t *member; 802 geo_t *member;
722 803
723 mb_prop_store_destroy(&rdman->props); 804 mb_prop_store_destroy(&rdman->props);
724 805
725 free_free_objs(rdman); 806 free_free_objs(rdman);
727 808
728 /* Mark rdman clean that shapes and coords can be freed 809 /* Mark rdman clean that shapes and coords can be freed
729 * successfully. 810 * successfully.
730 */ 811 */
731 DARRAY_CLEAN(&rdman->dirty_coords); 812 DARRAY_CLEAN(&rdman->dirty_coords);
732 DARRAY_CLEAN(&rdman->dirty_pcache_area_coords);
733 DARRAY_CLEAN(&rdman->dirty_geos); 813 DARRAY_CLEAN(&rdman->dirty_geos);
734 814
735 coord = postorder_coord_subtree(rdman->root_coord, NULL); 815 coord = postorder_coord_subtree(rdman->root_coord, NULL);
736 while(coord) { 816 while(coord) {
737 saved_coord = coord; 817 saved_coord = coord;
746 */ 826 */
747 827
748 while((shape = STAILQ_HEAD(rdman->shapes)) != NULL) { 828 while((shape = STAILQ_HEAD(rdman->shapes)) != NULL) {
749 rdman_shape_free(rdman, shape); 829 rdman_shape_free(rdman, shape);
750 } 830 }
751 831
752 coord_canvas_info_free(rdman, rdman->root_coord->canvas_info); 832 coord_canvas_info_free(rdman, rdman->root_coord->canvas_info);
753 833
754 /* XXX: paints are not freed, here. All resources of paints would 834 /* XXX: paints are not freed, here. All resources of paints would
755 * be reclaimed by freeing elmpools. 835 * be reclaimed by freeing elmpools.
756 */ 836 */
757 837
758 elmpool_free(rdman->coord_pool); 838 elmpool_free(rdman->coord_pool);
759 elmpool_free(rdman->geo_pool); 839 elmpool_free(rdman->geo_pool);
760 elmpool_free(rdman->shnode_pool); 840 elmpool_free(rdman->shnode_pool);
841 elmpool_free(rdman->sh_path_pool);
842 elmpool_free(rdman->sh_rect_pool);
761 elmpool_free(rdman->observer_pool); 843 elmpool_free(rdman->observer_pool);
762 elmpool_free(rdman->subject_pool); 844 elmpool_free(rdman->subject_pool);
763 elmpool_free(rdman->paint_color_pool); 845 elmpool_free(rdman->paint_color_pool);
846 elmpool_free(rdman->paint_linear_pool);
847 elmpool_free(rdman->paint_radial_pool);
848 elmpool_free(rdman->paint_image_pool);
764 elmpool_free(rdman->pent_pool); 849 elmpool_free(rdman->pent_pool);
765 elmpool_free(rdman->coord_canvas_pool); 850 elmpool_free(rdman->coord_canvas_pool);
766 851
767 DARRAY_DESTROY(&rdman->dirty_coords); 852 DARRAY_DESTROY(&rdman->dirty_coords);
768 DARRAY_DESTROY(&rdman->dirty_pcache_area_coords);
769 DARRAY_DESTROY(&rdman->dirty_geos); 853 DARRAY_DESTROY(&rdman->dirty_geos);
770 DARRAY_DESTROY(&rdman->gen_geos); 854 DARRAY_DESTROY(&rdman->gen_geos);
771 DARRAY_DESTROY(&rdman->zeroing_coords); 855 DARRAY_DESTROY(&rdman->zeroing_coords);
772 } 856 }
773 857
800 int r; 884 int r;
801 885
802 geo = elmpool_elm_alloc(rdman->geo_pool); 886 geo = elmpool_elm_alloc(rdman->geo_pool);
803 if(geo == NULL) 887 if(geo == NULL)
804 return ERR; 888 return ERR;
805 889
806 geo_init(geo); 890 geo_init(geo);
807 geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); 891 geo->mouse_event = subject_new(&rdman->observer_factory, geo, OBJT_GEO);
808 subject_set_monitor(geo->mouse_event, rdman->addrm_monitor); 892 subject_set_monitor(geo->mouse_event, rdman->addrm_monitor);
809 893
810 geo_attach_coord(geo, coord); 894 geo_attach_coord(geo, coord);
811 895
812 /* New one should be dirty to recompute it when drawing. */ 896 /* New one should be dirty to recompute it when drawing. */
852 936
853 if(shape->stroke != NULL) 937 if(shape->stroke != NULL)
854 rdman_paint_stroke(rdman, (paint_t *)NULL, shape); 938 rdman_paint_stroke(rdman, (paint_t *)NULL, shape);
855 if(shape->fill != NULL) 939 if(shape->fill != NULL)
856 rdman_paint_fill(rdman, (paint_t *)NULL, shape); 940 rdman_paint_fill(rdman, (paint_t *)NULL, shape);
857 941
858 if(geo != NULL) { 942 if(geo != NULL) {
859 subject_free(geo->mouse_event); 943 subject_free(geo->mouse_event);
860 geo_detach_coord(geo, shape->coord); 944 geo_detach_coord(geo, shape->coord);
861 sh_detach_coord(shape); 945 sh_detach_coord(shape);
862 sh_detach_geo(shape); 946 sh_detach_geo(shape);
867 shape->free(shape); 951 shape->free(shape);
868 952
869 if(rdman->last_mouse_over == (mb_obj_t *)shape) 953 if(rdman->last_mouse_over == (mb_obj_t *)shape)
870 rdman->last_mouse_over = NULL; 954 rdman->last_mouse_over = NULL;
871 955
872 956
873 return OK; 957 return OK;
874 } 958 }
875 959
876 shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) { 960 shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) {
877 shnode_t *node; 961 shnode_t *node;
887 int rdman_paint_free(redraw_man_t *rdman, paint_t *paint) { 971 int rdman_paint_free(redraw_man_t *rdman, paint_t *paint) {
888 shnode_t *shnode, *saved_shnode; 972 shnode_t *shnode, *saved_shnode;
889 shape_t *shape; 973 shape_t *shape;
890 974
891 if(rdman_is_dirty(rdman)) { 975 if(rdman_is_dirty(rdman)) {
892 if(!(paint->flags & PNTF_FREE)) 976 if(paint->flags & PNTF_FREE)
893 return ERR; 977 return ERR;
894 add_free_obj(rdman, paint, (free_func_t)rdman_paint_free); 978 add_free_obj(rdman, paint, (free_func_t)rdman_paint_free);
895 paint->flags |= PNTF_FREE; 979 paint->flags |= PNTF_FREE;
896 return OK; 980 return OK;
897 } 981 }
899 /* Free member shapes that using this paint. */ 983 /* Free member shapes that using this paint. */
900 saved_shnode = NULL; 984 saved_shnode = NULL;
901 FORPAINTMEMBERS(paint, shnode) { 985 FORPAINTMEMBERS(paint, shnode) {
902 if(saved_shnode) { 986 if(saved_shnode) {
903 RM_PAINTMEMBER(paint, saved_shnode); 987 RM_PAINTMEMBER(paint, saved_shnode);
904 988
905 shape = saved_shnode->shape; 989 shape = saved_shnode->shape;
906 if(shape->stroke == paint) 990 if(shape->stroke == paint)
907 rdman_paint_stroke(rdman, (paint_t *)NULL, shape); 991 rdman_paint_stroke(rdman, (paint_t *)NULL, shape);
908 if(shape->fill == paint) 992 if(shape->fill == paint)
909 rdman_paint_fill(rdman, (paint_t *)NULL, shape); 993 rdman_paint_fill(rdman, (paint_t *)NULL, shape);
910 994
911 shnode_free(rdman, saved_shnode); 995 shnode_free(rdman, saved_shnode);
912 } 996 }
913 saved_shnode = shnode; 997 saved_shnode = shnode;
914 } 998 }
915 if(saved_shnode) { 999 if(saved_shnode) {
916 RM_PAINTMEMBER(paint, saved_shnode); 1000 RM_PAINTMEMBER(paint, saved_shnode);
917 1001
918 shape = saved_shnode->shape; 1002 shape = saved_shnode->shape;
919 if(shape->stroke == paint) 1003 if(shape->stroke == paint)
920 rdman_paint_stroke(rdman, (paint_t *)NULL, shape); 1004 rdman_paint_stroke(rdman, (paint_t *)NULL, shape);
921 if(shape->fill == paint) 1005 if(shape->fill == paint)
922 rdman_paint_fill(rdman, (paint_t *)NULL, shape); 1006 rdman_paint_fill(rdman, (paint_t *)NULL, shape);
923 1007
924 shnode_free(rdman, saved_shnode); 1008 shnode_free(rdman, saved_shnode);
925 } 1009 }
926 1010
927 paint->free(rdman, paint); 1011 paint->free(rdman, paint);
928 return OK; 1012 return OK;
950 if(coord == NULL) 1034 if(coord == NULL)
951 return NULL; 1035 return NULL;
952 1036
953 coord_init(coord, parent); 1037 coord_init(coord, parent);
954 mb_prop_store_init(&coord->obj.props, rdman->pent_pool); 1038 mb_prop_store_init(&coord->obj.props, rdman->pent_pool);
955 coord->mouse_event = subject_new(&rdman->ob_factory, 1039 coord->mouse_event = subject_new(&rdman->observer_factory,
956 coord, 1040 coord,
957 OBJT_COORD); 1041 OBJT_COORD);
958 subject_set_monitor(coord->mouse_event, rdman->addrm_monitor); 1042 subject_set_monitor(coord->mouse_event, rdman->addrm_monitor);
959 /*! \note default opacity == 1 */ 1043 /*! \note default opacity == 1 */
960 coord->opacity = 1; 1044 coord->opacity = 1;
986 static int rdman_coord_free_postponse(redraw_man_t *rdman, coord_t *coord) { 1070 static int rdman_coord_free_postponse(redraw_man_t *rdman, coord_t *coord) {
987 int r; 1071 int r;
988 1072
989 if(coord->flags & COF_FREE) 1073 if(coord->flags & COF_FREE)
990 return ERR; 1074 return ERR;
991 1075
992 coord->flags |= COF_FREE; 1076 coord->flags |= COF_FREE;
993 coord_hide(coord); 1077 coord_hide(coord);
994 if(!(coord->flags & COF_DIRTY)) { 1078 if(!(coord->flags & COF_DIRTY)) {
995 r = add_dirty_coord(rdman, coord); 1079 r = add_dirty_coord(rdman, coord);
996 if(r != OK) 1080 if(r != OK)
1031 FORMEMBERS(coord, member) { 1115 FORMEMBERS(coord, member) {
1032 cm_cnt++; 1116 cm_cnt++;
1033 if(!(member->flags & GEF_FREE)) 1117 if(!(member->flags & GEF_FREE))
1034 return ERR; 1118 return ERR;
1035 } 1119 }
1036 1120
1037 if(cm_cnt || rdman_is_dirty(rdman)) 1121 if(cm_cnt || rdman_is_dirty(rdman))
1038 return rdman_coord_free_postponse(rdman, coord); 1122 return rdman_coord_free_postponse(rdman, coord);
1039 1123
1040 /* Free canvas and canvas_info (\ref redraw) */ 1124 /* Free canvas and canvas_info (\ref redraw) */
1041 if(coord_is_cached(coord)) { 1125 if(coord_is_cached(coord)) {
1224 break; 1308 break;
1225 #endif /* UNITTEST */ 1309 #endif /* UNITTEST */
1226 } 1310 }
1227 shape->geo->flags &= ~GEF_DIRTY; 1311 shape->geo->flags &= ~GEF_DIRTY;
1228 1312
1229 if(is_coord_subtree_hidden(shape->coord)) 1313 if(sh_get_flags(shape, GEF_HIDDEN) ||
1230 sh_hide(shape); 1314 is_coord_subtree_hidden(shape->coord))
1315 sh_set_flags(shape, GEF_NOT_SHOWED);
1231 else 1316 else
1232 sh_show(shape); 1317 sh_clear_flags(shape, GEF_NOT_SHOWED);
1233 } 1318 }
1234 1319
1235 /*! \brief Setup canvas_info for the coord. 1320 /*! \brief Setup canvas_info for the coord.
1236 * 1321 *
1237 * Own a canvas or inherit it from parent. 1322 * Own a canvas or inherit it from parent.
1240 */ 1325 */
1241 static void setup_canvas_info(redraw_man_t *rdman, coord_t *coord) { 1326 static void setup_canvas_info(redraw_man_t *rdman, coord_t *coord) {
1242 if(coord->parent == NULL) 1327 if(coord->parent == NULL)
1243 return; 1328 return;
1244 1329
1245 if(coord->opacity != 1 || coord_is_cached(coord)) { 1330 if(coord->opacity != 1 || coord_is_always_cached(coord)) {
1246 if(!coord_is_cached(coord)) { 1331 if(!coord_is_cached(coord)) {
1247 /* canvas is assigned latter, in zeroing_coord() */ 1332 /* canvas is assigned latter, in zeroing_coord() */
1248 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); 1333 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL);
1249 coord_set_flags(coord, COF_OWN_CANVAS); 1334 coord_set_flags(coord, COF_OWN_CANVAS);
1250 } 1335 }
1262 } 1347 }
1263 } 1348 }
1264 1349
1265 /* \brief Compute matrix from cached canvas to parent device space. 1350 /* \brief Compute matrix from cached canvas to parent device space.
1266 */ 1351 */
1267 static void compute_cached_2_pdev_matrix(coord_t *coord, 1352 static void compute_cached_2_pdev_matrix(coord_t *coord) {
1268 co_aix canvas2pdev_matrix[6]) { 1353 co_aix *canvas2pdev_matrix = coord_get_2pdev(coord);
1269 coord_t *parent; 1354 coord_t *parent;
1270 co_aix *aggr; 1355 co_aix *aggr;
1271 co_aix *matrix, *paggr; 1356 co_aix *matrix, *paggr;
1272 co_aix scale_x, scale_y; 1357 co_aix scale_x, scale_y;
1273 co_aix shift_x, shift_y; 1358 co_aix shift_x, shift_y;
1275 1360
1276 aggr = coord_get_aggr_matrix(coord); 1361 aggr = coord_get_aggr_matrix(coord);
1277 matrix = coord->matrix; 1362 matrix = coord->matrix;
1278 parent = coord->parent; 1363 parent = coord->parent;
1279 paggr = coord_get_aggr_matrix(parent); 1364 paggr = coord_get_aggr_matrix(parent);
1280 1365
1281 scale_x = matrix[0] / aggr[0]; 1366 scale_x = matrix[0] / aggr[0];
1282 scale_y = matrix[3] / aggr[3]; 1367 scale_y = matrix[4] / aggr[4];
1283 shift_x = matrix[2] - scale_x * aggr[2]; 1368 shift_x = matrix[2] - scale_x * aggr[2];
1284 shift_y = matrix[5] - scale_y * aggr[5]; 1369 shift_y = matrix[5] - scale_y * aggr[5];
1285 1370
1286 canvas2p[0] = scale_x; 1371 canvas2p[0] = scale_x;
1287 canvas2p[1] = 0; 1372 canvas2p[1] = 0;
1289 canvas2p[3] = 0; 1374 canvas2p[3] = 0;
1290 canvas2p[4] = scale_y; 1375 canvas2p[4] = scale_y;
1291 canvas2p[5] = shift_y; 1376 canvas2p[5] = shift_y;
1292 1377
1293 matrix_mul(paggr, canvas2p, canvas2pdev_matrix); 1378 matrix_mul(paggr, canvas2p, canvas2pdev_matrix);
1379
1380 compute_reverse(canvas2pdev_matrix, coord_get_2pdev_rev(coord));
1294 } 1381 }
1295 1382
1296 /*! \brief Compute area in parent cached coord for a cached coord. 1383 /*! \brief Compute area in parent cached coord for a cached coord.
1297 * 1384 *
1298 * The coordination system of cached coord and descendants is resized, 1385 * The coordination system of cached coord and descendants is resized,
1301 * 1388 *
1302 * The bounding box where the canvas would be draw on the canvas on 1389 * The bounding box where the canvas would be draw on the canvas on
1303 * ancestral cached coord can be retreived by shifting and resizing 1390 * ancestral cached coord can be retreived by shifting and resizing
1304 * canvas box in reverse and transform to coordination system of 1391 * canvas box in reverse and transform to coordination system of
1305 * ancestral cached coord. 1392 * ancestral cached coord.
1306 */ 1393 */
1307 static void compute_pcache_area(coord_t *coord) { 1394 static void compute_pcache_area(coord_t *coord) {
1308 co_aix cached2pdev[6]; 1395 co_aix *cached2pdev = coord_get_2pdev(coord);
1309 int c_w, c_h; 1396 int c_w, c_h;
1310 canvas_t *canvas; 1397 canvas_t *canvas;
1311 coord_canvas_info_t *canvas_info; 1398 coord_canvas_info_t *canvas_info;
1312 co_aix poses[4][2]; 1399 co_aix poses[4][2];
1313 1400
1314 canvas_info = coord->canvas_info; 1401 canvas_info = coord->canvas_info;
1315 SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area, 1402 SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area,
1316 area_t *); 1403 area_t *);
1317 compute_cached_2_pdev_matrix(coord, cached2pdev); 1404
1318
1319 canvas = _coord_get_canvas(coord); 1405 canvas = _coord_get_canvas(coord);
1320 canvas_get_size(canvas, &c_w, &c_h); 1406 canvas_get_size(canvas, &c_w, &c_h);
1321 1407
1322 poses[0][0] = 0; 1408 poses[0][0] = 0;
1323 poses[0][1] = 0; 1409 poses[0][1] = 0;
1324 poses[1][0] = c_w; 1410 poses[1][0] = c_w;
1325 poses[1][1] = c_h; 1411 poses[1][1] = c_h;
1326 poses[2][0] = 0; 1412 poses[2][0] = 0;
1329 poses[3][1] = 0; 1415 poses[3][1] = 0;
1330 matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]); 1416 matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]);
1331 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); 1417 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]);
1332 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); 1418 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]);
1333 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); 1419 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]);
1334 1420
1335 area_init(coord_get_pcache_area(coord), 4, poses); 1421 area_init(coord_get_pcache_area(coord), 4, poses);
1336 1422
1337 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); 1423 coord_clear_flags(coord, COF_DIRTY_PCACHE_AREA);
1338 } 1424 }
1339 1425
1340 /*! \brief Compute area of a coord. 1426 /*! \brief Compute area of a coord.
1341 */ 1427 */
1342 static int 1428 static int
1343 compute_area(coord_t *coord) { 1429 compute_area(coord_t *coord) {
1344 static co_aix (*poses)[2]; 1430 static co_aix (*poses)[2] = NULL;
1345 static int max_poses = 0; 1431 static int max_poses = 0;
1346 geo_t *geo; 1432 geo_t *geo;
1347 int cnt, pos_cnt; 1433 int cnt, pos_cnt;
1348 1434
1349 cnt = 0; 1435 cnt = 0;
1350 FORMEMBERS(coord, geo) { 1436 FORMEMBERS(coord, geo) {
1351 cnt++; 1437 cnt++;
1352 } 1438 }
1353 1439
1354 if(max_poses < (cnt * 2)) { 1440 if(max_poses < (cnt * 2)) {
1355 free(poses); 1441 if(poses)
1442 free(poses);
1356 max_poses = cnt * 2; 1443 max_poses = cnt * 2;
1357 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses); 1444 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses);
1358 if(poses == NULL) 1445 if(poses == NULL)
1359 return ERR; 1446 return ERR;
1360 } 1447 }
1372 1459
1373 static int coord_clean_members_n_compute_area(coord_t *coord) { 1460 static int coord_clean_members_n_compute_area(coord_t *coord) {
1374 geo_t *geo; 1461 geo_t *geo;
1375 int r; 1462 int r;
1376 /*! \note poses is shared by invokings, it is not support reentrying. */ 1463 /*! \note poses is shared by invokings, it is not support reentrying. */
1377 1464
1378 /* Clean member shapes. */ 1465 /* Clean member shapes. */
1379 FORMEMBERS(coord, geo) { 1466 FORMEMBERS(coord, geo) {
1380 clean_shape(geo->shape); 1467 clean_shape(geo->shape);
1381 } 1468 }
1382 1469
1394 * normal one. (see compute_aggr_of_cached_coord()). 1481 * normal one. (see compute_aggr_of_cached_coord()).
1395 * 1482 *
1396 * \note coords their opacity != 1 are also traded as cached ones. 1483 * \note coords their opacity != 1 are also traded as cached ones.
1397 */ 1484 */
1398 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { 1485 static int clean_coord(redraw_man_t *rdman, coord_t *coord) {
1399 coord_t *child;
1400 int r; 1486 int r;
1401 1487
1402 setup_canvas_info(rdman, coord); 1488 setup_canvas_info(rdman, coord);
1403 1489
1404 compute_aggr(coord); 1490 compute_aggr(coord);
1405 1491
1406 /* Areas of cached coords are computed in two phase. 1492 /* Areas of cached coords are computed in two phase.
1410 */ 1496 */
1411 r = coord_clean_members_n_compute_area(coord); 1497 r = coord_clean_members_n_compute_area(coord);
1412 if(r != OK) 1498 if(r != OK)
1413 return ERR; 1499 return ERR;
1414 1500
1501 /* Dirty areas of cached one is added after update pcache_areas.
1502 */
1415 add_dirty_area(rdman, coord, coord->cur_area); 1503 add_dirty_area(rdman, coord, coord->cur_area);
1416 add_dirty_area(rdman, coord, coord->last_area); 1504 add_dirty_area(rdman, coord, coord->last_area);
1417 1505
1418 coord_clear_flags(coord, COF_DIRTY); 1506 coord_clear_flags(coord, COF_DIRTY);
1419 coord_set_flags(coord, COF_JUST_CLEAN); 1507 coord_set_flags(coord, COF_JUST_CLEAN);
1420 1508
1421 FORCHILDREN(coord, child) {
1422 if(coord_is_cached(child))
1423 add_dirty_pcache_area_coord(rdman, child);
1424 }
1425
1426 return OK; 1509 return OK;
1427 } 1510 }
1428 1511
1429 /*! \brief Clean coord_t objects. 1512 /*! \brief Clean coord_t objects.
1430 * 1513 *
1432 * 1515 *
1433 * This function also responsible for computing area of parent cached 1516 * This function also responsible for computing area of parent cached
1434 * coord, coord_canvas_info_t::pcache_cur_area, for its cached children. 1517 * coord, coord_canvas_info_t::pcache_cur_area, for its cached children.
1435 */ 1518 */
1436 static int clean_rdman_coords(redraw_man_t *rdman) { 1519 static int clean_rdman_coords(redraw_man_t *rdman) {
1437 coord_t *coord, *child; 1520 coord_t *coord;
1438 coord_t **dirty_coords; 1521 coord_t **dirty_coords;
1439 int n_dirty_coords; 1522 int n_dirty_coords;
1440 int i, r; 1523 int i, r;
1441 1524
1442 n_dirty_coords = rdman->dirty_coords.num; 1525 n_dirty_coords = rdman->dirty_coords.num;
1474 clean_shape(visit_geo->shape); 1557 clean_shape(visit_geo->shape);
1475 coord = geo_get_coord(visit_geo); 1558 coord = geo_get_coord(visit_geo);
1476 add_dirty_area(rdman, coord, visit_geo->cur_area); 1559 add_dirty_area(rdman, coord, visit_geo->cur_area);
1477 add_dirty_area(rdman, coord, visit_geo->last_area); 1560 add_dirty_area(rdman, coord, visit_geo->last_area);
1478 } 1561 }
1479 } 1562 }
1480 1563
1481 return OK; 1564 return OK;
1482 } 1565 }
1483 1566
1484 /*! \brief Shift space of coord to align left-top of minimum covering. 1567 /*! \brief Shift space of coord to align left-top of minimum covering.
1487 * sub-graphic to origin of the space. 1570 * sub-graphic to origin of the space.
1488 */ 1571 */
1489 static 1572 static
1490 void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { 1573 void zeroing_coord(redraw_man_t *rdman, coord_t *coord) {
1491 coord_t *cur; 1574 coord_t *cur;
1492 area_t *area, *saved_area; 1575 area_t *area;
1493 geo_t *geo; 1576 geo_t *geo;
1494 co_aix min_x, min_y; 1577 co_aix min_x, min_y;
1495 co_aix max_x, max_y; 1578 co_aix max_x, max_y;
1496 co_aix x, y; 1579 co_aix x, y;
1497 int w, h; 1580 int w, h;
1498 int c_w, c_h; 1581 int c_w, c_h;
1499 mbe_t *canvas; 1582 mbe_t *canvas;
1500 co_aix *aggr; 1583 co_aix *aggr;
1501 co_aix poses[4][2];
1502 1584
1503 if(coord->parent == NULL) /*! \note Should not zeroing root coord */ 1585 if(coord->parent == NULL) /*! \note Should not zeroing root coord */
1504 abort(); 1586 abort();
1505 if(!(coord_is_zeroing(coord))) 1587 if(!(coord_is_zeroing(coord)))
1506 abort(); 1588 abort();
1517 max_y = min_y + area->h; 1599 max_y = min_y + area->h;
1518 1600
1519 for(cur = preorder_coord_subtree(coord, coord); 1601 for(cur = preorder_coord_subtree(coord, coord);
1520 cur != NULL; 1602 cur != NULL;
1521 cur = preorder_coord_subtree(coord, cur)) { 1603 cur = preorder_coord_subtree(coord, cur)) {
1522 area = coord_get_area(cur); 1604 if(coord_is_cached(cur)) {
1605 preorder_coord_skip_subtree(cur);
1606 /* This means pcache_area of descendants must be computed
1607 * before zeroing ancestor cached one.
1608 * (See add_rdman_zeroing_n_pcache_coords())
1609 */
1610 area = coord_get_pcache_area(cur);
1611 } else
1612 area = coord_get_area(cur);
1613
1614 if(area->w == 0 && area->h == 0)
1615 continue;
1616
1617 if(min_x == max_x && min_y == max_y) {
1618 min_x = area->x;
1619 max_x = area->x + area->w;
1620 min_y = area->y;
1621 max_y = area->y + area->h;
1622 continue;
1623 }
1624
1523 if(area->x < min_x) 1625 if(area->x < min_x)
1524 min_x = area->x; 1626 min_x = area->x;
1525 if(area->y < min_y) 1627 if(area->y < min_y)
1526 min_y = area->y; 1628 min_y = area->y;
1527 1629
1528 x = area->x + area->w; 1630 x = area->x + area->w;
1529 y = area->y + area->h; 1631 y = area->y + area->h;
1530 1632
1531 if(x > max_x) 1633 if(x > max_x)
1532 max_x = x; 1634 max_x = x;
1533 if(y > max_y) 1635 if(y > max_y)
1534 max_y = y; 1636 max_y = y;
1535 if(coord_is_cached(cur))
1536 preorder_coord_skip_subtree(cur);
1537 } 1637 }
1538 1638
1539 w = max_x - min_x; 1639 w = max_x - min_x;
1540 h = max_y - min_y; 1640 h = max_y - min_y;
1541 1641
1542 canvas = _coord_get_canvas(coord); 1642 canvas = _coord_get_canvas(coord);
1543 if(canvas) 1643 if(canvas)
1544 canvas_get_size(canvas, &c_w, &c_h); 1644 canvas_get_size(canvas, &c_w, &c_h);
1545 else 1645 else
1546 c_w = c_h = 0; 1646 c_w = c_h = 0;
1558 h >= (c_h >> 2) && w >= (c_w >> 2)) { 1658 h >= (c_h >> 2) && w >= (c_w >> 2)) {
1559 /* Canvas fully cover sub-graphic. */ 1659 /* Canvas fully cover sub-graphic. */
1560 coord_set_flags(coord, COF_SKIP_ZERO); 1660 coord_set_flags(coord, COF_SKIP_ZERO);
1561 return; 1661 return;
1562 } 1662 }
1563 1663
1564 /* 1664 /*
1565 * Adjust matrics of descendants to align left-top corner of 1665 * Adjust matrics of descendants to align left-top corner of
1566 * minimum covering area with origin of space defined by 1666 * minimum covering area with origin of space defined by
1567 * zeroing coord. 1667 * zeroing coord.
1568 */ 1668 */
1575 */ 1675 */
1576 preorder_coord_skip_subtree(cur); 1676 preorder_coord_skip_subtree(cur);
1577 } 1677 }
1578 /* Shift space */ 1678 /* Shift space */
1579 aggr = coord_get_aggr_matrix(cur); 1679 aggr = coord_get_aggr_matrix(cur);
1580 aggr[3] -= min_x; 1680 aggr[2] -= min_x;
1581 aggr[5] -= min_y; 1681 aggr[5] -= min_y;
1582 1682
1583 FOR_COORD_MEMBERS(coord, geo) { 1683 FOR_COORD_MEMBERS(coord, geo) {
1584 /* \see GEO_SWAP() */ 1684 /* \see GEO_SWAP() */
1585 if(!geo_get_flags(geo, GEF_SWAP)) 1685 if(!geo_get_flags(geo, GEF_SWAP))
1586 SWAP(geo->cur_area, geo->last_area, area_t *); 1686 SWAP(geo->cur_area, geo->last_area, area_t *);
1587 } 1687 }
1588 coord_clean_members_n_compute_area(cur); 1688 coord_clean_members_n_compute_area(cur);
1589 } 1689 }
1590 1690
1591 /* 1691 /*
1592 * Setup canvas 1692 * Setup canvas
1593 * 1693 *
1594 * Canvas of a cached coord is not setted in 1694 * Canvas of a cached coord is not setted in
1595 * coord_canvas_info_new(). It should be setted, here. 1695 * coord_canvas_info_new(). It should be setted, here.
1602 } 1702 }
1603 1703
1604 coord_set_flags(coord, COF_JUST_ZERO); 1704 coord_set_flags(coord, COF_JUST_ZERO);
1605 } 1705 }
1606 1706
1607 /*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. 1707 /*! \brief Add coords that need to perform zeroing or re-compute pcache_area.
1608 * 1708 *
1609 * All possible coords that need a zeroing have at least one dirty geo. 1709 * A coord that need to perform zeroing has one or more dirty members
1610 */ 1710 * in its descendants.
1611 static int add_rdman_zeroing_coords(redraw_man_t *rdman) { 1711 *
1712 * To zeroing a coord, pcache_area of first level cached descendants
1713 * must be updated. To update the pcache_area of a cached coord, the
1714 * cached coord also need to perform zeroing. So, zeroing and
1715 * re-computing pcache_area are interleaved.
1716 *
1717 * The pcache_area of a cached coord must be re-computed if its
1718 * parent/ancestors is dirty/just cleaned, or it must be zeroed. It
1719 * means cached coord with jsut cleaned parent should also re-compute
1720 * pcache_area. So, this function also check and add coords for this
1721 * situation.
1722 */
1723 static int add_rdman_zeroing_n_pcache_coords(redraw_man_t *rdman) {
1612 int i; 1724 int i;
1613 int n_dirty_geos; 1725 int n_dirty_geos;
1614 geo_t **dirty_geos, *geo; 1726 geo_t **dirty_geos, *geo;
1615 int n_dirty_coords; 1727 int n_dirty_coords;
1616 coord_t **dirty_coords, *coord; 1728 coord_t **dirty_coords, *coord;
1729 coord_t *parent_coord;
1617 1730
1618 /* Mark all cached ancestral coords of dirty geos */ 1731 /* Mark all cached ancestral coords of dirty geos */
1619 n_dirty_geos = rdman->dirty_geos.num; 1732 n_dirty_geos = rdman->dirty_geos.num;
1620 dirty_geos = rdman->dirty_geos.ds; 1733 dirty_geos = rdman->dirty_geos.ds;
1621 for(i = 0; i < n_dirty_geos; i++) { 1734 for(i = 0; i < n_dirty_geos; i++) {
1626 break; 1739 break;
1627 coord_set_flags(coord, COF_TEMP_MARK); 1740 coord_set_flags(coord, COF_TEMP_MARK);
1628 coord = coord_get_cached(coord_get_parent(coord)); 1741 coord = coord_get_cached(coord_get_parent(coord));
1629 } 1742 }
1630 } 1743 }
1631 1744
1632 /* Mark all cached ancestral coords of dirty coords */ 1745 /* Mark all cached ancestral coords of dirty coords */
1633 n_dirty_coords = rdman->dirty_coords.num; 1746 n_dirty_coords = rdman->dirty_coords.num;
1634 dirty_coords = rdman->dirty_coords.ds; 1747 dirty_coords = rdman->dirty_coords.ds;
1635 for(i = 0; i < n_dirty_coords; i++) { 1748 for(i = 0; i < n_dirty_coords; i++) {
1636 coord = coord_get_cached(dirty_coords[i]); 1749 coord = coord_get_cached(dirty_coords[i]);
1639 break; 1752 break;
1640 coord_set_flags(coord, COF_TEMP_MARK); 1753 coord_set_flags(coord, COF_TEMP_MARK);
1641 coord = coord_get_cached(coord_get_parent(coord)); 1754 coord = coord_get_cached(coord_get_parent(coord));
1642 } 1755 }
1643 } 1756 }
1644 1757
1645 /* Add all marked coords into redraw_man_t::zeroing_coords list */ 1758 /* Add all marked coords into redraw_man_t::zeroing_coords list */
1646 FOR_COORDS_PREORDER(rdman->root_coord, coord) { 1759 FOR_COORDS_PREORDER(rdman->root_coord, coord) {
1647 if(!coord_is_cached(coord)) 1760 if(!coord_is_cached(coord) || coord_is_root(coord))
1648 continue; /* skip coords that is not cached */ 1761 continue; /* skip coords that is not cached */
1649 1762
1650 if(!coord_get_flags(coord, COF_TEMP_MARK)) { 1763 if(!coord_get_flags(coord, COF_TEMP_MARK)) {
1651 if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) 1764 parent_coord = coord_get_parent(coord);
1765 /* The pcache_area of a cached coord that is a child of a
1766 * just cleaned one must be recomputed.
1767 */
1768 if(coord_get_flags(parent_coord, COF_JUST_CLEAN))
1652 add_dirty_pcache_area_coord(rdman, coord); 1769 add_dirty_pcache_area_coord(rdman, coord);
1770
1653 preorder_coord_skip_subtree(coord); 1771 preorder_coord_skip_subtree(coord);
1654 continue; 1772 continue;
1655 } 1773 }
1656 add_zeroing_coord(rdman, coord); 1774 add_zeroing_coord(rdman, coord);
1657 1775
1658 coord_clear_flags(coord, COF_TEMP_MARK); 1776 coord_clear_flags(coord, COF_TEMP_MARK);
1659 } 1777 }
1660 1778
1661 return OK; 1779 return OK;
1662 } 1780 }
1663 1781
1664 /*! \brief Zeroing coords in redraw_man_t::zeroing_coords. 1782 /*! \brief Zeroing coords in redraw_man_t::zeroing_coords.
1665 * 1783 *
1669 */ 1787 */
1670 static int zeroing_rdman_coords(redraw_man_t *rdman) { 1788 static int zeroing_rdman_coords(redraw_man_t *rdman) {
1671 int i; 1789 int i;
1672 coords_t *all_zeroing; 1790 coords_t *all_zeroing;
1673 coord_t *coord; 1791 coord_t *coord;
1674 1792
1675 all_zeroing = &rdman->zeroing_coords; 1793 all_zeroing = &rdman->zeroing_coords;
1676 /*! Zeroing is performed from leaves to root. 1794 /*! Zeroing is performed from leaves to root.
1677 * 1795 *
1678 * REASON: The size of canvas is also effected by cached 1796 * REASON: The size of canvas is also effected by cached
1679 * descedants. A cached coord is only effected by parent 1797 * descedants. A cached coord is only effected by parent
1684 * performed before zeroing. It means ancestors of a 1802 * performed before zeroing. It means ancestors of a
1685 * cached coord would not effect it when zeroing. 1803 * cached coord would not effect it when zeroing.
1686 */ 1804 */
1687 for(i = all_zeroing->num - 1; i >= 0; i--) { 1805 for(i = all_zeroing->num - 1; i >= 0; i--) {
1688 coord = all_zeroing->ds[i]; 1806 coord = all_zeroing->ds[i];
1689 zeroing_coord(rdman, coord); 1807 if(coord_is_zeroing(coord))
1808 zeroing_coord(rdman, coord);
1809 compute_cached_2_pdev_matrix(coord);
1810 /* This is required by ancester cached ones to perform
1811 * zeroing.
1812 */
1690 compute_pcache_area(coord); 1813 compute_pcache_area(coord);
1691 } 1814 }
1692 1815
1693 return OK; 1816 return OK;
1694 } 1817 }
1695 1818
1696 /*! \brief Compute pcache_area for coords whoes pcache_area is dirty. 1819 /*! \brief Update aggregated cache_2_pdev matrix for cached coords.
1697 * 1820 *
1698 * coord_t::dirty_pcache_area_coords also includes part of coords in 1821 * This is perfromed from root to leaves. Aggregated cache_2_pdev is
1699 * coord_t::zeroing_coords. The pcache_area of coords that is in 1822 * named as aggr_2_pdev field of canvas_info_t. It is the matrix to
1700 * coord_t::dirty_pcache_area_coords, but is not in 1823 * transform a point from space of a cached coord to the space of root
1701 * coord_t::zeroing_coords should be computed here. 1824 * coord.
1702 * zeroing_rdman_coords() is responsible for computing pcache_area for
1703 * zeroing ones.
1704 */ 1825 */
1705 static int 1826 static int
1706 compute_rdman_coords_pcache_area(redraw_man_t *rdman) { 1827 update_aggr_pdev(redraw_man_t *rdman) {
1707 coords_t *all_coords;
1708 coord_t *coord;
1709 int i; 1828 int i;
1710 1829 coords_t *all_zeroing;
1711 all_coords = &rdman->dirty_pcache_area_coords; 1830 coord_t *coord, *parent_cached;
1712 for(i = 0; i < all_coords->num; i++) { 1831
1713 coord = all_coords->ds[i]; 1832 all_zeroing = &rdman->zeroing_coords;
1714 if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) 1833 for(i = 0; i < all_zeroing->num; i++) {
1715 compute_pcache_area(coord); 1834 coord = all_zeroing->ds[i];
1716 } 1835 parent_cached = coord_get_cached(coord_get_parent(coord));
1836 matrix_mul(coord_get_2pdev(parent_cached),
1837 coord_get_2pdev(coord),
1838 coord_get_aggr2pdev(coord));
1839 matrix_mul(coord_get_2pdev_rev(coord),
1840 coord_get_2pdev_rev(parent_cached),
1841 coord_get_aggr2pdev_rev(coord));
1842 }
1843
1717 return OK; 1844 return OK;
1718 } 1845 }
1719 1846
1720 /*! \brief Add aggregated dirty areas to ancestor. 1847 /*! \brief Add aggregated dirty areas to ancestor.
1721 * 1848 *
1725 */ 1852 */
1726 static void add_aggr_dirty_areas_to_ancestor(redraw_man_t *rdman, 1853 static void add_aggr_dirty_areas_to_ancestor(redraw_man_t *rdman,
1727 coord_t *coord) { 1854 coord_t *coord) {
1728 int i; 1855 int i;
1729 int n_areas; 1856 int n_areas;
1730 int enable_poses1 = 0;
1731 co_aix poses0[2][2], poses1[2][2]; 1857 co_aix poses0[2][2], poses1[2][2];
1732 co_aix reverse[6]; 1858 co_aix *canvas2pdev_matrix;
1733 co_aix canvas2pdev_matrix[6];
1734 area_t **areas, *area; 1859 area_t **areas, *area;
1735 area_t *area0, *area1; 1860 area_t *area0, *area1;
1736 coord_t *parent, *pcached_coord; 1861 coord_t *parent, *pcached_coord;
1737 1862
1738 n_areas = _coord_get_dirty_areas(coord)->num; 1863 n_areas = _coord_get_dirty_areas(coord)->num;
1739 areas = _coord_get_dirty_areas(coord)->ds; 1864 areas = _coord_get_dirty_areas(coord)->ds;
1740 if(n_areas == 0) 1865 if(n_areas == 0) {
1741 abort(); /* should not happen! */ 1866 /* Go here for cached one that is descendant of another zeroed
1742 1867 * one, but itself is not zeroed. It is here for recomputing
1868 * pcache areas.
1869 */
1870 if(coord_get_flags(coord, COF_JUST_CLEAN | COF_JUST_ZERO))
1871 abort(); /* should not happen! */
1872
1873 parent = coord_get_parent(coord);
1874 pcached_coord = coord_get_cached(parent);
1875 area = coord_get_pcache_area(coord);
1876 add_dirty_area(rdman, pcached_coord, area);
1877 area = coord_get_pcache_last_area(coord);
1878 add_dirty_area(rdman, pcached_coord, area);
1879 return;
1880 }
1881
1743 area0 = _coord_get_aggr_dirty_areas(coord); 1882 area0 = _coord_get_aggr_dirty_areas(coord);
1744 area1 = area0 + 1; 1883 area1 = area0 + 1;
1745 1884
1746 /* TODO: Since both cur & last area of coords are added into dirty 1885 /* TODO: Since both cur & last area of coords are added into dirty
1747 * area list, position of both areas shoud be adjusted for 1886 * area list, position of both areas shoud be adjusted for
1753 break; 1892 break;
1754 } 1893 }
1755 1894
1756 if(i >= n_areas) 1895 if(i >= n_areas)
1757 return; 1896 return;
1758 1897
1759 area = areas[i++]; 1898 area = areas[i++];
1760 poses0[0][0] = area->x; 1899 poses0[0][0] = area->x;
1761 poses0[0][1] = area->y; 1900 poses0[0][1] = area->y;
1762 poses0[1][0] = area->x + area->w; 1901 poses0[1][0] = area->x + area->w;
1763 poses0[1][1] = area->y + area->h; 1902 poses0[1][1] = area->y + area->h;
1764 1903
1765 if(i < n_areas) { 1904 if(i < n_areas) {
1766 area = areas[i++]; 1905 area = areas[i++];
1767 poses1[0][0] = area->x; 1906 poses1[0][0] = area->x;
1768 poses1[0][1] = area->y; 1907 poses1[0][1] = area->y;
1769 poses1[1][0] = area->x + area->w; 1908 poses1[1][0] = area->x + area->w;
1772 poses1[0][0] = 0; 1911 poses1[0][0] = 0;
1773 poses1[0][1] = 0; 1912 poses1[0][1] = 0;
1774 poses1[1][0] = 0; 1913 poses1[1][0] = 0;
1775 poses1[1][1] = 0; 1914 poses1[1][1] = 0;
1776 } 1915 }
1777 1916
1778 for(; i < n_areas - 1;) { 1917 for(; i < n_areas - 1;) {
1779 /* Even areas */ 1918 /* Even areas */
1780 area = areas[i++]; 1919 area = areas[i++];
1781 if(area->w != 0 || area->h != 0) { 1920 if(area->w != 0 || area->h != 0) {
1782 poses0[0][0] = MB_MIN(poses0[0][0], area->x); 1921 poses0[0][0] = MB_MIN(poses0[0][0], area->x);
1791 poses1[0][1] = MB_MIN(poses1[0][1], area->y); 1930 poses1[0][1] = MB_MIN(poses1[0][1], area->y);
1792 poses1[1][0] = MB_MAX(poses1[1][0], area->x + area->w); 1931 poses1[1][0] = MB_MAX(poses1[1][0], area->x + area->w);
1793 poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h); 1932 poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h);
1794 } 1933 }
1795 } 1934 }
1796 1935
1797 if(i < n_areas) { 1936 if(i < n_areas) {
1798 area = areas[i]; 1937 area = areas[i];
1799 if(area->w != 0 || area->h != 0) { 1938 if(area->w != 0 || area->h != 0) {
1800 poses0[0][0] = MB_MIN(poses0[0][0], area->x); 1939 poses0[0][0] = MB_MIN(poses0[0][0], area->x);
1801 poses0[0][1] = MB_MIN(poses0[0][1], area->y); 1940 poses0[0][1] = MB_MIN(poses0[0][1], area->y);
1802 poses0[1][0] = MB_MAX(poses0[1][0], area->x + area->w); 1941 poses0[1][0] = MB_MAX(poses0[1][0], area->x + area->w);
1803 poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h); 1942 poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h);
1804 } 1943 }
1805 } 1944 }
1806 1945
1807 parent = coord_get_parent(coord); 1946 parent = coord_get_parent(coord);
1808 pcached_coord = coord_get_cached(parent); 1947 pcached_coord = coord_get_cached(parent);
1809 1948
1810 compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); 1949 canvas2pdev_matrix = coord_get_2pdev(coord);
1811 1950
1812 /* Add dirty areas to parent cached coord. */ 1951 /* Add dirty areas to parent cached coord. */
1813 matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1); 1952 matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1);
1814 matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1); 1953 matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1);
1815 area_init(area0, 2, poses0); 1954 area_init(area0, 2, poses0);
1816 add_dirty_area(rdman, pcached_coord, area0); 1955 add_dirty_area(rdman, pcached_coord, area0);
1817 1956
1818 matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1); 1957 matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1);
1819 matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1); 1958 matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1);
1820 area_init(area1, 2, poses1); 1959 area_init(area1, 2, poses1);
1821 add_dirty_area(rdman, pcached_coord, area1); 1960 add_dirty_area(rdman, pcached_coord, area1);
1822 1961
1838 * areas and one or new areas. Both aggregation areas are add into 1977 * areas and one or new areas. Both aggregation areas are add into
1839 * dirty_areas list of closet ancestral cached coord. 1978 * dirty_areas list of closet ancestral cached coord.
1840 */ 1979 */
1841 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { 1980 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) {
1842 int i; 1981 int i;
1843 int n_zeroing; 1982 coord_t *coord, *parent_coord, *pcached_coord;
1844 coord_t **zeroings; 1983 int n_zeroing_coords; /* number of dirty pcache area coords */
1845 coord_t *coord, *pcached_coord; 1984 coord_t **zeroing_coords; /* dirty pcache area coords */
1846 int n_dpca_coords; /* number of dirty pcache area coords */ 1985
1847 coord_t **dpca_coords; /* dirty pcache area coords */ 1986 n_zeroing_coords = rdman->zeroing_coords.num;
1848 1987 zeroing_coords = rdman->zeroing_coords.ds;
1849 /* Add aggregated areas to parent cached one for coords in zeroing 1988 for(i = n_zeroing_coords - 1; i >= 0; i--) {
1850 * list 1989 coord = zeroing_coords[i];
1851 */
1852 n_zeroing = rdman->zeroing_coords.num;
1853 zeroings = rdman->zeroing_coords.ds;
1854 for(i = 0; i < n_zeroing; i++) {
1855 if(coord_get_flags(coord, COF_TEMP_MARK))
1856 continue;
1857 coord_set_flags(coord, COF_TEMP_MARK);
1858
1859 coord = zeroings[i];
1860 pcached_coord = coord_get_cached(coord_get_parent(coord));
1861
1862 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord))
1863 continue;
1864
1865 if(IS_CACHE_REDRAW_ALL(coord)) { 1990 if(IS_CACHE_REDRAW_ALL(coord)) {
1991 parent_coord = coord_get_parent(coord);
1992 pcached_coord = coord_get_cached(parent_coord);
1993
1866 add_dirty_area(rdman, pcached_coord, 1994 add_dirty_area(rdman, pcached_coord,
1867 coord_get_pcache_area(coord)); 1995 coord_get_pcache_area(coord));
1868 add_dirty_area(rdman, pcached_coord, 1996 add_dirty_area(rdman, pcached_coord,
1869 coord_get_pcache_last_area(coord)); 1997 coord_get_pcache_last_area(coord));
1870 } else { 1998 } else {
1871 add_aggr_dirty_areas_to_ancestor(rdman, coord); 1999 add_aggr_dirty_areas_to_ancestor(rdman, coord);
1872 } 2000 }
1873 }
1874
1875 /* Add pcache_areas to parent cached one for coord that is
1876 * non-zeroing and its parent is changed.
1877 */
1878 n_dpca_coords = rdman->dirty_pcache_area_coords.num;
1879 dpca_coords = rdman->dirty_pcache_area_coords.ds;
1880 for(i = 0; i < n_dpca_coords; i++) {
1881 if(coord_get_flags(coord, COF_TEMP_MARK))
1882 continue;
1883 coord_set_flags(coord, COF_TEMP_MARK);
1884
1885 coord = dpca_coords[i];
1886 pcached_coord = coord_get_cached(coord_get_parent(coord));
1887
1888 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord))
1889 continue;
1890
1891 add_dirty_area(rdman, pcached_coord,
1892 coord_get_pcache_area(coord));
1893 add_dirty_area(rdman, pcached_coord,
1894 coord_get_pcache_last_area(coord));
1895 }
1896
1897 /* Remove temporary mark */
1898 for(i = 0; i < n_zeroing; i++) {
1899 coord_clear_flags(zeroings[i], COF_TEMP_MARK);
1900 }
1901 for(i = 0; i < n_dpca_coords; i++) {
1902 coord_clear_flags(dpca_coords[i], COF_TEMP_MARK);
1903 } 2001 }
1904 2002
1905 return OK; 2003 return OK;
1906 } 2004 }
1907 2005
1979 SWAP(coord->cur_area, coord->last_area, area_t *); 2077 SWAP(coord->cur_area, coord->last_area, area_t *);
1980 FOR_COORD_MEMBERS(coord, geo) { 2078 FOR_COORD_MEMBERS(coord, geo) {
1981 GEO_SWAP(geo); 2079 GEO_SWAP(geo);
1982 } 2080 }
1983 } 2081 }
1984 2082
2083 /* XXX: some geo may swap two times. Should avoid it.
2084 */
1985 geos = rdman->dirty_geos.ds; 2085 geos = rdman->dirty_geos.ds;
1986 for(i = 0; i < rdman->dirty_geos.num; i++) { 2086 for(i = 0; i < rdman->dirty_geos.num; i++) {
1987 geo = geos[i]; 2087 geo = geos[i];
1988 GEO_SWAP(geo); 2088 GEO_SWAP(geo);
1989 } 2089 }
1990 2090
1991 r = clean_rdman_coords(rdman); 2091 r = clean_rdman_coords(rdman);
1992 if(r != OK) 2092 if(r != OK)
1993 return ERR; 2093 return ERR;
1994 2094
1995 /* TODO: save area of cached coord and descendants in 2095 /* TODO: save area of cached coord and descendants in
2001 return ERR; 2101 return ERR;
2002 2102
2003 /* Zeroing must be performed after clearing to get latest position 2103 /* Zeroing must be performed after clearing to get latest position
2004 * of shapes for computing new bounding box 2104 * of shapes for computing new bounding box
2005 */ 2105 */
2006 r = add_rdman_zeroing_coords(rdman); 2106 r = add_rdman_zeroing_n_pcache_coords(rdman);
2007 if(r != OK) 2107 if(r != OK)
2008 return ERR; 2108 return ERR;
2009 2109
2010 r = zeroing_rdman_coords(rdman); 2110 r = zeroing_rdman_coords(rdman);
2011 if(r != OK) 2111 if(r != OK)
2012 return ERR; 2112 return ERR;
2013 2113
2014 r = compute_rdman_coords_pcache_area(rdman); 2114 r = add_rdman_aggr_dirty_areas(rdman);
2015 if(r != OK) 2115 if(r != OK)
2016 return ERR; 2116 return ERR;
2017 2117
2018 r = add_rdman_aggr_dirty_areas(rdman); 2118 r = update_aggr_pdev(rdman);
2019 if(r != OK) 2119 if(r != OK)
2020 return ERR; 2120 return ERR;
2021 2121
2022 /* 2122 /*
2023 * Clear all flags setted by zeroing. 2123 * Clear all flags setted by zeroing.
2033 } 2133 }
2034 coords = rdman->zeroing_coords.ds; 2134 coords = rdman->zeroing_coords.ds;
2035 for(i = 0; i < rdman->zeroing_coords.num; i++) 2135 for(i = 0; i < rdman->zeroing_coords.num; i++)
2036 coord_clear_flags(coords[i], 2136 coord_clear_flags(coords[i],
2037 COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); 2137 COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO);
2038 coords = rdman->dirty_pcache_area_coords.ds;
2039 for(i = 0; i < rdman->dirty_pcache_area_coords.num; i++)
2040 coord_clear_flags(coords[i],
2041 COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO);
2042 2138
2043 /* \see GEO_SWAP() */ 2139 /* \see GEO_SWAP() */
2044 for(i = 0; i < rdman->dirty_geos.num; i++) { 2140 for(i = 0; i < rdman->dirty_geos.num; i++) {
2045 geo = geos[i]; 2141 geo = geos[i];
2046 geo_clear_flags(geo, GEF_SWAP); 2142 geo_clear_flags(geo, GEF_SWAP);
2047 } 2143 }
2048 2144
2049 return OK; 2145 return OK;
2050 } 2146 }
2051 2147
2052 2148
2053 /* Drawing and Redrawing 2149 /* Drawing and Redrawing
2057 #ifndef UNITTEST 2153 #ifndef UNITTEST
2058 static void set_shape_stroke_param(shape_t *shape, mbe_t *cr) { 2154 static void set_shape_stroke_param(shape_t *shape, mbe_t *cr) {
2059 mbe_set_line_width(cr, shape->stroke_width); 2155 mbe_set_line_width(cr, shape->stroke_width);
2060 } 2156 }
2061 2157
2062 static void fill_path_preserve(redraw_man_t *rdman) { 2158 static void fill_path_preserve(redraw_man_t *rdman, mbe_t *cr) {
2063 mbe_fill_preserve(rdman->cr); 2159 mbe_fill_preserve(cr);
2064 } 2160 }
2065 2161
2066 static void fill_path(redraw_man_t *rdman) { 2162 static void fill_path(redraw_man_t *rdman, mbe_t *cr) {
2067 mbe_fill(rdman->cr); 2163 mbe_fill(cr);
2068 } 2164 }
2069 2165
2070 static void stroke_path(redraw_man_t *rdman) { 2166 static void stroke_path(redraw_man_t *rdman, mbe_t *cr) {
2071 mbe_stroke(rdman->cr); 2167 mbe_stroke(cr);
2072 } 2168 }
2073 #else 2169 #else
2074 static void set_shape_stroke_param(shape_t *shape, mbe_t *cr) { 2170 static void set_shape_stroke_param(shape_t *shape, mbe_t *cr) {
2075 } 2171 }
2076 2172
2077 static void fill_path_preserve(redraw_man_t *rdman) { 2173 static void fill_path_preserve(redraw_man_t *rdman, mbe_t *cr) {
2078 } 2174 }
2079 2175
2080 static void fill_path(redraw_man_t *rdman) { 2176 static void fill_path(redraw_man_t *rdman, mbe_t *cr) {
2081 } 2177 }
2082 2178
2083 static void stroke_path(redraw_man_t *rdman) { 2179 static void stroke_path(redraw_man_t *rdman, mbe_t *cr) {
2084 } 2180 }
2085 #endif 2181 #endif
2086 2182
2087 static void draw_shape(redraw_man_t *rdman, mbe_t *cr, shape_t *shape) { 2183 static void draw_shape(redraw_man_t *rdman, mbe_t *cr, shape_t *shape) {
2088 paint_t *fill, *stroke; 2184 paint_t *fill, *stroke;
2118 #endif /* UNITTEST */ 2214 #endif /* UNITTEST */
2119 } 2215 }
2120 2216
2121 fill = shape->fill; 2217 fill = shape->fill;
2122 if(shape->fill) { 2218 if(shape->fill) {
2123 fill->prepare(fill, cr); 2219 fill->prepare(fill, cr, shape);
2124 if(shape->stroke) 2220 if(shape->stroke)
2125 fill_path_preserve(rdman); 2221 fill_path_preserve(rdman, cr);
2126 else 2222 else
2127 fill_path(rdman); 2223 fill_path(rdman, cr);
2128 } 2224 }
2129 2225
2130 stroke = shape->stroke; 2226 stroke = shape->stroke;
2131 if(stroke) { 2227 if(stroke) {
2132 stroke->prepare(stroke, cr); 2228 stroke->prepare(stroke, cr, shape);
2133 set_shape_stroke_param(shape, cr); 2229 set_shape_stroke_param(shape, cr);
2134 stroke_path(rdman); 2230 stroke_path(rdman, cr);
2135 } 2231 }
2136 } 2232 }
2137 } 2233 }
2138 2234
2139 #ifndef UNITTEST 2235 #ifndef UNITTEST
2140 static void clear_canvas(canvas_t *canvas) { 2236 static void clear_canvas(canvas_t *canvas) {
2141 mbe_clear(canvas); 2237 mbe_clear(canvas);
2142 } 2238 }
2143 2239
2144 #define make_clip(canvas, n_dirty_areas, dirty_areas) \ 2240 static void make_clip(mbe_t *cr, int n_dirty_areas,
2145 mbe_scissoring(canvas, n_dirty_areas, dirty_areas) 2241 area_t **dirty_areas) {
2242 int i;
2243 area_t *area;
2244
2245 mbe_new_path(cr);
2246 for(i = 0; i < n_dirty_areas; i++) {
2247 area = dirty_areas[i];
2248 if(area->w < 0.1 || area->h < 0.1)
2249 continue;
2250 mbe_rectangle(cr, area->x, area->y, area->w, area->h);
2251 }
2252 mbe_clip(cr);
2253 }
2146 2254
2147 static void reset_clip(canvas_t *cr) { 2255 static void reset_clip(canvas_t *cr) {
2148 mbe_reset_scissoring(cr); 2256 mbe_reset_clip(cr);
2149 } 2257 }
2150 2258
2151 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, 2259 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas,
2152 area_t **dirty_areas) { 2260 area_t **dirty_areas) {
2153 if(n_dirty_areas) 2261 if(n_dirty_areas)
2154 make_clip(rdman->backend, n_dirty_areas, dirty_areas); 2262 make_clip(rdman->backend, n_dirty_areas, dirty_areas);
2155 2263
2156 mbe_copy_source(rdman->cr, rdman->backend); 2264 mbe_copy_source(rdman->cr, rdman->backend);
2157 } 2265 }
2158 #else /* UNITTEST */ 2266 #else /* UNITTEST */
2159 #define make_clip(canvas, n_dirty_areas, dirty_areas) 2267 static void make_clip(mbe_t *cr, int n_dirty_areas,
2268 area_t **dirty_areas) {
2269 }
2160 2270
2161 static void clear_canvas(canvas_t *canvas) { 2271 static void clear_canvas(canvas_t *canvas) {
2162 } 2272 }
2163 2273
2164 static void reset_clip(canvas_t *cr) { 2274 static void reset_clip(canvas_t *cr) {
2167 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, 2277 static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas,
2168 area_t **dirty_areas) { 2278 area_t **dirty_areas) {
2169 } 2279 }
2170 #endif /* UNITTEST */ 2280 #endif /* UNITTEST */
2171 2281
2172 static void update_cached_canvas_2_parent(redraw_man_t *rdman, 2282 static void
2173 coord_t *coord) { 2283 _update_cached_canvas_2_parent(redraw_man_t *rdman, co_aix reverse[6],
2174 mbe_t *pcanvas, *canvas; 2284 mbe_t *canvas, mbe_t *pcanvas,
2285 co_aix opacity) {
2175 mbe_surface_t *surface; 2286 mbe_surface_t *surface;
2176 mbe_pattern_t *pattern; 2287 mbe_pattern_t *pattern;
2177 co_aix reverse[6];
2178 co_aix canvas2pdev_matrix[6];
2179
2180 if(coord_is_root(coord))
2181 return;
2182
2183 compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix);
2184 compute_reverse(canvas2pdev_matrix, reverse);
2185 2288
2186 canvas = _coord_get_canvas(coord);
2187 pcanvas = _coord_get_canvas(coord->parent);
2188 surface = mbe_get_target(canvas); 2289 surface = mbe_get_target(canvas);
2189 pattern = mbe_pattern_create_for_surface(surface); 2290 pattern = mbe_pattern_create_for_surface(surface);
2190 mbe_pattern_set_matrix(pattern, reverse); 2291 mbe_pattern_set_matrix(pattern, reverse);
2191 mbe_set_source(pcanvas, pattern); 2292 mbe_set_source(pcanvas, pattern);
2192 mbe_paint_with_alpha(pcanvas, coord->opacity); 2293 mbe_paint_with_alpha(pcanvas, opacity);
2294 }
2295
2296 static void update_cached_canvas_2_parent(redraw_man_t *rdman,
2297 coord_t *coord) {
2298 mbe_t *pcanvas, *canvas;
2299 co_aix *c2pdev_reverse;
2300
2301 if(coord_is_root(coord))
2302 return;
2303
2304 c2pdev_reverse = coord_get_2pdev_rev(coord);
2305
2306 canvas = _coord_get_canvas(coord);
2307 pcanvas = _coord_get_canvas(coord->parent);
2308 #ifndef UNITTEST
2309 _update_cached_canvas_2_parent(rdman, c2pdev_reverse, canvas, pcanvas,
2310 coord->opacity);
2311 #else
2312 memcpy(((mock_mbe_t *)canvas)->parent_2_cache, c2pdev_reverse,
2313 sizeof(co_aix) * 6);
2314 #endif
2193 } 2315 }
2194 2316
2195 static int draw_coord_shapes_in_dirty_areas(redraw_man_t *rdman, 2317 static int draw_coord_shapes_in_dirty_areas(redraw_man_t *rdman,
2196 coord_t *coord) { 2318 coord_t *coord) {
2197 int dirty = 0; 2319 int dirty = 0;
2203 coord_t *child; 2325 coord_t *child;
2204 int mem_idx; 2326 int mem_idx;
2205 2327
2206 if(coord->flags & COF_HIDDEN) 2328 if(coord->flags & COF_HIDDEN)
2207 return OK; 2329 return OK;
2208 2330
2209 areas = _coord_get_dirty_areas(coord)->ds; 2331 areas = _coord_get_dirty_areas(coord)->ds;
2210 n_areas = _coord_get_dirty_areas(coord)->num; 2332 n_areas = _coord_get_dirty_areas(coord)->num;
2211 canvas = _coord_get_canvas(coord); 2333 canvas = _coord_get_canvas(coord);
2212 2334
2213 member = FIRST_MEMBER(coord); 2335 member = FIRST_MEMBER(coord);
2214 mem_idx = 0; 2336 mem_idx = 0;
2215 child = FIRST_CHILD(coord); 2337 child = FIRST_CHILD(coord);
2216 while(child != NULL || member != NULL) { 2338 while(child != NULL || member != NULL) {
2217 if(child && child->before_pmem == mem_idx) { 2339 if(child && child->before_pmem == mem_idx) {
2218 if(coord_is_cached(child)) { 2340 if(coord_is_cached(child)) {
2219 if(!(child->flags & COF_HIDDEN) && 2341 if(!(child->flags & COF_HIDDEN) &&
2220 is_area_in_areas(coord_get_area(child), n_areas, areas)) { 2342 is_area_in_areas(coord_get_pcache_area(child),
2343 n_areas, areas)) {
2221 update_cached_canvas_2_parent(rdman, child); 2344 update_cached_canvas_2_parent(rdman, child);
2222 dirty = 1; 2345 dirty = 1;
2223 } 2346 }
2224 } else { 2347 } else {
2225 r = draw_coord_shapes_in_dirty_areas(rdman, child); 2348 r = draw_coord_shapes_in_dirty_areas(rdman, child);
2226 dirty |= r; 2349 dirty |= r;
2227 } 2350 }
2228 child = NEXT_CHILD(child); 2351 child = NEXT_CHILD(child);
2229 } else { 2352 } else {
2230 ASSERT(member != NULL); 2353 ASSERT(member != NULL);
2231 if((!(member->flags & GEF_HIDDEN)) && 2354 if((!(member->flags & GEF_NOT_SHOWED)) &&
2232 is_geo_in_areas(member, n_areas, areas)) { 2355 is_geo_in_areas(member, n_areas, areas)) {
2233 draw_shape(rdman, canvas, member->shape); 2356 draw_shape(rdman, canvas, member->shape);
2234 dirty = 1; 2357 dirty = 1;
2235 } 2358 }
2236 2359
2249 int n_areas; 2372 int n_areas;
2250 mbe_t *canvas; 2373 mbe_t *canvas;
2251 mbe_surface_t *surface; 2374 mbe_surface_t *surface;
2252 int i; 2375 int i;
2253 int r; 2376 int r;
2254 2377
2255 canvas = _coord_get_canvas(coord); 2378 canvas = _coord_get_canvas(coord);
2256 2379
2257 if(IS_CACHE_REDRAW_ALL(coord)) { 2380 if(IS_CACHE_REDRAW_ALL(coord)) {
2258 /* 2381 /*
2259 * full_area covers all dirty areas of the cached coord. 2382 * full_area covers all dirty areas of the cached coord.
2260 */ 2383 */
2261 DARRAY_CLEAN(_coord_get_dirty_areas(coord)); 2384 DARRAY_CLEAN(_coord_get_dirty_areas(coord));
2267 add_dirty_area(rdman, coord, &full_area); 2390 add_dirty_area(rdman, coord, &full_area);
2268 } 2391 }
2269 2392
2270 areas = _coord_get_dirty_areas(coord)->ds; 2393 areas = _coord_get_dirty_areas(coord)->ds;
2271 n_areas = _coord_get_dirty_areas(coord)->num; 2394 n_areas = _coord_get_dirty_areas(coord)->num;
2272 2395
2273 for(i = 0; i < n_areas; i++) { 2396 for(i = 0; i < n_areas; i++) {
2274 area = areas[i]; 2397 area = areas[i];
2275 area->x = floorf(area->x); 2398 area->x = floorf(area->x);
2276 area->y = floorf(area->y); 2399 area->y = floorf(area->y);
2277 area->w = ceilf(area->w); 2400 area->w = ceilf(area->w);
2280 2403
2281 make_clip(canvas, n_areas, areas); 2404 make_clip(canvas, n_areas, areas);
2282 clear_canvas(canvas); 2405 clear_canvas(canvas);
2283 2406
2284 r = draw_coord_shapes_in_dirty_areas(rdman, coord); 2407 r = draw_coord_shapes_in_dirty_areas(rdman, coord);
2285 2408
2286 reset_clip(canvas); 2409 reset_clip(canvas);
2287 2410
2288 return OK; 2411 return OK;
2289 } 2412 }
2290 2413
2304 if(coord_get_flags(coord, COF_TEMP_MARK)) 2427 if(coord_get_flags(coord, COF_TEMP_MARK))
2305 continue; 2428 continue;
2306 draw_dirty_cached_coord(rdman, coord); 2429 draw_dirty_cached_coord(rdman, coord);
2307 coord_set_flags(coord, COF_TEMP_MARK); 2430 coord_set_flags(coord, COF_TEMP_MARK);
2308 } 2431 }
2309 for(i = 0; i < num; i++) 2432 for(i = 0; i < num; i++) {
2433 coord = zeroings[i];
2310 coord_clear_flags(coord, COF_TEMP_MARK); 2434 coord_clear_flags(coord, COF_TEMP_MARK);
2435 }
2311 2436
2312 draw_dirty_cached_coord(rdman, rdman->root_coord); 2437 draw_dirty_cached_coord(rdman, rdman->root_coord);
2313 } 2438 }
2314 2439
2315 2440
2348 int rdman_redraw_changed(redraw_man_t *rdman) { 2473 int rdman_redraw_changed(redraw_man_t *rdman) {
2349 int r; 2474 int r;
2350 event_t event; 2475 event_t event;
2351 subject_t *redraw; 2476 subject_t *redraw;
2352 int i; 2477 int i;
2353 coord_t *coord, **coords; 2478 coord_t *coord;
2354 int n_areas; 2479 int n_areas;
2355 area_t **areas; 2480 area_t **areas;
2356 2481
2357 r = rdman_clean_dirties(rdman); 2482 r = rdman_clean_dirties(rdman);
2358 if(r != OK) 2483 if(r != OK)
2359 return ERR; 2484 return ERR;
2360 2485
2361 if(rdman->n_dirty_areas > 0) { 2486 if(rdman->n_dirty_areas > 0) {
2376 } 2501 }
2377 2502
2378 DARRAY_CLEAN(&rdman->dirty_coords); 2503 DARRAY_CLEAN(&rdman->dirty_coords);
2379 DARRAY_CLEAN(&rdman->dirty_geos); 2504 DARRAY_CLEAN(&rdman->dirty_geos);
2380 DARRAY_CLEAN(&rdman->zeroing_coords); 2505 DARRAY_CLEAN(&rdman->zeroing_coords);
2381 DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); 2506
2382
2383 /* Free postponsed removing */ 2507 /* Free postponsed removing */
2384 free_free_objs(rdman); 2508 free_free_objs(rdman);
2385 2509
2386 redraw = rdman_get_redraw_subject(rdman); 2510 redraw = rdman_get_redraw_subject(rdman);
2387 event.type = EVT_RDMAN_REDRAW; 2511 event.type = EVT_RDMAN_REDRAW;
2439 /*! \brief Helping function to travel descendant shapes of a coord. 2563 /*! \brief Helping function to travel descendant shapes of a coord.
2440 */ 2564 */
2441 geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) { 2565 geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) {
2442 geo_t *next; 2566 geo_t *next;
2443 coord_t *coord; 2567 coord_t *coord;
2444 2568
2445 if(last == NULL) { 2569 if(last == NULL) {
2446 coord = rdman->root_coord; 2570 coord = rdman->root_coord;
2447 while(coord != NULL && FIRST_MEMBER(coord) == NULL) 2571 while(coord != NULL && FIRST_MEMBER(coord) == NULL)
2448 coord = preorder_coord_subtree(rdman->root_coord, coord); 2572 coord = preorder_coord_subtree(rdman->root_coord, coord);
2449 if(coord == NULL) 2573 if(coord == NULL)
2495 /* \defgroup rdman_observer Observer memory management 2619 /* \defgroup rdman_observer Observer memory management
2496 * 2620 *
2497 * Implment factory and strategy functions for observers and subjects. 2621 * Implment factory and strategy functions for observers and subjects.
2498 * @{ 2622 * @{
2499 */ 2623 */
2500 static subject_t *ob_subject_alloc(ob_factory_t *factory) { 2624 static subject_t *observer_subject_alloc(observer_factory_t *factory) {
2501 redraw_man_t *rdman; 2625 redraw_man_t *rdman;
2502 subject_t *subject; 2626 subject_t *subject;
2503 2627
2504 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); 2628 rdman = MEM2OBJ(factory, redraw_man_t, observer_factory);
2505 subject = elmpool_elm_alloc(rdman->subject_pool); 2629 subject = elmpool_elm_alloc(rdman->subject_pool);
2506 2630
2507 return subject; 2631 return subject;
2508 } 2632 }
2509 2633
2510 static void ob_subject_free(ob_factory_t *factory, subject_t *subject) { 2634 static void
2635 observer_subject_free(observer_factory_t *factory, subject_t *subject) {
2511 redraw_man_t *rdman; 2636 redraw_man_t *rdman;
2512 2637
2513 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); 2638 rdman = MEM2OBJ(factory, redraw_man_t, observer_factory);
2514 elmpool_elm_free(rdman->subject_pool, subject); 2639 elmpool_elm_free(rdman->subject_pool, subject);
2515 } 2640 }
2516 2641
2517 static observer_t *ob_observer_alloc(ob_factory_t *factory) { 2642 static observer_t *observer_observer_alloc(observer_factory_t *factory) {
2518 redraw_man_t *rdman; 2643 redraw_man_t *rdman;
2519 observer_t *observer; 2644 observer_t *observer;
2520 2645
2521 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); 2646 rdman = MEM2OBJ(factory, redraw_man_t, observer_factory);
2522 observer = elmpool_elm_alloc(rdman->observer_pool); 2647 observer = elmpool_elm_alloc(rdman->observer_pool);
2523 2648
2524 return observer; 2649 return observer;
2525 } 2650 }
2526 2651
2527 static void ob_observer_free(ob_factory_t *factory, observer_t *observer) { 2652 static void
2653 observer_observer_free(observer_factory_t *factory, observer_t *observer) {
2528 redraw_man_t *rdman; 2654 redraw_man_t *rdman;
2529 2655
2530 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); 2656 rdman = MEM2OBJ(factory, redraw_man_t, observer_factory);
2531 elmpool_elm_free(rdman->observer_pool, observer); 2657 elmpool_elm_free(rdman->observer_pool, observer);
2532 } 2658 }
2533 2659
2534 static subject_t *ob_get_parent_subject(ob_factory_t *factory, 2660 static subject_t *
2535 subject_t *cur_subject) { 2661 observer_get_parent_subject(observer_factory_t *factory,
2662 subject_t *cur_subject) {
2536 redraw_man_t *rdman; 2663 redraw_man_t *rdman;
2537 coord_t *coord, *parent_coord; 2664 coord_t *coord, *parent_coord;
2538 geo_t *geo; 2665 geo_t *geo;
2539 subject_t *parent; 2666 subject_t *parent;
2540 2667
2541 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); 2668 rdman = MEM2OBJ(factory, redraw_man_t, observer_factory);
2542 switch(cur_subject->obj_type) { 2669 switch(cur_subject->obj_type) {
2543 case OBJT_GEO: 2670 case OBJT_GEO:
2544 geo = (geo_t *)cur_subject->obj; 2671 geo = (geo_t *)cur_subject->obj;
2545 parent_coord = geo->shape->coord; 2672 parent_coord = geo->shape->coord;
2546 parent = parent_coord->mouse_event; 2673 parent = parent_coord->mouse_event;
2568 */ 2695 */
2569 paint_t *rdman_img_ldr_load_paint(redraw_man_t *rdman, const char *img_id) { 2696 paint_t *rdman_img_ldr_load_paint(redraw_man_t *rdman, const char *img_id) {
2570 mb_img_data_t *img_data; 2697 mb_img_data_t *img_data;
2571 paint_t *paint; 2698 paint_t *paint;
2572 mb_img_ldr_t *ldr = rdman_img_ldr(rdman); 2699 mb_img_ldr_t *ldr = rdman_img_ldr(rdman);
2573 2700
2574 img_data = MB_IMG_LDR_LOAD(ldr, img_id); 2701 img_data = MB_IMG_LDR_LOAD(ldr, img_id);
2575 if(img_data == NULL) 2702 if(img_data == NULL)
2576 return NULL; 2703 return NULL;
2577 2704
2578 paint = rdman_paint_image_new(rdman, img_data); 2705 paint = rdman_paint_image_new(rdman, img_data);
2579 if(paint == NULL) 2706 if(paint == NULL)
2580 MB_IMG_DATA_FREE(img_data); 2707 MB_IMG_DATA_FREE(img_data);
2581 2708
2582 return paint; 2709 return paint;
2583 } 2710 }
2584 2711
2585 #ifdef UNITTEST 2712 #ifdef UNITTEST
2586 /* Test cases */ 2713 /* Test cases */
2591 shape_t shape; 2718 shape_t shape;
2592 co_aix x, y; 2719 co_aix x, y;
2593 co_aix w, h; 2720 co_aix w, h;
2594 int trans_cnt; 2721 int trans_cnt;
2595 int draw_cnt; 2722 int draw_cnt;
2723 mbe_t *last_draw;
2596 }; 2724 };
2597 2725
2598 void sh_dummy_free(shape_t *sh) { 2726 void sh_dummy_free(shape_t *sh) {
2599 free(sh); 2727 free(sh);
2600 } 2728 }
2614 dummy->w = w; 2742 dummy->w = w;
2615 dummy->h = h; 2743 dummy->h = h;
2616 dummy->trans_cnt = 0; 2744 dummy->trans_cnt = 0;
2617 dummy->draw_cnt = 0; 2745 dummy->draw_cnt = 0;
2618 dummy->shape.free = sh_dummy_free; 2746 dummy->shape.free = sh_dummy_free;
2619 2747
2620 rdman_shape_man(rdman, (shape_t *)dummy); 2748 rdman_man_shape(rdman, (shape_t *)dummy);
2621 2749
2622 return (shape_t *)dummy; 2750 return (shape_t *)dummy;
2623 } 2751 }
2624 2752
2625 void sh_dummy_transform(shape_t *shape) { 2753 void sh_dummy_transform(shape_t *shape) {
2626 sh_dummy_t *dummy = (sh_dummy_t *)shape; 2754 sh_dummy_t *dummy = (sh_dummy_t *)shape;
2627 co_aix poses[2][2]; 2755 co_aix poses[2][2];
2628 co_aix x1, y1, x2, y2; 2756 co_aix x1, y1, x2, y2;
2629 2757
2630 if(shape->geo && shape->coord) { 2758 if(shape->geo && shape->coord) {
2631 x1 = dummy->x; 2759 x1 = dummy->x;
2632 y1 = dummy->y; 2760 y1 = dummy->y;
2633 x2 = x1 + dummy->w; 2761 x2 = x1 + dummy->w;
2634 y2 = y1 + dummy->h; 2762 y2 = y1 + dummy->h;
2637 coord_trans_pos(shape->coord, &x2, &y2); 2765 coord_trans_pos(shape->coord, &x2, &y2);
2638 poses[0][0] = x1; 2766 poses[0][0] = x1;
2639 poses[0][1] = y1; 2767 poses[0][1] = y1;
2640 poses[1][0] = x2; 2768 poses[1][0] = x2;
2641 poses[1][1] = y2; 2769 poses[1][1] = y2;
2642 2770
2643 if(shape->geo) 2771 if(shape->geo)
2644 geo_from_positions(shape->geo, 2, poses); 2772 geo_from_positions(shape->geo, 2, poses);
2645 } 2773 }
2646 dummy->trans_cnt++; 2774 dummy->trans_cnt++;
2647 } 2775 }
2649 void sh_dummy_fill(shape_t *shape, mbe_t *cr) { 2777 void sh_dummy_fill(shape_t *shape, mbe_t *cr) {
2650 sh_dummy_t *dummy; 2778 sh_dummy_t *dummy;
2651 2779
2652 dummy = (sh_dummy_t *)shape; 2780 dummy = (sh_dummy_t *)shape;
2653 dummy->draw_cnt++; 2781 dummy->draw_cnt++;
2782 dummy->last_draw = cr;
2654 } 2783 }
2655 2784
2656 static void dummy_paint_prepare(paint_t *paint, mbe_t *cr) { 2785 static void dummy_paint_prepare(paint_t *paint, mbe_t *cr) {
2657 } 2786 }
2658 2787
2701 CU_ASSERT(dummys[1]->trans_cnt == 1); 2830 CU_ASSERT(dummys[1]->trans_cnt == 1);
2702 CU_ASSERT(dummys[2]->trans_cnt == 1); 2831 CU_ASSERT(dummys[2]->trans_cnt == 1);
2703 CU_ASSERT(dummys[0]->draw_cnt == 1); 2832 CU_ASSERT(dummys[0]->draw_cnt == 1);
2704 CU_ASSERT(dummys[1]->draw_cnt == 1); 2833 CU_ASSERT(dummys[1]->draw_cnt == 1);
2705 CU_ASSERT(dummys[2]->draw_cnt == 1); 2834 CU_ASSERT(dummys[2]->draw_cnt == 1);
2706 2835
2707 coords[2]->matrix[2] = 100; 2836 coords[2]->matrix[2] = 100;
2708 coords[2]->matrix[5] = 100; 2837 coords[2]->matrix[5] = 100;
2709 rdman_coord_changed(rdman, coords[0]); 2838 rdman_coord_changed(rdman, coords[0]);
2710 rdman_coord_changed(rdman, coords[2]); 2839 rdman_coord_changed(rdman, coords[2]);
2711 rdman_redraw_changed(rdman); 2840 rdman_redraw_changed(rdman);
2739 2868
2740 redraw_man_destroy(rdman); 2869 redraw_man_destroy(rdman);
2741 CU_ASSERT(test_free_pass == 4); 2870 CU_ASSERT(test_free_pass == 4);
2742 } 2871 }
2743 2872
2873 static void
2874 test_setup_canvas_info(void) {
2875 redraw_man_t *rdman;
2876 redraw_man_t _rdman;
2877 coord_t *coord;
2878
2879 redraw_man_init(&_rdman, NULL, NULL);
2880 rdman = &_rdman;
2881
2882 coord = rdman_coord_new(rdman, rdman->root_coord);
2883 CU_ASSERT(coord->parent == rdman->root_coord);
2884
2885 coord_set_opacity(coord, 0.9);
2886 setup_canvas_info(rdman, coord);
2887
2888 CU_ASSERT(coord->canvas_info != rdman->root_coord->canvas_info);
2889
2890 coord_set_opacity(coord, 1);
2891 setup_canvas_info(rdman, coord);
2892
2893 CU_ASSERT(coord->canvas_info == rdman->root_coord->canvas_info);
2894 }
2895
2896 static void
2897 test_own_canvas_area(void) {
2898 redraw_man_t *rdman;
2899 redraw_man_t _rdman;
2900 coord_t *coord1, *coord2;
2901 sh_dummy_t *sh;
2902
2903 redraw_man_init(&_rdman, NULL, NULL);
2904 rdman = &_rdman;
2905
2906 coord1 = rdman_coord_new(rdman, rdman->root_coord);
2907 CU_ASSERT(coord1->parent == rdman->root_coord);
2908
2909 coord2 = rdman_coord_new(rdman, coord1);
2910 CU_ASSERT(coord2->parent == coord1);
2911
2912 coord_set_opacity(coord2, 0.9);
2913 rdman_coord_changed(rdman, coord2);
2914
2915 sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20);
2916 rdman_add_shape(rdman, (shape_t *)sh, coord2);
2917 rdman_shape_changed(rdman, (shape_t *)sh);
2918
2919 clean_coord(rdman, coord2);
2920
2921 /* Parent cached coord must be updated */
2922 CU_ASSERT(geo_get_area(coord2)->x == 100);
2923 CU_ASSERT(geo_get_area(coord2)->y == 100);
2924 CU_ASSERT(geo_get_area(coord2)->w <= 22 && geo_get_area(coord2)->w >= 19);
2925 CU_ASSERT(geo_get_area(coord2)->h <= 22 && geo_get_area(coord2)->h >= 19);
2926
2927 redraw_man_destroy(rdman);
2928 }
2929
2930 static void
2931 test_own_canvas(void) {
2932 redraw_man_t *rdman;
2933 redraw_man_t _rdman;
2934 coord_t *coord1, *coord2;
2935 sh_dummy_t *sh;
2936
2937 redraw_man_init(&_rdman, NULL, NULL);
2938 rdman = &_rdman;
2939
2940 coord1 = rdman_coord_new(rdman, rdman->root_coord);
2941 CU_ASSERT(coord1->parent == rdman->root_coord);
2942
2943 coord2 = rdman_coord_new(rdman, coord1);
2944 CU_ASSERT(coord2->parent == coord1);
2945
2946 coord_set_opacity(coord2, 0.9);
2947 rdman_coord_changed(rdman, coord2);
2948
2949 sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20);
2950 rdman_add_shape(rdman, (shape_t *)sh, coord2);
2951 rdman_shape_changed(rdman, (shape_t *)sh);
2952
2953 rdman_clean_dirties(rdman);
2954
2955 /* Parent cached coord must be updated */
2956 CU_ASSERT(_coord_get_dirty_areas(rdman->root_coord)->num == 1);
2957
2958 CU_ASSERT(geo_get_area(coord2)->x == 0);
2959 CU_ASSERT(geo_get_area(coord2)->y == 0);
2960 CU_ASSERT(geo_get_area(coord2)->w <= 22 && geo_get_area(coord2)->w >= 19);
2961 CU_ASSERT(geo_get_area(coord2)->h <= 22 && geo_get_area(coord2)->h >= 19);
2962
2963 redraw_man_destroy(rdman);
2964 }
2965
2966 static void
2967 test_own_canvas_redraw(void) {
2968 redraw_man_t *rdman;
2969 redraw_man_t _rdman;
2970 coord_t *coord1, *coord2;
2971 sh_dummy_t *sh;
2972 paint_t *paint;
2973 co_aix *parent_2_cache;
2974
2975 redraw_man_init(&_rdman, NULL, NULL);
2976 rdman = &_rdman;
2977
2978 coord1 = rdman_coord_new(rdman, rdman->root_coord);
2979 CU_ASSERT(coord1->parent == rdman->root_coord);
2980
2981 coord2 = rdman_coord_new(rdman, coord1);
2982 CU_ASSERT(coord2->parent == coord1);
2983
2984 coord_set_opacity(coord2, 0.9);
2985 rdman_coord_changed(rdman, coord2);
2986
2987 sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20);
2988 rdman_add_shape(rdman, (shape_t *)sh, coord2);
2989 rdman_shape_changed(rdman, (shape_t *)sh);
2990
2991 paint = dummy_paint_new(rdman);
2992 rdman_paint_fill(rdman, paint, (shape_t *)sh);
2993
2994 rdman_redraw_all(rdman);
2995
2996 CU_ASSERT(sh->draw_cnt == 1);
2997 CU_ASSERT(sh->last_draw == _coord_get_canvas(coord2));
2998
2999 parent_2_cache = ((mock_mbe_t *)_coord_get_canvas(coord2))->parent_2_cache;
3000 CU_ASSERT(parent_2_cache[0] == 1);
3001 CU_ASSERT(parent_2_cache[1] == 0);
3002 CU_ASSERT(parent_2_cache[2] == -100);
3003 CU_ASSERT(parent_2_cache[3] == 0);
3004 CU_ASSERT(parent_2_cache[4] == 1);
3005 CU_ASSERT(parent_2_cache[5] == -100);
3006
3007 coord2->matrix[2] = 20;
3008 coord2->matrix[5] = 30;
3009 rdman_coord_changed(rdman, coord2);
3010 rdman_redraw_changed(rdman);
3011
3012 /* To test if transform matrix of cached coord working */
3013 parent_2_cache = ((mock_mbe_t *)_coord_get_canvas(coord2))->parent_2_cache;
3014 CU_ASSERT(parent_2_cache[0] == 1);
3015 CU_ASSERT(parent_2_cache[1] == 0);
3016 CU_ASSERT(parent_2_cache[2] == -120);
3017 CU_ASSERT(parent_2_cache[3] == 0);
3018 CU_ASSERT(parent_2_cache[4] == 1);
3019 CU_ASSERT(parent_2_cache[5] == -130);
3020
3021 rdman_paint_free(rdman, paint);
3022 redraw_man_destroy(rdman);
3023 }
3024
2744 CU_pSuite get_redraw_man_suite(void) { 3025 CU_pSuite get_redraw_man_suite(void) {
2745 CU_pSuite suite; 3026 CU_pSuite suite;
2746 3027
2747 suite = CU_add_suite("Suite_redraw_man", NULL, NULL); 3028 suite = CU_add_suite("Suite_redraw_man", NULL, NULL);
2748 CU_ADD_TEST(suite, test_rdman_redraw_changed); 3029 CU_ADD_TEST(suite, test_rdman_redraw_changed);
2749 CU_ADD_TEST(suite, test_rdman_free_objs); 3030 CU_ADD_TEST(suite, test_rdman_free_objs);
3031 CU_ADD_TEST(suite, test_setup_canvas_info);
3032 CU_ADD_TEST(suite, test_own_canvas_area);
3033 CU_ADD_TEST(suite, test_own_canvas);
3034 CU_ADD_TEST(suite, test_own_canvas_redraw);
2750 3035
2751 return suite; 3036 return suite;
2752 } 3037 }
2753 3038
2754 #endif /* UNITTEST */ 3039 #endif /* UNITTEST */