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

1.1.4 by Daniel Holbach
Import upstream version 2.3.16
1
/* GIMP - The GNU Image Manipulation Program
1 by Daniel Holbach
Import upstream version 2.2.9
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
 */
18
19
#include "config.h"
20
21
#include <gtk/gtk.h>
22
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
23
#include "libgimpmath/gimpmath.h"
1 by Daniel Holbach
Import upstream version 2.2.9
24
25
#include "display-types.h"
26
27
#include "config/gimpdisplayconfig.h"
28
29
#include "core/gimp.h"
30
#include "core/gimpimage.h"
31
#include "core/gimpunit.h"
32
33
#include "gimpdisplay.h"
34
#include "gimpdisplayshell.h"
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
35
#include "gimpdisplayshell-draw.h"
1 by Daniel Holbach
Import upstream version 2.2.9
36
#include "gimpdisplayshell-scale.h"
37
#include "gimpdisplayshell-scroll.h"
38
#include "gimpdisplayshell-title.h"
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
39
#include "gimpdisplayshell-transform.h"
40
41
42
#define SCALE_TIMEOUT             2
43
#define SCALE_EPSILON             0.0001
44
#define ALMOST_CENTERED_THRESHOLD 2
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
45
46
#define SCALE_EQUALS(a,b) (fabs ((a) - (b)) < SCALE_EPSILON)
47
48
1 by Daniel Holbach
Import upstream version 2.2.9
49
/*  local function prototypes  */
50
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
51
static void      gimp_display_shell_scale_to             (GimpDisplayShell *shell,
52
                                                          gdouble           scale,
53
                                                          gint              viewport_x,
54
                                                          gint              viewport_y);
55
56
static gboolean  gimp_display_shell_scale_image_starts_to_fit
57
                                                         (GimpDisplayShell *shell,
58
                                                          gdouble           new_scale,
59
                                                          gdouble           current_scale,
60
                                                          gboolean         *vertically,
61
                                                          gboolean         *horizontally);
62
static void      gimp_display_shell_scale_viewport_coord_almost_centered
63
                                                         (GimpDisplayShell *shell,
64
                                                          gint              x,
65
                                                          gint              y,
66
                                                          gboolean         *horizontally,
67
                                                          gboolean         *vertically);
68
69
static void      gimp_display_shell_scale_get_zoom_focus (GimpDisplayShell *shell,
70
                                                          gdouble           new_scale,
71
                                                          gdouble           current_scale,
72
                                                          gint             *x,
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
73
                                                          gint             *y,
74
                                                          GimpZoomFocus     zoom_focus);
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
75
76
static gdouble   img2real                                (GimpDisplayShell *shell,
77
                                                          gboolean          xdir,
78
                                                          gdouble           a);
1 by Daniel Holbach
Import upstream version 2.2.9
79
80
81
/*  public functions  */
82
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
83
/**
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
84
 * gimp_display_shell_update_scrollbars_and_rulers:
85
 * @shell: the #GimpDisplayShell
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
86
 *
87
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
88
void
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
89
gimp_display_shell_update_scrollbars_and_rulers (GimpDisplayShell *shell)
1 by Daniel Holbach
Import upstream version 2.2.9
90
{
91
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
92
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
93
  gimp_display_shell_scale_update_scrollbars (shell);
94
  gimp_display_shell_scale_update_rulers (shell);
95
}
96
97
/**
98
 * gimp_display_shell_scale_update_scrollbars:
99
 * @shell:
100
 *
101
 **/
102
void
103
gimp_display_shell_scale_update_scrollbars (GimpDisplayShell *shell)
104
{
105
  GimpImage *image;
106
  gint       image_width;
107
  gint       image_height;
108
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
109
  if (! shell->display)
110
    return;
111
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
112
  image = shell->display->image;
113
114
  if (image)
115
    {
116
      image_width  = gimp_image_get_width  (image);
117
      image_height = gimp_image_get_height (image);
118
    }
119
  else
120
    {
121
      image_width  = shell->disp_width;
122
      image_height = shell->disp_height;
123
    }
124
125
126
  /* Horizontal scrollbar */
1 by Daniel Holbach
Import upstream version 2.2.9
127
128
  shell->hsbdata->value          = shell->offset_x;
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
129
  shell->hsbdata->page_size      = shell->disp_width;
1 by Daniel Holbach
Import upstream version 2.2.9
130
  shell->hsbdata->page_increment = shell->disp_width / 2;
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
131
132
  gimp_display_shell_scroll_setup_hscrollbar (shell, shell->offset_x);
133
134
  gtk_adjustment_changed (shell->hsbdata);
135
136
137
  /* Vertcal scrollbar */
1 by Daniel Holbach
Import upstream version 2.2.9
138
139
  shell->vsbdata->value          = shell->offset_y;
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
140
  shell->vsbdata->page_size      = shell->disp_height;
1 by Daniel Holbach
Import upstream version 2.2.9
141
  shell->vsbdata->page_increment = shell->disp_height / 2;
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
142
143
  gimp_display_shell_scroll_setup_vscrollbar (shell, shell->offset_y);
144
1 by Daniel Holbach
Import upstream version 2.2.9
145
  gtk_adjustment_changed (shell->vsbdata);
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
146
}
147
148
/**
149
 * gimp_display_shell_scale_update_rulers:
150
 * @shell:
151
 *
152
 **/
