~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to libgimp/gimpzoompreview.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LIBGIMP - The GIMP Library
 
2
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 
3
 *
 
4
 * gimpzoompreview.c
 
5
 * Copyright (C) 2005  David Odin <dindinx@gimp.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <gtk/gtk.h>
 
26
 
 
27
#include "libgimpwidgets/gimpwidgets.h"
 
28
 
 
29
#include "gimpuitypes.h"
 
30
 
 
31
#include "gimp.h"
 
32
 
 
33
#include "gimpdrawablepreview.h"
 
34
#include "gimpzoompreview.h"
 
35
 
 
36
 
 
37
enum
 
38
{
 
39
  PROP_0,
 
40
  PROP_DRAWABLE,
 
41
  PROP_MODEL
 
42
};
 
43
 
 
44
typedef struct GimpZoomPreviewPrivate
 
45
{
 
46
  GimpDrawable  *drawable;
 
47
  GimpZoomModel *model;
 
48
  GdkRectangle   extents;
 
49
} GimpZoomPreviewPrivate;
 
50
 
 
51
 
 
52
#define GIMP_ZOOM_PREVIEW_GET_PRIVATE(obj) \
 
53
  ((GimpZoomPreviewPrivate *) ((GimpZoomPreview *) (obj))->priv)
 
54
 
 
55
static GObject * gimp_zoom_preview_constructor (GType                  type,
 
56
                                                guint                  n_params,
 
57
                                                GObjectConstructParam *params);
 
58
 
 
59
static void     gimp_zoom_preview_get_property    (GObject         *object,
 
60
                                                   guint            property_id,
 
61
                                                   GValue          *value,
 
62
                                                   GParamSpec      *pspec);
 
63
static void     gimp_zoom_preview_set_property    (GObject         *object,
 
64
                                                   guint            property_id,
 
65
                                                   const GValue    *value,
 
66
                                                   GParamSpec      *pspec);
 
67
static void     gimp_zoom_preview_finalize        (GObject         *object);
 
68
 
 
69
static void     gimp_zoom_preview_set_adjustments (GimpZoomPreview *preview,
 
70
                                                   gdouble          old_factor,
 
71
                                                   gdouble          new_factor);
 
72
static void     gimp_zoom_preview_size_allocate   (GtkWidget       *widget,
 
73
                                                   GtkAllocation   *allocation,
 
74
                                                   GimpZoomPreview *preview);
 
75
static void     gimp_zoom_preview_style_set       (GtkWidget       *widget,
 
76
                                                   GtkStyle        *prev_style);
 
77
static gboolean gimp_zoom_preview_scroll_event    (GtkWidget       *widget,
 
78
                                                   GdkEventScroll  *event,
 
79
                                                   GimpZoomPreview *preview);
 
80
static void     gimp_zoom_preview_draw            (GimpPreview     *preview);
 
81
static void     gimp_zoom_preview_draw_buffer     (GimpPreview     *preview,
 
82
                                                   const guchar    *buffer,
 
83
                                                   gint             rowstride);
 
84
static void     gimp_zoom_preview_draw_thumb      (GimpPreview     *preview,
 
85
                                                   GimpPreviewArea *area,
 
86
                                                   gint             width,
 
87
                                                   gint             height);
 
88
static void     gimp_zoom_preview_set_cursor      (GimpPreview     *preview);
 
89
static void     gimp_zoom_preview_transform       (GimpPreview     *preview,
 
90
                                                   gint             src_x,
 
91
                                                   gint             src_y,
 
92
                                                   gint            *dest_x,
 
93
                                                   gint            *dest_y);
 
94
static void     gimp_zoom_preview_untransform     (GimpPreview     *preview,
 
95
                                                   gint             src_x,
 
96
                                                   gint             src_y,
 
97
                                                   gint            *dest_x,
 
98
                                                   gint            *dest_y);
 
99
 
 
100
static void     gimp_zoom_preview_set_drawable    (GimpZoomPreview *preview,
 
101
                                                   GimpDrawable    *drawable);
 
102
static void     gimp_zoom_preview_set_model       (GimpZoomPreview *preview,
 
103
                                                   GimpZoomModel   *model);
 
104
 
 
105
static void     gimp_zoom_preview_get_source_area (GimpPreview     *preview,
 
106
                                                   gint            *x,
 
107
                                                   gint            *y,
 
108
                                                   gint            *w,
 
109
                                                   gint            *h);
 
