~ubuntu-branches/debian/jessie/cheese/jessie

« back to all changes in this revision

Viewing changes to libcheese/um-crop-area.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2010-05-04 17:37:18 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20100504173718-k2rx3nryi4vd0xyx
Tags: 2.30.1-1
* New upstream release.
  - HAL dependency has been dropped. Use (g)udev for v4l capability probing
    on Linux. Closes: #573774
  - Split code into separate libraries.
* debian/control.in
  - Drop Build-Depends on libhal-dev.
  - Drop Build-Depends on libebook1.2-dev.
  - Bump Build-Depends on libgtk2.0-dev to (>= 2.19.1).
  - Bump Build-Depends on libgstreamer*-dev to (>= 0.10.23).
  - Add Build-Depends on libcanberra-gtk-dev.
  - Add Build-Depends on libxtst-dev.
  - Add Build-Depends on libgudev-1.0-dev on Linux.
  - Bump Standards-Version to 3.8.4. No further changes.
* Switch to source format 3.0 (quilt)
  - Add debian/source/format.
* debian/rules
  - Drop lpia specific configure flags, lpia is dead.
* Update package layout (based on work by Ubuntu)
  - Move data files into new cheese-common package.
  - Keep binary along with its desktop and dbus service file in the cheese
    package.
  - Add libcheese-gtk18 and libcheese-gtk-dev package for the new
    libcheese-gtk library. Use a symbols file for improved shlibs
    dependencies.
  - Add Conflicts/Replaces to cheese-common to ensure proper upgrades from
    previous versions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright 2009  Red Hat, Inc,
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * Written by: Matthias Clasen <mclasen@redhat.com>
 
20
 */
 
21
 
 
22
#include <stdlib.h>
 
23
 
 
24
#include <glib.h>
 
25
#include <glib/gi18n.h>
 
26
#include <gtk/gtk.h>
 
27
 
 
28
#include "um-crop-area.h"
 
29
 
 
30
struct _UmCropAreaPrivate {
 
31
        GdkPixbuf *browse_pixbuf;
 
32
        GdkPixbuf *pixbuf;
 
33
        GdkPixbuf *color_shifted;
 
34
        gdouble scale;
 
35
        GdkRectangle image;
 
36
        GdkCursorType current_cursor;
 
37
        GdkRectangle crop;
 
38
        gint active_region;
 
39
        gint last_press_x;
 
40
        gint last_press_y;
 
41
};
 
42
 
 
43
G_DEFINE_TYPE (UmCropArea, um_crop_area, GTK_TYPE_DRAWING_AREA);
 
44
 
 
45
static inline guchar
 
46
shift_color_byte (guchar b,
 
47
                  int    shift)
 
48
{
 
49
        return CLAMP(b + shift, 0, 255);
 
50
}
 
51
 
 
52
static void
 
53
shift_colors (GdkPixbuf *pixbuf,
 
54
              gint       red,
 
55
              gint       green,
 
56
              gint       blue,
 
57
              gint       alpha)
 
58
{
 
59
        gint x, y, offset, y_offset, rowstride, width, height;
 
60
        guchar *pixels;
 
61
        gint channels;
 
62
 
 
63
        width = gdk_pixbuf_get_width (pixbuf);
 
64
        height = gdk_pixbuf_get_height (pixbuf);
 
65
        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
 
66
        pixels = gdk_pixbuf_get_pixels (pixbuf);
 
67
        channels = gdk_pixbuf_get_n_channels (pixbuf);
 
68
 
 
69
        for (y = 0; y < height; y++) {
 
70
                y_offset = y * rowstride;
 
71
                for (x = 0; x < width; x++) {
 
72
                        offset = y_offset + x * channels;
 
73
                        if (red != 0)
 
74
                                pixels[offset] = shift_color_byte (pixels[offset], red);
 
75
                        if (green != 0)
 
76
                                pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
 
77
                        if (blue != 0)
 
78
                                pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
 
79
                        if (alpha != 0 && channels >= 4)
 
80
                                pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
 
81
                }
 
82
        }
 
83
}
 
