changeset 24:e598bc809c0f

No more flash when animation. 1. Add a buffer surface. 2. Draw on the surface 3. Copy content of buffer surface to XLib surface.
author Thinker K.F. Li <thinker@branda.to>
date Sun, 03 Aug 2008 02:08:31 +0800
parents 56f592f56ff7
children 29937c26bb01
files src/X_main.c src/redraw_man.c src/redraw_man.h
diffstat 3 files changed, 39 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/X_main.c	Sat Aug 02 23:10:42 2008 +0800
+++ b/src/X_main.c	Sun Aug 03 02:08:31 2008 +0800
@@ -13,6 +13,8 @@
 Display *display;
 
 void draw_path(cairo_t *cr, int w, int h) {
+    cairo_t *tmpcr;
+    cairo_surface_t *tmpsuf;
     redraw_man_t rdman;
     shape_t *path1, *path2, *path3;
     coord_t *coord1, *coord2;
@@ -21,7 +23,10 @@
     grad_stop_t fill3_stops[3];
     int i;
 
-    redraw_man_init(&rdman, cr);
+    tmpsuf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+    tmpcr = cairo_create(tmpsuf);
+    cairo_set_source_surface(cr, tmpsuf, 0, 0);
+    redraw_man_init(&rdman, tmpcr, cr);
     coord1 = rdman_coord_new(&rdman, rdman.root_coord);
     coord2 = rdman_coord_new(&rdman, rdman.root_coord);
 
@@ -94,6 +99,8 @@
     redraw_man_destroy(&rdman);
     sh_path_free(path1);
     sh_path_free(path2);
+    cairo_destroy(tmpcr);
+    cairo_surface_destroy(tmpsuf);
 }
 
 void drawing(cairo_surface_t *surface, int w, int h) {
--- a/src/redraw_man.c	Sat Aug 02 23:10:42 2008 +0800
+++ b/src/redraw_man.c	Sun Aug 03 02:08:31 2008 +0800
@@ -181,7 +181,7 @@
     return OK;
 }
 
-int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) {
+int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend) {
     extern void redraw_man_destroy(redraw_man_t *rdman);
 
     memset(rdman, 0, sizeof(redraw_man_t));
@@ -210,6 +210,7 @@
     coord_init(rdman->root_coord, NULL);
 
     rdman->cr = cr;
+    rdman->backend = backend;
 
     return OK;
 }
@@ -501,37 +502,49 @@
     cairo_pattern_reference(pt);
     /* TODO: clean to background color. */
     cairo_set_source_rgb(cr, 0, 0, 0);
-    cairo_fill_preserve(cr);
+    cairo_paint(cr);
     cairo_set_source(cr, pt);
     cairo_pattern_destroy(pt);
 }
 
-static void make_clip(redraw_man_t *rdman, int n_dirty_areas,
+static void make_clip(cairo_t *cr, int n_dirty_areas,
 		      area_t **dirty_areas) {
     int i;
     area_t *area;
-    cairo_t *cr;
-
-    cr = rdman->cr;
 
     for(i = 0; i < n_dirty_areas; i++) {
 	area = dirty_areas[i];
 	cairo_rectangle(cr, area->x, area->y, area->w, area->h);
     }
-    clean_clip(cr);
     cairo_clip(cr);
 }
 
 static void reset_clip(redraw_man_t *rdman) {
     cairo_reset_clip(rdman->cr);
+    cairo_reset_clip(rdman->backend);
+}
+
+static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas,
+			      area_t **dirty_areas) {
+    if(n_dirty_areas)
+	make_clip(rdman->backend, n_dirty_areas, dirty_areas);
+    
+    cairo_paint(rdman->backend);
 }
 #else /* UNITTEST */
-static void make_clip(redraw_man_t *rdman, int n_dirty_areas,
+static void clean_clip(cairo_t *cr) {
+}
+
+static void make_clip(cairo_t *cr, int n_dirty_areas,
                       area_t **dirty_areas) {
 }
 
 static void reset_clip(redraw_man_t *rdman) {
 }
+
+static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas,
+			      area_t **dirty_areas) {
+}
 #endif /* UNITTEST */
 
 static void draw_shapes_in_areas(redraw_man_t *rdman,
@@ -554,6 +567,7 @@
     }
 }
 
+
 /*! \brief Re-draw all changed shapes or shapes affected by changed coords.
  *
  * A coord object has a geo to keep track the range that it's members will
@@ -616,8 +630,10 @@
     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);
+	make_clip(rdman->cr, n_dirty_areas, dirty_areas);
+	clean_clip(rdman->cr);
 	draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas);
+	copy_cr_2_backend(rdman, rdman->n_dirty_areas, rdman->dirty_areas);
 	rdman->n_dirty_areas = 0;
 	reset_clip(rdman);
     }
@@ -639,6 +655,7 @@
 	    clean_shape(geo->shape);
 	draw_shape(rdman, geo->shape);
     }
+    copy_cr_2_backend(rdman, 0, NULL);
     rdman->n_dirty_geos = 0;
 
     return OK;
@@ -826,7 +843,7 @@
     int n;
     int i;
 
-    redraw_man_init(&rdman, NULL);
+    redraw_man_init(&rdman, NULL, NULL);
     coords[0] = rdman.root_coord;
     for(i = 1; i < 3; i++) {
 	coords[i] = rdman_coord_new(&rdman, rdman.root_coord);
@@ -879,7 +896,7 @@
     dummys = (sh_dummy_t **)shapes;
 
     rdman = &_rdman;
-    redraw_man_init(rdman, NULL);
+    redraw_man_init(rdman, NULL, NULL);
     paint = dummy_paint_new(rdman);
     for(i = 0; i < 3; i++) {
 	shapes[i] = sh_dummy_new(0, 0, 50, 50);
--- a/src/redraw_man.h	Sat Aug 02 23:10:42 2008 +0800
+++ b/src/redraw_man.h	Sun Aug 03 02:08:31 2008 +0800
@@ -48,9 +48,11 @@
     area_t **dirty_areas;
 
     cairo_t *cr;
+    cairo_t *backend;
 } redraw_man_t;
 
-extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr);
+extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr,
+			   cairo_t *backend);
 extern void redraw_man_destroy(redraw_man_t *rdman);
 extern int rdman_find_overlaid_shapes(redraw_man_t *rdman,
 				      geo_t *geo,