gimptransformtool.c 46.4 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"

32 33 34 35 36 37 38 39
#include "core/gimpchannel.h"
#include "core/gimpcontext.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
#include "core/gimpimage-mask.h"
#include "core/gimplayer.h"
#include "core/gimpmarshal.h"

40
#include "gui/info-dialog.h"
Nate Summers's avatar
Nate Summers committed
41
#include "cursorutil.h"
42 43 44
#include "gdisplay.h"
#include "gimpui.h"

Nate Summers's avatar
Nate Summers committed
45 46 47 48 49
#include "drawable.h"
#include "floating_sel.h"
#include "gimprc.h"
#include "path_transform.h"
#include "pixel_region.h"
50
#include "pixel_surround.h"
Nate Summers's avatar
Nate Summers committed
51 52 53 54
#include "undo.h"
#include "tile_manager.h"
#include "tile.h"

55 56 57 58 59
#include "gimptoolinfo.h"
#include "tool_manager.h"
#include "tool_options.h"
#include "transform_options.h"
#include "gimptransformtool.h"
60 61 62 63 64

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

#include "libgimp/gimpintl.h"

69

Nate Summers's avatar
Nate Summers committed
70 71 72 73
enum
{
  TRANSFORM,
  LAST_SIGNAL
Nate Summers's avatar
Nate Summers committed
74
};
Nate Summers's avatar
Nate Summers committed
75 76 77 78 79 80 81

#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
82
  gimp_transform_tool_cubic(dx, (row)[0], (row)[step], (row)[step+step], (row)[step+step+step])
Nate Summers's avatar
Nate Summers committed
83
#define CUBIC_SCALED_ROW(dx, row, step, i) \
Nate Summers's avatar
Nate Summers committed
84
  gimp_transform_tool_cubic(dx, (row)[0] * (row)[i], \
Nate Summers's avatar
Nate Summers committed
85 86 87 88 89 90 91 92
            (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);

93

Nate Summers's avatar
Nate Summers committed
94
/*  forward function declarations  */
Nate Summers's avatar
Nate Summers committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
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
110

111 112 113
static void    gimp_transform_tool_destroy     (GtkObject              *object);

static void   gimp_transform_tool_button_press (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
114 115 116
                                                GdkEventButton         *bevent,
			                        GDisplay               *gdisp);
			          
117
static void gimp_transform_tool_button_release (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
118 119 120
			                        GdkEventButton         *bevent,
			                        GDisplay               *gdisp);
			                        
121
static void    gimp_transform_tool_motion      (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
122 123 124
		                                GdkEventMotion         *mevent,
		                                GDisplay               *gdisp);
		                                
125
static void  gimp_transform_tool_cursor_update (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
126 127 128
	                 		        GdkEventMotion         *mevent,
			                        GDisplay               *gdisp);
			                        
129
static void    gimp_transform_tool_control     (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
130 131
			                        ToolAction              action,
			                        GDisplay               *gdisp);
132 133 134 135

static void    gimp_transform_tool_draw        (GimpDrawTool           *draw_tool);


Nate Summers's avatar
Nate Summers committed
136
/*  variables  */
Nate Summers's avatar
Nate Summers committed
137 138 139 140 141
static TranInfo           old_trans_info;
InfoDialog               *transform_info        = NULL;
static gboolean           transform_info_inited = FALSE;
static GimpDrawToolClass *parent_class          = NULL;
static guint gimp_transform_tool_signals[LAST_SIGNAL] = { 0 };
Nate Summers's avatar
Nate Summers committed
142

143

Nate Summers's avatar
Nate Summers committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
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
172 173 174
  GtkObjectClass    *object_class;
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_class;
Nate Summers's avatar
Nate Summers committed
175 176 177

  object_class = (GtkObjectClass *) klass;
  tool_class   = (GimpToolClass *) klass;
Nate Summers's avatar
Nate Summers committed
178
  draw_class   = (GimpDrawToolClass *) klass;
Nate Summers's avatar
Nate Summers committed
179 180 181 182 183

  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
184
    		    GTK_RUN_LAST,
Nate Summers's avatar
Nate Summers committed
185 186 187
    		    object_class->type,
    		    GTK_SIGNAL_OFFSET (GimpTransformToolClass,
    		    		       transform),
Nate Summers's avatar
Nate Summers committed
188
    		    gimp_marshal_POINTER__POINTER_INT,
Nate Summers's avatar
Nate Summers committed
189 190 191 192 193 194 195
    		    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
196
  object_class->destroy      = gimp_transform_tool_destroy;
Nate Summers's avatar
Nate Summers committed
197 198 199 200 201 202

  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
203 204

  draw_class->draw           = gimp_transform_tool_draw;
Nate Summers's avatar
Nate Summers committed
205 206 207
}

