home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  7.3 KB  |  275 lines

  1. /* The GIMP -- an image manipulation program
  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 <stdlib.h>
  22.  
  23. #include <glib.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "gdisplay.h"
  29. #include "gdisplay_ops.h"
  30. #include "gimprc.h"
  31. #include "nav_window.h"
  32. #include "scale.h"
  33. #include "tools.h"
  34.  
  35. void
  36. bounds_checking (GDisplay *gdisp)
  37. {
  38.   gint sx, sy;
  39.  
  40.   sx = SCALEX (gdisp, gdisp->gimage->width);
  41.   sy = SCALEY (gdisp, gdisp->gimage->height);
  42.  
  43.   gdisp->offset_x = CLAMP (gdisp->offset_x, 0,
  44.                LOWPASS (sx - gdisp->disp_width));
  45.  
  46.   gdisp->offset_y = CLAMP (gdisp->offset_y, 0,
  47.                LOWPASS (sy - gdisp->disp_height));
  48. }
  49.  
  50.  
  51. void
  52. resize_display (GDisplay *gdisp,
  53.         gboolean  resize_window,
  54.         gboolean  redisplay)
  55. {
  56.   /* freeze the active tool */
  57.   active_tool_control (PAUSE, (void *) gdisp);
  58.  
  59.   if (resize_window)
  60.     gdisplay_shrink_wrap (gdisp);
  61.  
  62.   bounds_checking (gdisp);
  63.   setup_scale (gdisp);
  64.  
  65.   if (resize_window || redisplay)
  66.     {
  67.       gdisplay_expose_full (gdisp);
  68.       gdisplays_flush ();
  69.       /* title may have changed if it includes the zoom ratio */
  70.       gdisplay_update_title (gdisp);
  71.     }
  72.  
  73.   /* re-enable the active tool */
  74.   active_tool_control (RESUME, (void *) gdisp);
  75. }
  76.  
  77.  
  78. void
  79. shrink_wrap_display (GDisplay *gdisp)
  80. {
  81.   /* freeze the active tool */
  82.   active_tool_control (PAUSE, (void *) gdisp);
  83.  
  84.   gdisplay_shrink_wrap (gdisp);
  85.  
  86.   bounds_checking (gdisp);
  87.   setup_scale (gdisp);
  88.  
  89.   gdisplay_expose_full (gdisp);
  90.   gdisplays_flush ();
  91.  
  92.   /* re-enable the active tool */
  93.   active_tool_control (RESUME, (void *) gdisp);
  94. }
  95.  
  96.  
  97. void
  98. change_scale (GDisplay *gdisp,
  99.           ZoomType  zoom_type)
  100. {
  101.   guchar scalesrc, scaledest;
  102.   gdouble offset_x, offset_y;
  103.   glong sx, sy;
  104.  
  105.   /* user zoom control, so resolution versions not needed -- austin */
  106.   scalesrc = SCALESRC (gdisp);
  107.   scaledest = SCALEDEST (gdisp);
  108.  
  109.   offset_x = gdisp->offset_x + (gdisp->disp_width / 2.0);
  110.   offset_y = gdisp->offset_y + (gdisp->disp_height / 2.0);
  111.  
  112.   offset_x *= ((double) scalesrc / (double) scaledest);
  113.   offset_y *= ((double) scalesrc / (double) scaledest);
  114.  
  115.   switch (zoom_type)
  116.     {
  117.     case ZOOMIN :
  118.       if (scalesrc > 1)
  119.     scalesrc--;
  120.       else
  121.     if (scaledest < 0x10)
  122.       scaledest++;
  123.     else
  124.       return;
  125.       break;
  126.  
  127.     case ZOOMOUT :
  128.       if (scaledest > 1)
  129.     scaledest--;
  130.       else
  131.     if (scalesrc < 0x10)
  132.       scalesrc++;
  133.     else
  134.       return;
  135.       break;
  136.  
  137.     default :
  138.       scalesrc = zoom_type % 100;
  139.       if (scalesrc < 1)
  140.     scalesrc = 1;
  141.       else if (scalesrc > 0x10)
  142.     scalesrc = 0x10;
  143.       scaledest = zoom_type / 100;
  144.       if (scaledest < 1)
  145.     scaledest = 1;
  146.       else if (scaledest > 0x10)
  147.     scaledest = 0x10;
  148.       break;
  149.     }
  150.  
  151.   sx = (gdisp->gimage->width * scaledest) / scalesrc;
  152.   sy = (gdisp->gimage->height * scaledest) / scalesrc;
  153.  
  154.   /*  The slider value is a short, so make sure we are within its
  155.       range.  If we are trying to scale past it, then stop the scale  */
  156.   if (sx < 0xffff && sy < 0xffff)
  157.     {
  158.       gdisp->scale = (scaledest << 8) + scalesrc;
  159.  
  160.       /*  set the offsets  */
  161.       offset_x *= ((double) scaledest / (double) scalesrc);
  162.       offset_y *= ((double) scaledest / (double) scalesrc);
  163.  
  164.       gdisp->offset_x = (int) (offset_x - (gdisp->disp_width / 2));
  165.       gdisp->offset_y = (int) (offset_y - (gdisp->disp_height / 2));
  166.  
  167.       /*  resize the image  */
  168.       resize_display (gdisp, allow_resize_windows, TRUE);
  169.     }
  170. }
  171.  
  172.  
  173. /* scale image coord to realworld units (cm, inches, pixels) */
  174. /* 27/Feb/1999 I tried inlining this, but the result was slightly
  175.  * slower (poorer cache locality, probably) -- austin */
  176. static gdouble
  177. img2real (GDisplay *gdisp,
  178.       gboolean  xdir,
  179.       gdouble   a)
  180. {
  181.   gdouble res;
  182.  
  183.   if (gdisp->dot_for_dot)
  184.     return a;
  185.  
  186.   if (xdir)
  187.     res = gdisp->gimage->xresolution;
  188.   else
  189.     res = gdisp->gimage->yresolution;
  190.  
  191.   return a * gimp_unit_get_factor (gdisp->gimage->unit) / res;
  192. }
  193.  
  194.  
  195. void
  196. setup_scale (GDisplay *gdisp)
  197. {
  198.   GtkRuler *hruler;
  199.   GtkRuler *vruler;
  200.   gfloat sx, sy;
  201.   gfloat stepx, stepy;
  202.  
  203.   sx = SCALEX (gdisp, gdisp->gimage->width);
  204.   sy = SCALEY (gdisp, gdisp->gimage->height);
  205.   stepx = SCALEFACTOR_X (gdisp);
  206.   stepy = SCALEFACTOR_Y (gdisp);
  207.  
  208.   gdisp->hsbdata->value = gdisp->offset_x;
  209.   gdisp->hsbdata->upper = sx;
  210.   gdisp->hsbdata->page_size = MIN (sx, gdisp->disp_width);
  211.   gdisp->hsbdata->page_increment = (gdisp->disp_width / 2);
  212.   gdisp->hsbdata->step_increment = stepx;
  213.  
  214.   gdisp->vsbdata->value = gdisp->offset_y;
  215.   gdisp->vsbdata->upper = sy;
  216.   gdisp->vsbdata->page_size = MIN (sy, gdisp->disp_height);
  217.   gdisp->vsbdata->page_increment = (gdisp->disp_height / 2);
  218.   gdisp->vsbdata->step_increment = stepy;
  219.  
  220.   gtk_signal_emit_by_name (GTK_OBJECT (gdisp->hsbdata), "changed");
  221.   gtk_signal_emit_by_name (GTK_OBJECT (gdisp->vsbdata), "changed");
  222.  
  223.   hruler = GTK_RULER (gdisp->hrule);
  224.   vruler = GTK_RULER (gdisp->vrule);
  225.  
  226.   hruler->lower = 0;
  227.   hruler->upper = img2real (gdisp, TRUE, FUNSCALEX (gdisp, gdisp->disp_width));
  228.   hruler->max_size = img2real (gdisp, TRUE, MAX (gdisp->gimage->width,
  229.                          gdisp->gimage->height));
  230.  
  231.   vruler->lower = 0;
  232.   vruler->upper = img2real(gdisp, FALSE, FUNSCALEY(gdisp, gdisp->disp_height));
  233.   vruler->max_size = img2real (gdisp, FALSE, MAX (gdisp->gimage->width,
  234.                           gdisp->gimage->height));
  235.  
  236.   if (sx < gdisp->disp_width)
  237.     {
  238.       gdisp->disp_xoffset = (gdisp->disp_width - sx) / 2;
  239.       hruler->lower -= img2real(gdisp, TRUE,
  240.                 FUNSCALEX (gdisp, (double) gdisp->disp_xoffset));
  241.       hruler->upper -= img2real(gdisp, TRUE,
  242.                 FUNSCALEX (gdisp, (double) gdisp->disp_xoffset));
  243.     }
  244.   else
  245.     {
  246.       gdisp->disp_xoffset = 0;
  247.       hruler->lower += img2real (gdisp, TRUE,
  248.                  FUNSCALEX (gdisp, (double) gdisp->offset_x));
  249.       hruler->upper += img2real (gdisp, TRUE,
  250.                  FUNSCALEX (gdisp, (double) gdisp->offset_x));
  251.     }
  252.  
  253.   if (sy < gdisp->disp_height)
  254.     {
  255.       gdisp->disp_yoffset = (gdisp->disp_height - sy) / 2;
  256.       vruler->lower -= img2real(gdisp, FALSE,
  257.                 FUNSCALEY (gdisp, (double) gdisp->disp_yoffset));
  258.       vruler->upper -= img2real(gdisp, FALSE,
  259.                 FUNSCALEY (gdisp, (double) gdisp->disp_yoffset));
  260.     }
  261.   else
  262.     {
  263.       gdisp->disp_yoffset = 0;
  264.       vruler->lower += img2real (gdisp, FALSE,
  265.                  FUNSCALEY (gdisp, (double) gdisp->offset_y));
  266.       vruler->upper += img2real (gdisp, FALSE,
  267.                  FUNSCALEY (gdisp, (double) gdisp->offset_y));
  268.     }
  269.  
  270.   gtk_widget_queue_draw (GTK_WIDGET (hruler));
  271.   gtk_widget_queue_draw (GTK_WIDGET (vruler));
  272.  
  273.   nav_window_update_window_marker (gdisp->window_nav_dialog);
  274. }
  275.