gimptransformtool.c 57.5 KB
Newer Older
Nate Summers's avatar
Nate Summers committed
1
/* The GIMP -- an image manipulation program
Nate Summers's avatar
Nate Summers committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
 *
 * 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
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

#include <stdlib.h>

#include <gtk/gtk.h>

#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "apptypes.h"

30 31
#include "paint-funcs/paint-funcs.h"

Nate Summers's avatar
Nate Summers committed
32 33 34 35 36 37
#include "cursorutil.h"
#include "drawable.h"
#include "floating_sel.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "gimpchannel.h"
38
#include "gimpcontext.h"
Nate Summers's avatar
Nate Summers committed
39 40
#include "gimpimage.h"
#include "gimplayer.h"
Nate Summers's avatar
Nate Summers committed
41
#include "gimpmarshal.h"
Nate Summers's avatar
Nate Summers committed
42 43 44 45 46
#include "gimprc.h"
#include "gimpui.h"
#include "info_dialog.h"
#include "path_transform.h"
#include "pixel_region.h"
47
#include "pixel_surround.h"
Nate Summers's avatar
Nate Summers committed
48 49 50 51
#include "undo.h"
#include "tile_manager.h"
#include "tile.h"

Nate Summers's avatar
Nate Summers committed
52
#include "tools/gimptool.h"
53
#include "tools/gimptoolinfo.h"
Nate Summers's avatar
Nate Summers committed
54
#include "tools/tool_manager.h"
55
#include "tools/tool_options.h"
Nate Summers's avatar
Nate Summers committed
56 57
#include "tools/gimpdrawtool.h"
#include "tools/gimptransformtool.h"
58 59 60 61 62

#include "tools/gimpperspectivetool.h"
#include "tools/gimprotatetool.h"
#include "tools/gimpscaletool.h"
#include "tools/gimpsheartool.h"
63
#include "tools/gimpfliptool.h"
Nate Summers's avatar
Nate Summers committed
64 65 66 67 68 69 70

#include "libgimp/gimpintl.h"

enum
{
  TRANSFORM,
  LAST_SIGNAL
Nate Summers's avatar
Nate Summers committed
71
};
Nate Summers's avatar
Nate Summers committed
72

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

typedef struct _TransformOptions TransformOptions;

struct _TransformOptions
{
  ToolOptions  tool_options;

  GtkType      type;
  GtkType      type_d;
  GtkWidget   *type_w[4];  /* 4 radio buttons */

  gboolean     smoothing;
  gboolean     smoothing_d;
  GtkWidget   *smoothing_w;

  gint	       direction;
  gint         direction_d;
  GtkWidget   *direction_w[2];  /* 2 radio buttons */

  gboolean     show_grid;
  gboolean     show_grid_d;
  GtkWidget   *show_grid_w;

  gint	       grid_size;
  gint         grid_size_d;
  GtkObject   *grid_size_w;

  gboolean     clip;
  gboolean     clip_d;
  GtkWidget   *clip_w;

  gboolean     showpath;
  gboolean     showpath_d;
  GtkWidget   *showpath_w;
};

Nate Summers's avatar
Nate Summers committed
109 110 111 112 113 114
#define BILINEAR(jk,j1k,jk1,j1k1,dx,dy) \
                ((1-dy) * (jk + dx * (j1k - jk)) + \
		    dy  * (jk1 + dx * (j1k1 - jk1)))

/* access interleaved pixels */
#define CUBIC_ROW(dx, row, step) \
Nate Summers's avatar
Nate Summers committed
115
  gimp_transform_tool_cubic(dx, (row)[0], (row)[step], (row)[step+step], (row)[step+step+step])
Nate Summers's avatar
Nate Summers committed
116
#define CUBIC_SCALED_ROW(dx, row, step, i) \
Nate Summers's avatar
Nate Summers committed
117
  gimp_transform_tool_cubic(dx, (row)[0] * (row)[i], \
Nate Summers's avatar
Nate Summers committed
118 119 120 121 122 123 124 125
            (row)[step] * (row)[step + i], \
            (row)[step+step]* (row)[step+step + i], \
            (row)[step+step+step] * (row)[step+step+step + i])

#define REF_TILE(i,x,y) \
     tile[i] = tile_manager_get_tile (float_tiles, x, y, TRUE, FALSE); \
     src[i] = tile_data_pointer (tile[i], (x) % TILE_WIDTH, (y) % TILE_HEIGHT);

126

Nate Summers's avatar
Nate Summers committed
127
/*  forward function declarations  */
Nate Summers's avatar
Nate Summers committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
static void      gimp_transform_tool_bounds    (GimpTransformTool      *tool,
                                                GDisplay               *gdisp);
static void      gimp_transform_tool_recalc    (GimpTransformTool      *tool,
					        GDisplay               *gdisp);
static void      gimp_transform_tool_doit      (GimpTransformTool      *tool,
					        GDisplay               *gdisp);
static gdouble   gimp_transform_tool_cubic     (gdouble                 dx,
					        gint                    jm1,
					        gint                    j,
					        gint                    jp1,
					        gint                    jp2);
static void    gimp_transform_tool_setup_grid  (GimpTransformTool      *tool);
static void    gimp_transform_tool_grid_recalc (GimpTransformTool      *gimp_transform_tool);
static void    gimp_transform_tool_init        (GimpTransformTool      *tool);
static void    gimp_transform_tool_class_init  (GimpTransformToolClass *tool);
Nate Summers's avatar
Nate Summers committed
143

144 145 146
static void    gimp_transform_tool_destroy     (GtkObject              *object);

static void   gimp_transform_tool_button_press (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
147 148 149
                                                GdkEventButton         *bevent,
			                        GDisplay               *gdisp);
			          
150
static void gimp_transform_tool_button_release (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
151 152 153
			                        GdkEventButton         *bevent,
			                        GDisplay               *gdisp);
			                        