84
 
 
85
static void
 
86
update_pixbufs (UmCropArea *area)
 
87
{
 
88
        GtkAllocation allocation;
 
89
        GtkStyle *style;
 
90
        GtkWidget *widget;
 
91
        GdkColor *color;
 
92
        gdouble scale;
 
93
        gint width;
 
94
        gint height;
 
95
        gint dest_x, dest_y, dest_width, dest_height;
 
96
        guint32 pixel;
 
97
 
 
98
        widget = GTK_WIDGET (area);
 
99
        gtk_widget_get_allocation (widget, &allocation);
 
100
 
 
101
        if (area->priv->pixbuf == NULL ||
 
102
            gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
 
103
            gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height) {
 
104
                if (area->priv->pixbuf != NULL)
 
105
                        g_object_unref (area->priv->pixbuf);
 
106
                area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
 
107
                                             allocation.width, allocation.height);
 
108
 
 
109
                style = gtk_widget_get_style (widget);
 
110
                color = &style->bg[gtk_widget_get_state (widget)];
 
111
                pixel = ((color->red & 0xff00) << 16) |
 
112
                        ((color->green & 0xff00) << 8) |
 
113
                         (color->blue & 0xff00);
 
114
                gdk_pixbuf_fill (area->priv->pixbuf, pixel);
 
115
 
 
116
                width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
 
117
                height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
 
118
 
 
119
                scale = allocation.height / (gdouble)height;
 
120
                if (scale * width > allocation.width)
 
121
                    scale = allocation.width / (gdouble)width;
 
122
 
 
123
                dest_width = width * scale;
 
124
                dest_height = height * scale;
 
125
                dest_x = (allocation.width - dest_width) / 2;
 
126
                dest_y = (allocation.height - dest_height) / 2,
 
127
 
 
128
                gdk_pixbuf_scale (area->priv->browse_pixbuf,
 
129
                                  area->priv->pixbuf,
 
130
                                  dest_x, dest_y,
 
131
                                  dest_width, dest_height,
 
132
                                  dest_x, dest_y,
 
133
                                  scale, scale,
 
134
                                  GDK_INTERP_BILINEAR);
 
135
 
 
136
                if (area->priv->color_shifted)
 
137
                        g_object_unref (area->priv->color_shifted);
 
138
                area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
 
139
                shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
 
140
 
 
141
                if (area->priv->scale == 0.0) {
 
142
                        area->priv->crop.width = 96.0 / scale;
 
143
                        area->priv->crop.height = 96.0 / scale;
 
144
                        area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
 
145
                        area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
 
146
                }
 
147
 
 
148
                area->priv->scale = scale;
 
149
                area->priv->image.x = dest_x;
 
150
                area->priv->image.y = dest_y;
 
151
                area->priv->image.width = dest_width;
 
152
                area->priv->image.height = dest_height;
 
153
        }
 
154
}
 
155
 
 
156
static void
 
157
crop_to_widget (UmCropArea    *area,
 
158
                GdkRectangle  *crop)
 
159
{
 
160
        crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
 
161
        crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
 
162
        crop->width = area->priv->crop.width * area->priv->scale;
 
163
        crop->height = area->priv->crop.height * area->priv->scale;
 
164
}
 
165
 
 
166
typedef enum {
 
167
        OUTSIDE,
 
168
        INSIDE,
 
169
        TOP,
 
170
        TOP_LEFT,
 
171
        TOP_RIGHT,
 
172
        BOTTOM,
 
173
        BOTTOM_LEFT,
 
174
        BOTTOM_RIGHT,
 
175
        LEFT,
 
176
        RIGHT
 
177
} Location;
 
178
 
 
179
static gboolean
 
180
um_crop_area_expose (GtkWidget      *widget,
 
181
                     GdkEventExpose *event)
 
