gimptransformtool.c 44.9 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

Michael Natterer's avatar
Michael Natterer committed
30
#include "base/tile-manager.h"
31

Michael Natterer's avatar
Michael Natterer committed
32
#include "core/gimp.h"
33
#include "core/gimpchannel.h"
34
#include "core/gimpcontext.h"
Michael Natterer's avatar
Michael Natterer committed
35
#include "core/gimpdrawable-transform.h"
36
37
#include "core/gimpimage.h"
#include "core/gimpimage-mask.h"
38
#include "core/gimpimage-undo.h"
39
#include "core/gimpimage-undo-push.h"
40
#include "core/gimpitem-linked.h"
41
#include "core/gimplayer.h"
Michael Natterer's avatar
Michael Natterer committed
42
#include "core/gimptoolinfo.h"
43

44
45
46
#include "vectors/gimpvectors.h"
#include "vectors/gimpstroke.h"

47
#include "widgets/gimpdialogfactory.h"
Michael Natterer's avatar
Michael Natterer committed
48
49
#include "widgets/gimpviewabledialog.h"

50
#include "display/gimpdisplay.h"
Michael Natterer's avatar
Michael Natterer committed
51
#include "display/gimpprogress.h"
Nate Summers's avatar
Nate Summers committed
52

53
54
55
56
#ifdef __GNUC__
#warning FIXME #include "gui/gui-types.h"
#endif
#include "gui/gui-types.h"
57
58
#include "gui/info-dialog.h"

59
#include "gimptoolcontrol.h"
60
#include "gimptransformoptions.h"
61
62
#include "gimptransformtool.h"
#include "gimptransformtool-undo.h"
63

64
#include "gimp-intl.h"
Nate Summers's avatar
Nate Summers committed
65

66

67
#define HANDLE_SIZE 10
Michael Natterer's avatar
Michael Natterer committed
68

69

Michael Natterer's avatar
Michael Natterer committed
70
71
72
73
74
/*  local function prototypes  */

static void   gimp_transform_tool_init        (GimpTransformTool      *tool);
static void   gimp_transform_tool_class_init  (GimpTransformToolClass *tool);

75
76
77
static GObject * gimp_transform_tool_constructor   (GType              type,
                                                    guint              n_params,
                                                    GObjectConstructParam *params);
Michael Natterer's avatar
Michael Natterer committed
78
79
static void   gimp_transform_tool_finalize         (GObject           *object);

80
81
static void   gimp_transform_tool_initialize       (GimpTool          *tool,
                                                    GimpDisplay       *gdisp);
Michael Natterer's avatar
Michael Natterer committed
82
static void   gimp_transform_tool_control          (GimpTool          *tool,
83
                                                    GimpToolAction     action,
Michael Natterer's avatar
Michael Natterer committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
                                                    GimpDisplay       *gdisp);
