[cheese] um-crop-area: Update from gnome-control-center
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cheese] um-crop-area: Update from gnome-control-center
- Date: Mon, 7 Mar 2011 09:40:31 +0000 (UTC)
commit 7aa7fbb952073d263bc6d7dbfe8d71aed7cfb753
Author: Bastien Nocera <hadess hadess net>
Date: Tue Feb 1 01:13:44 2011 +0000
um-crop-area: Update from gnome-control-center
for GTK+ 3.x porting.
https://bugzilla.gnome.org/show_bug.cgi?id=641100
libcheese/um-crop-area.c | 1204 ++++++++++++++++++++++++++--------------------
libcheese/um-crop-area.h | 33 +-
2 files changed, 694 insertions(+), 543 deletions(-)
---
diff --git a/libcheese/um-crop-area.c b/libcheese/um-crop-area.c
index dd79e1d..177ec02 100644
--- a/libcheese/um-crop-area.c
+++ b/libcheese/um-crop-area.c
@@ -19,6 +19,8 @@
* Written by: Matthias Clasen <mclasen redhat com>
*/
+#include "cheese-config.h"
+
#include <stdlib.h>
#include <glib.h>
@@ -27,18 +29,20 @@
#include "um-crop-area.h"
-struct _UmCropAreaPrivate
-{
- GdkPixbuf *browse_pixbuf;
- GdkPixbuf *pixbuf;
- GdkPixbuf *color_shifted;
- gdouble scale;
- GdkRectangle image;
- GdkCursorType current_cursor;
- GdkRectangle crop;
- gint active_region;
- gint last_press_x;
- gint last_press_y;
+struct _UmCropAreaPrivate {
+ GdkPixbuf *browse_pixbuf;
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *color_shifted;
+ gdouble scale;
+ GdkRectangle image;
+ GdkCursorType current_cursor;
+ GdkRectangle crop;
+ gint active_region;
+ gint last_press_x;
+ gint last_press_y;
+ gint base_width;
+ gint base_height;
+ gdouble aspect;
};
G_DEFINE_TYPE (UmCropArea, um_crop_area, GTK_TYPE_DRAWING_AREA);
@@ -47,7 +51,7 @@ static inline guchar
shift_color_byte (guchar b,
int shift)
{
- return CLAMP (b + shift, 0, 255);
+ return CLAMP(b + shift, 0, 255);
}
static void
@@ -57,280 +61,206 @@ shift_colors (GdkPixbuf *pixbuf,
gint blue,
gint alpha)
{
- gint x, y, offset, y_offset, rowstride, width, height;
- guchar *pixels;
- gint channels;
-
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- channels = gdk_pixbuf_get_n_channels (pixbuf);
-
- for (y = 0; y < height; y++)
- {
- y_offset = y * rowstride;
- for (x = 0; x < width; x++)
- {
- offset = y_offset + x * channels;
- if (red != 0)
- pixels[offset] = shift_color_byte (pixels[offset], red);
- if (green != 0)
- pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
- if (blue != 0)
- pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
- if (alpha != 0 && channels >= 4)
- pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
- }
- }
+ gint x, y, offset, y_offset, rowstride, width, height;
+ guchar *pixels;
+ gint channels;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
+ channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+ for (y = 0; y < height; y++) {
+ y_offset = y * rowstride;
+ for (x = 0; x < width; x++) {
+ offset = y_offset + x * channels;
+ if (red != 0)
+ pixels[offset] = shift_color_byte (pixels[offset], red);
+ if (green != 0)
+ pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
+ if (blue != 0)
+ pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
+ if (alpha != 0 && channels >= 4)
+ pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
+ }
+ }
}
static void
update_pixbufs (UmCropArea *area)
{
- GtkAllocation allocation;
- GtkStyle *style;
- GtkWidget *widget;
- GdkColor *color;
- gdouble scale;
- gint width;
- gint height;
- gint dest_x, dest_y, dest_width, dest_height;
- guint32 pixel;
-
- widget = GTK_WIDGET (area);
- gtk_widget_get_allocation (widget, &allocation);
-
- if (area->priv->pixbuf == NULL ||
- gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
- gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height)
- {
- if (area->priv->pixbuf != NULL)
- g_object_unref (area->priv->pixbuf);
- area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
- allocation.width, allocation.height);
-
- style = gtk_widget_get_style (widget);
- color = &style->bg[gtk_widget_get_state (widget)];
- pixel = ((color->red & 0xff00) << 16) |
- ((color->green & 0xff00) << 8) |
- (color->blue & 0xff00);
- gdk_pixbuf_fill (area->priv->pixbuf, pixel);
-
- width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
- height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
-
- scale = allocation.height / (gdouble) height;
- if (scale * width > allocation.width)
- scale = allocation.width / (gdouble) width;
-
- dest_width = width * scale;
- dest_height = height * scale;
- dest_x = (allocation.width - dest_width) / 2;
- dest_y = (allocation.height - dest_height) / 2,
-
- gdk_pixbuf_scale (area->priv->browse_pixbuf,
- area->priv->pixbuf,
- dest_x, dest_y,
- dest_width, dest_height,
- dest_x, dest_y,
- scale, scale,
- GDK_INTERP_BILINEAR);
-
- if (area->priv->color_shifted)
- g_object_unref (area->priv->color_shifted);
- area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
- shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
-
- if (area->priv->scale == 0.0)
- {
- area->priv->crop.width = 96.0 / scale;
- area->priv->crop.height = 96.0 / scale;
- area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
- area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
- }
-
- area->priv->scale = scale;
- area->priv->image.x = dest_x;
- area->priv->image.y = dest_y;
- area->priv->image.width = dest_width;
- area->priv->image.height = dest_height;
- }
+ gint width;
+ gint height;
+ GtkAllocation allocation;
+ gdouble scale;
+ GdkRGBA color;
+ guint32 pixel;
+ gint dest_x, dest_y, dest_width, dest_height;
+ GtkWidget *widget;
+ GtkStyleContext *context;
+
+ widget = GTK_WIDGET (area);
+ gtk_widget_get_allocation (widget, &allocation);
+ context = gtk_widget_get_style_context (widget);
+
+ if (area->priv->pixbuf == NULL ||
+ gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
+ gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height) {
+ if (area->priv->pixbuf != NULL)
+ g_object_unref (area->priv->pixbuf);
+ area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ gdk_pixbuf_get_has_alpha (area->priv->browse_pixbuf),
+ 8,
+ allocation.width, allocation.height);
+
+ gtk_style_context_get_background_color (context, gtk_style_context_get_state (context), &color);
+ pixel = (((gint)(color.red * 255)) << 16) |
+ (((gint)(color.green * 255)) << 8) |
+ ((gint)(color.blue * 255));
+ gdk_pixbuf_fill (area->priv->pixbuf, pixel);
+
+ width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+ height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+
+ scale = allocation.height / (gdouble)height;
+ if (scale * width > allocation.width)
+ scale = allocation.width / (gdouble)width;
+
+ dest_width = width * scale;
+ dest_height = height * scale;
+ dest_x = (allocation.width - dest_width) / 2;
+ dest_y = (allocation.height - dest_height) / 2,
+
+ gdk_pixbuf_scale (area->priv->browse_pixbuf,
+ area->priv->pixbuf,
+ dest_x, dest_y,
+ dest_width, dest_height,
+ dest_x, dest_y,
+ scale, scale,
+ GDK_INTERP_BILINEAR);
+
+ if (area->priv->color_shifted)
+ g_object_unref (area->priv->color_shifted);
+ area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
+ shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
+
+ if (area->priv->scale == 0.0) {
+ area->priv->crop.width = 2 * area->priv->base_width / scale;
+ area->priv->crop.height = 2 * area->priv->base_height / scale;
+ area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
+ area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
+ }
+
+ area->priv->scale = scale;
+ area->priv->image.x = dest_x;
+ area->priv->image.y = dest_y;
+ area->priv->image.width = dest_width;
+ area->priv->image.height = dest_height;
+ }
}
static void
-crop_to_widget (UmCropArea *area,
- GdkRectangle *crop)
+crop_to_widget (UmCropArea *area,
+ GdkRectangle *crop)
{
- crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
- crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
- crop->width = area->priv->crop.width * area->priv->scale;
- crop->height = area->priv->crop.height * area->priv->scale;
+ crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
+ crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
+ crop->width = area->priv->crop.width * area->priv->scale;
+ crop->height = area->priv->crop.height * area->priv->scale;
}
-typedef enum
-{
- OUTSIDE,
- INSIDE,
- TOP,
- TOP_LEFT,
- TOP_RIGHT,
- BOTTOM,
- BOTTOM_LEFT,
- BOTTOM_RIGHT,
- LEFT,
- RIGHT
+typedef enum {
+ OUTSIDE,
+ INSIDE,
+ TOP,
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT,
+ LEFT,
+ RIGHT
} Location;
static gboolean
-um_crop_area_expose (GtkWidget *widget,
- GdkEventExpose *event)
+um_crop_area_draw (GtkWidget *widget,
+ cairo_t *cr)
{
- GtkStateType state;
- GtkStyle *style;
- cairo_t *cr;
- GdkRectangle area;
- GdkRectangle crop;
- GdkWindow *window;
- gint width, height;
- UmCropArea *uarea = UM_CROP_AREA (widget);
-
- if (uarea->priv->browse_pixbuf == NULL)
- return FALSE;
-
- update_pixbufs (uarea);
-
- window = gtk_widget_get_window (widget);
- style = gtk_widget_get_style (widget);
- state = gtk_widget_get_state (widget);
-
- width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
- height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
- crop_to_widget (uarea, &crop);
-
- area.x = 0;
- area.y = 0;
- area.width = width;
- area.height = crop.y;
- gdk_rectangle_intersect (&area, &event->area, &area);
- gdk_draw_pixbuf (window,
- style->fg_gc[state],
- uarea->priv->color_shifted,
- area.x, area.y,
- area.x, area.y,
- area.width, area.height,
- GDK_RGB_DITHER_NONE, 0, 0);
-
- area.x = 0;
- area.y = crop.y;
- area.width = crop.x;
- area.height = crop.height;
- gdk_rectangle_intersect (&area, &event->area, &area);
- gdk_draw_pixbuf (window,
- style->fg_gc[state],
- uarea->priv->color_shifted,
- area.x, area.y,
- area.x, area.y,
- area.width, area.height,
- GDK_RGB_DITHER_NONE, 0, 0);
-
- area.x = crop.x;
- area.y = crop.y;
- area.width = crop.width;
- area.height = crop.height;
- gdk_rectangle_intersect (&area, &event->area, &area);
- gdk_draw_pixbuf (window,
- style->fg_gc[state],
- uarea->priv->pixbuf,
- area.x, area.y,
- area.x, area.y,
- area.width, area.height,
- GDK_RGB_DITHER_NONE, 0, 0);
-
- area.x = crop.x + crop.width;
- area.y = crop.y;
- area.width = width - area.x;
- area.height = crop.height;
- gdk_rectangle_intersect (&area, &event->area, &area);
- gdk_draw_pixbuf (window,
- style->fg_gc[state],
- uarea->priv->color_shifted,
- area.x, area.y,
- area.x, area.y,
- area.width, area.height,
- GDK_RGB_DITHER_NONE, 0, 0);
-
- area.x = 0;
- area.y = crop.y + crop.width;
- area.width = width;
- area.height = height - area.y;
- gdk_rectangle_intersect (&area, &event->area, &area);
- gdk_draw_pixbuf (window,
- style->fg_gc[state],
- uarea->priv->color_shifted,
- area.x, area.y,
- area.x, area.y,
- area.width, area.height,
- GDK_RGB_DITHER_NONE, 0, 0);
-
- cr = gdk_cairo_create (window);
- gdk_cairo_rectangle (cr, &event->area);
- cairo_clip (cr);
-
- if (uarea->priv->active_region != OUTSIDE)
- {
- gint x1, x2, y1, y2;
- gdk_cairo_set_source_color (cr, &style->white);
- cairo_set_line_width (cr, 1.0);
- x1 = crop.x + crop.width / 3.0;
- x2 = crop.x + 2 * crop.width / 3.0;
- y1 = crop.y + crop.height / 3.0;
- y2 = crop.y + 2 * crop.height / 3.0;
-
- cairo_move_to (cr, x1 + 0.5, crop.y);
- cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
-
- cairo_move_to (cr, x2 + 0.5, crop.y);
- cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
-
- cairo_move_to (cr, crop.x, y1 + 0.5);
- cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
-
- cairo_move_to (cr, crop.x, y2 + 0.5);
- cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
- cairo_stroke (cr);
- }
-
- gdk_cairo_set_source_color (cr, &style->black);
- cairo_set_line_width (cr, 1.0);
- cairo_rectangle (cr,
- crop.x + 0.5,
- crop.y + 0.5,
- crop.width - 1.0,
- crop.height - 1.0);
- cairo_stroke (cr);
-
- gdk_cairo_set_source_color (cr, &style->white);
- cairo_set_line_width (cr, 2.0);
- cairo_rectangle (cr,
- crop.x + 2.0,
- crop.y + 2.0,
- crop.width - 4.0,
- crop.height - 4.0);
- cairo_stroke (cr);
-
- cairo_destroy (cr);
-
- return FALSE;
+ GdkRectangle crop;
+ gint width, height;
+ UmCropArea *uarea = UM_CROP_AREA (widget);
+
+ if (uarea->priv->browse_pixbuf == NULL)
+ return FALSE;
+
+ update_pixbufs (uarea);
+
+ width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
+ height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
+ crop_to_widget (uarea, &crop);
+
+ gdk_cairo_set_source_pixbuf (cr, uarea->priv->color_shifted, 0, 0);
+ cairo_rectangle (cr, 0, 0, width, crop.y);
+ cairo_rectangle (cr, 0, crop.y, crop.x, crop.height);
+ cairo_rectangle (cr, crop.x + crop.width, crop.y, width - crop.x - crop.width, crop.height);
+ cairo_rectangle (cr, 0, crop.y + crop.height, width, height - crop.y - crop.height);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, uarea->priv->pixbuf, 0, 0);
+ cairo_rectangle (cr, crop.x, crop.y, crop.width, crop.height);
+ cairo_fill (cr);
+
+ if (uarea->priv->active_region != OUTSIDE) {
+ gint x1, x2, y1, y2;
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_set_line_width (cr, 1.0);
+ x1 = crop.x + crop.width / 3.0;
+ x2 = crop.x + 2 * crop.width / 3.0;
+ y1 = crop.y + crop.height / 3.0;
+ y2 = crop.y + 2 * crop.height / 3.0;
+
+ cairo_move_to (cr, x1 + 0.5, crop.y);
+ cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
+
+ cairo_move_to (cr, x2 + 0.5, crop.y);
+ cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
+
+ cairo_move_to (cr, crop.x, y1 + 0.5);
+ cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
+
+ cairo_move_to (cr, crop.x, y2 + 0.5);
+ cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
+ cairo_stroke (cr);
+ }
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_set_line_width (cr, 1.0);
+ cairo_rectangle (cr,
+ crop.x + 0.5,
+ crop.y + 0.5,
+ crop.width - 1.0,
+ crop.height - 1.0);
+ cairo_stroke (cr);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_set_line_width (cr, 2.0);
+ cairo_rectangle (cr,
+ crop.x + 2.0,
+ crop.y + 2.0,
+ crop.width - 4.0,
+ crop.height - 4.0);
+ cairo_stroke (cr);
+
+ return FALSE;
}
-typedef enum
-{
- BELOW,
- LOWER,
- BETWEEN,
- UPPER,
- ABOVE
+typedef enum {
+ BELOW,
+ LOWER,
+ BETWEEN,
+ UPPER,
+ ABOVE
} Range;
static Range
@@ -338,17 +268,17 @@ find_range (gint x,
gint min,
gint max)
{
- gint tolerance = 12;
-
- if (x < min - tolerance)
- return BELOW;
- if (x <= min + tolerance)
- return LOWER;
- if (x < max - tolerance)
- return BETWEEN;
- if (x <= max + tolerance)
- return UPPER;
- return ABOVE;
+ gint tolerance = 12;
+
+ if (x < min - tolerance)
+ return BELOW;
+ if (x <= min + tolerance)
+ return LOWER;
+ if (x < max - tolerance)
+ return BETWEEN;
+ if (x <= max + tolerance)
+ return UPPER;
+ return ABOVE;
}
static Location
@@ -356,314 +286,532 @@ find_location (GdkRectangle *rect,
gint x,
gint y)
{
- Range x_range, y_range;
- Location location[5][5] = {
- {OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE},
- {OUTSIDE, TOP_LEFT, TOP, TOP_RIGHT, OUTSIDE},
- {OUTSIDE, LEFT, INSIDE, RIGHT, OUTSIDE},
- {OUTSIDE, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT, OUTSIDE},
- {OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE}
- };
-
- x_range = find_range (x, rect->x, rect->x + rect->width);
- y_range = find_range (y, rect->y, rect->y + rect->height);
-
- return location[y_range][x_range];
+ Range x_range, y_range;
+ Location location[5][5] = {
+ { OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE },
+ { OUTSIDE, TOP_LEFT, TOP, TOP_RIGHT, OUTSIDE },
+ { OUTSIDE, LEFT, INSIDE, RIGHT, OUTSIDE },
+ { OUTSIDE, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT, OUTSIDE },
+ { OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE }
+ };
+
+ x_range = find_range (x, rect->x, rect->x + rect->width);
+ y_range = find_range (y, rect->y, rect->y + rect->height);
+
+ return location[y_range][x_range];
}
static void
update_cursor (UmCropArea *area,
- gint x,
- gint y)
+ gint x,
+ gint y)
+{
+ gint cursor_type;
+ GdkRectangle crop;
+ gint region;
+
+ region = area->priv->active_region;
+ if (region == OUTSIDE) {
+ crop_to_widget (area, &crop);
+ region = find_location (&crop, x, y);
+ }
+
+ switch (region) {
+ case OUTSIDE:
+ cursor_type = GDK_LEFT_PTR;
+ break;
+ case TOP_LEFT:
+ cursor_type = GDK_TOP_LEFT_CORNER;
+ break;
+ case TOP:
+ cursor_type = GDK_TOP_SIDE;
+ break;
+ case TOP_RIGHT:
+ cursor_type = GDK_TOP_RIGHT_CORNER;
+ break;
+ case LEFT:
+ cursor_type = GDK_LEFT_SIDE;
+ break;
+ case INSIDE:
+ cursor_type = GDK_FLEUR;
+ break;
+ case RIGHT:
+ cursor_type = GDK_RIGHT_SIDE;
+ break;
+ case BOTTOM_LEFT:
+ cursor_type = GDK_BOTTOM_LEFT_CORNER;
+ break;
+ case BOTTOM:
+ cursor_type = GDK_BOTTOM_SIDE;
+ break;
+ case BOTTOM_RIGHT:
+ cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (cursor_type != area->priv->current_cursor) {
+ GdkCursor *cursor = gdk_cursor_new (cursor_type);
+ gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (area)), cursor);
+ g_object_unref (cursor);
+ area->priv->current_cursor = cursor_type;
+ }
+}
+
+static int
+eval_radial_line (gdouble center_x, gdouble center_y,
+ gdouble bounds_x, gdouble bounds_y,
+ gdouble user_x)
{
- gint cursor_type;
- GdkRectangle crop;
-
- crop_to_widget (area, &crop);
-
- switch (find_location (&crop, x, y))
- {
- case OUTSIDE:
- cursor_type = GDK_LEFT_PTR;
- break;
- case TOP_LEFT:
- cursor_type = GDK_TOP_LEFT_CORNER;
- break;
- case TOP:
- cursor_type = GDK_TOP_SIDE;
- break;
- case TOP_RIGHT:
- cursor_type = GDK_TOP_RIGHT_CORNER;
- break;
- case LEFT:
- cursor_type = GDK_LEFT_SIDE;
- break;
- case INSIDE:
- cursor_type = GDK_FLEUR;
- break;
- case RIGHT:
- cursor_type = GDK_RIGHT_SIDE;
- break;
- case BOTTOM_LEFT:
- cursor_type = GDK_BOTTOM_LEFT_CORNER;
- break;
- case BOTTOM:
- cursor_type = GDK_BOTTOM_SIDE;
- break;
- case BOTTOM_RIGHT:
- cursor_type = GDK_BOTTOM_RIGHT_CORNER;
- break;
- }
-
- if (cursor_type != area->priv->current_cursor)
- {
- GdkCursor *cursor = gdk_cursor_new (cursor_type);
- gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (area)), cursor);
- gdk_cursor_unref (cursor);
- area->priv->current_cursor = cursor_type;
- }
+ gdouble decision_slope;
+ gdouble decision_intercept;
+
+ decision_slope = (bounds_y - center_y) / (bounds_x - center_x);
+ decision_intercept = bounds_y = -(decision_slope * bounds_x);
+
+ return (int) (decision_slope * user_x + decision_intercept);
}
static gboolean
um_crop_area_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event)
{
- gint x, y;
- gint x2, y2;
- gint delta_x, delta_y;
- gint width, height, d;
- UmCropArea *area = UM_CROP_AREA (widget);
-
- width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
- height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
-
- x = (event->x - area->priv->image.x) / area->priv->scale;
- y = (event->y - area->priv->image.y) / area->priv->scale;
- x = CLAMP (x, 0, width);
- y = CLAMP (y, 0, height);
-
- delta_x = x - area->priv->last_press_x;
- delta_y = y - area->priv->last_press_y;
- area->priv->last_press_x = x;
- area->priv->last_press_y = y;
-
- x2 = area->priv->crop.x + area->priv->crop.width;
- y2 = area->priv->crop.y + area->priv->crop.height;
-
- switch (area->priv->active_region)
- {
- case INSIDE:
- area->priv->crop.x = CLAMP (area->priv->crop.x + delta_x, 0, width - area->priv->crop.width);
- area->priv->crop.y = CLAMP (area->priv->crop.y + delta_y, 0, height - area->priv->crop.height);
- break;
-
- case TOP_LEFT:
- d = MAX (x2 - x, y2 - y);
- if (d < 48 / area->priv->scale)
- d = 48 / area->priv->scale;
- if (x2 - d < 0)
- d = x2;
- if (y2 - d < 0)
- d = y2;
- area->priv->crop.x = x2 - d;
- area->priv->crop.y = y2 - d;
- area->priv->crop.width = area->priv->crop.height = d;
- break;
-
- case TOP:
- case TOP_RIGHT:
- d = MAX (y2 - y, x - area->priv->crop.x);
- if (d < 48 / area->priv->scale)
- d = 48 / area->priv->scale;
- if (area->priv->crop.x + d > width)
- d = width - area->priv->crop.x;
- if (y2 - d < 0)
- d = y2;
- area->priv->crop.y = y2 - d;
- area->priv->crop.width = area->priv->crop.height = d;
- break;
-
- case LEFT:
- case BOTTOM_LEFT:
- d = MAX (x2 - x, y - area->priv->crop.y);
- if (d < 48 / area->priv->scale)
- d = 48 / area->priv->scale;
- if (area->priv->crop.y + d > height)
- d = height - area->priv->crop.y;
- if (x2 - d < 0)
- d = x2;
- area->priv->crop.x = x2 - d;
- area->priv->crop.width = area->priv->crop.height = d;
- break;
-
- case RIGHT:
- case BOTTOM_RIGHT:
- case BOTTOM:
- area->priv->crop.width = MAX (x - area->priv->crop.x, y - area->priv->crop.y);
- if (area->priv->crop.width < 48 / area->priv->scale)
- area->priv->crop.width = 48 / area->priv->scale;
- if (area->priv->crop.x + area->priv->crop.width > width)
- area->priv->crop.width = width - area->priv->crop.x;
- area->priv->crop.height = area->priv->crop.width;
- if (area->priv->crop.y + area->priv->crop.height > height)
- area->priv->crop.height = height - area->priv->crop.y;
- area->priv->crop.width = area->priv->crop.height;
- break;
-
- case OUTSIDE:
- break;
- default:;
- }
-
- update_cursor (area, event->x, event->y);
- gtk_widget_queue_draw (widget);
-
- return FALSE;
+ UmCropArea *area = UM_CROP_AREA (widget);
+ gint x, y;
+ gint delta_x, delta_y;
+ gint width, height;
+ gint adj_width, adj_height;
+ gint pb_width, pb_height;
+ GdkRectangle damage;
+ gint left, right, top, bottom;
+ gdouble new_width, new_height;
+ gdouble center_x, center_y;
+ gint min_width, min_height;
+
+ if (area->priv->browse_pixbuf == NULL)
+ return FALSE;
+
+ update_cursor (area, event->x, event->y);
+
+ crop_to_widget (area, &damage);
+ gtk_widget_queue_draw_area (widget,
+ damage.x - 1, damage.y - 1,
+ damage.width + 2, damage.height + 2);
+
+ pb_width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+ pb_height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+
+ x = (event->x - area->priv->image.x) / area->priv->scale;
+ y = (event->y - area->priv->image.y) / area->priv->scale;
+
+ delta_x = x - area->priv->last_press_x;
+ delta_y = y - area->priv->last_press_y;
+ area->priv->last_press_x = x;
+ area->priv->last_press_y = y;
+
+ left = area->priv->crop.x;
+ right = area->priv->crop.x + area->priv->crop.width - 1;
+ top = area->priv->crop.y;
+ bottom = area->priv->crop.y + area->priv->crop.height - 1;
+
+ center_x = (left + right) / 2.0;
+ center_y = (top + bottom) / 2.0;
+
+ switch (area->priv->active_region) {
+ case INSIDE:
+ width = right - left + 1;
+ height = bottom - top + 1;
+
+ left += delta_x;
+ right += delta_x;
+ top += delta_y;
+ bottom += delta_y;
+
+ if (left < 0)
+ left = 0;
+ if (top < 0)
+ top = 0;
+ if (right > pb_width)
+ right = pb_width;
+ if (bottom > pb_height)
+ bottom = pb_height;
+
+ adj_width = right - left + 1;
+ adj_height = bottom - top + 1;
+ if (adj_width != width) {
+ if (delta_x < 0)
+ right = left + width - 1;
+ else
+ left = right - width + 1;
+ }
+ if (adj_height != height) {
+ if (delta_y < 0)
+ bottom = top + height - 1;
+ else
+ top = bottom - height + 1;
+ }
+
+ break;
+
+ case TOP_LEFT:
+ if (area->priv->aspect < 0) {
+ top = y;
+ left = x;
+ }
+ else if (y < eval_radial_line (center_x, center_y, left, top, x)) {
+ top = y;
+ new_width = (bottom - top) * area->priv->aspect;
+ left = right - new_width;
+ }
+ else {
+ left = x;
+ new_height = (right - left) / area->priv->aspect;
+ top = bottom - new_height;
+ }
+ break;
+
+ case TOP:
+ top = y;
+ if (area->priv->aspect > 0) {
+ new_width = (bottom - top) * area->priv->aspect;
+ right = left + new_width;
+ }
+ break;
+
+ case TOP_RIGHT:
+ if (area->priv->aspect < 0) {
+ top = y;
+ right = x;
+ }
+ else if (y < eval_radial_line (center_x, center_y, right, top, x)) {
+ top = y;
+ new_width = (bottom - top) * area->priv->aspect;
+ right = left + new_width;
+ }
+ else {
+ right = x;
+ new_height = (right - left) / area->priv->aspect;
+ top = bottom - new_height;
+ }
+ break;
+
+ case LEFT:
+ left = x;
+ if (area->priv->aspect > 0) {
+ new_height = (right - left) / area->priv->aspect;
+ bottom = top + new_height;
+ }
+ break;
+
+ case BOTTOM_LEFT:
+ if (area->priv->aspect < 0) {
+ bottom = y;
+ left = x;
+ }
+ else if (y < eval_radial_line (center_x, center_y, left, bottom, x)) {
+ left = x;
+ new_height = (right - left) / area->priv->aspect;
+ bottom = top + new_height;
+ }
+ else {
+ bottom = y;
+ new_width = (bottom - top) * area->priv->aspect;
+ left = right - new_width;
+ }
+ break;
+
+ case RIGHT:
+ right = x;
+ if (area->priv->aspect > 0) {
+ new_height = (right - left) / area->priv->aspect;
+ bottom = top + new_height;
+ }
+ break;
+
+ case BOTTOM_RIGHT:
+ if (area->priv->aspect < 0) {
+ bottom = y;
+ right = x;
+ }
+ else if (y < eval_radial_line (center_x, center_y, right, bottom, x)) {
+ right = x;
+ new_height = (right - left) / area->priv->aspect;
+ bottom = top + new_height;
+ }
+ else {
+ bottom = y;
+ new_width = (bottom - top) * area->priv->aspect;
+ right = left + new_width;
+ }
+ break;
+
+ case BOTTOM:
+ bottom = y;
+ if (area->priv->aspect > 0) {
+ new_width = (bottom - top) * area->priv->aspect;
+ right= left + new_width;
+ }
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ min_width = area->priv->base_width / area->priv->scale;
+ min_height = area->priv->base_height / area->priv->scale;
+
+ width = right - left + 1;
+ height = bottom - top + 1;
+ if (area->priv->aspect < 0) {
+ if (left < 0)
+ left = 0;
+ if (top < 0)
+ top = 0;
+ if (right > pb_width)
+ right = pb_width;
+ if (bottom > pb_height)
+ bottom = pb_height;
+
+ width = right - left + 1;
+ height = bottom - top + 1;
+
+ switch (area->priv->active_region) {
+ case LEFT:
+ case TOP_LEFT:
+ case BOTTOM_LEFT:
+ if (width < min_width)
+ left = right - min_width;
+ break;
+ case RIGHT:
+ case TOP_RIGHT:
+ case BOTTOM_RIGHT:
+ if (width < min_width)
+ right = left + min_width;
+ break;
+
+ default: ;
+ }
+
+ switch (area->priv->active_region) {
+ case TOP:
+ case TOP_LEFT:
+ case TOP_RIGHT:
+ if (height < min_height)
+ top = bottom - min_height;
+ break;
+ case BOTTOM:
+ case BOTTOM_LEFT:
+ case BOTTOM_RIGHT:
+ if (height < min_height)
+ bottom = top + min_height;
+ break;
+
+ default: ;
+ }
+ }
+ else {
+ if (left < 0 || top < 0 ||
+ right > pb_width || bottom > pb_height ||
+ width < min_width || height < min_height) {
+ left = area->priv->crop.x;
+ right = area->priv->crop.x + area->priv->crop.width - 1;
+ top = area->priv->crop.y;
+ bottom = area->priv->crop.y + area->priv->crop.height - 1;
+ }
+ }
+
+ area->priv->crop.x = left;
+ area->priv->crop.y = top;
+ area->priv->crop.width = right - left + 1;
+ area->priv->crop.height = bottom - top + 1;
+
+ crop_to_widget (area, &damage);
+ gtk_widget_queue_draw_area (widget,
+ damage.x - 1, damage.y - 1,
+ damage.width + 2, damage.height + 2);
+
+ return FALSE;
}
static gboolean
um_crop_area_button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
- GdkRectangle crop;
- UmCropArea *area = UM_CROP_AREA (widget);
+ UmCropArea *area = UM_CROP_AREA (widget);
+ GdkRectangle crop;
- crop_to_widget (area, &crop);
+ if (area->priv->browse_pixbuf == NULL)
+ return FALSE;
- area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
- area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
- area->priv->active_region = find_location (&crop, event->x, event->y);
+ crop_to_widget (area, &crop);
- gtk_widget_queue_draw (widget);
+ area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
+ area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
+ area->priv->active_region = find_location (&crop, event->x, event->y);
- return FALSE;
+ gtk_widget_queue_draw_area (widget,
+ crop.x - 1, crop.y - 1,
+ crop.width + 2, crop.height + 2);
+
+ return FALSE;
}
static gboolean
um_crop_area_button_release_event (GtkWidget *widget,
GdkEventButton *event)
{
- UmCropArea *area = UM_CROP_AREA (widget);
+ UmCropArea *area = UM_CROP_AREA (widget);
+ GdkRectangle crop;
+
+ if (area->priv->browse_pixbuf == NULL)
+ return FALSE;
+
+ crop_to_widget (area, &crop);
- area->priv->last_press_x = -1;
- area->priv->last_press_y = -1;
- area->priv->active_region = OUTSIDE;
+ area->priv->last_press_x = -1;
+ area->priv->last_press_y = -1;
+ area->priv->active_region = OUTSIDE;
- gtk_widget_queue_draw (widget);
+ gtk_widget_queue_draw_area (widget,
+ crop.x - 1, crop.y - 1,
+ crop.width + 2, crop.height + 2);
- return FALSE;
+ return FALSE;
}
static void
um_crop_area_finalize (GObject *object)
{
- UmCropArea *area = UM_CROP_AREA (object);
-
- if (area->priv->browse_pixbuf)
- {
- g_object_unref (area->priv->browse_pixbuf);
- area->priv->browse_pixbuf = NULL;
- }
- if (area->priv->pixbuf)
- {
- g_object_unref (area->priv->pixbuf);
- area->priv->pixbuf = NULL;
- }
- if (area->priv->color_shifted)
- {
- g_object_unref (area->priv->color_shifted);
- area->priv->color_shifted = NULL;
- }
+ UmCropArea *area = UM_CROP_AREA (object);
+
+ if (area->priv->browse_pixbuf) {
+ g_object_unref (area->priv->browse_pixbuf);
+ area->priv->browse_pixbuf = NULL;
+ }
+ if (area->priv->pixbuf) {
+ g_object_unref (area->priv->pixbuf);
+ area->priv->pixbuf = NULL;
+ }
+ if (area->priv->color_shifted) {
+ g_object_unref (area->priv->color_shifted);
+ area->priv->color_shifted = NULL;
+ }
}
static void
um_crop_area_class_init (UmCropAreaClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- object_class->finalize = um_crop_area_finalize;
- widget_class->expose_event = um_crop_area_expose;
- widget_class->button_press_event = um_crop_area_button_press_event;
- widget_class->button_release_event = um_crop_area_button_release_event;
- widget_class->motion_notify_event = um_crop_area_motion_notify_event;
+ object_class->finalize = um_crop_area_finalize;
+ widget_class->draw = um_crop_area_draw;
+ widget_class->button_press_event = um_crop_area_button_press_event;
+ widget_class->button_release_event = um_crop_area_button_release_event;
+ widget_class->motion_notify_event = um_crop_area_motion_notify_event;
- g_type_class_add_private (klass, sizeof (UmCropAreaPrivate));
+ g_type_class_add_private (klass, sizeof (UmCropAreaPrivate));
}
static void
um_crop_area_init (UmCropArea *area)
{
- area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), UM_TYPE_CROP_AREA,
- UmCropAreaPrivate));
-
- gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK);
-
- area->priv->scale = 0.0;
- area->priv->image.x = 0;
- area->priv->image.y = 0;
- area->priv->image.width = 0;
- area->priv->image.height = 0;
- area->priv->active_region = OUTSIDE;
+ area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), UM_TYPE_CROP_AREA,
+ UmCropAreaPrivate));
+
+ gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK);
+
+ area->priv->scale = 0.0;
+ area->priv->image.x = 0;
+ area->priv->image.y = 0;
+ area->priv->image.width = 0;
+ area->priv->image.height = 0;
+ area->priv->active_region = OUTSIDE;
+ area->priv->base_width = 48;
+ area->priv->base_height = 48;
+ area->priv->aspect = 1;
}
GtkWidget *
um_crop_area_new (void)
{
- return g_object_new (UM_TYPE_CROP_AREA, NULL);
+ return g_object_new (UM_TYPE_CROP_AREA, NULL);
}
GdkPixbuf *
um_crop_area_get_picture (UmCropArea *area)
{
- return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
- area->priv->crop.x, area->priv->crop.y,
- area->priv->crop.width, area->priv->crop.height);
+ gint width, height;
+
+ width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+ height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+ width = MIN (area->priv->crop.width, width - area->priv->crop.x);
+ height = MIN (area->priv->crop.height, height - area->priv->crop.y);
+
+ return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
+ area->priv->crop.x,
+ area->priv->crop.y,
+ width, height);
}
void
um_crop_area_set_picture (UmCropArea *area,
GdkPixbuf *pixbuf)
{
- int width;
- int height;
-
- if (area->priv->browse_pixbuf)
- {
- g_object_unref (area->priv->browse_pixbuf);
- area->priv->browse_pixbuf = NULL;
- }
- if (pixbuf)
- {
- area->priv->browse_pixbuf = g_object_ref (pixbuf);
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- }
- else
- {
- width = 0;
- height = 0;
- }
-
-#if 0
- gtk_widget_get_allocation (um->browse_drawing_area, &allocation);
- um->priv->crop.width = 96;
- um->priv->crop.height = 96;
- um->priv->crop.x = (allocation.width - um->priv->crop.width) / 2;
- um->priv->crop.y = (allocation.height - um->priv->crop.height) / 2;
-#else
- area->priv->crop.width = 96;
- area->priv->crop.height = 96;
- area->priv->crop.x = (width - area->priv->crop.width) / 2;
- area->priv->crop.y = (height - area->priv->crop.height) / 2;
-#endif
- area->priv->scale = 0.0;
- area->priv->image.x = 0;
- area->priv->image.y = 0;
- area->priv->image.width = 0;
- area->priv->image.height = 0;
-
- gtk_widget_queue_draw (GTK_WIDGET (area));
+ int width;
+ int height;
+
+ if (area->priv->browse_pixbuf) {
+ g_object_unref (area->priv->browse_pixbuf);
+ area->priv->browse_pixbuf = NULL;
+ }
+ if (pixbuf) {
+ area->priv->browse_pixbuf = g_object_ref (pixbuf);
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ } else {
+ width = 0;
+ height = 0;
+ }
+
+ area->priv->crop.width = 2 * area->priv->base_width;
+ area->priv->crop.height = 2 * area->priv->base_height;
+ area->priv->crop.x = (width - area->priv->crop.width) / 2;
+ area->priv->crop.y = (height - area->priv->crop.height) / 2;
+
+ area->priv->scale = 0.0;
+ area->priv->image.x = 0;
+ area->priv->image.y = 0;
+ area->priv->image.width = 0;
+ area->priv->image.height = 0;
+
+ gtk_widget_queue_draw (GTK_WIDGET (area));
+}
+
+void
+um_crop_area_set_min_size (UmCropArea *area,
+ gint width,
+ gint height)
+{
+ area->priv->base_width = width;
+ area->priv->base_height = height;
+
+ if (area->priv->aspect > 0) {
+ area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
+ }
+}
+
+void
+um_crop_area_set_constrain_aspect (UmCropArea *area,
+ gboolean constrain)
+{
+ if (constrain) {
+ area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
+ }
+ else {
+ area->priv->aspect = -1;
+ }
}
diff --git a/libcheese/um-crop-area.h b/libcheese/um-crop-area.h
index 6db90f8..8992957 100644
--- a/libcheese/um-crop-area.h
+++ b/libcheese/um-crop-area.h
@@ -27,35 +27,38 @@ G_BEGIN_DECLS
#define UM_TYPE_CROP_AREA (um_crop_area_get_type ())
#define UM_CROP_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UM_TYPE_CROP_AREA, \
- UmCropArea))
+ UmCropArea))
#define UM_CROP_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UM_TYPE_CROP_AREA, \
- UmCropAreaClass))
+ UmCropAreaClass))
#define UM_IS_CROP_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UM_TYPE_CROP_AREA))
#define UM_IS_CROP_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UM_TYPE_CROP_AREA))
#define UM_CROP_AREA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UM_TYPE_CROP_AREA, \
- UmCropAreaClass))
+ UmCropAreaClass))
typedef struct _UmCropAreaClass UmCropAreaClass;
typedef struct _UmCropArea UmCropArea;
typedef struct _UmCropAreaPrivate UmCropAreaPrivate;
-struct _UmCropAreaClass
-{
- GtkDrawingAreaClass parent_class;
+struct _UmCropAreaClass {
+ GtkDrawingAreaClass parent_class;
};
-struct _UmCropArea
-{
- GtkDrawingArea parent_instance;
- UmCropAreaPrivate *priv;
+struct _UmCropArea {
+ GtkDrawingArea parent_instance;
+ UmCropAreaPrivate *priv;
};
-GType um_crop_area_get_type (void) G_GNUC_CONST;
+GType um_crop_area_get_type (void) G_GNUC_CONST;
-GtkWidget *um_crop_area_new (void);
-GdkPixbuf *um_crop_area_get_picture (UmCropArea *area);
-void um_crop_area_set_picture (UmCropArea *area,
- GdkPixbuf *pixbuf);
+GtkWidget *um_crop_area_new (void);
+GdkPixbuf *um_crop_area_get_picture (UmCropArea *area);
+void um_crop_area_set_picture (UmCropArea *area,
+ GdkPixbuf *pixbuf);
+void um_crop_area_set_min_size (UmCropArea *area,
+ gint width,
+ gint height);
+void um_crop_area_set_constrain_aspect (UmCropArea *area,
+ gboolean constrain);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]