3 #include <gtk-canvas.h>
5 #include "canvas-simplerect.h"
6 #include "rgb_macros.h"
18 ARG_OUTLINE_COLOR_RGBA,
23 static void gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class);
24 static void gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect);
25 static void gtk_canvas_simplerect_set_arg (GtkObject *object,
28 static void gtk_canvas_simplerect_get_arg (GtkObject *object,
32 static void gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
33 static void gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
34 static double gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item);
35 static void gtk_canvas_simplerect_render (GtkCanvasItem *item, GtkCanvasBuf *buf);
36 static void gtk_canvas_simplerect_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
38 static GtkCanvasItemClass *parent_class;
42 gtk_canvas_simplerect_get_type (void)
44 static GtkType simplerect_type = 0;
46 if (!simplerect_type) {
47 GtkTypeInfo simplerect_info = {
48 "GtkCanvasSimpleRect",
49 sizeof (GtkCanvasSimpleRect),
50 sizeof (GtkCanvasSimpleRectClass),
51 (GtkClassInitFunc) gtk_canvas_simplerect_class_init,
52 (GtkObjectInitFunc) gtk_canvas_simplerect_init,
53 NULL, /* reserved_1 */
54 NULL, /* reserved_2 */
55 (GtkClassInitFunc) NULL
58 simplerect_type = gtk_type_unique (gtk_canvas_item_get_type (), &simplerect_info);
61 return simplerect_type;
65 gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class)
67 GtkObjectClass *object_class;
68 GtkCanvasItemClass *item_class;
70 object_class = (GtkObjectClass *) class;
71 item_class = (GtkCanvasItemClass *) class;
73 parent_class = gtk_type_class (gtk_canvas_item_get_type ());
75 gtk_object_add_arg_type ("GtkCanvasSimpleRect::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1);
76 gtk_object_add_arg_type ("GtkCanvasSimpleRect::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1);
77 gtk_object_add_arg_type ("GtkCanvasSimpleRect::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2);
78 gtk_object_add_arg_type ("GtkCanvasSimpleRect::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2);
79 gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FILL);
80 gtk_object_add_arg_type ("GtkCanvasSimpleRect::draw", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW);
81 gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA);
82 gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_COLOR_RGBA);
83 gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_pixels", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_PIXELS);
84 gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_what", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_WHAT);
86 object_class->set_arg = gtk_canvas_simplerect_set_arg;
87 object_class->get_arg = gtk_canvas_simplerect_get_arg;
89 item_class->update = gtk_canvas_simplerect_update;
90 item_class->bounds = gtk_canvas_simplerect_bounds;
91 item_class->point = gtk_canvas_simplerect_point;
92 item_class->render = gtk_canvas_simplerect_render;
93 item_class->draw = gtk_canvas_simplerect_draw;
97 gtk_canvas_simplerect_init (GtkCanvasSimpleRect *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;
111 GTK_CANVAS_ITEM(simplerect)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
115 gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
117 GtkCanvasSimpleRect *simplerect = GTK_CANVAS_SIMPLERECT (item);
119 *x1 = simplerect->x1;
120 *y1 = simplerect->y1;
121 *x2 = simplerect->x2 + 1;
122 *y2 = simplerect->y2 + 1;
127 gtk_canvas_simplerect_reset_bounds (GtkCanvasItem *item)
129 GtkCanvasSimpleRect* simplerect;
130 double x1, x2, y1, y2;
131 double old_x1, old_x2, old_y1, old_y2;
139 gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
140 gtk_canvas_item_i2w (item, &x1, &y1);
141 gtk_canvas_item_i2w (item, &x2, &y2);
148 /* now compute bounding box in canvas units */
150 simplerect = GTK_CANVAS_SIMPLERECT (item);
152 gtk_canvas_w2c (GTK_CANVAS(item->canvas), x1, y1, &simplerect->bbox_ulx, &simplerect->bbox_uly);
153 gtk_canvas_w2c (GTK_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
155 /* now queue redraws for changed areas */
157 if (item->x1 != old_x1) {
159 /* left edge changed. redraw the area that altered */
161 a = MIN(item->x1, old_x1);
162 b = MAX(item->x1, old_x1);
163 gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
166 if (item->x2 != old_x2) {
168 /* right edge changed. redraw the area that altered */
170 a = MIN(item->x2, old_x2);
171 b = MAX(item->x2, old_x2);
172 gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
175 if (item->y1 != old_y1) {
177 /* top edge changed. redraw the area that altered */
179 a = MIN(item->y1, old_y1);
180 b = MAX(item->y1, old_y1);
181 gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
184 if (item->y2 != old_y2) {
186 /* lower edge changed. redraw the area that altered */
188 a = MIN(item->y2, old_y2);
189 b = MAX(item->y2, old_y2);
190 gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
199 gtk_canvas_simplerect_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
202 GtkCanvasSimpleRect *simplerect;
206 item = GTK_CANVAS_ITEM (object);
207 simplerect = GTK_CANVAS_SIMPLERECT (object);
210 bounds_changed = FALSE;
214 if (simplerect->x1 != GTK_VALUE_DOUBLE (*arg)) {
215 simplerect->x1 = GTK_VALUE_DOUBLE (*arg);
216 bounds_changed = TRUE;
221 if (simplerect->y1 != GTK_VALUE_DOUBLE (*arg)) {
222 simplerect->y1 = GTK_VALUE_DOUBLE (*arg);
223 bounds_changed = TRUE;
228 if (simplerect->x2 != GTK_VALUE_DOUBLE (*arg)) {
229 simplerect->x2 = GTK_VALUE_DOUBLE (*arg);
230 bounds_changed = TRUE;
235 if (simplerect->y2 != GTK_VALUE_DOUBLE (*arg)) {
236 simplerect->y2 = GTK_VALUE_DOUBLE (*arg);
237 bounds_changed = TRUE;
242 if (simplerect->draw != GTK_VALUE_BOOL (*arg)) {
243 simplerect->draw = GTK_VALUE_BOOL (*arg);
250 if (simplerect->fill != GTK_VALUE_BOOL (*arg)) {
251 simplerect->fill = GTK_VALUE_BOOL (*arg);
256 case ARG_FILL_COLOR_RGBA:
257 if (simplerect->fill_color != GTK_VALUE_INT(*arg)) {
258 simplerect->fill_color = GTK_VALUE_INT(*arg);
263 case ARG_OUTLINE_COLOR_RGBA:
264 if (simplerect->outline_color != GTK_VALUE_INT(*arg)) {
265 simplerect->outline_color = GTK_VALUE_INT(*arg);
270 case ARG_OUTLINE_PIXELS:
271 if (simplerect->outline_pixels != GTK_VALUE_INT(*arg)) {
272 simplerect->outline_pixels = GTK_VALUE_INT(*arg);
277 case ARG_OUTLINE_WHAT:
278 if (simplerect->outline_what != GTK_VALUE_INT(*arg)) {
279 simplerect->outline_what = GTK_VALUE_INT(*arg);
288 simplerect->full_draw_on_update = update;
290 if (update || bounds_changed) {
291 gtk_canvas_item_request_update (item);
296 gtk_canvas_simplerect_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
298 GtkCanvasSimpleRect *simplerect;
300 simplerect = GTK_CANVAS_SIMPLERECT (object);
304 GTK_VALUE_DOUBLE (*arg) = simplerect->x1;
307 GTK_VALUE_DOUBLE (*arg) = simplerect->y1;
310 GTK_VALUE_DOUBLE (*arg) = simplerect->x2;
313 GTK_VALUE_DOUBLE (*arg) = simplerect->y2;
316 GTK_VALUE_BOOL (*arg) = simplerect->draw;
319 GTK_VALUE_BOOL (*arg) = simplerect->fill;
321 case ARG_FILL_COLOR_RGBA:
322 GTK_VALUE_INT (*arg) = simplerect->fill_color;
324 case ARG_OUTLINE_COLOR_RGBA:
325 GTK_VALUE_INT (*arg) = simplerect->outline_color;
327 case ARG_OUTLINE_PIXELS:
328 GTK_VALUE_INT (*arg) = simplerect->outline_pixels;
330 case ARG_OUTLINE_WHAT:
331 GTK_VALUE_INT (*arg) = simplerect->outline_what;
334 arg->type = GTK_TYPE_INVALID;
340 gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
342 GtkCanvasSimpleRect *simplerect;
345 simplerect = GTK_CANVAS_SIMPLERECT (item);
347 if (parent_class->update)
348 (* parent_class->update) (item, affine, clip_path, flags);
350 gtk_canvas_simplerect_reset_bounds (item);
352 if (simplerect->full_draw_on_update) {
353 gtk_canvas_request_redraw (item->canvas,
354 simplerect->bbox_ulx,
355 simplerect->bbox_uly,
356 simplerect->bbox_lrx+1,
357 simplerect->bbox_lry+1);
358 simplerect->full_draw_on_update = FALSE;
361 UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a);
362 UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo);
365 #define SIMPLERECT_FAST_RENDERER
366 #ifdef SIMPLERECT_FAST_RENDERER
369 gtk_canvas_simplerect_render (GtkCanvasItem *item,
372 GtkCanvasSimpleRect *simplerect;
376 ArtIRect intersection;
379 simplerect = GTK_CANVAS_SIMPLERECT (item);
381 if (parent_class->render) {
382 (*parent_class->render) (item, buf);
387 // this can be useful for debugging/understanding how the canvas redraws
390 // gint randr, randg, randb;
391 // randr = random() % 255;
392 // randg = random() % 255;
393 // randb = random() % 255;
394 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
396 gtk_canvas_buf_ensure_buf (buf);
400 if (!simplerect->draw) {
404 self.x0 = simplerect->bbox_ulx;
405 self.y0 = simplerect->bbox_uly;
406 self.x1 = simplerect->bbox_lrx;
407 self.y1 = simplerect->bbox_lry;
409 art_irect_intersect (&intersection, &self, &buf->rect);
411 begin = MAX(simplerect->bbox_ulx, buf->rect.x0);
412 end = MIN((simplerect->bbox_lrx-1), buf->rect.x1);
414 sy = simplerect->bbox_uly;
415 ey = simplerect->bbox_lry-1;
417 if (simplerect->fill) {
419 // this can be useful for debugging/understanding how the canvas redraws
422 // gint randr, randg, randb;
423 // randr = random() % 255;
424 // randg = random() % 255;
425 // randb = random() % 255;
426 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
428 FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a,
429 intersection.x0, intersection.y0,
430 intersection.x1, intersection.y1);
434 for (i = 0; i < simplerect->outline_pixels; ++i) {
436 if (simplerect->outline_what & 0x1) {
437 if (begin == simplerect->bbox_ulx) {
438 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
442 if (simplerect->outline_what & 0x2) {
443 if (end == (simplerect->bbox_lrx - 1)) {
444 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
448 if (simplerect->outline_what & 0x4) {
449 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
452 if (simplerect->outline_what & 0x8) {
453 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
458 #else /* SIMPLERECT_FAST_RENDERER */
461 gtk_canvas_simplerect_render (GtkCanvasItem *item,
464 GtkCanvasSimpleRect *simplerect;
469 simplerect = GTK_CANVAS_SIMPLERECT (item);
471 if (parent_class->render) {
472 (*parent_class->render) (item, buf);
477 // this can be useful for debugging/understanding how the canvas redraws
480 // gint randr, randg, randb;
481 // randr = random() % 255;
482 // randg = random() % 255;
483 // randb = random() % 255;
484 // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
486 gtk_canvas_buf_ensure_buf (buf);
490 if (!simplerect->draw) {
494 begin = MAX(simplerect->bbox_ulx,buf->rect.x0);
495 end = MIN((simplerect->bbox_lrx-1),buf->rect.x1);
497 sy = simplerect->bbox_uly;
498 ey = simplerect->bbox_lry-1;
500 if (simplerect->fill) {
502 // this can be useful for debugging/understanding how the canvas redraws
505 // gint randr, randg, randb;
506 // randr = random() % 255;
507 // randg = random() % 255;
508 // randb = random() % 255;
509 // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
511 PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey);
514 for (i = 0; i < simplerect->outline_pixels; ++i) {
516 if (simplerect->outline_what & 0x1) {
517 if (begin == simplerect->bbox_ulx) {
518 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
522 if (simplerect->outline_what & 0x2) {
523 if (end == (simplerect->bbox_lrx - 1)) {
524 PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
528 if (simplerect->outline_what & 0x4) {
529 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
532 if (simplerect->outline_what & 0x8) {
533 PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
537 #endif /* SIMPLERECT_FAST_RENDERER */
540 gtk_canvas_simplerect_draw (GtkCanvasItem *item,
541 GdkDrawable *drawable,
543 int width, int height)
545 fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n");
550 gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item)
552 GtkCanvasSimpleRect *simplerect;
553 double x1, y1, x2, y2;
556 simplerect = GTK_CANVAS_SIMPLERECT (item);
560 /* Find the bounds for the rectangle plus its outline width */
562 gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
564 /* Is point inside rectangle */
566 if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
570 /* Point is outside rectangle */
586 return sqrt (dx * dx + dy * dy);