182
{
 
183
        GtkStateType state;
 
184
        GtkStyle *style;
 
185
        cairo_t *cr;
 
186
        GdkRectangle area;
 
187
        GdkRectangle crop;
 
188
        GdkWindow *window;
 
189
        gint width, height;
 
190
        UmCropArea *uarea = UM_CROP_AREA (widget);
 
191
 
 
192
        if (uarea->priv->browse_pixbuf == NULL)
 
193
                return FALSE;
 
194
 
 
195
        update_pixbufs (uarea);
 
196
 
 
197
        window = gtk_widget_get_window (widget);
 
198
        style = gtk_widget_get_style (widget);
 
199
        state = gtk_widget_get_state (widget);
 
200
 
 
201
        width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
 
202
        height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
 
203
        crop_to_widget (uarea, &crop);
 
204
 
 
205
        area.x = 0;
 
206
        area.y = 0;
 
207
        area.width = width;
 
208
        area.height = crop.y;
 
209
        gdk_rectangle_intersect (&area, &event->area, &area);
 
210
        gdk_draw_pixbuf (window,
 
211
                         style->fg_gc[state],
 
212
                         uarea->priv->color_shifted,
 
213
                         area.x, area.y,
 
214
                         area.x, area.y,
 
215
                         area.width, area.height,
 
216
                         GDK_RGB_DITHER_NONE, 0, 0);
 
217
 
 
218
        area.x = 0;
 
219
        area.y = crop.y;
 
220
        area.width = crop.x;
 
221
        area.height = crop.height;
 
222
        gdk_rectangle_intersect (&area, &event->area, &area);
 
223
        gdk_draw_pixbuf (window,
 
224
                         style->fg_gc[state],
 
225
                         uarea->priv->color_shifted,
 
226
                         area.x, area.y,
 
227
                         area.x, area.y,
 
228
                         area.width, area.height,
 
229
                         GDK_RGB_DITHER_NONE, 0, 0);
 
230
 
 
231
        area.x = crop.x;
 
232
        area.y = crop.y;
 
233
        area.width = crop.width;
 
234
        area.height = crop.height;
 
235
        gdk_rectangle_intersect (&area, &event->area, &area);
 
236
        gdk_draw_pixbuf (window,
 
237
                         style->fg_gc[state],
 
238
                         uarea->priv->pixbuf,
 
239
                         area.x, area.y,
 
240
                         area.x, area.y,
 
241
                         area.width, area.height,
 
242
                         GDK_RGB_DITHER_NONE, 0, 0);
 
243
 
 
244
        area.x = crop.x + crop.width;
 
245
        area.y = crop.y;
 
246
        area.width = width - area.x;
 
247
        area.height = crop.height;
 
248
        gdk_rectangle_intersect (&area, &event->area, &area);
 
249
        gdk_draw_pixbuf (window,
 
250
                         style->fg_gc[state],
 
251
                         uarea->priv->color_shifted,
 
252
                         area.x, area.y,
 
253
                         area.x, area.y,
 
254
                         area.width, area.height,
 
255
                         GDK_RGB_DITHER_NONE, 0, 0);
 
256
 
 
257
        area.x = 0;
 
258
        area.y = crop.y + crop.width;
 
259
        area.width = width;
 
260
        area.height = height - area.y;
 
261
        gdk_rectangle_intersect (&area, &event->area, &area);
 
262
        gdk_draw_pixbuf (window,
 
263
                         style->fg_gc[state],
 
264
                         uarea->priv->color_shifted,
 
265
                         area.x, area.y,
 
266
                         area.x, area.y,
 
267
                         area.width, area.height,
 
268
                         GDK_RGB_DITHER_NONE, 0, 0);
 
269
 
 
270
        cr = gdk_cairo_create (window);
 
271
        gdk_cairo_rectangle (cr, &event->area);
 
272
        cairo_clip (cr);
 
273
 
 
274
        if (uarea->priv->active_region != OUTSIDE) {
 
275
                gint x1, x2, y1, y2;
 
276
                gdk_cairo_set_source_color (cr, &style->white);
 
277
                cairo_set_line_width (cr, 1.0);
 
278
                x1 = crop.x + crop.width / 3.0;
 
279
                x2 = crop.x + 2 * crop.width / 3.0;
 
280
                y1 = crop.y + crop.height / 3.0;
 
281
                y2 = crop.y + 2 * crop.height / 3.0;
 
282
 
 
283
                cairo_move_to (cr, x1 + 0.5, crop.y);
 
284
                cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
 
285
 
 
286
                cairo_move_to (cr, x2 + 0.5, crop.y);
 
287
                cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
 
288
 
 
289
                cairo_move_to (cr, crop.x, y1 + 0.5);
 
290
                cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
 
291
 
 
292
                cairo_move_to (cr, crop.x, y2 + 0.5);
 
293
                cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
 
294
                cairo_stroke (cr);
 
295
        }
 
296
 
 
297
        gdk_cairo_set_source_color (cr, &style->black);
 
298
        cairo_set_line_width (cr, 1.0);
 
299
        cairo_rectangle (cr,
 
300
                         crop.x + 0.5,
 
301
                         crop.y + 0.5,
 
302
                         crop.width - 1.0,
 
303
                         crop.height - 1.0);
 
304
        cairo_stroke (cr);
 
305
 
 
306
        gdk_cairo_set_source_color (cr, &style->white);
 
307
        cairo_set_line_width (cr, 2.0);
 
308
        cairo_rectangle (cr,
 
309
                         crop.x + 2.0,
 
310
                         crop.y + 2.0,
 
311
                         crop.width - 4.0,
 
312
                         crop.height - 4.0);
 
313
        cairo_stroke (cr);
 
314
 
 
315
        cairo_destroy (cr);
 
316
 
 
317
        return FALSE;
 
318
}
 
