1 /*
2 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
3 * All rights reserved.
4 *
5 * This file is part of the Gnome Library.
6 *
7 * The Gnome Library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * The Gnome Library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with the Gnome Library; see the file COPYING.LIB. If not,
19 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22 /*
23 @NOTATION@
24 */
25 /* Rectangle and ellipse item types for GnomeCanvas widget
26 *
27 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
28 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
29 *
30 *
31 * Authors: Federico Mena <federico@nuclecu.unam.mx>
32 * Rusty Conover <rconover@bangtail.net>
33 */
34
35 #include <config.h>
36 #include <math.h>
37 #include "gnome-canvas-rect-ellipse.h"
38 #include "gnome-canvas-util.h"
39 #include "gnome-canvas-shape.h"
40
41
42 #include "libart_lgpl/art_vpath.h"
43 #include "libart_lgpl/art_svp.h"
44 #include "libart_lgpl/art_svp_vpath.h"
45 #include "libart_lgpl/art_rgb_svp.h"
46
47 /* Base class for rectangle and ellipse item types */
48
49 #define noVERBOSE
50
51 enum {
52 PROP_0,
53 PROP_X1,
54 PROP_Y1,
55 PROP_X2,
56 PROP_Y2
57 };
58
59
60 static void gnome_canvas_re_class_init (GnomeCanvasREClass *class);
61 static void gnome_canvas_re_init (GnomeCanvasRE *re);
62 static void gnome_canvas_re_destroy (GtkObject *object);
63 static void gnome_canvas_re_set_property (GObject *object,
64 guint param_id,
65 const GValue *value,
66 GParamSpec *pspec);
67 static void gnome_canvas_re_get_property (GObject *object,
68 guint param_id,
69 GValue *value,
70 GParamSpec *pspec);
71
72 static void gnome_canvas_rect_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
73 static void gnome_canvas_ellipse_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
74
75 static GnomeCanvasItemClass *re_parent_class;
76
77
78 GType
gnome_canvas_re_get_type(void)79 gnome_canvas_re_get_type (void)
80 {
81 static GType re_type;
82
83 if (!re_type) {
84 const GTypeInfo object_info = {
85 sizeof (GnomeCanvasREClass),
86 (GBaseInitFunc) NULL,
87 (GBaseFinalizeFunc) NULL,
88 (GClassInitFunc) gnome_canvas_re_class_init,
89 (GClassFinalizeFunc) NULL,
90 NULL, /* class_data */
91 sizeof (GnomeCanvasRE),
92 0, /* n_preallocs */
93 (GInstanceInitFunc) gnome_canvas_re_init,
94 NULL /* value_table */
95 };
96
97 re_type = g_type_register_static (GNOME_TYPE_CANVAS_SHAPE, "GnomeCanvasRE",
98 &object_info, 0);
99 }
100
101 return re_type;
102 }
103
104 static void
gnome_canvas_re_class_init(GnomeCanvasREClass * class)105 gnome_canvas_re_class_init (GnomeCanvasREClass *class)
106 {
107 GObjectClass *gobject_class;
108 GtkObjectClass *object_class;
109
110 gobject_class = (GObjectClass *) class;
111 object_class = (GtkObjectClass *) class;
112
113 re_parent_class = g_type_class_peek_parent (class);
114
115 gobject_class->set_property = gnome_canvas_re_set_property;
116 gobject_class->get_property = gnome_canvas_re_get_property;
117
118 g_object_class_install_property
119 (gobject_class,
120 PROP_X1,
121 g_param_spec_double ("x1", NULL, NULL,
122 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
123 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
124 g_object_class_install_property
125 (gobject_class,
126 PROP_Y1,
127 g_param_spec_double ("y1", NULL, NULL,
128 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
129 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
130 g_object_class_install_property
131 (gobject_class,
132 PROP_X2,
133 g_param_spec_double ("x2", NULL, NULL,
134 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
135 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
136 g_object_class_install_property
137 (gobject_class,
138 PROP_Y2,
139 g_param_spec_double ("y2", NULL, NULL,
140 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
141 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
142
143 object_class->destroy = gnome_canvas_re_destroy;
144 }
145
146 static void
gnome_canvas_re_init(GnomeCanvasRE * re)147 gnome_canvas_re_init (GnomeCanvasRE *re)
148 {
149 re->x1 = 0.0;
150 re->y1 = 0.0;
151 re->x2 = 0.0;
152 re->y2 = 0.0;
153 re->path_dirty = 0;
154 }
155
156 static void
gnome_canvas_re_destroy(GtkObject * object)157 gnome_canvas_re_destroy (GtkObject *object)
158 {
159 g_return_if_fail (object != NULL);
160 g_return_if_fail (GNOME_IS_CANVAS_RE (object));
161
162 if (GTK_OBJECT_CLASS (re_parent_class)->destroy)
163 (* GTK_OBJECT_CLASS (re_parent_class)->destroy) (object);
164 }
165
166 static void
gnome_canvas_re_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)167 gnome_canvas_re_set_property (GObject *object,
168 guint param_id,
169 const GValue *value,
170 GParamSpec *pspec)
171 {
172 GnomeCanvasItem *item;
173 GnomeCanvasRE *re;
174
175 g_return_if_fail (object != NULL);
176 g_return_if_fail (GNOME_IS_CANVAS_RE (object));
177
178 item = GNOME_CANVAS_ITEM (object);
179 re = GNOME_CANVAS_RE (object);
180
181 switch (param_id) {
182 case PROP_X1:
183 re->x1 = g_value_get_double (value);
184 re->path_dirty = 1;
185 gnome_canvas_item_request_update (item);
186 break;
187
188 case PROP_Y1:
189 re->y1 = g_value_get_double (value);
190 re->path_dirty = 1;
191 gnome_canvas_item_request_update (item);
192 break;
193
194 case PROP_X2:
195 re->x2 = g_value_get_double (value);
196 re->path_dirty = 1;
197 gnome_canvas_item_request_update (item);
198 break;
199
200 case PROP_Y2:
201 re->y2 = g_value_get_double (value);
202 re->path_dirty = 1;
203 gnome_canvas_item_request_update (item);
204 break;
205
206 default:
207 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
208 break;
209 }
210 }
211
212 static void
gnome_canvas_re_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)213 gnome_canvas_re_get_property (GObject *object,
214 guint param_id,
215 GValue *value,
216 GParamSpec *pspec)
217 {
218 GnomeCanvasRE *re;
219
220 g_return_if_fail (object != NULL);
221 g_return_if_fail (GNOME_IS_CANVAS_RE (object));
222
223 re = GNOME_CANVAS_RE (object);
224
225 switch (param_id) {
226 case PROP_X1:
227 g_value_set_double (value, re->x1);
228 break;
229
230 case PROP_Y1:
231 g_value_set_double (value, re->y1);
232 break;
233
234 case PROP_X2:
235 g_value_set_double (value, re->x2);
236 break;
237
238 case PROP_Y2:
239 g_value_set_double (value, re->y2);
240 break;
241
242 default:
243 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
244 break;
245 }
246 }
247
248 /* Rectangle item */
249 static void gnome_canvas_rect_class_init (GnomeCanvasRectClass *class);
250
251
252
253 GType
gnome_canvas_rect_get_type(void)254 gnome_canvas_rect_get_type (void)
255 {
256 static GType rect_type;
257
258 if (!rect_type) {
259 const GTypeInfo object_info = {
260 sizeof (GnomeCanvasRectClass),
261 (GBaseInitFunc) NULL,
262 (GBaseFinalizeFunc) NULL,
263 (GClassInitFunc) gnome_canvas_rect_class_init,
264 (GClassFinalizeFunc) NULL,
265 NULL, /* class_data */
266 sizeof (GnomeCanvasRect),
267 0, /* n_preallocs */
268 (GInstanceInitFunc) NULL,
269 NULL /* value_table */
270 };
271
272 rect_type = g_type_register_static (GNOME_TYPE_CANVAS_RE, "GnomeCanvasRect",
273 &object_info, 0);
274 }
275
276 return rect_type;
277 }
278
279 static void
gnome_canvas_rect_class_init(GnomeCanvasRectClass * class)280 gnome_canvas_rect_class_init (GnomeCanvasRectClass *class)
281 {
282 GnomeCanvasItemClass *item_class;
283
284 item_class = (GnomeCanvasItemClass *) class;
285
286 item_class->update = gnome_canvas_rect_update;
287 }
288
289 static void
gnome_canvas_rect_update(GnomeCanvasItem * item,double affine[6],ArtSVP * clip_path,gint flags)290 gnome_canvas_rect_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gint flags)
291 { GnomeCanvasRE *re;
292
293 GnomeCanvasPathDef *path_def;
294
295 re = GNOME_CANVAS_RE(item);
296
297 if (re->path_dirty) {
298 path_def = gnome_canvas_path_def_new ();
299
300 gnome_canvas_path_def_moveto(path_def, re->x1, re->y1);
301 gnome_canvas_path_def_lineto(path_def, re->x2, re->y1);
302 gnome_canvas_path_def_lineto(path_def, re->x2, re->y2);
303 gnome_canvas_path_def_lineto(path_def, re->x1, re->y2);
304 gnome_canvas_path_def_lineto(path_def, re->x1, re->y1);
305 gnome_canvas_path_def_closepath_current(path_def);
306 gnome_canvas_shape_set_path_def (GNOME_CANVAS_SHAPE (item), path_def);
307 gnome_canvas_path_def_unref(path_def);
308 re->path_dirty = 0;
309 }
310
311 if (re_parent_class->update)
312 (* re_parent_class->update) (item, affine, clip_path, flags);
313 }
314
315 /* Ellipse item */
316
317
318 static void gnome_canvas_ellipse_class_init (GnomeCanvasEllipseClass *class);
319
320
321 GType
gnome_canvas_ellipse_get_type(void)322 gnome_canvas_ellipse_get_type (void)
323 {
324 static GType ellipse_type;
325
326 if (!ellipse_type) {
327 const GTypeInfo object_info = {
328 sizeof (GnomeCanvasEllipseClass),
329 (GBaseInitFunc) NULL,
330 (GBaseFinalizeFunc) NULL,
331 (GClassInitFunc) gnome_canvas_ellipse_class_init,
332 (GClassFinalizeFunc) NULL,
333 NULL, /* class_data */
334 sizeof (GnomeCanvasEllipse),
335 0, /* n_preallocs */
336 (GInstanceInitFunc) NULL,
337 NULL /* value_table */
338 };
339
340 ellipse_type = g_type_register_static (GNOME_TYPE_CANVAS_RE, "GnomeCanvasEllipse",
341 &object_info, 0);
342 }
343
344 return ellipse_type;
345 }
346
347 static void
gnome_canvas_ellipse_class_init(GnomeCanvasEllipseClass * class)348 gnome_canvas_ellipse_class_init (GnomeCanvasEllipseClass *class)
349 {
350 GnomeCanvasItemClass *item_class;
351
352 item_class = (GnomeCanvasItemClass *) class;
353
354 item_class->update = gnome_canvas_ellipse_update;
355 }
356
357 #define N_PTS 90
358
359 static void
gnome_canvas_ellipse_update(GnomeCanvasItem * item,double affine[6],ArtSVP * clip_path,gint flags)360 gnome_canvas_ellipse_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gint flags) {
361 GnomeCanvasPathDef *path_def;
362 GnomeCanvasRE *re;
363
364 re = GNOME_CANVAS_RE(item);
365
366 if (re->path_dirty) {
367 gdouble cx, cy, rx, ry;
368 gdouble beta = 0.26521648983954400922; /* 4*(1-cos(pi/8))/(3*sin(pi/8)) */
369 gdouble sincosA = 0.70710678118654752440; /* sin (pi/4), cos (pi/4) */
370 gdouble dx1, dy1, dx2, dy2;
371 gdouble mx, my;
372
373 path_def = gnome_canvas_path_def_new();
374
375 cx = (re->x2 + re->x1) * 0.5;
376 cy = (re->y2 + re->y1) * 0.5;
377 rx = re->x2 - cx;
378 ry = re->y2 - cy;
379
380 dx1 = beta * rx;
381 dy1 = beta * ry;
382 dx2 = beta * rx * sincosA;
383 dy2 = beta * ry * sincosA;
384 mx = rx * sincosA;
385 my = ry * sincosA;
386
387 gnome_canvas_path_def_moveto (path_def, cx + rx, cy);
388 gnome_canvas_path_def_curveto (path_def,
389 cx + rx, cy - dy1,
390 cx + mx + dx2, cy - my + dy2,
391 cx + mx, cy - my);
392 gnome_canvas_path_def_curveto (path_def,
393 cx + mx - dx2, cy - my - dy2,
394 cx + dx1, cy - ry,
395 cx, cy - ry);
396 gnome_canvas_path_def_curveto (path_def,
397 cx - dx1, cy - ry,
398 cx - mx + dx2, cy - my - dy2,
399 cx - mx, cy - my);
400 gnome_canvas_path_def_curveto (path_def,
401 cx - mx - dx2, cy - my + dy2,
402 cx - rx, cy - dy1,
403 cx - rx, cy);
404
405 gnome_canvas_path_def_curveto (path_def,
406 cx - rx, cy + dy1,
407 cx - mx - dx2, cy + my - dy2,
408 cx - mx, cy + my);
409 gnome_canvas_path_def_curveto (path_def,
410 cx - mx + dx2, cy + my + dy2,
411 cx - dx1, cy + ry,
412 cx, cy + ry);
413 gnome_canvas_path_def_curveto (path_def,
414 cx + dx1, cy + ry,
415 cx + mx - dx2, cy + my + dy2,
416 cx + mx, cy + my);
417 gnome_canvas_path_def_curveto (path_def,
418 cx + mx + dx2, cy + my - dy2,
419 cx + rx, cy + dy1,
420 cx + rx, cy);
421
422 gnome_canvas_path_def_closepath_current(path_def);
423
424 gnome_canvas_shape_set_path_def (GNOME_CANVAS_SHAPE (item), path_def);
425 gnome_canvas_path_def_unref(path_def);
426 re->path_dirty = 0;
427 }
428
429 if (re_parent_class->update)
430 (* re_parent_class->update) (item, affine, clip_path, flags);
431 }
432