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

Michael Natterer's avatar
Michael Natterer committed
28
#include "tools-types.h"
29
#include "gui/gui-types.h"
Nate Summers's avatar
Nate Summers committed
30

Michael Natterer's avatar
Michael Natterer committed
31
32
33
34
35
36
#include "base/base-config.h"
#include "base/pixel-region.h"
#include "base/pixel-surround.h"
#include "base/tile-manager.h"
#include "base/tile.h"

37
38
#include "paint-funcs/paint-funcs.h"

Michael Natterer's avatar
Michael Natterer committed
39
#include "core/gimp.h"
40
41
42
43
44
45
46
#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"
Michael Natterer's avatar
Michael Natterer committed
47
#include "core/gimptoolinfo.h"
48

49
#include "gui/info-dialog.h"
50
51

#include "display/gimpdisplay.h"
52
#include "display/gimpdisplay-foreach.h"
Michael Natterer's avatar
Michael Natterer committed
53
#include "display/gimpdisplayshell.h"
Nate Summers's avatar
Nate Summers committed
54

55
56
57
58
#include "tool_manager.h"
#include "tool_options.h"
#include "transform_options.h"
#include "gimptransformtool.h"
Michael Natterer's avatar
Michael Natterer committed
59
60
61
62
63
#include "gimpperspectivetool.h"
#include "gimprotatetool.h"
#include "gimpscaletool.h"
#include "gimpsheartool.h"
#include "gimpfliptool.h"
64

Michael Natterer's avatar
Michael Natterer committed
65
66
67
68
#include "app_procs.h"
#include "floating_sel.h"
#include "undo.h"
#include "path_transform.h"
Nate Summers's avatar
Nate Summers committed
69
70
71

#include "libgimp/gimpintl.h"

72

Nate Summers's avatar
Nate Summers committed
73
74
75
76
enum
{
  TRANSFORM,
  LAST_SIGNAL
Nate Summers's avatar
Nate Summers committed
77
};
Nate Summers's avatar
Nate Summers committed
78

79
80
#define HANDLE 10

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

98