153
void
154
gimp_display_shell_scale_update_rulers (GimpDisplayShell *shell)
155
{
156
  GimpImage *image;
157
  gint       image_width;
158
  gint       image_height;
159
  gdouble    horizontal_lower;
160
  gdouble    horizontal_upper;
161
  gdouble    horizontal_max_size;
162
  gdouble    vertical_lower;
163
  gdouble    vertical_upper;
164
  gdouble    vertical_max_size;
165
  gint       scaled_viewport_offset_x;
166
  gint       scaled_viewport_offset_y;
167
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
168
  if (! shell->display)
169
    return;
170
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
171
  image = shell->display->image;
172
173
  if (image)
174
    {
175
      image_width  = gimp_image_get_width  (image);
176
      image_height = gimp_image_get_height (image);
177
    }
178
  else
179
    {
180
      image_width  = shell->disp_width;
181
      image_height = shell->disp_height;
182
    }
183
184
185
  /* Initialize values */
186
187
  horizontal_lower = 0;
188
  vertical_lower   = 0;
189
190
  if (image)
191
    {
192
      horizontal_upper    = img2real (shell, TRUE,
193
                                      FUNSCALEX (shell, shell->disp_width));
194
      horizontal_max_size = img2real (shell, TRUE,
195
                                      MAX (image_width, image_height));
196
197
      vertical_upper      = img2real (shell, FALSE,
198
                                      FUNSCALEY (shell, shell->disp_height));
199
      vertical_max_size   = img2real (shell, FALSE,
200
                                      MAX (image_width, image_height));
201
    }
202
  else
203
    {
204
      horizontal_upper    = image_width;
205
      horizontal_max_size = MAX (image_width, image_height);
206
207
      vertical_upper      = image_height;
208
      vertical_max_size   = MAX (image_width, image_height);
209
    }
210
211
212
  /* Adjust due to scrolling */
213
214
  gimp_display_shell_scroll_get_scaled_viewport_offset (shell,
215
                                                        &scaled_viewport_offset_x,
216
                                                        &scaled_viewport_offset_y);
217
218
  horizontal_lower -= img2real (shell, TRUE,
219
                                FUNSCALEX (shell,
220
                                           (gdouble) scaled_viewport_offset_x));
221
  horizontal_upper -= img2real (shell, TRUE,
222
                                FUNSCALEX (shell,
223
                                           (gdouble) scaled_viewport_offset_x));
224
225
  vertical_lower   -= img2real (shell, FALSE,
226
                                FUNSCALEY (shell,
227
                                           (gdouble) scaled_viewport_offset_y));
228
  vertical_upper   -= img2real (shell, FALSE,
229
                                FUNSCALEY (shell,
230
                                           (gdouble) scaled_viewport_offset_y));
231
232
233
  /* Finally setup the actual rulers */
234
235
  gimp_ruler_set_range (GIMP_RULER (shell->hrule),
236
                        horizontal_lower,
237
                        horizontal_upper,
238
                        horizontal_max_size);
239
240
  gimp_ruler_set_unit  (GIMP_RULER (shell->hrule),
241
                        shell->unit);
242
243
  gimp_ruler_set_range (GIMP_RULER (shell->vrule),
244
                        vertical_lower,
245
                        vertical_upper,
246
                        vertical_max_size);
247
248
  gimp_ruler_set_unit  (GIMP_RULER (shell->vrule),
249
                        shell->unit);
1 by Daniel Holbach
Import upstream version 2.2.9
250
}
251
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
252
/**
253
 * gimp_display_shell_scale_revert:
254
 * @shell:     the #GimpDisplayShell
255
 *
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
256
 * Reverts the display to the previously used scale. If no previous
257
 * scale exist, then the call does nothing.
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
258
 *
259
 * Return value: %TRUE if the scale was reverted, otherwise %FALSE.
260
 **/
