📄 gtkcurve.c
字号:
if (c->curve_type != GTK_CURVE_TYPE_FREE) { for (src = dst = 0; src < c->num_ctlpoints; ++src) { if (c->ctlpoint[src][0] >= min_x) { memcpy (c->ctlpoint + dst, c->ctlpoint + src, sizeof (*c->ctlpoint)); ++dst; } } if (dst < src) { c->num_ctlpoints -= (src - dst); if (c->num_ctlpoints <= 0) { c->num_ctlpoints = 1; c->ctlpoint[0][0] = min_x; c->ctlpoint[0][1] = c->min_y; gtk_curve_interpolate (c, width, height); gtk_curve_draw (c, width, height); } c->ctlpoint = g_realloc (c->ctlpoint, c->num_ctlpoints * sizeof (*c->ctlpoint)); } } new_type = GDK_FLEUR; c->grab_point = -1; break; case GDK_MOTION_NOTIFY: mevent = (GdkEventMotion *) event; switch (c->curve_type) { case GTK_CURVE_TYPE_LINEAR: case GTK_CURVE_TYPE_SPLINE: if (c->grab_point == -1) { /* if no point is grabbed... */ if (distance <= MIN_DISTANCE) new_type = GDK_FLEUR; else new_type = GDK_TCROSS; } else { /* drag the grabbed point */ new_type = GDK_TCROSS; leftbound = -MIN_DISTANCE; if (c->grab_point > 0) leftbound = project (c->ctlpoint[c->grab_point - 1][0], min_x, c->max_x, width); rightbound = width + RADIUS * 2 + MIN_DISTANCE; if (c->grab_point + 1 < c->num_ctlpoints) rightbound = project (c->ctlpoint[c->grab_point + 1][0], min_x, c->max_x, width); if (tx <= leftbound || tx >= rightbound || ty > height + RADIUS * 2 + MIN_DISTANCE || ty < -MIN_DISTANCE) c->ctlpoint[c->grab_point][0] = min_x - 1.0; else { rx = unproject (x, min_x, c->max_x, width); ry = unproject (height - y, c->min_y, c->max_y, height); c->ctlpoint[c->grab_point][0] = rx; c->ctlpoint[c->grab_point][1] = ry; } gtk_curve_interpolate (c, width, height); gtk_curve_draw (c, width, height); } break; case GTK_CURVE_TYPE_FREE: if (c->grab_point != -1) { if (c->grab_point > x) { x1 = x; x2 = c->grab_point; y1 = y; y2 = c->last; } else { x1 = c->grab_point; x2 = x; y1 = c->last; y2 = y; } if (x2 != x1) for (i = x1; i <= x2; i++) { c->point[i].x = RADIUS + i; c->point[i].y = RADIUS + (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1)); } else { c->point[x].x = RADIUS + x; c->point[x].y = RADIUS + y; } c->grab_point = x; c->last = y; gtk_curve_draw (c, width, height); } if (mevent->state & GDK_BUTTON1_MASK) new_type = GDK_TCROSS; else new_type = GDK_PENCIL; break; } if (new_type != (GdkCursorType) c->cursor_type) { GdkCursor *cursor; c->cursor_type = new_type; cursor = gdk_cursor_new (c->cursor_type); gdk_window_set_cursor (w->window, cursor); gdk_cursor_destroy (cursor); } break; default: break; } return FALSE;}voidgtk_curve_set_curve_type (GtkCurve *c, GtkCurveType new_type){ gfloat rx, dx; gint x, i; if (new_type != c->curve_type) { gint width, height; width = GTK_WIDGET(c)->allocation.width - RADIUS * 2; height = GTK_WIDGET(c)->allocation.height - RADIUS * 2; if (new_type == GTK_CURVE_TYPE_FREE) { gtk_curve_interpolate (c, width, height); c->curve_type = new_type; } else if (c->curve_type == GTK_CURVE_TYPE_FREE) { if (c->ctlpoint) g_free (c->ctlpoint); c->num_ctlpoints = 9; c->ctlpoint = g_malloc (c->num_ctlpoints * sizeof (*c->ctlpoint)); rx = 0.0; dx = (width - 1) / (gfloat) (c->num_ctlpoints - 1); for (i = 0; i < c->num_ctlpoints; ++i, rx += dx) { x = (int) (rx + 0.5); c->ctlpoint[i][0] = unproject (x, c->min_x, c->max_x, width); c->ctlpoint[i][1] = unproject (RADIUS + height - c->point[x].y, c->min_y, c->max_y, height); } c->curve_type = new_type; gtk_curve_interpolate (c, width, height); } else { c->curve_type = new_type; gtk_curve_interpolate (c, width, height); } gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal); gtk_curve_draw (c, width, height); }}static voidgtk_curve_size_graph (GtkCurve *curve){ gint width, height; gfloat aspect; width = (curve->max_x - curve->min_x) + 1; height = (curve->max_y - curve->min_y) + 1; aspect = width / (gfloat) height; if (width > gdk_screen_width () / 4) width = gdk_screen_width () / 4; if (height > gdk_screen_height () / 4) height = gdk_screen_height () / 4; if (aspect < 1.0) width = height * aspect; else height = width / aspect; gtk_drawing_area_size (GTK_DRAWING_AREA (curve), width + RADIUS * 2, height + RADIUS * 2);}static voidgtk_curve_reset_vector (GtkCurve *curve){ if (curve->ctlpoint) g_free (curve->ctlpoint); curve->num_ctlpoints = 2; curve->ctlpoint = g_malloc (2 * sizeof (curve->ctlpoint[0])); curve->ctlpoint[0][0] = curve->min_x; curve->ctlpoint[0][1] = curve->min_y; curve->ctlpoint[1][0] = curve->max_x; curve->ctlpoint[1][1] = curve->max_y; if (curve->pixmap) { gint width, height; width = GTK_WIDGET (curve)->allocation.width - RADIUS * 2; height = GTK_WIDGET (curve)->allocation.height - RADIUS * 2; if (curve->curve_type == GTK_CURVE_TYPE_FREE) { curve->curve_type = GTK_CURVE_TYPE_LINEAR; gtk_curve_interpolate (curve, width, height); curve->curve_type = GTK_CURVE_TYPE_FREE; } else gtk_curve_interpolate (curve, width, height); gtk_curve_draw (curve, width, height); }}voidgtk_curve_reset (GtkCurve *c){ GtkCurveType old_type; old_type = c->curve_type; c->curve_type = GTK_CURVE_TYPE_SPLINE; gtk_curve_reset_vector (c); if (old_type != GTK_CURVE_TYPE_SPLINE) gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);}voidgtk_curve_set_gamma (GtkCurve *c, gfloat gamma){ gfloat x, one_over_gamma, height, one_over_width; GtkCurveType old_type; gint i; if (c->num_points < 2) return; old_type = c->curve_type; c->curve_type = GTK_CURVE_TYPE_FREE; if (gamma <= 0) one_over_gamma = 1.0; else one_over_gamma = 1.0 / gamma; one_over_width = 1.0 / (c->num_points - 1); height = c->height; for (i = 0; i < c->num_points; ++i) { x = (gfloat) i / (c->num_points - 1); c->point[i].x = RADIUS + i; c->point[i].y = RADIUS + (height * (1.0 - pow (x, one_over_gamma)) + 0.5); } if (old_type != GTK_CURVE_TYPE_FREE) gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal); gtk_curve_draw (c, c->num_points, c->height);}voidgtk_curve_set_range (GtkCurve *curve, gfloat min_x, gfloat max_x, gfloat min_y, gfloat max_y){ curve->min_x = min_x; curve->max_x = max_x; curve->min_y = min_y; curve->max_y = max_y; gtk_curve_size_graph (curve); gtk_curve_reset_vector (curve);}voidgtk_curve_set_vector (GtkCurve *c, int veclen, gfloat vector[]){ GtkCurveType old_type; gfloat rx, dx, ry; gint i, height; old_type = c->curve_type; c->curve_type = GTK_CURVE_TYPE_FREE; if (c->point) height = GTK_WIDGET (c)->allocation.height - RADIUS * 2; else { height = (c->max_y - c->min_y); if (height > gdk_screen_height () / 4) height = gdk_screen_height () / 4; c->height = height; c->num_points = veclen; c->point = g_malloc (c->num_points * sizeof (c->point[0])); } rx = 0; dx = (veclen - 1.0) / (c->num_points - 1.0); for (i = 0; i < c->num_points; ++i, rx += dx) { ry = vector[(int) (rx + 0.5)]; if (ry > c->max_y) ry = c->max_y; if (ry < c->min_y) ry = c->min_y; c->point[i].x = RADIUS + i; c->point[i].y = RADIUS + height - project (ry, c->min_y, c->max_y, height); } if (old_type != GTK_CURVE_TYPE_FREE) gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal); gtk_curve_draw (c, c->num_points, height);}voidgtk_curve_get_vector (GtkCurve *c, int veclen, gfloat vector[]){ gfloat rx, ry, dx, dy, min_x, delta_x, *mem, *xv, *yv, *y2v, prev; gint dst, i, x, next, num_active_ctlpoints = 0, first_active = -1; min_x = c->min_x; if (c->curve_type != GTK_CURVE_TYPE_FREE) { /* count active points: */ prev = min_x - 1.0; for (i = num_active_ctlpoints = 0; i < c->num_ctlpoints; ++i) if (c->ctlpoint[i][0] > prev) { if (first_active < 0) first_active = i; prev = c->ctlpoint[i][0]; ++num_active_ctlpoints; } /* handle degenerate case: */ if (num_active_ctlpoints < 2) { if (num_active_ctlpoints > 0) ry = c->ctlpoint[first_active][1]; else ry = c->min_y; if (ry < c->min_y) ry = c->min_y; if (ry > c->max_y) ry = c->max_y; for (x = 0; x < veclen; ++x) vector[x] = ry; return; } } switch (c->curve_type) { case GTK_CURVE_TYPE_SPLINE: mem = g_malloc (3 * num_active_ctlpoints * sizeof (gfloat)); xv = mem; yv = mem + num_active_ctlpoints; y2v = mem + 2*num_active_ctlpoints; prev = min_x - 1.0; for (i = dst = 0; i < c->num_ctlpoints; ++i) if (c->ctlpoint[i][0] > prev) { prev = c->ctlpoint[i][0]; xv[dst] = c->ctlpoint[i][0]; yv[dst] = c->ctlpoint[i][1]; ++dst; } spline_solve (num_active_ctlpoints, xv, yv, y2v); rx = min_x; dx = (c->max_x - min_x) / (veclen - 1); for (x = 0; x < veclen; ++x, rx += dx) { ry = spline_eval (num_active_ctlpoints, xv, yv, y2v, rx); if (ry < c->min_y) ry = c->min_y; if (ry > c->max_y) ry = c->max_y; vector[x] = ry; } g_free (mem); break; case GTK_CURVE_TYPE_LINEAR: dx = (c->max_x - min_x) / (veclen - 1); rx = min_x; ry = c->min_y; dy = 0.0; i = first_active; for (x = 0; x < veclen; ++x, rx += dx) { if (rx >= c->ctlpoint[i][0]) { if (rx > c->ctlpoint[i][0]) ry = c->min_y; dy = 0.0; next = i + 1; while (next < c->num_ctlpoints && c->ctlpoint[next][0] <= c->ctlpoint[i][0]) ++next; if (next < c->num_ctlpoints) { delta_x = c->ctlpoint[next][0] - c->ctlpoint[i][0]; dy = ((c->ctlpoint[next][1] - c->ctlpoint[i][1]) / delta_x); dy *= dx; ry = c->ctlpoint[i][1]; i = next; } } vector[x] = ry; ry += dy; } break; case GTK_CURVE_TYPE_FREE: if (c->point) { rx = 0.0; dx = c->num_points / (double) veclen; for (x = 0; x < veclen; ++x, rx += dx) vector[x] = unproject (RADIUS + c->height - c->point[(int) rx].y, c->min_y, c->max_y, c->height); } else memset (vector, 0, veclen * sizeof (vector[0])); break; }}GtkWidget*gtk_curve_new (void){ return gtk_type_new (gtk_curve_get_type ());}static voidgtk_curve_finalize (GtkObject *object){ GtkCurve *curve; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_CURVE (object)); curve = GTK_CURVE (object); if (curve->pixmap) gdk_pixmap_unref (curve->pixmap); if (curve->point) g_free (curve->point); if (curve->ctlpoint) g_free (curve->ctlpoint); (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -