3 #include <libgnomecanvas/libgnomecanvas.h>
5 #include "canvas-simplerect.h"
6 #include "rgb_macros.h"
18 ARG_OUTLINE_COLOR_RGBA,
23 static void gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass *class);
24 static void gnome_canvas_simplerect_init (GnomeCanvasSimpleRect *simplerect);
25 static void gnome_canvas_simplerect_set_arg (GtkObject *object,
28 static void gnome_canvas_simplerect_get_arg (GtkObject *object,
32 static void gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
33 static void gnome_canvas_simplerect_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
34 static double gnome_canvas_simplerect_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item);
35 static void gnome_canvas_simplerect_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
36 static void gnome_canvas_simplerect_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
38 static GnomeCanvasItemClass *parent_class;
42 gnome_canvas_simplerect_get_type (void)
44 static GtkType simplerect_type = 0;
46 if (!simplerect_type) {
47 GtkTypeInfo simplerect_info = {
48 "GnomeCanvasSimpleRect",
49 sizeof (GnomeCanvasSimpleRect),
50 sizeof (GnomeCanvasSimpleRectClass),
51 (GtkClassInitFunc) gnome_canvas_simplerect_class_init,
52 (GtkObjectInitFunc) gnome_canvas_simplerect_init,
53 NULL, /* reserved_1 */
54 NULL, /* reserved_2 */
55 (GtkClassInitFunc) NULL
58 simplerect_type = gtk_type_unique (gnome_canvas_item_get_type (), &simplerect_info);
61 return simplerect_type;
65 gnome_canvas_simplerect_class_init (GnomeCanvasSimpleRectClass *class)
67 GtkObjectClass *object_class;
68 GnomeCanvasItemClass *item_class;
70 object_class = (GtkObjectClass *) class;
71 item_class = (GnomeCanvasItemClass *) class;
73 parent_class = gtk_type_class (gnome_canvas_item_get_type ());
75 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1);
76 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1);
77 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2);
78 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2);
79 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FILL);
80 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::draw", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW);
81 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::fill_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA);
82 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::outline_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_COLOR_RGBA);
83 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::outline_pixels", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_PIXELS);
84 gtk_object_add_arg_type ("GnomeCanvasSimpleRect::outline_what", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_WHAT);
86 object_class->set_arg = gnome_canvas_simplerect_set_arg;
87 object_class->get_arg = gnome_canvas_simplerect_get_arg;
89 item_class->update = gnome_canvas_simplerect_update;
90 item_class->bounds = gnome_canvas_simplerect_bounds;
91 item_class->point = gnome_canvas_simplerect_point;
92 item_class->render = gnome_canvas_simplerect_render;
93 item_class->draw = gnome_canvas_simplerect_draw;
97 gnome_canvas_simplerect_init (GnomeCanvasSimpleRect *simplerect)
100 simplerect->y1 = 0.0;
101 simplerect->x2 = 0.0;
102 simplerect->y2 = 0.0;
103 simplerect->fill = TRUE;
104 simplerect->draw = TRUE;
105 simplerect->full_draw_on_update = TRUE;
106 simplerect->fill_color = 0;
107 simplerect->outline_color = 0;
108 simplerect->outline_pixels = 1;
109 simplerect->outline_what = 0xf;
112 // GNOME_CANVAS_ITEM(simplerect)->object.flags |= GNOME_CANVAS_ITEM_NO_AUTO_REDRAW;
116 gnome_canvas_simplerect_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
118 GnomeCanvasSimpleRect *simplerect = GNOME_CANVAS_SIMPLERECT (item);
120 *x1 = simplerect->x1;
121 *y1 = simplerect->y1;
122 *x2 = simplerect->x2 + 1;
123 *y2 = simplerect->y2 + 1;
128 gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
130 GnomeCanvasSimpleRect* simplerect;
131 double x1, x2, y1, y2;
132 double old_x1, old_x2, old_y1, old_y2;
140 gnome_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
141 gnome_canvas_item_i2w (item, &x1, &y1);
142 gnome_canvas_item_i2w (item, &x2, &y2);
149 /* now compute bounding box in canvas units */
151 simplerect = GNOME_CANVAS_SIMPLERECT (item);
153 gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x1, y1, &simplerect->bbox_ulx, &simplerect->bbox_uly);
154 gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
156 /* now queue redraws for changed areas */
158 if (item->x1 != old_x1) {
160 /* left edge changed. redraw the area that altered */
162 a = MIN(item->x1, old_x1);
163 b = MAX(item->x1, old_x1);
164 gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
167 if (item->x2 != old_x2) {
169 /* right edge changed. redraw the area that altered */
171 a = MIN(item->x2, old_x2);
172 b = MAX(item->x2, old_x2);
173 gnome_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
176 if (item->y1 != old_y1) {
178 /* top edge changed. redraw the area that altered */
180 a = MIN(item->y1, old_y1);
181 b = MAX(item->y1, old_y1);
182 gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
185 if (item->y2 != old_y2) {
187 /* lower edge changed. redraw the area that altered */
189 a = MIN(item->y2, old_y2);
190 b = MAX(item->y2, old_y2);
191 gnome_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
200 gnome_canvas_simplerect_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
202 GnomeCanvasItem *item;
203 GnomeCanvasSimpleRect *simplerect;
207 item = GNOME_CANVAS_ITEM (object);
208 simplerect = GNOME_CANVAS_SIMPLERECT (object);
211 bounds_changed = FALSE;
215 if (simplerect->x1 != GTK_VALUE_DOUBLE (*arg)) {
216 simplerect->x1 = GTK_VALUE_DOUBLE (*arg);
217 bounds_changed = TRUE;
222 if (simplerect->y1 != GTK_VALUE_DOUBLE (*arg)) {
223 simplerect->y1 = GTK_VALUE_DOUBLE (*arg);
224 bounds_changed = TRUE;
229 if (simplerect->x2 != GTK_VALUE_DOUBLE (*arg)) {
230 simplerect->x2 = GTK_VALUE_DOUBLE (*arg);
231 bounds_changed = TRUE;
236 if (simplerect->y2 != GTK_VALUE_DOUBLE (*arg)) {
237 simplerect->y2 = GTK_VALUE_DOUBLE (*arg);
238 bounds_changed = TRUE;
243 if (simplerect->draw != GTK_VALUE_BOOL (*arg)) {
244 simplerect->draw = GTK_VALUE_BOOL (*arg);
251 if (simplerect->fill != GTK_VALUE_BOOL (*arg)) {
252 simplerect->fill = GTK_VALUE_BOOL (*arg);
257 case ARG_FILL_COLOR_RGBA:
258 if (simplerect->fill_color != GTK_VALUE_INT(*arg)) {
259 simplerect->fill_color = GTK_VALUE_INT(*arg);
264 case ARG_OUTLINE_COLOR_RGBA:
265 if (simplerect->outline_color != GTK_VALUE_INT(*arg)) {
266 simplerect->outline_color = GTK_VALUE_INT(*arg);
271 case ARG_OUTLINE_PIXELS:
272 if (simplerect->outline_pixels != GTK_VALUE_INT(*arg)) {
273 simplerect->outline_pixels = GTK_VALUE_INT(*arg);
278 case ARG_OUTLINE_WHAT:
279 if (simplerect->outline_what != GTK_VALUE_INT(*arg)) {
280 simplerect->outline_what = GTK_VALUE_INT(*arg);
289 simplerect->full_draw_on_update = update;
291 if (update || bounds_changed) {
292 gnome_canvas_item_request_update (item);
297 gnome_canvas_simplerect_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
299 GnomeCanvasSimpleRect *simplerect;
301 simplerect = GNOME_CANVAS_SIMPLERECT (object);
305 GTK_VALUE_DOUBLE (*arg) = simplerect->x1;
308 GTK_VALUE_DOUBLE (*arg) = simplerect->y1;
311 GTK_VALUE_DOUBLE (*arg) = simplerect->x2;
314 GTK_VALUE_DOUBLE (*arg) = simplerect->y2;
317 GTK_VALUE_BOOL (*arg) = simplerect->draw;
320 GTK_VALUE_BOOL (*arg) = simplerect->fill;
322 case ARG_FILL_COLOR_RGBA:
323 GTK_VALUE_INT (*arg) = simplerect->fill_color;
325 case ARG_OUTLINE_COLOR_RGBA:
326 GTK_VALUE_INT (*arg) = simplerect->outline_color;
328 case ARG_OUTLINE_PIXELS:
329 GTK_VALUE_INT (*arg) = simplerect->outline_pixels;
331 case ARG_OUTLINE_WHAT:
332 GTK_VALUE_INT (*arg) = simplerect->outline_what;
335 arg->type = GTK_TYPE_INVALID;
341 gnome_canvas_simplerect_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
343 GnomeCanvasSimpleRect *simplerect;
346 simplerect = GNOME_CANVAS_SIMPLERECT (item);
348 if (parent_class->update)
349 (* parent_class->update) (item, affine, clip_path, flags);
351 gnome_canvas_simplerect_reset_bounds (item);
353 if (simplerect->full_draw_on_update) {
354 gnome_canvas_request_redraw (item->canvas,
355 simplerect->bbox_ulx,
356 simplerect->bbox_uly,
357 simplerect->bbox_lrx+1,
358 simplerect->bbox_lry+1);
359 simplerect->full_draw_on_update = FALSE;
362 UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a);
363 UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo);
366 #define SIMPLERECT_FAST_RENDERER
367 #ifdef SIMPLERECT_FAST_RENDERER
370 gnome_canvas_simplerect_render (GnomeCanvasItem *item,
373 GnomeCanvasSimpleRect *simplerect;
377 ArtIRect intersection;
380 simplerect = GNOME_CANVAS_SIMPLERECT (item);
382 if (parent_class->render) {
383 (*parent_class->render) (item, buf);
388 // this can be useful for debugging/understanding how the canvas redraws
391 // gint randr, randg, randb;
392 // randr = random() % 255;
393 // randg = random() % 255;
394 // randb = random() % 255;
395 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
397 gnome_canvas_buf_ensure_buf (buf);
401 if (!simplerect->draw) {
405 self.x0 = simplerect->bbox_ulx;
406 self.y0 = simplerect->bbox_uly;
407 self.x1 = simplerect->bbox_lrx;
408 self.y1 = simplerect->bbox_lry;
410 art_irect_intersect (&intersection, &self, &buf->rect);
412 begin = MAX(simplerect->bbox_ulx, buf->rect.x0);
413 end = MIN((simplerect->bbox_lrx-1), buf->rect.x1);
415 sy = simplerect->bbox_uly;
416 ey = simplerect->bbox_lry-1;
418 if (simplerect->fill) {
420 // this can be useful for debugging/understanding how the canvas redraws
423 // gint randr, randg, randb;
424 // randr = random() % 255;
425 // randg = random() % 255;
426 // randb = random() % 255;
427 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
429 FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a,
430 intersection.x0, intersection.y0,
431 intersection.x1, intersection.y1);
435 for (i = 0; i < simplerect->outline_pixels; ++i) {
437 if (simplerect->outline_what & 0x1) {
438 if (begin == simplerect->bbox_ulx) {
439 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
443 if (simplerect->outline_what & 0x2) {
444 if (end == (simplerect->bbox_lrx - 1)) {
445 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
449 if (simplerect->outline_what & 0x4) {
450 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
453 if (simplerect->outline_what & 0x8) {
454 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
459 #else /* SIMPLERECT_FAST_RENDERER */
462 gnome_canvas_simplerect_render (GnomeCanvasItem *item,
465 GnomeCanvasSimpleRect *simplerect;
470 simplerect = GNOME_CANVAS_SIMPLERECT (item);
472 if (parent_class->render) {
473 (*parent_class->render) (item, buf);
478 // this can be useful for debugging/understanding how the canvas redraws
481 // gint randr, randg, randb;
482 // randr = random() % 255;
483 // randg = random() % 255;
484 // randb = random() % 255;
485 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
487 gnome_canvas_buf_ensure_buf (buf);
491 if (!simplerect->draw) {
495 begin = MAX(simplerect->bbox_ulx,buf->rect.x0);
496 end = MIN((simplerect->bbox_lrx-1),buf->rect.x1);
498 sy = simplerect->bbox_uly;
499 ey = simplerect->bbox_lry-1;
501 if (simplerect->fill) {
503 // this can be useful for debugging/understanding how the canvas redraws
506 // gint randr, randg, randb;
507 // randr = random() % 255;
508 // randg = random() % 255;
509 // randb = random() % 255;
510 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
512 PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey);
515 for (i = 0; i < simplerect->outline_pixels; ++i) {
517 if (simplerect->outline_what & 0x1) {
518 if (begin == simplerect->bbox_ulx) {
519 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
523 if (simplerect->outline_what & 0x2) {
524 if (end == (simplerect->bbox_lrx - 1)) {
525 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
529 if (simplerect->outline_what & 0x4) {
530 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
533 if (simplerect->outline_what & 0x8) {
534 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
538 #endif /* SIMPLERECT_FAST_RENDERER */
541 gnome_canvas_simplerect_draw (GnomeCanvasItem *item,
542 GdkDrawable *drawable,
544 int width, int height)
546 fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n");
551 gnome_canvas_simplerect_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
553 GnomeCanvasSimpleRect *simplerect;
554 double x1, y1, x2, y2;
557 simplerect = GNOME_CANVAS_SIMPLERECT (item);
561 /* Find the bounds for the rectangle plus its outline width */
563 gnome_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
565 /* Is point inside rectangle */
567 if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
571 /* Point is outside rectangle */
587 return sqrt (dx * dx + dy * dy);