261
gboolean
262
gimp_display_shell_scale_revert (GimpDisplayShell *shell)
263
{
264
  g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
265
266
  /* don't bother if no scale has been set */
267
  if (shell->last_scale < SCALE_EPSILON)
268
    return FALSE;
269
270
  shell->last_scale_time = 0;
271
272
  gimp_display_shell_scale_by_values (shell,
273
                                      shell->last_scale,
274
                                      shell->last_offset_x,
275
                                      shell->last_offset_y,
276
                                      FALSE);   /* don't resize the window */
277
278
  return TRUE;
279
}
280
281
/**
282
 * gimp_display_shell_scale_can_revert:
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
283
 * @shell: the #GimpDisplayShell
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
284
 *
285
 * Return value: %TRUE if a previous display scale exists, otherwise %FALSE.
286
 **/
287
gboolean
288
gimp_display_shell_scale_can_revert (GimpDisplayShell *shell)
289
{
290
  g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
291
292
  return (shell->last_scale > SCALE_EPSILON);
293
}
294
295
/**
296
 * gimp_display_shell_scale_set_dot_for_dot:
297
 * @shell:        the #GimpDisplayShell
298
 * @dot_for_dot:  whether "Dot for Dot" should be enabled
299
 *
300
 * If @dot_for_dot is set to %TRUE then the "Dot for Dot" mode (where image and
301
 * screen pixels are of the same size) is activated. Dually, the mode is
302
 * disabled if @dot_for_dot is %FALSE.
303
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
304
void
305
gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *shell,
306
                                          gboolean          dot_for_dot)
307
{
308
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
309
310
  if (dot_for_dot != shell->dot_for_dot)
311
    {
312
      /* freeze the active tool */
313
      gimp_display_shell_pause (shell);
314
315
      shell->dot_for_dot = dot_for_dot;
316
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
317
      gimp_display_shell_scale_changed (shell);
318
1 by Daniel Holbach
Import upstream version 2.2.9
319
      gimp_display_shell_scale_resize (shell,
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
320
                                       shell->display->config->resize_windows_on_zoom,
321
                                       FALSE);
1 by Daniel Holbach
Import upstream version 2.2.9
322
323
      /* re-enable the active tool */
324
      gimp_display_shell_resume (shell);
325
    }
326
}
327
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
328
/**
329
 * gimp_display_shell_scale:
330
 * @shell:     the #GimpDisplayShell
331
 * @zoom_type: whether to zoom in, our or to a specific scale
332
 * @scale:     ignored unless @zoom_type == %GIMP_ZOOM_TO
333
 *
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
334
 * This function figures out the context of the zoom and behaves
335
 * appropriatley thereafter.
336
 *
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
337
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
338
void
339
gimp_display_shell_scale (GimpDisplayShell *shell,
340
                          GimpZoomType      zoom_type,
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
341
                          gdouble           new_scale,
342
                          GimpZoomFocus     zoom_focus)
1 by Daniel Holbach
Import upstream version 2.2.9
343
{
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
344
  gint    x, y;
345
  gdouble current_scale;
346
  gdouble real_new_scale;
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
347
348
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
349
  g_return_if_fail (shell->canvas != NULL);
350
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
351
  current_scale = gimp_zoom_model_get_factor (shell->zoom);
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
352
353
  if (zoom_type != GIMP_ZOOM_TO)
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
354
    {
355
      real_new_scale = gimp_zoom_model_zoom_step (zoom_type, current_scale);
356
    }
357
  else
358
    {
359
      real_new_scale = new_scale;
360
    }
361
362
  if (! SCALE_EQUALS (real_new_scale, current_scale))
363
    {
364
      if (shell->display->config->resize_windows_on_zoom)
365
        {
366
          /* If the window is resized on zoom, simply do the zoom and
367
           * get things rolling
368
           */
369
          gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, real_new_scale);
370
          gimp_display_shell_shrink_wrap (shell, FALSE);
371
        }
372
      else
373
        {
374
          gboolean starts_fitting_horizontally;
375
          gboolean starts_fitting_vertically;
376
          gboolean almost_centered_horizontally;
377
          gboolean almost_centered_vertically;
378
379
          gimp_display_shell_scale_get_zoom_focus (shell,
380
                                                   real_new_scale,
381
                                                   current_scale,
382
                                                   &x,
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
383
                                                   &y,
384
                                                   zoom_focus);
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
385
386
          gimp_display_shell_scale_to (shell, real_new_scale, x, y);
387
388
389
          /* If an image axis started to fit due to zooming out or if
390
           * the focus point is as good as in the center, center on
391
           * that axis
392
           */
393
          gimp_display_shell_scale_image_starts_to_fit (shell,
394
                                                        real_new_scale,
395
                                                        current_scale,
396
                                                        &starts_fitting_horizontally,
397
                                                        &starts_fitting_vertically);
398
          gimp_display_shell_scale_viewport_coord_almost_centered (shell,
399
                                                                   x,
400
                                                                   y,
401
                                                                   &almost_centered_horizontally,
402
                                                                   &almost_centered_vertically);
403
          gimp_display_shell_scroll_center_image (shell,
404
                                                  starts_fitting_horizontally ||
405
                                                  almost_centered_horizontally,
406
                                                  starts_fitting_vertically ||
407
                                                  almost_centered_vertically);
408
        }