110
 
 
111
 
 
112
G_DEFINE_TYPE (GimpZoomPreview, gimp_zoom_preview, GIMP_TYPE_SCROLLED_PREVIEW)
 
113
 
 
114
#define parent_class gimp_zoom_preview_parent_class
 
115
 
 
116
 
 
117
static void
 
118
gimp_zoom_preview_class_init (GimpZoomPreviewClass *klass)
 
119
{
 
120
  GObjectClass     *object_class  = G_OBJECT_CLASS (klass);
 
121
  GtkWidgetClass   *widget_class  = GTK_WIDGET_CLASS (klass);
 
122
  GimpPreviewClass *preview_class = GIMP_PREVIEW_CLASS (klass);
 
123
 
 
124
  object_class->constructor  = gimp_zoom_preview_constructor;
 
125
  object_class->get_property = gimp_zoom_preview_get_property;
 
126
  object_class->set_property = gimp_zoom_preview_set_property;
 
127
  object_class->finalize     = gimp_zoom_preview_finalize;
 
128
 
 
129
  widget_class->style_set    = gimp_zoom_preview_style_set;
 
130
 
 
131
  preview_class->draw        = gimp_zoom_preview_draw;
 
132
  preview_class->draw_buffer = gimp_zoom_preview_draw_buffer;
 
133
  preview_class->draw_thumb  = gimp_zoom_preview_draw_thumb;
 
134
  preview_class->set_cursor  = gimp_zoom_preview_set_cursor;
 
135
  preview_class->transform   = gimp_zoom_preview_transform;
 
136
  preview_class->untransform = gimp_zoom_preview_untransform;
 
137
 
 
138
  g_type_class_add_private (object_class, sizeof (GimpZoomPreviewPrivate));
 
139
 
 
140
  /**
 
141
   * GimpZoomPreview:drawable:
 
142
   *
 
143
   * The drawable the #GimpZoomPreview is attached to.
 
144
   *
 
145
   * Since: GIMP 2.4
 
146
   */
 
147
  g_object_class_install_property (object_class, PROP_DRAWABLE,
 
148
                                   g_param_spec_pointer ("drawable", NULL, NULL,
 
149
                                                         GIMP_PARAM_READWRITE |
 
150
                                                         G_PARAM_CONSTRUCT_ONLY));
 
151
 
 
152
  /**
 
153
   * GimpZoomPreview:model:
 
154
   *
 
155
   * The #GimpZoomModel used by this #GimpZoomPreview.
 
156
   *
 
157
   * Since: GIMP 2.4
 
158
   */
 
159
  g_object_class_install_property (object_class, PROP_MODEL,
 
160
                                   g_param_spec_object ("model", NULL, NULL,
 
161
                                                        GIMP_TYPE_ZOOM_MODEL,
 
162
                                                        GIMP_PARAM_READWRITE |
 
163
                                                        G_PARAM_CONSTRUCT_ONLY));
 
164
}
 
165
 
 
166
static void
 
167
gimp_zoom_preview_init (GimpZoomPreview *preview)
 