static void
Nate Summers's avatar
Nate Summers committed
208
gimp_transform_tool_init (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
209
{
210 211
  GimpTool *tool = GIMP_TOOL (tr_tool);
  gint      i;
Nate Summers's avatar
Nate Summers committed
212 213 214 215 216 217 218 219 220 221 222

  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;

223 224 225
  /* FIXME */
  tr_tool->interactive = TRUE;

Nate Summers's avatar
Nate Summers committed
226 227
  tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
228

Nate Summers's avatar
Nate Summers committed
229 230
}

Nate Summers's avatar
Nate Summers committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
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
247 248 249 250
static void
transform_ok_callback (GtkWidget *widget,
		       gpointer   data)
{
Nate Summers's avatar
Nate Summers committed
251
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
252

Nate Summers's avatar
Nate Summers committed
253 254
  tool = GIMP_TOOL(data);
  gimp_transform_tool_doit (GIMP_TRANSFORM_TOOL(tool), tool->gdisp);
Nate Summers's avatar
Nate Summers committed
255 256 257 258 259 260 261 262 263 264
}

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

265 266
  tool    = GIMP_TRANSFORM_TOOL (data);
  dr_tool = GIMP_DRAW_TOOL (data);
Nate Summers's avatar
Nate Summers committed
267 268

  /*  stop the current tool drawing process  */
Nate Summers's avatar
Nate Summers committed
269
  gimp_draw_tool_pause (dr_tool);
Nate Summers's avatar
Nate Summers committed
270 271 272 273 274 275

  /*  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
276
  gimp_transform_tool_recalc (tool, GIMP_TOOL(tool)->gdisp);
Nate Summers's avatar
Nate Summers committed
277 278

  /*  resume drawing the current tool  */
Nate Summers's avatar
Nate Summers committed
279
  gimp_draw_tool_resume (dr_tool);
Nate Summers's avatar
Nate Summers committed
280 281
}

282 283
static void
gimp_transform_tool_destroy (GtkObject *object)
Nate Summers's avatar
Nate Summers committed
284
{
285 286
  GimpTransformTool *tr_tool;
  GimpTool          *tool;
Nate Summers's avatar
Nate Summers committed
287

288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
  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
314
gimp_transform_tool_button_press (GimpTool           *tool,
Nate Summers's avatar
Nate Summers committed
315 316 317
                                  GdkEventButton     *bevent,
			          GDisplay           *gdisp)
{
Nate Summers's avatar
Nate Summers committed
318 319 320 321 322 323 324
  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
325

326
  gt_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345

  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...  */
346 347
      gimp_draw_tool_start (GIMP_DRAW_TOOL (gt_tool), gdisp->canvas->window);

Nate Summers's avatar
Nate Summers committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
      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;
	}

375 376
      if ((SQR (x - gt_tool->scx) +
	   SQR (y - gt_tool->scy)) <= 100)
Nate Summers's avatar
Nate Summers committed
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
	{
	  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)))
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 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 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
    {
      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
489 490
}

491
static void
Nate Summers's avatar
Nate Summers committed
492 493 494
gimp_transform_tool_button_release (GimpTool         *tool,
			            GdkEventButton   *bevent,
			            GDisplay         *gdisp)
Nate Summers's avatar
Nate Summers committed
495
{
Nate Summers's avatar
Nate Summers committed
496 497
  GimpTransformTool *gt_tool;
  gint               i;
Nate Summers's avatar
Nate Summers committed
498

499
  gt_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
500 501 502 503

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

  /*  if we are creating, there is nothing to be done...exit  */
504
  if (gt_tool->function == TRANSFORM_CREATING && gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
505 506 507 508 509 510 511 512 513 514
    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  */
515
      if ((bevent->state & GDK_SHIFT_MASK) || GIMP_IS_FLIP_TOOL (tool))
Nate Summers's avatar
Nate Summers committed
516
	{
Nate Summers's avatar
Nate Summers committed
517
	  gimp_transform_tool_doit (gt_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
518 519 520 521 522 523 524 525 526 527 528
	}
      else
	{
	  /*  Only update the paths preview */
	  path_transform_current_path (gdisp->gimage,
				       gt_tool->transform, TRUE);
	}
    }
  else
    {
      /*  stop the current tool drawing process  */
529
      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
530 531 532 533 534 535 536 537 538

      /*  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  */
539
      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
540 541 542 543 544 545 546 547 548 549 550

      /* 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;
}

551
static void
Nate Summers's avatar
Nate Summers committed
552 553 554 555 556 557 558 559 560 561 562 563
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 ();

564
  tool = GIMP_TOOL (gt_tool);
Nate Summers's avatar
Nate Summers committed
565 566

  /* undraw the tool before we muck around with the transform matrix */
567
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (gt_tool));
Nate Summers's avatar
Nate Summers committed
568 569 570 571 572 573 574 575 576

  /*  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);

577 578 579
  /* 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
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
  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
596
  new_tiles = gimp_transform_tool_transform (gt_tool, gdisp,
597
					     TRANSFORM_FINISH);
Nate Summers's avatar
Nate Summers committed
598

Nate Summers's avatar
Nate Summers committed
599
  gimp_transform_tool_transform (gt_tool, gdisp, TRANSFORM_INIT);
Nate Summers's avatar
Nate Summers committed
600 601 602 603 604 605 606 607 608 609

  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,
610
				 new_tiles, new_layer);
Nate Summers's avatar
Nate Summers committed
611 612

      /*  create and initialize the transform_undo structure  */
613 614 615
      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
616

Nate Summers's avatar
Nate Summers committed
617 618
      for (i = 0; i < TRAN_INFO_SIZE; i++)
	tu->trans_info[i] = old_trans_info[i];
619 620

      tu->original  = NULL;
Nate Summers's avatar
Nate Summers committed
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
      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 ();

663
  gimp_transform_tool_reset (gt_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
664 665

  /*  if this tool is non-interactive, make it inactive after use  */
Nate Summers's avatar
Nate Summers committed
666
  if (!gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
667 668 669
    tool->state = INACTIVE;
}

670
static void
Nate Summers's avatar
Nate Summers committed
671 672 673
gimp_transform_tool_motion (GimpTool          *tool,
		            GdkEventMotion    *mevent,
		            GDisplay          *gdisp)
Nate Summers's avatar
Nate Summers committed
674
{
Nate Summers's avatar
Nate Summers committed
675
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
676

677
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
678

679
  if (! tr_tool->bpressed)
Nate Summers's avatar
Nate Summers committed
680 681 682 683 684
    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
685 686
  if (tr_tool->function == TRANSFORM_CREATING ||
      !tr_tool->interactive)
Nate Summers's avatar
Nate Summers committed
687 688 689
    return;

  /*  stop the current tool drawing process  */
690
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
691 692

  gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
Nate Summers's avatar
Nate Summers committed
693 694 695
			       &tr_tool->curx,
			       &tr_tool->cury, TRUE, 0);
  tr_tool->state = mevent->state;
Nate Summers's avatar
Nate Summers committed
696 697

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

Nate Summers's avatar
Nate Summers committed
700 701
  tr_tool->lastx = tr_tool->curx;
  tr_tool->lasty = tr_tool->cury;
Nate Summers's avatar
Nate Summers committed
702 703

  /*  resume drawing the current tool  */
704
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
705 706
}

707
static void
Nate Summers's avatar
Nate Summers committed
708
gimp_transform_tool_cursor_update (GimpTool           *tool,
Nate Summers's avatar
Nate Summers committed
709 710
			           GdkEventMotion     *mevent,
			           GDisplay           *gdisp)
Nate Summers's avatar
Nate Summers committed
711
{
Nate Summers's avatar
Nate Summers committed
712 713 714 715
  GimpTransformTool  *tr_tool;
  GimpDrawable       *drawable;
  GdkCursorType       ctype = GDK_TOP_LEFT_ARROW;
  gint                x, y;
Nate Summers's avatar
Nate Summers committed
716

717
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747

  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);
}

748 749 750 751
static void
gimp_transform_tool_control (GimpTool   *tool,
			     ToolAction  action,
			     GDisplay   *gdisp)
Nate Summers's avatar
Nate Summers committed
752
{
753 754
  GimpDrawTool      *dr_tool;
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
755

756 757
  dr_tool = GIMP_DRAW_TOOL (tool);
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
758 759 760 761 762 763 764

  switch (action)
    {
    case PAUSE:
      break;

    case RESUME:
Nate Summers's avatar
Nate Summers committed
765
      gimp_transform_tool_recalc (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
766 767 768
      break;

    case HALT:
Nate Summers's avatar
Nate Summers committed
769
      gimp_transform_tool_reset (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
770 771 772 773 774 775
      break;

    default:
      break;
    }

776 777
  if (GIMP_TOOL_CLASS (parent_class)->control)
    GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
Nate Summers's avatar
Nate Summers committed
778 779
}

780
static void
Nate Summers's avatar
Nate Summers committed
781
gimp_transform_tool_draw (GimpDrawTool *dr_tool)
Nate Summers's avatar
Nate Summers committed
782
{
Nate Summers's avatar
Nate Summers committed
783 784 785 786 787 788 789 790
  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;

791 792
  tr_tool = GIMP_TRANSFORM_TOOL (dr_tool);
  tool    = GIMP_TOOL (dr_tool);
Nate Summers's avatar
Nate Summers committed
793

794
  gdisp   = tool->gdisp;
Nate Summers's avatar
Nate Summers committed
795 796 797 798 799 800 801 802 803 804 805 806 807 808

  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
809 810 811 812 813 814

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

  /*  draw the bounding box  */
Nate Summers's avatar
Nate Summers committed
815
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
816
		 x1, y1, x2, y2);
Nate Summers's avatar
Nate Summers committed
817
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
818
		 x2, y2, x4, y4);
Nate Summers's avatar
Nate Summers committed
819
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
820
		 x3, y3, x4, y4);
Nate Summers's avatar
Nate Summers committed
821
  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
822 823 824 825
		 x3, y3, x1, y1);

  /*  Draw the grid */