409
    }
1 by Daniel Holbach
Import upstream version 2.2.9
410
}
411
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
412
/**
413
 * gimp_display_shell_scale_fit_in:
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
414
 * @shell: the #GimpDisplayShell
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
415
 *
416
 * Sets the scale such that the entire image precisely fits in the display
417
 * area.
418
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
419
void
420
gimp_display_shell_scale_fit_in (GimpDisplayShell *shell)
421
{
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
422
  GimpImage *image;
1 by Daniel Holbach
Import upstream version 2.2.9
423
  gint       image_width;
424
  gint       image_height;
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
425
  gdouble    xres;
426
  gdouble    yres;
1 by Daniel Holbach
Import upstream version 2.2.9
427
  gdouble    zoom_factor;
428
429
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
430
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
431
  image = shell->display->image;
1 by Daniel Holbach
Import upstream version 2.2.9
432
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
433
  image_width  = gimp_image_get_width  (image);
434
  image_height = gimp_image_get_height (image);
435
436
  gimp_image_get_resolution (image, &xres, &yres);
1 by Daniel Holbach
Import upstream version 2.2.9
437
438
  if (! shell->dot_for_dot)
439
    {
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
440
      image_width  = ROUND (image_width  * shell->monitor_xres / xres);
441
      image_height = ROUND (image_height * shell->monitor_yres / yres);
1 by Daniel Holbach
Import upstream version 2.2.9
442
    }
443
444
  zoom_factor = MIN ((gdouble) shell->disp_width  / (gdouble) image_width,
445
                     (gdouble) shell->disp_height / (gdouble) image_height);
446
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
447
  gimp_display_shell_scale (shell,
448
                            GIMP_ZOOM_TO,
449
                            zoom_factor,
450
                            GIMP_ZOOM_FOCUS_BEST_GUESS);
451
  
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
452
  gimp_display_shell_scroll_center_image (shell, TRUE, TRUE);
453
}
454
455
/**
456
 * gimp_display_shell_scale_image_is_within_viewport:
457
 * @shell:
458
 *
459
 * Returns: %TRUE if the (scaled) image is smaller than and within the
460
 *          viewport.
461
 **/
462
gboolean
463
gimp_display_shell_scale_image_is_within_viewport (GimpDisplayShell *shell,
464
                                                   gboolean         *horizontally,
465
                                                   gboolean         *vertically)
466
{
467
  gint     sw, sh;
468
  gboolean horizontally_dummy, vertically_dummy;
469
470
  g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
471
472
  if (! horizontally) horizontally = &horizontally_dummy;
473
  if (! vertically)   vertically   = &vertically_dummy;
474
475
  gimp_display_shell_draw_get_scaled_image_size (shell, &sw, &sh);
476
477
  *horizontally = sw              <= shell->disp_width       &&
478
                  shell->offset_x <= 0                       &&
479
                  shell->offset_x >= sw - shell->disp_width;
480
481
  *vertically   = sh              <= shell->disp_height      &&
482
                  shell->offset_y <= 0                       &&
483
                  shell->offset_y >= sh - shell->disp_height;
484
485
  return *vertically && *horizontally;
486
}
487
488
/**
489
 * gimp_display_shell_scale_fill:
490
 * @shell: the #GimpDisplayShell
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
491
 *
492
 * Sets the scale such that the entire display area is precisely filled by the
493
 * image.
494
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
495
void
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
496
gimp_display_shell_scale_fill (GimpDisplayShell *shell)
1 by Daniel Holbach
Import upstream version 2.2.9
497
{
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
498
  GimpImage *image;
1 by Daniel Holbach
Import upstream version 2.2.9
499
  gint       image_width;
500
  gint       image_height;
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
501
  gdouble    xres;
502
  gdouble    yres;
1 by Daniel Holbach
Import upstream version 2.2.9
503
  gdouble    zoom_factor;
504
505
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
506
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
507
  image = shell->display->image;
1 by Daniel Holbach
Import upstream version 2.2.9
508
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
509
  image_width  = gimp_image_get_width  (image);
510
  image_height = gimp_image_get_height (image);
511
512
  gimp_image_get_resolution (image, &xres, &yres);
1 by Daniel Holbach
Import upstream version 2.2.9
513
514
  if (! shell->dot_for_dot)
515
    {
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
516
      image_width  = ROUND (image_width  * shell->monitor_xres / xres);
517
      image_height = ROUND (image_height * shell->monitor_yres / yres);
1 by Daniel Holbach
Import upstream version 2.2.9
518
    }
519
520
  zoom_factor = MAX ((gdouble) shell->disp_width  / (gdouble) image_width,
521
                     (gdouble) shell->disp_height / (gdouble) image_height);
522
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
523
  gimp_display_shell_scale (shell,
524
                            GIMP_ZOOM_TO,
525
                            zoom_factor,
526
                            GIMP_ZOOM_FOCUS_BEST_GUESS);
527
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
528
  gimp_display_shell_scroll_center_image (shell, TRUE, TRUE);
529
}
530
531
/**
532
 * gimp_display_shell_scale_handle_zoom_revert:
533
 * @shell:
534
 *
535
 * Handle the updating of the Revert Zoom variables.
536
 **/
