changeset 18:0f3baa488a62

Support solid color paint for fill.
author Thinker K.F. Li <thinker@branda.to>
date Sat, 02 Aug 2008 14:45:42 +0800
parents 41f0907b27ac
children cf6d65398619
files src/Makefile src/X_main.c src/geo.c src/mb_types.h src/paint.c src/paint.h src/redraw_man.c src/redraw_man.h
diffstat 8 files changed, 179 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile	Fri Aug 01 23:32:22 2008 +0800
+++ b/src/Makefile	Sat Aug 02 14:45:42 2008 +0800
@@ -1,4 +1,4 @@
-SRCS =	coord.c geo.c shape_path.c redraw_man.c tools.c
+SRCS =	coord.c geo.c shape_path.c redraw_man.c paint.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`
@@ -29,3 +29,6 @@
 		echo "delete $$i"; \
 		rm -f $$i; \
 	done
+
+depend:
+	mkdep $(CFLAGS) $(SRCS)
--- a/src/X_main.c	Fri Aug 01 23:32:22 2008 +0800
+++ b/src/X_main.c	Sat Aug 02 14:45:42 2008 +0800
@@ -8,6 +8,7 @@
 #include <string.h>
 #include "shapes.h"
 #include "redraw_man.h"
+#include "paint.h"
 
 Display *display;
 
@@ -15,12 +16,15 @@
     redraw_man_t rdman;
     shape_t *path;
     coord_t *coord;
+    paint_t *fill;
     int i;
 
     redraw_man_init(&rdman, cr);
     coord = rdman.root_coord;
 
+    fill = paint_color_new(&rdman, 1, 1, 0);
     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 ");
+    rdman_paint_fill(&rdman, fill, path);
     coord->matrix[0] = 0.8;
     coord->matrix[1] = 0;
     coord->matrix[2] = 20;
@@ -33,15 +37,25 @@
 
     XFlush(display);
 
-    for(i = 0; i < 10; i++) {
-	usleep(50000);
-	coord->matrix[2] += 5;
-	coord->matrix[5] += 5;
+    for(i = 0; i < 50; i++) {
+	usleep(20000);
+	coord->matrix[2] += 1;
+	coord->matrix[5] += 1;
+	paint_color_set(fill, 1, 1, (i/25) & 0x1);
 	rdman_coord_changed(&rdman, coord);
 	rdman_redraw_changed(&rdman);
 	XFlush(display);
     }
 
+    for(i = 0; i < 5; i++) {
+	usleep(500000);
+	paint_color_set(fill, 1, i % 2, 0);
+	rdman_paint_changed(&rdman, fill);
+	rdman_redraw_changed(&rdman);
+	XFlush(display);
+    }
+
+    fill->free(fill);
     redraw_man_destroy(&rdman);
     sh_path_free(path);
 }
--- a/src/geo.c	Fri Aug 01 23:32:22 2008 +0800
+++ b/src/geo.c	Sat Aug 02 14:45:42 2008 +0800
@@ -5,6 +5,7 @@
  * figures out components that should be re-drawed.
  */
 #include <stdio.h>
+#include <string.h>
 #include "mb_types.h"
 
 static int is_scale_overlay(co_aix x1, co_aix w1, co_aix x2, co_aix w2) {
--- a/src/mb_types.h	Fri Aug 01 23:32:22 2008 +0800
+++ b/src/mb_types.h	Sat Aug 02 14:45:42 2008 +0800
@@ -1,12 +1,26 @@
 #ifndef __MB_TYPES_H_
 #define __MB_TYPES_H_
 
+#include <cairo.h>
 #include "tools.h"
 
 typedef float co_aix;
 typedef struct _shape shape_t;
 typedef struct _geo geo_t;
 typedef struct _area area_t;
+typedef struct _shnode shnode_t;
+typedef struct _paint paint_t;
+
+struct _paint {
+    void (*prepare)(paint_t *paint, cairo_t *cr);
+    void (*free)(paint_t *paint);
+    STAILQ(shnode_t) members;
+};
+
+struct _shnode {
+    shape_t *shape;
+    shnode_t *next;
+};
 
 struct _area {
     co_aix x, y;
@@ -96,6 +110,7 @@
     geo_t *geo;
     coord_t *coord;
     shape_t *coord_mem_next;
+    paint_t *fill, *stroke;
 };
 enum { SHT_UNKNOW, SHT_PATH, SHT_TEXT };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/paint.c	Sat Aug 02 14:45:42 2008 +0800
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <cairo.h>
+#include "paint.h"
+
+typedef struct _paint_color {
+    paint_t paint;
+    co_comp_t r, g, b;
+    redraw_man_t *rdman;
+} paint_color_t;
+
+
+static void paint_color_prepare(paint_t *paint, cairo_t *cr) {
+    paint_color_t *color = (paint_color_t *)paint;
+
+    cairo_set_source_rgb(cr, color->r, color->g, color->b);
+}
+
+static void paint_color_free(paint_t *paint) {
+    paint_color_t *color = (paint_color_t *)paint;
+
+    shnode_list_free(color->rdman, paint->members);
+    free(paint);
+}
+
+paint_t *paint_color_new(redraw_man_t *rdman,
+			 co_comp_t r, co_comp_t g, co_comp_t b) {
+    paint_color_t *color;
+
+    color = (paint_color_t *)malloc(sizeof(paint_color_t));
+    if(color == NULL)
+	return NULL;
+    color->rdman = rdman;
+    color->r = r;
+    color->g = g;
+    color->b = b;
+    color->paint.prepare = paint_color_prepare;
+    color->paint.free = paint_color_free;
+    STAILQ_INIT(color->paint.members);
+    return (paint_t *)color;
+}
+
+void paint_color_set(paint_t *paint,
+		     co_comp_t r, co_comp_t g, co_comp_t b) {
+    paint_color_t *color = (paint_color_t *)paint;
+
+    color->r = r;
+    color->g = g;
+    color->b = b;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/paint.h	Sat Aug 02 14:45:42 2008 +0800
@@ -0,0 +1,15 @@
+#ifndef __PAINT_H_
+#define __PAINT_H_
+
+#include <cairo.h>
+#include "mb_types.h"
+#include "redraw_man.h"
+
+typedef float co_comp_t;
+
+extern paint_t *paint_color_new(redraw_man_t *rdman,
+				co_comp_t r, co_comp_t g, co_comp_t b);
+extern void paint_color_set(paint_t *paint,
+			    co_comp_t r, co_comp_t g, co_comp_t b);
+
+#endif /* __PAINT_H_ */
--- a/src/redraw_man.c	Fri Aug 01 23:32:22 2008 +0800
+++ b/src/redraw_man.c	Sat Aug 02 14:45:42 2008 +0800
@@ -196,6 +196,13 @@
 	return ERR;
     }
 
+    rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16);
+    if(rdman->shnode_pool == NULL) {
+	elmpool_free(rdman->geo_pool);
+	elmpool_free(rdman->coord_pool);
+	return ERR;
+    }
+
     rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool);
     if(rdman->root_coord == NULL)
 	redraw_man_destroy(rdman);
@@ -210,6 +217,7 @@
 void redraw_man_destroy(redraw_man_t *rdman) {
     elmpool_free(rdman->coord_pool);
     elmpool_free(rdman->geo_pool);
+    elmpool_free(rdman->shnode_pool);
     if(rdman->dirty_coords)
 	free(rdman->dirty_coords);
     if(rdman->dirty_geos)
@@ -422,12 +430,7 @@
     return OK;
 }
 
-/*! \brief Mark a shape is changed.
- *
- * The geo_t object of a changed shape is mark as dirty and
- * put into dirty_geos list.
- */
-int rdman_shape_changed(redraw_man_t *rdman, shape_t *shape) {
+static int _rdman_shape_changed(redraw_man_t *rdman, shape_t *shape) {
     geo_t *geo;
     int r;
 
@@ -444,11 +447,25 @@
     return OK;
 }
 
+/*! \brief Mark a shape is changed.
+ *
+ * The geo_t object of a changed shape is mark as dirty and
+ * put into dirty_geos list.
+ */
+int rdman_shape_changed(redraw_man_t *rdman, shape_t *shape) {
+    return _rdman_shape_changed(rdman, shape);
+}
+
 /* Drawing and Redrawing
  * ============================================================
  */
 
 static void draw_shape(redraw_man_t *rdman, shape_t *shape) {
+    paint_t *fill;
+
+    fill = shape->fill;
+    if(fill)
+	fill->prepare(fill, rdman->cr);
     switch(shape->sh_type) {
     case SHT_PATH:
 	sh_path_draw(shape, rdman->cr);
@@ -611,6 +628,31 @@
     return OK;
 }
 
+shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) {
+    shnode_t *node;
+
+    node = (shnode_t *)elmpool_elm_alloc(rdman->shnode_pool);
+    if(node) {
+	node->shape = shape;
+	node->next = NULL;
+    }
+    return node;
+}
+
+int rdman_paint_changed(redraw_man_t *rdman, paint_t *paint) {
+    shnode_t *node;
+    int r;
+
+    for(node = STAILQ_HEAD(paint->members);
+	node != NULL;
+	node = STAILQ_NEXT(shnode_t, next, node)) {
+	r = _rdman_shape_changed(rdman, node->shape);
+	if(r != OK)
+	    return ERR;
+    }
+    return OK;
+}
+
 /*
  * Dirty of geo
  * A geo is dirty when any of the shape, size or positions is changed.
--- a/src/redraw_man.h	Fri Aug 01 23:32:22 2008 +0800
+++ b/src/redraw_man.h	Sat Aug 02 14:45:42 2008 +0800
@@ -33,6 +33,7 @@
 
     elmpool_t *geo_pool;
     elmpool_t *coord_pool;
+    elmpool_t *shnode_pool;
 
     int max_dirty_coords;
     int n_dirty_coords;
@@ -63,6 +64,33 @@
 extern int rdman_shape_changed(redraw_man_t *rdman, shape_t *shape);
 extern int rdman_redraw_changed(redraw_man_t *rdman);
 extern int rdman_redraw_all(redraw_man_t *rdman);
+extern shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape);
+#define shnode_free(rdman, node) elmpool_elm_free((rdman)->shnode_pool, node)
+#define shnode_list_free(rdman, q)				\
+    do {							\
+	shnode_t *__node, *__last;				\
+	__last = STAILQ_HEAD(q);				\
+	if(__last == NULL) break;				\
+	for(__node = STAILQ_NEXT(shnode_t, next, __last);	\
+	    __node != NULL;					\
+	    __node = STAILQ_NEXT(shnode_t, next, __node)) {	\
+	    shnode_free(rdman, __last);				\
+	    __last = __node;					\
+	}							\
+	shnode_free(rdman, __last);				\
+    } while(0)
+#define rdman_paint_fill(rdman, paint, shape)		\
+    do {						\
+	shnode_t *__node;				\
+	if((shape)->fill != (paint) &&			\
+	   (shape)->stroke != (paint)) {		\
+	    __node = shnode_new(rdman, shape);		\
+	    STAILQ_INS_TAIL((paint)->members,		\
+			    shnode_t, next, __node);	\
+	}						\
+	shape->fill = paint;				\
+    } while(0)
+extern int rdman_paint_changed(redraw_man_t *rdman, paint_t *paint);
 
 
 #endif /* __REDRAW_MAN_H_ */