168
{
 
169
  preview->priv = G_TYPE_INSTANCE_GET_PRIVATE (preview,
 
170
                                               GIMP_TYPE_ZOOM_PREVIEW,
 
171
                                               GimpZoomPreviewPrivate);
 
172
 
 
173
  g_signal_connect (GIMP_PREVIEW (preview)->area, "size-allocate",
 
174
                    G_CALLBACK (gimp_zoom_preview_size_allocate),
 
175
                    preview);
 
176
  g_signal_connect (GIMP_PREVIEW (preview)->area, "scroll-event",
 
177
                    G_CALLBACK (gimp_zoom_preview_scroll_event),
 
178
                    preview);
 
179
 
 
180
  g_object_set (GIMP_PREVIEW (preview)->area,
 
181
                "check-size", gimp_check_size (),
 
182
                "check-type", gimp_check_type (),
 
183
                NULL);
 
184
 
 
185
  gimp_scrolled_preview_set_policy (GIMP_SCROLLED_PREVIEW (preview),
 
186
                                    GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
 
187
}
 
188
 
 
189
static GObject *
 
190
gimp_zoom_preview_constructor (GType                  type,
 
191
                               guint                  n_params,
 
192
                               GObjectConstructParam *params)
 
193
{
 
194
  GimpZoomPreviewPrivate *priv;
 
195
  GObject                *object;
 
196
 
 
197
  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
198
 
 
199
  priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (object);
 
200
 
 
201
  if (! priv->model)
 
202
    {
 
203
      GimpZoomModel *model = gimp_zoom_model_new ();
 
204
 
 
205
      gimp_zoom_model_set_range (model, 1.0, 256.0);
 
206
      gimp_zoom_preview_set_model (GIMP_ZOOM_PREVIEW (object), model);
 
207
 
 
208
      g_object_unref (model);
 
209
    }
 
210
 
 
211
  gimp_zoom_preview_set_adjustments (GIMP_ZOOM_PREVIEW (object), 1.0, 1.0);
 
212
 
 
213
  return object;
 
214
}
 
215
 
 
216
static void
 
217
gimp_zoom_preview_get_property (GObject    *object,
 
218
                                guint       property_id,
 
219
                                GValue     *value,
 
220
                                GParamSpec *pspec)
 
221
{
 
222
  GimpZoomPreview *preview = GIMP_ZOOM_PREVIEW (object);
 
223
 
 
224
  switch (property_id)
 
225
    {
 
226
    case PROP_DRAWABLE:
 
227
      g_value_set_pointer (value, gimp_zoom_preview_get_drawable (preview));
 
228
      break;
 
229
 
 
230
    case PROP_MODEL:
 
231
      g_value_set_object (value, gimp_zoom_preview_get_model (preview));
 
232
      break;
 
233
 
 
234
    default:
 
235
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
236
      break;
 
237
    }
 
238
}
 
239
 
 
240
static void
 
241
gimp_zoom_preview_set_property (GObject      *object,
 
242
                                guint         property_id,
 
243
                                const GValue *value,
 
244
                                GParamSpec   *pspec)
 
245
{
 
246
  GimpZoomPreview *preview = GIMP_ZOOM_PREVIEW (object);
 
247
 
 
248
  switch (property_id)
 
249
    {
 
250
    case PROP_DRAWABLE:
 
251
      gimp_zoom_preview_set_drawable (preview, g_value_get_pointer (value));
 
252
      break;
 
253
 
 
254
    case PROP_MODEL:
 
255
      gimp_zoom_preview_set_model (preview, g_value_get_object (value));
 
256
      break;
 
257
 
 
258
    default:
 
259
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
260
      break;
 
261
    }
 
262
}
 
263
 
 
264
static void
 
265
gimp_zoom_preview_finalize (GObject *object)
 
266
{
 
267
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (object);
 
268
 
 
269
  if (priv->model)
 
270
    {
 
271
      g_object_unref (priv->model);
 
272
      priv->model = NULL;
 
273
    }
 
274
 
 
275
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
276
}
 
277
 
 
278
static void
 
279
gimp_zoom_preview_set_adjustments (GimpZoomPreview *preview,
 
280
                                   gdouble          old_factor,
 
281
                                   gdouble          new_factor)
 
282
{
 
283
  GimpScrolledPreview *scrolled_preview = GIMP_SCROLLED_PREVIEW (preview);
 
284
  GtkAdjustment       *adj;
 
285
  gdouble              width;
 
286
  gdouble              height;
 
287
  gdouble              ratio;
 
288
 
 
289
  gimp_scrolled_preview_freeze (scrolled_preview);
 
290
 
 
291
  width  = GIMP_PREVIEW (preview)->width;
 
292
  height = GIMP_PREVIEW (preview)->height;
 
293
 
 
294
  ratio = new_factor / old_factor;
 
295
 
 
296
  adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_preview->hscr));
 
297
  adj->lower          = 0;
 
298
  adj->page_size      = width;
 
299
  adj->upper          = width * new_factor;
 
300
  adj->step_increment = new_factor;
 
301
  adj->page_increment = MAX (width / 2.0, adj->step_increment);
 
302
  adj->value          = CLAMP ((adj->value + width / 2.0) * ratio
 
303
                               - width / 2.0,
 
304
                               adj->lower, adj->upper - width);
 
305
  gtk_adjustment_changed (adj);
 
306
  gtk_adjustment_value_changed (adj);
 
