changeset 545:425da926d310

Working on XSCurve widget implementation.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 23 Feb 2007 05:10:00 +0000
parents 260c286108e6
children 70fe31fe2bf5
files src/xs_curve.c src/xs_curve.h
diffstat 2 files changed, 160 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/src/xs_curve.c	Wed Feb 21 15:23:02 2007 +0000
+++ b/src/xs_curve.c	Fri Feb 23 05:10:00 2007 +0000
@@ -1,9 +1,12 @@
+/*
+ *
+ *
+ *
+ */
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
-
 #include <stdio.h>
-
 #include "xs_curve.h"
 #include <gtk/gtkdrawingarea.h>
 #include <gtk/gtkmain.h>
@@ -12,8 +15,8 @@
 
 #define RADIUS		3	/* radius of the control points */
 #define RADIUS2		(RADIUS * 2)
+#define MIN_DISTANCE	7	/* min distance between control points */
 
-#define MIN_DISTANCE	8	/* min distance between control points */
 
 #define GRAPH_MASK	(GDK_EXPOSURE_MASK |		\
 			GDK_POINTER_MOTION_MASK |	\
@@ -29,7 +32,6 @@
 
 enum {
 	ARG_0,
-	ARG_CURVE_TYPE,
 	ARG_MIN_X,
 	ARG_MAX_X,
 	ARG_MIN_Y,
@@ -96,13 +98,13 @@
 	curve->height = 0;
 	curve->grab_point = -1;
 
-	curve->num_ctlpoints = 0;
+	curve->nctlpoints = 0;
 	curve->ctlpoints = NULL;
 
 	curve->min_x = 0.0;
-	curve->max_x = 2048.0;
+	curve->max_x = 2047.0;
 	curve->min_y = 0.0;
-	curve->max_y = 22000.0;
+	curve->max_y = 24000.0;
 
 	old_mask = gtk_widget_get_events(GTK_WIDGET(curve));
 	gtk_widget_set_events(GTK_WIDGET(curve), old_mask | GRAPH_MASK);
@@ -220,6 +222,7 @@
 			i * (width / 4.0) + RADIUS, height + RADIUS);
 	}
 
+#define Qprintf(x,y,...)
 
 #if 1
 	/* Draw the spline/curve itself */
@@ -229,44 +232,46 @@
 	p3 = p2; p3++;
 
 	/* Draw each curve segment */
-	fprintf(stderr, "-- npoints = %d\n", curve->num_ctlpoints);
-	if (curve->num_ctlpoints > 5)
-	for (i = 0; i < curve->num_ctlpoints; i++, ++p0, ++p1, ++p2, ++p3) {
+	Qprintf(stderr, "-- npoints = %d\n", curve->nctlpoints);
+	if (curve->nctlpoints > 5)
+	for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) {
 		gfloat k1, k2, a, b, c, d, x;
-fprintf(stderr, "#%d: ", i);
+		
+		Qprintf(stderr, "#%d: ", i);
 		if (p1->x == p2->x)
 			continue;
-#define PPASK(q, p) fprintf(stderr, q "=[%1.3f, %1.3f]  ", p->x, p->y)
+#define PPASK(q, p) Qprintf(stderr, q "=[%1.3f, %1.3f]  ", p->x, p->y)
 
 		PPASK("p0", p1);
 		PPASK("p1", p1);
 		PPASK("p2", p2);
 		PPASK("p3", p3);
 		
-		fprintf(stderr, "\ncase #");
+		Qprintf(stderr, "\ncase #");
 		if (p0->x == p1->x && p2->x == p3->x) {
-			fprintf(stderr, "1");
+			Qprintf(stderr, "1");
 			k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x);
 		} else if (p0->x == p1->x) {
-			fprintf(stderr, "2");
+			Qprintf(stderr, "2");
 			k2 = (p3->y - p1->y) / (p3->x - p1->x);
 			k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2;
 		} else if (p2->x == p3->x) {
-			fprintf(stderr, "3");
+			Qprintf(stderr, "3");
 			k1 = (p2->y - p0->y) / (p2->x - p0->x);
 			k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2;
 		} else {
-			fprintf(stderr, "4");
+			Qprintf(stderr, "4");
 			k1 = (p2->y - p0->y) / (p2->x - p0->x);
 			k2 = (p3->y - p1->y) / (p3->x - p1->x);
 		}
 
 		xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d);