Nate Summers's avatar
Nate Summers committed
99
/*  forward function declarations  */
Nate Summers's avatar
Nate Summers committed
100
static void      gimp_transform_tool_bounds    (GimpTransformTool      *tool,
101
                                                GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
102
static void      gimp_transform_tool_recalc    (GimpTransformTool      *tool,
103
					        GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
104
static void      gimp_transform_tool_doit      (GimpTransformTool      *tool,
105
					        GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
106
107
108
109
110
111
112
113
114
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
115

116
static void    gimp_transform_tool_finalize    (GObject                *object);
117
118

static void   gimp_transform_tool_button_press (GimpTool               *tool,
119
120
121
                                                GimpCoords             *coords,
                                                guint32                 time,
                                                GdkModifierType         state,
122
			                        GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
123
			          
124
static void gimp_transform_tool_button_release (GimpTool               *tool,
125
126
127
                                                GimpCoords             *coords,
                                                guint32                 time,
			                        GdkModifierType         state,
128
			                        GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
129
			                        
130
static void    gimp_transform_tool_motion      (GimpTool               *tool,
131
132
133
                                                GimpCoords             *coords,
                                                guint32                 time,
		                                GdkModifierType         state,
134
		                                GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
135
		                                
136
static void  gimp_transform_tool_cursor_update (GimpTool               *tool,
137
138
                                                GimpCoords             *coords,
	                 		        GdkModifierType         state,
139
			                        GimpDisplay            *gdisp);
Nate Summers's avatar
Nate Summers committed
140
			                        
141
static void    gimp_transform_tool_control     (GimpTool               *tool,
Nate Summers's avatar
Nate Summers committed
142
			                        ToolAction              action,
143
			                        GimpDisplay            *gdisp);
144
145
146
147

static void    gimp_transform_tool_draw        (GimpDrawTool           *draw_tool);


Nate Summers's avatar
Nate Summers committed
148
/*  variables  */
Nate Summers's avatar
Nate Summers committed
149
150
151
static TranInfo           old_trans_info;
InfoDialog               *transform_info        = NULL;
static gboolean           transform_info_inited = FALSE;
Nate Summers's avatar
Nate Summers committed
152

153
static GimpDrawToolClass *parent_class = NULL;
154

155
156
157
158
static guint   gimp_transform_tool_signals[LAST_SIGNAL] = { 0 };


GType
Nate Summers's avatar
Nate Summers committed
159
160
gimp_transform_tool_get_type (void)
{
161
  static GType tool_type = 0;
Nate Summers's avatar
Nate Summers committed
162
163
164

  if (! tool_type)
    {
165
      static const GTypeInfo tool_info =
Nate Summers's avatar
Nate Summers committed
166
167
      {
        sizeof (GimpTransformToolClass),
168
169
170
171
172
173
174
175
	(GBaseInitFunc) NULL,
	(GBaseFinalizeFunc) NULL,
	(GClassInitFunc) gimp_transform_tool_class_init,
	NULL,           /* class_finalize */
	NULL,           /* class_data     */
	sizeof (GimpTransformTool),
	0,              /* n_preallocs    */
	(GInstanceInitFunc) gimp_transform_tool_init,
Nate Summers's avatar
Nate Summers committed
176
177
      };

178
179
180
      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
					  "GimpTransformTool", 
                                          &tool_info, 0);
Nate Summers's avatar
Nate Summers committed
181
182
183
184
185
186
187
188
    }

  return tool_type;
}

static void
gimp_transform_tool_class_init (GimpTransformToolClass *klass)
{
189
  GObjectClass      *object_class;
Nate Summers's avatar
Nate Summers committed
190
191
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_class;
Nate Summers's avatar
Nate Summers committed
192

193
194
195
  object_class = G_OBJECT_CLASS (klass);
  tool_class   = GIMP_TOOL_CLASS (klass);
  draw_class   = GIMP_DRAW_TOOL_CLASS (klass);
Nate Summers's avatar
Nate Summers committed
196

197
  parent_class = g_type_class_peek_parent (klass);
Nate Summers's avatar
Nate Summers committed
198
199

  gimp_transform_tool_signals[TRANSFORM] =
200
201
202
203
204
205
206
207
208
    g_signal_new ("transform",
		  G_TYPE_FROM_CLASS (klass),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GimpTransformToolClass, transform),
		  NULL, NULL,
		  gimp_cclosure_marshal_POINTER__POINTER_INT,
		  G_TYPE_POINTER, 2,
		  G_TYPE_POINTER,
		  G_TYPE_INT);
Nate Summers's avatar
Nate Summers committed
209

210
  object_class->finalize     = gimp_transform_tool_finalize;
Nate Summers's avatar
Nate Summers committed
211

212
  tool_class->control        = gimp_transform_tool_control;
Nate Summers's avatar
Nate Summers committed
213
214
215
216
  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;
Nate Summers's avatar
Nate Summers committed
217
218

  draw_class->draw           = gimp_transform_tool_draw;
Nate Summers's avatar
Nate Summers committed
219
220
221
}

static void
Nate Summers's avatar
Nate Summers committed
222
gimp_transform_tool_init (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
223
{
224
225
  GimpTool *tool = GIMP_TOOL (tr_tool);
  gint      i;
Nate Summers's avatar
Nate Summers committed
226
227
228
229
230
231
232
233
234

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

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

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

235
236
237
  /* FIXME */
  tr_tool->interactive = TRUE;

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

Nate Summers's avatar
Nate Summers committed
241
242
}

Nate Summers's avatar
Nate Summers committed
243
244
TileManager *
gimp_transform_tool_transform (GimpTransformTool   *tool,
245
                               GimpDisplay         *gdisp,
Nate Summers's avatar
Nate Summers committed
246
247
248
249
250
251
252
			       TransformState       state)
{
  TileManager *retval;

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

253
254
  g_signal_emit (G_OBJECT (tool), gimp_transform_tool_signals[TRANSFORM], 0,
                 gdisp, state, &retval);
Nate Summers's avatar
Nate Summers committed
255
256
257
258

  return retval;
}

Nate Summers's avatar
Nate Summers committed
259
260
261
262
static void
transform_ok_callback (GtkWidget *widget,
		       gpointer   data)
{
Nate Summers's avatar
Nate Summers committed
263
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
264

Nate Summers's avatar
Nate Summers committed
265
266
  tool = GIMP_TOOL(data);
  gimp_transform_tool_doit (GIMP_TRANSFORM_TOOL(tool), tool->gdisp);
Nate Summers's avatar
Nate Summers committed
267
268
269
270
271
272
273
274
275
276
}

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

277
278
  tool    = GIMP_TRANSFORM_TOOL (data);
  dr_tool = GIMP_DRAW_TOOL (data);
Nate Summers's avatar
Nate Summers committed
279
280

  /*  stop the current tool drawing process  */
Nate Summers's avatar
Nate Summers committed
281
  gimp_draw_tool_pause (dr_tool);
Nate Summers's avatar
Nate Summers committed
282
283
284
285
286
287

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

  /*  resume drawing the current tool  */
Nate Summers's avatar
Nate Summers committed
291
  gimp_draw_tool_resume (dr_tool);
Nate Summers's avatar
Nate Summers committed
292
293
}

294
static void
295
gimp_transform_tool_finalize (GObject *object)
Nate Summers's avatar
Nate Summers committed
296
{
297
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
298

299
300
301
  tr_tool = GIMP_TRANSFORM_TOOL (object);

  if (tr_tool->original)
302
303
304
305
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
306
307

  if (transform_info)
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    {
      info_dialog_free (transform_info);
      transform_info        = NULL;
      transform_info_inited = FALSE;
    }

  if (tr_tool->grid_coords)
    {
      g_free (tr_tool->grid_coords);
      tr_tool->grid_coords = NULL;
    }

  if (tr_tool->tgrid_coords)
    {
      g_free (tr_tool->tgrid_coords);
      tr_tool->tgrid_coords = NULL;
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
330
331
332
gimp_transform_tool_control (GimpTool    *tool,
			     ToolAction   action,
			     GimpDisplay *gdisp)
333
334
335
336
337
338
{
  GimpDrawTool      *dr_tool;
  GimpTransformTool *tr_tool;

  dr_tool = GIMP_DRAW_TOOL (tool);
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
339

340
341
342
343
  switch (action)
    {
    case PAUSE:
      break;
344

345
346
347
    case RESUME:
      gimp_transform_tool_recalc (tr_tool, gdisp);
      break;
348

349
350
351
    case HALT:
      gimp_transform_tool_reset (tr_tool, gdisp);
      break;
352

353
354
355
356
357
358
    default:
      break;
    }

  if (GIMP_TOOL_CLASS (parent_class)->control)
    GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
359
360
361
}

static void
362
363
364
365
366
gimp_transform_tool_button_press (GimpTool        *tool,
                                  GimpCoords      *coords,
                                  guint32          time,
                                  GdkModifierType  state,
			          GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
367
{
Michael Natterer's avatar
Michael Natterer committed
368
  GimpTransformTool *gt_tool;
369
  GimpDrawTool      *draw_tool;
Michael Natterer's avatar
Michael Natterer committed
370
371
  GimpDisplayShell  *shell;
  GimpDrawable      *drawable;
372
373
  gdouble            dist;
  gdouble            closest_dist;
Michael Natterer's avatar
Michael Natterer committed
374
375
  gint               i;
  gint               off_x, off_y;
Nate Summers's avatar
Nate Summers committed
376

377
378
  gt_tool   = GIMP_TRANSFORM_TOOL (tool);
  draw_tool = GIMP_DRAW_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
379

Michael Natterer's avatar
Michael Natterer committed
380
381
  shell = GIMP_DISPLAY_SHELL (gdisp->shell);

Nate Summers's avatar
Nate Summers committed
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  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...  */
Michael Natterer's avatar
Michael Natterer committed
398
      gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), shell->canvas->window);
399

400
401
402
      closest_dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                                   coords->x, coords->y,
                                                   gt_tool->tx1, gt_tool->ty1);
Nate Summers's avatar
Nate Summers committed
403
404
      gt_tool->function = TRANSFORM_HANDLE_1;

405
406
407
      dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                           coords->x, coords->y,
                                           gt_tool->tx2, gt_tool->ty2);
Nate Summers's avatar
Nate Summers committed
408
409
410
411
412
413
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  gt_tool->function = TRANSFORM_HANDLE_2;
	}

414
415
416
      dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                           coords->x, coords->y,
                                           gt_tool->tx3, gt_tool->ty3);
Nate Summers's avatar
Nate Summers committed
417
418
419
420
421
422
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  gt_tool->function = TRANSFORM_HANDLE_3;
	}

423
424
425
      dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                           coords->x, coords->y,
                                           gt_tool->tx4, gt_tool->ty4);