307
 
 
308
  adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_preview->vscr));
 
309
  adj->lower          = 0;
 
310
  adj->page_size      = height;
 
311
  adj->upper          = height * new_factor;
 
312
  adj->step_increment = new_factor;
 
313
  adj->page_increment = MAX (height / 2.0, adj->step_increment);
 
314
  adj->value          = CLAMP ((adj->value + height / 2.0) * ratio
 
315
                               - height / 2.0,
 
316
                               adj->lower, adj->upper - height);
 
317
  gtk_adjustment_changed (adj);
 
318
  gtk_adjustment_value_changed (adj);
 
319
 
 
320
  gimp_scrolled_preview_thaw (scrolled_preview);
 
321
}
 
322
 
 
323
static void
 
324
gimp_zoom_preview_size_allocate (GtkWidget       *widget,
 
325
                                 GtkAllocation   *allocation,
 
326
                                 GimpZoomPreview *preview)
 
327
{
 
328
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
329
  gdouble                 zoom;
 
330
 
 
331
  gint width  = GIMP_PREVIEW (preview)->xmax - GIMP_PREVIEW (preview)->xmin;
 
332
  gint height = GIMP_PREVIEW (preview)->ymax - GIMP_PREVIEW (preview)->ymin;
 
333
 
 
334
  GIMP_PREVIEW (preview)->width  = MIN (width,  allocation->width);
 
335
  GIMP_PREVIEW (preview)->height = MIN (height, allocation->height);
 
336
 
 
337
  zoom = gimp_zoom_model_get_factor (priv->model);
 
338
 
 
339
  gimp_zoom_preview_set_adjustments (preview, zoom, zoom);
 
340
}
 
341
 
 
342
static void
 
343
gimp_zoom_preview_style_set (GtkWidget *widget,
 
344
                             GtkStyle  *prev_style)
 
345
{
 
346
  GimpPreview            *preview  = GIMP_PREVIEW (widget);
 
347
  GimpZoomPreviewPrivate *priv     = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
348
  GimpDrawable           *drawable = priv->drawable;
 
349
  gint                    size;
 
350
  gint                    width, height;
 
351
  gint                    x1, y1;
 
352
  gint                    x2, y2;
 
353
 
 
354
  if (GTK_WIDGET_CLASS (parent_class)->style_set)
 
355
    GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
 
356
 
 
357
  gtk_widget_style_get (widget, "size", &size, NULL);
 
358
 
 
359
  if (_gimp_drawable_preview_get_bounds (drawable, &x1, &y1, &x2, &y2))
 
360
    {
 
361
      width  = x2 - x1;
 
362
      height = y2 - y1;
 
363
    }
 
364
  else
 
365
    {
 
366
      width  = gimp_drawable_width  (drawable->drawable_id);
 
367
      height = gimp_drawable_height (drawable->drawable_id);
 
368
    }
 
369
 
 
370
  if (width > height)
 
371
    {
 
372
      preview->width  = MIN (width, size);
 
373
      preview->height = (height * preview->width) / width;
 
374
    }
 
375
  else
 
376
    {
 
377
      preview->height = MIN (height, size);
 
378
      preview->width  = (width * preview->height) / height;
 
379
    }
 
380
 
 
381
  gtk_widget_set_size_request (preview->area,
 
382
                               preview->width, preview->height);
 
383
}
 
384
 
 
385
static gboolean
 
386
gimp_zoom_preview_scroll_event (GtkWidget       *widget,
 
387
                                GdkEventScroll  *event,
 
388
                                GimpZoomPreview *preview)
 
389
{
 
390
  if (event->state & GDK_CONTROL_MASK)
 
391
    {
 
392
      GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
393
 
 
394
      gimp_scrolled_preview_freeze (GIMP_SCROLLED_PREVIEW (preview));
 
395
 
 
396
      switch (event->direction)
 
397
        {
 
398
        case GDK_SCROLL_UP:
 
399
          gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_IN, 0.0);
 
400
          break;
 
401
 
 
402
        case GDK_SCROLL_DOWN:
 
403
          gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_OUT, 0.0);
 
404
          break;
 
405
 
 
406
        default:
 
407
          break;
 
408
        }
 
409
 
 
410
      gimp_scrolled_preview_thaw (GIMP_SCROLLED_PREVIEW (preview));
 
