From 209d967b1bb80a9735d690d8f4f0455ecb9970ca Mon Sep 17 00:00:00 2001 From: Taybin Rutkin Date: Sun, 25 Sep 2005 18:42:24 +0000 Subject: Initial import of gtk2_ardour. git-svn-id: svn://localhost/trunk/ardour2@24 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-simplerect.c | 587 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 gtk2_ardour/canvas-simplerect.c (limited to 'gtk2_ardour/canvas-simplerect.c') diff --git a/gtk2_ardour/canvas-simplerect.c b/gtk2_ardour/canvas-simplerect.c new file mode 100644 index 0000000000..4ee4985a2c --- /dev/null +++ b/gtk2_ardour/canvas-simplerect.c @@ -0,0 +1,587 @@ +#include +#include +#include + +#include "canvas-simplerect.h" +#include "rgb_macros.h" + +enum { + ARG_0, + ARG_X1, + ARG_Y1, + ARG_X2, + ARG_Y2, + ARG_OUTLINE_PIXELS, + ARG_OUTLINE_WHAT, + ARG_FILL, + ARG_FILL_COLOR_RGBA, + ARG_OUTLINE_COLOR_RGBA, + ARG_DRAW + +}; + +static void gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class); +static void gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect); +static void gtk_canvas_simplerect_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_canvas_simplerect_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); +static void gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2); +static double gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item); +static void gtk_canvas_simplerect_render (GtkCanvasItem *item, GtkCanvasBuf *buf); +static void gtk_canvas_simplerect_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h); + +static GtkCanvasItemClass *parent_class; + + +GtkType +gtk_canvas_simplerect_get_type (void) +{ + static GtkType simplerect_type = 0; + + if (!simplerect_type) { + GtkTypeInfo simplerect_info = { + "GtkCanvasSimpleRect", + sizeof (GtkCanvasSimpleRect), + sizeof (GtkCanvasSimpleRectClass), + (GtkClassInitFunc) gtk_canvas_simplerect_class_init, + (GtkObjectInitFunc) gtk_canvas_simplerect_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + simplerect_type = gtk_type_unique (gtk_canvas_item_get_type (), &simplerect_info); + } + + return simplerect_type; +} + +static void +gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class) +{ + GtkObjectClass *object_class; + GtkCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) class; + item_class = (GtkCanvasItemClass *) class; + + parent_class = gtk_type_class (gtk_canvas_item_get_type ()); + + gtk_object_add_arg_type ("GtkCanvasSimpleRect::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FILL); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::draw", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_COLOR_RGBA); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_pixels", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_PIXELS); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_what", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_WHAT); + + object_class->set_arg = gtk_canvas_simplerect_set_arg; + object_class->get_arg = gtk_canvas_simplerect_get_arg; + + item_class->update = gtk_canvas_simplerect_update; + item_class->bounds = gtk_canvas_simplerect_bounds; + item_class->point = gtk_canvas_simplerect_point; + item_class->render = gtk_canvas_simplerect_render; + item_class->draw = gtk_canvas_simplerect_draw; +} + +static void +gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect) +{ + simplerect->x1 = 0.0; + simplerect->y1 = 0.0; + simplerect->x2 = 0.0; + simplerect->y2 = 0.0; + simplerect->fill = TRUE; + simplerect->draw = TRUE; + simplerect->full_draw_on_update = TRUE; + simplerect->fill_color = 0; + simplerect->outline_color = 0; + simplerect->outline_pixels = 1; + simplerect->outline_what = 0xf; + + GTK_CANVAS_ITEM(simplerect)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; +} + +static void +gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + GtkCanvasSimpleRect *simplerect = GTK_CANVAS_SIMPLERECT (item); + + *x1 = simplerect->x1; + *y1 = simplerect->y1; + *x2 = simplerect->x2 + 1; + *y2 = simplerect->y2 + 1; + +} + +static void +gtk_canvas_simplerect_reset_bounds (GtkCanvasItem *item) +{ + GtkCanvasSimpleRect* simplerect; + double x1, x2, y1, y2; + double old_x1, old_x2, old_y1, old_y2; + double a, b; + + old_x1 = item->x1; + old_y1 = item->y1; + old_x2 = item->x2; + old_y2 = item->y2; + + gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2); + gtk_canvas_item_i2w (item, &x1, &y1); + gtk_canvas_item_i2w (item, &x2, &y2); + + item->x1 = x1; + item->y1 = y1; + item->x2 = x2; + item->y2 = y2; + + /* now compute bounding box in canvas units */ + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x1, y1, &simplerect->bbox_ulx, &simplerect->bbox_uly); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry); + + /* now queue redraws for changed areas */ + + if (item->x1 != old_x1) { + + /* left edge changed. redraw the area that altered */ + + a = MIN(item->x1, old_x1); + b = MAX(item->x1, old_x1); + gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2); + } + + if (item->x2 != old_x2) { + + /* right edge changed. redraw the area that altered */ + + a = MIN(item->x2, old_x2); + b = MAX(item->x2, old_x2); + gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2); + } + + if (item->y1 != old_y1) { + + /* top edge changed. redraw the area that altered */ + + a = MIN(item->y1, old_y1); + b = MAX(item->y1, old_y1); + gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1); + } + + if (item->y2 != old_y2) { + + /* lower edge changed. redraw the area that altered */ + + a = MIN(item->y2, old_y2); + b = MAX(item->y2, old_y2); + gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1); + } +} + +/* + * CANVAS CALLBACKS + */ + +static void +gtk_canvas_simplerect_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasItem *item; + GtkCanvasSimpleRect *simplerect; + int update; + int bounds_changed; + + item = GTK_CANVAS_ITEM (object); + simplerect = GTK_CANVAS_SIMPLERECT (object); + + update = FALSE; + bounds_changed = FALSE; + + switch (arg_id) { + case ARG_X1: + if (simplerect->x1 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->x1 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_Y1: + if (simplerect->y1 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->y1 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_X2: + if (simplerect->x2 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->x2 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_Y2: + if (simplerect->y2 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->y2 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_DRAW: + if (simplerect->draw != GTK_VALUE_BOOL (*arg)) { + simplerect->draw = GTK_VALUE_BOOL (*arg); + update = TRUE; + } + break; + + + case ARG_FILL: + if (simplerect->fill != GTK_VALUE_BOOL (*arg)) { + simplerect->fill = GTK_VALUE_BOOL (*arg); + update = TRUE; + } + break; + + case ARG_FILL_COLOR_RGBA: + if (simplerect->fill_color != GTK_VALUE_INT(*arg)) { + simplerect->fill_color = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + case ARG_OUTLINE_COLOR_RGBA: + if (simplerect->outline_color != GTK_VALUE_INT(*arg)) { + simplerect->outline_color = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + case ARG_OUTLINE_PIXELS: + if (simplerect->outline_pixels != GTK_VALUE_INT(*arg)) { + simplerect->outline_pixels = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + case ARG_OUTLINE_WHAT: + if (simplerect->outline_what != GTK_VALUE_INT(*arg)) { + simplerect->outline_what = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + default: + break; + } + + simplerect->full_draw_on_update = update; + + if (update || bounds_changed) { + gtk_canvas_item_request_update (item); + } +} + +static void +gtk_canvas_simplerect_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasSimpleRect *simplerect; + + simplerect = GTK_CANVAS_SIMPLERECT (object); + + switch (arg_id) { + case ARG_X1: + GTK_VALUE_DOUBLE (*arg) = simplerect->x1; + break; + case ARG_Y1: + GTK_VALUE_DOUBLE (*arg) = simplerect->y1; + break; + case ARG_X2: + GTK_VALUE_DOUBLE (*arg) = simplerect->x2; + break; + case ARG_Y2: + GTK_VALUE_DOUBLE (*arg) = simplerect->y2; + break; + case ARG_DRAW: + GTK_VALUE_BOOL (*arg) = simplerect->draw; + break; + case ARG_FILL: + GTK_VALUE_BOOL (*arg) = simplerect->fill; + break; + case ARG_FILL_COLOR_RGBA: + GTK_VALUE_INT (*arg) = simplerect->fill_color; + break; + case ARG_OUTLINE_COLOR_RGBA: + GTK_VALUE_INT (*arg) = simplerect->outline_color; + break; + case ARG_OUTLINE_PIXELS: + GTK_VALUE_INT (*arg) = simplerect->outline_pixels; + break; + case ARG_OUTLINE_WHAT: + GTK_VALUE_INT (*arg) = simplerect->outline_what; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GtkCanvasSimpleRect *simplerect; + unsigned char foo; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + gtk_canvas_simplerect_reset_bounds (item); + + if (simplerect->full_draw_on_update) { + gtk_canvas_request_redraw (item->canvas, + simplerect->bbox_ulx, + simplerect->bbox_uly, + simplerect->bbox_lrx+1, + simplerect->bbox_lry+1); + simplerect->full_draw_on_update = FALSE; + } + + UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a); + UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo); +} + +#define SIMPLERECT_FAST_RENDERER +#ifdef SIMPLERECT_FAST_RENDERER + +static void +gtk_canvas_simplerect_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasSimpleRect *simplerect; + int end, begin; + int ey, sy; + unsigned int i; + ArtIRect intersection; + ArtIRect self; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1); + + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + if (!simplerect->draw) { + return; + } + + self.x0 = simplerect->bbox_ulx; + self.y0 = simplerect->bbox_uly; + self.x1 = simplerect->bbox_lrx; + self.y1 = simplerect->bbox_lry; + + art_irect_intersect (&intersection, &self, &buf->rect); + + begin = MAX(simplerect->bbox_ulx, buf->rect.x0); + end = MIN((simplerect->bbox_lrx-1), buf->rect.x1); + + sy = simplerect->bbox_uly; + ey = simplerect->bbox_lry-1; + + if (simplerect->fill) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey); + + FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, + intersection.x0, intersection.y0, + intersection.x1, intersection.y1); + + } + + for (i = 0; i < simplerect->outline_pixels; ++i) { + + if (simplerect->outline_what & 0x1) { + if (begin == simplerect->bbox_ulx) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey); + } + } + + if (simplerect->outline_what & 0x2) { + if (end == (simplerect->bbox_lrx - 1)) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1); + } + } + + if (simplerect->outline_what & 0x4) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i); + } + + if (simplerect->outline_what & 0x8) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i); + } + } +} + +#else /* SIMPLERECT_FAST_RENDERER */ + +static void +gtk_canvas_simplerect_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasSimpleRect *simplerect; + int end, begin; + int ey, sy; + unsigned int i; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1); + + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + if (!simplerect->draw) { + return; + } + + begin = MAX(simplerect->bbox_ulx,buf->rect.x0); + end = MIN((simplerect->bbox_lrx-1),buf->rect.x1); + + sy = simplerect->bbox_uly; + ey = simplerect->bbox_lry-1; + + if (simplerect->fill) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey); + + PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey); + } + + for (i = 0; i < simplerect->outline_pixels; ++i) { + + if (simplerect->outline_what & 0x1) { + if (begin == simplerect->bbox_ulx) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey); + } + } + + if (simplerect->outline_what & 0x2) { + if (end == (simplerect->bbox_lrx - 1)) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1); + } + } + + if (simplerect->outline_what & 0x4) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i); + } + + if (simplerect->outline_what & 0x8) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i); + } + } +} +#endif /* SIMPLERECT_FAST_RENDERER */ + +static void +gtk_canvas_simplerect_draw (GtkCanvasItem *item, + GdkDrawable *drawable, + int x, int y, + int width, int height) +{ + fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n"); + abort (); +} + +static double +gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) +{ + GtkCanvasSimpleRect *simplerect; + double x1, y1, x2, y2; + double dx, dy; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + *actual_item = item; + + /* Find the bounds for the rectangle plus its outline width */ + + gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2); + + /* Is point inside rectangle */ + + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { + return 0.0; + } + + /* Point is outside rectangle */ + + if (x < x1) + dx = x1 - x; + else if (x > x2) + dx = x - x2; + else + dx = 0.0; + + if (y < y1) + dy = y1 - y; + else if (y > y2) + dy = y - y2; + else + dy = 0.0; + + return sqrt (dx * dx + dy * dy); +} -- cgit v1.2.3