4 #include <libgnomecanvas/libgnomecanvas.h>
6 #include "canvas-simplerect.h"
7 #include "rgb_macros.h"
9 #define _(Text) dgettext (PACKAGE,Text)
21 PROP_OUTLINE_COLOR_RGBA
,
25 static void gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass
*class);
27 static void gnome_canvas_simplerect_init (GnomeCanvasSimpleRect
*simplerect
);
29 static void gnome_canvas_simplerect_destroy (GtkObject
*object
);
31 static void gnome_canvas_simplerect_set_property (GObject
*object
,
36 static void gnome_canvas_simplerect_get_property (GObject
*object
,
41 static void gnome_canvas_simplerect_update (GnomeCanvasItem
*item
,
46 static void gnome_canvas_simplerect_bounds (GnomeCanvasItem
*item
,
52 static double gnome_canvas_simplerect_point (GnomeCanvasItem
*item
, double x
, double y
, int cx
, int cy
, GnomeCanvasItem
**actual_item
);
54 static void gnome_canvas_simplerect_render (GnomeCanvasItem
*item
, GnomeCanvasBuf
*buf
);
56 static void gnome_canvas_simplerect_draw (GnomeCanvasItem
*item
, GdkDrawable
*drawable
, int x
, int y
, int w
, int h
);
58 static GnomeCanvasItemClass
*parent_class
;
62 gnome_canvas_simplerect_get_type (void)
64 static GType simplerect_type
;
66 if (!simplerect_type
) {
67 static const GTypeInfo object_info
= {
68 sizeof (GnomeCanvasSimpleRectClass
),
70 (GBaseFinalizeFunc
) NULL
,
71 (GClassInitFunc
) gnome_canvas_simplerect_class_init
,
72 (GClassFinalizeFunc
) NULL
,
73 NULL
, /* class_data */
74 sizeof (GnomeCanvasSimpleRect
),
76 (GInstanceInitFunc
) gnome_canvas_simplerect_init
,
77 NULL
/* value_table */
80 simplerect_type
= g_type_register_static (GNOME_TYPE_CANVAS_ITEM
, "GnomeCanvasSimpleRect",
84 return simplerect_type
;
88 gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass
*class)
90 GObjectClass
*gobject_class
;
91 GtkObjectClass
*object_class
;
92 GnomeCanvasItemClass
*item_class
;
94 gobject_class
= (GObjectClass
*) class;
95 object_class
= (GtkObjectClass
*) class;
96 item_class
= (GnomeCanvasItemClass
*) class;
98 parent_class
= g_type_class_peek_parent (class);
100 gobject_class
->set_property
= gnome_canvas_simplerect_set_property
;
101 gobject_class
->get_property
= gnome_canvas_simplerect_get_property
;
103 g_object_class_install_property (gobject_class
,
105 g_param_spec_double ("x1",
107 _("x coordinate of upper left corner of rect"),
113 g_object_class_install_property (gobject_class
,
115 g_param_spec_double ("y1",
117 _("y coordinate of upper left corner of rect "),
124 g_object_class_install_property (gobject_class
,
126 g_param_spec_double ("x2",
128 _("x coordinate of lower right corner of rect"),
134 g_object_class_install_property (gobject_class
,
136 g_param_spec_double ("y2",
138 _("y coordinate of lower right corner of rect "),
145 g_object_class_install_property (gobject_class
,
147 g_param_spec_uint ("outline_pixels",
149 _("width in pixels of outline"),
156 g_object_class_install_property (gobject_class
,
158 g_param_spec_uint ("outline_what",
160 _("which boundaries to outline (mask)"),
168 g_object_class_install_property (gobject_class
,
170 g_param_spec_boolean ("fill",
176 g_object_class_install_property (gobject_class
,
178 g_param_spec_boolean ("draw",
185 g_object_class_install_property (gobject_class
,
186 PROP_OUTLINE_COLOR_RGBA
,
187 g_param_spec_uint ("outline_color_rgba",
188 _("outline color rgba"),
189 _("color of outline"),
196 g_object_class_install_property (gobject_class
,
197 PROP_FILL_COLOR_RGBA
,
198 g_param_spec_uint ("fill_color_rgba",
199 _("fill color rgba"),
206 object_class
->destroy
= gnome_canvas_simplerect_destroy
;
208 item_class
->update
= gnome_canvas_simplerect_update
;
209 item_class
->draw
= gnome_canvas_simplerect_draw
;
210 item_class
->bounds
= gnome_canvas_simplerect_bounds
;
211 item_class
->point
= gnome_canvas_simplerect_point
;
212 item_class
->render
= gnome_canvas_simplerect_render
;
217 gnome_canvas_simplerect_init (GnomeCanvasSimpleRect
*simplerect
)
219 simplerect
->x1
= 0.0;
220 simplerect
->y1
= 0.0;
221 simplerect
->x2
= 0.0;
222 simplerect
->y2
= 0.0;
223 simplerect
->fill
= TRUE
;
224 simplerect
->draw
= TRUE
;
225 simplerect
->full_draw_on_update
= TRUE
;
226 simplerect
->fill_color
= 0;
227 simplerect
->outline_color
= 0;
228 simplerect
->outline_pixels
= 1;
229 simplerect
->outline_what
= 0xf;
233 gnome_canvas_simplerect_destroy (GtkObject
*object
)
235 GnomeCanvasSimpleRect
*rect
;
237 g_return_if_fail (object
!= NULL
);
238 g_return_if_fail (GNOME_IS_CANVAS_SIMPLERECT (object
));
240 rect
= GNOME_CANVAS_SIMPLERECT (object
);
242 /* remember, destroy can be run multiple times! */
244 if (GTK_OBJECT_CLASS (parent_class
)->destroy
)
245 (* GTK_OBJECT_CLASS (parent_class
)->destroy
) (object
);
249 gnome_canvas_simplerect_bounds (GnomeCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
)
251 GnomeCanvasSimpleRect
*simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
253 *x1
= simplerect
->x1
;
254 *y1
= simplerect
->y1
;
255 *x2
= simplerect
->x2
+ 1;
256 *y2
= simplerect
->y2
+ 1;
261 gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem
*item
)
263 GnomeCanvasSimpleRect
* simplerect
;
264 double x1
, x2
, y1
, y2
;
265 double old_x1
, old_x2
, old_y1
, old_y2
;
266 ArtDRect unionrect
, old
, new;
273 gnome_canvas_simplerect_bounds (item
, &x1
, &y1
, &x2
, &y2
);
274 gnome_canvas_item_i2w (item
, &x1
, &y1
);
275 gnome_canvas_item_i2w (item
, &x2
, &y2
);
282 /* now compute bounding box in canvas units */
284 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
286 gnome_canvas_w2c (GNOME_CANVAS(item
->canvas
), x1
, y1
, &simplerect
->bbox_ulx
, &simplerect
->bbox_uly
);
287 gnome_canvas_w2c (GNOME_CANVAS(item
->canvas
), x2
, y2
, &simplerect
->bbox_lrx
, &simplerect
->bbox_lry
);
289 /* now queue redraws for changed areas */
291 if (item
->x1
== old_x1
&& item
->x2
== old_x2
) {
293 /* no change in x-axis position */
295 if (item
->y1
== old_y1
) {
296 /* top didn't change, so just draw bottom */
298 double start_y
= MIN (item
->y2
, old_y2
);
299 double end_y
= MAX (item
->y2
, old_y2
);
301 gnome_canvas_request_redraw (item
->canvas
, item
->x1
, start_y
- 0.5, item
->x2
, end_y
+ 1.5);
304 } else if (item
->y2
== old_y2
) {
306 /* bottom didn't change, just draw top */
308 double start_y
= MIN (item
->y1
, old_y1
);
309 double end_y
= MAX (item
->y1
, old_y1
);
311 gnome_canvas_request_redraw (item
->canvas
, item
->x1
, start_y
- 0.5, item
->x2
, end_y
+ 1.5);
316 } else if (item
->y1
== old_y1
&& item
->y2
== old_y2
) {
318 /* no change in y-axis position */
320 if (item
->x1
== old_x1
) {
321 /* start didn't change, so just draw at the end */
323 double start_x
= MIN (item
->x2
, old_x2
);
324 double end_x
= MAX (item
->x2
, old_x2
);
326 gnome_canvas_request_redraw (item
->canvas
, start_x
- 0.5, item
->y1
, end_x
+ 1.5, item
->y2
+ 0.5);
329 } else if (item
->x2
== old_x2
) {
331 /* end didn't change, so just draw at the start */
333 double start_x
= MIN (item
->x1
, old_x1
);
334 double end_x
= MAX (item
->x1
, old_x1
);
336 gnome_canvas_request_redraw (item
->canvas
, start_x
- 0.5, item
->y1
, end_x
+ 1.5, item
->y2
+ 0.5);
352 art_drect_union (&unionrect
, &old
, &new);
353 gnome_canvas_request_redraw (item
->canvas
,
365 gnome_canvas_simplerect_set_property (GObject
*object
,
373 GnomeCanvasSimpleRect
*simplerect
;
375 int bounds_changed
= FALSE
;
376 g_return_if_fail (object
!= NULL
);
377 g_return_if_fail (GNOME_IS_CANVAS_SIMPLERECT (object
));
379 simplerect
= GNOME_CANVAS_SIMPLERECT (object
);
383 if (simplerect
->x1
!= g_value_get_double (value
)) {
384 simplerect
->x1
= g_value_get_double (value
);
385 bounds_changed
= TRUE
;
390 if (simplerect
->y1
!= g_value_get_double (value
)) {
391 simplerect
->y1
= g_value_get_double (value
);
392 bounds_changed
= TRUE
;
397 if (simplerect
->x2
!= g_value_get_double (value
)) {
398 simplerect
->x2
= g_value_get_double (value
);
399 bounds_changed
= TRUE
;
404 if (simplerect
->y2
!= g_value_get_double (value
)) {
405 simplerect
->y2
= g_value_get_double (value
);
406 bounds_changed
= TRUE
;
411 if (simplerect
->draw
!= g_value_get_boolean (value
)) {
412 simplerect
->draw
= g_value_get_boolean (value
);
419 if (simplerect
->fill
!= g_value_get_boolean (value
)) {
420 simplerect
->fill
= g_value_get_boolean (value
);
425 case PROP_FILL_COLOR_RGBA
:
426 if (simplerect
->fill_color
!= g_value_get_uint(value
)) {
427 simplerect
->fill_color
= g_value_get_uint(value
);
432 case PROP_OUTLINE_COLOR_RGBA
:
433 if (simplerect
->outline_color
!= g_value_get_uint(value
)) {
434 simplerect
->outline_color
= g_value_get_uint(value
);
439 case PROP_OUTLINE_PIXELS
:
440 if (simplerect
->outline_pixels
!= g_value_get_uint(value
)) {
441 simplerect
->outline_pixels
= g_value_get_uint(value
);
446 case PROP_OUTLINE_WHAT
:
447 if (simplerect
->outline_what
!= g_value_get_uint(value
)) {
448 simplerect
->outline_what
= g_value_get_uint(value
);
457 if (!simplerect
->full_draw_on_update
) {
458 /* XXX: not sure about this;
460 * I changed the next line to be conditional, rather than always
461 * being executed. Without the condition, the following bug occurs:
463 * caller sets a property (e.g. outline colour); this sets update = TRUE and hence full_draw_on_update = TRUE
464 * update is requested (and it is intended, I suppose, that during this update, full_draw_on_update is noted)
465 * ... update does not occur before ...
466 * caller sets the same property again to the same value; this sets update = FALSE and hence full_draw_on_update = FALSE
467 * update now occurs, but full_draw_on_update is FALSE, so the full redraw does not happen,
468 * which results in graphical glitches.
472 simplerect
->full_draw_on_update
= update
;
475 if (update
|| bounds_changed
) {
476 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(object
));
481 gnome_canvas_simplerect_get_property (GObject
*object
,
486 GnomeCanvasSimpleRect
*rect
= GNOME_CANVAS_SIMPLERECT (object
);
488 g_return_if_fail (object
!= NULL
);
489 g_return_if_fail (GNOME_IS_CANVAS_SIMPLERECT (object
));
493 g_value_set_double (value
, rect
->x1
);
496 g_value_set_double (value
, rect
->x2
);
499 g_value_set_double (value
, rect
->y1
);
502 g_value_set_double (value
, rect
->y2
);
504 case PROP_OUTLINE_WHAT
:
505 g_value_set_uint (value
, rect
->outline_what
);
508 g_value_set_boolean (value
, rect
->fill
);
510 case PROP_OUTLINE_PIXELS
:
511 g_value_set_uint (value
, rect
->outline_pixels
);
513 case PROP_FILL_COLOR_RGBA
:
514 g_value_set_uint (value
, rect
->fill_color
);
516 case PROP_OUTLINE_COLOR_RGBA
:
517 g_value_set_uint (value
, rect
->outline_color
);
520 g_value_set_boolean (value
, rect
->draw
);
524 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
531 gnome_canvas_simplerect_update (GnomeCanvasItem
*item
, double *affine
, ArtSVP
*clip_path
, int flags
)
533 GnomeCanvasSimpleRect
*simplerect
;
535 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
537 if (parent_class
->update
)
538 (* parent_class
->update
) (item
, affine
, clip_path
, flags
);
540 gnome_canvas_simplerect_reset_bounds (item
);
542 if (simplerect
->full_draw_on_update
) {
543 gnome_canvas_request_redraw (item
->canvas
,
544 simplerect
->bbox_ulx
,
545 simplerect
->bbox_uly
,
546 simplerect
->bbox_lrx
+0.5,
547 simplerect
->bbox_lry
+0.5);
548 simplerect
->full_draw_on_update
= FALSE
;
551 UINT_TO_RGBA (simplerect
->fill_color
, &simplerect
->fill_r
, &simplerect
->fill_g
, &simplerect
->fill_b
, &simplerect
->fill_a
);
552 UINT_TO_RGBA (simplerect
->outline_color
, &simplerect
->outline_r
, &simplerect
->outline_g
, &simplerect
->outline_b
, &simplerect
->outline_a
);
555 // this can be useful for debugging/understanding how the canvas redraws
558 #undef HARLEQUIN_DEBUGGING
560 #undef SIMPLERECT_FAST_RENDERER
561 #ifdef SIMPLERECT_FAST_RENDERER
564 gnome_canvas_simplerect_render (GnomeCanvasItem
*item
,
567 GnomeCanvasSimpleRect
*simplerect
;
571 ArtIRect intersection
;
574 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
576 if (parent_class
->render
) {
577 (*parent_class
->render
) (item
, buf
);
582 #ifdef HARLEQUIN_DEBUGGING
583 gint randr
, randg
, randb
;
584 randr
= random() % 255;
585 randg
= random() % 255;
586 randb
= random() % 255;
587 PAINT_BOX(buf
, randr
, randg
, randb
, 255, buf
->rect
.x0
, buf
->rect
.y0
, buf
->rect
.x1
, buf
->rect
.y1
);
589 gnome_canvas_buf_ensure_buf (buf
);
593 if (!simplerect
->draw
) {
597 self
.x0
= simplerect
->bbox_ulx
;
598 self
.y0
= simplerect
->bbox_uly
;
599 self
.x1
= simplerect
->bbox_lrx
;
600 self
.y1
= simplerect
->bbox_lry
;
602 art_irect_intersect (&intersection
, &self
, &buf
->rect
);
604 begin
= MAX(simplerect
->bbox_ulx
, buf
->rect
.x0
);
605 end
= MIN((simplerect
->bbox_lrx
-1), buf
->rect
.x1
);
607 sy
= simplerect
->bbox_uly
;
608 ey
= simplerect
->bbox_lry
-1;
610 if (simplerect
->fill
) {
612 // this can be useful for debugging/understanding how the canvas redraws
615 #ifdef HARLEQUIN_DEBUGGING
616 gint randr
, randg
, randb
;
617 randr
= random() % 255;
618 randg
= random() % 255;
619 randb
= random() % 255;
620 PAINT_BOX(buf
, randr
, randg
, randb
, simplerect
->fill_a
, begin
, sy
, end
, ey
);
622 PAINT_BOX (buf
, simplerect
->fill_r
, simplerect
->fill_g
, simplerect
->fill_b
, simplerect
->fill_a
,
623 intersection
.x0
, intersection
.y0
,
624 intersection
.x1
, intersection
.y1
);
629 if (simplerect
->outline_a
> 0) {
630 for (i
= 0; i
< simplerect
->outline_pixels
; ++i
) {
632 if (simplerect
->outline_what
& 0x1) {
633 if (begin
== simplerect
->bbox_ulx
) {
634 PAINT_VERTA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, begin
+ i
, sy
, ey
);
638 if (simplerect
->outline_what
& 0x2) {
639 if (end
== (simplerect
->bbox_lrx
- 1)) {
640 PAINT_VERTA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, end
- i
, sy
, ey
+ 1);
644 if (simplerect
->outline_what
& 0x4) {
645 PAINT_HORIZA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, begin
, end
, sy
+i
);
648 if (simplerect
->outline_what
& 0x8) {
649 PAINT_HORIZA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, begin
, end
+ 1, ey
-i
);
655 #else /* SIMPLERECT_FAST_RENDERER */
658 gnome_canvas_simplerect_render (GnomeCanvasItem
*item
,
661 GnomeCanvasSimpleRect
*simplerect
;
666 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
668 if (parent_class
->render
) {
669 (*parent_class
->render
) (item
, buf
);
674 #ifdef HARLEQUIN_DEBUGGING
675 gint randr
, randg
, randb
;
676 randr
= random() % 255;
677 randg
= random() % 255;
678 randb
= random() % 255;
679 PAINT_BOX(buf
, randr
, randg
, randb
, 255, buf
->rect
.x0
, buf
->rect
.y0
, buf
->rect
.x1
, buf
->rect
.y1
);
681 gnome_canvas_buf_ensure_buf (buf
);
685 if (!simplerect
->draw
) {
689 begin
= MAX(simplerect
->bbox_ulx
,buf
->rect
.x0
);
690 end
= MIN((simplerect
->bbox_lrx
-1),buf
->rect
.x1
);
692 sy
= simplerect
->bbox_uly
;
693 ey
= simplerect
->bbox_lry
-1;
695 if (simplerect
->fill
) {
697 #ifdef HARLEQUIN_DEBUGGING
698 gint randr
, randg
, randb
;
699 randr
= random() % 255;
700 randg
= random() % 255;
701 randb
= random() % 255;
702 PAINT_BOX(buf
, randr
, randg
, randb
, simplerect
->fill_a
, begin
, sy
, end
, ey
);
704 PAINT_BOX(buf
, simplerect
->fill_r
, simplerect
->fill_g
, simplerect
->fill_b
, simplerect
->fill_a
, begin
, sy
, end
, ey
);
708 if (simplerect
->outline_a
) {
709 for (i
= 0; i
< (int) simplerect
->outline_pixels
; ++i
) {
711 if (simplerect
->outline_what
& 0x1) {
712 if (begin
== simplerect
->bbox_ulx
) {
713 PAINT_VERTA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, begin
+ i
, sy
, ey
);
717 if (simplerect
->outline_what
& 0x2) {
718 if (end
== (simplerect
->bbox_lrx
- 1)) {
719 PAINT_VERTA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, end
- i
, sy
, ey
+ 1);
723 if (simplerect
->outline_what
& 0x4) {
724 PAINT_HORIZA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, begin
, end
, sy
+i
);
727 if (simplerect
->outline_what
& 0x8) {
728 PAINT_HORIZA(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, simplerect
->outline_a
, begin
, end
+ 1, ey
-i
);
733 #endif /* SIMPLERECT_FAST_RENDERER */
736 gnome_canvas_simplerect_draw (GnomeCanvasItem
*item
,
737 GdkDrawable
*drawable
,
739 int width
, int height
)
741 GnomeCanvasSimpleRect
*simplerect
;
748 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
750 cr
= gdk_cairo_create (drawable
);
752 if (x
> simplerect
->bbox_ulx
) {
755 ulx
= simplerect
->bbox_ulx
;
758 if (y
> simplerect
->bbox_uly
) {
761 uly
= simplerect
->bbox_uly
;
764 if (x
+ width
> simplerect
->bbox_lrx
) {
765 lrx
= simplerect
->bbox_lrx
;
770 if (y
+ height
> simplerect
->bbox_lry
) {
771 lry
= simplerect
->bbox_lry
;
781 cairo_rectangle (cr
, ulx
, uly
, lrx
- ulx
, lry
- uly
);
783 if (simplerect
->fill
) {
784 cairo_set_source_rgba (cr
,
785 simplerect
->fill_r
/255.0,
786 simplerect
->fill_g
/255.0,
787 simplerect
->fill_b
/255.0,
788 simplerect
->fill_a
/255.0);
792 if (simplerect
->outline_what
&& simplerect
->outline_pixels
) {
794 #define x_in_range(a) (x <= (a) && (a) < x + width)
795 #define y_in_range(a) (y <= (a) && (a) < y + height)
797 cairo_set_line_width (cr
, simplerect
->outline_pixels
);
799 cairo_set_source_rgb (cr
,
800 simplerect
->outline_r
/255.0,
801 simplerect
->outline_g
/255.0,
802 simplerect
->outline_b
/255.0);
804 if (simplerect
->outline_what
& 0x1) {
805 /* left edge, if visible */
806 if (x_in_range (simplerect
->bbox_ulx
)) {
807 cairo_move_to (cr
, ulx
+0.5, uly
+0.5);
808 cairo_line_to (cr
, ulx
+0.5, lry
+0.5);
813 if (simplerect
->outline_what
& 0x2) {
814 /* right edge, if visible */
815 if (x_in_range (simplerect
->bbox_lrx
)) {
816 cairo_move_to (cr
, lrx
+0.5, uly
+0.5);
817 cairo_line_to (cr
, lrx
+0.5, lry
+0.5);
822 if (simplerect
->outline_what
& 0x4) {
824 if (y_in_range (simplerect
->bbox_uly
)) {
825 cairo_move_to (cr
, ulx
+0.5, uly
+0.5);
826 cairo_line_to (cr
, lrx
+0.5, uly
+0.5);
831 if (simplerect
->outline_what
& 0x8) {
833 if (y_in_range (simplerect
->bbox_lry
)) {
834 cairo_move_to (cr
, ulx
+0.5, lry
+0.5);
835 cairo_line_to (cr
, lrx
+0.5, lry
+0.5);
845 gnome_canvas_simplerect_point (GnomeCanvasItem
*item
, double x
, double y
, int cx
, int cy
, GnomeCanvasItem
**actual_item
)
850 GnomeCanvasSimpleRect
*simplerect
;
851 double x1
, y1
, x2
, y2
;
854 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
858 /* Find the bounds for the rectangle plus its outline width */
860 gnome_canvas_simplerect_bounds (item
, &x1
, &y1
, &x2
, &y2
);
862 /* Is point inside rectangle */
864 if ((x
>= x1
) && (y
>= y1
) && (x
<= x2
) && (y
<= y2
)) {
868 /* Point is outside rectangle */
884 return sqrt (dx
* dx
+ dy
* dy
);