411
    }
 
412
 
 
413
  return FALSE;
 
414
}
 
415
 
 
416
static void
 
417
gimp_zoom_preview_draw (GimpPreview *preview)
 
418
{
 
419
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
420
  GimpDrawable           *drawable;
 
421
  guchar                 *data;
 
422
  gint                    width;
 
423
  gint                    height;
 
424
  gint                    bpp;
 
425
 
 
426
  if (! priv->model)
 
427
    return;
 
428
 
 
429
  drawable = priv->drawable;
 
430
  if (! drawable)
 
431
    return;
 
432
 
 
433
  data = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview),
 
434
                                       &width, &height, &bpp);
 
435
 
 
436
  if (data)
 
437
    {
 
438
      gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview->area),
 
439
                              0, 0, width, height,
 
440
                              gimp_drawable_type (drawable->drawable_id),
 
441
                              data, width * bpp);
 
442
      g_free (data);
 
443
    }
 
444
}
 
445
 
 
446
static void
 
447
gimp_zoom_preview_draw_buffer (GimpPreview  *preview,
 
448
                               const guchar *buffer,
 
449
                               gint          rowstride)
 
450
{
 
451
  GimpZoomPreviewPrivate *priv     = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
452
  GimpDrawable           *drawable = priv->drawable;
 
453
  gint32                  image_id;
 
454
 
 
455
  image_id = gimp_drawable_get_image (drawable->drawable_id);
 
456
 
 
457
  if (gimp_selection_is_empty (image_id))
 
458
    {
 
459
      gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview->area),
 
460
                              0, 0,
 
461
                              preview->width, preview->height,
 
462
                              gimp_drawable_type (drawable->drawable_id),
 
463
                              buffer,
 
464
                              rowstride);
 
465
    }
 
466
  else
 
467
    {
 
468
      guchar  *sel;
 
469
      guchar  *src;
 
470
      gint     selection_id;
 
471
      gint     width, height;
 
472
      gint     bpp;
 
473
      gint     src_x;
 
474
      gint     src_y;
 
475
      gint     src_width;
 
476
      gint     src_height;
 
477
 
 
478
      selection_id = gimp_image_get_selection (image_id);
 
479
 
 
480
      width  = preview->width;
 
481
      height = preview->height;
 
482
 
 
483
      gimp_zoom_preview_get_source_area (preview,
 
484
                                         &src_x, &src_y,
 
485
                                         &src_width, &src_height);
 
486
 
 
487
      src = gimp_drawable_get_sub_thumbnail_data (drawable->drawable_id,
 
488
                                                  src_x, src_y,
 
489
                                                  src_width, src_height,
 
490
                                                  &width, &height, &bpp);
 
491
      sel = gimp_drawable_get_sub_thumbnail_data (selection_id,
 
492
                                                  src_x, src_y,
 
493
                                                  src_width, src_height,
 
494
                                                  &width, &height, &bpp);
 
495
 
 
496
      gimp_preview_area_mask (GIMP_PREVIEW_AREA (preview->area),
 
497
                              0, 0, preview->width, preview->height,
 
498
                              gimp_drawable_type (drawable->drawable_id),
 
499
                              src, width * drawable->bpp,
 
500
                              buffer, rowstride,
 
501
                              sel, width);
 
502
 
 
503
      g_free (sel);
 
504
      g_free (src);
 
505
    }
 
506
 
 
507
}
 
508
 
 
509
static void
 
510
gimp_zoom_preview_draw_thumb (GimpPreview     *preview,
 
511
                              GimpPreviewArea *area,
 
512
                              gint             width,
 
513
                              gint             height)
 
514
{
 
515
  GimpZoomPreviewPrivate *priv     = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
516
  GimpDrawable           *drawable = priv->drawable;
 
517
 
 
518
  if (drawable)
 
519
    _gimp_drawable_preview_area_draw_thumb (area, drawable, width, height);
 
520
}
 
521
 
 
522
static void
 
523
gimp_zoom_preview_set_cursor (GimpPreview *preview)
 
524
{
 
525
  if (! GTK_WIDGET_REALIZED (preview->area))
 
526
    return;
 
527
 
 
528
  if (gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview)) > 1.0)
 
529
    {
 
530
      gdk_window_set_cursor (preview->area->window,
 
531
                             GIMP_SCROLLED_PREVIEW (preview)->cursor_move);
 
532
    }
 
