2 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
5 * This file is part of the Gnome Library.
7 * The Gnome Library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * The Gnome Library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with the Gnome Library; see the file COPYING.LIB. If not,
19 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 /* Rectangle and ellipse item types for FooCanvas widget
27 * FooCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
28 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
31 * Author: Federico Mena <federico@nuclecu.unam.mx>
36 #include "foo-canvas-rect-ellipse.h"
37 #include "foo-canvas-util.h"
42 #include <X11/extensions/Xrender.h>
45 /* Base class for rectangle and ellipse item types */
59 PROP_OUTLINE_COLOR_GDK
,
60 PROP_OUTLINE_COLOR_RGBA
,
69 static void foo_canvas_re_class_init (FooCanvasREClass
*klass
);
70 static void foo_canvas_re_init (FooCanvasRE
*re
);
71 static void foo_canvas_re_destroy (GtkObject
*object
);
72 static void foo_canvas_re_set_property (GObject
*object
,
76 static void foo_canvas_re_get_property (GObject
*object
,
81 static void foo_canvas_re_update_shared (FooCanvasItem
*item
,
82 double i2w_dx
, double i2w_dy
, int flags
);
83 static void foo_canvas_re_realize (FooCanvasItem
*item
);
84 static void foo_canvas_re_bounds (FooCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
);
85 static void foo_canvas_re_translate (FooCanvasItem
*item
, double dx
, double dy
);
86 static void foo_canvas_rect_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, int flags
);
87 static void foo_canvas_ellipse_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, int flags
);
94 static Rect
make_rect (int x0
, int y0
, int x1
, int y1
);
95 static void diff_rects (Rect r1
, Rect r2
, int *count
, Rect result
[4]);
97 static FooCanvasItemClass
*re_parent_class
;
98 static FooCanvasREClass
*rect_parent_class
;
102 foo_canvas_re_get_type (void)
104 static GType re_type
= 0;
107 GTypeInfo re_info
= {
108 sizeof (FooCanvasREClass
),
109 (GBaseInitFunc
) NULL
,
110 (GBaseFinalizeFunc
) NULL
,
111 (GClassInitFunc
) foo_canvas_re_class_init
,
112 NULL
, /* class_finalize */
113 NULL
, /* class_data */
114 sizeof (FooCanvasRE
),
116 (GInstanceInitFunc
) foo_canvas_re_init
119 re_type
= g_type_register_static (foo_canvas_item_get_type (),
129 foo_canvas_re_class_init (FooCanvasREClass
*klass
)
131 GObjectClass
*gobject_class
;
132 GtkObjectClass
*object_class
;
133 FooCanvasItemClass
*item_class
;
135 gobject_class
= (GObjectClass
*) klass
;
136 object_class
= (GtkObjectClass
*) klass
;
137 item_class
= (FooCanvasItemClass
*) klass
;
139 re_parent_class
= g_type_class_peek_parent (klass
);
141 gobject_class
->set_property
= foo_canvas_re_set_property
;
142 gobject_class
->get_property
= foo_canvas_re_get_property
;
144 g_object_class_install_property
147 g_param_spec_double ("x1", NULL
, NULL
,
148 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0,
150 g_object_class_install_property
153 g_param_spec_double ("y1", NULL
, NULL
,
154 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0,
156 g_object_class_install_property
159 g_param_spec_double ("x2", NULL
, NULL
,
160 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0,
162 g_object_class_install_property
165 g_param_spec_double ("y2", NULL
, NULL
,
166 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0,
168 g_object_class_install_property
171 g_param_spec_string ("fill-color", NULL
, NULL
,
174 g_object_class_install_property
177 g_param_spec_boxed ("fill-color-gdk", NULL
, NULL
,
180 g_object_class_install_property
182 PROP_FILL_COLOR_RGBA
,
183 g_param_spec_uint ("fill-color-rgba", NULL
, NULL
,
186 g_object_class_install_property
189 g_param_spec_object ("fill-stipple", NULL
, NULL
,
192 g_object_class_install_property
195 g_param_spec_string ("outline-color", NULL
, NULL
,
198 g_object_class_install_property
200 PROP_OUTLINE_COLOR_GDK
,
201 g_param_spec_boxed ("outline-color-gdk", NULL
, NULL
,
204 g_object_class_install_property
206 PROP_OUTLINE_COLOR_RGBA
,
207 g_param_spec_uint ("outline-color-rgba", NULL
, NULL
,
210 g_object_class_install_property
212 PROP_OUTLINE_STIPPLE
,
213 g_param_spec_object ("outline-stipple", NULL
, NULL
,
216 g_object_class_install_property
219 g_param_spec_uint ("width-pixels", NULL
, NULL
,
222 g_object_class_install_property
225 g_param_spec_double ("width-units", NULL
, NULL
,
226 0.0, G_MAXDOUBLE
, 0.0,
228 g_object_class_install_property
231 g_param_spec_boolean ("aa", NULL
, NULL
,
235 object_class
->destroy
= foo_canvas_re_destroy
;
237 item_class
->realize
= foo_canvas_re_realize
;
238 item_class
->translate
= foo_canvas_re_translate
;
239 item_class
->bounds
= foo_canvas_re_bounds
;
243 foo_canvas_re_init (FooCanvasRE
*re
)
254 foo_canvas_re_destroy (GtkObject
*object
)
258 g_return_if_fail (object
!= NULL
);
259 g_return_if_fail (FOO_IS_CANVAS_RE (object
));
261 re
= FOO_CANVAS_RE (object
);
263 /* remember, destroy can be run multiple times! */
265 if (re
->fill_stipple
)
266 g_object_unref (re
->fill_stipple
);
267 re
->fill_stipple
= NULL
;
269 if (re
->outline_stipple
)
270 g_object_unref (re
->outline_stipple
);
271 re
->outline_stipple
= NULL
;
273 if (GTK_OBJECT_CLASS (re_parent_class
)->destroy
)
274 (* GTK_OBJECT_CLASS (re_parent_class
)->destroy
) (object
);
278 get_draw_width_pixels (FooCanvasRE
*re
)
281 if (re
->width_pixels
)
284 width
= re
->width
* re
->item
.canvas
->pixels_per_unit
;
285 width
+= 2.0; /* AA puts 1 px around for fuzzing */
290 get_draw_width_units (FooCanvasRE
*re
)
292 double width
= get_draw_width_pixels (re
);
293 return (width
/ re
->item
.canvas
->pixels_per_unit
);
296 static void get_bounds (FooCanvasRE
*re
, double *px1
, double *py1
, double *px2
, double *py2
)
299 double x1
, y1
, x2
, y2
;
300 int cx1
, cy1
, cx2
, cy2
;
304 g_print ("re get_bounds\n");
306 item
= FOO_CANVAS_ITEM (re
);
308 hwidth
= get_draw_width_units (re
) / 2.0;
314 foo_canvas_item_i2w (item
, &x1
, &y1
);
315 foo_canvas_item_i2w (item
, &x2
, &y2
);
316 foo_canvas_w2c (item
->canvas
, x1
- hwidth
, y1
- hwidth
, &cx1
, &cy1
);
317 foo_canvas_w2c (item
->canvas
, x2
+ hwidth
, y2
+ hwidth
, &cx2
, &cy2
);
323 /* Some safety fudging */
332 foo_canvas_re_set_fill (FooCanvasRE
*re
, gboolean fill_set
)
334 if (re
->fill_set
!= fill_set
) {
335 re
->fill_set
= fill_set
;
336 foo_canvas_item_request_update (FOO_CANVAS_ITEM (re
));
341 foo_canvas_re_set_outline (FooCanvasRE
*re
, gboolean outline_set
)
343 if (re
->outline_set
!= outline_set
) {
344 re
->outline_set
= outline_set
;
345 foo_canvas_item_request_update (FOO_CANVAS_ITEM (re
));
350 foo_canvas_re_set_property (GObject
*object
,
357 GdkColor color
= { 0, 0, 0, 0, };
361 g_return_if_fail (object
!= NULL
);
362 g_return_if_fail (FOO_IS_CANVAS_RE (object
));
364 item
= FOO_CANVAS_ITEM (object
);
365 re
= FOO_CANVAS_RE (object
);
370 re
->x1
= g_value_get_double (value
);
372 foo_canvas_item_request_update (item
);
376 re
->y1
= g_value_get_double (value
);
378 foo_canvas_item_request_update (item
);
382 re
->x2
= g_value_get_double (value
);
384 foo_canvas_item_request_update (item
);
388 re
->y2
= g_value_get_double (value
);
390 foo_canvas_item_request_update (item
);
393 case PROP_FILL_COLOR
:
394 case PROP_FILL_COLOR_GDK
:
395 case PROP_FILL_COLOR_RGBA
:
397 case PROP_FILL_COLOR
:
398 if (g_value_get_string (value
) &&
399 gdk_color_parse (g_value_get_string (value
), &color
))
400 foo_canvas_re_set_fill (re
, TRUE
);
402 foo_canvas_re_set_fill (re
, FALSE
);
404 re
->fill_color
= ((color
.red
& 0xff00) << 16 |
405 (color
.green
& 0xff00) << 8 |
406 (color
.blue
& 0xff00) |
410 case PROP_FILL_COLOR_GDK
:
411 pcolor
= g_value_get_boxed (value
);
412 foo_canvas_re_set_fill (re
, pcolor
!= NULL
);
415 GdkColormap
*colormap
;
418 colormap
= gtk_widget_get_colormap (GTK_WIDGET (item
->canvas
));
419 gdk_rgb_find_color (colormap
, &color
);
423 re
->fill_color
= ((color
.red
& 0xff00) << 16 |
424 (color
.green
& 0xff00) << 8 |
425 (color
.blue
& 0xff00) |
429 case PROP_FILL_COLOR_RGBA
:
430 foo_canvas_re_set_fill (re
, TRUE
);
431 re
->fill_color
= g_value_get_uint (value
);
435 g_print ("re fill color = %08x\n", re
->fill_color
);
438 re
->fill_pixel
= color
.pixel
;
440 re
->fill_pixel
= foo_canvas_get_color_pixel (item
->canvas
, re
->fill_color
);
442 foo_canvas_item_request_redraw (item
);
445 case PROP_OUTLINE_COLOR
:
446 case PROP_OUTLINE_COLOR_GDK
:
447 case PROP_OUTLINE_COLOR_RGBA
:
449 case PROP_OUTLINE_COLOR
:
450 if (g_value_get_string (value
) &&
451 gdk_color_parse (g_value_get_string (value
), &color
))
452 foo_canvas_re_set_outline (re
, TRUE
);
454 foo_canvas_re_set_outline (re
, FALSE
);
456 re
->outline_color
= ((color
.red
& 0xff00) << 16 |
457 (color
.green
& 0xff00) << 8 |
458 (color
.blue
& 0xff00) |
462 case PROP_OUTLINE_COLOR_GDK
:
463 pcolor
= g_value_get_boxed (value
);
464 foo_canvas_re_set_outline (re
, pcolor
!= NULL
);
467 GdkColormap
*colormap
;
470 colormap
= gtk_widget_get_colormap (GTK_WIDGET (item
->canvas
));
471 gdk_rgb_find_color (colormap
, &color
);
476 re
->outline_color
= ((color
.red
& 0xff00) << 16 |
477 (color
.green
& 0xff00) << 8 |
478 (color
.blue
& 0xff00) |
482 case PROP_OUTLINE_COLOR_RGBA
:
483 foo_canvas_re_set_outline (re
, TRUE
);
484 re
->outline_color
= g_value_get_uint (value
);
488 g_print ("re outline color %x %x %x\n", color
.red
, color
.green
, color
.blue
);
491 re
->outline_pixel
= color
.pixel
;
493 re
->outline_pixel
= foo_canvas_get_color_pixel (item
->canvas
,
496 foo_canvas_item_request_redraw (item
);
499 case PROP_FILL_STIPPLE
:
500 if (re
->fill_stipple
)
501 g_object_unref (re
->fill_stipple
);
502 re
->fill_stipple
= (GdkBitmap
*) g_value_get_object (value
);
503 g_object_ref (re
->fill_stipple
);
506 case PROP_OUTLINE_STIPPLE
:
507 if (re
->outline_stipple
)
508 g_object_unref (re
->outline_stipple
);
509 re
->outline_stipple
= (GdkBitmap
*) g_value_get_object (value
);
510 g_object_ref (re
->outline_stipple
);
513 case PROP_WIDTH_PIXELS
:
514 re
->width
= g_value_get_uint (value
);
515 re
->width_pixels
= TRUE
;
516 foo_canvas_item_request_update (item
);
519 case PROP_WIDTH_UNITS
:
520 re
->width
= fabs (g_value_get_double (value
));
521 re
->width_pixels
= FALSE
;
522 foo_canvas_item_request_update (item
);
526 re
->aa
= g_value_get_boolean (value
);
527 foo_canvas_item_request_update (item
);
531 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
536 /* Allocates a GdkColor structure filled with the specified pixel, and puts it into the specified
537 * value for returning it in the get_property method.
540 get_color_value (FooCanvasRE
*re
, gulong pixel
, GValue
*value
)
543 FooCanvasItem
*item
= (FooCanvasItem
*) re
;
544 GdkColormap
*colormap
= gtk_widget_get_colormap (GTK_WIDGET (item
->canvas
));
546 gdk_colormap_query_color (colormap
, pixel
, &color
);
547 g_value_set_boxed (value
, &color
);
551 foo_canvas_re_get_property (GObject
*object
,
558 g_return_if_fail (object
!= NULL
);
559 g_return_if_fail (FOO_IS_CANVAS_RE (object
));
561 re
= FOO_CANVAS_RE (object
);
565 g_value_set_double (value
, re
->x1
);
569 g_value_set_double (value
, re
->y1
);
573 g_value_set_double (value
, re
->x2
);
577 g_value_set_double (value
, re
->y2
);
580 case PROP_FILL_COLOR_GDK
:
581 get_color_value (re
, re
->fill_pixel
, value
);
584 case PROP_OUTLINE_COLOR_GDK
:
585 get_color_value (re
, re
->outline_pixel
, value
);
588 case PROP_FILL_COLOR_RGBA
:
589 g_value_set_uint (value
, re
->fill_color
);
592 case PROP_OUTLINE_COLOR_RGBA
:
593 g_value_set_uint (value
, re
->outline_color
);
596 case PROP_FILL_STIPPLE
:
597 g_value_set_object (value
, (GObject
*) re
->fill_stipple
);
600 case PROP_OUTLINE_STIPPLE
:
601 g_value_set_object (value
, (GObject
*) re
->outline_stipple
);
605 g_value_set_boolean (value
, re
->aa
);
609 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
615 foo_canvas_re_update_shared (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, int flags
)
620 g_print ("foo_canvas_re_update_shared\n");
622 re
= FOO_CANVAS_RE (item
);
624 if (re_parent_class
->update
)
625 (* re_parent_class
->update
) (item
, i2w_dx
, i2w_dy
, flags
);
633 foo_canvas_re_realize (FooCanvasItem
*item
)
638 g_print ("foo_canvas_re_realize\n");
640 re
= FOO_CANVAS_RE (item
);
642 if (re_parent_class
->realize
)
643 (* re_parent_class
->realize
) (item
);
645 re
->fill_pixel
= foo_canvas_get_color_pixel (item
->canvas
, re
->fill_color
);
646 re
->outline_pixel
= foo_canvas_get_color_pixel (item
->canvas
, re
->outline_color
);
649 (* FOO_CANVAS_ITEM_CLASS (item
->object
.klass
)->update
) (item
, NULL
, NULL
, 0);
654 foo_canvas_re_translate (FooCanvasItem
*item
, double dx
, double dy
)
659 g_print ("foo_canvas_re_translate\n");
661 re
= FOO_CANVAS_RE (item
);
670 foo_canvas_re_bounds (FooCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
)
676 g_print ("foo_canvas_re_bounds\n");
678 re
= FOO_CANVAS_RE (item
);
680 hwidth
= get_draw_width_units (re
) / 2.0;
682 *x1
= re
->x1
- hwidth
;
683 *y1
= re
->y1
- hwidth
;
684 *x2
= re
->x2
+ hwidth
;
685 *y2
= re
->y2
+ hwidth
;
691 static void foo_canvas_rect_class_init (FooCanvasRectClass
*klass
);
692 static void foo_canvas_rect_init (FooCanvasRect
*rect
);
693 static void foo_canvas_rect_finalize (GObject
*object
);
694 static void foo_canvas_rect_realize (FooCanvasItem
*item
);
696 static void foo_canvas_rect_draw (FooCanvasItem
*item
, GdkDrawable
*drawable
, GdkEventExpose
*expose
);
697 static double foo_canvas_rect_point (FooCanvasItem
*item
, double x
, double y
, int cx
, int cy
,
698 FooCanvasItem
**actual_item
);
700 struct _FooCanvasRectPrivate
{
701 Rect last_update_rect
;
702 Rect last_outline_update_rect
;
703 int last_outline_update_width
;
707 XRenderPictFormat
*format
;
712 foo_canvas_rect_get_type (void)
714 static GType rect_type
= 0;
717 GTypeInfo rect_info
= {
718 sizeof (FooCanvasRectClass
),
719 (GBaseInitFunc
) NULL
,
720 (GBaseFinalizeFunc
) NULL
,
721 (GClassInitFunc
) foo_canvas_rect_class_init
,
722 NULL
, /* class_finalize */
723 NULL
, /* class_data */
724 sizeof (FooCanvasRect
),
726 (GInstanceInitFunc
) foo_canvas_rect_init
729 rect_type
= g_type_register_static (foo_canvas_re_get_type (),
739 foo_canvas_rect_class_init (FooCanvasRectClass
*klass
)
741 FooCanvasItemClass
*item_class
;
743 rect_parent_class
= g_type_class_peek_parent (klass
);
745 item_class
= (FooCanvasItemClass
*) klass
;
747 item_class
->draw
= foo_canvas_rect_draw
;
748 item_class
->point
= foo_canvas_rect_point
;
749 item_class
->update
= foo_canvas_rect_update
;
750 item_class
->realize
= foo_canvas_rect_realize
;
752 G_OBJECT_CLASS (klass
)->finalize
= foo_canvas_rect_finalize
;
757 foo_canvas_rect_init (FooCanvasRect
*rect
)
759 rect
->priv
= g_new0 (FooCanvasRectPrivate
, 1);
763 foo_canvas_rect_finalize (GObject
*object
)
765 FooCanvasRect
*rect
= FOO_CANVAS_RECT (object
);
771 G_OBJECT_CLASS (rect_parent_class
)->finalize (object
);
775 foo_canvas_rect_realize (FooCanvasItem
*item
)
777 if (FOO_CANVAS_ITEM_CLASS (rect_parent_class
)->realize
) {
778 (* FOO_CANVAS_ITEM_CLASS (rect_parent_class
)->realize
) (item
);
783 foo_canvas_rect_draw (FooCanvasItem
*item
, GdkDrawable
*drawable
, GdkEventExpose
*expose
)
787 double x1
, y1
, x2
, y2
;
788 int cx1
, cy1
, cx2
, cy2
;
789 double i2w_dx
, i2w_dy
;
792 re
= FOO_CANVAS_RE (item
);
794 /* Get canvas pixel coordinates */
797 foo_canvas_item_i2w (item
, &i2w_dx
, &i2w_dy
);
799 x1
= re
->x1
+ i2w_dx
;
800 y1
= re
->y1
+ i2w_dy
;
801 x2
= re
->x2
+ i2w_dx
;
802 y2
= re
->y2
+ i2w_dy
;
804 foo_canvas_w2c (item
->canvas
, x1
, y1
, &cx1
, &cy1
);
805 foo_canvas_w2c (item
->canvas
, x2
, y2
, &cx2
, &cy2
);
807 if (re
->width_pixels
)
810 width
= re
->width
* re
->item
.canvas
->pixels_per_unit
;
812 cr
= gdk_cairo_create (drawable
);
814 cairo_set_antialias (cr
, CAIRO_ANTIALIAS_NONE
);
815 cairo_set_line_width (cr
, width
);
818 /* FIXME: Use stipple */
819 cairo_set_source_rgba (cr
,
820 ((double) ((re
->fill_color
& 0xff000000) >> 24)) / 255,
821 ((double) ((re
->fill_color
& 0xff0000) >> 16)) / 255,
822 ((double) ((re
->fill_color
& 0xff00) >> 8)) / 255,
823 ((double) ((re
->fill_color
& 0xff))) / 255);
824 cairo_rectangle (cr
, cx1
, cy1
, cx2
- cx1
+ 1, cy2
- cy1
+ 1);
828 if (re
->outline_set
) {
829 /* FIXME: Use stipple */
830 cairo_set_source_rgba (cr
,
831 ((double) ((re
->outline_color
& 0xff000000) >> 24)) / 255,
832 ((double) ((re
->outline_color
& 0xff0000) >> 16)) / 255,
833 ((double) ((re
->outline_color
& 0xff00) >> 8)) / 255,
834 ((double) ((re
->outline_color
& 0xff))) / 255);
835 cairo_rectangle (cr
, cx1
, cy1
, cx2
- cx1
, cy2
- cy1
);
842 foo_canvas_rect_point (FooCanvasItem
*item
, double x
, double y
, int cx
, int cy
, FooCanvasItem
**actual_item
)
845 double x1
, y1
, x2
, y2
;
851 g_print ("foo_canvas_rect_point\n");
853 re
= FOO_CANVAS_RE (item
);
857 /* Find the bounds for the rectangle plus its outline width */
864 if (re
->outline_set
) {
865 hwidth
= get_draw_width_units (re
) / 2.0;
873 /* Is point inside rectangle (which can be hollow if it has no fill set)? */
875 if ((x
>= x1
) && (y
>= y1
) && (x
<= x2
) && (y
<= y2
)) {
876 if (re
->fill_set
|| !re
->outline_set
)
900 /* Point is outside rectangle */
916 return sqrt (dx
* dx
+ dy
* dy
);
920 request_redraw_borders (FooCanvas
*canvas
,
924 foo_canvas_request_redraw (canvas
,
925 update_rect
->x0
, update_rect
->y0
,
926 update_rect
->x1
, update_rect
->y0
+ width
);
927 foo_canvas_request_redraw (canvas
,
928 update_rect
->x0
, update_rect
->y1
-width
,
929 update_rect
->x1
, update_rect
->y1
);
930 foo_canvas_request_redraw (canvas
,
931 update_rect
->x0
, update_rect
->y0
,
932 update_rect
->x0
+width
, update_rect
->y1
);
933 foo_canvas_request_redraw (canvas
,
934 update_rect
->x1
-width
, update_rect
->y0
,
935 update_rect
->x1
, update_rect
->y1
);
940 foo_canvas_rect_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, gint flags
)
943 double x1
, y1
, x2
, y2
;
944 int cx1
, cy1
, cx2
, cy2
;
945 int repaint_rects_count
, i
;
947 int width_lt
, width_rb
;
948 Rect update_rect
, repaint_rects
[4];
949 FooCanvasRectPrivate
*priv
;
951 foo_canvas_re_update_shared (item
, i2w_dx
, i2w_dy
, flags
);
953 re
= FOO_CANVAS_RE (item
);
954 priv
= FOO_CANVAS_RECT (item
)->priv
;
956 x1
= re
->x1
+ i2w_dx
;
957 y1
= re
->y1
+ i2w_dy
;
958 x2
= re
->x2
+ i2w_dx
;
959 y2
= re
->y2
+ i2w_dy
;
961 foo_canvas_w2c (item
->canvas
, x1
, y1
, &cx1
, &cy1
);
962 foo_canvas_w2c (item
->canvas
, x2
, y2
, &cx2
, &cy2
);
964 update_rect
= make_rect (cx1
, cy1
, cx2
+1, cy2
+1);
966 foo_canvas_request_redraw (item
->canvas
,
967 update_rect
.x0
, update_rect
.y0
,
968 update_rect
.x1
, update_rect
.y1
);
969 foo_canvas_request_redraw (item
->canvas
,
970 priv
->last_update_rect
.x0
, priv
->last_update_rect
.y0
,
971 priv
->last_update_rect
.x1
, priv
->last_update_rect
.y1
);
973 diff_rects (update_rect
, priv
->last_update_rect
,
974 &repaint_rects_count
, repaint_rects
);
975 for (i
= 0; i
< repaint_rects_count
; i
++) {
976 foo_canvas_request_redraw (item
->canvas
,
977 repaint_rects
[i
].x0
, repaint_rects
[i
].y0
,
978 repaint_rects
[i
].x1
, repaint_rects
[i
].y1
);
981 priv
->last_update_rect
= update_rect
;
983 if (re
->outline_set
) {
984 /* Outline and bounding box */
985 width_pixels
= get_draw_width_pixels (re
);
987 width_lt
= width_pixels
/ 2;
988 width_rb
= (width_pixels
+ 1) / 2;
995 update_rect
= make_rect (cx1
, cy1
, cx2
, cy2
);
996 request_redraw_borders (item
->canvas
, &update_rect
,
997 (width_lt
+ width_rb
));
998 request_redraw_borders (item
->canvas
, &priv
->last_outline_update_rect
,
999 priv
->last_outline_update_width
);
1000 priv
->last_outline_update_rect
= update_rect
;
1001 priv
->last_outline_update_width
= width_lt
+ width_rb
;
1018 static void foo_canvas_ellipse_class_init (FooCanvasEllipseClass
*klass
);
1020 static void foo_canvas_ellipse_draw (FooCanvasItem
*item
, GdkDrawable
*drawable
, GdkEventExpose
*expose
);
1021 static double foo_canvas_ellipse_point (FooCanvasItem
*item
, double x
, double y
, int cx
, int cy
,
1022 FooCanvasItem
**actual_item
);
1026 foo_canvas_ellipse_get_type (void)
1028 static GType ellipse_type
= 0;
1030 if (!ellipse_type
) {
1031 GTypeInfo ellipse_info
= {
1032 sizeof (FooCanvasEllipseClass
),
1033 (GBaseInitFunc
) NULL
,
1034 (GBaseFinalizeFunc
) NULL
,
1035 (GClassInitFunc
) foo_canvas_ellipse_class_init
,
1036 NULL
, /* class_finalize */
1037 NULL
, /* class_data */
1038 sizeof (FooCanvasEllipse
),
1039 0, /* n_preallocs */
1040 (GInstanceInitFunc
) NULL
1044 ellipse_type
= g_type_register_static (foo_canvas_re_get_type (),
1050 return ellipse_type
;
1054 foo_canvas_ellipse_class_init (FooCanvasEllipseClass
*klass
)
1056 FooCanvasItemClass
*item_class
;
1058 item_class
= (FooCanvasItemClass
*) klass
;
1060 item_class
->draw
= foo_canvas_ellipse_draw
;
1061 item_class
->point
= foo_canvas_ellipse_point
;
1062 item_class
->update
= foo_canvas_ellipse_update
;
1066 foo_canvas_ellipse_draw (FooCanvasItem
*item
, GdkDrawable
*drawable
, GdkEventExpose
*expose
)
1071 double i2w_dx
, i2w_dy
;
1074 re
= FOO_CANVAS_RE (item
);
1076 /* Get canvas pixel coordinates */
1080 foo_canvas_item_i2w (item
, &i2w_dx
, &i2w_dy
);
1082 foo_canvas_w2c (item
->canvas
,
1086 foo_canvas_w2c (item
->canvas
,
1091 if (re
->width_pixels
)
1094 width
= re
->width
* re
->item
.canvas
->pixels_per_unit
;
1096 cr
= gdk_cairo_create (drawable
);
1098 cairo_set_antialias (cr
, CAIRO_ANTIALIAS_NONE
);
1099 cairo_set_line_width (cr
, width
);
1102 /* FIXME: set stipple as source */
1103 cairo_set_source_rgba (cr
,
1104 ((double) ((re
->fill_color
& 0xff000000) >> 24)) / 255,
1105 ((double) ((re
->fill_color
& 0xff0000) >> 16)) / 255,
1106 ((double) ((re
->fill_color
& 0xff00) >> 8)) / 255,
1107 ((double) ((re
->fill_color
& 0xff))) / 255);
1109 cairo_translate (cr
, x1
+ (x2
- x1
)/2, y1
+ (y2
- y1
)/2);
1110 cairo_scale (cr
, (x2
- x1
)/2, (y2
- y1
)/2);
1111 cairo_arc (cr
, 0.0, 0.0, 1.0, 0 * 64, 360 * 64);
1113 cairo_fill_preserve (cr
);
1116 if (re
->outline_set
) {
1117 /* FIXME: set stipple as source */
1119 cairo_set_source_rgba (cr
,
1120 ((double) ((re
->outline_color
& 0xff000000) >> 24)) / 255,
1121 ((double) ((re
->outline_color
& 0xff0000) >> 16)) / 255,
1122 ((double) ((re
->outline_color
& 0xff00) >> 8)) / 255,
1123 ((double) ((re
->outline_color
& 0xff))) / 255);
1127 cairo_translate (cr
, x1
+ (x2
- x1
)/2, y1
+ (y2
- y1
)/2);
1128 cairo_scale (cr
, (x2
- x1
)/2, (y2
- y1
)/2);
1129 cairo_arc (cr
, 0.0, 0.0, 1.0, 0 * 64, 360 * 64);
1138 foo_canvas_ellipse_point (FooCanvasItem
*item
, double x
, double y
, int cx
, int cy
, FooCanvasItem
**actual_item
)
1143 double outline_dist
;
1147 double diamx
, diamy
;
1149 re
= FOO_CANVAS_RE (item
);
1151 *actual_item
= item
;
1153 if (re
->outline_set
) {
1154 width
= get_draw_width_units (re
);
1158 /* Compute the distance between the center of the ellipse and the point, with the ellipse
1159 * considered as being scaled to a circle.
1162 dx
= x
- (re
->x1
+ re
->x2
) / 2.0;
1163 dy
= y
- (re
->y1
+ re
->y2
) / 2.0;
1164 center_dist
= sqrt (dx
* dx
+ dy
* dy
);
1166 a
= dx
/ ((re
->x2
+ width
- re
->x1
) / 2.0);
1167 b
= dy
/ ((re
->y2
+ width
- re
->y1
) / 2.0);
1168 scaled_dist
= sqrt (a
* a
+ b
* b
);
1170 /* If the scaled distance is greater than 1, then we are outside. Compute the distance from
1171 * the point to the edge of the circle, then scale back to the original un-scaled coordinate
1175 if (scaled_dist
> 1.0)
1176 return (center_dist
/ scaled_dist
) * (scaled_dist
- 1.0);
1178 /* We are inside the outer edge of the ellipse. If it is filled, then we are "inside".
1179 * Otherwise, do the same computation as above, but also check whether we are inside the
1186 if (scaled_dist
> FOO_CANVAS_EPSILON
)
1187 outline_dist
= (center_dist
/ scaled_dist
) * (1.0 - scaled_dist
) - width
;
1189 /* Handle very small distance */
1191 diamx
= re
->x2
- re
->x1
;
1192 diamy
= re
->y2
- re
->y1
;
1195 outline_dist
= (diamx
- width
) / 2.0;
1197 outline_dist
= (diamy
- width
) / 2.0;
1200 if (outline_dist
< 0.0)
1203 return outline_dist
;
1207 foo_canvas_ellipse_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, gint flags
)
1210 double x0
, y0
, x1
, y1
;
1213 g_print ("foo_canvas_sllipse_update item %x\n", item
);
1216 foo_canvas_re_update_shared (item
, i2w_dx
, i2w_dy
, flags
);
1217 re
= FOO_CANVAS_RE (item
);
1219 get_bounds (re
, &x0
, &y0
, &x1
, &y1
);
1220 foo_canvas_update_bbox (item
, x0
, y0
, x1
, y1
);
1224 rect_empty (const Rect
*src
) {
1225 return (src
->x1
<= src
->x0
|| src
->y1
<= src
->y0
);
1229 make_rect (int x0
, int y0
, int x1
, int y1
)
1241 rects_intersect (Rect r1
, Rect r2
)
1243 if (r1
.x0
>= r2
.x1
) {
1246 if (r2
.x0
>= r1
.x1
) {
1249 if (r1
.y0
>= r2
.y1
) {
1252 if (r2
.y0
>= r1
.y1
) {
1259 diff_rects_guts (Rect ra
, Rect rb
, int *count
, Rect result
[4])
1261 if (ra
.x0
< rb
.x0
) {
1262 result
[(*count
)++] = make_rect (ra
.x0
, ra
.y0
, rb
.x0
, ra
.y1
);
1264 if (ra
.y0
< rb
.y0
) {
1265 result
[(*count
)++] = make_rect (ra
.x0
, ra
.y0
, ra
.x1
, rb
.y0
);
1267 if (ra
.x1
< rb
.x1
) {
1268 result
[(*count
)++] = make_rect (ra
.x1
, rb
.y0
, rb
.x1
, rb
.y1
);
1270 if (ra
.y1
< rb
.y1
) {
1271 result
[(*count
)++] = make_rect (rb
.x0
, ra
.y1
, rb
.x1
, rb
.y1
);
1276 diff_rects (Rect r1
, Rect r2
, int *count
, Rect result
[4])
1278 g_assert (count
!= NULL
);
1279 g_assert (result
!= NULL
);
1283 if (rects_intersect (r1
, r2
)) {
1284 diff_rects_guts (r1
, r2
, count
, result
);
1285 diff_rects_guts (r2
, r1
, count
, result
);
1287 if (!rect_empty (&r1
)) {
1288 result
[(*count
)++] = r1
;
1290 if (!rect_empty (&r2
)) {
1291 result
[(*count
)++] = r2
;