537
void
538
gimp_display_shell_scale_handle_zoom_revert (GimpDisplayShell *shell)
539
{
540
  guint now;
541
542
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
543
544
  now = time (NULL);
545
546
  if (now - shell->last_scale_time >= SCALE_TIMEOUT)
547
    {
548
      shell->last_scale    = gimp_zoom_model_get_factor (shell->zoom);
549
      shell->last_offset_x = shell->offset_x;
550
      shell->last_offset_y = shell->offset_y;
551
    }
552
553
  shell->last_scale_time = now;
1 by Daniel Holbach
Import upstream version 2.2.9
554
}
555
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
556
/**
557
 * gimp_display_shell_scale_by_values:
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
558
 * @shell:         the #GimpDisplayShell
559
 * @scale:         the new scale
560
 * @offset_x:      the new X offset
561
 * @offset_y:      the new Y offset
562
 * @resize_window: whether the display window should be resized
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
563
 *
564
 * Directly sets the image scale and image offsets used by the display. If
565
 * @resize_window is %TRUE then the display window is resized to better
566
 * accomodate the image, see gimp_display_shell_shrink_wrap().
567
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
568
void
569
gimp_display_shell_scale_by_values (GimpDisplayShell *shell,
570
                                    gdouble           scale,
571
                                    gint              offset_x,
572
                                    gint              offset_y,
573
                                    gboolean          resize_window)
574
{
575
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
576
577
  /*  Abort early if the values are all setup already. We don't
578
   *  want to inadvertently resize the window (bug #164281).
579
   */
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
580
  if (SCALE_EQUALS (gimp_zoom_model_get_factor (shell->zoom), scale) &&
1 by Daniel Holbach
Import upstream version 2.2.9
581
      shell->offset_x == offset_x &&
582
      shell->offset_y == offset_y)
583
    return;
584
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
585
  gimp_display_shell_scale_handle_zoom_revert (shell);
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
586
1 by Daniel Holbach
Import upstream version 2.2.9
587
  /* freeze the active tool */
588
  gimp_display_shell_pause (shell);
589
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
590
  gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, scale);
591
1 by Daniel Holbach
Import upstream version 2.2.9
592
  shell->offset_x = offset_x;
593
  shell->offset_y = offset_y;
594
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
595
  gimp_display_shell_scale_resize (shell, resize_window, FALSE);
1 by Daniel Holbach
Import upstream version 2.2.9
596
597
  /* re-enable the active tool */
598
  gimp_display_shell_resume (shell);
599
}
600
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
601
/**
602
 * gimp_display_shell_scale_shrink_wrap:
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
603
 * @shell: the #GimpDisplayShell
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
604
 *
605
 * Convenience function with the same functionality as
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
606
 * gimp_display_shell_scale_resize(@shell, TRUE, grow_only).
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
607
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
608
void
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
609
gimp_display_shell_scale_shrink_wrap (GimpDisplayShell *shell,
610
                                      gboolean          grow_only)
1 by Daniel Holbach
Import upstream version 2.2.9
611
{
612
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
613
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
614
  gimp_display_shell_scale_resize (shell, TRUE, grow_only);
1 by Daniel Holbach
Import upstream version 2.2.9
615
}
616
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
617
/**
618
 * gimp_display_shell_scale_resize:
619
 * @shell:          the #GimpDisplayShell
620
 * @resize_window:  whether the display window should be resized
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
621
 * @grow_only:      whether shrinking of the window is allowed or not
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
622
 *
623
 * Function commonly called after a change in display scale to make the changes
624
 * visible to the user. If @resize_window is %TRUE then the display window is
625
 * resized to accomodate the display image as per
626
 * gimp_display_shell_shrink_wrap().
627
 **/
1 by Daniel Holbach
Import upstream version 2.2.9
628
void
629
gimp_display_shell_scale_resize (GimpDisplayShell *shell,
630
                                 gboolean          resize_window,
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
631
                                 gboolean          grow_only)