154
static void    gimp_transform_tool_motion      (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
155 156 157
		                                GdkEventMotion         *mevent,
		                                GDisplay               *gdisp);
		                                
158
static void  gimp_transform_tool_cursor_update (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
159 160 161
	                 		        GdkEventMotion         *mevent,
			                        GDisplay               *gdisp);
			                        
162
static void    gimp_transform_tool_control     (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
163 164
			                        ToolAction              action,
			                        GDisplay               *gdisp);
165 166 167

static void    gimp_transform_tool_draw        (GimpDrawTool           *draw_tool);

168
static void    gimp_transform_tool_change_type (GtkType new_type);
Nate Summers's avatar
Nate Summers committed
169

170
static TransformOptions * transform_options_new   (void);
171
static void               transform_options_reset (ToolOptions *tool_options);
172 173


Nate Summers's avatar
Nate Summers committed
174
/*  variables  */
Nate Summers's avatar
Nate Summers committed
175 176 177 178
static TranInfo           old_trans_info;
InfoDialog               *transform_info        = NULL;
static gboolean           transform_info_inited = FALSE;
static GimpDrawToolClass *parent_class          = NULL;
179
static TransformOptions  *transform_options     = NULL;
Nate Summers's avatar
Nate Summers committed
180
static guint gimp_transform_tool_signals[LAST_SIGNAL] = { 0 };
Nate Summers's avatar
Nate Summers committed
181

182

Nate Summers's avatar
Nate Summers committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
GtkType
gimp_transform_tool_get_type (void)
{
  static GtkType tool_type = 0;

  if (! tool_type)
    {
      GtkTypeInfo tool_info =
      {
        "GimpTransformTool",
        sizeof (GimpTransformTool),
        sizeof (GimpTransformToolClass),
        (GtkClassInitFunc) gimp_transform_tool_class_init,
        (GtkObjectInitFunc) gimp_transform_tool_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        NULL /* (GtkClassInitFunc) gimp_tool_class_init, */
      };

      tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info);
    }

  return tool_type;
}

static void
gimp_transform_tool_class_init (GimpTransformToolClass *klass)
{
Nate Summers's avatar
Nate Summers committed
211 212 213
  GtkObjectClass    *object_class;
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_class;
Nate Summers's avatar
Nate Summers committed
214 215 216

  object_class = (GtkObjectClass *) klass;
  tool_class   = (GimpToolClass *) klass;
Nate Summers's avatar
Nate Summers committed
217
  draw_class   = (GimpDrawToolClass *) klass;
Nate Summers's avatar
Nate Summers committed
218 219 220 221 222

  parent_class = gtk_type_class (GIMP_TYPE_DRAW_TOOL);

  gimp_transform_tool_signals[TRANSFORM] =
    gtk_signal_new ("transform",
Nate Summers's avatar
Nate Summers committed
223
    		    GTK_RUN_LAST,
Nate Summers's avatar
Nate Summers committed
224 225 226
    		    object_class->type,
    		    GTK_SIGNAL_OFFSET (GimpTransformToolClass,
    		    		       transform),
Nate Summers's avatar
Nate Summers committed
227
    		    gimp_marshal_POINTER__POINTER_INT,
Nate Summers's avatar
Nate Summers committed
228 229 230 231 232 233 234
    		    GTK_TYPE_POINTER, 2,
    		    GTK_TYPE_POINTER,
    		    GTK_TYPE_INT);

  gtk_object_class_add_signals (object_class, gimp_transform_tool_signals,
				LAST_SIGNAL);

Nate Summers's avatar
Nate Summers committed
235
  object_class->destroy      = gimp_transform_tool_destroy;
Nate Summers's avatar
Nate Summers committed
236 237 238 239 240 241

  tool_class->button_press   = gimp_transform_tool_button_press;
  tool_class->button_release = gimp_transform_tool_button_release;
  tool_class->motion         = gimp_transform_tool_motion;
  tool_class->cursor_update  = gimp_transform_tool_cursor_update;
  tool_class->control        = gimp_transform_tool_control;
Nate Summers's avatar
Nate Summers committed
242 243

  draw_class->draw           = gimp_transform_tool_draw;
Nate Summers's avatar
Nate Summers committed
244 245 246
}