-		fprintf(stderr, " seg[%1.3f, %1.3f] => [%1.3f, %1.3f] k1=%1.3f, k2=%1.3f\n\n",
+
+		Qprintf(stderr, " seg[%1.3f, %1.3f] => [%1.3f, %1.3f] k1=%1.3f, k2=%1.3f\n\n",
 			p1->x, p1->y,
 			p2->x, p2->y,
 			k1, k2);
-#if 1
+
 		for (x = p1->x; x <= p2->x; x += res) {
 			gfloat y = ((a * x + b) * x + c) * x + d;
 			gint qx, qy;
@@ -278,13 +283,13 @@
 				RADIUS + xs_project(y, curve->min_y, curve->max_y, height));
 
 		}
-#endif
 	}
-	fprintf(stderr, "-------\n");
+
+	Qprintf(stderr, "-------\n");
 #endif
 
 	/* Draw control points */
-	for (i = 0; i < curve->num_ctlpoints; ++i) {
+	for (i = 0; i < curve->nctlpoints; ++i) {
 		gint x, y;
 
 		if (GET_X(i) < curve->min_x || GET_Y(i) < curve->min_y ||
@@ -311,7 +316,6 @@
 {
 	GdkCursorType new_type = curve->cursor_type;
 	GdkEventButton *bevent;
-	GdkEventMotion *mevent;
 	GtkWidget *w;
 	gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x;
 	guint distance;
@@ -327,11 +331,10 @@
 	gdk_window_get_pointer(w->window, &tx, &ty, NULL);
 	x = CLAMP((tx - RADIUS), 0, width - 1);
 	y = CLAMP((ty - RADIUS), 0, height - 1);
-
 	min_x = curve->min_x;
 
 	distance = ~0U;
-	for (i = 0; i < curve->num_ctlpoints; ++i) {
+	for (i = 0; i < curve->nctlpoints; ++i) {
 		cx = xs_project(GET_X(i), min_x, curve->max_x, width);
 		if ((guint) abs(x - cx) < distance) {
 			distance = abs(x - cx);
@@ -364,16 +367,20 @@
 
 		if (distance > MIN_DISTANCE) {
 			/* insert a new control point */
-			if (curve->num_ctlpoints > 0) {
+			if (curve->nctlpoints > 0) {
 				cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width);
 				if (x > cx) closest_point++;
 			}
 			
-			curve->num_ctlpoints++;
+			curve->nctlpoints++;
+			
+			curve->ctlpoints = g_realloc(curve->ctlpoints,
+				curve->nctlpoints * sizeof(*curve->ctlpoints));
 			
-			curve->ctlpoints = g_realloc(curve->ctlpoints, curve->num_ctlpoints * sizeof(*curve->ctlpoints));
-			for (i = curve->num_ctlpoints - 1; i > closest_point; --i) {
-				memcpy(curve->ctlpoints + i, curve->ctlpoints + i - 1, sizeof(*curve->ctlpoints));
+			for (i = curve->nctlpoints - 1; i > closest_point; --i) {
+				memcpy(curve->ctlpoints + i,
+					curve->ctlpoints + i - 1,
+					sizeof(*curve->ctlpoints));
 			}
 		}
 		
@@ -391,21 +398,25 @@
 		gtk_grab_remove(widget);
 
 		/* delete inactive points: */
-		for (src = dst = 0; src < curve->num_ctlpoints; ++src)
-		if (GET_X(src) >= min_x) {
-			memcpy(curve->ctlpoints + dst, curve->ctlpoints + src, sizeof(*curve->ctlpoints));
-			dst++;
+		for (src = dst = 0; src < curve->nctlpoints; ++src) {
+			if (GET_X(src) >= min_x) {
+				memcpy(curve->ctlpoints + dst,
+					curve->ctlpoints + src,
+					sizeof(*curve->ctlpoints));
+				dst++;
+			}
 		}
 
 		if (dst < src) {
-			curve->num_ctlpoints -= (src - dst);
-			if (curve->num_ctlpoints <= 0) {
-				curve->num_ctlpoints = 1;
+			curve->nctlpoints -= (src - dst);
+			if (curve->nctlpoints <= 0) {
+				curve->nctlpoints = 1;
 				GET_X(0) = min_x;
 				GET_Y(0) = curve->min_y;
 				xs_curve_draw(curve, width, height);
 			}
-			curve->ctlpoints = g_realloc(curve->ctlpoints, curve->num_ctlpoints * sizeof(*curve->ctlpoints));
+			curve->ctlpoints = g_realloc(curve->ctlpoints,
+				curve->nctlpoints * sizeof(*curve->ctlpoints));
 		}
 
 		new_type = GDK_FLEUR;
@@ -414,8 +425,6 @@
 		break;
 
 	case GDK_MOTION_NOTIFY:
-		mevent = (GdkEventMotion *) event;
-
 		if (curve->grab_point == -1) {
 			/* if no point is grabbed...  */
 			if (distance <= MIN_DISTANCE)
@@ -436,7 +445,7 @@
 			}
 
 			rightbound = width + RADIUS2 + MIN_DISTANCE;
-			if (curve->grab_point + 1 < curve->num_ctlpoints) {
+			if (curve->grab_point + 1 < curve->nctlpoints) {
 				rightbound = xs_project(
 					GET_X(curve->grab_point+1),
 					min_x, curve->max_x, width);
@@ -454,12 +463,11 @@
 			
 			xs_curve_draw(curve, width, height);
 		}
-
+		
+		/* See if cursor type was changed and update accordingly */
 		if (new_type != (GdkCursorType) curve->cursor_type) {
 			GdkCursor *cursor;
-
 			curve->cursor_type = new_type;
-
 			cursor = gdk_cursor_new(curve->cursor_type);
 			gdk_window_set_cursor(w->window, cursor);
 			gdk_cursor_destroy(cursor);
@@ -498,26 +506,8 @@
 }
 
 
-void xs_curve_reset(XSCurve *curve)
+static void xs_curve_update(XSCurve *curve)
 {
-	if (curve->ctlpoints)
-		g_free(curve->ctlpoints);
-
-	curve->num_ctlpoints = 4;
-	curve->ctlpoints = g_malloc(curve->num_ctlpoints * sizeof(curve->ctlpoints[0]));
-
-	GET_X(0) = curve->min_x;
-	GET_Y(0) = curve->min_y;
-
-	GET_X(1) = curve->min_x;
-	GET_Y(1) = curve->min_y;
-
-	GET_X(2) = curve->max_x;
-	GET_Y(2) = curve->max_y;
-
-	GET_X(3) = curve->max_x;
-	GET_Y(3) = curve->max_y;
-
 	if (curve->pixmap) {
 		gint width, height;
 
@@ -528,10 +518,33 @@
 }
 
 
-void xs_curve_set_range(XSCurve *curve, gfloat min_x, gfloat max_x, gfloat min_y, gfloat max_y)
+void xs_curve_reset(XSCurve *curve)
+{
+	if (curve->ctlpoints)
+		g_free(curve->ctlpoints);
+
+	curve->nctlpoints = 4;
+	curve->ctlpoints = g_malloc(curve->nctlpoints * sizeof(curve->ctlpoints[0]));
+
+	GET_X(0) = curve->min_x;
+	GET_Y(0) = curve->min_y;
+	GET_X(1) = curve->min_x;
+	GET_Y(1) = curve->min_y;
+
+	GET_X(2) = curve->max_x;
+	GET_Y(2) = curve->max_y;
+	GET_X(3) = curve->max_x;
+	GET_Y(3) = curve->max_y;
+	
+	xs_curve_update(curve);
+}
+
+
+void xs_curve_set_range(XSCurve *curve, gfloat min_x, gfloat min_y, gfloat max_x, gfloat max_y)
 {
 	curve->min_x = min_x;
 	curve->max_x = max_x;
+	
 	curve->min_y = min_y;
 	curve->max_y = max_y;
 
@@ -540,6 +553,75 @@
 }
 
 
+gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints)
+{
+	if (npoints != curve->nctlpoints) {
+		curve->nctlpoints = npoints;
+		curve->ctlpoints = (t_xs_point *) g_realloc(curve->ctlpoints,
+			curve->nctlpoints * sizeof(*curve->ctlpoints));
+
+		if (curve->ctlpoints == NULL)
+			return FALSE;
+	}
+	
+	return TRUE;
+}
+
+
+void xs_curve_get_data(XSCurve *curve, t_xs_point ***points, gint **npoints)
+{
+	*points = &(curve->ctlpoints);
+	*npoints = &(curve->nctlpoints);
+}
+
+
+gboolean xs_curve_set_points(XSCurve *curve, t_xs_int_point *points, gint npoints)
+{
+	gint i;
+
+	if (!xs_curve_realloc_data(curve, npoints + 4))
+		return FALSE;
+	
+	GET_X(0) = curve->min_x;
+	GET_Y(0) = curve->min_y;
+	GET_X(1) = curve->min_x;
+	GET_Y(1) = curve->min_y;
+
+	for (i = 0; i < npoints; i++) {
+		GET_X(i+2) = points[i].x;
+		GET_Y(i+2) = points[i].y;
+	}
+
+	GET_X(npoints+2) = curve->max_x;
+	GET_Y(npoints+2) = curve->max_y;
+	GET_X(npoints+3) = curve->max_x;
+	GET_Y(npoints+3) = curve->max_y;
+	
+	xs_curve_update(curve);
+	return TRUE;
+}
+
+
+gboolean xs_curve_get_points(XSCurve *curve, t_xs_int_point **points, gint *npoints)
+{
+	gint i, n;
+	
+	n = curve->nctlpoints - 4;
+	
+	*points = g_malloc(n * sizeof(t_xs_int_point));
+	if (*points == NULL)
+		return FALSE;
+	
+	*npoints = n;
+	for (i = 2; i < curve->nctlpoints - 2; i++) {
+		(*points)[i].x = GET_X(i);
+		(*points)[i].y = GET_Y(i);
+	}
+
+	return TRUE;
+}
+
+
 GtkWidget *xs_curve_new(void)
 {
 	return gtk_type_new(xs_curve_get_type());
@@ -563,4 +645,3 @@
 
 	(*GTK_OBJECT_CLASS(parent_class)->finalize) (object);
 }
-
--- a/src/xs_curve.h	Wed Feb 21 15:23:02 2007 +0000
+++ b/src/xs_curve.h	Fri Feb 23 05:10:00 2007 +0000
@@ -8,7 +8,8 @@
 extern "C" {
 #endif
 
-
+/* Macros for type-classing this GtkWidget/object
+ */
 #define XS_TYPE_CURVE			(xs_curve_get_type())
 #define XS_CURVE(obj)			(GTK_CHECK_CAST ((obj), XS_TYPE_CURVE, XSCurve))
 #define XS_CURVE_CLASS(luokka)		(GTK_CHECK_CLASS_CAST ((luokka), XS_TYPE_CURVE, XSCurveClass))
@@ -16,6 +17,8 @@
 #define XS_IS_CURVE_CLASS(luokka)	(GTK_CHECK_CLASS_TYPE ((luokka), XS_TYPE_CURVE))
 
 
+/* Structures
+ */
 typedef struct _XSCurve	XSCurve;
 typedef struct _XSCurveClass	XSCurveClass;
 
@@ -23,6 +26,9 @@
 	gfloat x,y;
 } t_xs_point;
 
+typedef struct {
+	gint x, y;
+} t_xs_int_point;
 
 struct _XSCurve {
 	GtkDrawingArea graph;
@@ -38,7 +44,7 @@
 	gint last;
 
 	/* control points */
-	gint num_ctlpoints;	/* number of control points */
+	gint nctlpoints;	/* number of control points */
 	t_xs_point *ctlpoints;	/* array of control points */
 };
 
@@ -51,8 +57,12 @@
 GtkWidget*	xs_curve_new		(void);
 void		xs_curve_reset		(XSCurve *curve);
 void		xs_curve_set_range	(XSCurve *curve,
-					 gfloat min_x, gfloat max_x,
-					 gfloat min_y, gfloat max_y);
+					 gfloat min_x, gfloat min_y,
+					 gfloat max_x, gfloat max_y);
+gboolean	xs_curve_realloc_data	(XSCurve *curve, gint npoints);
+void		xs_curve_get_data	(XSCurve *curve, t_xs_point ***points, gint **npoints);
+gboolean	xs_curve_set_points	(XSCurve *curve, t_xs_int_point *points, gint npoints);
+gboolean	xs_curve_get_points	(XSCurve *curve, t_xs_int_point **points, gint *npoints);
 
 #ifdef __cplusplus
 }