319
 
 
320
typedef enum {
 
321
        BELOW,
 
322
        LOWER,
 
323
        BETWEEN,
 
324
        UPPER,
 
325
        ABOVE
 
326
} Range;
 
327
 
 
328
static Range
 
329
find_range (gint x,
 
330
            gint min,
 
331
            gint max)
 
332
{
 
333
        gint tolerance = 12;
 
334
 
 
335
        if (x < min - tolerance)
 
336
                return BELOW;
 
337
        if (x <= min + tolerance)
 
338
                return LOWER;
 
339
        if (x < max - tolerance)
 
340
                return BETWEEN;
 
341
        if (x <= max + tolerance)
 
342
                return UPPER;
 
343
        return ABOVE;
 
344
}
 
345
 
 
346
static Location
 
347
find_location (GdkRectangle *rect,
 
348
               gint          x,
 
349
               gint          y)
 
350
{
 
351
        Range x_range, y_range;
 
352
        Location location[5][5] = {
 
353
                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE },
 
354
                { OUTSIDE, TOP_LEFT,    TOP,     TOP_RIGHT,    OUTSIDE },
 
355
                { OUTSIDE, LEFT,        INSIDE,  RIGHT,        OUTSIDE },
 
356
                { OUTSIDE, BOTTOM_LEFT, BOTTOM,  BOTTOM_RIGHT, OUTSIDE },
 
357
                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE }
 
358
        };
 
359
 
 
360
        x_range = find_range (x, rect->x, rect->x + rect->width);
 
361
        y_range = find_range (y, rect->y, rect->y + rect->height);
 
362
 
 
363
        return location[y_range][x_range];
 
364
}
 
365
 
 
366
static void
 
367
update_cursor (UmCropArea *area,
 
368
               gint           x,
 
369
               gint           y)
 