static void
Nate Summers's avatar
Nate Summers committed
247
gimp_transform_tool_init (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
248
{
249 250
  GimpTool *tool = GIMP_TOOL (tr_tool);
  gint      i;
Nate Summers's avatar
Nate Summers committed
251 252 253 254 255 256 257 258 259 260 261

  tr_tool->function = TRANSFORM_CREATING;
  tr_tool->original = NULL;

  tr_tool->bpressed = FALSE;

  for (i = 0; i < TRAN_INFO_SIZE; i++)
    tr_tool->trans_info[i] = 0;

  tr_tool->grid_coords = tr_tool->tgrid_coords = NULL;

262 263 264
  /* FIXME */
  tr_tool->interactive = TRUE;

Nate Summers's avatar
Nate Summers committed
265 266
  tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

  if (! transform_options)
    {
      transform_options = transform_options_new ();

      tool_manager_register_tool_options (GIMP_TYPE_ROTATE_TOOL,
					  (ToolOptions *) transform_options);
      tool_manager_register_tool_options (GIMP_TYPE_SCALE_TOOL,
					  (ToolOptions *) transform_options);
      tool_manager_register_tool_options (GIMP_TYPE_SHEAR_TOOL,
					  (ToolOptions *) transform_options);
      tool_manager_register_tool_options (GIMP_TYPE_PERSPECTIVE_TOOL,
					  (ToolOptions *) transform_options);

      /*  press all default buttons  */
282
      transform_options_reset ((ToolOptions *) transform_options);
283
    }
Nate Summers's avatar
Nate Summers committed
284 285
}

Nate Summers's avatar
Nate Summers committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
TileManager *
gimp_transform_tool_transform (GimpTransformTool   *tool,
                               GDisplay            *gdisp,
			       TransformState       state)
{
  TileManager *retval;

  g_return_val_if_fail (tool, NULL);
  g_return_val_if_fail (GIMP_IS_TRANSFORM_TOOL (tool), NULL);

  gtk_signal_emit (GTK_OBJECT (tool), gimp_transform_tool_signals[TRANSFORM],
                   gdisp, state, &retval);

  return retval;
}

Nate Summers's avatar
Nate Summers committed
302 303 304 305
static void
transform_ok_callback (GtkWidget *widget,
		       gpointer   data)
{
Nate Summers's avatar
Nate Summers committed
306
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
307

Nate Summers's avatar
Nate Summers committed
308 309
  tool = GIMP_TOOL(data);
  gimp_transform_tool_doit (GIMP_TRANSFORM_TOOL(tool), tool->gdisp);
Nate Summers's avatar
Nate Summers committed
310 311 312 313 314 315 316 317 318 319
}

static void
transform_reset_callback (GtkWidget *widget,
			  gpointer   data)
{
  GimpTransformTool   *tool;
  GimpDrawTool        *dr_tool;
  gint                 i;

320 321
  tool    = GIMP_TRANSFORM_TOOL (data);
  dr_tool = GIMP_DRAW_TOOL (data);
Nate Summers's avatar
Nate Summers committed
322 323

  /*  stop the current tool drawing process  */
Nate Summers's avatar
Nate Summers committed
324
  gimp_draw_tool_pause (dr_tool);
Nate Summers's avatar
Nate Summers committed
325 326 327 328 329 330

  /*  Restore the previous transformation info  */
  for (i = 0; i < TRAN_INFO_SIZE; i++)
    tool->trans_info [i] = old_trans_info [i];

  /*  recalculate the tool's transformation matrix  */
Nate Summers's avatar
Nate Summers committed
331
  gimp_transform_tool_recalc (tool, GIMP_TOOL(tool)->gdisp);
Nate Summers's avatar
Nate Summers committed
332 333

  /*  resume drawing the current tool  */
Nate Summers's avatar
Nate Summers committed
334
  gimp_draw_tool_resume (dr_tool);
Nate Summers's avatar
Nate Summers committed
335 336
}

337 338
static void
gimp_transform_tool_destroy (GtkObject *object)
Nate Summers's avatar
Nate Summers committed
339
{
340 341
  GimpTransformTool *tr_tool;
  GimpTool          *tool;
Nate Summers's avatar
Nate Summers committed
342

343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
  tr_tool = GIMP_TRANSFORM_TOOL (object);
  tool    = GIMP_TOOL           (tr_tool);

  /*  Free up the original selection if it exists  */
  if (tr_tool->original)
    tile_manager_destroy (tr_tool->original);

  /*  If there is an information dialog, free it up  */
  if (transform_info)
    info_dialog_free (transform_info);

  transform_info        = NULL;
  transform_info_inited = FALSE;

  /*  Free the grid line endpoint arrays if they exist */
  if (tr_tool->grid_coords != NULL)
    g_free (tr_tool->grid_coords);

  if (tr_tool->tgrid_coords != NULL)
    g_free (tr_tool->tgrid_coords);

  if (GTK_OBJECT_CLASS (parent_class)->destroy)
    GTK_OBJECT_CLASS (parent_class)->destroy (object);
}

static void
Nate Summers's avatar
Nate Summers committed
369
gimp_transform_tool_button_press (GimpTool           *tool,
Nate Summers's avatar
Nate Summers committed
370 371 372
                                  GdkEventButton     *bevent,
			          GDisplay           *gdisp)
{
Nate Summers's avatar
Nate Summers committed
373 374 375 376 377 378 379
  GimpTransformTool  *gt_tool;
  GimpDrawable       *drawable;
  gint                dist;
  gint                closest_dist;
  gint                x, y;
  gint                i;
  gint                off_x, off_y;
Nate Summers's avatar
Nate Summers committed
380

381
  gt_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

  gt_tool->bpressed = TRUE; /* ALT */

  drawable = gimp_image_active_drawable (gdisp->gimage);

  if (gt_tool->function == TRANSFORM_CREATING && tool->state == ACTIVE)
    {
      /*  Save the current transformation info  */
      for (i = 0; i < TRAN_INFO_SIZE; i++)
	old_trans_info [i] = gt_tool->trans_info [i];
    }

  /*  if we have already displayed the bounding box and handles,
   *  check to make sure that the display which currently owns the
   *  tool is the one which just received the button pressed event
   */
  if ((gdisp == tool->gdisp) && gt_tool->interactive)
    {
      /*  start drawing the bounding box and handles...  */
401 402
      gimp_draw_tool_start (GIMP_DRAW_TOOL (gt_tool), gdisp->canvas->window);

Nate Summers's avatar
Nate Summers committed
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
      x = bevent->x;
      y = bevent->y;

      closest_dist = SQR (x - gt_tool->sx1) + SQR (y - gt_tool->sy1);
      gt_tool->function = TRANSFORM_HANDLE_1;

      dist = SQR (x - gt_tool->sx2) + SQR (y - gt_tool->sy2);
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  gt_tool->function = TRANSFORM_HANDLE_2;
	}

      dist = SQR (x - gt_tool->sx3) + SQR (y - gt_tool->sy3);
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  gt_tool->function = TRANSFORM_HANDLE_3;
	}

      dist = SQR (x - gt_tool->sx4) + SQR (y - gt_tool->sy4);
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  gt_tool->function = TRANSFORM_HANDLE_4;
	}

430 431
      if ((SQR (x - gt_tool->scx) +
	   SQR (y - gt_tool->scy)) <= 100)
