changeset 23:56f592f56ff7

Fix bug and add linear gradient paint. - fix the bug that forget to clear n_dirty_geos in rdman_redraw_all().
author Thinker K.F. Li <thinker@branda.to>
date Sat, 02 Aug 2008 23:10:42 +0800
parents 8fcf2d878ecd
children e598bc809c0f
files src/X_main.c src/paint.c src/paint.h src/redraw_man.c
diffstat 4 files changed, 119 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/X_main.c	Sat Aug 02 16:20:15 2008 +0800
+++ b/src/X_main.c	Sat Aug 02 23:10:42 2008 +0800
@@ -14,10 +14,11 @@
 
 void draw_path(cairo_t *cr, int w, int h) {
     redraw_man_t rdman;
-    shape_t *path1, *path2;
+    shape_t *path1, *path2, *path3;
     coord_t *coord1, *coord2;
-    paint_t *fill1, *fill2;
+    paint_t *fill1, *fill2, *fill3;
     paint_t *stroke;
+    grad_stop_t fill3_stops[3];
     int i;
 
     redraw_man_init(&rdman, cr);
@@ -48,6 +49,16 @@
     rdman_add_shape(&rdman, (shape_t *)path1, coord1);
     rdman_add_shape(&rdman, (shape_t *)path2, coord2);
 
+    
+    fill3 = paint_linear_new(&rdman, 50, 50, 150, 150);
+    grad_stop_init(fill3_stops, 0, 1, 0, 0, 0.5);
+    grad_stop_init(fill3_stops + 1, 0.5, 0, 1, 0, 0.5);
+    grad_stop_init(fill3_stops + 2, 1, 0, 0, 1, 0.5);
+    paint_linear_stops(fill3, 3, fill3_stops);
+    path3 = sh_path_new("M 50,50 L 50,150 L 150,150 L 150,50 z");
+    rdman_paint_fill(&rdman, fill3, path3);
+    rdman_add_shape(&rdman, (shape_t *)path3, rdman.root_coord);
+
     rdman_redraw_all(&rdman);
 
     XFlush(display);
--- a/src/paint.c	Sat Aug 02 16:20:15 2008 +0800
+++ b/src/paint.c	Sat Aug 02 23:10:42 2008 +0800
@@ -3,6 +3,8 @@
 #include <cairo.h>
 #include "paint.h"
 
+/*! \brief Solid color paint.
+ */
 typedef struct _paint_color {
     paint_t paint;
     co_comp_t r, g, b, a;
@@ -50,3 +52,85 @@
     color->b = b;
     color->a = a;
 }
+
+/*! \brief Linear gradient.
+ */
+typedef struct _paint_linear {
+    paint_t paint;
+    co_aix x1, y1;
+    co_aix x2, y2;
+    int n_stops;
+    grad_stop_t *stops;
+    int flags;
+    cairo_pattern_t *ptn;
+} paint_linear_t;
+
+#define LIF_DIRTY 0x1
+
+static void paint_linear_prepare(paint_t *paint, cairo_t *cr) {
+    paint_linear_t *linear = (paint_linear_t *)paint;
+    cairo_pattern_t *ptn;
+    grad_stop_t *stop;
+    int i;
+
+    ptn = linear->ptn;
+    if(linear->flags & LIF_DIRTY) {
+	if(ptn)
+	    cairo_pattern_destroy(ptn);
+	linear->flags &= ~LIF_DIRTY;
+	ptn = cairo_pattern_create_linear(linear->x1, linear->y1,
+					  linear->x2, linear->y2);
+	for(i = 0; i < linear->n_stops; i++) {
+	    stop = &linear->stops[i];
+	    cairo_pattern_add_color_stop_rgba(ptn, stop->offset,
+					      stop->r, stop->g, stop->b,
+					      stop->a);
+	}
+	linear->ptn = ptn;
+    }
+
+    cairo_set_source(cr, ptn);
+}
+
+static void paint_linear_free(paint_t *paint) {
+    paint_linear_t *linear = (paint_linear_t *)paint;
+
+    if(linear->ptn)
+	cairo_pattern_destroy(linear->ptn);
+    free(paint);
+}
+
+paint_t *paint_linear_new(redraw_man_t *rdman,
+			  co_aix x1, co_aix y1, co_aix x2, co_aix y2) {
+    paint_linear_t *linear;
+
+    linear = (paint_linear_t *)malloc(sizeof(paint_linear_t));
+    if(linear == NULL)
+	return NULL;
+
+    paint_init(&linear->paint, paint_linear_prepare, paint_linear_free);
+
+    linear->x1 = x1;
+    linear->y1 = y1;
+    linear->x2 = x2;
+    linear->y2 = y2;
+    linear->n_stops = 0;
+    linear->stops = NULL;
+    linear->flags = LIF_DIRTY;
+    linear->ptn = NULL;
+
+    return (paint_t *)linear;
+}
+
+grad_stop_t *paint_linear_stops(paint_t *paint,
+				int n_stops,
+				grad_stop_t *stops) {
+    paint_linear_t *linear = (paint_linear_t *)paint;
+    grad_stop_t *old_stops;
+    
+    old_stops = linear->stops;
+    linear->n_stops = n_stops;
+    linear->stops = stops;
+    return old_stops;
+}
+
--- a/src/paint.h	Sat Aug 02 16:20:15 2008 +0800
+++ b/src/paint.h	Sat Aug 02 23:10:42 2008 +0800
@@ -21,4 +21,25 @@
 	 STAILQ_INIT((_paint)->members);	\
      } while(0)					\
 
+
+typedef struct _grad_stop {
+    co_aix offset;
+    co_comp_t r, g, b, a;
+} grad_stop_t;
+
+extern paint_t *paint_linear_new(redraw_man_t *rdman,
+				 co_aix x1, co_aix y1, co_aix x2, co_aix y2);
+extern grad_stop_t *paint_linear_stops(paint_t *paint,
+				       int n_stops,
+				       grad_stop_t *stops);
+#define grad_stop_init(stop, _offset, _r, _g, _b, _a)	\
+    do {						\
+	(stop)->offset = _offset;			\
+	(stop)->r = _r;					\
+	(stop)->g = _g;					\
+	(stop)->b = _b;					\
+	(stop)->a = _a;					\
+    } while(0)
+
+
 #endif /* __PAINT_H_ */
--- a/src/redraw_man.c	Sat Aug 02 16:20:15 2008 +0800
+++ b/src/redraw_man.c	Sat Aug 02 23:10:42 2008 +0800
@@ -639,6 +639,7 @@
 	    clean_shape(geo->shape);
 	draw_shape(rdman, geo->shape);
     }
+    rdman->n_dirty_geos = 0;
 
     return OK;
 }