370
{
 
371
        gint cursor_type;
 
372
        GdkRectangle crop;
 
373
 
 
374
        crop_to_widget (area, &crop);
 
375
 
 
376
        switch (find_location (&crop, x, y)) {
 
377
        case OUTSIDE:
 
378
                cursor_type = GDK_LEFT_PTR;
 
379
                break;
 
380
        case TOP_LEFT:
 
381
                cursor_type = GDK_TOP_LEFT_CORNER;
 
382
                break;
 
383
        case TOP:
 
384
                cursor_type = GDK_TOP_SIDE;
 
385
                break;
 
386
        case TOP_RIGHT:
 
387
                cursor_type = GDK_TOP_RIGHT_CORNER;
 
388
                break;
 
389
        case LEFT:
 
390
                cursor_type = GDK_LEFT_SIDE;
 
391
                break;
 
392
        case INSIDE:
 
393
                cursor_type = GDK_FLEUR;
 
394
                break;
 
395
        case RIGHT:
 
396
                cursor_type = GDK_RIGHT_SIDE;
 
397
                break;
 
398
        case BOTTOM_LEFT:
 
399
                cursor_type = GDK_BOTTOM_LEFT_CORNER;
 
400
                break;
 
401
        case BOTTOM:
 
402
                cursor_type = GDK_BOTTOM_SIDE;
 
403
                break;
 
404
        case BOTTOM_RIGHT:
 
405
                cursor_type = GDK_BOTTOM_RIGHT_CORNER;
 
406
                break;
 
407
        }
 
408
 
 
409
        if (cursor_type != area->priv->current_cursor) {
 
410
                GdkCursor *cursor = gdk_cursor_new (cursor_type);
 
411
                gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (area)), cursor);
 
412
                gdk_cursor_unref (cursor);
 
413
                area->priv->current_cursor = cursor_type;
 
414
        }
 
415
}
 
416
 
 
417
static gboolean 
 
418
um_crop_area_motion_notify_event (GtkWidget      *widget,
 
419
                                  GdkEventMotion *event)
 
