GObject canvas changes
[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_MAXUINT,
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_MAXUINT,
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_MAXUINT,
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_MAXUINT,
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 = FALSE;
303         int bounds_changed = FALSE;
304
305         simplerect = GNOME_CANVAS_SIMPLERECT (object);
306
307         switch (prop_id) {
308         case PROP_X1:
309                 if (simplerect->x1 != g_value_get_double (value)) {
310                         simplerect->x1 = g_value_get_double (value);
311                         bounds_changed = TRUE;
312                 }
313                 break;
314
315         case PROP_Y1:
316                 if (simplerect->y1 != g_value_get_double (value)) {
317                         simplerect->y1 = g_value_get_double (value);
318                         bounds_changed = TRUE;
319                 }
320                 break;
321
322         case PROP_X2:
323                 if (simplerect->x2 != g_value_get_double (value)) {
324                         simplerect->x2 = g_value_get_double (value);
325                         bounds_changed = TRUE;
326                 }
327                 break;
328
329         case PROP_Y2:
330                 if (simplerect->y2 != g_value_get_double (value)) {
331                         simplerect->y2 = g_value_get_double (value);
332                         bounds_changed = TRUE;
333                 }
334                 break;
335
336         case PROP_DRAW:
337                 if (simplerect->draw != g_value_get_boolean (value)) {
338                         simplerect->draw = g_value_get_boolean (value);
339                         update = TRUE;
340                 }
341                 break;
342
343
344         case PROP_FILL:
345                 if (simplerect->fill != g_value_get_boolean (value)) {
346                         simplerect->fill = g_value_get_boolean (value);
347                         update = TRUE;
348                 }
349                 break;
350
351         case PROP_FILL_COLOR_RGBA:
352                 if (simplerect->fill_color != g_value_get_uint(value)) {
353                         simplerect->fill_color = g_value_get_uint(value);
354                         update = TRUE;
355                 }
356                 break;
357
358         case PROP_OUTLINE_COLOR_RGBA:
359                 if (simplerect->outline_color != g_value_get_uint(value)) {
360                         simplerect->outline_color = g_value_get_uint(value);
361                         update = TRUE;
362                 }
363                 break;
364
365         case PROP_OUTLINE_PIXELS:
366                 if (simplerect->outline_pixels != g_value_get_uint(value)) {
367                         simplerect->outline_pixels = g_value_get_uint(value);
368                         update = TRUE;
369                 }
370                 break;
371
372         case PROP_OUTLINE_WHAT:
373                 if (simplerect->outline_what != g_value_get_uint(value)) {
374                         simplerect->outline_what = g_value_get_uint(value);
375                         update = TRUE;
376                 }
377                 break;
378
379         default:
380                 break;
381         }
382
383         simplerect->full_draw_on_update = update;
384
385         if (update || bounds_changed) {
386                 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(object));
387         }
388 }
389
390 static void
391 gnome_canvas_simplerect_get_property (GObject      *object,
392                                       guint         prop_id,
393                                       GValue       *value,
394                                       GParamSpec   *pspec)
395 {
396         GnomeCanvasSimpleRect *rect = GNOME_CANVAS_SIMPLERECT (object);
397         
398         switch (prop_id) {
399         case PROP_X1:
400                 g_value_set_double (value, rect->x1);
401                 break;
402         case PROP_X2:
403                 g_value_set_double (value, rect->x2);
404                 break;
405         case PROP_Y1:
406                 g_value_set_double (value, rect->y1);
407                 break;
408         case PROP_Y2:
409                 g_value_set_double (value, rect->y2);
410                 break;
411         case PROP_OUTLINE_WHAT:
412                 g_value_set_uint (value, rect->outline_what);
413                 break;
414         case PROP_FILL:
415                 g_value_set_boolean (value, rect->fill);
416                 break;
417         case PROP_OUTLINE_PIXELS:
418                 g_value_set_uint (value, rect->outline_pixels);
419                 break;
420         case PROP_FILL_COLOR_RGBA:
421                 g_value_set_uint (value, rect->fill_color);
422                 break;
423         case PROP_OUTLINE_COLOR_RGBA:
424                 g_value_set_uint (value, rect->outline_color);
425                 break;
426         case PROP_DRAW:
427                 g_value_set_boolean (value, rect->draw);
428                 break;
429                 
430         default:
431                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
432                 break;
433         }
434 }
435
436
437 static void
438 gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
439 {
440         GnomeCanvasSimpleRect *simplerect;
441         unsigned char foo;
442
443         simplerect = GNOME_CANVAS_SIMPLERECT (item);
444
445         if (parent_class->update)
446                 (* parent_class->update) (item, affine, clip_path, flags);
447
448         gnome_canvas_simplerect_reset_bounds (item);
449
450         if (simplerect->full_draw_on_update) {
451                 gnome_canvas_request_redraw (item->canvas, 
452                                            simplerect->bbox_ulx,
453                                            simplerect->bbox_uly,
454                                            simplerect->bbox_lrx+1,
455                                            simplerect->bbox_lry+1);
456                 simplerect->full_draw_on_update = FALSE;
457         }
458
459         UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a);
460         UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo);
461 }
462
463 #define SIMPLERECT_FAST_RENDERER
464 #ifdef SIMPLERECT_FAST_RENDERER
465
466 static void
467 gnome_canvas_simplerect_render (GnomeCanvasItem *item,
468                               GnomeCanvasBuf *buf)
469 {
470         GnomeCanvasSimpleRect *simplerect;
471         int end, begin;
472         int ey, sy;
473         unsigned int i;
474         ArtIRect intersection;
475         ArtIRect self;
476
477         simplerect = GNOME_CANVAS_SIMPLERECT (item);
478
479         if (parent_class->render) {
480                 (*parent_class->render) (item, buf);
481         }
482
483         if (buf->is_bg) {
484
485                 // this can be useful for debugging/understanding how the canvas redraws
486                 // stuff.
487
488                 // gint randr, randg, randb;
489                 // randr = random() % 255;
490                 // randg = random() % 255;
491                 // randb = random() % 255;
492                 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
493
494                 gnome_canvas_buf_ensure_buf (buf);
495                 buf->is_bg = FALSE;
496         }
497
498         if (!simplerect->draw) {
499                 return;
500         }
501         
502         self.x0 = simplerect->bbox_ulx;
503         self.y0 = simplerect->bbox_uly;
504         self.x1 = simplerect->bbox_lrx;
505         self.y1 = simplerect->bbox_lry;
506
507         art_irect_intersect (&intersection, &self, &buf->rect);
508
509         begin = MAX(simplerect->bbox_ulx, buf->rect.x0);
510         end = MIN((simplerect->bbox_lrx-1), buf->rect.x1);
511
512         sy = simplerect->bbox_uly;
513         ey = simplerect->bbox_lry-1;
514
515         if (simplerect->fill) {
516                 
517                 // this can be useful for debugging/understanding how the canvas redraws
518                 // stuff.
519                 
520                 // gint randr, randg, randb;
521                 // randr = random() % 255;
522                 // randg = random() % 255;
523                 // randb = random() % 255;
524                 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
525                 
526                 FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, 
527                                 intersection.x0, intersection.y0,
528                                 intersection.x1, intersection.y1);
529                 
530         }
531
532         for (i = 0; i < simplerect->outline_pixels; ++i) {
533
534                 if (simplerect->outline_what & 0x1) {
535                         if (begin == simplerect->bbox_ulx) {
536                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
537                         }
538                 }
539
540                 if (simplerect->outline_what & 0x2) {
541                         if (end == (simplerect->bbox_lrx - 1)) {
542                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
543                         }
544                 }
545
546                 if (simplerect->outline_what & 0x4) {
547                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
548                 }
549         
550                 if (simplerect->outline_what & 0x8) {
551                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
552                 }
553         }
554 }
555
556 #else /* SIMPLERECT_FAST_RENDERER */
557
558 static void
559 gnome_canvas_simplerect_render (GnomeCanvasItem *item,
560                               GnomeCanvasBuf *buf)
561 {
562         GnomeCanvasSimpleRect *simplerect;
563         int end, begin;
564         int ey, sy;
565         unsigned int i;
566
567         simplerect = GNOME_CANVAS_SIMPLERECT (item);
568
569         if (parent_class->render) {
570                 (*parent_class->render) (item, buf);
571         }
572
573         if (buf->is_bg) {
574
575                 // this can be useful for debugging/understanding how the canvas redraws
576                 // stuff.
577
578                 // gint randr, randg, randb;
579                 // randr = random() % 255;
580                 // randg = random() % 255;
581                 // randb = random() % 255;
582                 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
583
584                 gnome_canvas_buf_ensure_buf (buf);
585                 buf->is_bg = FALSE;
586         }
587
588         if (!simplerect->draw) {
589                 return;
590         }
591
592         begin = MAX(simplerect->bbox_ulx,buf->rect.x0);
593         end = MIN((simplerect->bbox_lrx-1),buf->rect.x1);
594
595         sy = simplerect->bbox_uly;
596         ey = simplerect->bbox_lry-1;
597
598         if (simplerect->fill) {
599                 
600                 // this can be useful for debugging/understanding how the canvas redraws
601                 // stuff.
602                 
603                 // gint randr, randg, randb;
604                 // randr = random() % 255;
605                 // randg = random() % 255;
606                 // randb = random() % 255;
607                 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
608                 
609                 PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey);
610         }
611
612         for (i = 0; i < simplerect->outline_pixels; ++i) {
613
614                 if (simplerect->outline_what & 0x1) {
615                         if (begin == simplerect->bbox_ulx) {
616                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
617                         }
618                 }
619
620                 if (simplerect->outline_what & 0x2) {
621                         if (end == (simplerect->bbox_lrx - 1)) {
622                                 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
623                         }
624                 }
625
626                 if (simplerect->outline_what & 0x4) {
627                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
628                 }
629         
630                 if (simplerect->outline_what & 0x8) {
631                         PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
632                 }
633         }
634 }
635 #endif /* SIMPLERECT_FAST_RENDERER */
636
637 static void
638 gnome_canvas_simplerect_draw (GnomeCanvasItem *item,
639                             GdkDrawable *drawable,
640                             int x, int y,
641                             int width, int height)
642 {
643         fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n");
644         abort ();
645 }
646
647 static double
648 gnome_canvas_simplerect_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
649 {
650         GnomeCanvasSimpleRect *simplerect;
651         double x1, y1, x2, y2;
652         double dx, dy;
653
654         simplerect = GNOME_CANVAS_SIMPLERECT (item);
655
656         *actual_item = item;
657
658         /* Find the bounds for the rectangle plus its outline width */
659
660         gnome_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
661
662         /* Is point inside rectangle */
663         
664         if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
665                 return 0.0;
666         }
667
668         /* Point is outside rectangle */
669
670         if (x < x1)
671                 dx = x1 - x;
672         else if (x > x2)
673                 dx = x - x2;
674         else
675                 dx = 0.0;
676
677         if (y < y1)
678                 dy = y1 - y;
679         else if (y > y2)
680                 dy = y - y2;
681         else
682                 dy = 0.0;
683
684         return sqrt (dx * dx + dy * dy);
685 }