Nate Summers's avatar
Nate Summers committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
	{
	  gt_tool->function = TRANSFORM_HANDLE_CENTER;
	}

      /*  Save the current pointer position  */
      gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
				   &gt_tool->startx,
				   &gt_tool->starty, TRUE, 0);
      gt_tool->lastx = gt_tool->startx;
      gt_tool->lasty = gt_tool->starty;

      gdk_pointer_grab (gdisp->canvas->window, FALSE,
			GDK_POINTER_MOTION_HINT_MASK |
			GDK_BUTTON1_MOTION_MASK |
			GDK_BUTTON_RELEASE_MASK,
			NULL, NULL, bevent->time);

      tool->state = ACTIVE;
      return;
    }


  /*  Initialisation stuff: if the cursor is clicked inside the current
   *  selection, show the bounding box and handles...
   */
  gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y,
			       FALSE, FALSE);

  gimp_drawable_offsets (drawable, &off_x, &off_y);
  if (x >= off_x && y >= off_y &&
      x < (off_x + gimp_drawable_width (drawable)) &&
      y < (off_y + gimp_drawable_height (drawable)))
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
    {
      if (gimage_mask_is_empty (gdisp->gimage) ||
	  gimage_mask_value (gdisp->gimage, x, y))
	{
	  if (GIMP_IS_LAYER (drawable) &&
	      gimp_layer_get_mask (GIMP_LAYER (drawable)))
	    {
	      g_message (_("Transformations do not work on\n"
			   "layers that contain layer masks."));
	      tool->state = INACTIVE;
	      return;
	    }

	  /*  If the tool is already active, clear the current state
	   *  and reset
	   */
	  if (tool->state == ACTIVE)
	    gimp_transform_tool_reset (gt_tool, gdisp);

	  /*  Set the pointer to the active display  */
	  tool->gdisp    = gdisp;
	  tool->drawable = drawable;
	  tool->state    = ACTIVE;

	  /*  Grab the pointer if we're in non-interactive mode  */
	  if (!gt_tool->interactive)
	    gdk_pointer_grab (gdisp->canvas->window, FALSE,
			      (GDK_POINTER_MOTION_HINT_MASK |
			       GDK_BUTTON1_MOTION_MASK |
			       GDK_BUTTON_RELEASE_MASK),
			      NULL, NULL, bevent->time);

	  /*  Find the transform bounds for some tools (like scale,
	   *  perspective) that actually need the bounds for
	   *  initializing
	   */
	  gimp_transform_tool_bounds (gt_tool, gdisp);

	  /*  Calculate the grid line endpoints  */
	  if (gimp_transform_tool_show_grid ())
	    gimp_transform_tool_setup_grid (gt_tool);

	  /*  Initialize the transform tool */
	  gimp_transform_tool_transform (gt_tool, gdisp, TRANSFORM_INIT);

	  if (transform_info && !transform_info_inited)
	    {
	      GtkType tool_type;

	      tool_type =
		gimp_context_get_tool (gimp_context_get_user ())->tool_type;

	      gimp_dialog_create_action_area
		(GTK_DIALOG (transform_info->shell),

		 /* FIXME: this does not belong here */
		 (tool_type == GIMP_TYPE_ROTATE_TOOL)      ? _("Rotate")    :
		 (tool_type == GIMP_TYPE_SCALE_TOOL)       ? _("Scale")     :
		 (tool_type == GIMP_TYPE_SHEAR_TOOL)       ? _("Shear")     :
		 (tool_type == GIMP_TYPE_PERSPECTIVE_TOOL) ? _("Transform") :
		 "EEK",
		 transform_ok_callback,
		 tool, NULL, NULL, TRUE, FALSE,

		 _("Reset"), transform_reset_callback,
		 tool, NULL, NULL, FALSE, FALSE,

		 NULL);

	      transform_info_inited = TRUE;
	    }

	  /*  Recalculate the transform tool  */
	  gimp_transform_tool_recalc (gt_tool, gdisp);

	  /*  recall this function to find which handle we're dragging  */
	  if (gt_tool->interactive)
	    gimp_transform_tool_button_press (tool, bevent, gdisp);
	}
    }
Nate Summers's avatar
Nate Summers committed
544 545
}

546
static void
Nate Summers's avatar
Nate Summers committed
547 548 549
gimp_transform_tool_button_release (GimpTool         *tool,
			            GdkEventButton   *bevent,
			            GDisplay         *gdisp)
