changeset 15:c2ce186a5c37

X_main uses rdman_redraw_all()
author Thinker K.F. Li <thinker@branda.to>
date Fri, 01 Aug 2008 01:40:07 +0800
parents d34232f15863
children e17e12b112c4
files src/Makefile src/X_main.c src/coord.c src/geo.c src/mb_types.h src/redraw_man.c src/redraw_man.h src/shape_path.c
diffstat 8 files changed, 157 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/Makefile	Fri Aug 01 01:40:07 2008 +0800
@@ -1,7 +1,7 @@
 SRCS =	coord.c geo.c shape_path.c redraw_man.c tools.c
 OBJS = ${SRCS:C/(.*)\.c/\1.o/g}
 TESTCASE_OBJS = ${SRCS:C/(.*)\.c/testcase-\1.o/g}
-CFLAGS =	-Wall -I/usr/local/include `pkg-config --cflags cairo`
+CFLAGS+=	-Wall -I/usr/local/include `pkg-config --cflags cairo`
 LDFLAGS =	`pkg-config --libs cairo`
 BINS =	testcase X_main
 
--- a/src/X_main.c	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/X_main.c	Fri Aug 01 01:40:07 2008 +0800
@@ -14,7 +14,7 @@
     shape_t *path;
     coord_t *coord;
 
-    redraw_man_init(&rdman);
+    redraw_man_init(&rdman, cr);
     coord = rdman.root_coord;
 
     path = sh_path_new("M 22,89.36218 C -34,-0.63782 39,-9.637817 82,12.36218 C 125,34.36218 142,136.36218 142,136.36218 C 100.66667,125.36218 74.26756,123.42795 22,89.36218 z ");
@@ -23,9 +23,12 @@
     coord->aggr_matrix[2] = 20;
     coord->aggr_matrix[4] = 0.8;
     coord->aggr_matrix[5] = 20;
+    rdman_coord_changed(&rdman, coord);
     rdman_add_shape(&rdman, (shape_t *)path, coord);
-    sh_path_transform(path);
-    sh_path_draw(path, cr);
+
+    rdman_redraw_all(&rdman);
+
+    redraw_man_destroy(&rdman);
     sh_path_free(path);
 }
 
--- a/src/coord.c	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/coord.c	Fri Aug 01 01:40:07 2008 +0800
@@ -87,6 +87,8 @@
     }
     co->matrix[0] = 1;
     co->matrix[4] = 1;
+    co->cur_area = &co->areas[0];
+    co->last_area = &co->areas[1];
 }
 
 void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y) {
--- a/src/geo.c	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/geo.c	Fri Aug 01 01:40:07 2008 +0800
@@ -31,12 +31,12 @@
     return _is_overlay(r1, r2);
 }
 
-void geo_init(geo_t *g, int n_pos, co_aix pos[][2]) {
+void area_init(area_t *area, int n_pos, co_aix pos[][2]) {
     co_aix min_x, max_x;
     co_aix min_y, max_y;
     co_aix x, y;
     int i;
-
+    
     min_x = max_x = pos[0][0];
     min_y = max_y = pos[0][1];
     for(i = 1; i < n_pos; i++) {
@@ -52,13 +52,16 @@
 	    max_y = y;
     }
 
+    area->x = min_x;
+    area->w = max_x - min_x;
+    area->y = min_y;
+    area->h = max_y - min_y;
+}
+
+void geo_init(geo_t *g, int n_pos, co_aix pos[][2]) {
     g->cur_area = g->areas;
     g->last_area = g->areas + 1;
-
-    g->cur_area->x = min_x;
-    g->cur_area->w = max_x - min_x;
-    g->cur_area->y = min_y;
-    g->cur_area->h = max_y - min_y;
+    area_init(g->cur_area, n_pos, pos);
 }
 
 void geo_mark_overlay(geo_t *g, int n_others, geo_t **others,
--- a/src/mb_types.h	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/mb_types.h	Fri Aug 01 01:40:07 2008 +0800
@@ -27,6 +27,7 @@
 #define GEF_DIRTY 0x1
 
 extern int is_overlay(area_t *r1, area_t *r2);
+extern void area_init(area_t *area, int n_pos, co_aix pos[][2]);
 extern void geo_init(geo_t *g, int n_pos, co_aix pos[][2]);
 extern void geo_mark_overlay(geo_t *g, int n_others, geo_t **others,
 			     int *n_overlays, geo_t **overlays);
@@ -55,6 +56,7 @@
     unsigned int order;
     unsigned int flags;
     area_t *cur_area, *last_area;
+    area_t areas[2];
 
     co_aix matrix[6];
     co_aix aggr_matrix[6];
--- a/src/redraw_man.c	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/redraw_man.c	Fri Aug 01 01:40:07 2008 +0800
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <cairo.h>
 #include "mb_types.h"
 #include "shapes.h"
 #include "tools.h"
@@ -12,7 +13,7 @@
 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL)
 #define SWAP(a, b, t) do { t c;  c = a; a = b; b = c; } while(0)
 
-int redraw_man_init(redraw_man_t *rdman) {
+int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) {
     extern void redraw_man_destroy(redraw_man_t *rdman);
 
     memset(rdman, 0, sizeof(redraw_man_t));
@@ -33,6 +34,8 @@
     rdman->n_coords = 1;
     coord_init(rdman->root_coord, NULL);
 
+    rdman->cr = cr;
+
     return OK;
 }
 
@@ -132,6 +135,7 @@
 	    visit->order = ++next_order;
 	rdman->next_geo_order = next_order;
     }
