Mercurial > audlegacy-plugins
comparison src/sid/xs_curve.c @ 2509:1223e8510d8a
Change tabs to 4 spaces, everywhere.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 03 Apr 2008 00:52:14 +0300 |
parents | 05bfc86250f3 |
children | 45ef6d7c0174 |
comparison
equal
deleted
inserted
replaced
2508:58889ccbe807 | 2509:1223e8510d8a |
---|---|
31 #include <gtk/gtkdrawingarea.h> | 31 #include <gtk/gtkdrawingarea.h> |
32 #include <gtk/gtkmain.h> | 32 #include <gtk/gtkmain.h> |
33 #include <gtk/gtkprivate.h> | 33 #include <gtk/gtkprivate.h> |
34 | 34 |
35 | 35 |
36 #define RADIUS 3 /* radius of the control points */ | 36 #define RADIUS 3 /* radius of the control points */ |
37 #define RADIUS2 (RADIUS * 2) | 37 #define RADIUS2 (RADIUS * 2) |
38 #define MIN_DISTANCE 7 /* min distance between control points */ | 38 #define MIN_DISTANCE 7 /* min distance between control points */ |
39 | 39 |
40 | 40 |
41 #define GRAPH_MASK (GDK_EXPOSURE_MASK | \ | 41 #define GRAPH_MASK (GDK_EXPOSURE_MASK | \ |
42 GDK_POINTER_MOTION_MASK | \ | 42 GDK_POINTER_MOTION_MASK | \ |
43 GDK_POINTER_MOTION_HINT_MASK | \ | 43 GDK_POINTER_MOTION_HINT_MASK | \ |
44 GDK_ENTER_NOTIFY_MASK | \ | 44 GDK_ENTER_NOTIFY_MASK | \ |
45 GDK_BUTTON_PRESS_MASK | \ | 45 GDK_BUTTON_PRESS_MASK | \ |
46 GDK_BUTTON_RELEASE_MASK | \ | 46 GDK_BUTTON_RELEASE_MASK | \ |
47 GDK_BUTTON1_MOTION_MASK) | 47 GDK_BUTTON1_MOTION_MASK) |
48 | 48 |
49 #define GET_X(i) curve->ctlpoints[i].x | 49 #define GET_X(i) curve->ctlpoints[i].x |
50 #define GET_Y(i) curve->ctlpoints[i].y | 50 #define GET_Y(i) curve->ctlpoints[i].y |
51 | 51 |
52 | 52 |
53 enum { | 53 enum { |
54 PROP_0, | 54 PROP_0, |
55 PROP_MIN_X, | 55 PROP_MIN_X, |
56 PROP_MAX_X, | 56 PROP_MAX_X, |
57 PROP_MIN_Y, | 57 PROP_MIN_Y, |
58 PROP_MAX_Y | 58 PROP_MAX_Y |
59 }; | 59 }; |
60 | 60 |
61 static GtkDrawingAreaClass *parent_class = NULL; | 61 static GtkDrawingAreaClass *parent_class = NULL; |
62 | 62 |
63 static void xs_curve_class_init(XSCurveClass * class); | 63 static void xs_curve_class_init(XSCurveClass * class); |
64 static void xs_curve_init(XSCurve * curve); | 64 static void xs_curve_init(XSCurve * curve); |
65 static void xs_curve_get_property(GObject * object, guint param_id, | 65 static void xs_curve_get_property(GObject * object, guint param_id, |
66 GValue * value, GParamSpec * pspec); | 66 GValue * value, GParamSpec * pspec); |
67 static void xs_curve_set_property(GObject * object, guint param_id, | 67 static void xs_curve_set_property(GObject * object, guint param_id, |
68 const GValue * value, GParamSpec * pspec); | 68 const GValue * value, GParamSpec * pspec); |
69 static void xs_curve_finalize(GObject * object); | 69 static void xs_curve_finalize(GObject * object); |
70 static gint xs_curve_graph_events(GtkWidget * widget, GdkEvent * event, XSCurve * c); | 70 static gint xs_curve_graph_events(GtkWidget * widget, GdkEvent * event, XSCurve * c); |
71 static void xs_curve_size_graph(XSCurve * curve); | 71 static void xs_curve_size_graph(XSCurve * curve); |
72 | 72 |
73 | 73 |
74 GtkType xs_curve_get_type(void) | 74 GtkType xs_curve_get_type(void) |
75 { | 75 { |
76 static GType curve_type = 0; | 76 static GType curve_type = 0; |
77 | 77 |
78 if (!curve_type) { | 78 if (!curve_type) { |
79 static const GTypeInfo curve_info = { | 79 static const GTypeInfo curve_info = { |
80 sizeof(XSCurveClass), | 80 sizeof(XSCurveClass), |
81 NULL, /* base_init */ | 81 NULL, /* base_init */ |
82 NULL, /* base_finalize */ | 82 NULL, /* base_finalize */ |
83 (GClassInitFunc) xs_curve_class_init, | 83 (GClassInitFunc) xs_curve_class_init, |
84 NULL, /* class_finalize */ | 84 NULL, /* class_finalize */ |
85 NULL, /* class_data */ | 85 NULL, /* class_data */ |
86 sizeof(XSCurve), | 86 sizeof(XSCurve), |
87 0, /* n_preallocs */ | 87 0, /* n_preallocs */ |
88 (GInstanceInitFunc) xs_curve_init, | 88 (GInstanceInitFunc) xs_curve_init, |
89 }; | 89 }; |
90 | 90 |
91 curve_type = g_type_register_static( | 91 curve_type = g_type_register_static( |
92 GTK_TYPE_DRAWING_AREA, "XSCurve", | 92 GTK_TYPE_DRAWING_AREA, "XSCurve", |
93 &curve_info, 0); | 93 &curve_info, 0); |
94 } | 94 } |
95 return curve_type; | 95 return curve_type; |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 static void xs_curve_class_init(XSCurveClass *class) | 99 static void xs_curve_class_init(XSCurveClass *class) |
100 { | 100 { |
101 GObjectClass *gobject_class = G_OBJECT_CLASS(class); | 101 GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
102 | 102 |
103 parent_class = g_type_class_peek_parent(class); | 103 parent_class = g_type_class_peek_parent(class); |
104 | 104 |
105 gobject_class->finalize = xs_curve_finalize; | 105 gobject_class->finalize = xs_curve_finalize; |
106 | 106 |
107 gobject_class->set_property = xs_curve_set_property; | 107 gobject_class->set_property = xs_curve_set_property; |
108 gobject_class->get_property = xs_curve_get_property; | 108 gobject_class->get_property = xs_curve_get_property; |
109 | 109 |
110 g_object_class_install_property(gobject_class, PROP_MIN_X, | 110 g_object_class_install_property(gobject_class, PROP_MIN_X, |
111 g_param_spec_float("min-x", | 111 g_param_spec_float("min-x", |
112 "Minimum X", | 112 "Minimum X", |
113 "Minimum possible value for X", | 113 "Minimum possible value for X", |
114 -G_MAXFLOAT, G_MAXFLOAT, 0.0, | 114 -G_MAXFLOAT, G_MAXFLOAT, 0.0, |
115 GTK_PARAM_READWRITE) | 115 GTK_PARAM_READWRITE) |
116 ); | 116 ); |
117 | 117 |
118 g_object_class_install_property(gobject_class, PROP_MAX_X, | 118 g_object_class_install_property(gobject_class, PROP_MAX_X, |
119 g_param_spec_float("max-x", | 119 g_param_spec_float("max-x", |
120 "Maximum X", | 120 "Maximum X", |
121 "Maximum possible X value", | 121 "Maximum possible X value", |
122 -G_MAXFLOAT, G_MAXFLOAT, 1.0, | 122 -G_MAXFLOAT, G_MAXFLOAT, 1.0, |
123 GTK_PARAM_READWRITE) | 123 GTK_PARAM_READWRITE) |
124 ); | 124 ); |
125 | 125 |
126 g_object_class_install_property(gobject_class, PROP_MIN_Y, | 126 g_object_class_install_property(gobject_class, PROP_MIN_Y, |
127 g_param_spec_float("min-y", | 127 g_param_spec_float("min-y", |
128 "Minimum Y", | 128 "Minimum Y", |
129 "Minimum possible value for Y", | 129 "Minimum possible value for Y", |
130 -G_MAXFLOAT, G_MAXFLOAT, 0.0, | 130 -G_MAXFLOAT, G_MAXFLOAT, 0.0, |
131 GTK_PARAM_READWRITE) | 131 GTK_PARAM_READWRITE) |
132 ); | 132 ); |
133 | 133 |
134 g_object_class_install_property(gobject_class, PROP_MAX_Y, | 134 g_object_class_install_property(gobject_class, PROP_MAX_Y, |
135 g_param_spec_float("max-y", | 135 g_param_spec_float("max-y", |
136 "Maximum Y", | 136 "Maximum Y", |
137 "Maximum possible value for Y", | 137 "Maximum possible value for Y", |
138 -G_MAXFLOAT, G_MAXFLOAT, 1.0, | 138 -G_MAXFLOAT, G_MAXFLOAT, 1.0, |
139 GTK_PARAM_READWRITE) | 139 GTK_PARAM_READWRITE) |
140 ); | 140 ); |
141 } | 141 } |
142 | 142 |
143 | 143 |
144 static void xs_curve_init(XSCurve *curve) | 144 static void xs_curve_init(XSCurve *curve) |
145 { | 145 { |
146 gint old_mask; | 146 gint old_mask; |
147 | 147 |
148 curve->pixmap = NULL; | 148 curve->pixmap = NULL; |
149 curve->grab_point = -1; | 149 curve->grab_point = -1; |
150 | 150 |
151 curve->nctlpoints = 0; | 151 curve->nctlpoints = 0; |
152 curve->ctlpoints = NULL; | 152 curve->ctlpoints = NULL; |
153 | 153 |
154 curve->min_x = 0.0; | 154 curve->min_x = 0.0; |
155 curve->max_x = 2047.0; | 155 curve->max_x = 2047.0; |
156 curve->min_y = 0.0; | 156 curve->min_y = 0.0; |
157 curve->max_y = 24000.0; | 157 curve->max_y = 24000.0; |
158 | 158 |
159 old_mask = gtk_widget_get_events(GTK_WIDGET(curve)); | 159 old_mask = gtk_widget_get_events(GTK_WIDGET(curve)); |
160 gtk_widget_set_events(GTK_WIDGET(curve), old_mask | GRAPH_MASK); | 160 gtk_widget_set_events(GTK_WIDGET(curve), old_mask | GRAPH_MASK); |
161 g_signal_connect(curve, "event", G_CALLBACK(xs_curve_graph_events), curve); | 161 g_signal_connect(curve, "event", G_CALLBACK(xs_curve_graph_events), curve); |
162 xs_curve_size_graph(curve); | 162 xs_curve_size_graph(curve); |
163 } | 163 } |
164 | 164 |
165 | 165 |
166 static void xs_curve_set_property(GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) | 166 static void xs_curve_set_property(GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) |
167 { | 167 { |
168 XSCurve *curve = XS_CURVE(object); | 168 XSCurve *curve = XS_CURVE(object); |
169 | 169 |
170 switch (prop_id) { | 170 switch (prop_id) { |
171 case PROP_MIN_X: | 171 case PROP_MIN_X: |
172 xs_curve_set_range(curve, | 172 xs_curve_set_range(curve, |
173 g_value_get_float(value), curve->max_x, | 173 g_value_get_float(value), curve->max_x, |
174 curve->min_y, curve->max_y); | 174 curve->min_y, curve->max_y); |
175 break; | 175 break; |
176 case PROP_MAX_X: | 176 case PROP_MAX_X: |
177 xs_curve_set_range(curve, | 177 xs_curve_set_range(curve, |
178 curve->min_x, g_value_get_float(value), | 178 curve->min_x, g_value_get_float(value), |
179 curve->min_y, curve->max_y); | 179 curve->min_y, curve->max_y); |
180 break; | 180 break; |
181 case PROP_MIN_Y: | 181 case PROP_MIN_Y: |
182 xs_curve_set_range(curve, | 182 xs_curve_set_range(curve, |
183 curve->min_x, curve->max_x, | 183 curve->min_x, curve->max_x, |
184 g_value_get_float(value), curve->max_y); | 184 g_value_get_float(value), curve->max_y); |
185 break; | 185 break; |
186 case PROP_MAX_Y: | 186 case PROP_MAX_Y: |
187 xs_curve_set_range(curve, | 187 xs_curve_set_range(curve, |
188 curve->min_x, curve->max_x, | 188 curve->min_x, curve->max_x, |
189 curve->min_y, g_value_get_float(value)); | 189 curve->min_y, g_value_get_float(value)); |
190 break; | 190 break; |
191 default: | 191 default: |
192 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); | 192 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); |
193 break; | 193 break; |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 | 197 |
198 static void xs_curve_get_property(GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) | 198 static void xs_curve_get_property(GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) |
199 { | 199 { |
200 XSCurve *curve = XS_CURVE(object); | 200 XSCurve *curve = XS_CURVE(object); |
201 | 201 |
202 switch (prop_id) { | 202 switch (prop_id) { |
203 case PROP_MIN_X: | 203 case PROP_MIN_X: |
204 g_value_set_float(value, curve->min_x); | 204 g_value_set_float(value, curve->min_x); |
205 break; | 205 break; |
206 case PROP_MAX_X: | 206 case PROP_MAX_X: |
207 g_value_set_float(value, curve->max_x); | 207 g_value_set_float(value, curve->max_x); |
208 break; | 208 break; |
209 case PROP_MIN_Y: | 209 case PROP_MIN_Y: |
210 g_value_set_float(value, curve->min_y); | 210 g_value_set_float(value, curve->min_y); |
211 break; | 211 break; |
212 case PROP_MAX_Y: | 212 case PROP_MAX_Y: |
213 g_value_set_float(value, curve->max_y); | 213 g_value_set_float(value, curve->max_y); |
214 break; | 214 break; |
215 default: | 215 default: |
216 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); | 216 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); |
217 break; | 217 break; |
218 } | 218 } |
219 } | 219 } |
220 | 220 |
221 | 221 |
222 static int xs_project(gfloat value, gfloat min, gfloat max, int norm) | 222 static int xs_project(gfloat value, gfloat min, gfloat max, int norm) |
223 { | 223 { |
224 return (norm - 1) * ((value - min) / (max - min)) + 0.5; | 224 return (norm - 1) * ((value - min) / (max - min)) + 0.5; |
225 } | 225 } |
226 | 226 |
227 | 227 |
228 static gfloat xs_unproject(gint value, gfloat min, gfloat max, int norm) | 228 static gfloat xs_unproject(gint value, gfloat min, gfloat max, int norm) |
229 { | 229 { |
230 return value / (gfloat) (norm - 1) * (max - min) + min; | 230 return value / (gfloat) (norm - 1) * (max - min) + min; |
231 } | 231 } |
232 | 232 |
233 | 233 |
234 static inline void xs_cubic_coeff(gfloat x1, gfloat y1, | 234 static inline void xs_cubic_coeff(gfloat x1, gfloat y1, |
235 gfloat x2, gfloat y2, | 235 gfloat x2, gfloat y2, |
236 gfloat k1, gfloat k2, | 236 gfloat k1, gfloat k2, |
237 gfloat *a, gfloat *b, | 237 gfloat *a, gfloat *b, |
238 gfloat *c, gfloat *d) | 238 gfloat *c, gfloat *d) |
239 { | 239 { |
240 gfloat dx = x2 - x1, dy = y2 - y1; | 240 gfloat dx = x2 - x1, dy = y2 - y1; |
241 | 241 |
242 *a = ((k1 + k2) - 2 * dy / dx) / (dx * dx); | 242 *a = ((k1 + k2) - 2 * dy / dx) / (dx * dx); |
243 *b = ((k2 - k1) / dx - 3 * (x1 + x2) * (*a)) / 2; | 243 *b = ((k2 - k1) / dx - 3 * (x1 + x2) * (*a)) / 2; |
244 *c = k1 - (3 * x1 * (*a) + 2 * (*b)) * x1; | 244 *c = k1 - (3 * x1 * (*a) + 2 * (*b)) * x1; |
245 *d = y1 - ((x1 * (*a) + (*b)) * x1 + (*c)) * x1; | 245 *d = y1 - ((x1 * (*a) + (*b)) * x1 + (*c)) * x1; |
246 } | 246 } |
247 | 247 |
248 | 248 |
249 static void xs_curve_draw(XSCurve *curve, gint width, gint height) | 249 static void xs_curve_draw(XSCurve *curve, gint width, gint height) |
250 { | 250 { |
251 gfloat res = 5.0f; | 251 gfloat res = 5.0f; |
252 GtkStateType state; | 252 GtkStateType state; |
253 GtkStyle *style; | 253 GtkStyle *style; |
254 gint i, ox = -1, oy = -1; | 254 gint i, ox = -1, oy = -1; |
255 t_xs_point *p0, *p1, *p2, *p3; | 255 t_xs_point *p0, *p1, *p2, *p3; |
256 | 256 |
257 if (!curve->pixmap) | 257 if (!curve->pixmap) |
258 return; | 258 return; |
259 | 259 |
260 state = GTK_STATE_NORMAL; | 260 state = GTK_STATE_NORMAL; |
261 if (!GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(curve))) | 261 if (!GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(curve))) |
262 state = GTK_STATE_INSENSITIVE; | 262 state = GTK_STATE_INSENSITIVE; |
263 | 263 |
264 style = GTK_WIDGET(curve)->style; | 264 style = GTK_WIDGET(curve)->style; |
265 | 265 |
266 /* Clear the pixmap */ | 266 /* Clear the pixmap */ |
267 gtk_paint_flat_box(style, curve->pixmap, | 267 gtk_paint_flat_box(style, curve->pixmap, |
268 GTK_STATE_NORMAL, GTK_SHADOW_NONE, | 268 GTK_STATE_NORMAL, GTK_SHADOW_NONE, |
269 NULL, GTK_WIDGET(curve), "curve_bg", | 269 NULL, GTK_WIDGET(curve), "curve_bg", |
270 0, 0, | 270 0, 0, |
271 width + RADIUS2, | 271 width + RADIUS2, |
272 height + RADIUS2); | 272 height + RADIUS2); |
273 | 273 |
274 | 274 |
275 /* Draw the grid */ | 275 /* Draw the grid */ |
276 for (i = 0; i < 5; i++) { | 276 for (i = 0; i < 5; i++) { |
277 gdk_draw_line(curve->pixmap, style->dark_gc[state], | 277 gdk_draw_line(curve->pixmap, style->dark_gc[state], |
278 RADIUS, i * (height / 4.0) + RADIUS, | 278 RADIUS, i * (height / 4.0) + RADIUS, |
279 width + RADIUS, i * (height / 4.0) + RADIUS); | 279 width + RADIUS, i * (height / 4.0) + RADIUS); |
280 | 280 |
281 gdk_draw_line(curve->pixmap, style->dark_gc[state], | 281 gdk_draw_line(curve->pixmap, style->dark_gc[state], |
282 i * (width / 4.0) + RADIUS, RADIUS, | 282 i * (width / 4.0) + RADIUS, RADIUS, |
283 i * (width / 4.0) + RADIUS, height + RADIUS); | 283 i * (width / 4.0) + RADIUS, height + RADIUS); |
284 } | 284 } |
285 | 285 |
286 #if 1 | 286 #if 1 |
287 /* Draw the spline/curve itself */ | 287 /* Draw the spline/curve itself */ |
288 p0 = curve->ctlpoints; | 288 p0 = curve->ctlpoints; |
289 p1 = p0; | 289 p1 = p0; |
290 p2 = p1; p2++; | 290 p2 = p1; p2++; |
291 p3 = p2; p3++; | 291 p3 = p2; p3++; |
292 | 292 |
293 /* Draw each curve segment */ | 293 /* Draw each curve segment */ |
294 if (curve->nctlpoints > 5) | 294 if (curve->nctlpoints > 5) |
295 for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) { | 295 for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) { |
296 gint n; | 296 gint n; |
297 gfloat k1, k2, a, b, c, d, x; | 297 gfloat k1, k2, a, b, c, d, x; |
298 | 298 |
299 if (p1->x == p2->x) | 299 if (p1->x == p2->x) |
300 continue; | 300 continue; |
301 | 301 |
302 if (p0->x == p1->x && p2->x == p3->x) { | 302 if (p0->x == p1->x && p2->x == p3->x) { |
303 k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x); | 303 k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x); |
304 } else if (p0->x == p1->x) { | 304 } else if (p0->x == p1->x) { |
305 k2 = (p3->y - p1->y) / (p3->x - p1->x); | 305 k2 = (p3->y - p1->y) / (p3->x - p1->x); |
306 k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2; | 306 k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2; |
307 } else if (p2->x == p3->x) { | 307 } else if (p2->x == p3->x) { |
308 k1 = (p2->y - p0->y) / (p2->x - p0->x); | 308 k1 = (p2->y - p0->y) / (p2->x - p0->x); |
309 k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2; | 309 k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2; |
310 } else { | 310 } else { |
311 k1 = (p2->y - p0->y) / (p2->x - p0->x); | 311 k1 = (p2->y - p0->y) / (p2->x - p0->x); |
312 k2 = (p3->y - p1->y) / (p3->x - p1->x); | 312 k2 = (p3->y - p1->y) / (p3->x - p1->x); |
313 } | 313 } |
314 | 314 |
315 xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d); | 315 xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d); |
316 | 316 |
317 for (x = p1->x; x <= p2->x; x += res, n++) { | 317 for (x = p1->x; x <= p2->x; x += res, n++) { |
318 gfloat y = ((a * x + b) * x + c) * x + d; | 318 gfloat y = ((a * x + b) * x + c) * x + d; |
319 gint qx, qy; | 319 gint qx, qy; |
320 qx = RADIUS + xs_project(x, curve->min_x, curve->max_x, width); | 320 qx = RADIUS + xs_project(x, curve->min_x, curve->max_x, width); |
321 qy = RADIUS + xs_project(y, curve->min_y, curve->max_y, height); | 321 qy = RADIUS + xs_project(y, curve->min_y, curve->max_y, height); |
322 | 322 |
323 if (ox != -1) { | 323 if (ox != -1) { |
324 gdk_draw_line(curve->pixmap, style->fg_gc[state], | 324 gdk_draw_line(curve->pixmap, style->fg_gc[state], |
325 ox, oy, qx, qy); | 325 ox, oy, qx, qy); |
326 } | 326 } |
327 ox = qx; oy = qy; | 327 ox = qx; oy = qy; |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 #endif | 331 #endif |
332 | 332 |
333 /* Draw control points */ | 333 /* Draw control points */ |
334 for (i = 0; i < curve->nctlpoints; ++i) { | 334 for (i = 0; i < curve->nctlpoints; ++i) { |
335 gint x, y; | 335 gint x, y; |
336 GtkStateType cstate; | 336 GtkStateType cstate; |
337 | 337 |
338 if (GET_X(i) < curve->min_x || GET_Y(i) < curve->min_y || | 338 if (GET_X(i) < curve->min_x || GET_Y(i) < curve->min_y || |
339 GET_X(i) >= curve->max_x || GET_Y(i) >= curve->max_y) | 339 GET_X(i) >= curve->max_x || GET_Y(i) >= curve->max_y) |
340 continue; | 340 continue; |
341 | 341 |
342 x = xs_project(GET_X(i), curve->min_x, curve->max_x, width); | 342 x = xs_project(GET_X(i), curve->min_x, curve->max_x, width); |
343 y = xs_project(GET_Y(i), curve->min_y, curve->max_y, height); | 343 y = xs_project(GET_Y(i), curve->min_y, curve->max_y, height); |
344 | 344 |
345 if (i == curve->grab_point) { | 345 if (i == curve->grab_point) { |
346 cstate = GTK_STATE_SELECTED; | 346 cstate = GTK_STATE_SELECTED; |
347 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], | 347 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], |
348 x + RADIUS, RADIUS, x + RADIUS, height + RADIUS); | 348 x + RADIUS, RADIUS, x + RADIUS, height + RADIUS); |
349 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], | 349 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], |
350 RADIUS, y + RADIUS, width + RADIUS, y + RADIUS); | 350 RADIUS, y + RADIUS, width + RADIUS, y + RADIUS); |
351 } else | 351 } else |
352 cstate = state; | 352 cstate = state; |
353 | 353 |
354 gdk_draw_arc(curve->pixmap, style->fg_gc[cstate], TRUE, | 354 gdk_draw_arc(curve->pixmap, style->fg_gc[cstate], TRUE, |
355 x, y, RADIUS2, RADIUS2, 0, 360 * 64); | 355 x, y, RADIUS2, RADIUS2, 0, 360 * 64); |
356 } | 356 } |
357 | 357 |
358 /* Draw pixmap in the widget */ | 358 /* Draw pixmap in the widget */ |
359 gdk_draw_pixmap(GTK_WIDGET(curve)->window, | 359 gdk_draw_pixmap(GTK_WIDGET(curve)->window, |
360 style->fg_gc[state], curve->pixmap, | 360 style->fg_gc[state], curve->pixmap, |
361 0, 0, 0, 0, | 361 0, 0, 0, 0, |
362 width + RADIUS2, | 362 width + RADIUS2, |
363 height + RADIUS2); | 363 height + RADIUS2); |
364 } | 364 } |
365 | 365 |
366 | 366 |
367 static gint xs_curve_graph_events(GtkWidget *widget, GdkEvent *event, XSCurve *curve) | 367 static gint xs_curve_graph_events(GtkWidget *widget, GdkEvent *event, XSCurve *curve) |
368 { | 368 { |
369 GdkCursorType new_type = curve->cursor_type; | 369 GdkCursorType new_type = curve->cursor_type; |
370 GdkEventButton *bevent; | 370 GdkEventButton *bevent; |
371 GtkWidget *w; | 371 GtkWidget *w; |
372 gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x; | 372 gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x; |
373 guint distance; | 373 guint distance; |
374 | 374 |
375 w = GTK_WIDGET(curve); | 375 w = GTK_WIDGET(curve); |
376 width = w->allocation.width - RADIUS2; | 376 width = w->allocation.width - RADIUS2; |
377 height = w->allocation.height - RADIUS2; | 377 height = w->allocation.height - RADIUS2; |
378 | 378 |
379 if ((width < 0) || (height < 0)) | 379 if ((width < 0) || (height < 0)) |
380 return FALSE; | 380 return FALSE; |
381 | 381 |
382 /* get the pointer position */ | 382 /* get the pointer position */ |
383 gdk_window_get_pointer(w->window, &tx, &ty, NULL); | 383 gdk_window_get_pointer(w->window, &tx, &ty, NULL); |
384 x = CLAMP((tx - RADIUS), 0, width - 1); | 384 x = CLAMP((tx - RADIUS), 0, width - 1); |
385 y = CLAMP((ty - RADIUS), 0, height - 1); | 385 y = CLAMP((ty - RADIUS), 0, height - 1); |
386 min_x = curve->min_x; | 386 min_x = curve->min_x; |
387 | 387 |
388 distance = ~0U; | 388 distance = ~0U; |
389 for (i = 0; i < curve->nctlpoints; ++i) { | 389 for (i = 0; i < curve->nctlpoints; ++i) { |
390 cx = xs_project(GET_X(i), min_x, curve->max_x, width); | 390 cx = xs_project(GET_X(i), min_x, curve->max_x, width); |
391 if ((guint) abs(x - cx) < distance) { | 391 if ((guint) abs(x - cx) < distance) { |
392 distance = abs(x - cx); | 392 distance = abs(x - cx); |
393 closest_point = i; | 393 closest_point = i; |
394 } | 394 } |
395 } | 395 } |
396 | 396 |
397 /* Act based on event type */ | 397 /* Act based on event type */ |
398 switch (event->type) { | 398 switch (event->type) { |
399 case GDK_CONFIGURE: | 399 case GDK_CONFIGURE: |
400 if (curve->pixmap) | 400 if (curve->pixmap) |
401 gdk_pixmap_unref(curve->pixmap); | 401 gdk_pixmap_unref(curve->pixmap); |
402 curve->pixmap = 0; | 402 curve->pixmap = 0; |
403 | 403 |
404 /* fall through */ | 404 /* fall through */ |
405 | 405 |
406 case GDK_EXPOSE: | 406 case GDK_EXPOSE: |
407 if (!curve->pixmap) { | 407 if (!curve->pixmap) { |
408 curve->pixmap = gdk_pixmap_new(w->window, | 408 curve->pixmap = gdk_pixmap_new(w->window, |
409 w->allocation.width, w->allocation.height, -1); | 409 w->allocation.width, w->allocation.height, -1); |
410 } | 410 } |
411 xs_curve_draw(curve, width, height); | 411 xs_curve_draw(curve, width, height); |
412 break; | 412 break; |
413 | 413 |
414 case GDK_BUTTON_PRESS: | 414 case GDK_BUTTON_PRESS: |
415 gtk_grab_add(widget); | 415 gtk_grab_add(widget); |
416 | 416 |
417 bevent = (GdkEventButton *) event; | 417 bevent = (GdkEventButton *) event; |
418 new_type = GDK_TCROSS; | 418 new_type = GDK_TCROSS; |
419 | 419 |
420 if (distance > MIN_DISTANCE) { | 420 if (distance > MIN_DISTANCE) { |
421 /* insert a new control point */ | 421 /* insert a new control point */ |
422 if (curve->nctlpoints > 0) { | 422 if (curve->nctlpoints > 0) { |
423 cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width); | 423 cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width); |
424 if (x > cx) closest_point++; | 424 if (x > cx) closest_point++; |
425 } | 425 } |
426 | 426 |
427 curve->nctlpoints++; | 427 curve->nctlpoints++; |
428 | 428 |
429 curve->ctlpoints = g_realloc(curve->ctlpoints, | 429 curve->ctlpoints = g_realloc(curve->ctlpoints, |
430 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 430 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
431 | 431 |
432 for (i = curve->nctlpoints - 1; i > closest_point; --i) { | 432 for (i = curve->nctlpoints - 1; i > closest_point; --i) { |
433 memcpy(curve->ctlpoints + i, | 433 memcpy(curve->ctlpoints + i, |
434 curve->ctlpoints + i - 1, | 434 curve->ctlpoints + i - 1, |
435 sizeof(*curve->ctlpoints)); | 435 sizeof(*curve->ctlpoints)); |
436 } | 436 } |
437 } | 437 } |
438 | 438 |
439 curve->grab_point = closest_point; | 439 curve->grab_point = closest_point; |
440 GET_X(curve->grab_point) = xs_unproject(x, min_x, curve->max_x, width); | 440 GET_X(curve->grab_point) = xs_unproject(x, min_x, curve->max_x, width); |
441 GET_Y(curve->grab_point) = xs_unproject(y, curve->min_y, curve->max_y, height); | 441 GET_Y(curve->grab_point) = xs_unproject(y, curve->min_y, curve->max_y, height); |
442 | 442 |
443 xs_curve_draw(curve, width, height); | 443 xs_curve_draw(curve, width, height); |
444 break; | 444 break; |
445 | 445 |
446 case GDK_BUTTON_RELEASE: | 446 case GDK_BUTTON_RELEASE: |
447 { | 447 { |
448 gint src, dst; | 448 gint src, dst; |
449 | 449 |
450 gtk_grab_remove(widget); | 450 gtk_grab_remove(widget); |
451 | 451 |
452 /* delete inactive points: */ | 452 /* delete inactive points: */ |
453 for (src = dst = 0; src < curve->nctlpoints; ++src) { | 453 for (src = dst = 0; src < curve->nctlpoints; ++src) { |
454 if (GET_X(src) >= min_x) { | 454 if (GET_X(src) >= min_x) { |
455 memcpy(curve->ctlpoints + dst, | 455 memcpy(curve->ctlpoints + dst, |
456 curve->ctlpoints + src, | 456 curve->ctlpoints + src, |
457 sizeof(*curve->ctlpoints)); | 457 sizeof(*curve->ctlpoints)); |
458 dst++; | 458 dst++; |
459 } | 459 } |
460 } | 460 } |
461 | 461 |
462 if (dst < src) { | 462 if (dst < src) { |
463 curve->nctlpoints -= (src - dst); | 463 curve->nctlpoints -= (src - dst); |
464 if (curve->nctlpoints <= 0) { | 464 if (curve->nctlpoints <= 0) { |
465 curve->nctlpoints = 1; | 465 curve->nctlpoints = 1; |
466 GET_X(0) = min_x; | 466 GET_X(0) = min_x; |
467 GET_Y(0) = curve->min_y; | 467 GET_Y(0) = curve->min_y; |
468 xs_curve_draw(curve, width, height); | 468 xs_curve_draw(curve, width, height); |
469 } | 469 } |
470 curve->ctlpoints = g_realloc(curve->ctlpoints, | 470 curve->ctlpoints = g_realloc(curve->ctlpoints, |
471 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 471 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
472 } | 472 } |
473 | 473 |
474 new_type = GDK_FLEUR; | 474 new_type = GDK_FLEUR; |
475 curve->grab_point = -1; | 475 curve->grab_point = -1; |
476 } | 476 } |
477 xs_curve_draw(curve, width, height); | 477 xs_curve_draw(curve, width, height); |
478 break; | 478 break; |
479 | 479 |
480 case GDK_MOTION_NOTIFY: | 480 case GDK_MOTION_NOTIFY: |
481 if (curve->grab_point == -1) { | 481 if (curve->grab_point == -1) { |
482 /* if no point is grabbed... */ | 482 /* if no point is grabbed... */ |
483 if (distance <= MIN_DISTANCE) | 483 if (distance <= MIN_DISTANCE) |
484 new_type = GDK_FLEUR; | 484 new_type = GDK_FLEUR; |
485 else | 485 else |
486 new_type = GDK_TCROSS; | 486 new_type = GDK_TCROSS; |
487 } else { | 487 } else { |
488 gint leftbound, rightbound; | 488 gint leftbound, rightbound; |
489 | 489 |
490 /* drag the grabbed point */ | 490 /* drag the grabbed point */ |
491 new_type = GDK_TCROSS; | 491 new_type = GDK_TCROSS; |
492 | 492 |
493 leftbound = -MIN_DISTANCE; | 493 leftbound = -MIN_DISTANCE; |
494 if (curve->grab_point > 0) { | 494 if (curve->grab_point > 0) { |
495 leftbound = xs_project( | 495 leftbound = xs_project( |
496 GET_X(curve->grab_point-1), | 496 GET_X(curve->grab_point-1), |
497 min_x, curve->max_x, width); | 497 min_x, curve->max_x, width); |
498 } | 498 } |
499 | 499 |
500 rightbound = width + RADIUS2 + MIN_DISTANCE; | 500 rightbound = width + RADIUS2 + MIN_DISTANCE; |
501 if (curve->grab_point + 1 < curve->nctlpoints) { | 501 if (curve->grab_point + 1 < curve->nctlpoints) { |
502 rightbound = xs_project( | 502 rightbound = xs_project( |
503 GET_X(curve->grab_point+1), | 503 GET_X(curve->grab_point+1), |
504 min_x, curve->max_x, width); | 504 min_x, curve->max_x, width); |
505 } | 505 } |
506 | 506 |
507 if ((tx <= leftbound) || (tx >= rightbound) || | 507 if ((tx <= leftbound) || (tx >= rightbound) || |
508 (ty > height + RADIUS2 + MIN_DISTANCE) || (ty < -MIN_DISTANCE)) { | 508 (ty > height + RADIUS2 + MIN_DISTANCE) || (ty < -MIN_DISTANCE)) { |
509 GET_X(curve->grab_point) = min_x - 1.0; | 509 GET_X(curve->grab_point) = min_x - 1.0; |
510 } else { | 510 } else { |
511 GET_X(curve->grab_point) = | 511 GET_X(curve->grab_point) = |
512 xs_unproject(x, min_x, curve->max_x, width); | 512 xs_unproject(x, min_x, curve->max_x, width); |
513 GET_Y(curve->grab_point) = | 513 GET_Y(curve->grab_point) = |
514 xs_unproject(y, curve->min_y, curve->max_y, height); | 514 xs_unproject(y, curve->min_y, curve->max_y, height); |
515 } | 515 } |
516 | 516 |
517 xs_curve_draw(curve, width, height); | 517 xs_curve_draw(curve, width, height); |
518 } | 518 } |
519 | 519 |
520 /* See if cursor type was changed and update accordingly */ | 520 /* See if cursor type was changed and update accordingly */ |
521 if (new_type != (GdkCursorType) curve->cursor_type) { | 521 if (new_type != (GdkCursorType) curve->cursor_type) { |
522 GdkCursor *cursor; | 522 GdkCursor *cursor; |
523 curve->cursor_type = new_type; | 523 curve->cursor_type = new_type; |
524 cursor = gdk_cursor_new(curve->cursor_type); | 524 cursor = gdk_cursor_new(curve->cursor_type); |
525 gdk_window_set_cursor(w->window, cursor); | 525 gdk_window_set_cursor(w->window, cursor); |
526 gdk_cursor_destroy(cursor); | 526 gdk_cursor_destroy(cursor); |
527 } | 527 } |
528 break; | 528 break; |
529 | 529 |
530 default: | 530 default: |
531 break; | 531 break; |
532 } | 532 } |
533 | 533 |
534 return FALSE; | 534 return FALSE; |
535 } | 535 } |
536 | 536 |
537 | 537 |
538 static void xs_curve_size_graph(XSCurve *curve) | 538 static void xs_curve_size_graph(XSCurve *curve) |
539 { | 539 { |
540 gint width, height; | 540 gint width, height; |
541 gfloat aspect; | 541 gfloat aspect; |
542 GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(curve)); | 542 GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(curve)); |
543 | 543 |
544 width = (curve->max_x - curve->min_x) + 1; | 544 width = (curve->max_x - curve->min_x) + 1; |
545 height = (curve->max_y - curve->min_y) + 1; | 545 height = (curve->max_y - curve->min_y) + 1; |
546 aspect = width / (gfloat) height; | 546 aspect = width / (gfloat) height; |
547 | 547 |
548 if (width > gdk_screen_get_width(screen) / 4) | 548 if (width > gdk_screen_get_width(screen) / 4) |
549 width = gdk_screen_get_width(screen) / 4; | 549 width = gdk_screen_get_width(screen) / 4; |
550 | 550 |
551 if (height > gdk_screen_get_height(screen) / 4) | 551 if (height > gdk_screen_get_height(screen) / 4) |
552 height = gdk_screen_get_height(screen) / 4; | 552 height = gdk_screen_get_height(screen) / 4; |
553 | 553 |
554 if (aspect < 1.0) | 554 if (aspect < 1.0) |
555 width = height * aspect; | 555 width = height * aspect; |
556 else | 556 else |
557 height = width / aspect; | 557 height = width / aspect; |
558 | 558 |
559 gtk_widget_set_size_request(GTK_WIDGET(curve), width + RADIUS2, height + RADIUS2); | 559 gtk_widget_set_size_request(GTK_WIDGET(curve), width + RADIUS2, height + RADIUS2); |
560 } | 560 } |
561 | 561 |
562 | 562 |
563 static void xs_curve_update(XSCurve *curve) | 563 static void xs_curve_update(XSCurve *curve) |
564 { | 564 { |
565 if (curve->pixmap) { | 565 if (curve->pixmap) { |
566 gint width, height; | 566 gint width, height; |
567 | 567 |
568 width = GTK_WIDGET(curve)->allocation.width - RADIUS2; | 568 width = GTK_WIDGET(curve)->allocation.width - RADIUS2; |
569 height = GTK_WIDGET(curve)->allocation.height - RADIUS2; | 569 height = GTK_WIDGET(curve)->allocation.height - RADIUS2; |
570 xs_curve_draw(curve, width, height); | 570 xs_curve_draw(curve, width, height); |
571 } | 571 } |
572 } | 572 } |
573 | 573 |
574 | 574 |
575 void xs_curve_reset(XSCurve *curve) | 575 void xs_curve_reset(XSCurve *curve) |
576 { | 576 { |
577 if (curve->ctlpoints) | 577 if (curve->ctlpoints) |
578 g_free(curve->ctlpoints); | 578 g_free(curve->ctlpoints); |
579 | 579 |
580 curve->nctlpoints = 4; | 580 curve->nctlpoints = 4; |
581 curve->ctlpoints = g_malloc(curve->nctlpoints * sizeof(curve->ctlpoints[0])); | 581 curve->ctlpoints = g_malloc(curve->nctlpoints * sizeof(curve->ctlpoints[0])); |
582 | 582 |
583 GET_X(0) = curve->min_x; | 583 GET_X(0) = curve->min_x; |
584 GET_Y(0) = curve->min_y; | 584 GET_Y(0) = curve->min_y; |
585 GET_X(1) = curve->min_x; | 585 GET_X(1) = curve->min_x; |
586 GET_Y(1) = curve->min_y; | 586 GET_Y(1) = curve->min_y; |
587 | 587 |
588 GET_X(2) = curve->max_x; | 588 GET_X(2) = curve->max_x; |
589 GET_Y(2) = curve->max_y; | 589 GET_Y(2) = curve->max_y; |
590 GET_X(3) = curve->max_x; | 590 GET_X(3) = curve->max_x; |
591 GET_Y(3) = curve->max_y; | 591 GET_Y(3) = curve->max_y; |
592 | 592 |
593 xs_curve_update(curve); | 593 xs_curve_update(curve); |
594 } | 594 } |
595 | 595 |
596 | 596 |
597 void xs_curve_set_range(XSCurve *curve, gfloat min_x, gfloat min_y, gfloat max_x, gfloat max_y) | 597 void xs_curve_set_range(XSCurve *curve, gfloat min_x, gfloat min_y, gfloat max_x, gfloat max_y) |
598 { | 598 { |
599 g_object_freeze_notify(G_OBJECT(curve)); | 599 g_object_freeze_notify(G_OBJECT(curve)); |
600 if (curve->min_x != min_x) { | 600 if (curve->min_x != min_x) { |
601 curve->min_x = min_x; | 601 curve->min_x = min_x; |
602 g_object_notify(G_OBJECT(curve), "min-x"); | 602 g_object_notify(G_OBJECT(curve), "min-x"); |
603 } | 603 } |
604 if (curve->max_x != max_x) { | 604 if (curve->max_x != max_x) { |
605 curve->max_x = max_x; | 605 curve->max_x = max_x; |
606 g_object_notify(G_OBJECT(curve), "max-x"); | 606 g_object_notify(G_OBJECT(curve), "max-x"); |
607 } | 607 } |
608 if (curve->min_y != min_y) { | 608 if (curve->min_y != min_y) { |
609 curve->min_y = min_y; | 609 curve->min_y = min_y; |
610 g_object_notify(G_OBJECT(curve), "min-y"); | 610 g_object_notify(G_OBJECT(curve), "min-y"); |
611 } | 611 } |
612 if (curve->max_y != max_y) { | 612 if (curve->max_y != max_y) { |
613 curve->max_y = max_y; | 613 curve->max_y = max_y; |
614 g_object_notify(G_OBJECT(curve), "max-y"); | 614 g_object_notify(G_OBJECT(curve), "max-y"); |
615 } | 615 } |
616 g_object_thaw_notify(G_OBJECT(curve)); | 616 g_object_thaw_notify(G_OBJECT(curve)); |
617 | 617 |
618 xs_curve_size_graph(curve); | 618 xs_curve_size_graph(curve); |
619 xs_curve_reset(curve); | 619 xs_curve_reset(curve); |
620 } | 620 } |
621 | 621 |
622 | 622 |
623 gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints) | 623 gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints) |
624 { | 624 { |
625 if (npoints != curve->nctlpoints) { | 625 if (npoints != curve->nctlpoints) { |
626 curve->nctlpoints = npoints; | 626 curve->nctlpoints = npoints; |
627 curve->ctlpoints = (t_xs_point *) g_realloc(curve->ctlpoints, | 627 curve->ctlpoints = (t_xs_point *) g_realloc(curve->ctlpoints, |
628 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 628 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
629 | 629 |
630 if (curve->ctlpoints == NULL) | 630 if (curve->ctlpoints == NULL) |
631 return FALSE; | 631 return FALSE; |
632 } | 632 } |
633 | 633 |
634 return TRUE; | 634 return TRUE; |
635 } | 635 } |
636 | 636 |
637 | 637 |
638 void xs_curve_get_data(XSCurve *curve, t_xs_point ***points, gint **npoints) | 638 void xs_curve_get_data(XSCurve *curve, t_xs_point ***points, gint **npoints) |
639 { | 639 { |
640 *points = &(curve->ctlpoints); | 640 *points = &(curve->ctlpoints); |
641 *npoints = &(curve->nctlpoints); | 641 *npoints = &(curve->nctlpoints); |
642 } | 642 } |
643 | 643 |
644 | 644 |
645 gboolean xs_curve_set_points(XSCurve *curve, t_xs_int_point *points, gint npoints) | 645 gboolean xs_curve_set_points(XSCurve *curve, t_xs_int_point *points, gint npoints) |
646 { | 646 { |
647 gint i; | 647 gint i; |
648 | 648 |
649 if (!xs_curve_realloc_data(curve, npoints + 4)) | 649 if (!xs_curve_realloc_data(curve, npoints + 4)) |
650 return FALSE; | 650 return FALSE; |
651 | 651 |
652 GET_X(0) = curve->min_x; | 652 GET_X(0) = curve->min_x; |
653 GET_Y(0) = curve->min_y; | 653 GET_Y(0) = curve->min_y; |
654 GET_X(1) = curve->min_x; | 654 GET_X(1) = curve->min_x; |
655 GET_Y(1) = curve->min_y; | 655 GET_Y(1) = curve->min_y; |
656 | 656 |
657 for (i = 0; i < npoints; i++) { | 657 for (i = 0; i < npoints; i++) { |
658 GET_X(i+2) = points[i].x; | 658 GET_X(i+2) = points[i].x; |
659 GET_Y(i+2) = points[i].y; | 659 GET_Y(i+2) = points[i].y; |
660 } | 660 } |
661 | 661 |
662 GET_X(npoints+2) = curve->max_x; | 662 GET_X(npoints+2) = curve->max_x; |
663 GET_Y(npoints+2) = curve->max_y; | 663 GET_Y(npoints+2) = curve->max_y; |
664 GET_X(npoints+3) = curve->max_x; | 664 GET_X(npoints+3) = curve->max_x; |
665 GET_Y(npoints+3) = curve->max_y; | 665 GET_Y(npoints+3) = curve->max_y; |
666 | 666 |
667 xs_curve_update(curve); | 667 xs_curve_update(curve); |
668 return TRUE; | 668 return TRUE; |
669 } | 669 } |
670 | 670 |
671 | 671 |
672 gboolean xs_curve_get_points(XSCurve *curve, t_xs_int_point **points, gint *npoints) | 672 gboolean xs_curve_get_points(XSCurve *curve, t_xs_int_point **points, gint *npoints) |
673 { | 673 { |
674 gint i, n; | 674 gint i, n; |
675 | 675 |
676 n = curve->nctlpoints - 4; | 676 n = curve->nctlpoints - 4; |
677 | 677 |
678 *points = g_malloc(n * sizeof(t_xs_int_point)); | 678 *points = g_malloc(n * sizeof(t_xs_int_point)); |
679 if (*points == NULL) | 679 if (*points == NULL) |
680 return FALSE; | 680 return FALSE; |
681 | 681 |
682 *npoints = n; | 682 *npoints = n; |
683 for (i = 2; i < curve->nctlpoints - 2; i++) { | 683 for (i = 2; i < curve->nctlpoints - 2; i++) { |
684 (*points)[i].x = GET_X(i); | 684 (*points)[i].x = GET_X(i); |
685 (*points)[i].y = GET_Y(i); | 685 (*points)[i].y = GET_Y(i); |
686 } | 686 } |
687 | 687 |
688 return TRUE; | 688 return TRUE; |
689 } | 689 } |
690 | 690 |
691 | 691 |
692 GtkWidget *xs_curve_new(void) | 692 GtkWidget *xs_curve_new(void) |
693 { | 693 { |
694 return g_object_new(XS_TYPE_CURVE, NULL); | 694 return g_object_new(XS_TYPE_CURVE, NULL); |
695 } | 695 } |
696 | 696 |
697 | 697 |
698 static void xs_curve_finalize(GObject *object) | 698 static void xs_curve_finalize(GObject *object) |
699 { | 699 { |
700 XSCurve *curve; | 700 XSCurve *curve; |
701 | 701 |
702 g_return_if_fail(object != NULL); | 702 g_return_if_fail(object != NULL); |
703 g_return_if_fail(XS_IS_CURVE(object)); | 703 g_return_if_fail(XS_IS_CURVE(object)); |
704 | 704 |
705 curve = XS_CURVE(object); | 705 curve = XS_CURVE(object); |
706 if (curve->pixmap) | 706 if (curve->pixmap) |
707 g_object_unref(curve->pixmap); | 707 g_object_unref(curve->pixmap); |
708 if (curve->ctlpoints) | 708 if (curve->ctlpoints) |
709 g_free(curve->ctlpoints); | 709 g_free(curve->ctlpoints); |
710 | 710 |
711 G_OBJECT_CLASS(parent_class)->finalize(object); | 711 G_OBJECT_CLASS(parent_class)->finalize(object); |
712 } | 712 } |