static void   gimp_transform_tool_button_press     (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    guint32            time,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
static void   gimp_transform_tool_button_release   (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    guint32            time,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
static void   gimp_transform_tool_motion           (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    guint32            time,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
100
101
102
103
104
static void   gimp_transform_tool_modifier_key     (GimpTool          *tool,
                                                    GdkModifierType    key,
                                                    gboolean           press,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
105
106
107
108
static void   gimp_transform_tool_oper_update      (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
Michael Natterer's avatar
Michael Natterer committed
109
110
111
112
113
114
115
static void   gimp_transform_tool_cursor_update    (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);

static void   gimp_transform_tool_draw             (GimpDrawTool      *draw_tool);

116
117
static TileManager *
              gimp_transform_tool_real_transform   (GimpTransformTool *tr_tool,
118
                                                    GimpItem          *item,
119
120
                                                    GimpDisplay       *gdisp);

121
static void   gimp_transform_tool_halt             (GimpTransformTool *tr_tool);
Michael Natterer's avatar
Michael Natterer committed
122
123
static void   gimp_transform_tool_bounds           (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp);
Michael Natterer's avatar
Michael Natterer committed
124
125
126
static void   gimp_transform_tool_dialog           (GimpTransformTool *tr_tool);
static void   gimp_transform_tool_prepare          (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp);
Michael Natterer's avatar
Michael Natterer committed
127
128
129
130
131
132
133
static void   gimp_transform_tool_recalc           (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp);
static void   gimp_transform_tool_doit             (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp);
static void   gimp_transform_tool_grid_recalc      (GimpTransformTool *tr_tool);

static void   transform_reset_callback             (GtkWidget         *widget,
Michael Natterer's avatar
Michael Natterer committed
134
135
136
137
138
                                                    GimpTransformTool *tr_tool);
static void   transform_cancel_callback            (GtkWidget         *widget,
                                                    GimpTransformTool *tr_tool);
static void   transform_ok_callback                (GtkWidget         *widget,
                                                    GimpTransformTool *tr_tool);
139

140
static void   gimp_transform_tool_notify_type   (GimpTransformOptions *options,
141
142
                                                 GParamSpec           *pspec,
                                                 GimpTransformTool    *tr_tool);
143
static void   gimp_transform_tool_notify_grid   (GimpTransformOptions *options,
144
145
146
                                                 GParamSpec           *pspec,
                                                 GimpTransformTool    *tr_tool);

147

148
static GimpDrawToolClass *parent_class = NULL;
149

150
151

GType
Nate Summers's avatar
Nate Summers committed
152
153
gimp_transform_tool_get_type (void)
{
154
  static GType tool_type = 0;
Nate Summers's avatar
Nate Summers committed
155
156
157

  if (! tool_type)
    {
158
      static const GTypeInfo tool_info =
Nate Summers's avatar
Nate Summers committed
159
160
      {
        sizeof (GimpTransformToolClass),
161
162
163
164
165
166
167
168
	(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
169
170
      };

171
      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
172
					  "GimpTransformTool",
173
                                          &tool_info, 0);
Nate Summers's avatar
Nate Summers committed
174
175
176
177
178
179
180
181
    }

  return tool_type;
}

static void
gimp_transform_tool_class_init (GimpTransformToolClass *klass)
{
182
  GObjectClass      *object_class;
Nate Summers's avatar
Nate Summers committed
183
184
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_class;
Nate Summers's avatar
Nate Summers committed
185

186
187
188
  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
189

190
  parent_class = g_type_class_peek_parent (klass);
Nate Summers's avatar
Nate Summers committed
191

192
  object_class->constructor  = gimp_transform_tool_constructor;
193
  object_class->finalize     = gimp_transform_tool_finalize;
Nate Summers's avatar
Nate Summers committed
194

195
  tool_class->initialize     = gimp_transform_tool_initialize;
196
  tool_class->control        = gimp_transform_tool_control;
Nate Summers's avatar
Nate Summers committed
197
198
199
  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;
200
  tool_class->modifier_key   = gimp_transform_tool_modifier_key;
201
  tool_class->oper_update    = gimp_transform_tool_oper_update;
Nate Summers's avatar
Nate Summers committed
202
  tool_class->cursor_update  = gimp_transform_tool_cursor_update;
Nate Summers's avatar
Nate Summers committed
203
204

  draw_class->draw           = gimp_transform_tool_draw;
Michael Natterer's avatar
Michael Natterer committed
205
206
207
208
209

  klass->dialog              = NULL;
  klass->prepare             = NULL;
  klass->motion              = NULL;
  klass->recalc              = NULL;
210
  klass->transform           = gimp_transform_tool_real_transform;
Nate Summers's avatar
Nate Summers committed
211
212
213
}

static void
Michael Natterer's avatar
Michael Natterer committed
214
gimp_transform_tool_init (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
215
{
Michael Natterer's avatar
Michael Natterer committed
216
  GimpTool *tool;
217
  gint      i;
Nate Summers's avatar
Nate Summers committed
218

Michael Natterer's avatar
Michael Natterer committed
219
  tool = GIMP_TOOL (tr_tool);
Michael Natterer's avatar
Michael Natterer committed
220

Michael Natterer's avatar
Michael Natterer committed
221
222
223
  gimp_tool_control_set_scroll_lock (tool->control, TRUE);
  gimp_tool_control_set_preserve    (tool->control, FALSE);

Michael Natterer's avatar
Michael Natterer committed
224
225
  tr_tool->function = TRANSFORM_CREATING;
  tr_tool->original = NULL;
Nate Summers's avatar
Nate Summers committed
226
227

  for (i = 0; i < TRAN_INFO_SIZE; i++)
228
    {
Michael Natterer's avatar
Michael Natterer committed
229
230
      tr_tool->trans_info[i]     = 0.0;
      tr_tool->old_trans_info[i] = 0.0;
231
    }
Nate Summers's avatar
Nate Summers committed
232

233
  gimp_matrix3_identity (&tr_tool->transform);
234

235
236
237
238
239
240
241
  tr_tool->use_grid         = TRUE;
  tr_tool->use_center       = TRUE;
  tr_tool->ngx              = 0;
  tr_tool->ngy              = 0;
  tr_tool->grid_coords      = NULL;
  tr_tool->tgrid_coords     = NULL;

242
  tr_tool->type             = GIMP_TRANSFORM_TYPE_LAYER;
243
  tr_tool->direction        = GIMP_TRANSFORM_FORWARD;
244

245
246
247
  tr_tool->shell_desc       = NULL;
  tr_tool->progress_text    = _("Transforming...");
  tr_tool->info_dialog      = NULL;
Nate Summers's avatar
Nate Summers committed
248
249
}

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
static GObject *
gimp_transform_tool_constructor (GType                  type,
                                 guint                  n_params,
                                 GObjectConstructParam *params)
{
  GObject           *object;
  GimpTool          *tool;
  GimpTransformTool *tr_tool;

  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);

  tool    = GIMP_TOOL (object);
  tr_tool = GIMP_TRANSFORM_TOOL (object);

  g_assert (GIMP_IS_TOOL_INFO (tool->tool_info));

  if (tr_tool->use_grid)
    {
      tr_tool->type =
        GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options)->type;
      tr_tool->direction =
        GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options)->direction;

      g_signal_connect_object (tool->tool_info->tool_options,
                               "notify::type",
                               G_CALLBACK (gimp_transform_tool_notify_type),
                               tr_tool, 0);
      g_signal_connect_object (tool->tool_info->tool_options,
                               "notify::direction",
                               G_CALLBACK (gimp_transform_tool_notify_type),
                               tr_tool, 0);
      g_signal_connect_object (tool->tool_info->tool_options,
                               "notify::grid-type",
                               G_CALLBACK (gimp_transform_tool_notify_grid),
                               tr_tool, 0);
      g_signal_connect_object (tool->tool_info->tool_options,
                               "notify::grid-size",
                               G_CALLBACK (gimp_transform_tool_notify_grid),
                               tr_tool, 0);
    }

  return object;
}

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
      tile_manager_unref (tr_tool->original);
304
305
      tr_tool->original = NULL;
    }
306

307
  if (tr_tool->info_dialog)
308
    {
309
310
      info_dialog_free (tr_tool->info_dialog);
      tr_tool->info_dialog = NULL;
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    }

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

328
329
330
331
332
333
334
335
336
static void
gimp_transform_tool_initialize (GimpTool    *tool,
				GimpDisplay *gdisp)
{
  GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);

  if (gdisp != tool->gdisp)
    {
      GimpDrawable *drawable = gimp_image_active_drawable (gdisp->gimage);
337
      gint          i;
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

      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."));
          return;
        }

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

      /*  Initialize the transform tool dialog */
      if (! tr_tool->info_dialog)
        gimp_transform_tool_dialog (tr_tool);

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

      gimp_transform_tool_prepare (tr_tool, gdisp);

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

      /*  start drawing the bounding box and handles...  */
      gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), gdisp);

      tr_tool->function = TRANSFORM_CREATING;

      /*  Save the current transformation info  */
      for (i = 0; i < TRAN_INFO_SIZE; i++)
	tr_tool->old_trans_info[i] = tr_tool->trans_info[i];
    }
}

