changeset 55:01ed2bc37eed

Radial gradient paint
author Thinker K.F. Li <thinker@branda.to>
date Sun, 10 Aug 2008 16:44:21 +0800
parents 1b6dbafdf906
children e444a8c01735
files src/X_main.c src/paint.c src/paint.h src/tools.h
diffstat 4 files changed, 103 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/X_main.c	Sun Aug 10 00:29:11 2008 +0800
+++ b/src/X_main.c	Sun Aug 10 16:44:21 2008 +0800
@@ -127,6 +127,8 @@
     shape_t *path1, *path2, *rect;
     coord_t *coord1, *coord2, *coord3;
     paint_t *fill1, *fill2, *fill3;
+    paint_t *text_fill;
+    grad_stop_t text_stops[2];
     paint_t *stroke, *text_stroke;
     shape_t *text;
     grad_stop_t fill3_stops[3];
@@ -155,9 +157,12 @@
     face = cairo_get_font_face(tmpcr);
     text = sh_text_new("hello \xe6\xbc\xa2\xe5\xad\x97", 10, h / 4,
 		       36.0, face);
+    grad_stop_init(text_stops, 0, 0.2, 0.9, 0.2, 1);
+    grad_stop_init(text_stops + 1, 1, 0.9, 0.2, 0.2, 0.1);
+    text_fill = paint_radial_new(&rdman, 100, h / 4, 70, 2, text_stops);
     rdman_paint_stroke(&rdman, text_stroke, text);
     text->stroke_width = 0.5;
-    rdman_paint_fill(&rdman, fill1, text);
+    rdman_paint_fill(&rdman, text_fill, text);
     rdman_add_shape(&rdman, text, coord3);
 
     path1 = 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 ");
@@ -237,6 +242,7 @@
     fill2->free(fill2);
     stroke->free(stroke);
     text_stroke->free(text_stroke);
+    text_fill->free(text_fill);
     redraw_man_destroy(&rdman);
     sh_path_free(path1);
     sh_path_free(path2);
--- a/src/paint.c	Sun Aug 10 00:29:11 2008 +0800
+++ b/src/paint.c	Sun Aug 10 16:44:21 2008 +0800
@@ -3,6 +3,8 @@
 #include <cairo.h>
 #include "paint.h"
 
+#define ASSERT(x)
+
 /*! \brief Solid color paint.
  */
 typedef struct _paint_color {
@@ -142,6 +144,90 @@
     old_stops = linear->stops;
     linear->n_stops = n_stops;
     linear->stops = stops;
+    linear->flags |= LIF_DIRTY;
+
     return old_stops;
 }
 
+/*! \brief Radial gradient.
+ *
+ * NOTE: The only supported gradient unit is userSpaceOnUse.
+ */
+typedef struct _paint_radial {
+    paint_t paint;
+    co_aix cx, cy;
+    co_aix r;
+    int n_stops;
+    grad_stop_t *stops;
+    int flags;
+    cairo_pattern_t *ptn;
+} paint_radial_t;
+
+#define RDF_DIRTY 0x1
+
+static void paint_radial_prepare(paint_t *paint, cairo_t *cr) {
+    paint_radial_t *radial = (paint_radial_t *)paint;
+    cairo_pattern_t *ptn;
+    grad_stop_t *stop;
+    int i;
+
+    if(radial->flags & RDF_DIRTY) {
+	ptn = cairo_pattern_create_radial(radial->cx, radial->cy, 0,
+					  radial->cx, radial->cy,
+					  radial->r);
+	ASSERT(ptn != NULL);
+	stop = radial->stops;
+	for(i = 0; i < radial->n_stops; i++, stop++) {
+	    cairo_pattern_add_color_stop_rgba(ptn, stop->offset,
+					      stop->r, stop->g,
+					      stop->b, stop->a);
+	}
+	cairo_pattern_destroy(radial->ptn);
+	radial->ptn = ptn;
+    }
+    cairo_set_source(cr, radial->ptn);
+}
+
+static void paint_radial_free(paint_t *paint) {
+    paint_radial_t *radial = (paint_radial_t *)paint;
+
+    if(radial->ptn)
+	cairo_pattern_destroy(radial->ptn);
+    free(paint);
+}
+
+paint_t *paint_radial_new(redraw_man_t *rdman,
+			  co_aix cx, co_aix cy, co_aix r,
+			  int n_stops, grad_stop_t *stops) {
+    paint_radial_t *radial;
+
+    radial = O_ALLOC(paint_radial_t);
+    if(radial == NULL)
+	return NULL;
+
+    paint_init(&radial->paint, paint_radial_prepare, paint_radial_free);
+    radial->cx = cx;
+    radial->cy = cy;
+    radial->r = r;
+    radial->n_stops = n_stops;
+    radial->stops = stops;
+    radial->flags = RDF_DIRTY;
+    radial->ptn = NULL;
+
+    return (paint_t *)radial;
+}
+
+grad_stop_t *paint_radial_stops(paint_t *paint,
+				int n_stops,
+				grad_stop_t *stops) {
+    paint_radial_t *radial = (paint_radial_t *)paint;
+    grad_stop_t *old_stops;
+    
+    old_stops = radial->stops;
+    radial->n_stops = n_stops;
+    radial->stops = stops;
+    radial->flags |= RDF_DIRTY;
+
+    return old_stops;
+}
+
--- a/src/paint.h	Sun Aug 10 00:29:11 2008 +0800
+++ b/src/paint.h	Sun Aug 10 16:44:21 2008 +0800
@@ -35,6 +35,13 @@
 extern grad_stop_t *paint_linear_stops(paint_t *paint,
 				       int n_stops,
 				       grad_stop_t *stops);
+extern paint_t *paint_radial_new(redraw_man_t *rdman,
+				 co_aix cx, co_aix cy, co_aix r,
+				 int n_stops, grad_stop_t *stops);
+extern grad_stop_t *paint_radial_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;			\
--- a/src/tools.h	Sun Aug 10 00:29:11 2008 +0800
+++ b/src/tools.h	Sun Aug 10 16:44:21 2008 +0800
@@ -63,4 +63,7 @@
 	}						\
     } while(0)
 
+
+#define O_ALLOC(type) ((type *)malloc(sizeof(type)))
+
 #endif /* __TOOLS_H_ */