Nate Summers's avatar
Nate Summers committed
426
427
428
429
430
431
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  gt_tool->function = TRANSFORM_HANDLE_4;
	}

432
433
434
435
      if (gimp_draw_tool_in_radius (draw_tool, gdisp,
                                    coords->x, coords->y,
                                    gt_tool->tcx, gt_tool->tcy,
                                    HANDLE >> 1))
Nate Summers's avatar
Nate Summers committed
436
437
438
439
440
	{
	  gt_tool->function = TRANSFORM_HANDLE_CENTER;
	}

      /*  Save the current pointer position  */
441
442
      gt_tool->lastx = gt_tool->startx = coords->x;
      gt_tool->lasty = gt_tool->starty = coords->y;
Nate Summers's avatar
Nate Summers committed
443

Michael Natterer's avatar
Michael Natterer committed
444
      gdk_pointer_grab (shell->canvas->window, FALSE,
Nate Summers's avatar
Nate Summers committed
445
446
447
			GDK_POINTER_MOTION_HINT_MASK |
			GDK_BUTTON1_MOTION_MASK |
			GDK_BUTTON_RELEASE_MASK,
448
			NULL, NULL, time);
Nate Summers's avatar
Nate Summers committed
449
450
451
452
453
454
455
456
457

      tool->state = ACTIVE;
      return;
    }

  /*  Initialisation stuff: if the cursor is clicked inside the current
   *  selection, show the bounding box and handles...
   */
  gimp_drawable_offsets (drawable, &off_x, &off_y);