533
  else
 
534
    {
 
535
      gdk_window_set_cursor (preview->area->window, preview->default_cursor);
 
536
    }
 
537
}
 
538
 
 
539
static void
 
540
gimp_zoom_preview_transform (GimpPreview *preview,
 
541
                             gint         src_x,
 
542
                             gint         src_y,
 
543
                             gint        *dest_x,
 
544
                             gint        *dest_y)
 
545
{
 
546
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
547
 
 
548
  gdouble zoom = gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview));
 
549
 
 
550
  *dest_x = ((gdouble) (src_x - priv->extents.x) *
 
551
             preview->width / priv->extents.width * zoom) - preview->xoff;
 
552
 
 
553
  *dest_y = ((gdouble) (src_y - priv->extents.y) *
 
554
             preview->height / priv->extents.height * zoom) - preview->yoff;
 
555
}
 
556
 
 
557
static void
 
558
gimp_zoom_preview_untransform (GimpPreview *preview,
 
559
                               gint         src_x,
 
560
                               gint         src_y,
 
561
                               gint        *dest_x,
 
562
                               gint        *dest_y)
 
563
{
 
564
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
565
 
 
566
  gdouble zoom = gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview));
 
567
 
 
568
  *dest_x = (priv->extents.x +
 
569
             ((gdouble) (src_x + preview->xoff) *
 
570
              priv->extents.width / preview->width / zoom));
 
571
 
 
572
  *dest_y = (priv->extents.y +
 
573
             ((gdouble) (src_y + preview->yoff) *
 
574
              priv->extents.height / preview->height / zoom));
 
575
}
 
576
 
 
577
static void
 
578
gimp_zoom_preview_set_drawable (GimpZoomPreview *preview,
 
579
                                GimpDrawable    *drawable)
 
580
{
 
581
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
582
  gint                    width, height;
 
583
  gint                    max_width, max_height;
 
584
  gint                    x1, y1;
 
585
  gint                    x2, y2;
 
586
 
 
587
  g_return_if_fail (priv->drawable == NULL);
 
588
 
 
589
  priv->drawable = drawable;
 
590
 
 
591
  if (_gimp_drawable_preview_get_bounds (drawable, &x1, &y1, &x2, &y2))
 
592
    {
 
593
      width  = x2 - x1;
 
594
      height = y2 - y1;
 
595
 
 
596
      priv->extents.x = x1;
 
597
      priv->extents.y = y1;
 
598
    }
 
599
  else
 
600
    {
 
601
      width  = gimp_drawable_width  (drawable->drawable_id);
 
602
      height = gimp_drawable_height (drawable->drawable_id);
 
603
 
 
604
      priv->extents.x = 0;
 
605
      priv->extents.y = 0;
 
606
    }
 
607
 
 
608
  priv->extents.width  = width;
 
609
  priv->extents.height = height;
 
610
 
 
611
  if (width > height)
 
612
    {
 
613
      max_width  = MIN (width, 512);
 
614
      max_height = (height * max_width) / width;
 
615
    }
 
616
  else
 
617
    {
 
618
      max_height = MIN (height, 512);
 
619
      max_width  = (width * max_height) / height;
 
620
    }
 
621
 
 
622
  gimp_preview_set_bounds (GIMP_PREVIEW (preview),
 
623
                           0, 0, max_width, max_height);
 
624
 
 
625
  g_object_set (GIMP_PREVIEW (preview)->frame,
 
626
                "ratio", (gdouble) width / (gdouble) height,
 
627
                NULL);
 
628
}
 
629
 
 
630
static void
 
631
gimp_zoom_preview_set_model (GimpZoomPreview *preview,
 
632
                             GimpZoomModel   *model)
 