377
static void
378
379
380
gimp_transform_tool_control (GimpTool       *tool,
			     GimpToolAction  action,
			     GimpDisplay    *gdisp)
381
{
Michael Natterer's avatar
Michael Natterer committed
382
  GimpTransformTool *tr_tool;
383

Michael Natterer's avatar
Michael Natterer committed
384
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
385

386
387
388
389
  switch (action)
    {
    case PAUSE:
      break;
390

391
    case RESUME:
Michael Natterer's avatar
Michael Natterer committed
392
      gimp_transform_tool_recalc (tr_tool, gdisp);
393
      break;
394

395
    case HALT:
396
      gimp_transform_tool_halt (tr_tool);
397
      return; /* don't upchain */
398
      break;
399

400
401
402
403
    default:
      break;
    }

Michael Natterer's avatar
Michael Natterer committed
404
  GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
405
406
407
}

static void
408
409
410
411
412
gimp_transform_tool_button_press (GimpTool        *tool,
                                  GimpCoords      *coords,
                                  guint32          time,
                                  GdkModifierType  state,
			          GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
413
{
Michael Natterer's avatar
Michael Natterer committed
414
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
415

416
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
417

418
419
  if (tr_tool->function == TRANSFORM_CREATING && tr_tool->use_grid)
    gimp_transform_tool_oper_update (tool, coords, state, gdisp);
420

421
422
  tr_tool->lastx = tr_tool->startx = coords->x;
  tr_tool->lasty = tr_tool->starty = coords->y;
Nate Summers's avatar
Nate Summers committed
423

424
  gimp_tool_control_activate (tool->control);
Nate Summers's avatar
Nate Summers committed
425
426
}

427
static void
428
429
430
431
432
gimp_transform_tool_button_release (GimpTool        *tool,
                                    GimpCoords      *coords,
                                    guint32          time,
			            GdkModifierType  state,
			            GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
433
{
Michael Natterer's avatar
Michael Natterer committed
434
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
435
  gint               i;
Nate Summers's avatar
Nate Summers committed
436

Michael Natterer's avatar
Michael Natterer committed
437
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
438
439

  /*  if we are creating, there is nothing to be done...exit  */
440
  if (tr_tool->function == TRANSFORM_CREATING && tr_tool->use_grid)
Nate Summers's avatar
Nate Summers committed
441
442
443
    return;

  /*  if the 3rd button isn't pressed, transform the selected mask  */
444
  if (! (state & GDK_BUTTON3_MASK))
Nate Summers's avatar
Nate Summers committed
445
446
    {
      /* Shift-clicking is another way to approve the transform  */
447
      if ((state & GDK_SHIFT_MASK) || ! tr_tool->use_grid)
Nate Summers's avatar
Nate Summers committed
448
	{
Michael Natterer's avatar
Michael Natterer committed
449
	  gimp_transform_tool_doit (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
450
451
452
453
	}
    }
  else
    {
454
      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
455
456
457

      /*  Restore the previous transformation info  */
      for (i = 0; i < TRAN_INFO_SIZE; i++)
458
	tr_tool->trans_info[i] = tr_tool->old_trans_info[i];
Nate Summers's avatar
Nate Summers committed
459
460

      /*  recalculate the tool's transformation matrix  */
Michael Natterer's avatar
Michael Natterer committed
461
      gimp_transform_tool_recalc (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
462

463
      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
464
    }
465
466

  gimp_tool_control_halt (tool->control);
Nate Summers's avatar
Nate Summers committed
467
468
}

469
static void
470
471
472
473
474
gimp_transform_tool_motion (GimpTool        *tool,
                            GimpCoords      *coords,
                            guint32          time,
		            GdkModifierType  state,
		            GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
475
{
Michael Natterer's avatar
Michael Natterer committed
476
477
  GimpTransformToolClass *tr_tool_class;
  GimpTransformTool      *tr_tool;
Nate Summers's avatar
Nate Summers committed
478

Michael Natterer's avatar
Michael Natterer committed
479
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
480

481
  /*  if we are creating, there is nothing to be done so exit.  */
482
  if (tr_tool->function == TRANSFORM_CREATING || ! tr_tool->use_grid)
Nate Summers's avatar
Nate Summers committed
483
484
    return;

485
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
486

Michael Natterer's avatar
Michael Natterer committed
487
488
489
  tr_tool->curx  = coords->x;
  tr_tool->cury  = coords->y;
  tr_tool->state = state;
Nate Summers's avatar
Nate Summers committed
490
491

  /*  recalculate the tool's transformation matrix  */
Michael Natterer's avatar
Michael Natterer committed
492
493
494
495
496
  tr_tool_class = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool);

  if (tr_tool_class->motion)
    {
      tr_tool_class->motion (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
497

Michael Natterer's avatar
Michael Natterer committed
498
499
500
501
502
503
      if (tr_tool_class->recalc)
        tr_tool_class->recalc (tr_tool, gdisp);
    }

  tr_tool->lastx = tr_tool->curx;
  tr_tool->lasty = tr_tool->cury;
Nate Summers's avatar
Nate Summers committed
504

505
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
506
507
}

508
509
510
511
512
513
514
static void
gimp_transform_tool_modifier_key (GimpTool        *tool,
                                  GdkModifierType  key,
                                  gboolean         press,
                                  GdkModifierType  state,
                                  GimpDisplay     *gdisp)
{
515
  GimpTransformOptions *options;
516

517
  options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
518

519
  if (key == GDK_CONTROL_MASK)
520
    {
521
      g_object_set (options,
522
523
                    "constrain-1", ! options->constrain_1,
                    NULL);
524
    }
525
  else if (key == GDK_MOD1_MASK)
526
    {
527
      g_object_set (options,
528
529
                    "constrain-2", ! options->constrain_2,
                    NULL);
530
531
532
    }
}

533
534
535
536
537
538
539
540
541
542
543
544
static void
gimp_transform_tool_oper_update (GimpTool        *tool,
                                 GimpCoords      *coords,
                                 GdkModifierType  state,
                                 GimpDisplay     *gdisp)
{
  GimpTransformTool *tr_tool;
  GimpDrawTool      *draw_tool;

  tr_tool   = GIMP_TRANSFORM_TOOL (tool);
  draw_tool = GIMP_DRAW_TOOL (tool);

545
546
547
  if (! tr_tool->use_grid)
    return;

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
  if (gdisp == tool->gdisp)
    {
      gdouble closest_dist;
      gdouble dist;

      closest_dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                                   coords->x, coords->y,
                                                   tr_tool->tx1, tr_tool->ty1);
      tr_tool->function = TRANSFORM_HANDLE_1;

      dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                           coords->x, coords->y,
                                           tr_tool->tx2, tr_tool->ty2);
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  tr_tool->function = TRANSFORM_HANDLE_2;
	}

      dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                           coords->x, coords->y,
                                           tr_tool->tx3, tr_tool->ty3);
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  tr_tool->function = TRANSFORM_HANDLE_3;
	}

      dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
                                           coords->x, coords->y,
                                           tr_tool->tx4, tr_tool->ty4);
      if (dist < closest_dist)
	{
	  closest_dist = dist;
	  tr_tool->function = TRANSFORM_HANDLE_4;
	}

      if (gimp_draw_tool_on_handle (draw_tool, gdisp,
                                    coords->x, coords->y,
                                    GIMP_HANDLE_CIRCLE,
                                    tr_tool->tcx, tr_tool->tcy,
589
                                    HANDLE_SIZE, HANDLE_SIZE,
590
591
592
593
594
595
596
597
                                    GTK_ANCHOR_CENTER,
                                    FALSE))
	{
	  tr_tool->function = TRANSFORM_HANDLE_CENTER;
	}
    }
}