Nate Summers's avatar
Nate Summers committed
826
  if ((tr_tool->grid_coords != NULL) &&
Nate Summers's avatar
Nate Summers committed
827 828
      (tr_tool->tgrid_coords != NULL) /* FIXME!!! this doesn't belong here &&
      ((tool->type != PERSPECTIVE)  ||
Nate Summers's avatar
Nate Summers committed
829
       ((tr_tool->transform[0][0] >=0.0) &&
Nate Summers's avatar
Nate Summers committed
830
	(tr_tool->transform[1][1] >=0.0)) */ ) 
Nate Summers's avatar
Nate Summers committed
831 832
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
833
      k = tr_tool->ngx + tr_tool->ngy;
834

Nate Summers's avatar
Nate Summers committed
835 836
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
837 838
	  gdisplay_transform_coords (gdisp, tr_tool->tgrid_coords[gci],
				     tr_tool->tgrid_coords[gci+1],
Nate Summers's avatar
Nate Summers committed
839
				     &xa, &ya, FALSE);
Nate Summers's avatar
Nate Summers committed
840 841
	  gdisplay_transform_coords (gdisp, tr_tool->tgrid_coords[gci+2],
				     tr_tool->tgrid_coords[gci+3],
Nate Summers's avatar
Nate Summers committed
842 843
				     &xb, &yb, FALSE);

Nate Summers's avatar
Nate Summers committed
844
	  gdk_draw_line (dr_tool->win, dr_tool->gc,
Nate Summers's avatar
Nate Summers committed
845 846 847 848 849 850
			 xa, ya, xb, yb);
	  gci += 4;
	}
    }

  /*  draw the tool handles  */