1 by Daniel Holbach
Import upstream version 2.2.9
632
{
633
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
634
635
  /* freeze the active tool */
636
  gimp_display_shell_pause (shell);
637
638
  if (resize_window)
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
639
    gimp_display_shell_shrink_wrap (shell, grow_only);
1 by Daniel Holbach
Import upstream version 2.2.9
640
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
641
  gimp_display_shell_scroll_clamp_and_update (shell);
1 by Daniel Holbach
Import upstream version 2.2.9
642
  gimp_display_shell_scaled (shell);
643
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
644
  gimp_display_shell_expose_full (shell);
1 by Daniel Holbach
Import upstream version 2.2.9
645
646
  /* re-enable the active tool */
647
  gimp_display_shell_resume (shell);
648
}
649
1.1.4 by Daniel Holbach
Import upstream version 2.3.16
650
/**
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
651
 * gimp_display_shell_calculate_scale_x_and_y:
652
 * @shell:
653
 * @scale:
654
 * @scale_x:
655
 * @scale_y:
656
 *
657
 **/
658
void
659
gimp_display_shell_calculate_scale_x_and_y (const GimpDisplayShell *shell,
660
                                            gdouble                 scale,
661
                                            gdouble                *scale_x,
662
                                            gdouble                *scale_y)
663
{
664
  gdouble xres;
665
  gdouble yres;
666
667
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
668
  g_return_if_fail (GIMP_IS_IMAGE (shell->display->image));
669
670
  gimp_image_get_resolution (shell->display->image, &xres, &yres);
671
672
  if (scale_x) *scale_x = scale * SCREEN_XRES (shell) / xres;
673
  if (scale_y) *scale_y = scale * SCREEN_YRES (shell) / yres;
674
}
675
676
void
677
gimp_display_shell_set_initial_scale (GimpDisplayShell *shell,
678
                                      gdouble           scale,
679
                                      gint             *display_width,
680
                                      gint             *display_height)
681
{
682
  GdkScreen *screen;
683
  gint       image_width;
684
  gint       image_height;
685
  gint       shell_width;
686
  gint       shell_height;
687
  gint       screen_width;
688
  gint       screen_height;
689
690
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
691
692
  screen = gtk_widget_get_screen (GTK_WIDGET (shell));
693
694
  image_width  = gimp_image_get_width  (shell->display->image);
695
  image_height = gimp_image_get_height (shell->display->image);
696
697
  screen_width  = gdk_screen_get_width (screen)  * 0.75;
698
  screen_height = gdk_screen_get_height (screen) * 0.75;
699
700
  /* We need to zoom before we use SCALE[XY] */
701
  gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, scale);
702
703
  shell_width  = SCALEX (shell, image_width);
704
  shell_height = SCALEY (shell, image_height);
705
706
  if (shell->display->config->initial_zoom_to_fit)
707
    {
708
      /*  Limit to the size of the screen...  */
709
      if (shell_width > screen_width || shell_height > screen_height)
710
        {
711
          gdouble new_scale;
712
          gdouble current = gimp_zoom_model_get_factor (shell->zoom);
713
714
          new_scale = current * MIN (((gdouble) screen_height) / shell_height,
715
                                     ((gdouble) screen_width)  / shell_width);
716
717
          new_scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, new_scale);
718
719
          /*  Since zooming out might skip a zoom step we zoom in
720
           *  again and test if we are small enough.
721
           */
722
          gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO,
723
                                gimp_zoom_model_zoom_step (GIMP_ZOOM_IN,
724
                                                           new_scale));
725
726
          if (SCALEX (shell, image_width) > screen_width ||
727
              SCALEY (shell, image_height) > screen_height)
728
            gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, new_scale);
729
730
          shell_width  = SCALEX (shell, image_width);
731
          shell_height = SCALEY (shell, image_height);
732
        }
733
    }
734
  else
735
    {
736
      /*  Set up size like above, but do not zoom to fit. Useful when
737
       *  working on large images.
738
       */
739
      if (shell_width > screen_width)
740
        shell_width = screen_width;
741
742
      if (shell_height > screen_height)
743
        shell_height = screen_height;
744
    }
745
746
  if (display_width)
747
    *display_width = shell_width;
748
749
  if (display_height)
750
    *display_height = shell_height;
751
}
752
753
/**
754
 * gimp_display_shell_scale_to:
755
 * @shell:
756
 * @scale:
757
 * @viewport_x:
758
 * @viewport_y:
759
 *
760
 * Zooms. The display offsets are adjusted so that the point specified
761
 * by @x and @y doesn't change it's position on screen.
762
 **/
763
static void
764
gimp_display_shell_scale_to (GimpDisplayShell *shell,
765
                             gdouble           scale,
766
                             gint              viewport_x,
767
                             gint              viewport_y)