598
static void
599
600
601
602
gimp_transform_tool_cursor_update (GimpTool        *tool,
                                   GimpCoords      *coords,
			           GdkModifierType  state,
			           GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
603
{
604
605
  GimpTransformTool    *tr_tool;
  GimpTransformOptions *options;
606
607

  tr_tool = GIMP_TRANSFORM_TOOL (tool);
608
  options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
Nate Summers's avatar
Nate Summers committed
609

Michael Natterer's avatar
Michael Natterer committed
610
  if (tr_tool->use_grid)
Nate Summers's avatar
Nate Summers committed
611
    {
Michael Natterer's avatar
Michael Natterer committed
612
613
      GdkCursorType      ctype     = GDK_TOP_LEFT_ARROW;
      GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE;
614

615
      switch (options->type)
Michael Natterer's avatar
Michael Natterer committed
616
        {
617
618
619
620
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
        case GIMP_TRANSFORM_TYPE_LAYER:
          {
            GimpDrawable *drawable;

            drawable = gimp_image_active_drawable (gdisp->gimage);

            if (drawable)
              {
                if (GIMP_IS_LAYER (drawable) &&
                    gimp_layer_get_mask (GIMP_LAYER (drawable)))
                  {
                    ctype = GIMP_BAD_CURSOR;
                  }
                else if (gimp_display_coords_in_active_drawable (gdisp, coords))
                  {
                    if (gimp_image_mask_is_empty (gdisp->gimage) ||
                        gimp_image_mask_value (gdisp->gimage,
                                               coords->x, coords->y))
                      {
                        ctype = GIMP_MOUSE_CURSOR;
                      }
                  }
              }
          }
          break;

        case GIMP_TRANSFORM_TYPE_SELECTION:
          if (gimp_image_mask_is_empty (gdisp->gimage) ||
              gimp_image_mask_value (gdisp->gimage, coords->x, coords->y))
Michael Natterer's avatar
Michael Natterer committed
646
            {
647
              ctype = GIMP_MOUSE_CURSOR;
Michael Natterer's avatar
Michael Natterer committed
648
            }
649
650
651
652
653
654
655
656
          break;

        case GIMP_TRANSFORM_TYPE_PATH:
          if (gimp_image_get_active_vectors (gdisp->gimage))
            ctype = GIMP_MOUSE_CURSOR;
          else
            ctype = GIMP_BAD_CURSOR;
          break;
Michael Natterer's avatar
Michael Natterer committed
657
        }
658

Michael Natterer's avatar
Michael Natterer committed
659
660
661
662
663
664
665
666
      if (tr_tool->use_center && tr_tool->function == TRANSFORM_HANDLE_CENTER)
        {
          cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
        }

      gimp_tool_control_set_cursor          (tool->control, ctype);
      gimp_tool_control_set_cursor_modifier (tool->control, cmodifier);
    }
667
668

  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, gdisp);
Nate Summers's avatar
Nate Summers committed
669
670
}