420
{
 
421
        gint x, y;
 
422
        gint x2, y2;
 
423
        gint delta_x, delta_y;
 
424
        gint width, height, d;
 
425
        UmCropArea *area = UM_CROP_AREA (widget);
 
426
 
 
427
        width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
 
428
        height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
 
429
 
 
430
        x = (event->x - area->priv->image.x) / area->priv->scale;
 
431
        y = (event->y - area->priv->image.y) / area->priv->scale;
 
432
        x = CLAMP (x, 0, width);
 
433
        y = CLAMP (y, 0, height);
 
434
 
 
435
        delta_x = x - area->priv->last_press_x;
 
436
        delta_y = y - area->priv->last_press_y;
 
437
        area->priv->last_press_x = x;
 
438
        area->priv->last_press_y = y;
 
439
 
 
440
        x2 = area->priv->crop.x + area->priv->crop.width;
 
441
        y2 = area->priv->crop.y + area->priv->crop.height;
 
442
 
 
443
        switch (area->priv->active_region) {
 
444
        case INSIDE:
 
445
                area->priv->crop.x = CLAMP (area->priv->crop.x + delta_x, 0, width - area->priv->crop.width);
 
446
                area->priv->crop.y = CLAMP (area->priv->crop.y + delta_y, 0, height - area->priv->crop.height);
 
447
                break;
 
448
 
 
449
        case TOP_LEFT:
 
450
                d = MAX (x2 - x, y2 - y);
 
451
                if (d < 48 / area->priv->scale)
 
452
                        d = 48 / area->priv->scale;
 
453
                if (x2 - d < 0)
 
454
                        d = x2;
 
455
                if (y2 - d < 0)
 
456
                        d = y2;
 
457
                area->priv->crop.x = x2 - d;
 
458
                area->priv->crop.y = y2 - d;
 
459
                area->priv->crop.width = area->priv->crop.height = d;
 
460
                break;
 
461
 
 
462
        case TOP:
 
463
        case TOP_RIGHT:
 
464
                d = MAX (y2 - y, x - area->priv->crop.x);
 
465
                if (d < 48 / area->priv->scale)
 
466
                        d = 48 / area->priv->scale;
 
467
                if (area->priv->crop.x + d > width)
 
468
                        d = width - area->priv->crop.x;
 
469
                if (y2 - d < 0)
 
470
                        d = y2;
 
471
                area->priv->crop.y = y2 - d;
 
472
                area->priv->crop.width = area->priv->crop.height = d;
 
473
                break;
 
474
 
 
475
        case LEFT:
 
476
        case BOTTOM_LEFT:
 
477
                d = MAX (x2 - x, y - area->priv->crop.y);
 
478
                if (d < 48 / area->priv->scale)
 
479
                        d = 48 / area->priv->scale;
 
480
                if (area->priv->crop.y + d > height)
 
481
                        d = height - area->priv->crop.y;
 
482
                if (x2 - d < 0)
 
483
                        d = x2;
 
484
                area->priv->crop.x = x2 - d;
 
485
                area->priv->crop.width = area->priv->crop.height = d;
 
486
                break;
 
487
 
 
488
        case RIGHT:
 
489
        case BOTTOM_RIGHT:
 
490
        case BOTTOM:
 
491
                area->priv->crop.width = MAX (x - area->priv->crop.x, y - area->priv->crop.y);
 
492
                if (area->priv->crop.width < 48 / area->priv->scale)
 
493
                        area->priv->crop.width = 48 / area->priv->scale;
 
494
                if (area->priv->crop.x + area->priv->crop.width > width)
 
495
                        area->priv->crop.width = width - area->priv->crop.x;
 
496
                area->priv->crop.height = area->priv->crop.width;
 
497
                if (area->priv->crop.y + area->priv->crop.height > height)
 
498
                        area->priv->crop.height = height - area->priv->crop.y;
 
499
                area->priv->crop.width = area->priv->crop.height;
 
500
                break;
 
501
 
 
502
        case OUTSIDE:
 
503
                break;
 
504
        default: ;
 
505
        }
 
506
 
 
507
        update_cursor (area, event->x, event->y);
 
508
        gtk_widget_queue_draw (widget);
 
509
 
 
510
        return FALSE;
 
511
}
 
512
 
 
513
static gboolean
 
514
um_crop_area_button_press_event (GtkWidget      *widget,
 
515
                                 GdkEventButton *event)
 
516
{
 
517
        GdkRectangle crop;
 
518
        UmCropArea *area = UM_CROP_AREA (widget);
 
519
 
 
520
        crop_to_widget (area, &crop);
 
521
 
 
522
        area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
 
523
        area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
 
524
        area->priv->active_region = find_location (&crop, event->x, event->y);
 
525
 
 
526
        gtk_widget_queue_draw (widget);
 
527
 
 
528
        return FALSE;
 
529
}
 
530
 
 
531
static gboolean
 
532
um_crop_area_button_release_event (GtkWidget      *widget,
 
533
                                   GdkEventButton *event)
 
534
{
 
535
        UmCropArea *area = UM_CROP_AREA (widget);
 
536
 
 
537
        area->priv->last_press_x = -1;
 
538
        area->priv->last_press_y = -1;
 
539
        area->priv->active_region = OUTSIDE;
 
540
 
 
541
        gtk_widget_queue_draw (widget);
 
542
 
 
543
        return FALSE;
 
544
}
 
545
 
 
546
static void
 
547
um_crop_area_finalize (GObject *object)
 
548
{
 
549
        UmCropArea *area = UM_CROP_AREA (object);
 
550
 
 
551
        if (area->priv->browse_pixbuf) {
 
552
                g_object_unref (area->priv->browse_pixbuf);
 
553
                area->priv->browse_pixbuf = NULL;
 
554
        }
 
555
        if (area->priv->pixbuf) {
 
556
                g_object_unref (area->priv->pixbuf);
 
557
                area->priv->pixbuf = NULL;
 
558
        }
 
559
        if (area->priv->color_shifted) {
 
560
                g_object_unref (area->priv->color_shifted);
 
561
                area->priv->color_shifted = NULL;
 
562
        }
 
563
}
 