633
{
 
634
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
635
  GtkWidget              *button_bar;
 
636
  GtkWidget              *button;
 
637
  GtkWidget              *box;
 
638
 
 
639
  g_return_if_fail (priv->model == NULL);
 
640
 
 
641
  if (! model)
 
642
    return;
 
643
 
 
644
  priv->model = g_object_ref (model);
 
645
 
 
646
  g_signal_connect_swapped (priv->model, "zoomed",
 
647
                            G_CALLBACK (gimp_zoom_preview_set_adjustments),
 
648
                            preview);
 
649
 
 
650
  box = gimp_preview_get_controls (GIMP_PREVIEW (preview));
 
651
  g_return_if_fail (GTK_IS_BOX (box));
 
652
 
 
653
  button_bar = gtk_hbox_new (FALSE, 2);
 
654
  gtk_box_pack_end (GTK_BOX (box), button_bar, FALSE, FALSE, 0);
 
655
  gtk_widget_show (button_bar);
 
656
 
 
657
  /* zoom out */
 
658
  button = gimp_zoom_button_new (priv->model,
 
659
                                 GIMP_ZOOM_OUT, GTK_ICON_SIZE_SMALL_TOOLBAR);
 
660
  gtk_box_pack_start (GTK_BOX (button_bar), button, FALSE, FALSE, 0);
 
661
  gtk_widget_show (button);
 
662
 
 
663
  /* zoom in */
 
664
  button = gimp_zoom_button_new (priv->model,
 
665
                                 GIMP_ZOOM_IN, GTK_ICON_SIZE_SMALL_TOOLBAR);
 
666
  gtk_box_pack_start (GTK_BOX (button_bar), button, FALSE, FALSE, 0);
 
667
  gtk_widget_show (button);
 
668
}
 
669
 
 
670
static void
 
671
gimp_zoom_preview_get_source_area (GimpPreview *preview,
 
672
                                   gint        *x,
 
673
                                   gint        *y,
 
674
                                   gint        *w,
 
675
                                   gint        *h)
 
676
{
 
677
  GimpZoomPreviewPrivate *priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
678
  gdouble                 zoom = gimp_zoom_model_get_factor (priv->model);
 
679
 
 
680
  gimp_zoom_preview_untransform (preview, 0, 0, x, y);
 
681
 
 
682
  *w = priv->extents.width / zoom;
 
683
  *h = priv->extents.height / zoom;
 
684
}
 
685
 
 
686
 
 
687
/**
 
688
 * gimp_zoom_preview_new:
 
689
 * @drawable: a #GimpDrawable
 
690
 *
 
691
 * Creates a new #GimpZoomPreview widget for @drawable.
 
692
 *
 
693
 * Since: GIMP 2.4
 
694
 **/
 
695
GtkWidget *
 
696
gimp_zoom_preview_new (GimpDrawable *drawable)
 
697
{
 
698
  g_return_val_if_fail (drawable != NULL, NULL);
 
699
 
 
700
  return g_object_new (GIMP_TYPE_ZOOM_PREVIEW,
 
701
                       "drawable", drawable,
 
702
                       NULL);
 
703
}
 
704
 
 
705
/**
 
706
 * gimp_zoom_preview_new_with_model:
 
707
 * @drawable: a #GimpDrawable
 
708
 * @model:    a #GimpZoomModel
 
709
 *
 
710
 * Creates a new #GimpZoomPreview widget for @drawable using the
 
711
 * given @model.
 
712
 *
 
713
 * This variant of gimp_zoom_preview_new() allows you to create a
 
714
 * preview using an existing zoom model. This may be useful if for
 
715
 * example you want to have two zoom previews that keep their zoom
 
716
 * factor in sync.
 
717
 *
 
718
 * Since: GIMP 2.4
 
719
 **/
 
720
GtkWidget *
 
721
gimp_zoom_preview_new_with_model (GimpDrawable  *drawable,
 
722
                                  GimpZoomModel *model)
 
723
 
 
724
{
 
725
  g_return_val_if_fail (drawable != NULL, NULL);
 
726
  g_return_val_if_fail (GIMP_IS_ZOOM_MODEL (model), NULL);
 
727
 
 
728
  return g_object_new (GIMP_TYPE_ZOOM_PREVIEW,
 
729
                       "drawable", drawable,
 
730
                       "model",    model,
 
731
                       NULL);
 
732
}
 
733
 
 
734
 
 
735
/**
 
736
 * gimp_zoom_preview_get_drawable:
 
737
 * @preview: a #GimpZoomPreview widget
 
738
 *
 
739
 * Returns the #GimpDrawable the #GimpZoomPreview is attached to.
 
740
 *
 
741
 * Return Value: the #GimpDrawable that was passed to gimp_zoom_preview_new().
 
742
 *
 
743
 * Since: GIMP 2.4
 
744
 **/
 