671
static void
672
gimp_transform_tool_draw (GimpDrawTool *draw_tool)
Nate Summers's avatar
Nate Summers committed
673
{
674
  GimpTool             *tool;
675
676
  GimpTransformTool    *tr_tool;
  GimpTransformOptions *options;
677
678
  gdouble z1, z2, z3, z4;

679
680

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

682
683
684
  if (! tr_tool->use_grid)
    return;

685
  tool    = GIMP_TOOL (draw_tool);
686
  options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
687

Nate Summers's avatar
Nate Summers committed
688
  /*  draw the bounding box  */
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
  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
705

706
707
708
709
710
711
712
713
714
715
716
717
718
  /* We test if the transformed polygon is convex.
   * if z1 and z2 have the same sign as well as z3 and z4
   * the polygon is convex. */

  z1 = (tr_tool->tx2-tr_tool->tx1)*(tr_tool->ty4-tr_tool->ty1)
          -(tr_tool->tx4-tr_tool->tx1)*(tr_tool->ty2-tr_tool->ty1);
  z2 = (tr_tool->tx4-tr_tool->tx1)*(tr_tool->ty3-tr_tool->ty1)
          -(tr_tool->tx3-tr_tool->tx1)*(tr_tool->ty4-tr_tool->ty1);
  z3 = (tr_tool->tx4-tr_tool->tx2)*(tr_tool->ty3-tr_tool->ty2)
          -(tr_tool->tx3-tr_tool->tx2)*(tr_tool->ty4-tr_tool->ty2);
  z4 = (tr_tool->tx3-tr_tool->tx2)*(tr_tool->ty1-tr_tool->ty2)
          -(tr_tool->tx1-tr_tool->tx2)*(tr_tool->ty3-tr_tool->ty2);

719
  /*  Draw the grid (not for path transform since it looks ugly)  */
Nate Summers's avatar
Nate Summers committed
720

721
722
723
  if (tr_tool->type != GIMP_TRANSFORM_TYPE_PATH &&
      tr_tool->grid_coords                      &&
      tr_tool->tgrid_coords                     &&
724
725
      z1 * z2 > 0                               &&
      z3 * z4 > 0)
Nate Summers's avatar
Nate Summers committed
726
    {
727
728
      gint gci, i, k;

Nate Summers's avatar
Nate Summers committed
729
      k = tr_tool->ngx + tr_tool->ngy;
730

731
      for (i = 0, gci = 0; i < k; i++, gci += 4)
Nate Summers's avatar
Nate Summers committed
732
	{
733
734
735
736
737
738
          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
739
740
741
742
	}
    }

  /*  draw the tool handles  */
743
744
745
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx1, tr_tool->ty1,
746
                              HANDLE_SIZE, HANDLE_SIZE,
747
748
749
750
751
                              GTK_ANCHOR_CENTER,
                              FALSE);
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx2, tr_tool->ty2,
752
                              HANDLE_SIZE, HANDLE_SIZE,