Nate Summers's avatar
Nate Summers committed
550
{
Nate Summers's avatar
Nate Summers committed
551 552
  GimpTransformTool *gt_tool;
  gint               i;
Nate Summers's avatar
Nate Summers committed
553

554
  gt_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
555 556 557 558

  gt_tool->bpressed = FALSE; /* ALT */

  /*  if we are creating, there is nothing to be done...exit  */
559
  if (gt_tool->function == TRANSFORM_CREATING && gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
560 561 562 563 564 565 566 567 568 569
    return;

  /*  release of the pointer grab  */
  gdk_pointer_ungrab (bevent->time);
  gdk_flush ();

  /*  if the 3rd button isn't pressed, transform the selected mask  */
  if (! (bevent->state & GDK_BUTTON3_MASK))
    {
      /* Shift-clicking is another way to approve the transform  */
570
      if ((bevent->state & GDK_SHIFT_MASK) || GIMP_IS_FLIP_TOOL (tool))
Nate Summers's avatar
Nate Summers committed
571
	{
Nate Summers's avatar
Nate Summers committed
572
	  gimp_transform_tool_doit (gt_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
573 574 575 576 577 578 579 580 581 582 583
	}
      else
	{
	  /*  Only update the paths preview */
	  path_transform_current_path (gdisp->gimage,
				       gt_tool->transform, TRUE);
	}
    }
  else
    {
      /*  stop the current tool drawing process  */
584
      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
585 586 587 588 589 590 591 592 593

      /*  Restore the previous transformation info  */
      for (i = 0; i < TRAN_INFO_SIZE; i++)
	gt_tool->trans_info [i] = old_trans_info [i];

      /*  recalculate the tool's transformation matrix  */
      gimp_transform_tool_recalc (gt_tool, gdisp);

      /*  resume drawing the current tool  */
594
      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
595 596 597 598 599 600 601 602 603 604 605

      /* Update the paths preview */
      path_transform_current_path (gdisp->gimage,
				   gt_tool->transform, TRUE);
    }

  /*  if this tool is non-interactive, make it inactive after use  */
  if (!gt_tool->interactive)
    tool->state = INACTIVE;
}

606
static void
Nate Summers's avatar
Nate Summers committed
607 608 609 610 611 612 613 614 615 616 617 618
gimp_transform_tool_doit (GimpTransformTool  *gt_tool,
		          GDisplay           *gdisp)
{
  GimpTool      *tool;
  TileManager   *new_tiles;
  TransformUndo *tu;
  PathUndo      *pundo;
  gboolean       new_layer;
  gint           i, x, y;

  gimp_add_busy_cursors ();

619
  tool = GIMP_TOOL (gt_tool);
Nate Summers's avatar
Nate Summers committed
620 621

  /* undraw the tool before we muck around with the transform matrix */
622
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (gt_tool));
Nate Summers's avatar
Nate Summers committed
623 624 625 626 627 628 629 630 631

  /*  We're going to dirty this image, but we want to keep the tool
   *  around
   */
  tool->preserve = TRUE;

  /*  Start a transform undo group  */
  undo_push_group_start (gdisp->gimage, TRANSFORM_CORE_UNDO);

632 633 634
  /* With the old UI, if original is NULL, then this is the
   * first transformation. In the new UI, it is always so, right?
   */
Nate Summers's avatar
Nate Summers committed
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
  g_assert (gt_tool->original == NULL);

  /* If we're in interactive mode, we need to copy the current
   *  selection to the transform tool's private selection pointer, so
   *  that the original source can be repeatedly modified.
   */
  tool->drawable = gimp_image_active_drawable (gdisp->gimage);

  gt_tool->original = gimp_transform_tool_cut (gdisp->gimage,
					       tool->drawable,
					       &new_layer);

  pundo = path_transform_start_undo (gdisp->gimage);

  /*  Send the request for the transformation to the tool...
   */
Nate Summers's avatar
Nate Summers committed
651
  new_tiles = gimp_transform_tool_transform (gt_tool, gdisp,
652
					     TRANSFORM_FINISH);
Nate Summers's avatar
Nate Summers committed
653

Nate Summers's avatar
Nate Summers committed
654
  gimp_transform_tool_transform (gt_tool, gdisp, TRANSFORM_INIT);
Nate Summers's avatar
Nate Summers committed
655 656 657 658 659 660 661 662 663 664

  gimp_transform_tool_recalc (gt_tool, gdisp);

  if (new_tiles)
    {
      /*  paste the new transformed image to the gimage...also implement
       *  undo...
       */
      /*  FIXME: we should check if the drawable is still valid  */
      gimp_transform_tool_paste (gdisp->gimage, tool->drawable,
665
				 new_tiles, new_layer);
Nate Summers's avatar
Nate Summers committed
666 667

      /*  create and initialize the transform_undo structure  */
668 669 670
      tu = g_new0 (TransformUndo, 1);
      tu->tool_ID   = tool->ID;
      tu->tool_type = GTK_OBJECT (tool)->klass->type;
Nate Summers's avatar
Nate Summers committed
671

Nate Summers's avatar
Nate Summers committed
672 673
      for (i = 0; i < TRAN_INFO_SIZE; i++)
	tu->trans_info[i] = old_trans_info[i];
674 675

      tu->original  = NULL;
Nate Summers's avatar
Nate Summers committed
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
      tu->path_undo = pundo;

      /*  Make a note of the new current drawable (since we may have
       *  a floating selection, etc now.
       */
      tool->drawable = gimp_image_active_drawable (gdisp->gimage);

      undo_push_transform (gdisp->gimage, (void *) tu);
    }

  /*  push the undo group end  */
  undo_push_group_end (gdisp->gimage);

  /*  We're done dirtying the image, and would like to be restarted
   *  if the image gets dirty while the tool exists
   */
  tool->preserve = FALSE;

  /*  Flush the gdisplays  */
  if (gdisp->disp_xoffset || gdisp->disp_yoffset)
    {
      gdk_window_get_size (gdisp->canvas->window, &x, &y);
      if (gdisp->disp_yoffset)
	{
	  gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_width,
				gdisp->disp_yoffset);
	  gdisplay_expose_area (gdisp, 0, gdisp->disp_yoffset + y,
				gdisp->disp_width, gdisp->disp_height);
	}
      if (gdisp->disp_xoffset)
	{
	  gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_xoffset,
				gdisp->disp_height);
	  gdisplay_expose_area (gdisp, gdisp->disp_xoffset + x, 0,
				gdisp->disp_width, gdisp->disp_height);
	}
    }

  gimp_remove_busy_cursors (NULL);

  gdisplays_flush ();

