a4ded6fadcb26ca4b8c56c6d2013faf54557cd68
[ardour.git] / gtk2_ardour / canvas-simplerect.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <libgnomecanvas/libgnomecanvas.h>
4
5 #include "canvas-simplerect.h"
6 #include "rgb_macros.h"
7 #include "gettext.h"
8 #define _(Text)  dgettext (PACKAGE,Text)
9
10 enum {
11         PROP_0,
12         PROP_X1,
13         PROP_Y1,
14         PROP_X2,
15         PROP_Y2,
16         PROP_OUTLINE_PIXELS,
17         PROP_OUTLINE_WHAT,
18         PROP_FILL,
19         PROP_FILL_COLOR_RGBA,
20         PROP_OUTLINE_COLOR_RGBA,
21         PROP_DRAW
22         
23 };
24
25 static void  gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass *class);
26 static void   gnome_canvas_simplerect_init       (GnomeCanvasSimpleRect      *simplerect);
27 static void   gnome_canvas_simplerect_set_property  (GObject        *object,
28                                                      guint            prop_id,
29                                                      const GValue   *value,
30                                                      GParamSpec     *pspec);
31 static void   gnome_canvas_simplerect_get_property  (GObject        *object,
32                                                      guint           prop_id,
33                                                      GValue         *value,
34                                                      GParamSpec     *pspec);
35 static void   gnome_canvas_simplerect_update      (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
36 static void   gnome_canvas_simplerect_bounds      (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
37 static double gnome_canvas_simplerect_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item);
38 static void   gnome_canvas_simplerect_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
39 static void   gnome_canvas_simplerect_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
40
41 static GnomeCanvasItemClass *parent_class;
42
43
44 GtkType
45 gnome_canvas_simplerect_get_type (void)
46 {
47         static GtkType simplerect_type = 0;
48
49         if (!simplerect_type) {
50                 GtkTypeInfo simplerect_info = {
51                         "GnomeCanvasSimpleRect",
52                         sizeof (GnomeCanvasSimpleRect),
53                         sizeof (GnomeCanvasSimpleRectClass),
54                         (GtkClassInitFunc) gnome_canvas_simplerect_class_init,
55                         (GtkObjectInitFunc) gnome_canvas_simplerect_init,
56                         NULL, /* reserved_1 */
57                         NULL, /* reserved_2 */
58                         (GtkClassInitFunc) NULL
59                 };
60
61                 simplerect_type = gtk_type_unique (gnome_canvas_item_get_type (), &simplerect_info);
62         }
63
64         return simplerect_type;
65 }
66
67 static void
68 gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass *class)
69 {
70         GObjectClass *object_class;
71         GnomeCanvasItemClass *item_class;
72
73         object_class = G_OBJECT_CLASS (class);
74         item_class = (GnomeCanvasItemClass *) class;
75
76         parent_class = gtk_type_class (gnome_canvas_item_get_type ());
77
78         object_class->set_property = gnome_canvas_simplerect_set_property;
79         object_class->get_property = gnome_canvas_simplerect_get_property;
80         
81         g_object_class_install_property (object_class,
82                                          PROP_X1,
83                                          g_param_spec_double ("x1",
84                                                               _("x1"),
85                                                               _("x coordinate of upper left corner of rect"),
86                                                               -G_MAXDOUBLE,
87                                                               G_MAXDOUBLE,
88                                                               0.0,
89                                                               G_PARAM_READWRITE));  
90         
91         g_object_class_install_property (object_class,
92                                          PROP_Y1,
93                                          g_param_spec_double ("y1",
94                                                               _("y1"),
95                                                               _("y coordinate of upper left corner of rect "),
96                                                               -G_MAXDOUBLE,
97                                                               G_MAXDOUBLE,
98                                                               0.0,
99                                                               G_PARAM_READWRITE));  
100         
101
102         g_object_class_install_property (object_class,
103                                          PROP_X2,
104                                          g_param_spec_double ("x2",
105                                                               _("x2"),
106                                                               _("x coordinate of lower right corner of rect"),
107                                                               -G_MAXDOUBLE,
108                                                               G_MAXDOUBLE,
109                                                               0.0,
110                                                               G_PARAM_READWRITE));  
111         
112         g_object_class_install_property (object_class,
113                                          PROP_Y2,
114                                          g_param_spec_double ("y2",
115                                                               _("y2"),
116                                                               _("y coordinate of lower right corner of rect "),
117                                                               -G_MAXDOUBLE,
118                                                               G_MAXDOUBLE,
119                                                               0.0,
120                                                               G_PARAM_READWRITE));  
121         
122
123         g_object_class_install_property (object_class,
124                                          PROP_OUTLINE_PIXELS,
125                                          g_param_spec_uint ("outline_pixels",
126                                                               _("outline pixels"),
127                                                               _("width in pixels of outline"),
128                                                               0,
129                                                               G_MAXINT,
130                                                               0,
131                                                               G_PARAM_READWRITE));  
132         
133
134         g_object_class_install_property (object_class,
135                                          PROP_OUTLINE_WHAT,
136                                          g_param_spec_uint ("outline_what",
137                                                               _("outline what"),
138                                                               _("which boundaries to outline (mask)"),
139                                                               0,
140                                                               G_MAXINT,
141                                                               0,
142                                                               G_PARAM_READWRITE));  
143         
144
145
146         g_object_class_install_property (object_class,
147                                          PROP_FILL,
148                                          g_param_spec_boolean ("fill",
149                                                                _("fill"),
150                                                                _("fill rectangle"),
151                                                                TRUE,
152                                                                G_PARAM_READWRITE));  
153         
154         g_object_class_install_property (object_class,
155                                          PROP_DRAW,
156                                          g_param_spec_boolean ("draw",
157                                                                _("draw"),
158                                                                _("draw rectangle"),
159                                                                TRUE,
160                                                                G_PARAM_READWRITE));  
161         
162
163         g_object_class_install_property (object_class,
164                                          PROP_OUTLINE_COLOR_RGBA,
165                                          g_param_spec_uint ("outline_color_rgba",
166                                                               _("outline color rgba"),
167                                                               _("color of outline"),
168                                                               0,
169                                                               G_MAXINT,
170                                                               0,
171                                                               G_PARAM_READWRITE));  
172         
173
174         g_object_class_install_property (object_class,
175                                          PROP_FILL_COLOR_RGBA,
176                                          g_param_spec_uint ("fill_color_rgba",
177                                                               _("fill color rgba"),
178                                                               _("color of fill"),
179                                                               0,
180                                                               G_MAXINT,
181                                                               0,
182                                                               G_PARAM_READWRITE));  
183         
184         item_class->update = gnome_canvas_simplerect_update;
185         item_class->bounds = gnome_canvas_simplerect_bounds;
186         item_class->point = gnome_canvas_simplerect_point;
187         item_class->render = gnome_canvas_simplerect_render;
188         item_class->draw = gnome_canvas_simplerect_draw;
189 }
190
191 static void
192 gnome_canvas_simplerect_init (GnomeCanvasSimpleRect *simplerect)
193 {
194         simplerect->x1 = 0.0;
195         simplerect->y1 = 0.0;
196         simplerect->x2 = 0.0;
197         simplerect->y2 = 0.0;
198         simplerect->fill = TRUE;
199         simplerect->draw = TRUE;
200         simplerect->full_draw_on_update = TRUE;
201         simplerect->fill_color = 0;
202         simplerect->outline_color = 0;
203         simplerect->outline_pixels = 1;
204         simplerect->outline_what = 0xf;
205
206         // GTK2FIX
207         // GNOME_CANVAS_ITEM(simplerect)->object.flags |= GNOME_CANVAS_ITEM_NO_AUTO_REDRAW;
208 }
209
210 static void
211 gnome_canvas_simplerect_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
212 {
213         GnomeCanvasSimpleRect *simplerect = GNOME_CANVAS_SIMPLERECT (item);
214
215         *x1 = simplerect->x1;
216         *y1 = simplerect->y1;
217         *x2 = simplerect->x2 + 1;
218         *y2 = simplerect->y2 + 1;
219
220 }
221
222 static void 
223 gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
224 {
225         GnomeCanvasSimpleRect* simplerect;
226         double x1, x2, y1, y2;
227         double old_x1, old_x2, old_y1, old_y2;
228         double a, b;
229         
230         old_x1 = item->x1;
231         old_y1 = item->y1;
232         old_x2 = item->x2;
233         old_y2 = item->y2;
234
235         gnome_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
236         gnome_canvas_item_i2w (item, &x1, &y1);
237         gnome_canvas_item_i2w (item, &x2, &y2);
238
239         item->x1 = x1;
240         item->y1 = y1;
241         item->x2 = x2;
242         item->y2 = y2;
243
244         /* now compute bounding box in canvas units */
245
246         simplerect = GNOME_CANVAS_SIMPLERECT (item);
247
248         gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x1, y1, &simplerect->bbox_ulx, &simplerect->bbox_uly);
249         gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
250
251         /* now queue redraws for changed areas */
252
253         if (item->x1 != old_x1) {
254                 
255                 /* left edge changed. redraw the area that altered */
256                 
257                 a = MIN(item->x1, old_x1); 
258                 b = MAX(item->x1, old_x1);
259                 gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
260         }
261         
262         if (item->x2 != old_x2) {
263                 
264                 /* right edge changed. redraw the area that altered */
265                 
266                 a = MIN(item->x2, old_x2);
267                 b = MAX(item->x2, old_x2);
268                 gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
269         }
270         
271         if (item->y1 != old_y1) {
272                 
273                 /* top edge changed. redraw the area that altered */
274                 
275                 a = MIN(item->y1, old_y1);
276                 b = MAX(item->y1, old_y1);
277                 gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
278         }
279         
280         if (item->y2 != old_y2) {
281                 
282                 /* lower edge changed. redraw the area that altered */
283                 
284                 a = MIN(item->y2, old_y2);
285                 b = MAX(item->y2, old_y2);
286                 gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
287         }
288 }
289
290 /* 
291  * CANVAS CALLBACKS 
292  */
293
294 static void
295 gnome_canvas_simplerect_set_property (GObject      *object,
296                                       guint         prop_id,
297                                       const GValue *value,
298                                       GParamSpec   *pspec)
299
300 {
301         GnomeCanvasSimpleRect *simplerect;
302         int update;
303         int bounds_changed;
304
305         simplerect = GNOME_CANVAS_SIMPLERECT (object);
306
307         update = FALSE;
308         bounds_changed = FALSE;
309
310         switch (prop_id) {
311         case PROP_X1:
312                 if (simplerect->x1 != g_value_get_double (value)) {
313                         simplerect->x1 = g_value_get_double (value);
314                         bounds_changed = TRUE;
315                 }
316                 break;
317
318         case PROP_Y1:
319                 if (simplerect->y1 != g_value_get_double (value)) {
320                         simplerect->y1 = g_value_get_double (value);
321                         bounds_changed = TRUE;
322                 }
323                 break;
324
325         case PROP_X2:
326                 if (simplerect->x2 != g_value_get_double (value)) {
327                         simplerect->x2 = g_value_get_double (value);
328                         bounds_changed = TRUE;
329                 }
330                 break;
331
332         case PROP_Y2:
333                 if (simplerect->y2 != g_value_get_double (value)) {
334                         simplerect->y2 = g_value_get_double (value);
335                         bounds_changed = TRUE;
336                 }
337                 break;
338
339         case PROP_DRAW:
340                 if (simplerect->draw != g_value_get_boolean (value)) {
341                         simplerect->draw = g_value_get_boolean (value);
342                         update = TRUE;
343                 }
344                 break;
345
346
347         case PROP_FILL:
348                 if (simplerect->fill != g_value_get_boolean (value)) {
349                         simplerect->fill = g_value_get_boolean (value);
350                         update = TRUE;
351                 }
352                 break;
353
354         case PROP_FILL_COLOR_RGBA:
355                 if (simplerect->fill_color != g_value_get_uint(value)) {
356                         simplerect->fill_color = g_value_get_uint(value);
357                         update = TRUE;
358                 }
359                 break;
360
361         case PROP_OUTLINE_COLOR_RGBA:
362                 if (simplerect->outline_color != g_value_get_uint(value)) {
363                         simplerect->outline_color = g_value_get_uint(value);
364                         update = TRUE;
365                 }
366                 break;
367
368         case PROP_OUTLINE_PIXELS:
369                 if (simplerect->outline_pixels != g_value_get_uint(value)) {
370                         simplerect->outline_pixels = g_value_get_uint(value);
371                         update = TRUE;
372                 }
373                 break;
374
375         case PROP_OUTLINE_WHAT:
376                 if (simplerect->outline_what != g_value_get_uint(value)) {
377                         simplerect->outline_what = g_value_get_uint(value);
378                         update = TRUE;
379                 }
380                 break;
381
382         default:
383                 break;
384         }
385
386         simplerect->full_draw_on_update = update;
387
388         if (update || bounds_changed) {
389                 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(object));
390         }
391 }
392
393 static void
394 gnome_canvas_simplerect_get_property (GObject      *object,
395                                       guint         prop_id,
396                                       GValue       *value,
397                                       GParamSpec   *pspec)
398 {
399         GnomeCanvasSimpleRect *rect = GNOME_CANVAS_SIMPLERECT (object);
400         
401         switch (prop_id) {
402         case PROP_X1:
403                 g_value_set_double (value, rect->x1);
404                 break;
405         case PROP_X2:
406                 g_value_set_double (value, rect->x2);
407                 break;
408         case PROP_Y1:
409                 g_value_set_double (value, rect->y1);
410                 break;
411         case PROP_Y2:
412                 g_value_set_double (value, rect->y2);
413                 break;
414         case PROP_OUTLINE_WHAT:
415                 g_value_set_uint (value, rect->outline_what);
416                 break;
417         case PROP_FILL:
418                 g_value_set_boolean (value, rect->fill);
419                 break;
420         case PROP_OUTLINE_PIXELS:
421                 g_value_set_uint (value, rect->outline_pixels);
422                 break;
423         case PROP_FILL_COLOR_RGBA:
424                 g_value_set_uint (value, rect->fill_color);
425                 break;
426         case PROP_OUTLINE_COLOR_RGBA:
427                 g_value_set_uint (value, rect->outline_color);
428                 break;
429         case PROP_DRAW:
430                 g_value_set_boolean (value, rect->draw);
431                 break;
432                 
433         default:
434                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
435                 break;
436         }
437 }
438
439
440 static void
441 gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
442 {
443         GnomeCanvasSimpleRect *simplerect;
444         unsigned char foo;
445
446         simplerect = GNOME_CANVAS_SIMPLERECT (item);
447
448         if (parent_class->update)
449                 (* parent_class->update) (item, affine, clip_path, flags);
450
451         gnome_canvas_simplerect_reset_bounds (item);
452
453         if (simplerect->full_draw_on_update) {
454                 gnome_canvas_request_redraw (item->canvas, 
455                                            simplerect->bbox_ulx,
456                                            simplerect->bbox_uly,
457                                            simplerect->bbox_lrx+1,
458                                            simplerect->bbox_lry+1);
459                 simplerect->full_draw_on_update = FALSE;
460         }
461
462         UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a);
463         UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo);
464 }
465
466 #define SIMPLERECT_FAST_RENDERER
467 #ifdef SIMPLERECT_FAST_RENDERER
468
469 static void
470 gnome_canvas_simplerect_render (GnomeCanvasItem *item,
471                               GnomeCanvasBuf *buf)
472 {
473         GnomeCanvasSimpleRect *simplerect;
474         int end, begin;
475         int ey, sy;
476         unsigned int i;
477         ArtIRect intersection;
478         ArtIRect self;
479
480         simplerect = GNOME_CANVAS_SIMPLERECT (item);
481
482         if (parent_class->render) {
483                 (*parent_class->render) (item, buf);
484         }
485
486         if (buf->is_bg) {
487
488                 // this can be useful for debugging/understanding how the canvas redraws
489                 // stuff.
490
491                 // gint randr, randg, randb;
492                 // randr = random() % 255;
493                 // randg = random() % 255;
494                 // randb = random() % 255;
495                 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
496
497                 gnome_canvas_buf_ensure_buf (buf);
498                 buf->is_bg = FALSE;
499         }
500
501         if (!simplerect->draw) {
502                 return;
503         }
504         
505         self.x0 = simplerect->bbox_ulx;
506         self.y0 = simplerect->bbox_uly;
507         self.x1 = simplerect->bbox_lrx;
508         self.y1 = simplerect->bbox_lry;
509
510         art_irect_intersect (&intersection, &self, &buf->rect);
511
512         begin = MAX(simplerect->bbox_ulx, buf->rect.x0);
513         end = MIN((simplerect->bbox_lrx-1), buf->rect.x1);
514
515         sy = simplerect->bbox_uly;
516         ey = simplerect->bbox_lry-1;
517
518         if (simplerect->fill) {
519                 
520                 // this can be useful for debugging/understanding how the canvas redraws
521                 // stuff.
522                 
523                 // gint randr, randg, randb;
524                 // randr = random() % 255;
525                 // randg = random() % 255;
526                 // randb = random() % 255;
527                 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
528                 
529                 FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, 
530                                 intersection.x0, intersection.y0,
531                                 intersection.x1, intersection.y1);
532                 
533         }
534
535         for (i = 0; i < simplerect->outline_pixels; ++i) {
536
537                 if (simplerect->outline_what & 0x1) {
538                         if (begin == simplerect->bbox_ulx) {
539                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
540                         }
541                 }
542
543                 if (simplerect->outline_what & 0x2) {
544                         if (end == (simplerect->bbox_lrx - 1)) {
545                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
546                         }
547                 }
548
549                 if (simplerect->outline_what & 0x4) {
550                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
551                 }
552         
553                 if (simplerect->outline_what & 0x8) {
554                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
555                 }
556         }
557 }
558
559 #else /* SIMPLERECT_FAST_RENDERER */
560
561 static void
562 gnome_canvas_simplerect_render (GnomeCanvasItem *item,
563                               GnomeCanvasBuf *buf)
564 {
565         GnomeCanvasSimpleRect *simplerect;
566         int end, begin;
567         int ey, sy;
568         unsigned int i;
569
570         simplerect = GNOME_CANVAS_SIMPLERECT (item);
571
572         if (parent_class->render) {
573                 (*parent_class->render) (item, buf);
574         }
575
576         if (buf->is_bg) {
577
578                 // this can be useful for debugging/understanding how the canvas redraws
579                 // stuff.
580
581                 // gint randr, randg, randb;
582                 // randr = random() % 255;
583                 // randg = random() % 255;
584                 // randb = random() % 255;
585                 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
586
587                 gnome_canvas_buf_ensure_buf (buf);
588                 buf->is_bg = FALSE;
589         }
590
591         if (!simplerect->draw) {
592                 return;
593         }
594
595         begin = MAX(simplerect->bbox_ulx,buf->rect.x0);
596         end = MIN((simplerect->bbox_lrx-1),buf->rect.x1);
597
598         sy = simplerect->bbox_uly;
599         ey = simplerect->bbox_lry-1;
600
601         if (simplerect->fill) {
602                 
603                 // this can be useful for debugging/understanding how the canvas redraws
604                 // stuff.
605                 
606                 // gint randr, randg, randb;
607                 // randr = random() % 255;
608                 // randg = random() % 255;
609                 // randb = random() % 255;
610                 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
611                 
612                 PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey);
613         }
614
615         for (i = 0; i < simplerect->outline_pixels; ++i) {
616
617                 if (simplerect->outline_what & 0x1) {
618                         if (begin == simplerect->bbox_ulx) {
619                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
620                         }
621                 }
622
623                 if (simplerect->outline_what & 0x2) {
624                         if (end == (simplerect->bbox_lrx - 1)) {
625                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
626                         }
627                 }
628
629                 if (simplerect->outline_what & 0x4) {
630                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
631                 }
632         
633                 if (simplerect->outline_what & 0x8) {
634                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
635                 }
636         }
637 }
638 #endif /* SIMPLERECT_FAST_RENDERER */
639
640 static void
641 gnome_canvas_simplerect_draw (GnomeCanvasItem *item,
642                             GdkDrawable *drawable,
643                             int x, int y,
644                             int width, int height)
645 {
646         fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n");
647         abort ();
648 }
649
650 static double
651 gnome_canvas_simplerect_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
652 {
653         GnomeCanvasSimpleRect *simplerect;
654         double x1, y1, x2, y2;
655         double dx, dy;
656
657         simplerect = GNOME_CANVAS_SIMPLERECT (item);
658
659         *actual_item = item;
660
661         /* Find the bounds for the rectangle plus its outline width */
662
663         gnome_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
664
665         /* Is point inside rectangle */
666         
667         if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
668                 return 0.0;
669         }
670
671         /* Point is outside rectangle */
672
673         if (x < x1)
674                 dx = x1 - x;
675         else if (x > x2)
676                 dx = x - x2;
677         else
678                 dx = 0.0;
679
680         if (y < y1)
681                 dy = y1 - y;
682         else if (y > y2)
683                 dy = y - y2;
684         else
685                 dy = 0.0;
686
687         return sqrt (dx * dx + dy * dy);
688 }