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
,
26 static void gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass
*class);
28 static void gnome_canvas_simplerect_init (GnomeCanvasSimpleRect
*simplerect
);
30 static void gnome_canvas_simplerect_destroy (GtkObject
*object
);
32 static void gnome_canvas_simplerect_set_property (GObject
*object
,
37 static void gnome_canvas_simplerect_get_property (GObject
*object
,
42 static void gnome_canvas_simplerect_update (GnomeCanvasItem
*item
,
47 static void gnome_canvas_simplerect_bounds (GnomeCanvasItem
*item
,
53 static double gnome_canvas_simplerect_point (GnomeCanvasItem
*item
, double x
, double y
, int cx
, int cy
, GnomeCanvasItem
**actual_item
);
55 static void gnome_canvas_simplerect_render (GnomeCanvasItem
*item
, GnomeCanvasBuf
*buf
);
57 static void gnome_canvas_simplerect_draw (GnomeCanvasItem
*item
, GdkDrawable
*drawable
, int x
, int y
, int w
, int h
);
59 static GnomeCanvasItemClass
*parent_class
;
63 gnome_canvas_simplerect_get_type (void)
65 static GType simplerect_type
;
67 if (!simplerect_type
) {
68 static const GTypeInfo object_info
= {
69 sizeof (GnomeCanvasSimpleRectClass
),
71 (GBaseFinalizeFunc
) NULL
,
72 (GClassInitFunc
) gnome_canvas_simplerect_class_init
,
73 (GClassFinalizeFunc
) NULL
,
74 NULL
, /* class_data */
75 sizeof (GnomeCanvasSimpleRect
),
77 (GInstanceInitFunc
) gnome_canvas_simplerect_init
,
78 NULL
/* value_table */
81 simplerect_type
= g_type_register_static (GNOME_TYPE_CANVAS_ITEM
, "GnomeCanvasSimpleRect",
85 return simplerect_type
;
89 gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass
*class)
91 GObjectClass
*gobject_class
;
92 GtkObjectClass
*object_class
;
93 GnomeCanvasItemClass
*item_class
;
95 gobject_class
= (GObjectClass
*) class;
96 object_class
= (GtkObjectClass
*) class;
97 item_class
= (GnomeCanvasItemClass
*) class;
99 parent_class
= g_type_class_peek_parent (class);
101 gobject_class
->set_property
= gnome_canvas_simplerect_set_property
;
102 gobject_class
->get_property
= gnome_canvas_simplerect_get_property
;
104 g_object_class_install_property (gobject_class
,
106 g_param_spec_double ("x1",
108 _("x coordinate of upper left corner of rect"),
114 g_object_class_install_property (gobject_class
,
116 g_param_spec_double ("y1",
118 _("y coordinate of upper left corner of rect "),
125 g_object_class_install_property (gobject_class
,
127 g_param_spec_double ("x2",
129 _("x coordinate of lower right corner of rect"),
135 g_object_class_install_property (gobject_class
,
137 g_param_spec_double ("y2",
139 _("y coordinate of lower right corner of rect "),
146 g_object_class_install_property (gobject_class
,
148 g_param_spec_uint ("outline_pixels",
150 _("width in pixels of outline"),
157 g_object_class_install_property (gobject_class
,
159 g_param_spec_uint ("outline_what",
161 _("which boundaries to outline (mask)"),
169 g_object_class_install_property (gobject_class
,
171 g_param_spec_boolean ("fill",
177 g_object_class_install_property (gobject_class
,
179 g_param_spec_boolean ("draw",
186 g_object_class_install_property (gobject_class
,
187 PROP_OUTLINE_COLOR_RGBA
,
188 g_param_spec_uint ("outline_color_rgba",
189 _("outline color rgba"),
190 _("color of outline"),
197 g_object_class_install_property (gobject_class
,
198 PROP_FILL_COLOR_RGBA
,
199 g_param_spec_uint ("fill_color_rgba",
200 _("fill color rgba"),
207 object_class
->destroy
= gnome_canvas_simplerect_destroy
;
209 item_class
->update
= gnome_canvas_simplerect_update
;
210 item_class
->draw
= gnome_canvas_simplerect_draw
;
211 item_class
->bounds
= gnome_canvas_simplerect_bounds
;
212 item_class
->point
= gnome_canvas_simplerect_point
;
213 item_class
->render
= gnome_canvas_simplerect_render
;
218 gnome_canvas_simplerect_init (GnomeCanvasSimpleRect
*simplerect
)
220 simplerect
->x1
= 0.0;
221 simplerect
->y1
= 0.0;
222 simplerect
->x2
= 0.0;
223 simplerect
->y2
= 0.0;
224 simplerect
->fill
= TRUE
;
225 simplerect
->draw
= TRUE
;
226 simplerect
->full_draw_on_update
= TRUE
;
227 simplerect
->fill_color
= 0;
228 simplerect
->outline_color
= 0;
229 simplerect
->outline_pixels
= 1;
230 simplerect
->outline_what
= 0xf;
234 gnome_canvas_simplerect_destroy (GtkObject
*object
)
236 GnomeCanvasSimpleRect
*rect
;
238 g_return_if_fail (object
!= NULL
);
239 g_return_if_fail (GNOME_IS_CANVAS_SIMPLERECT (object
));
241 rect
= GNOME_CANVAS_SIMPLERECT (object
);
243 /* remember, destroy can be run multiple times! */
245 if (GTK_OBJECT_CLASS (parent_class
)->destroy
)
246 (* GTK_OBJECT_CLASS (parent_class
)->destroy
) (object
);
250 gnome_canvas_simplerect_bounds (GnomeCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
)
252 GnomeCanvasSimpleRect
*simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
254 *x1
= simplerect
->x1
;
255 *y1
= simplerect
->y1
;
256 *x2
= simplerect
->x2
+ 1;
257 *y2
= simplerect
->y2
+ 1;
263 gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem
*item
)
265 GnomeCanvasSimpleRect
* simplerect
;
266 double x1
, x2
, y1
, y2
;
267 double old_x1
, old_x2
, old_y1
, old_y2
;
268 ArtDRect unionrect
, old
, new;
275 gnome_canvas_simplerect_bounds (item
, &x1
, &y1
, &x2
, &y2
);
276 gnome_canvas_item_i2w (item
, &x1
, &y1
);
277 gnome_canvas_item_i2w (item
, &x2
, &y2
);
284 /* now compute bounding box in canvas units */
286 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
288 gnome_canvas_w2c (GNOME_CANVAS(item
->canvas
), x1
, y1
, &simplerect
->bbox_ulx
, &simplerect
->bbox_uly
);
289 gnome_canvas_w2c (GNOME_CANVAS(item
->canvas
), x2
, y2
, &simplerect
->bbox_lrx
, &simplerect
->bbox_lry
);
291 /* now queue redraws for changed areas */
293 if (item
->x1
== old_x1
&& item
->x2
== old_x2
) {
295 /* no change in x-axis position */
297 if (item
->y1
== old_y1
) {
298 /* top didn't change, so just draw bottom */
300 double start_y
= MIN (item
->y2
, old_y2
);
301 double end_y
= MAX (item
->y2
, old_y2
);
303 gnome_canvas_request_redraw (item
->canvas
, item
->x1
, start_y
- 0.5, item
->x2
, end_y
+ 1.5);
306 } else if (item
->y2
== old_y2
) {
308 /* bottom didn't change, just draw top */
310 double start_y
= MIN (item
->y1
, old_y1
);
311 double end_y
= MAX (item
->y1
, old_y1
);
313 gnome_canvas_request_redraw (item
->canvas
, item
->x1
, start_y
- 0.5, item
->x2
, end_y
+ 1.5);
318 } else if (item
->y1
== old_y1
&& item
->y2
== old_y2
) {
320 /* no change in y-axis position */
322 if (item
->x1
== old_x1
) {
323 /* start didn't change, so just draw at the end */
325 double start_x
= MIN (item
->x2
, old_x2
);
326 double end_x
= MAX (item
->x2
, old_x2
);
328 gnome_canvas_request_redraw (item
->canvas
, start_x
- 0.5, item
->y1
, end_x
+ 1.5, item
->y2
);
331 } else if (item
->x2
== old_x2
) {
333 /* end didn't change, so just draw at the start */
335 double start_x
= MIN (item
->x1
, old_x1
);
336 double end_x
= MAX (item
->x1
, old_x1
);
338 gnome_canvas_request_redraw (item
->canvas
, start_x
- 0.5, item
->y1
, end_x
+ 1.5, item
->y2
+ 0.5);
354 art_drect_union (&unionrect
, &old
, &new);
355 gnome_canvas_request_redraw (item
->canvas
,
367 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 simplerect
->full_draw_on_update
= update
;
459 if (update
|| bounds_changed
) {
460 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(object
));
465 gnome_canvas_simplerect_get_property (GObject
*object
,
470 GnomeCanvasSimpleRect
*rect
= GNOME_CANVAS_SIMPLERECT (object
);
472 g_return_if_fail (object
!= NULL
);
473 g_return_if_fail (GNOME_IS_CANVAS_SIMPLERECT (object
));
477 g_value_set_double (value
, rect
->x1
);
480 g_value_set_double (value
, rect
->x2
);
483 g_value_set_double (value
, rect
->y1
);
486 g_value_set_double (value
, rect
->y2
);
488 case PROP_OUTLINE_WHAT
:
489 g_value_set_uint (value
, rect
->outline_what
);
492 g_value_set_boolean (value
, rect
->fill
);
494 case PROP_OUTLINE_PIXELS
:
495 g_value_set_uint (value
, rect
->outline_pixels
);
497 case PROP_FILL_COLOR_RGBA
:
498 g_value_set_uint (value
, rect
->fill_color
);
500 case PROP_OUTLINE_COLOR_RGBA
:
501 g_value_set_uint (value
, rect
->outline_color
);
504 g_value_set_boolean (value
, rect
->draw
);
508 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
515 gnome_canvas_simplerect_update (GnomeCanvasItem
*item
, double *affine
, ArtSVP
*clip_path
, int flags
)
517 GnomeCanvasSimpleRect
*simplerect
;
520 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
522 if (parent_class
->update
)
523 (* parent_class
->update
) (item
, affine
, clip_path
, flags
);
525 gnome_canvas_simplerect_reset_bounds (item
);
527 if (simplerect
->full_draw_on_update
) {
528 gnome_canvas_request_redraw (item
->canvas
,
529 simplerect
->bbox_ulx
,
530 simplerect
->bbox_uly
,
531 simplerect
->bbox_lrx
+0.5,
532 simplerect
->bbox_lry
+0.5);
533 simplerect
->full_draw_on_update
= FALSE
;
536 UINT_TO_RGBA (simplerect
->fill_color
, &simplerect
->fill_r
, &simplerect
->fill_g
, &simplerect
->fill_b
, &simplerect
->fill_a
);
537 UINT_TO_RGBA (simplerect
->outline_color
, &simplerect
->outline_r
, &simplerect
->outline_g
, &simplerect
->outline_b
, &foo
);
540 // this can be useful for debugging/understanding how the canvas redraws
543 #undef HARLEQUIN_DEBUGGING
545 #undef SIMPLERECT_FAST_RENDERER
546 #ifdef SIMPLERECT_FAST_RENDERER
549 gnome_canvas_simplerect_render (GnomeCanvasItem
*item
,
552 GnomeCanvasSimpleRect
*simplerect
;
556 ArtIRect intersection
;
559 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
561 if (parent_class
->render
) {
562 (*parent_class
->render
) (item
, buf
);
567 #ifdef HARLEQUIN_DEBUGGING
568 gint randr
, randg
, randb
;
569 randr
= random() % 255;
570 randg
= random() % 255;
571 randb
= random() % 255;
572 PAINT_BOX(buf
, randr
, randg
, randb
, 255, buf
->rect
.x0
, buf
->rect
.y0
, buf
->rect
.x1
, buf
->rect
.y1
);
574 gnome_canvas_buf_ensure_buf (buf
);
578 if (!simplerect
->draw
) {
582 self
.x0
= simplerect
->bbox_ulx
;
583 self
.y0
= simplerect
->bbox_uly
;
584 self
.x1
= simplerect
->bbox_lrx
;
585 self
.y1
= simplerect
->bbox_lry
;
587 art_irect_intersect (&intersection
, &self
, &buf
->rect
);
589 begin
= MAX(simplerect
->bbox_ulx
, buf
->rect
.x0
);
590 end
= MIN((simplerect
->bbox_lrx
-1), buf
->rect
.x1
);
592 sy
= simplerect
->bbox_uly
;
593 ey
= simplerect
->bbox_lry
-1;
595 if (simplerect
->fill
) {
597 // this can be useful for debugging/understanding how the canvas redraws
600 #ifdef HARLEQUIN_DEBUGGING
601 gint randr
, randg
, randb
;
602 randr
= random() % 255;
603 randg
= random() % 255;
604 randb
= random() % 255;
605 PAINT_BOX(buf
, randr
, randg
, randb
, simplerect
->fill_a
, begin
, sy
, end
, ey
);
607 PAINT_BOX (buf
, simplerect
->fill_r
, simplerect
->fill_g
, simplerect
->fill_b
, simplerect
->fill_a
,
608 intersection
.x0
, intersection
.y0
,
609 intersection
.x1
, intersection
.y1
);
614 for (i
= 0; i
< simplerect
->outline_pixels
; ++i
) {
616 if (simplerect
->outline_what
& 0x1) {
617 if (begin
== simplerect
->bbox_ulx
) {
618 PAINT_VERT(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, begin
+ i
, sy
, ey
);
622 if (simplerect
->outline_what
& 0x2) {
623 if (end
== (simplerect
->bbox_lrx
- 1)) {
624 PAINT_VERT(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, end
- i
, sy
, ey
+ 1);
628 if (simplerect
->outline_what
& 0x4) {
629 PAINT_HORIZ(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, begin
, end
, sy
+i
);
632 if (simplerect
->outline_what
& 0x8) {
633 PAINT_HORIZ(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, begin
, end
+ 1, ey
-i
);
638 #else /* SIMPLERECT_FAST_RENDERER */
641 gnome_canvas_simplerect_render (GnomeCanvasItem
*item
,
644 GnomeCanvasSimpleRect
*simplerect
;
649 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
651 if (parent_class
->render
) {
652 (*parent_class
->render
) (item
, buf
);
657 #ifdef HARLEQUIN_DEBUGGING
658 gint randr
, randg
, randb
;
659 randr
= random() % 255;
660 randg
= random() % 255;
661 randb
= random() % 255;
662 PAINT_BOX(buf
, randr
, randg
, randb
, 255, buf
->rect
.x0
, buf
->rect
.y0
, buf
->rect
.x1
, buf
->rect
.y1
);
664 gnome_canvas_buf_ensure_buf (buf
);
668 if (!simplerect
->draw
) {
672 begin
= MAX(simplerect
->bbox_ulx
,buf
->rect
.x0
);
673 end
= MIN((simplerect
->bbox_lrx
-1),buf
->rect
.x1
);
675 sy
= simplerect
->bbox_uly
;
676 ey
= simplerect
->bbox_lry
-1;
678 if (simplerect
->fill
) {
680 #ifdef HARLEQUIN_DEBUGGING
681 gint randr
, randg
, randb
;
682 randr
= random() % 255;
683 randg
= random() % 255;
684 randb
= random() % 255;
685 PAINT_BOX(buf
, randr
, randg
, randb
, simplerect
->fill_a
, begin
, sy
, end
, ey
);
687 PAINT_BOX(buf
, simplerect
->fill_r
, simplerect
->fill_g
, simplerect
->fill_b
, simplerect
->fill_a
, begin
, sy
, end
, ey
);
691 for (i
= 0; i
< simplerect
->outline_pixels
; ++i
) {
693 if (simplerect
->outline_what
& 0x1) {
694 if (begin
== simplerect
->bbox_ulx
) {
695 PAINT_VERT(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, begin
+ i
, sy
, ey
);
699 if (simplerect
->outline_what
& 0x2) {
700 if (end
== (simplerect
->bbox_lrx
- 1)) {
701 PAINT_VERT(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, end
- i
, sy
, ey
+ 1);
705 if (simplerect
->outline_what
& 0x4) {
706 PAINT_HORIZ(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, begin
, end
, sy
+i
);
709 if (simplerect
->outline_what
& 0x8) {
710 PAINT_HORIZ(buf
, simplerect
->outline_r
, simplerect
->outline_g
, simplerect
->outline_b
, begin
, end
+ 1, ey
-i
);
714 #endif /* SIMPLERECT_FAST_RENDERER */
717 gnome_canvas_simplerect_draw (GnomeCanvasItem
*item
,
718 GdkDrawable
*drawable
,
720 int width
, int height
)
722 GnomeCanvasSimpleRect
*simplerect
;
729 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
731 cr
= gdk_cairo_create (drawable
);
733 if (x
> simplerect
->bbox_ulx
) {
736 ulx
= simplerect
->bbox_ulx
;
739 if (y
> simplerect
->bbox_uly
) {
742 uly
= simplerect
->bbox_uly
;
745 if (x
+ width
> simplerect
->bbox_lrx
) {
746 lrx
= simplerect
->bbox_lrx
;
751 if (y
+ height
> simplerect
->bbox_lry
) {
752 lry
= simplerect
->bbox_lry
;
762 cairo_rectangle (cr
, ulx
, uly
, lrx
- ulx
, lry
- uly
);
764 if (simplerect
->fill
) {
765 cairo_set_source_rgba (cr
,
766 simplerect
->fill_r
/255.0,
767 simplerect
->fill_g
/255.0,
768 simplerect
->fill_b
/255.0,
769 simplerect
->fill_a
/255.0);
773 if (simplerect
->outline_what
&& simplerect
->outline_pixels
) {
775 #define x_in_range(a) (x <= (a) && (a) < x + width)
776 #define y_in_range(a) (y <= (a) && (a) < y + height)
778 cairo_set_line_width (cr
, simplerect
->outline_pixels
);
780 cairo_set_source_rgb (cr
,
781 simplerect
->outline_r
/255.0,
782 simplerect
->outline_g
/255.0,
783 simplerect
->outline_b
/255.0);
785 if (simplerect
->outline_what
& 0x1) {
786 /* left edge, if visible */
787 if (x_in_range (simplerect
->bbox_ulx
)) {
788 cairo_move_to (cr
, ulx
+0.5, uly
+0.5);
789 cairo_line_to (cr
, ulx
+0.5, lry
+0.5);
794 if (simplerect
->outline_what
& 0x2) {
795 /* right edge, if visible */
796 if (x_in_range (simplerect
->bbox_lrx
)) {
797 cairo_move_to (cr
, lrx
+0.5, uly
+0.5);
798 cairo_line_to (cr
, lrx
+0.5, lry
+0.5);
803 if (simplerect
->outline_what
& 0x4) {
805 if (y_in_range (simplerect
->bbox_uly
)) {
806 cairo_move_to (cr
, ulx
+0.5, uly
+0.5);
807 cairo_line_to (cr
, lrx
+0.5, uly
+0.5);
812 if (simplerect
->outline_what
& 0x8) {
814 if (y_in_range (simplerect
->bbox_lry
)) {
815 cairo_move_to (cr
, ulx
+0.5, lry
+0.5);
816 cairo_line_to (cr
, lrx
+0.5, lry
+0.5);
826 gnome_canvas_simplerect_point (GnomeCanvasItem
*item
, double x
, double y
, int cx
, int cy
, GnomeCanvasItem
**actual_item
)
828 GnomeCanvasSimpleRect
*simplerect
;
829 double x1
, y1
, x2
, y2
;
832 simplerect
= GNOME_CANVAS_SIMPLERECT (item
);
836 /* Find the bounds for the rectangle plus its outline width */
838 gnome_canvas_simplerect_bounds (item
, &x1
, &y1
, &x2
, &y2
);
840 /* Is point inside rectangle */
842 if ((x
>= x1
) && (y
>= y1
) && (x
<= x2
) && (y
<= y2
)) {
846 /* Point is outside rectangle */
862 return sqrt (dx
* dx
+ dy
* dy
);