+    geo->flags |= GEF_DIRTY;
 
     sh_attach_coord(shape, coord);
 
@@ -237,6 +241,7 @@
     int r;
 
     if(rdman->n_dirty_areas >= rdman->max_dirty_areas) {
+	/* every geo object and coord object can contribute 2 areas. */
 	max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2;
 	r = extend_memblk((void **)&rdman->dirty_areas,
 			  sizeof(area_t *) * rdman->n_dirty_areas,
@@ -320,28 +325,106 @@
     }
 }
 
-static void make_redrawing_members(redraw_man_t *rdman, coord_t *coord) {
-    shape_t *shape;
-
-    for(shape = STAILQ_HEAD(coord->members);
-	shape != NULL;
-	shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) {
-	shape->geo->flags &= ~GEF_DIRTY;
-	add_dirty_geo(rdman, shape->geo);
+static void update_shape_geo(shape_t *shape) {
+    switch(shape->sh_type) {
+    case SHT_PATH:
+	sh_path_transform(shape);
+	break;
     }
 }
 
-static void compute_coord_area(coord_t *coord) {
+static void area_to_positions(area_t *area, co_aix (*poses)[2]) {
+    poses[0][0] = area->x;
+    poses[0][1] = area->y;
+    poses[1][0] = area->x + area->w;
+    poses[1][1] = area->y + area->h;;
 }
 
-static void update_shape_geo(shape_t *shape) {
+static int compute_coord_area(coord_t *coord) {
+    shape_t *shape;
+    geo_t *geo;
+    co_aix (*poses)[2];
+    int cnt, pos_cnt;
+    int i;
+
+    cnt = 0;
+    for(shape = STAILQ_HEAD(coord->members);
+	shape != NULL;
+	shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) {
+	SWAP(shape->geo->cur_area, shape->geo->last_area, area_t *);
+	update_shape_geo(shape);
+	cnt++;
+    }
+
+    poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt);
+    if(poses == NULL)
+	return ERR;
+
+    pos_cnt = 0;
+    for(shape = STAILQ_HEAD(coord->members);
+	shape != NULL;
+	shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) {
+	geo = shape->geo;
+	
+	area_to_positions(&geo->areas[0], poses + pos_cnt);
+	pos_cnt += 2;
+	area_to_positions(&geo->areas[1], poses + pos_cnt);
+	pos_cnt += 2;
+    }
+
+    for(i = 0; i < pos_cnt; i++)
+	coord_trans_pos(coord, &poses[i][0], &poses[i][1]);
+
+    area_init(coord->cur_area, cnt, poses);
+    free(poses);
+
+    return OK;
 }
 
 static void draw_shape(redraw_man_t *rdman, shape_t *shape) {
+    switch(shape->sh_type) {
+    case SHT_PATH:
+	sh_path_draw(shape, rdman->cr);
+	break;
+    }
 }
 
-static void clip_and_show(redraw_man_t *rdman, int n_dirty_areas,
-			  area_t **dirty_areas) {
+static void make_clip(redraw_man_t *rdman, int n_dirty_areas,
+		      area_t **dirty_areas) {
+    int i;
+    area_t *area;
+    cairo_t *cr;
+
+    cr = rdman->cr;
+
+    cairo_reset_clip(cr);
+    for(i = 0; i < n_dirty_areas; i++) {
+	area = dirty_areas[i];
+	cairo_rectangle(cr, area->x, area->y, area->w, area->h);
+    }
+    cairo_clip(cr);
+}
+
+static void draw_shapes_in_areas(redraw_man_t *rdman,
+				 int n_areas,
+				 area_t **areas) {
+    geo_t *visit_geo;
+    int i;
+
+    for(visit_geo = STAILQ_HEAD(rdman->all_geos);
+	visit_geo != NULL;
+	visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) {
+	if(visit_geo->flags & GEF_DIRTY) {
+	    visit_geo->flags &= ~GEF_DIRTY;
+	    update_shape_geo(visit_geo->shape);
+	}
+	for(i = 0; i < n_areas; i++) {
+	    if(is_overlay(visit_geo->cur_area, areas[i])) {
+		draw_shape(rdman, visit_geo->shape);
+		break;
+	    }
+	}
+    }
 }
 
 /*! \brief Re-draw all changed shapes or shapes affected by changed coords.
@@ -371,14 +454,13 @@
  * - Scan all shapes and redraw shapes overlaid with dirty areas.
  *
  * dirty flag of coord objects is cleared after update.
+ * dirty flag of geo objects is also cleared after recomputing.
+ * Clean dirty flag can prevent redundant computing for geo and
+ * corod objects.
  *
- * assert(n_dirty_geos <= (num_of(shape) + num_of(coord)))
- * Because
- * - num_of(geo from coord) < num_of(coord)
- * - num_of(geo from shape) < num_of(shape)
  */
 int rdman_redraw_changed(redraw_man_t *rdman) {
-    int i;
+    int i, r;
     int n_dirty_coords;
     coord_t **dirty_coords;
     coord_t *visit_coord;
@@ -407,10 +489,11 @@
 		visit_coord->flags &= ~COF_DIRTY;
 
 		SWAP(visit_coord->cur_area, visit_coord->last_area, area_t *);
-		compute_coord_area(visit_coord);
+		r = compute_coord_area(visit_coord);
+		if(r == ERR)
+		    return ERR;
 		add_dirty_area(rdman, visit_coord->cur_area);
 		add_dirty_area(rdman, visit_coord->last_area);
-		make_redrawing_members(rdman, visit_coord);
 	    }
 	}
 	rdman->n_dirty_coords = 0;
@@ -430,21 +513,32 @@
 	    add_dirty_area(rdman, visit_geo->cur_area);
 	    add_dirty_area(rdman, visit_geo->last_area);
 	}
+	rdman->n_dirty_geos = 0;
+    }
 	
-	n_dirty_areas = rdman->n_dirty_areas;
-	dirty_areas = rdman->dirty_areas;
-	for(visit_geo = STAILQ_HEAD(rdman->all_geos);
-	    visit_geo != NULL;
-	    visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) {
-	    for(i = 0; i < n_dirty_areas; i++) {
-		if(is_overlay(visit_geo->cur_area,
-			      dirty_areas[i])) {
-		    draw_shape(rdman, visit_geo->shape);
-		    break;
-		}
-	    }
+    n_dirty_areas = rdman->n_dirty_areas;
+    dirty_areas = rdman->dirty_areas;
+    if(n_dirty_areas > 0) {
+	make_clip(rdman, n_dirty_areas, dirty_areas);
+	draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas);
+	rdman->n_dirty_areas = 0;
+    }
+
+    return OK;
+}
+
+int rdman_redraw_all(redraw_man_t *rdman) {
+    geo_t *geo;
+
+    /* TODO: update dirty coord and it's members. */
+    for(geo = STAILQ_HEAD(rdman->all_geos);
+	geo != NULL;
+	geo = STAILQ_NEXT(geo_t, next, geo)) {
+	if(geo->flags & GEF_DIRTY) {
+	    geo->flags &= ~GEF_DIRTY;
+	    update_shape_geo(geo->shape);
 	}
-	clip_and_show(rdman, n_dirty_areas, dirty_areas);
+	draw_shape(rdman, geo->shape);
     }
 
     return OK;
@@ -541,7 +635,7 @@
     int n;
     int i;
 
-    redraw_man_init(&rdman);
+    redraw_man_init(&rdman, NULL);
     coords[0] = rdman.root_coord;
     for(i = 1; i < 3; i++) {
 	coords[i] = rdman_coord_new(&rdman, rdman.root_coord);
--- a/src/redraw_man.h	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/redraw_man.h	Fri Aug 01 01:40:07 2008 +0800
@@ -1,6 +1,7 @@
 #ifndef __REDRAW_MAN_H_
 #define __REDRAW_MAN_H_
 
+#include <cairo.h>
 #include "tools.h"
 #include "mb_types.h"
 
@@ -42,9 +43,11 @@
     int max_dirty_areas;
     int n_dirty_areas;
     area_t **dirty_areas;
+
+    cairo_t *cr;
 } redraw_man_t;
 
-extern int redraw_man_init(redraw_man_t *rdman);
+extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr);
 extern void redraw_man_destroy(redraw_man_t *rdman);
 extern int rdman_find_overlaid_shapes(redraw_man_t *rdman,
 				      geo_t *geo,
@@ -54,6 +57,9 @@
 extern int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape);
 extern coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent);
 extern int rdman_coord_free(redraw_man_t *rdman, coord_t *coord);
+extern int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord);
+extern int rdman_redraw_changed(redraw_man_t *rdman);
+extern int rdman_redraw_all(redraw_man_t *rdman);
 
 
 #endif /* __REDRAW_MAN_H_ */
--- a/src/shape_path.c	Thu Jul 31 17:43:20 2008 +0800
+++ b/src/shape_path.c	Fri Aug 01 01:40:07 2008 +0800
@@ -431,7 +431,7 @@
     cmd_len = path->cmd_len;
     cmds = path->dev_data;
     args = (co_aix *)(cmds + cmd_len);
-    x = y = 0;
+    x = y = x1 = y1 = x2 = y2 = 0;
     for(i = 0; i < cmd_len; i++) {
 	cmd = *cmds++;
 	switch(cmd) {