753
754
755
756
757
                              GTK_ANCHOR_CENTER,
                              FALSE);
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx3, tr_tool->ty3,
758
                              HANDLE_SIZE, HANDLE_SIZE,
759
760
761
762
763
                              GTK_ANCHOR_CENTER,
                              FALSE);
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx4, tr_tool->ty4,
764
                              HANDLE_SIZE, HANDLE_SIZE,
765
766
                              GTK_ANCHOR_CENTER,
                              FALSE);
Nate Summers's avatar
Nate Summers committed
767
768

  /*  draw the center  */
769
770
771
772
773
  if (tr_tool->use_center)
    {
      gimp_draw_tool_draw_handle (draw_tool,
                                  GIMP_HANDLE_FILLED_CIRCLE,
                                  tr_tool->tcx, tr_tool->tcy,
774
                                  HANDLE_SIZE, HANDLE_SIZE,
775
776
777
                                  GTK_ANCHOR_CENTER,
                                  FALSE);
    }
Nate Summers's avatar
Nate Summers committed
778

779
  if (tr_tool->type == GIMP_TRANSFORM_TYPE_PATH)
Nate Summers's avatar
Nate Summers committed
780
    {
781
782
783
      GimpVectors *vectors;
      GimpStroke  *stroke = NULL;
      GimpMatrix3  matrix = tr_tool->transform;
784

785
786
787
      vectors = gimp_image_get_active_vectors (tool->gdisp->gimage);

      if (vectors)
788
        {
789
790
791
792
793
794
795
796
797
798
799
          if (tr_tool->direction == GIMP_TRANSFORM_BACKWARD)
            gimp_matrix3_invert (&matrix);

          while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
            {
              GArray   *coords;
              gboolean  closed;
              gint      i;

              coords = gimp_stroke_interpolate (stroke, 1.0, &closed);

800
              if (coords)
801
                {
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
                  for (i = 0; i < coords->len; i++)
                    {
                      GimpCoords *curr = &g_array_index (coords, GimpCoords, i);

                      gimp_matrix3_transform_point (&matrix,
                                                    curr->x, curr->y,
                                                    &curr->x, &curr->y);
                    }

                  if (coords->len)
                    gimp_draw_tool_draw_strokes (draw_tool,
                                                 &g_array_index (coords,
                                                                 GimpCoords, 0),
                                                 coords->len, FALSE, FALSE);

                  g_array_free (coords, TRUE);
818
819
                }
            }
820
        }
Nate Summers's avatar
Nate Summers committed
821
822
823
    }
}

824
825
static TileManager *
gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
826
                                    GimpItem          *active_item,
827
828
                                    GimpDisplay       *gdisp)
{
829
830
831
  GimpTool             *tool;
  GimpTransformOptions *options;
  GimpProgress         *progress;
832
  TileManager          *ret = NULL;
833

834
835
  tool    = GIMP_TOOL (tr_tool);
  options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
836
837
838
839
840
841
842

  if (tr_tool->info_dialog)
    gtk_widget_set_sensitive (GTK_WIDGET (tr_tool->info_dialog->shell), FALSE);

  progress = gimp_progress_start (gdisp, tr_tool->progress_text, FALSE,
                                  NULL, NULL);

843
  if (gimp_item_get_linked (active_item))
844
    gimp_item_linked_transform (active_item, &tr_tool->transform,
845
846
847
848
849
                                options->direction,
                                options->interpolation, options->clip,
                                progress ?
                                gimp_progress_update_and_flush : NULL,
                                progress);
850

851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
  switch (options->type)
    {
    case GIMP_TRANSFORM_TYPE_LAYER:
    case GIMP_TRANSFORM_TYPE_SELECTION:
      {
        gboolean clip_result = options->clip;

        /*  always clip the selction and unfloated channels
         *  so they keep their size
         */
        if (GIMP_IS_CHANNEL (active_item) &&
            tile_manager_bpp (tr_tool->original) == 1)
          clip_result = TRUE;

        ret =
          gimp_drawable_transform_tiles_affine (GIMP_DRAWABLE (active_item),
                                                tr_tool->original,
868
                                                &tr_tool->transform,
869
870
871
872
                                                options->direction,
                                                options->interpolation,
                                                clip_result,
                                                progress ?
873
                                                gimp_progress_update_and_flush :
874
875
876
877
                                                NULL,
                                                progress);
      }
      break;
878

879
    case GIMP_TRANSFORM_TYPE_PATH:
880
881
882
883
884
885
886
887
888
      gimp_item_transform (active_item,
                           &tr_tool->transform,
                           options->direction,
                           options->interpolation,
                           options->clip,
                           progress ?
                           gimp_progress_update_and_flush :
                           NULL,
                           progress);
889
890
      break;
    }
891
892
893
894
895
896
897

  if (progress)
    gimp_progress_end (progress);

  return ret;
}