Nate Summers's avatar
Nate Summers committed
851
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
852
		      x1 - (srw >> 1), y1 - (srh >> 1), srw, srh);
Nate Summers's avatar
Nate Summers committed
853
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
854
		      x2 - (srw >> 1), y2 - (srh >> 1), srw, srh);
Nate Summers's avatar
Nate Summers committed
855
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
856
		      x3 - (srw >> 1), y3 - (srh >> 1), srw, srh);
Nate Summers's avatar
Nate Summers committed
857
  gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0,
Nate Summers's avatar
Nate Summers committed
858 859 860
		      x4 - (srw >> 1), y4 - (srh >> 1), srw, srh);

  /*  draw the center  */
861 862 863
  gdisplay_transform_coords (gdisp,
			     tr_tool->tcx, tr_tool->tcy,
			     &tr_tool->scx, &tr_tool->scy, FALSE);
Nate Summers's avatar
Nate Summers committed
864

865 866 867 868 869 870
  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
871

872
  if (gimp_transform_tool_showpath ())
Nate Summers's avatar
Nate Summers committed
873 874 875
    {
      GimpMatrix3 tmp_matrix;

876
      if (gimp_transform_tool_direction () == TRANSFORM_CORRECTIVE)
Nate Summers's avatar
Nate Summers committed
877
	{
Nate Summers's avatar
Nate Summers committed
878
	  gimp_matrix3_invert (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
879 880 881
	}
      else
	{
Nate Summers's avatar
Nate Summers committed
882
	  gimp_matrix3_duplicate (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
883 884
	}

Nate Summers's avatar
Nate Summers committed
885
      path_transform_draw_current (gdisp, dr_tool, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
886 887 888 889
    }
}

void
Nate Summers's avatar
Nate Summers committed
890
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
891
{
Nate Summers's avatar
Nate Summers committed
892 893 894 895
  GimpTool  *tool;
  gint       i, k;
  gint       gci;

896
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
897 898 899 900 901 902 903 904 905 906 907 908 909

  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
910

911 912 913
  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
914

Nate Summers's avatar
Nate Summers committed
915 916
  if (tr_tool->grid_coords != NULL &&
      tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
917 918
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
919
      k  = (tr_tool->ngx + tr_tool->ngy) * 2;
920

Nate Summers's avatar
Nate Summers committed
921 922
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
923 924 925 926 927
	  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
928 929 930 931 932 933
	  gci += 2;
	}
    }
}

void
934 935
gimp_transform_tool_reset (GimpTransformTool *tr_tool,
		           GDisplay          *gdisp)
Nate Summers's avatar
Nate Summers committed
936
{
Nate Summers's avatar
Nate Summers committed
937
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
938

939
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
940

Nate Summers's avatar
Nate Summers committed
941
  if (tr_tool->original)
942 943 944 945
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
Nate Summers's avatar
Nate Summers committed
946 947

  /*  inactivate the tool  */
Nate Summers's avatar
Nate Summers committed
948
  tr_tool->function = TRANSFORM_CREATING;
949
  gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
950 951 952 953 954 955 956 957
  info_dialog_popdown (transform_info);

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

static void
958 959
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
		            GDisplay          *gdisp)
Nate Summers's avatar
Nate Summers committed
960 961 962 963 964
{
  TileManager   *tiles;
  GimpDrawable  *drawable;
  gint           offset_x, offset_y;

965 966
  tiles    = tr_tool->original;
  drawable = gimp_image_active_drawable (gdisp->gimage);
Nate Summers's avatar
Nate Summers committed
967 968 969 970 971

  /*  find the boundaries  */
  if (tiles)
    {
      tile_manager_get_offsets (tiles,
Nate Summers's avatar
Nate Summers committed
972 973 974 975
				&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
976 977 978 979 980
    }
  else
    {
      gimp_drawable_offsets (drawable, &offset_x, &offset_y);
      gimp_drawable_mask_bounds (drawable,
Nate Summers's avatar
Nate Summers committed
981 982 983 984 985 986
				 &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
987
    }
Nate Summers's avatar
Nate Summers committed
988 989 990

  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
991 992

  /*  changing the bounds invalidates any grid we may have  */
Nate Summers's avatar
Nate Summers committed
993
  gimp_transform_tool_grid_recalc (tr_tool);
Nate Summers's avatar
Nate Summers committed
994 995 996 997 998
}

void
gimp_transform_tool_grid_density_changed (void)
{
Nate Summers's avatar
Nate Summers committed
999 1000
  GimpTransformTool *tr_tool;
  GimpDrawTool      *dr_tool;
Nate Summers's avatar
Nate Summers committed
1001

1002 1003
  tr_tool = GIMP_TRANSFORM_TOOL ( /* EEEEEEEK!!! */ active_tool);
  dr_tool = GIMP_DRAW_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1004

Nate Summers's avatar
Nate Summers committed
1005
  if (tr_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
1006 1007
    return;

Nate Summers's avatar
Nate Summers committed
1008
  gimp_draw_tool_pause (dr_tool);
1009

Nate Summers's avatar
Nate Summers committed
1010 1011
  gimp_transform_tool_grid_recalc (tr_tool);
  gimp_transform_tool_transform_bounding_box (tr_tool);
1012

Nate Summers's avatar
Nate Summers committed
1013
  gimp_draw_tool_resume (dr_tool);
Nate Summers's avatar
Nate Summers committed
1014 1015 1016
}

void
Nate Summers's avatar
Nate Summers committed
1017
gimp_transform_tool_showpath_changed (gint type /* a truly undescriptive name */)
Nate Summers's avatar
Nate Summers committed
1018
{
Nate Summers's avatar
Nate Summers committed
1019
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
1020

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

Nate Summers's avatar
Nate Summers committed
1023
  if (tr_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
1024 1025 1026
    return;

  if (type)
1027
    gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1028
  else
1029
    gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1030 1031 1032
}

static void
Nate Summers's avatar
Nate Summers committed
1033
gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1034
{
Nate Summers's avatar
Nate Summers committed
1035
  if (tr_tool->grid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1036
    {
Nate Summers's avatar
Nate Summers committed
1037 1038
      g_free (tr_tool->grid_coords);
      tr_tool->grid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1039
    }
1040

Nate Summers's avatar
Nate Summers committed
1041
  if (tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1042
    {
Nate Summers's avatar
Nate Summers committed
1043 1044
      g_free (tr_tool->tgrid_coords);
      tr_tool->tgrid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1045
    }
1046

1047
  if (gimp_transform_tool_show_grid ())
1048
    gimp_transform_tool_setup_grid (GIMP_TRANSFORM_TOOL ( /* EEEEEEK!!! */ active_tool));
Nate Summers's avatar
Nate Summers committed
1049 1050 1051
}

static void
Nate Summers's avatar
Nate Summers committed
1052
gimp_transform_tool_setup_grid (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1053
{
1054 1055 1056
  GimpTool *tool;
  gint      i, gci;
  gdouble  *coords;
Nate Summers's avatar
Nate Summers committed
1057

1058
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1059

Nate Summers's avatar
Nate Summers committed
1060
  /*  We use the gimp_transform_tool_grid_size function only here, even
Nate Summers's avatar
Nate Summers committed
1061 1062 1063
   *  if the user changes the grid size in the middle of an
   *  operation, nothing happens.
   */
1064
  tr_tool->ngx = (tr_tool->x2 - tr_tool->x1) / gimp_transform_tool_grid_size ();
Nate Summers's avatar
Nate Summers committed
1065 1066
  if (tr_tool->ngx > 0)
    tr_tool->ngx--;
Nate Summers's avatar
Nate Summers committed
1067

1068
  tr_tool->ngy = (tr_tool->y2 - tr_tool->y1) / gimp_transform_tool_grid_size ();
Nate Summers's avatar
Nate Summers committed
1069 1070
  if (tr_tool->ngy > 0)
    tr_tool->ngy--;
Nate Summers's avatar
Nate Summers committed
1071

Nate Summers's avatar
Nate Summers committed
1072
  tr_tool->grid_coords = coords =
1073
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1074

Nate Summers's avatar
Nate Summers committed
1075
  tr_tool->tgrid_coords =
1076
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1077 1078

  gci = 0;
1079

Nate Summers's avatar