718
  gimp_transform_tool_reset (gt_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
719 720

  /*  if this tool is non-interactive, make it inactive after use  */
Nate Summers's avatar
Nate Summers committed
721
  if (!gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
722 723 724
    tool->state = INACTIVE;
}

725
static void
Nate Summers's avatar
Nate Summers committed
726 727 728
gimp_transform_tool_motion (GimpTool          *tool,
		            GdkEventMotion    *mevent,
		            GDisplay          *gdisp)
Nate Summers's avatar
Nate Summers committed
729
{
Nate Summers's avatar
Nate Summers committed
730
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
731

732
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
733

734
  if (! tr_tool->bpressed)
Nate Summers's avatar
Nate Summers committed
735 736 737 738 739
    return;

  /*  if we are creating or this tool is non-interactive, there is
   *  nothing to be done so exit.
   */
Nate Summers's avatar
Nate Summers committed
740 741
  if (tr_tool->function == TRANSFORM_CREATING ||
      !tr_tool->interactive)
Nate Summers's avatar
Nate Summers committed
742 743 744
    return;

  /*  stop the current tool drawing process  */
745
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
746 747

  gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
Nate Summers's avatar
Nate Summers committed
748 749 750
			       &tr_tool->curx,
			       &tr_tool->cury, TRUE, 0);
  tr_tool->state = mevent->state;
Nate Summers's avatar
Nate Summers committed
751 752

  /*  recalculate the tool's transformation matrix  */
Nate Summers's avatar
Nate Summers committed
753
  gimp_transform_tool_transform (tr_tool, gdisp, TRANSFORM_MOTION);
Nate Summers's avatar
Nate Summers committed
754

Nate Summers's avatar
Nate Summers committed
755 756
  tr_tool->lastx = tr_tool->curx;
  tr_tool->lasty = tr_tool->cury;
Nate Summers's avatar
Nate Summers committed
757 758

  /*  resume drawing the current tool  */
759
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
760 761
}

762
static void
Nate Summers's avatar
Nate Summers committed
763
gimp_transform_tool_cursor_update (GimpTool           *tool,
Nate Summers's avatar
Nate Summers committed
764 765
			           GdkEventMotion     *mevent,
			           GDisplay           *gdisp)
Nate Summers's avatar
Nate Summers committed
766
{
Nate Summers's avatar
Nate Summers committed
767 768 769 770
  GimpTransformTool  *tr_tool;
  GimpDrawable       *drawable;
  GdkCursorType       ctype = GDK_TOP_LEFT_ARROW;
  gint                x, y;
Nate Summers's avatar
Nate Summers committed
771

772
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802

  gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
			       FALSE, FALSE);

  if ((drawable = gimp_image_active_drawable (gdisp->gimage)))
    {
      if (GIMP_IS_LAYER (drawable) &&
	  gimp_layer_get_mask (GIMP_LAYER (drawable)))
	{
	  ctype = GIMP_BAD_CURSOR;
	}
      else if (x >= drawable->offset_x &&
	       y >= drawable->offset_y &&
	       x < (drawable->offset_x + drawable->width) &&
	       y < (drawable->offset_y + drawable->height))
	{
	  if (gimage_mask_is_empty (gdisp->gimage) ||
	      gimage_mask_value (gdisp->gimage, x, y))
	    {
	      ctype = GIMP_MOUSE_CURSOR;
	    }
	}
    }

  gdisplay_install_tool_cursor (gdisp,
				ctype,
				tool->tool_cursor,
				GIMP_CURSOR_MODIFIER_NONE);
}

803 804 805 806
static void
gimp_transform_tool_control (GimpTool   *tool,
			     ToolAction  action,
			     GDisplay   *gdisp)
Nate Summers's avatar
Nate Summers committed
807
{
808 809
  GimpDrawTool      *dr_tool;
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
810

811 812
  dr_tool = GIMP_DRAW_TOOL (tool);
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
813 814 815 816 817 818 819

  switch (action)
    {
    case PAUSE:
      break;

    case RESUME:
Nate Summers's avatar
Nate Summers committed
820
      gimp_transform_tool_recalc (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
821 822 823
      break;

    case HALT:
Nate Summers's avatar
Nate Summers committed
824
      gimp_transform_tool_reset (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
825 826 827 828 829 830
      break;

    default:
      break;
    }

831 832
  if (GIMP_TOOL_CLASS (parent_class)->control)
    GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
Nate Summers's avatar
Nate Summers committed
833 834
}

835
static void
Nate Summers's avatar
Nate Summers committed
836
gimp_transform_tool_draw (GimpDrawTool *dr_tool)
Nate Summers's avatar
Nate Summers committed
837
{
Nate Summers's avatar
Nate Summers committed
838 839 840 841 842 843 844 845
  GDisplay           *gdisp;
  GimpTransformTool  *tr_tool;
  GimpTool           *tool;
  gint                x1, y1, x2, y2, x3, y3, x4, y4;
  gint                srw, srh;
  gint                i, k, gci;
  gint                xa, ya, xb, yb;

846 847
  tr_tool = GIMP_TRANSFORM_TOOL (dr_tool);
  tool    = GIMP_TOOL (dr_tool);
Nate Summers's avatar
Nate Summers committed
848

849
  gdisp   = tool->gdisp;
Nate Summers's avatar
Nate Summers committed
850 851 852 853 854 855 856 857 858 859 860 861 862 863

  gdisplay_transform_coords (gdisp, tr_tool->tx1, tr_tool->ty1,
			     &tr_tool->sx1, &tr_tool->sy1, FALSE);
  gdisplay_transform_coords (gdisp, tr_tool->tx2, tr_tool->ty2,
			     &tr_tool->sx2, &tr_tool->sy2, FALSE);
  gdisplay_transform_coords (gdisp, tr_tool->tx3, tr_tool->ty3,
			     &tr_tool->sx3, &tr_tool->sy3, FALSE);
  gdisplay_transform_coords (gdisp, tr_tool->tx4, tr_tool->ty4,
			     &tr_tool->sx4, &tr_tool->sy4, FALSE);

  x1 = tr_tool->sx1;  y1 = tr_tool->sy1;
  x2 = tr_tool->sx2;  y2 = tr_tool->sy2;
  x3 = tr_tool->sx3;  y3 = tr_tool->sy3;
  x4 = tr_tool->sx4;  y4 = tr_tool->sy4;
Nate Summers's avatar
Nate Summers committed
864 865 866 867 868 869

  /*  find the handles' width and height  */
  srw = 10;
  srh = 10;

  /*  draw the bounding box  */
Nate Summers's avatar
Nate Summers committed
870
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
871
		 x1, y1, x2, y2);
Nate Summers's avatar
Nate Summers committed
872
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
873
		 x2, y2, x4, y4);
Nate Summers's avatar
Nate Summers committed
874
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
875
		 x3, y3, x4, y4);
