1997-11-25 06:05:25 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-17 05:37:03 +08:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <stdlib.h>
|
2000-01-26 07:06:12 +08:00
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2003-04-04 16:32:51 +08:00
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
2001-05-21 21:58:46 +08:00
|
|
|
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "display-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2002-11-19 04:50:31 +08:00
|
|
|
#include "config/gimpdisplayconfig.h"
|
|
|
|
|
|
|
|
#include "core/gimp.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpimage.h"
|
2004-06-02 06:04:20 +08:00
|
|
|
#include "core/gimpunit.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
|
2003-08-24 21:52:51 +08:00
|
|
|
#include "widgets/gimphelp-ids.h"
|
2003-04-04 16:32:51 +08:00
|
|
|
#include "widgets/gimpviewabledialog.h"
|
|
|
|
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "gimpdisplay.h"
|
2001-11-01 05:20:09 +08:00
|
|
|
#include "gimpdisplayshell.h"
|
2001-11-02 17:31:21 +08:00
|
|
|
#include "gimpdisplayshell-scale.h"
|
|
|
|
#include "gimpdisplayshell-scroll.h"
|
2003-02-26 03:01:10 +08:00
|
|
|
#include "gimpdisplayshell-title.h"
|
2001-09-26 07:23:09 +08:00
|
|
|
|
2003-04-04 16:32:51 +08:00
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
|
2003-05-05 23:33:11 +08:00
|
|
|
typedef struct _ScaleDialogData ScaleDialogData;
|
|
|
|
|
|
|
|
struct _ScaleDialogData
|
|
|
|
{
|
|
|
|
GimpDisplayShell *shell;
|
2004-01-30 06:22:29 +08:00
|
|
|
GtkObject *scale_adj;
|
|
|
|
GtkObject *num_adj;
|
|
|
|
GtkObject *denom_adj;
|
2003-05-05 23:33:11 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2001-10-13 20:52:30 +08:00
|
|
|
/* local function prototypes */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
static void gimp_display_shell_scale_dialog_response (GtkWidget *widget,
|
|
|
|
gint response_id,
|
|
|
|
ScaleDialogData *dialog);
|
2004-01-30 06:22:29 +08:00
|
|
|
static void update_zoom_values (GtkAdjustment *adj,
|
|
|
|
ScaleDialogData *dialog);
|
2003-05-05 23:33:11 +08:00
|
|
|
static gdouble img2real (GimpDisplayShell *shell,
|
|
|
|
gboolean xdir,
|
|
|
|
gdouble a);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
2001-10-13 20:52:30 +08:00
|
|
|
/* public functions */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
gdouble
|
|
|
|
gimp_display_shell_scale_zoom_step (GimpZoomType zoom_type,
|
|
|
|
gdouble scale)
|
2003-05-05 22:48:15 +08:00
|
|
|
{
|
2004-01-30 06:22:29 +08:00
|
|
|
gint i, n_presets;
|
2004-02-01 08:36:53 +08:00
|
|
|
gdouble new_scale = 1.0;
|
2004-01-30 06:22:29 +08:00
|
|
|
|
|
|
|
/* This table is constructed to have fractions, that approximate
|
|
|
|
* sqrt(2)^k. This gives a smooth feeling regardless of the starting
|
|
|
|
* zoom level.
|
|
|
|
*
|
|
|
|
* Zooming in/out always jumps to a zoom step from the list above.
|
|
|
|
* However, we try to guarantee a certain size of the step, to
|
|
|
|
* avoid silly jumps from 101% to 100%.
|
|
|
|
* The factor 1.1 is chosen a bit arbitrary, but feels better
|
|
|
|
* than the geometric median of the zoom steps (2^(1/4)).
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define ZOOM_MIN_STEP 1.1
|
|
|
|
|
|
|
|
gdouble presets[] = {
|
|
|
|
1.0 / 256, 1.0 / 180, 1.0 / 128, 1.0 / 90,
|
|
|
|
1.0 / 64, 1.0 / 45, 1.0 / 32, 1.0 / 23,
|
|
|
|
1.0 / 16, 1.0 / 11, 1.0 / 8, 2.0 / 11,
|
|
|
|
1.0 / 4, 1.0 / 3, 1.0 / 2, 2.0 / 3,
|
|
|
|
1.0,
|
|
|
|
3.0 / 2, 2.0, 3.0,
|
|
|
|
4.0, 11.0 / 2, 8.0, 11.0,
|
|
|
|
16.0, 23.0, 32.0, 45.0,
|
|
|
|
64.0, 90.0, 128.0, 180.0,
|
|
|
|
256.0,
|
|
|
|
};
|
|
|
|
|
|
|
|
n_presets = G_N_ELEMENTS (presets);
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2003-05-05 22:48:15 +08:00
|
|
|
switch (zoom_type)
|
|
|
|
{
|
|
|
|
case GIMP_ZOOM_IN:
|
2004-01-30 06:22:29 +08:00
|
|
|
scale *= ZOOM_MIN_STEP;
|
|
|
|
|
|
|
|
new_scale = presets[n_presets-1];
|
|
|
|
|
|
|
|
for (i = n_presets - 1; i >= 0 && presets[i] > scale; i--)
|
|
|
|
new_scale = presets[i];
|
|
|
|
|
2003-05-05 22:48:15 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_ZOOM_OUT:
|
2004-01-30 06:22:29 +08:00
|
|
|
scale /= ZOOM_MIN_STEP;
|
|
|
|
|
|
|
|
new_scale = presets[0];
|
|
|
|
|
|
|
|
for (i = 0; i < n_presets && presets[i] < scale; i++)
|
|
|
|
new_scale = presets[i];
|
|
|
|
|
2003-05-05 22:48:15 +08:00
|
|
|
break;
|
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
case GIMP_ZOOM_TO:
|
|
|
|
new_scale = scale;
|
2003-05-05 22:48:15 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
return CLAMP (new_scale, 1.0/256.0, 256.0);
|
2003-05-05 22:48:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-01-30 06:22:29 +08:00
|
|
|
gimp_display_shell_scale_get_fraction (gdouble zoom_factor,
|
|
|
|
gint *numerator,
|
|
|
|
gint *denominator)
|
2003-05-05 22:48:15 +08:00
|
|
|
{
|
2004-01-11 08:28:38 +08:00
|
|
|
gint p0, p1, p2;
|
|
|
|
gint q0, q1, q2;
|
|
|
|
gdouble remainder, next_cf;
|
|
|
|
gboolean swapped = FALSE;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
g_return_if_fail (numerator != NULL && denominator != NULL);
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 08:28:38 +08:00
|
|
|
/* make sure that zooming behaves symmetrically */
|
|
|
|
if (zoom_factor < 1.0)
|
|
|
|
{
|
|
|
|
zoom_factor = 1.0 / zoom_factor;
|
|
|
|
swapped = TRUE;
|
|
|
|
}
|
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
/* calculate the continued fraction for the desired zoom factor */
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
p0 = 1;
|
|
|
|
q0 = 0;
|
|
|
|
p1 = floor (zoom_factor);
|
|
|
|
q1 = 1;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
remainder = zoom_factor - p1;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
while (fabs (remainder) >= 0.0001 &&
|
|
|
|
fabs (((gdouble) p1 / q1) - zoom_factor) > 0.0001)
|
|
|
|
{
|
|
|
|
remainder = 1.0 / remainder;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
next_cf = floor (remainder);
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
p2 = next_cf * p1 + p0;
|
|
|
|
q2 = next_cf * q1 + q0;
|
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
/* Numerator and Denominator are limited by 256 */
|
2004-01-11 08:28:38 +08:00
|
|
|
/* also absurd ratios like 170:171 are excluded */
|
2004-01-30 06:22:29 +08:00
|
|
|
if (p2 > 256 || q2 > 256 || (p2 > 1 && q2 > 1 && p2 * q2 > 200))
|
2004-01-11 07:44:24 +08:00
|
|
|
break;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
/* remember the last two fractions */
|
|
|
|
p0 = p1;
|
|
|
|
p1 = p2;
|
|
|
|
q0 = q1;
|
|
|
|
q1 = q2;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
remainder = remainder - next_cf;
|
|
|
|
}
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
zoom_factor = (gdouble) p1 / q1;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-11 07:44:24 +08:00
|
|
|
/* hard upper and lower bounds for zoom ratio */
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
if (zoom_factor > 256.0)
|
2004-01-11 07:44:24 +08:00
|
|
|
{
|
2004-01-30 06:22:29 +08:00
|
|
|
p1 = 256;
|
2004-01-11 07:44:24 +08:00
|
|
|
q1 = 1;
|
2003-05-05 22:48:15 +08:00
|
|
|
}
|
2004-01-30 06:22:29 +08:00
|
|
|
else if (zoom_factor < 1.0 / 256.0)
|
2004-01-11 07:44:24 +08:00
|
|
|
{
|
|
|
|
p1 = 1;
|
2004-01-30 06:22:29 +08:00
|
|
|
q1 = 256;
|
2004-01-11 07:44:24 +08:00
|
|
|
}
|
|
|
|
|
2004-01-11 08:28:38 +08:00
|
|
|
if (swapped)
|
|
|
|
{
|
2004-01-30 06:22:29 +08:00
|
|
|
*numerator = q1;
|
|
|
|
*denominator = p1;
|
2004-01-11 08:28:38 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-30 06:22:29 +08:00
|
|
|
*numerator = p1;
|
|
|
|
*denominator = q1;
|
2004-01-11 08:28:38 +08:00
|
|
|
}
|
2003-05-05 22:48:15 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_display_shell_scale_setup (GimpDisplayShell *shell)
|
|
|
|
{
|
|
|
|
GtkRuler *hruler;
|
|
|
|
GtkRuler *vruler;
|
|
|
|
gfloat sx, sy;
|
|
|
|
gfloat stepx, stepy;
|
|
|
|
gint image_width, image_height;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
|
|
|
|
2004-06-02 06:04:20 +08:00
|
|
|
if (! shell->gdisp)
|
|
|
|
return;
|
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
image_width = shell->gdisp->gimage->width;
|
|
|
|
image_height = shell->gdisp->gimage->height;
|
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
sx = SCALEX (shell, image_width);
|
|
|
|
sy = SCALEY (shell, image_height);
|
|
|
|
stepx = SCALEFACTOR_X (shell);
|
|
|
|
stepy = SCALEFACTOR_Y (shell);
|
2001-11-01 05:20:09 +08:00
|
|
|
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->hsbdata->value = shell->offset_x;
|
2001-11-01 05:20:09 +08:00
|
|
|
shell->hsbdata->upper = sx;
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->hsbdata->page_size = MIN (sx, shell->disp_width);
|
|
|
|
shell->hsbdata->page_increment = shell->disp_width / 2;
|
2001-11-01 05:20:09 +08:00
|
|
|
shell->hsbdata->step_increment = stepx;
|
|
|
|
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->vsbdata->value = shell->offset_y;
|
2001-11-01 05:20:09 +08:00
|
|
|
shell->vsbdata->upper = sy;
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->vsbdata->page_size = MIN (sy, shell->disp_height);
|
|
|
|
shell->vsbdata->page_increment = shell->disp_height / 2;
|
2001-11-01 05:20:09 +08:00
|
|
|
shell->vsbdata->step_increment = stepy;
|
|
|
|
|
|
|
|
gtk_adjustment_changed (shell->hsbdata);
|
|
|
|
gtk_adjustment_changed (shell->vsbdata);
|
|
|
|
|
|
|
|
hruler = GTK_RULER (shell->hrule);
|
|
|
|
vruler = GTK_RULER (shell->vrule);
|
|
|
|
|
|
|
|
hruler->lower = 0;
|
2002-06-27 06:16:59 +08:00
|
|
|
hruler->upper = img2real (shell, TRUE,
|
|
|
|
FUNSCALEX (shell, shell->disp_width));
|
|
|
|
hruler->max_size = img2real (shell, TRUE,
|
2001-11-01 05:20:09 +08:00
|
|
|
MAX (image_width, image_height));
|
|
|
|
|
|
|
|
vruler->lower = 0;
|
2002-06-27 06:16:59 +08:00
|
|
|
vruler->upper = img2real (shell, FALSE,
|
|
|
|
FUNSCALEY (shell, shell->disp_height));
|
|
|
|
vruler->max_size = img2real (shell, FALSE,
|
2001-11-01 05:20:09 +08:00
|
|
|
MAX (image_width, image_height));
|
|
|
|
|
2001-11-02 17:31:21 +08:00
|
|
|
if (sx < shell->disp_width)
|
2001-11-01 05:20:09 +08:00
|
|
|
{
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->disp_xoffset = (shell->disp_width - sx) / 2;
|
2001-11-01 05:20:09 +08:00
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
hruler->lower -= img2real (shell, TRUE,
|
|
|
|
FUNSCALEX (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->disp_xoffset));
|
2002-06-27 06:16:59 +08:00
|
|
|
hruler->upper -= img2real (shell, TRUE,
|
|
|
|
FUNSCALEX (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->disp_xoffset));
|
2001-11-01 05:20:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->disp_xoffset = 0;
|
2001-11-01 05:20:09 +08:00
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
hruler->lower += img2real (shell, TRUE,
|
|
|
|
FUNSCALEX (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->offset_x));
|
2002-06-27 06:16:59 +08:00
|
|
|
hruler->upper += img2real (shell, TRUE,
|
|
|
|
FUNSCALEX (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->offset_x));
|
2001-11-01 05:20:09 +08:00
|
|
|
}
|
|
|
|
|
2001-11-02 17:31:21 +08:00
|
|
|
if (sy < shell->disp_height)
|
2001-11-01 05:20:09 +08:00
|
|
|
{
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->disp_yoffset = (shell->disp_height - sy) / 2;
|
2001-11-01 05:20:09 +08:00
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
vruler->lower -= img2real (shell, FALSE,
|
|
|
|
FUNSCALEY (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->disp_yoffset));
|
2002-06-27 06:16:59 +08:00
|
|
|
vruler->upper -= img2real (shell, FALSE,
|
|
|
|
FUNSCALEY (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->disp_yoffset));
|
2001-11-01 05:20:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->disp_yoffset = 0;
|
2001-11-01 05:20:09 +08:00
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
vruler->lower += img2real (shell, FALSE,
|
|
|
|
FUNSCALEY (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->offset_y));
|
2002-06-27 06:16:59 +08:00
|
|
|
vruler->upper += img2real (shell, FALSE,
|
|
|
|
FUNSCALEY (shell,
|
2001-11-02 17:31:21 +08:00
|
|
|
(gdouble) shell->offset_y));
|
2001-11-01 05:20:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_queue_draw (GTK_WIDGET (hruler));
|
|
|
|
gtk_widget_queue_draw (GTK_WIDGET (vruler));
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
g_print ("offset_x: %d\n"
|
|
|
|
"offset_y: %d\n"
|
|
|
|
"disp_width: %d\n"
|
|
|
|
"disp_height: %d\n"
|
|
|
|
"disp_xoffset: %d\n"
|
|
|
|
"disp_yoffset: %d\n\n",
|
2001-11-02 17:31:21 +08:00
|
|
|
shell->offset_x, shell->offset_y,
|
|
|
|
shell->disp_width, shell->disp_height,
|
|
|
|
shell->disp_xoffset, shell->disp_yoffset);
|
2001-11-01 05:20:09 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *shell,
|
|
|
|
gboolean dot_for_dot)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
if (dot_for_dot != shell->dot_for_dot)
|
2001-11-01 05:20:09 +08:00
|
|
|
{
|
2003-01-11 05:15:41 +08:00
|
|
|
Gimp *gimp = shell->gdisp->gimage->gimp;
|
|
|
|
|
2002-02-17 19:46:39 +08:00
|
|
|
/* freeze the active tool */
|
2003-09-12 06:24:30 +08:00
|
|
|
gimp_display_shell_pause (shell);
|
2002-02-17 19:46:39 +08:00
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
shell->dot_for_dot = dot_for_dot;
|
2001-11-01 05:20:09 +08:00
|
|
|
|
|
|
|
gimp_display_shell_scale_resize (shell,
|
2003-01-11 05:15:41 +08:00
|
|
|
GIMP_DISPLAY_CONFIG (gimp->config)->resize_windows_on_zoom,
|
2002-11-19 04:50:31 +08:00
|
|
|
TRUE);
|
2002-02-17 19:46:39 +08:00
|
|
|
|
|
|
|
/* re-enable the active tool */
|
2003-09-12 06:24:30 +08:00
|
|
|
gimp_display_shell_resume (shell);
|
2001-11-01 05:20:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_display_shell_scale (GimpDisplayShell *shell,
|
2004-01-30 06:22:29 +08:00
|
|
|
GimpZoomType zoom_type,
|
|
|
|
gdouble new_scale)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-01-11 05:15:41 +08:00
|
|
|
GimpDisplayConfig *config;
|
2003-05-05 22:48:15 +08:00
|
|
|
gdouble offset_x, offset_y;
|
2004-01-30 06:22:29 +08:00
|
|
|
gdouble scale;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
2001-10-13 20:52:30 +08:00
|
|
|
|
2004-06-02 06:04:20 +08:00
|
|
|
scale = shell->scale;
|
|
|
|
|
|
|
|
if (! shell->gdisp)
|
|
|
|
return;
|
|
|
|
|
2003-05-05 23:33:11 +08:00
|
|
|
offset_x = shell->offset_x + (shell->disp_width / 2.0);
|
2001-11-02 17:31:21 +08:00
|
|
|
offset_y = shell->offset_y + (shell->disp_height / 2.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
offset_x /= scale;
|
|
|
|
offset_y /= scale;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
if (zoom_type == GIMP_ZOOM_TO)
|
|
|
|
scale = new_scale;
|
|
|
|
else
|
|
|
|
scale = gimp_display_shell_scale_zoom_step (zoom_type, scale);
|
2000-01-26 07:06:12 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
offset_x *= scale;
|
|
|
|
offset_y *= scale;
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2003-01-11 05:15:41 +08:00
|
|
|
config = GIMP_DISPLAY_CONFIG (shell->gdisp->gimage->gimp->config);
|
2003-05-05 22:48:15 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
gimp_display_shell_scale_by_values (shell, scale,
|
|
|
|
offset_x - (shell->disp_width / 2),
|
|
|
|
offset_y - (shell->disp_height / 2),
|
2003-01-11 05:15:41 +08:00
|
|
|
config->resize_windows_on_zoom);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-11-02 17:31:21 +08:00
|
|
|
void
|
|
|
|
gimp_display_shell_scale_fit (GimpDisplayShell *shell)
|
|
|
|
{
|
2003-01-11 05:15:41 +08:00
|
|
|
GimpImage *gimage;
|
|
|
|
gint image_width;
|
|
|
|
gint image_height;
|
|
|
|
gdouble zoom_factor;
|
2001-11-02 17:31:21 +08:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
|
|
|
|
2002-11-19 04:50:31 +08:00
|
|
|
gimage = shell->gdisp->gimage;
|
|
|
|
|
|
|
|
image_width = gimage->width;
|
|
|
|
image_height = gimage->height;
|
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
if (! shell->dot_for_dot)
|
2001-11-02 17:31:21 +08:00
|
|
|
{
|
|
|
|
image_width = ROUND (image_width *
|
2003-05-29 00:11:29 +08:00
|
|
|
shell->monitor_xres / gimage->xresolution);
|
2001-11-02 17:31:21 +08:00
|
|
|
image_height = ROUND (image_height *
|
2003-05-29 00:11:29 +08:00
|
|
|
shell->monitor_xres / gimage->yresolution);
|
2001-11-02 17:31:21 +08:00
|
|
|
}
|
|
|
|
|
2003-05-05 23:33:11 +08:00
|
|
|
zoom_factor = MIN ((gdouble) shell->disp_width / (gdouble) image_width,
|
|
|
|
(gdouble) shell->disp_height / (gdouble) image_height);
|
2001-11-02 17:31:21 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
gimp_display_shell_scale (shell, GIMP_ZOOM_TO, zoom_factor);
|
2002-02-17 19:46:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_display_shell_scale_by_values (GimpDisplayShell *shell,
|
2004-01-30 06:22:29 +08:00
|
|
|
gdouble scale,
|
2002-02-17 19:46:39 +08:00
|
|
|
gint offset_x,
|
|
|
|
gint offset_y,
|
|
|
|
gboolean resize_window)
|
|
|
|
{
|
2003-01-11 05:15:41 +08:00
|
|
|
Gimp *gimp;
|
|
|
|
|
2002-02-17 19:46:39 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
|
|
|
|
2003-01-11 05:15:41 +08:00
|
|
|
gimp = shell->gdisp->gimage->gimp;
|
|
|
|
|
2002-02-17 19:46:39 +08:00
|
|
|
/* freeze the active tool */
|
2003-09-12 06:24:30 +08:00
|
|
|
gimp_display_shell_pause (shell);
|
2002-02-17 19:46:39 +08:00
|
|
|
|
2002-06-27 06:16:59 +08:00
|
|
|
shell->scale = scale;
|
|
|
|
shell->offset_x = offset_x;
|
|
|
|
shell->offset_y = offset_y;
|
2002-02-17 19:46:39 +08:00
|
|
|
|
|
|
|
gimp_display_shell_scale_resize (shell, resize_window, TRUE);
|
|
|
|
|
|
|
|
/* re-enable the active tool */
|
2003-09-12 06:24:30 +08:00
|
|
|
gimp_display_shell_resume (shell);
|
2002-02-17 19:46:39 +08:00
|
|
|
}
|
2001-11-02 17:31:21 +08:00
|
|
|
|
2002-02-17 19:46:39 +08:00
|
|
|
void
|
|
|
|
gimp_display_shell_scale_shrink_wrap (GimpDisplayShell *shell)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
2001-11-02 17:31:21 +08:00
|
|
|
|
2002-02-17 19:46:39 +08:00
|
|
|
gimp_display_shell_scale_resize (shell, TRUE, TRUE);
|
2001-11-02 17:31:21 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_display_shell_scale_resize (GimpDisplayShell *shell,
|
|
|
|
gboolean resize_window,
|
|
|
|
gboolean redisplay)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-01-11 05:15:41 +08:00
|
|
|
Gimp *gimp;
|
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
2001-10-13 20:52:30 +08:00
|
|
|
|
2003-01-11 05:15:41 +08:00
|
|
|
gimp = shell->gdisp->gimage->gimp;
|
|
|
|
|
2001-10-13 20:52:30 +08:00
|
|
|
/* freeze the active tool */
|
2003-09-12 06:24:30 +08:00
|
|
|
gimp_display_shell_pause (shell);
|
2001-10-13 20:52:30 +08:00
|
|
|
|
|
|
|
if (resize_window)
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_display_shell_shrink_wrap (shell);
|
2001-10-13 20:52:30 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_display_shell_scroll_clamp_offsets (shell);
|
|
|
|
gimp_display_shell_scale_setup (shell);
|
2003-03-22 00:28:06 +08:00
|
|
|
gimp_display_shell_scaled (shell);
|
2001-10-13 20:52:30 +08:00
|
|
|
|
|
|
|
if (resize_window || redisplay)
|
2003-02-26 03:01:10 +08:00
|
|
|
gimp_display_shell_expose_full (shell);
|
2001-10-13 20:52:30 +08:00
|
|
|
|
|
|
|
/* re-enable the active tool */
|
2003-09-12 06:24:30 +08:00
|
|
|
gimp_display_shell_resume (shell);
|
2001-10-13 20:52:30 +08:00
|
|
|
}
|
|
|
|
|
2003-04-04 16:32:51 +08:00
|
|
|
void
|
|
|
|
gimp_display_shell_scale_dialog (GimpDisplayShell *shell)
|
|
|
|
{
|
|
|
|
ScaleDialogData *data;
|
|
|
|
GtkWidget *hbox;
|
2004-01-30 06:22:29 +08:00
|
|
|
GtkWidget *table;
|
2003-04-04 16:32:51 +08:00
|
|
|
GtkWidget *spin;
|
|
|
|
GtkWidget *label;
|
2004-01-30 06:22:29 +08:00
|
|
|
gint num, denom, row;
|
2003-04-04 16:32:51 +08:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
|
|
|
|
|
|
|
if (shell->scale_dialog)
|
|
|
|
{
|
|
|
|
gtk_window_present (GTK_WINDOW (shell->scale_dialog));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = g_new (ScaleDialogData, 1);
|
|
|
|
data->shell = shell;
|
|
|
|
|
|
|
|
shell->scale_dialog =
|
|
|
|
gimp_viewable_dialog_new (GIMP_VIEWABLE (shell->gdisp->gimage),
|
|
|
|
_("Zoom Ratio"), "display_scale",
|
|
|
|
GTK_STOCK_ZOOM_100,
|
|
|
|
_("Select Zoom Ratio"),
|
2003-11-08 23:29:47 +08:00
|
|
|
GTK_WIDGET (shell),
|
2003-04-04 16:32:51 +08:00
|
|
|
gimp_standard_help_func,
|
2003-08-24 21:52:51 +08:00
|
|
|
GIMP_HELP_VIEW_ZOOM_OTHER,
|
2003-05-05 23:33:11 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
2003-04-04 16:32:51 +08:00
|
|
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
g_object_weak_ref (G_OBJECT (shell->scale_dialog),
|
|
|
|
(GWeakNotify) g_free, data);
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (shell->scale_dialog),
|
|
|
|
(gpointer *) &shell->scale_dialog);
|
|
|
|
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (shell->scale_dialog),
|
|
|
|
GTK_WINDOW (shell));
|
|
|
|
gtk_window_set_destroy_with_parent (GTK_WINDOW (shell->scale_dialog), TRUE);
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
g_signal_connect (shell->scale_dialog, "response",
|
|
|
|
G_CALLBACK (gimp_display_shell_scale_dialog_response),
|
|
|
|
data);
|
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
table = gtk_table_new (2, 2, FALSE);
|
2004-02-03 23:51:25 +08:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (table), 6);
|
2004-01-30 06:22:29 +08:00
|
|
|
gtk_table_set_col_spacings (GTK_TABLE (table), 2);
|
|
|
|
gtk_table_set_row_spacings (GTK_TABLE (table), 4);
|
|
|
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (shell->scale_dialog)->vbox),
|
|
|
|
table);
|
|
|
|
gtk_widget_show (table);
|
|
|
|
|
|
|
|
row = 0;
|
|
|
|
|
2003-04-04 16:32:51 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 4);
|
2004-01-30 06:22:29 +08:00
|
|
|
gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
|
2004-05-12 19:37:21 +08:00
|
|
|
_("Zoom Ratio:"), 0.0, 0.5,
|
2004-01-30 06:22:29 +08:00
|
|
|
hbox, 1, FALSE);
|
2003-04-04 16:32:51 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
if (fabs (shell->other_scale) <= 0.0001)
|
|
|
|
shell->other_scale = shell->scale; /* other_scale not yet initialized */
|
2003-04-04 16:32:51 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
gimp_display_shell_scale_get_fraction (fabs (shell->other_scale),
|
|
|
|
&num, &denom);
|
2003-04-04 16:32:51 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
spin = gimp_spin_button_new (&data->num_adj,
|
|
|
|
num, 1, 256,
|
2003-04-04 16:32:51 +08:00
|
|
|
1, 8, 1, 1, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), spin, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (spin);
|
|
|
|
|
|
|
|
label = gtk_label_new (":");
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (label);
|
2003-05-05 23:33:11 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
spin = gimp_spin_button_new (&data->denom_adj,
|
|
|
|
denom, 1, 256,
|
2003-04-04 16:32:51 +08:00
|
|
|
1, 8, 1, 1, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), spin, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (spin);
|
|
|
|
|
2004-02-03 23:51:25 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 4);
|
|
|
|
gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
|
2004-05-12 19:37:21 +08:00
|
|
|
_("Zoom:"), 0.0, 0.5,
|
2004-02-03 23:51:25 +08:00
|
|
|
hbox, 1, FALSE);
|
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
spin = gimp_spin_button_new (&data->scale_adj,
|
|
|
|
fabs (shell->other_scale) * 100,
|
|
|
|
100.0 / 256.0, 25600.0,
|
|
|
|
10, 50, 0, 1, 2);
|
2004-02-03 23:51:25 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), spin, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (spin);
|
|
|
|
|
|
|
|
label = gtk_label_new ("%");
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (label);
|
2004-01-30 06:22:29 +08:00
|
|
|
|
|
|
|
g_signal_connect (data->scale_adj, "value-changed",
|
|
|
|
G_CALLBACK (update_zoom_values), data);
|
|
|
|
g_signal_connect (data->num_adj, "value-changed",
|
|
|
|
G_CALLBACK (update_zoom_values), data);
|
|
|
|
g_signal_connect (data->denom_adj, "value-changed",
|
|
|
|
G_CALLBACK (update_zoom_values), data);
|
|
|
|
|
2003-04-04 16:32:51 +08:00
|
|
|
gtk_widget_show (shell->scale_dialog);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-13 20:52:30 +08:00
|
|
|
/* private functions */
|
|
|
|
|
2003-04-04 16:32:51 +08:00
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
gimp_display_shell_scale_dialog_response (GtkWidget *widget,
|
|
|
|
gint response_id,
|
|
|
|
ScaleDialogData *dialog)
|
2003-04-04 16:32:51 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
|
|
{
|
2004-01-30 06:22:29 +08:00
|
|
|
gdouble scale;
|
2003-04-04 16:32:51 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
scale = gtk_adjustment_get_value (GTK_ADJUSTMENT (dialog->scale_adj));
|
2003-04-04 16:32:51 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
gimp_display_shell_scale (dialog->shell, GIMP_ZOOM_TO, scale / 100.0);
|
2003-11-06 23:27:05 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* need to emit "scaled" to get the menu updated */
|
|
|
|
gimp_display_shell_scaled (dialog->shell);
|
|
|
|
}
|
2003-04-04 16:32:51 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
dialog->shell->other_scale = - fabs (dialog->shell->other_scale);
|
2003-04-04 16:32:51 +08:00
|
|
|
|
|
|
|
gtk_widget_destroy (dialog->shell->scale_dialog);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
static void
|
|
|
|
update_zoom_values (GtkAdjustment *adj,
|
|
|
|
ScaleDialogData *dialog)
|
|
|
|
{
|
|
|
|
gint num, denom;
|
|
|
|
gdouble scale;
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
g_signal_handlers_block_by_func (GTK_ADJUSTMENT (dialog->scale_adj),
|
|
|
|
G_CALLBACK (update_zoom_values),
|
|
|
|
dialog);
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
g_signal_handlers_block_by_func (GTK_ADJUSTMENT (dialog->num_adj),
|
|
|
|
G_CALLBACK (update_zoom_values),
|
|
|
|
dialog);
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
g_signal_handlers_block_by_func (GTK_ADJUSTMENT (dialog->denom_adj),
|
|
|
|
G_CALLBACK (update_zoom_values),
|
|
|
|
dialog);
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
if (GTK_OBJECT (adj) == dialog->scale_adj)
|
|
|
|
{
|
|
|
|
scale = gtk_adjustment_get_value (GTK_ADJUSTMENT (dialog->scale_adj));
|
|
|
|
|
|
|
|
gimp_display_shell_scale_get_fraction (scale / 100.0, &num, &denom);
|
|
|
|
|
|
|
|
gtk_adjustment_set_value (GTK_ADJUSTMENT (dialog->num_adj), num);
|
|
|
|
gtk_adjustment_set_value (GTK_ADJUSTMENT (dialog->denom_adj), denom);
|
|
|
|
}
|
|
|
|
else /* fraction adjustments */
|
|
|
|
{
|
|
|
|
scale = (gtk_adjustment_get_value (GTK_ADJUSTMENT (dialog->num_adj)) /
|
|
|
|
gtk_adjustment_get_value (GTK_ADJUSTMENT (dialog->denom_adj)));
|
|
|
|
gtk_adjustment_set_value (GTK_ADJUSTMENT (dialog->scale_adj),
|
|
|
|
scale * 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_signal_handlers_unblock_by_func (GTK_ADJUSTMENT (dialog->scale_adj),
|
|
|
|
G_CALLBACK (update_zoom_values),
|
|
|
|
dialog);
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
g_signal_handlers_unblock_by_func (GTK_ADJUSTMENT (dialog->num_adj),
|
|
|
|
G_CALLBACK (update_zoom_values),
|
|
|
|
dialog);
|
2004-02-03 23:51:25 +08:00
|
|
|
|
2004-01-30 06:22:29 +08:00
|
|
|
g_signal_handlers_unblock_by_func (GTK_ADJUSTMENT (dialog->denom_adj),
|
|
|
|
G_CALLBACK (update_zoom_values),
|
|
|
|
dialog);
|
|
|
|
}
|
|
|
|
|
2001-10-13 20:52:30 +08:00
|
|
|
/* scale image coord to realworld units (cm, inches, pixels)
|
|
|
|
*
|
|
|
|
* 27/Feb/1999 I tried inlining this, but the result was slightly
|
|
|
|
* slower (poorer cache locality, probably) -- austin
|
|
|
|
*/
|
|
|
|
static gdouble
|
2002-06-27 06:16:59 +08:00
|
|
|
img2real (GimpDisplayShell *shell,
|
|
|
|
gboolean xdir,
|
2003-10-02 01:32:14 +08:00
|
|
|
gdouble len)
|
2001-10-13 20:52:30 +08:00
|
|
|
{
|
2004-05-07 23:45:56 +08:00
|
|
|
GimpImage *image = shell->gdisp->gimage;
|
2003-01-11 05:15:41 +08:00
|
|
|
gdouble res;
|
2001-10-13 20:52:30 +08:00
|
|
|
|
2004-06-02 06:04:20 +08:00
|
|
|
if (shell->unit == GIMP_UNIT_PIXEL)
|
2003-10-02 01:32:14 +08:00
|
|
|
return len;
|
2001-10-13 20:52:30 +08:00
|
|
|
|
|
|
|
if (xdir)
|
2004-05-07 23:45:56 +08:00
|
|
|
res = image->xresolution;
|
2001-10-13 20:52:30 +08:00
|
|
|
else
|
2004-05-07 23:45:56 +08:00
|
|
|
res = image->yresolution;
|
2001-10-13 20:52:30 +08:00
|
|
|
|
2004-06-02 06:04:20 +08:00
|
|
|
return len * _gimp_unit_get_factor (image->gimp, shell->unit) / res;
|
2001-10-13 20:52:30 +08:00
|
|
|
}
|