summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--roi.c147
1 files changed, 68 insertions, 79 deletions
diff --git a/roi.c b/roi.c
index d8d9912..91a71ca 100644
--- a/roi.c
+++ b/roi.c
@@ -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;
}