Nate Summers's avatar
Nate Summers committed
876
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
877 878 879 880
		 x3, y3, x1, y1);

  /*  Draw the grid */

Nate Summers's avatar
Nate Summers committed
881
  if ((tr_tool->grid_coords != NULL) &&
Nate Summers's avatar
Nate Summers committed
882 883
      (tr_tool->tgrid_coords != NULL) /* FIXME!!! this doesn't belong here &&
      ((tool->type != PERSPECTIVE)  ||
Nate Summers's avatar
Nate Summers committed
884
       ((tr_tool->transform[0][0] >=0.0) &&
Nate Summers's avatar
Nate Summers committed
885
	(tr_tool->transform[1][1] >=0.0)) */ ) 
Nate Summers's avatar
Nate Summers committed
886 887
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
888
      k = tr_tool->ngx + tr_tool->ngy;
889

Nate Summers's avatar
Nate Summers committed
890 891
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
892 893
	  gdisplay_transform_coords (gdisp, tr_tool->tgrid_coords[gci],
				     tr_tool->tgrid_coords[gci+1],
Nate Summers's avatar
Nate Summers committed
894
				     &xa, &ya, FALSE);
Nate Summers's avatar
Nate Summers committed
895 896
	  gdisplay_transform_coords (gdisp, tr_tool->tgrid_coords[gci+2],
				     tr_tool->tgrid_coords[gci+3],
Nate Summers's avatar
Nate Summers committed
897 898
				     &xb, &yb, FALSE);

Nate Summers's avatar
Nate Summers committed
899
	  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
900 901 902 903 904 905
			 xa, ya, xb, yb);
	  gci += 4;
	}
    }

  /*  draw the tool handles  */
Nate Summers's avatar
Nate Summers committed
906
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
907
		      x1 - (srw >> 1), y1 - (srh >> 1), srw, srh);
Nate Summers's avatar
Nate Summers committed
908
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
909
		      x2 - (srw >> 1), y2 - (srh >> 1), srw, srh);
Nate Summers's avatar
Nate Summers committed
910
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
911
		      x3 - (srw >> 1), y3 - (srh >> 1), srw, srh);
Nate Summers's avatar
Nate Summers committed
912
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
913 914 915
		      x4 - (srw >> 1), y4 - (srh >> 1), srw, srh);

  /*  draw the center  */
916 917 918
  gdisplay_transform_coords (gdisp,
			     tr_tool->tcx, tr_tool->tcy,
			     &tr_tool->scx, &tr_tool->scy, FALSE);
Nate Summers's avatar
Nate Summers committed
919

920 921 922 923 924 925
  gdk_draw_arc (dr_tool->win,
		dr_tool->gc,
		1,
		tr_tool->scx - (srw >> 1),
		tr_tool->scy - (srh >> 1),
		srw, srh, 0, 23040);
Nate Summers's avatar
Nate Summers committed
926

927
  if (gimp_transform_tool_showpath ())
Nate Summers's avatar
Nate Summers committed
928 929 930
    {
      GimpMatrix3 tmp_matrix;

931
      if (gimp_transform_tool_direction () == TRANSFORM_CORRECTIVE)
Nate Summers's avatar
Nate Summers committed
932
	{
Nate Summers's avatar
Nate Summers committed
933
	  gimp_matrix3_invert (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
934 935 936
	}
      else
	{
Nate Summers's avatar
Nate Summers committed
937
	  gimp_matrix3_duplicate (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
938 939
	}

Nate Summers's avatar
Nate Summers committed
940
      path_transform_draw_current (gdisp, dr_tool, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
941 942 943 944
    }
}

void
Nate Summers's avatar
Nate Summers committed
945
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
946
{
Nate Summers's avatar
Nate Summers committed
947 948 949 950
  GimpTool  *tool;
  gint       i, k;
  gint       gci;

951
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
952 953 954 955 956 957 958 959 960 961 962 963 964

  gimp_matrix3_transform_point (tr_tool->transform,
				tr_tool->x1, tr_tool->y1,
				&tr_tool->tx1, &tr_tool->ty1);
  gimp_matrix3_transform_point (tr_tool->transform,
				tr_tool->x2, tr_tool->y1,
				&tr_tool->tx2, &tr_tool->ty2);
  gimp_matrix3_transform_point (tr_tool->transform,
				tr_tool->x1, tr_tool->y2,
				&tr_tool->tx3, &tr_tool->ty3);
  gimp_matrix3_transform_point (tr_tool->transform,
				tr_tool->x2, tr_tool->y2,
				&tr_tool->tx4, &tr_tool->ty4);
Nate Summers's avatar
Nate Summers committed
965

966 967 968
  gimp_matrix3_transform_point (tr_tool->transform,
				tr_tool->cx, tr_tool->cy,
				&tr_tool->tcx, &tr_tool->tcy);
Nate Summers's avatar
Nate Summers committed
969

Nate Summers's avatar
Nate Summers committed
970 971
  if (tr_tool->grid_coords != NULL &&
      tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
972 973
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
974
      k  = (tr_tool->ngx + tr_tool->ngy) * 2;
975

Nate Summers's avatar
Nate Summers committed
976 977
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
978 979 980 981 982
	  gimp_matrix3_transform_point (tr_tool->transform,
					tr_tool->grid_coords[gci],
					tr_tool->grid_coords[gci+1],
					&(tr_tool->tgrid_coords[gci]),
					&(tr_tool->tgrid_coords[gci+1]));
Nate Summers's avatar
Nate Summers committed
983 984 985 986 987 988
	  gci += 2;
	}
    }
}

void
989 990
gimp_transform_tool_reset (GimpTransformTool *tr_tool,
		           GDisplay          *gdisp)
Nate Summers's avatar
Nate Summers committed
991
{
Nate Summers's avatar
Nate Summers committed
992
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
993

994
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
995

Nate Summers's avatar
Nate Summers committed
996
  if (tr_tool->original)
997 998 999 1000
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
Nate Summers's avatar
Nate Summers committed
1001 1002

  /*  inactivate the tool  */
Nate Summers's avatar
Nate Summers committed
1003
  tr_tool->function = TRANSFORM_CREATING;
1004
  gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1005 1006 1007 1008 1009 1010 1011 1012
  info_dialog_popdown (transform_info);

  tool->state    = INACTIVE;
  tool->gdisp    = NULL;
  tool->drawable = NULL;
}

static void
1013 1014
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
		            GDisplay          *gdisp)