564
 
 
565
static void
 
566
um_crop_area_class_init (UmCropAreaClass *klass)
 
567
{
 
568
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
569
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
570
 
 
571
        object_class->finalize     = um_crop_area_finalize;
 
572
        widget_class->expose_event = um_crop_area_expose;
 
573
        widget_class->button_press_event = um_crop_area_button_press_event;
 
574
        widget_class->button_release_event = um_crop_area_button_release_event;
 
575
        widget_class->motion_notify_event = um_crop_area_motion_notify_event;
 
576
 
 
577
        g_type_class_add_private (klass, sizeof (UmCropAreaPrivate));
 
578
}
 
579
 
 
580
static void
 
581
um_crop_area_init (UmCropArea *area)
 
582
{
 
583
        area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), UM_TYPE_CROP_AREA,
 
584
                                                   UmCropAreaPrivate));
 
585
 
 
586
        gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
 
587
                               GDK_BUTTON_PRESS_MASK |
 
588
                               GDK_BUTTON_RELEASE_MASK);
 
589
 
 
590
        area->priv->scale = 0.0;
 
591
        area->priv->image.x = 0;
 
592
        area->priv->image.y = 0;
 
593
        area->priv->image.width = 0;
 
594
        area->priv->image.height = 0;
 
595
        area->priv->active_region = OUTSIDE;
 
596
}
 
597
 
 
598
GtkWidget *
 
599
um_crop_area_new (void)
 
600
{
 
601
        return g_object_new (UM_TYPE_CROP_AREA, NULL);
 
602
}
 
603
 
 
604
GdkPixbuf *
 
605
um_crop_area_get_picture (UmCropArea *area)
 
606
{
 
607
        return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
 
608
                                         area->priv->crop.x, area->priv->crop.y,
 
609
                                         area->priv->crop.width, area->priv->crop.height);
 
610
}
 
611
 
 
612
void
 
613
um_crop_area_set_picture (UmCropArea *area,
 
614
                          GdkPixbuf  *pixbuf)
 
615
{
 
616
        int width;
 
617
        int height;
 
618
 
 
619
        if (area->priv->browse_pixbuf) {
 
620
                g_object_unref (area->priv->browse_pixbuf);
 
621
                area->priv->browse_pixbuf = NULL;
 
622
        }
 
623
        if (pixbuf) {
 
624
                area->priv->browse_pixbuf = g_object_ref (pixbuf);
 
625
                width = gdk_pixbuf_get_width (pixbuf);
 
626
                height = gdk_pixbuf_get_height (pixbuf);
 
627
        } else {
 
628
                width = 0;
 
629
                height = 0;
 
630
        }
 
631
 
 
632
#if 0
 
633
        gtk_widget_get_allocation (um->browse_drawing_area, &allocation);
 
634
        um->priv->crop.width = 96;
 
635
        um->priv->crop.height = 96;
 
636
        um->priv->crop.x = (allocation.width - um->priv->crop.width) / 2;
 
637
        um->priv->crop.y = (allocation.height - um->priv->crop.height) / 2;
 
638
#else
 
639
        area->priv->crop.width = 96;
 
640
        area->priv->crop.height = 96;
 
641
        area->priv->crop.x = (width - area->priv->crop.width) / 2;
 
642
        area->priv->crop.y = (height - area->priv->crop.height) / 2;
 
643
#endif
 
644
        area->priv->scale = 0.0;
 
645
        area->priv->image.x = 0;
 
646
        area->priv->image.y = 0;
 
647
        area->priv->image.width = 0;
 
648
        area->priv->image.height = 0;
 
649
 
 
650
        gtk_widget_queue_draw (GTK_WIDGET (area));
 
651
}
 
652