diff options
-rw-r--r-- | roi.c | 147 |
1 files changed, 68 insertions, 79 deletions
@@ -5,10 +5,6 @@ #include <gdk-pixbuf/gdk-pixbuf.h> #include <gtk/gtk.h> -struct rect { - gint x, y, width, height; -}; - struct roi { GtkWidget *window; GtkWidget *drawing_area; @@ -20,9 +16,12 @@ struct roi { GdkPixbuf *input, *modified_input; - struct rect motion; - struct rect roi_area; - struct rect previous_draw; + cairo_rectangle_t area; + + gboolean doing_rubberband; + struct { + double x1, y1, x2, y2; + } rubberband; }; void @@ -41,17 +40,17 @@ do_roi(struct roi *roi) } interval[3]; match = gdk_pixbuf_new_subpixbuf(roi->input, - roi->roi_area.x, - roi->roi_area.y, - roi->roi_area.width, - roi->roi_area.height); + roi->area.x, + roi->area.y, + roi->area.width, + roi->area.height); nch = gdk_pixbuf_get_n_channels(match); stride = gdk_pixbuf_get_rowstride(match); - s = roi->roi_area.width * roi->roi_area.height; + s = roi->area.width * roi->area.height; for (y = 0, row = gdk_pixbuf_get_pixels(match); - y < roi->roi_area.height; ++y, row += stride) { - for (x = 0, pix = row; x < roi->roi_area.width; ++x, pix += nch) { + y < roi->area.height; ++y, row += stride) { + for (x = 0, pix = row; x < roi->area.width; ++x, pix += nch) { for (i = 0; i < 3; ++i) middle[i] += pix[i]; } @@ -60,8 +59,8 @@ do_roi(struct roi *roi) middle[i] /= s; for (y = 0, row = gdk_pixbuf_get_pixels(match); - y < roi->roi_area.height; ++y, row += stride) { - for (x = 0, pix = row; x < roi->roi_area.width; ++x, pix += nch) { + y < roi->area.height; ++y, row += stride) { + for (x = 0, pix = row; x < roi->area.width; ++x, pix += nch) { for (i = 0; i < 3; ++i) sigma[i] += (pix[i] - middle[i]) * @@ -111,49 +110,13 @@ do_roi(struct roi *roi) gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer userdata) { - GtkStyleContext *context; struct roi *roi = userdata; - GdkWindow *win = gtk_widget_get_window(widget); - cairo_rectangle_t rect; - cairo_t *cr; - - rect.x = roi->motion.x; - rect.y = roi->motion.y; - rect.width = event->x - roi->motion.x; - rect.height = event->y - roi->motion.y; - - /* gdk_window_begin_paint_rect(win, &rect); */ - - context = gtk_widget_get_style_context(widget); - gtk_style_context_save(context); - gtk_style_context_add_class(context, GTK_STYLE_CLASS_RUBBERBAND); - cr = gdk_cairo_create(win); - cairo_save(cr); - gdk_cairo_set_source_pixbuf(cr, roi->input, 0, 0); - cairo_rectangle(cr, - roi->previous_draw.x, - roi->previous_draw.y, - roi->previous_draw.width+1, - roi->previous_draw.height+1); - cairo_clip(cr); - cairo_paint(cr); - cairo_restore(cr); - - roi->previous_draw.x = roi->motion.x; - roi->previous_draw.y = roi->motion.y; - roi->previous_draw.width = event->x - roi->motion.x; - roi->previous_draw.height = event->y - roi->motion.y; - - cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height); - cairo_clip(cr); - gtk_render_background(context, cr, - rect.x, rect.y, rect.width, rect.height); - gtk_render_frame(context, cr, - rect.x, rect.y, rect.width, rect.height); - cairo_destroy(cr); - gtk_style_context_restore(context); - /* gdk_window_end_paint(win); */ + if (roi->doing_rubberband) { + roi->rubberband.x2 = event->x; + roi->rubberband.y2 = event->y; + gtk_widget_queue_draw(roi->drawing_area); + } return TRUE; } @@ -163,13 +126,32 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer userdata) { struct roi *roi = userdata; - if (event->button != 1) + switch (event->button) { +#ifndef GDK_BUTTON_PRIMARY +#define GDK_BUTTON_PRIMARY 1 +#endif + case GDK_BUTTON_PRIMARY: + roi->rubberband.x1 = event->x; + roi->rubberband.x2 = event->x; + roi->rubberband.y1 = event->y; + roi->rubberband.y2 = event->y; + + roi->doing_rubberband = TRUE; + return FALSE; + default: return TRUE; + } +} - roi->motion.x = event->x; - roi->motion.y = event->y; - - return FALSE; +static inline void +calc_rubberband_rect(struct roi *roi, + double *x, double *y, + double *width, double *height) +{ + *x = MIN(roi->rubberband.x1, roi->rubberband.x2); + *y = MIN(roi->rubberband.y1, roi->rubberband.y2); + *width = ABS(roi->rubberband.x1 - roi->rubberband.x2); + *height = ABS(roi->rubberband.y1 - roi->rubberband.y2); } gboolean @@ -180,25 +162,13 @@ button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer userdata if (event->button != 1) return TRUE; - roi->roi_area.x = roi->motion.x; - roi->roi_area.y = roi->motion.y; - roi->roi_area.width = event->x - roi->motion.x; - roi->roi_area.height = event->y - roi->motion.y; - - if (roi->roi_area.width < 0) { - roi->roi_area.x -= roi->roi_area.width; - roi->roi_area.width = -roi->roi_area.width; - } - - if (roi->roi_area.height < 0) { - roi->roi_area.y -= roi->roi_area.height; - roi->roi_area.height = -roi->roi_area.height; - } + calc_rubberband_rect(roi, &roi->area.x, &roi->area.y, + &roi->area.width, &roi->area.height); - if (roi->roi_area.width != 0 && - roi->roi_area.height != 0) + if (roi->area.width > 0 && roi->area.height > 0) do_roi(roi); - roi->previous_draw.width = roi->previous_draw.height = 0; + + roi->doing_rubberband = FALSE; gtk_widget_queue_draw(roi->drawing_area); @@ -235,6 +205,22 @@ configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data) return FALSE; } +void +draw_rubberband(struct roi *roi, GtkWidget *widget, cairo_t *cr) +{ + GtkStyleContext *context; + double x, y, width, height; + + context = gtk_widget_get_style_context(widget); + gtk_style_context_save(context); + gtk_style_context_add_class(context, GTK_STYLE_CLASS_RUBBERBAND); + + calc_rubberband_rect(roi, &x, &y, &width, &height); + gtk_render_background(context, cr, x, y, width, height); + gtk_render_frame(context, cr, x, y, width, height); + gtk_style_context_restore(context); +} + gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer userdata) { @@ -244,6 +230,9 @@ draw_cb(GtkWidget *widget, cairo_t *cr, gpointer userdata) roi->modified_input : roi->input, 0, 0); cairo_paint(cr); + if (roi->doing_rubberband) + draw_rubberband(roi, widget, cr); + return FALSE; } |