745
GimpDrawable *
 
746
gimp_zoom_preview_get_drawable (GimpZoomPreview *preview)
 
747
{
 
748
  g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), NULL);
 
749
 
 
750
  return GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview)->drawable;
 
751
}
 
752
 
 
753
/**
 
754
 * gimp_zoom_preview_get_model:
 
755
 * @preview: a #GimpZoomPreview widget
 
756
 *
 
757
 * Returns the #GimpZoomModel the preview is using.
 
758
 *
 
759
 * Return Value: a pointer to the #GimpZoomModel owned by the @preview
 
760
 *
 
761
 * Since: GIMP 2.4
 
762
 **/
 
763
GimpZoomModel *
 
764
gimp_zoom_preview_get_model (GimpZoomPreview *preview)
 
765
{
 
766
  g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), NULL);
 
767
 
 
768
  return GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview)->model;
 
769
}
 
770
 
 
771
/**
 
772
 * gimp_zoom_preview_get_factor:
 
773
 * @preview: a #GimpZoomPreview widget
 
774
 *
 
775
 * Returns the zoom factor the preview is currently using.
 
776
 *
 
777
 * Return Value: the current zoom factor
 
778
 *
 
779
 * Since: GIMP 2.4
 
780
 **/
 
781
gdouble
 
782
gimp_zoom_preview_get_factor (GimpZoomPreview *preview)
 
783
{
 
784
  GimpZoomPreviewPrivate *priv;
 
785
 
 
786
  g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), 1.0);
 
787
 
 
788
  priv = GIMP_ZOOM_PREVIEW_GET_PRIVATE (preview);
 
789
 
 
790
  return priv->model ? gimp_zoom_model_get_factor (priv->model) : 1.0;
 
791
}
 
792
 
 
793
/**
 
794
 * gimp_zoom_preview_get_source:
 
795
 * @preview: a #GimpZoomPreview widget
 
796
 * @width: a pointer to an int where the current width of the zoom widget
 
797
 *         will be put.
 
798
 * @height: a pointer to an int where the current width of the zoom widget
 
799
 *          will be put.
 
800
 * @bpp: return location for the number of bytes per pixel
 
801
 *
 
802
 * Returns the scaled image data of the part of the drawable the
 
803
 * #GimpZoomPreview is currently showing, as a newly allocated array of guchar.
 
804
 * This function also allow to get the current width, height and bpp of the
 
805
 * #GimpZoomPreview.
 
806
 *
 
807
 * Return Value: newly allocated data that should be released using g_free()
 
808
 *               when it is not any longer needed
 
809
 *
 
810
 * Since: GIMP 2.4
 
811
 */
 
812
guchar *
 
813
gimp_zoom_preview_get_source (GimpZoomPreview *preview,
 
814
                              gint            *width,
 
815
                              gint            *height,
 
816
                              gint            *bpp)
 
817
{
 
818
  GimpDrawable *drawable;
 
819
 
 
820
  g_return_val_if_fail (GIMP_IS_ZOOM_PREVIEW (preview), NULL);
 
821
  g_return_val_if_fail (width != NULL && height != NULL && bpp != NULL, NULL);
 
822
 
 
823
  drawable = gimp_zoom_preview_get_drawable (preview);
 
824
 
 
825
  if (drawable)
 
826
    {
 
827
      GimpPreview *gimp_preview = GIMP_PREVIEW (preview);
 
828
      gint         src_x;
 
829
      gint         src_y;
 
830
      gint         src_width;
 
831
      gint         src_height;
 
832
 
 
833
      *width  = gimp_preview->width;
 
834
      *height = gimp_preview->height;
 
835
 
 
836
      gimp_zoom_preview_get_source_area (gimp_preview,
 
837
                                         &src_x, &src_y,
 
838
                                         &src_width, &src_height);
 
839
 
 
840
      return gimp_drawable_get_sub_thumbnail_data (drawable->drawable_id,
 
841
                                                   src_x, src_y,
 
842
                                                   src_width, src_height,
 
843
                                                   width, height, bpp);
 
844
    }
 
845
  else
 
846
    {
 
847
      *width  = 0;
 
848
      *height = 0;
 
849
      *bpp    = 0;
 
850
 
 
851
      return NULL;
 
852
    }
 
853
}