home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / shear_tool.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  9.6 KB  |  363 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 <glib.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "drawable.h"
  27. #include "gdisplay.h"
  28. #include "gimage_mask.h"
  29. #include "info_dialog.h"
  30. #include "shear_tool.h"
  31. #include "selection.h"
  32. #include "transform_tool.h"
  33. #include "undo.h"
  34.  
  35. #include "tile_manager_pvt.h"
  36.  
  37. #include "libgimp/gimpintl.h"
  38. #include "libgimp/gimpmath.h"
  39.  
  40. /*  index into trans_info array  */
  41. #define HORZ_OR_VERT 0
  42. #define XSHEAR       1
  43. #define YSHEAR       2
  44.  
  45. /*  the minimum movement before direction of shear can be determined (pixels) */
  46. #define MIN_MOVE     5
  47.  
  48. /*  variables local to this file  */
  49. static gdouble  xshear_val;
  50. static gdouble  yshear_val;
  51.  
  52. /*  forward function declarations  */
  53. static void   shear_tool_recalc  (Tool *, void *);
  54. static void   shear_tool_motion  (Tool *, void *);
  55. static void   shear_info_update  (Tool *);
  56.  
  57. /*  Info dialog callback funtions  */
  58. static void   shear_x_mag_changed (GtkWidget *widget, gpointer data);
  59. static void   shear_y_mag_changed (GtkWidget *widget, gpointer data);
  60.  
  61. TileManager *
  62. shear_tool_transform (Tool           *tool,
  63.               gpointer        gdisp_ptr,
  64.               TransformState  state)
  65. {
  66.   TransformCore *transform_core;
  67.   GDisplay       *gdisp;
  68.  
  69.   transform_core = (TransformCore *) tool->private;
  70.   gdisp = (GDisplay *) gdisp_ptr;
  71.  
  72.   switch (state)
  73.     {
  74.     case INIT:
  75.       if (!transform_info)
  76.     {
  77.       transform_info = info_dialog_new (_("Shear Information"),
  78.                         gimp_standard_help_func,
  79.                         "tools/transform_shear.html");
  80.  
  81.       info_dialog_add_spinbutton (transform_info,
  82.                       _("Shear Magnitude X:"),
  83.                       &xshear_val,
  84.                       -65536, 65536, 1, 15, 1, 1, 0,
  85.                       shear_x_mag_changed, tool);
  86.  
  87.       info_dialog_add_spinbutton (transform_info,
  88.                       _("Y:"),
  89.                       &yshear_val,
  90.                       -65536, 65536, 1, 15, 1, 1, 0,
  91.                       shear_y_mag_changed, tool);
  92.     }
  93.       gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), TRUE);
  94.       transform_core->trans_info[HORZ_OR_VERT] = ORIENTATION_UNKNOWN;
  95.       transform_core->trans_info[XSHEAR] = 0.0;
  96.       transform_core->trans_info[YSHEAR] = 0.0;
  97.  
  98.       return NULL;
  99.       break;
  100.  
  101.     case MOTION:
  102.       shear_tool_motion (tool, gdisp_ptr);
  103.       shear_tool_recalc (tool, gdisp_ptr);
  104.       break;
  105.  
  106.     case RECALC:
  107.       shear_tool_recalc (tool, gdisp_ptr);
  108.       break;
  109.  
  110.     case FINISH:
  111.       gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), FALSE);
  112.       return shear_tool_shear (gdisp->gimage,
  113.                    gimage_active_drawable (gdisp->gimage),
  114.                    gdisp,
  115.                    transform_core->original,
  116.                    transform_tool_smoothing (),
  117.                    transform_core->transform);
  118.       break;
  119.     }
  120.  
  121.   return NULL;
  122. }
  123.  
  124. Tool *
  125. tools_new_shear_tool (void)
  126. {
  127.   Tool          *tool;
  128.   TransformCore *private;
  129.  
  130.   tool = transform_core_new (SHEAR, TRUE);
  131.  
  132.   private = tool->private;
  133.  
  134.   /*  set the rotation specific transformation attributes  */
  135.   private->trans_func = shear_tool_transform;
  136.  
  137.   /*  assemble the transformation matrix  */
  138.   gimp_matrix3_identity (private->transform);
  139.  
  140.   return tool;
  141. }
  142.  
  143. void
  144. tools_free_shear_tool (Tool *tool)
  145. {
  146.   transform_core_free (tool);
  147. }
  148.  
  149. static void
  150. shear_info_update (Tool *tool)
  151. {
  152.   TransformCore *transform_core;
  153.  
  154.   transform_core = (TransformCore *) tool->private;
  155.  
  156.   xshear_val = transform_core->trans_info[XSHEAR];
  157.   yshear_val = transform_core->trans_info[YSHEAR];
  158.  
  159.   info_dialog_update (transform_info);
  160.   info_dialog_popup (transform_info);
  161. }
  162.  
  163. static void
  164. shear_x_mag_changed (GtkWidget *widget,
  165.              gpointer   data)
  166. {
  167.   Tool          *tool;
  168.   TransformCore *transform_core;
  169.   GDisplay      *gdisp;
  170.   gint           value;
  171.  
  172.   tool = (Tool *) data;
  173.  
  174.   if (tool)
  175.     {
  176.       gdisp = (GDisplay *) tool->gdisp_ptr;
  177.       transform_core = (TransformCore *) tool->private;
  178.  
  179.       value = GTK_ADJUSTMENT (widget)->value;
  180.  
  181.       if (value != transform_core->trans_info[XSHEAR])
  182.     {
  183.       draw_core_pause (transform_core->core, tool);
  184.       transform_core->trans_info[XSHEAR] = value;
  185.       shear_tool_recalc (tool, gdisp);
  186.       draw_core_resume (transform_core->core, tool);
  187.     }
  188.     }
  189. }
  190.  
  191. static void
  192. shear_y_mag_changed (GtkWidget *widget,
  193.              gpointer   data)
  194. {
  195.   Tool          *tool;
  196.   TransformCore *transform_core;
  197.   GDisplay      *gdisp;
  198.   gint           value;
  199.  
  200.   tool = (Tool *) data;
  201.  
  202.   if (tool)
  203.     {
  204.       gdisp = (GDisplay *) tool->gdisp_ptr;
  205.       transform_core = (TransformCore *) tool->private;
  206.  
  207.       value = GTK_ADJUSTMENT (widget)->value;
  208.  
  209.       if (value != transform_core->trans_info[YSHEAR])
  210.     {
  211.       draw_core_pause (transform_core->core, tool);
  212.       transform_core->trans_info[YSHEAR] = value;
  213.       shear_tool_recalc (tool, gdisp);
  214.       draw_core_resume (transform_core->core, tool);
  215.     }
  216.     }
  217. }
  218.  
  219. static void
  220. shear_tool_motion (Tool *tool,
  221.            void *gdisp_ptr)
  222. {
  223.   TransformCore *transform_core;
  224.   gint           diffx, diffy;
  225.   gint           dir;
  226.  
  227.   transform_core = (TransformCore *) tool->private;
  228.  
  229.   diffx = transform_core->curx - transform_core->lastx;
  230.   diffy = transform_core->cury - transform_core->lasty;
  231.  
  232.   /*  If we haven't yet decided on which way to control shearing
  233.    *  decide using the maximum differential
  234.    */
  235.  
  236.   if (transform_core->trans_info[HORZ_OR_VERT] == ORIENTATION_UNKNOWN)
  237.     {
  238.       if (abs (diffx) > MIN_MOVE || abs (diffy) > MIN_MOVE)
  239.     {
  240.       if (abs (diffx) > abs (diffy))
  241.         {
  242.           transform_core->trans_info[HORZ_OR_VERT] = ORIENTATION_HORIZONTAL;
  243.           transform_core->trans_info[ORIENTATION_VERTICAL] = 0.0;
  244.         }
  245.       else
  246.         {
  247.           transform_core->trans_info[HORZ_OR_VERT] = ORIENTATION_VERTICAL;
  248.           transform_core->trans_info[ORIENTATION_HORIZONTAL] = 0.0;
  249.         }
  250.     }
  251.       /*  set the current coords to the last ones  */
  252.       else
  253.     {
  254.       transform_core->curx = transform_core->lastx;
  255.       transform_core->cury = transform_core->lasty;
  256.     }
  257.     }
  258.  
  259.   /*  if the direction is known, keep track of the magnitude  */
  260.   if (transform_core->trans_info[HORZ_OR_VERT] != ORIENTATION_UNKNOWN)
  261.     {
  262.       dir = transform_core->trans_info[HORZ_OR_VERT];
  263.       switch (transform_core->function)
  264.     {
  265.     case HANDLE_1:
  266.       if (dir == ORIENTATION_HORIZONTAL)
  267.         transform_core->trans_info[XSHEAR] -= diffx;
  268.       else
  269.         transform_core->trans_info[YSHEAR] -= diffy;
  270.       break;
  271.     case HANDLE_2:
  272.       if (dir == ORIENTATION_HORIZONTAL)
  273.         transform_core->trans_info[XSHEAR] -= diffx;
  274.       else
  275.         transform_core->trans_info[YSHEAR] += diffy;
  276.       break;
  277.     case HANDLE_3:
  278.       if (dir == ORIENTATION_HORIZONTAL)
  279.         transform_core->trans_info[XSHEAR] += diffx;
  280.       else
  281.         transform_core->trans_info[YSHEAR] -= diffy;
  282.       break;
  283.     case HANDLE_4:
  284.       if (dir == ORIENTATION_HORIZONTAL)
  285.         transform_core->trans_info[XSHEAR] += diffx;
  286.       else
  287.         transform_core->trans_info[YSHEAR] += diffy;
  288.       break;
  289.     default:
  290.       break;
  291.     }
  292.     }
  293. }
  294.  
  295. static void
  296. shear_tool_recalc (Tool *tool,
  297.            void *gdisp_ptr)
  298. {
  299.   TransformCore *transform_core;
  300.   GDisplay      *gdisp;
  301.   gfloat         width, height;
  302.   gfloat         cx, cy;
  303.  
  304.   gdisp = (GDisplay *) tool->gdisp_ptr;
  305.   transform_core = (TransformCore *) tool->private;
  306.  
  307.   cx = (transform_core->x1 + transform_core->x2) / 2.0;
  308.   cy = (transform_core->y1 + transform_core->y2) / 2.0;
  309.  
  310.   width = transform_core->x2 - transform_core->x1;
  311.   height = transform_core->y2 - transform_core->y1;
  312.  
  313.   if (width == 0)
  314.     width = 1;
  315.   if (height == 0)
  316.     height = 1;
  317.  
  318.   /*  assemble the transformation matrix  */
  319.   gimp_matrix3_identity  (transform_core->transform);
  320.   gimp_matrix3_translate (transform_core->transform, -cx, -cy);
  321.  
  322.   /*  shear matrix  */
  323.   if (transform_core->trans_info[HORZ_OR_VERT] == ORIENTATION_HORIZONTAL)
  324.     gimp_matrix3_xshear (transform_core->transform,
  325.              (float) transform_core->trans_info [XSHEAR] / height);
  326.   else
  327.     gimp_matrix3_yshear (transform_core->transform,
  328.              (float) transform_core->trans_info [YSHEAR] / width);
  329.  
  330.   gimp_matrix3_translate (transform_core->transform, +cx, +cy);
  331.  
  332.   /*  transform the bounding box  */
  333.   transform_core_transform_bounding_box (tool);
  334.  
  335.   /*  update the information dialog  */
  336.   shear_info_update (tool);
  337. }
  338.  
  339. TileManager *
  340. shear_tool_shear (GimpImage    *gimage,
  341.           GimpDrawable *drawable,
  342.           GDisplay     *gdisp,
  343.           TileManager  *float_tiles,
  344.           gboolean      interpolation,
  345.           GimpMatrix3   matrix)
  346. {
  347.   gimp_progress *progress;
  348.   TileManager   *ret;
  349.  
  350.   progress = progress_start (gdisp, _("Shearing..."), FALSE, NULL, NULL);
  351.  
  352.   ret = transform_core_do (gimage, drawable, float_tiles,
  353.                interpolation, matrix,
  354.                progress ? progress_update_and_flush :
  355.                (progress_func_t) NULL,
  356.                progress);
  357.  
  358.   if (progress)
  359.     progress_end (progress);
  360.  
  361.   return ret;
  362. }
  363.