# HG changeset patch # User Matti Hamalainen # Date 1172207400 0 # Node ID 425da926d3105e7d4c86fd1b39250a413133c312 # Parent 260c286108e614520cc32e01f25c9e88e67d88af Working on XSCurve widget implementation. diff -r 260c286108e6 -r 425da926d310 src/xs_curve.c --- 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 #include #include - #include - #include "xs_curve.h" #include #include @@ -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); } - diff -r 260c286108e6 -r 425da926d310 src/xs_curve.h --- 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 }