Michael Natterer's avatar
Michael Natterer committed
898
899
900
901
static void
gimp_transform_tool_doit (GimpTransformTool  *tr_tool,
		          GimpDisplay        *gdisp)
{
902
903
  GimpTool             *tool;
  GimpTransformOptions *options;
904
  GimpItem             *active_item = NULL;
905
906
  TileManager          *new_tiles;
  gboolean              new_layer;
Michael Natterer's avatar
Michael Natterer committed
907

908
909
  tool    = GIMP_TOOL (tr_tool);
  options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
Michael Natterer's avatar
Michael Natterer committed
910

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
  switch (options->type)
    {
    case GIMP_TRANSFORM_TYPE_LAYER:
      active_item = (GimpItem *) gimp_image_active_drawable (gdisp->gimage);
      break;

    case GIMP_TRANSFORM_TYPE_SELECTION:
      active_item = (GimpItem *) gimp_image_get_mask (gdisp->gimage);
      break;

    case GIMP_TRANSFORM_TYPE_PATH:
      active_item = (GimpItem *) gimp_image_get_active_vectors (gdisp->gimage);
      break;
    }

  if (! active_item)
    return;

  gimp_set_busy (gdisp->gimage->gimp);

Michael Natterer's avatar
Michael Natterer committed
931
  /* undraw the tool before we muck around with the transform matrix */
932
  gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
Michael Natterer's avatar
Michael Natterer committed
933

934
  /*  We're going to dirty this image, but we want to keep the tool around  */
935
  gimp_tool_control_set_preserve (tool->control, TRUE);
Michael Natterer's avatar
Michael Natterer committed
936
937

  /*  Start a transform undo group  */
938
  gimp_image_undo_group_start (gdisp->gimage, GIMP_UNDO_GROUP_TRANSFORM,
939
                               tool->tool_info->blurb);
Michael Natterer's avatar
Michael Natterer committed
940
941
942
943
944
945
946
947
948
949
950
951

  /* With the old UI, if original is NULL, then this is the
   * first transformation. In the new UI, it is always so, right?
   */
  g_assert (tr_tool->original == NULL);

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

952
953
954
955
956
957
958
959
  switch (options->type)
    {
    case GIMP_TRANSFORM_TYPE_LAYER:
      tr_tool->original = gimp_drawable_transform_cut (tool->drawable,
                                                       &new_layer);
      break;

    case GIMP_TRANSFORM_TYPE_SELECTION:
960
      tr_tool->original = tile_manager_ref (GIMP_DRAWABLE (active_item)->tiles);
961
962
963
964
965
966
967
      tile_manager_set_offsets (tr_tool->original, 0, 0);
      break;

    case GIMP_TRANSFORM_TYPE_PATH:
      tr_tool->original = NULL;
      break;
    }
Michael Natterer's avatar
Michael Natterer committed
968
969
970

  /*  Send the request for the transformation to the tool...
   */
971
  new_tiles = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->transform (tr_tool,
972
                                                                  active_item,
973
                                                                  gdisp);
Michael Natterer's avatar
Michael Natterer committed
974

Michael Natterer's avatar
Michael Natterer committed
975
  gimp_transform_tool_prepare (tr_tool, gdisp);
Michael Natterer's avatar
Michael Natterer committed
976
977
  gimp_transform_tool_recalc (tr_tool, gdisp);

978
  switch (options->type)
Michael Natterer's avatar
Michael Natterer committed
979
    {
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
    case GIMP_TRANSFORM_TYPE_LAYER:
      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_drawable_transform_paste (tool->drawable,
                                         new_tiles,
                                         new_layer);
          tile_manager_unref (new_tiles);
        }
      break;

     case GIMP_TRANSFORM_TYPE_SELECTION:
      if (new_tiles)
        {
          gimp_image_mask_push_undo (gdisp->gimage, NULL);
Michael Natterer's avatar
Michael Natterer committed
998

999
          tile_manager_unref (GIMP_DRAWABLE (active_item)->tiles);
1000
1001
1002
1003
1004
1005
          GIMP_DRAWABLE (active_item)->tiles = new_tiles;

          GIMP_CHANNEL (active_item)->bounds_known = FALSE;

          gimp_image_mask_changed (gdisp->gimage);
        }
1006
1007
1008

      tile_manager_unref (tr_tool->original);
      tr_tool->original = NULL;
1009
1010
1011
      break;

    case GIMP_TRANSFORM_TYPE_PATH:
1012
      /*  Nothing to be done  */
1013
      break;
Michael Natterer's avatar
Michael Natterer committed
1014
1015
    }

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  /*  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);

  gimp_transform_tool_push_undo (gdisp->gimage, NULL,
                                 tool->ID,
                                 G_TYPE_FROM_INSTANCE (tool),
                                 tr_tool->old_trans_info,
                                 NULL);

Michael Natterer's avatar
Michael Natterer committed
1027
  /*  push the undo group end  */