458
459
460
461
462

  if (coords->x >= off_x &&
      coords->y >= off_y &&
      coords->x < (off_x + gimp_drawable_width (drawable)) &&
      coords->y < (off_y + gimp_drawable_height (drawable)))
463
464
    {
      if (gimage_mask_is_empty (gdisp->gimage) ||
465
	  gimage_mask_value (gdisp->gimage, coords->x, coords->y))
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
	{
	  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  */
488
	  if (! gt_tool->interactive)
Michael Natterer's avatar
Michael Natterer committed
489
490
491
492
	    gdk_pointer_grab (shell->canvas->window, FALSE,
			      GDK_POINTER_MOTION_HINT_MASK |
                              GDK_BUTTON1_MOTION_MASK |
                              GDK_BUTTON_RELEASE_MASK,
493
			      NULL, NULL, time);
494
495
496
497
498
499
500
501
502
503
504
505

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

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

	  if (transform_info && !transform_info_inited)
	    {
506
	      GType tool_type;
507
508

	      tool_type =
Michael Natterer's avatar
Michael Natterer committed
509
		gimp_context_get_tool (gimp_get_user_context (gdisp->gimage->gimp))->tool_type;
510
511

	      gimp_dialog_create_action_area
512
		(GIMP_DIALOG (transform_info->shell),
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535

		 /* 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)
536
	    gimp_transform_tool_button_press (tool, coords, time, state, gdisp);
537
538
	}
    }
Nate Summers's avatar
Nate Summers committed
539
540
}

541
static void
542
543
544
545
546
gimp_transform_tool_button_release (GimpTool        *tool,
                                    GimpCoords      *coords,
                                    guint32          time,
			            GdkModifierType  state,
			            GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
547
{
Nate Summers's avatar
Nate Summers committed
548
549
  GimpTransformTool *gt_tool;
  gint               i;
Nate Summers's avatar
Nate Summers committed
550

551
  gt_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
552
553

  /*  if we are creating, there is nothing to be done...exit  */
554
  if (gt_tool->function == TRANSFORM_CREATING && gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
555
556
557
    return;

  /*  release of the pointer grab  */
558
  gdk_pointer_ungrab (time);
Nate Summers's avatar
Nate Summers committed
559
560
561
  gdk_flush ();

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

      /*  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  */
589
      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
590
591
592
593
594
595
596

      /* 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  */
597
  if (! gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
598
599
600
    tool->state = INACTIVE;
}

601
static void
Nate Summers's avatar
Nate Summers committed
602
gimp_transform_tool_doit (GimpTransformTool  *gt_tool,
603
		          GimpDisplay        *gdisp)
Nate Summers's avatar
Nate Summers committed
604
{
Michael Natterer's avatar
Michael Natterer committed
605
606
607
608
609
610
  GimpDisplayShell *shell;
  GimpTool         *tool;
  TileManager      *new_tiles;
  TransformUndo    *tu;
  PathUndo         *pundo;
  gboolean          new_layer;
611
  gint              i;
Nate Summers's avatar
Nate Summers committed
612

613
  gimp_set_busy (gdisp->gimage->gimp);
Nate Summers's avatar
Nate Summers committed
614

615
  tool = GIMP_TOOL (gt_tool);
Nate Summers's avatar
Nate Summers committed
616

Michael Natterer's avatar
Michael Natterer committed
617
618
  shell = GIMP_DISPLAY_SHELL (gdisp->shell);

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

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

630
631
632
  /* 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
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  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
649
  new_tiles = gimp_transform_tool_transform (gt_tool, gdisp,
650
					     TRANSFORM_FINISH);
Nate Summers's avatar
Nate Summers committed
651

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

  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,
663
				 new_tiles, new_layer);
Nate Summers's avatar
Nate Summers committed
664
665

      /*  create and initialize the transform_undo structure  */
666
667
      tu = g_new0 (TransformUndo, 1);
      tu->tool_ID   = tool->ID;
668
      tu->tool_type = G_TYPE_FROM_INSTANCE (tool);
Nate Summers's avatar
Nate Summers committed
669

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

      tu->original  = NULL;
Nate Summers's avatar
Nate Summers committed
674
675
676
677
678
679
680
      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);

681
      undo_push_transform (gdisp->gimage, tu);
Nate Summers's avatar
Nate Summers committed
682
683
684
685
686
687
688
689
690
691
    }

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

692
693
694
695
#ifdef __GNUC__
#warning FIXME: investigate why display update was done here
#endif
#if 0
Nate Summers's avatar
Nate Summers committed
696
697
698
  /*  Flush the gdisplays  */
  if (gdisp->disp_xoffset || gdisp->disp_yoffset)
    {
699
700
701
702
      gint x, y;

      x = shell->disp_width;
      y = shell->disp_height;
703

Nate Summers's avatar
Nate Summers committed
704
705
      if (gdisp->disp_yoffset)
	{
Michael Natterer's avatar
Michael Natterer committed
706
707
708
709
710
711
712
	  gimp_display_shell_add_expose_area (shell,
                                              0, 0,
                                              gdisp->disp_width,
                                              gdisp->disp_yoffset);
	  gimp_display_shell_add_expose_area (shell,
                                              0, gdisp->disp_yoffset + y,
                                              gdisp->disp_width, gdisp->disp_height);
Nate Summers's avatar
Nate Summers committed
713
	}
Michael Natterer's avatar
Michael Natterer committed
714

Nate Summers's avatar
Nate Summers committed
715
716
      if (gdisp->disp_xoffset)
	{
Michael Natterer's avatar
Michael Natterer committed
717
718
719
720
721
722
	  gimp_display_shell_add_expose_area (shell,
                                              0, 0,
                                              gdisp->disp_xoffset, gdisp->disp_height);
	  gimp_display_shell_add_expose_area (shell,
                                              gdisp->disp_xoffset + x, 0,
                                              gdisp->disp_width, gdisp->disp_height);
Nate Summers's avatar
Nate Summers committed
723
724
	}
    }
725
#endif
Nate Summers's avatar
Nate Summers committed
726

727
  gimp_unset_busy (gdisp->gimage->gimp);
Nate Summers's avatar
Nate Summers committed
728
729
730

  gdisplays_flush ();

731
  gimp_transform_tool_reset (gt_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
732
733

  /*  if this tool is non-interactive, make it inactive after use  */
Nate Summers's avatar
Nate Summers committed
734
  if (!gt_tool->interactive)
Nate Summers's avatar
Nate Summers committed
735
736
737
    tool->state = INACTIVE;
}

738
static void
739
740
741
742
743
gimp_transform_tool_motion (GimpTool        *tool,
                            GimpCoords      *coords,
                            guint32          time,
		            GdkModifierType  state,
		            GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
744
{
Nate Summers's avatar
Nate Summers committed
745
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
746

747
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
748
749
750
751

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

755
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
756

757
758
759
  tr_tool->curx  = coords->x;
  tr_tool->cury  = coords->y;
  tr_tool->state = state;
Nate Summers's avatar
Nate Summers committed
760
761

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

Nate Summers's avatar
Nate Summers committed
764
765
  tr_tool->lastx = tr_tool->curx;
  tr_tool->lasty = tr_tool->cury;
Nate Summers's avatar
Nate Summers committed
766

767
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
768
769
}

770
static void
771
772
773
774
gimp_transform_tool_cursor_update (GimpTool        *tool,
                                   GimpCoords      *coords,
			           GdkModifierType  state,
			           GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
775
{
776
777
778
  GimpTransformTool *tr_tool;
  GimpDrawable      *drawable;
  GdkCursorType      ctype = GDK_TOP_LEFT_ARROW;
Nate Summers's avatar
Nate Summers committed
779

780
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
781
782
783

  if ((drawable = gimp_image_active_drawable (gdisp->gimage)))
    {
784
785
786
787
      gint off_x, off_y;

      gimp_drawable_offsets (drawable, &off_x, &off_y);

Nate Summers's avatar
Nate Summers committed
788
      if (GIMP_IS_LAYER (drawable) &&
789
          gimp_layer_get_mask (GIMP_LAYER (drawable)))
Nate Summers's avatar
Nate Summers committed
790
791
792
	{
	  ctype = GIMP_BAD_CURSOR;
	}
793
794
795
796
      else if (coords->x >= off_x &&
	       coords->y >= off_y &&
	       coords->x < (off_x + drawable->width) &&
	       coords->y < (off_y + drawable->height))
Nate Summers's avatar
Nate Summers committed
797
798
	{
	  if (gimage_mask_is_empty (gdisp->gimage) ||
799
	      gimage_mask_value (gdisp->gimage, coords->x, coords->y))
Nate Summers's avatar
Nate Summers committed
800
801
802
803
804
805
	    {
	      ctype = GIMP_MOUSE_CURSOR;
	    }
	}
    }

806
  gimp_display_shell_install_tool_cursor (GIMP_DISPLAY_SHELL (gdisp->shell),
Michael Natterer's avatar
Michael Natterer committed
807
808
809
                                          ctype,
                                          tool->tool_cursor,
                                          GIMP_CURSOR_MODIFIER_NONE);
Nate Summers's avatar
Nate Summers committed
810
811
}

812
static void
813
gimp_transform_tool_draw (GimpDrawTool *draw_tool)
Nate Summers's avatar
Nate Summers committed
814
{
815
816
817
818
  GimpTransformTool *tr_tool;
  gint               i, k, gci;

  tr_tool = GIMP_TRANSFORM_TOOL (draw_tool);
Nate Summers's avatar
Nate Summers committed
819
820

  /*  draw the bounding box  */
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  gimp_draw_tool_draw_line (draw_tool,
                            tr_tool->tx1, tr_tool->ty1,
                            tr_tool->tx2, tr_tool->ty2,
                            FALSE);
  gimp_draw_tool_draw_line (draw_tool,
                            tr_tool->tx2, tr_tool->ty2,
                            tr_tool->tx4, tr_tool->ty4,
                            FALSE);
  gimp_draw_tool_draw_line (draw_tool,
                            tr_tool->tx3, tr_tool->ty3,
                            tr_tool->tx4, tr_tool->ty4,
                            FALSE);
  gimp_draw_tool_draw_line (draw_tool,
                            tr_tool->tx3, tr_tool->ty3,
                            tr_tool->tx1, tr_tool->ty1,
                            FALSE);
Nate Summers's avatar
Nate Summers committed
837
838
839

  /*  Draw the grid */

Nate Summers's avatar
Nate Summers committed
840
  if ((tr_tool->grid_coords != NULL) &&
Nate Summers's avatar
Nate Summers committed
841
842
      (tr_tool->tgrid_coords != NULL) /* FIXME!!! this doesn't belong here &&
      ((tool->type != PERSPECTIVE)  ||
Nate Summers's avatar
Nate Summers committed
843
       ((tr_tool->transform[0][0] >=0.0) &&
Nate Summers's avatar
Nate Summers committed
844
	(tr_tool->transform[1][1] >=0.0)) */ ) 
Nate Summers's avatar
Nate Summers committed
845
846
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
847
      k = tr_tool->ngx + tr_tool->ngy;
848

Nate Summers's avatar
Nate Summers committed
849
850
      for (i = 0; i < k; i++)
	{
851
852
853
854
855
856
          gimp_draw_tool_draw_line (draw_tool,
                                    tr_tool->tgrid_coords[gci],
                                    tr_tool->tgrid_coords[gci + 1],
                                    tr_tool->tgrid_coords[gci + 2],
                                    tr_tool->tgrid_coords[gci + 3],
                                    FALSE);
Nate Summers's avatar
Nate Summers committed
857
858
859
860
861
	  gci += 4;
	}
    }

  /*  draw the tool handles  */
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
  gimp_draw_tool_draw_rectangle_by_center (draw_tool, FALSE,
                                           tr_tool->tx1, tr_tool->ty1,
                                           HANDLE, HANDLE,
                                           FALSE);
  gimp_draw_tool_draw_rectangle_by_center (draw_tool, FALSE,
                                           tr_tool->tx2, tr_tool->ty2,
                                           HANDLE, HANDLE,
                                           FALSE);
  gimp_draw_tool_draw_rectangle_by_center (draw_tool, FALSE,
                                           tr_tool->tx3, tr_tool->ty3,
                                           HANDLE, HANDLE,
                                           FALSE);
  gimp_draw_tool_draw_rectangle_by_center (draw_tool, FALSE,
                                           tr_tool->tx4, tr_tool->ty4,
                                           HANDLE, HANDLE,
                                           FALSE);
Nate Summers's avatar
Nate Summers committed
878
879

  /*  draw the center  */
880
881
882
883
884
  gimp_draw_tool_draw_arc_by_center (draw_tool, TRUE,
                                     tr_tool->tcx, tr_tool->tcy,
                                     HANDLE >> 1,
                                     0, 23040,
                                     FALSE);
Nate Summers's avatar
Nate Summers committed
885

886
  if (gimp_transform_tool_showpath ())
Nate Summers's avatar
Nate Summers committed
887
888
889
    {
      GimpMatrix3 tmp_matrix;

890
      if (gimp_transform_tool_direction () == TRANSFORM_CORRECTIVE)
Nate Summers's avatar
Nate Summers committed
891
	{
Nate Summers's avatar
Nate Summers committed
892
	  gimp_matrix3_invert (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
893
894
895
	}
      else
	{
Nate Summers's avatar
Nate Summers committed
896
	  gimp_matrix3_duplicate (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
897
898
	}

899
900
      path_transform_draw_current (GIMP_TOOL (draw_tool)->gdisp,
                                   draw_tool, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
901
902
903
904
    }
}

void
Nate Summers's avatar
Nate Summers committed
905
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
906
{
Nate Summers's avatar
Nate Summers committed
907
908
909
910
  GimpTool  *tool;
  gint       i, k;
  gint       gci;

911
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
912
913
914
915
916
917
918
919
920
921
922
923
924

  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
925

926
927
928
  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
929

Nate Summers's avatar
Nate Summers committed
930
931
  if (tr_tool->grid_coords != NULL &&
      tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
932
933
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
934
      k  = (tr_tool->ngx + tr_tool->ngy) * 2;
935

Nate Summers's avatar
Nate Summers committed
936
937
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
938
939
940
941
942
	  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
943
944
945
946
947
948
	  gci += 2;
	}
    }
}

void
949
gimp_transform_tool_reset (GimpTransformTool *tr_tool,
950
		           GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
951
{
Nate Summers's avatar
Nate Summers committed
952
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
953

954
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
955

Nate Summers's avatar
Nate Summers committed
956
  if (tr_tool->original)
957
958
959
960
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
Nate Summers's avatar
Nate Summers committed
961
962

  /*  inactivate the tool  */
Nate Summers's avatar
Nate Summers committed
963
  tr_tool->function = TRANSFORM_CREATING;
964
  gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
965
966
967
968
969
970
971
972
  info_dialog_popdown (transform_info);

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

static void
973
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
974
		            GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
975
{
976
977
978
  TileManager  *tiles;
  GimpDrawable *drawable;
  gint          offset_x, offset_y;
Nate Summers's avatar
Nate Summers committed
979

980
981
  tiles    = tr_tool->original;
  drawable = gimp_image_active_drawable (gdisp->gimage);
Nate Summers's avatar
Nate Summers committed
982
983
984
985
986

  /*  find the boundaries  */
  if (tiles)
    {
      tile_manager_get_offsets (tiles,
Nate Summers's avatar
Nate Summers committed
987
988
989
990
				&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
991
992
993
994
995
    }
  else
    {
      gimp_drawable_offsets (drawable, &offset_x, &offset_y);
      gimp_drawable_mask_bounds (drawable,
Nate Summers's avatar
Nate Summers committed
996
997
998
999
1000
1001
				 &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
1002
    }
Nate Summers's avatar
Nate Summers committed
1003
1004
1005

  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
1006
1007

  /*  changing the bounds invalidates any grid we may have  */
Nate Summers's avatar
Nate Summers committed
1008
  gimp_transform_tool_grid_recalc (tr_tool);
Nate Summers's avatar
Nate Summers committed
1009
1010
1011
1012
1013
}

void
gimp_transform_tool_grid_density_changed (void)
{
Nate Summers's avatar
Nate Summers committed
1014
1015
  GimpTransformTool *tr_tool;
  GimpDrawTool      *dr_tool;
Nate Summers's avatar
Nate Summers committed
1016

1017
1018
1019
  /* EEEK!!! */ 
  tr_tool = GIMP_TRANSFORM_TOOL (tool_manager_get_active (the_gimp));

1020
  dr_tool = GIMP_DRAW_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1021

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

Nate Summers's avatar
Nate Summers committed
1025
  gimp_draw_tool_pause (dr_tool);
1026

Nate Summers's avatar
Nate Summers committed
1027
1028
  gimp_transform_tool_grid_recalc (tr_tool);
  gimp_transform_tool_transform_bounding_box (tr_tool);
1029

Nate Summers's avatar
Nate Summers committed
1030
  gimp_draw_tool_resume (dr_tool);
Nate Summers's avatar
Nate Summers committed
1031
1032
1033
}

void
Nate Summers's avatar
Nate Summers committed
1034
gimp_transform_tool_showpath_changed (gint type /* a truly undescriptive name */)
Nate Summers's avatar
Nate Summers committed
1035
{
Nate Summers's avatar
Nate Summers committed
1036
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
1037

1038
1039
  /* EEEEEEEK!!! */ 
  tr_tool = GIMP_TRANSFORM_TOOL (tool_manager_get_active (the_gimp));
Nate Summers's avatar
Nate Summers committed
1040

Nate Summers's avatar
Nate Summers committed
1041
  if (tr_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
1042
1043
1044
    return;

  if (type)
1045
    gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1046
  else
1047
    gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1048
1049
1050
}

static void
Nate Summers's avatar
Nate Summers committed
1051
gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1052
{
Nate Summers's avatar
Nate Summers committed
1053
  if (tr_tool->grid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1054
    {
Nate Summers's avatar
Nate Summers committed
1055
1056
      g_free (tr_tool->grid_coords);
      tr_tool->grid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1057
    }
1058

Nate Summers's avatar
Nate Summers committed
1059
  if (tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1060
    {
Nate Summers's avatar
Nate Summers committed
1061
1062
      g_free (tr_tool->tgrid_coords);
      tr_tool->tgrid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1063
    }
1064

1065
  if (gimp_transform_tool_show_grid ())
1066
    gimp_transform_tool_setup_grid (tr_tool);
Nate Summers's avatar
Nate Summers committed
1067
1068
1069
}

static void
Nate Summers's avatar
Nate Summers committed
1070
gimp_transform_tool_setup_grid (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1071
{
1072
1073
1074
  GimpTool *tool;
  gint      i, gci;
  gdouble  *coords;
Nate Summers's avatar
Nate Summers committed
1075

1076
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1077

Nate Summers's avatar
Nate Summers committed
1078
  /*  We use the gimp_transform_tool_grid_size function only here, even
Nate Summers's avatar
Nate Summers committed
1079
1080
1081
   *  if the user changes the grid size in the middle of an
   *  operation, nothing happens.
   */
1082
  tr_tool->ngx = (tr_tool->x2 - tr_tool->x1) / gimp_transform_tool_grid_size ();
Nate Summers's avatar
Nate Summers committed
1083
1084
  if (tr_tool->ngx > 0)
    tr_tool->ngx--;
Nate Summers's avatar
Nate Summers committed
1085

1086
  tr_tool->ngy = (tr_tool->y2 - tr_tool->y1) / gimp_transform_tool_grid_size ();
Nate Summers's avatar
Nate Summers committed
1087
1088
  if (tr_tool->ngy > 0)
    tr_tool->ngy--;
Nate Summers's avatar
Nate Summers committed
1089

Nate Summers's avatar
Nate Summers committed
1090
  tr_tool->grid_coords = coords =
1091
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1092

Nate Summers's avatar
Nate Summers committed
1093
  tr_tool->tgrid_coords =
1094
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1095
1096

  gci = 0;
1097

Nate Summers's avatar
Nate Summers committed
1098
  for (i = 1; i <= tr_tool->ngx; i++)
Nate Summers's avatar
Nate Summers committed
1099
    {
Nate Summers's avatar
Nate Summers committed
1100
      coords[gci] = tr_tool->x1 +
1101
	((gdouble) i) / (tr_tool->ngx + 1) *
Nate Summers's avatar
Nate Summers committed
1102
1103
	(tr_tool->x2 - tr_tool->x1);
      coords[gci+1] = tr_tool->y1;
Nate Summers's avatar
Nate Summers committed
1104
      coords[gci+2] = coords[gci];
Nate Summers's avatar
Nate Summers committed
1105
      coords[gci+3] = tr_tool->y2;
Nate Summers's avatar
Nate Summers committed
1106
1107
      gci += 4;
    }
1108

Nate Summers's avatar
Nate Summers committed
1109
  for (i = 1; i <= tr_tool->ngy; i++)
Nate Summers's avatar
Nate Summers committed
1110
    {
Nate Summers's avatar
Nate Summers committed
1111
1112
      coords[gci] = tr_tool->x1;
      coords[gci+1] = tr_tool->y1 +
1113
	((gdouble) i) / (tr_tool->ngy + 1) *