768
{
769
  gdouble scale_x, scale_y;
770
  gdouble image_focus_x, image_focus_y;
771
  gint    target_offset_x, target_offset_y;
772
773
  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
774
775
  if (! shell->display)
776
    return;
777
778
  gimp_display_shell_untransform_xy_f (shell,
779
                                       viewport_x,
780
                                       viewport_y,
781
                                       &image_focus_x,
782
                                       &image_focus_y,
783
                                       FALSE);
784
785
  gimp_display_shell_calculate_scale_x_and_y (shell, scale, &scale_x, &scale_y);
786
787
  target_offset_x = scale_x * image_focus_x - viewport_x;
788
  target_offset_y = scale_y * image_focus_y - viewport_y;
789
790
  /* Note that we never come here if we need to
791
   * resize_windows_on_zoom
792
   */
793
  gimp_display_shell_scale_by_values (shell,
794
                                      scale,
795
                                      target_offset_x,
796
                                      target_offset_y,
797
                                      FALSE);
798
}
799
800
static gboolean
801
gimp_display_shell_scale_image_starts_to_fit (GimpDisplayShell *shell,
802
                                              gdouble           new_scale,
803
                                              gdouble           current_scale,
804
                                              gboolean         *vertically,
805
                                              gboolean         *horizontally)
806
{
807
  gboolean vertically_dummy;
808
  gboolean horizontally_dummy;
809
810
  if (! vertically)   vertically   = &vertically_dummy;
811
  if (! horizontally) horizontally = &horizontally_dummy;
812
813
  /* The image can only start to fit if we zoom out */
814
  if (new_scale > current_scale)
815
    {
816
      *vertically   = FALSE;
817
      *horizontally = FALSE;
818
    }
819
  else
820
    {
821
      gint current_scale_width;
822
      gint current_scale_height;
823
      gint new_scale_width;
824
      gint new_scale_height;
825
826
      gimp_display_shell_draw_get_scaled_image_size_for_scale (shell,
827
                                                               current_scale,
828
                                                               &current_scale_width,
829
                                                               &current_scale_height);
830
831
      gimp_display_shell_draw_get_scaled_image_size_for_scale (shell,
832
                                                               new_scale,
833
                                                               &new_scale_width,
834
                                                               &new_scale_height);
835
836
      *vertically   = (current_scale_width  >  shell->disp_width &&
837
                       new_scale_width      <= shell->disp_width);
838
      *horizontally = (current_scale_height >  shell->disp_height &&
839
                       new_scale_height     <= shell->disp_height);
840
    }
841
842
  return *vertically && *horizontally;
843
}
844
845
static gboolean
846
gimp_display_shell_scale_image_stops_to_fit (GimpDisplayShell *shell,
847
                                             gdouble           new_scale,
848
                                             gdouble           current_scale,
849
                                             gboolean         *vertically,
850
                                             gboolean         *horizontally)
851
{
852
  return gimp_display_shell_scale_image_starts_to_fit (shell,
853
                                                       current_scale,
854
                                                       new_scale,
855
                                                       vertically,
856
                                                       horizontally);
857
}
858
859
/**
860
 * gimp_display_shell_scale_viewport_coord_almost_centered:
861
 * @shell:
862
 * @x:
863
 * @y:
864
 * @horizontally:
865
 * @vertically:
866
 *
867
 **/
868
static void
869
gimp_display_shell_scale_viewport_coord_almost_centered (GimpDisplayShell *shell,
870
                                                         gint              x,
871
                                                         gint              y,
872
                                                         gboolean         *horizontally,
873
                                                         gboolean         *vertically)
874
{
875
  gint center_x = shell->disp_width  / 2;
876
  gint center_y = shell->disp_height / 2;
877
878
  *horizontally = x > center_x - ALMOST_CENTERED_THRESHOLD &&
879
                  x < center_x + ALMOST_CENTERED_THRESHOLD;
880
881
  *vertically   = y > center_y - ALMOST_CENTERED_THRESHOLD &&
882
                  y < center_y + ALMOST_CENTERED_THRESHOLD;
883
}
884
885
/**
886
 * gimp_display_shell_scale_get_zoom_focus:
887
 * @shell:
888
 * @new_scale:
889
 * @x:
890
 * @y:
891
 *
892
 * Calculates the viewport coordinate to focus on when zooming
893
 * independently for each axis.
894
 **/