1028
  gimp_image_undo_group_end (gdisp->gimage);
Michael Natterer's avatar
Michael Natterer committed
1029
1030
1031
1032

  /*  We're done dirtying the image, and would like to be restarted
   *  if the image gets dirty while the tool exists
   */
1033
  gimp_tool_control_set_preserve (tool->control, FALSE);
Michael Natterer's avatar
Michael Natterer committed
1034
1035
1036

  gimp_unset_busy (gdisp->gimage->gimp);

1037
  gimp_image_flush (gdisp->gimage);
Michael Natterer's avatar
Michael Natterer committed
1038

1039
  gimp_transform_tool_halt (tr_tool);
Michael Natterer's avatar
Michael Natterer committed
1040
1041
}

Nate Summers's avatar
Nate Summers committed
1042
void
Nate Summers's avatar
Nate Summers committed
1043
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1044
{
1045
  g_return_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
1046

1047
  gimp_matrix3_transform_point (&tr_tool->transform,
Nate Summers's avatar
Nate Summers committed
1048
1049
				tr_tool->x1, tr_tool->y1,
				&tr_tool->tx1, &tr_tool->ty1);
1050
  gimp_matrix3_transform_point (&tr_tool->transform,
Nate Summers's avatar
Nate Summers committed
1051
1052
				tr_tool->x2, tr_tool->y1,
				&tr_tool->tx2, &tr_tool->ty2);
1053
  gimp_matrix3_transform_point (&tr_tool->transform,
Nate Summers's avatar
Nate Summers committed
1054
1055
				tr_tool->x1, tr_tool->y2,
				&tr_tool->tx3, &tr_tool->ty3);
1056
  gimp_matrix3_transform_point (&tr_tool->transform,
Nate Summers's avatar
Nate Summers committed
1057
1058
				tr_tool->x2, tr_tool->y2,
				&tr_tool->tx4, &tr_tool->ty4);
Nate Summers's avatar
Nate Summers committed
1059

1060
  gimp_matrix3_transform_point (&tr_tool->transform,
1061
1062
				tr_tool->cx, tr_tool->cy,
				&tr_tool->tcx, &tr_tool->tcy);
Nate Summers's avatar
Nate Summers committed
1063

1064
  if (tr_tool->grid_coords != NULL && tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1065
    {
1066
1067
1068
      gint i, k;
      gint gci;

Nate Summers's avatar
Nate Summers committed
1069
      gci = 0;
1070
      k   = (tr_tool->ngx + tr_tool->ngy) * 2;
1071

Nate Summers's avatar
Nate Summers committed
1072
1073
      for (i = 0; i < k; i++)
	{
1074
	  gimp_matrix3_transform_point (&tr_tool->transform,
Nate Summers's avatar
Nate Summers committed
1075
					tr_tool->grid_coords[gci],
1076
1077
1078
					tr_tool->grid_coords[gci + 1],
					&tr_tool->tgrid_coords[gci],
					&tr_tool->tgrid_coords[gci + 1]);
Nate Summers's avatar
Nate Summers committed
1079
1080
1081
1082
1083
	  gci += 2;
	}
    }
}

1084
static void
1085
gimp_transform_tool_halt (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1086
{
1087
  GimpTool *tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1088

Nate Summers's avatar
Nate Summers committed
1089
  if (tr_tool->original)
1090
    {
1091
      tile_manager_unref (tr_tool->original);
1092
1093
      tr_tool->original = NULL;
    }
Nate Summers's avatar
Nate Summers committed
1094
1095

  /*  inactivate the tool  */
Nate Summers's avatar
Nate Summers committed
1096
  tr_tool->function = TRANSFORM_CREATING;
1097

1098
1099
  if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tr_tool)))
    gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
1100
1101
1102

  if (tr_tool->info_dialog)
    info_dialog_popdown (tr_tool->info_dialog);
Nate Summers's avatar
Nate Summers committed
1103
1104
1105
1106
1107
1108

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

static void
1109
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
1110
		            GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
1111
{
1112
  GimpTransformOptions *options;
Nate Summers's avatar
Nate Summers committed
1113

1114
1115
  options =
    GIMP_TRANSFORM_OPTIONS (GIMP_TOOL (tr_tool)->tool_info->tool_options);
Nate Summers's avatar
Nate Summers committed
1116
1117

  /*  find the boundaries  */
Michael Natterer's avatar