Nate Summers's avatar
Nate Summers committed
1015 1016 1017 1018 1019
{
  TileManager   *tiles;
  GimpDrawable  *drawable;
  gint           offset_x, offset_y;

1020 1021
  tiles    = tr_tool->original;
  drawable = gimp_image_active_drawable (gdisp->gimage);
Nate Summers's avatar
Nate Summers committed
1022 1023 1024 1025 1026

  /*  find the boundaries  */
  if (tiles)
    {
      tile_manager_get_offsets (tiles,
Nate Summers's avatar
Nate Summers committed
1027 1028 1029 1030
				&tr_tool->x1, &tr_tool->y1);
				
      tr_tool->x2 = tr_tool->x1 + tile_manager_width (tiles);
      tr_tool->y2 = tr_tool->y1 + tile_manager_height (tiles);
Nate Summers's avatar
Nate Summers committed
1031 1032 1033 1034 1035
    }
  else
    {
      gimp_drawable_offsets (drawable, &offset_x, &offset_y);
      gimp_drawable_mask_bounds (drawable,
Nate Summers's avatar
Nate Summers committed
1036 1037 1038 1039 1040 1041
				 &tr_tool->x1, &tr_tool->y1,
				 &tr_tool->x2, &tr_tool->y2);
      tr_tool->x1 += offset_x;
      tr_tool->y1 += offset_y;
      tr_tool->x2 += offset_x;
      tr_tool->y2 += offset_y;
Nate Summers's avatar
Nate Summers committed
1042
    }
Nate Summers's avatar
Nate Summers committed
1043 1044 1045

  tr_tool->cx = (tr_tool->x1 + tr_tool->x2) / 2;
  tr_tool->cy = (tr_tool->y1 + tr_tool->y2) / 2;
Nate Summers's avatar
Nate Summers committed
1046 1047

  /*  changing the bounds invalidates any grid we may have  */
Nate Summers's avatar
Nate Summers committed
1048
  gimp_transform_tool_grid_recalc (tr_tool);
Nate Summers's avatar
Nate Summers committed
1049 1050 1051 1052 1053
}

void
gimp_transform_tool_grid_density_changed (void)
{
Nate Summers's avatar
Nate Summers committed
1054 1055
  GimpTransformTool *tr_tool;
  GimpDrawTool      *dr_tool;
Nate Summers's avatar
Nate Summers committed
1056

1057 1058
  tr_tool = GIMP_TRANSFORM_TOOL ( /* EEEEEEEK!!! */ active_tool);
  dr_tool = GIMP_DRAW_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1059

Nate Summers's avatar
Nate Summers committed
1060
  if (tr_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
1061 1062
    return;

Nate Summers's avatar
Nate Summers committed
1063
  gimp_draw_tool_pause (dr_tool);
1064

Nate Summers's avatar
Nate Summers committed
1065 1066
  gimp_transform_tool_grid_recalc (tr_tool);
  gimp_transform_tool_transform_bounding_box (tr_tool);
1067

Nate Summers's avatar
Nate Summers committed
1068
  gimp_draw_tool_resume (dr_tool);
Nate Summers's avatar
Nate Summers committed
1069 1070 1071
}

void
Nate Summers's avatar
Nate Summers committed
1072
gimp_transform_tool_showpath_changed (gint type /* a truly undescriptive name */)
Nate Summers's avatar
Nate Summers committed
1073
{
Nate Summers's avatar
Nate Summers committed
1074
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
1075

1076
  tr_tool = GIMP_TRANSFORM_TOOL ( /* EEEEEEEK!!! */ active_tool);
Nate Summers's avatar
Nate Summers committed
1077

Nate Summers's avatar
Nate Summers committed
1078
  if (tr_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
1079 1080 1081
    return;

  if (type)
1082
    gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1083
  else
1084
    gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1085 1086 1087
}

static void
Nate Summers's avatar
Nate Summers committed
1088
gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1089
{
Nate Summers's avatar
Nate Summers committed
1090
  if (tr_tool->grid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1091
    {
Nate Summers's avatar
Nate Summers committed
1092 1093
      g_free (tr_tool->grid_coords);
      tr_tool->grid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1094
    }
1095

Nate Summers's avatar
Nate Summers committed
1096
  if (tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1097
    {
Nate Summers's avatar
Nate Summers committed
1098 1099
      g_free (tr_tool->tgrid_coords);
      tr_tool->tgrid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1100
    }
1101

1102
  if (gimp_transform_tool_show_grid ())
1103
    gimp_transform_tool_setup_grid (GIMP_TRANSFORM_TOOL ( /* EEEEEEK!!! */ active_tool));
Nate Summers's avatar
Nate Summers committed
1104 1105 1106
}

static void
Nate Summers's avatar
Nate Summers committed