895
static void
896
gimp_display_shell_scale_get_zoom_focus (GimpDisplayShell *shell,
897
                                         gdouble           new_scale,
898
                                         gdouble           current_scale,
899
                                         gint             *x,
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
900
                                         gint             *y,
901
                                         GimpZoomFocus     zoom_focus)
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
902
{
903
  gint image_center_x, image_center_y;
904
  gint other_x, other_y;
905
906
  /* Calculate stops-to-fit focus point */
907
  {
908
    gint sw, sh;
909
910
    gimp_display_shell_draw_get_scaled_image_size (shell,
911
                                                   &sw,
912
                                                   &sh);
913
    image_center_x = -shell->offset_x + sw / 2;
914
    image_center_y = -shell->offset_y + sh / 2;
915
  }
916
917
  /* Calculate other focus point */
918
  {
919
    GdkEvent *event;
920
    gboolean  event_looks_sane;
921
    gboolean  cursor_within_canvas;
922
    gint      canvas_pointer_x, canvas_pointer_y;
923
924
    /*  Center on the mouse position instead of the display center if
925
     *  one of the following conditions are fulfilled and pointer is
926
     *  within the canvas:
927
     *
928
     *   (1) there's no current event (the action was triggered by an
929
     *       input controller)
930
     *   (2) the event originates from the canvas (a scroll event)
931
     *   (3) the event originates from the shell (a key press event)
932
     *
933
     *  Basically the only situation where we don't want to center on
934
     *  mouse position is if the action is being called from a menu.
935
     */
936
937
    event = gtk_get_current_event ();
938
939
    event_looks_sane = ! event ||
940
                       gtk_get_event_widget (event) == shell->canvas ||
941
                       gtk_get_event_widget (event) == GTK_WIDGET (shell);
942
943
944
    gtk_widget_get_pointer (shell->canvas,
945
                            &canvas_pointer_x,
946
                            &canvas_pointer_y);
947
948
    cursor_within_canvas = canvas_pointer_x >= 0 &&
949
                           canvas_pointer_y >= 0 &&
950
                           canvas_pointer_x <  shell->disp_width &&
951
                           canvas_pointer_y <  shell->disp_height;
952
953
954
    if (event_looks_sane && cursor_within_canvas)
955
      {
956
        other_x = canvas_pointer_x;
957
        other_y = canvas_pointer_y;
958
      }
959
    else
960
      {
961
        other_x = shell->disp_width  / 2;
962
        other_y = shell->disp_height / 2;
963
      }
964
  }
965
966
  /* Decide which one to use for each axis */
1.1.16 by Sebastien Bacher
Import upstream version 2.6.1
967
  switch (zoom_focus)
968
    {
969
    case GIMP_ZOOM_FOCUS_POINTER:
970
      *x = other_x;
971
      *y = other_y;
972
      break;
973
974
    case GIMP_ZOOM_FOCUS_IMAGE_CENTER:
975
      *x = image_center_x;
976
      *y = image_center_y;
977
      break;
978
979
    case GIMP_ZOOM_FOCUS_BEST_GUESS:
980
    default:
981
      {
982
        gboolean within_horizontally, within_vertically;
983
        gboolean stops_horizontally, stops_vertically;
984
985
        gimp_display_shell_scale_image_is_within_viewport (shell,
986
                                                           &within_horizontally,
987
                                                           &within_vertically);
988
989
        gimp_display_shell_scale_image_stops_to_fit (shell,
990
                                                     new_scale,
991
                                                     current_scale,
992
                                                     &stops_horizontally,
993
                                                     &stops_vertically);
994
995
        *x = within_horizontally && ! stops_horizontally ? image_center_x : other_x;
996
        *y = within_vertically   && ! stops_vertically   ? image_center_y : other_y;
997
      }
998
      break;
999
    }
1 by Daniel Holbach
Import upstream version 2.2.9
1000
}
1001
1002
/* scale image coord to realworld units (cm, inches, pixels)
1003
 *
1004
 * 27/Feb/1999 I tried inlining this, but the result was slightly
1005
 * slower (poorer cache locality, probably) -- austin
1006
 */
1007
static gdouble
1008
img2real (GimpDisplayShell *shell,
1009
          gboolean          xdir,
1010
          gdouble           len)
1011
{
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
1012
  gdouble xres;
1013
  gdouble yres;
1014
  gdouble res;
1 by Daniel Holbach
Import upstream version 2.2.9
1015
1016
  if (shell->unit == GIMP_UNIT_PIXEL)
1017
    return len;
1018
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
1019
  gimp_image_get_resolution (shell->display->image, &xres, &yres);
1020
1 by Daniel Holbach
Import upstream version 2.2.9
1021
  if (xdir)
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
1022
    res = xres;
1 by Daniel Holbach
Import upstream version 2.2.9
1023
  else
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
1024
    res = yres;
1 by Daniel Holbach
Import upstream version 2.2.9
1025
1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
1026
  return len * _gimp_unit_get_factor (shell->display->gimp, shell->unit) / res;
1 by Daniel Holbach
Import upstream version 2.2.9
1027
}