gimptransformtool.c 34.3 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
#include "base/tile-manager.h"
32

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

44
#include "gui/info-dialog.h"
45
46

#include "display/gimpdisplay.h"
47
#include "display/gimpdisplay-foreach.h"
Nate Summers's avatar
Nate Summers committed
48

49
#include "gimptransformtool.h"
50
51
#include "tool_manager.h"
#include "transform_options.h"
52

Michael Natterer's avatar
Michael Natterer committed
53
#include "floating_sel.h"
Michael Natterer's avatar
Michael Natterer committed
54
#include "gimpprogress.h"
Michael Natterer's avatar
Michael Natterer committed
55
56
#include "undo.h"
#include "path_transform.h"
Nate Summers's avatar
Nate Summers committed
57
58
59

#include "libgimp/gimpintl.h"

60

Michael Natterer's avatar
Michael Natterer committed
61
62
#define HANDLE 10

63

Michael Natterer's avatar
Michael Natterer committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*  local function prototypes  */

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

static void   gimp_transform_tool_finalize         (GObject           *object);

static void   gimp_transform_tool_control          (GimpTool          *tool,
                                                    ToolAction         action,
                                                    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);
89
90
91
92
93
static void   gimp_transform_tool_modifier_key     (GimpTool          *tool,
                                                    GdkModifierType    key,
                                                    gboolean           press,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
94
95
96
97
static void   gimp_transform_tool_oper_update      (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
Michael Natterer's avatar
Michael Natterer committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
static void   gimp_transform_tool_cursor_update    (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);

static void   gimp_transform_tool_draw             (GimpDrawTool      *draw_tool);

static TileManager * gimp_transform_tool_transform (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp,
                                                    TransformState     state);
static void   gimp_transform_tool_reset            (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp);
static void   gimp_transform_tool_bounds           (GimpTransformTool *tr_tool,
                                                    GimpDisplay       *gdisp);
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_setup_grid       (GimpTransformTool *tr_tool,
                                                    TransformOptions  *options);
static void   gimp_transform_tool_grid_recalc      (GimpTransformTool *tr_tool);

static void   transform_ok_callback                (GtkWidget         *widget,
                                                    gpointer           data);
static void   transform_reset_callback             (GtkWidget         *widget,
                                                    gpointer           data);
124
125


126
static GimpDrawToolClass *parent_class = NULL;
127

128
129

GType
Nate Summers's avatar
Nate Summers committed
130
131
gimp_transform_tool_get_type (void)
{
132
  static GType tool_type = 0;
Nate Summers's avatar
Nate Summers committed
133
134
135

  if (! tool_type)
    {
136
      static const GTypeInfo tool_info =
Nate Summers's avatar
Nate Summers committed
137
138
      {
        sizeof (GimpTransformToolClass),
139
140
141
142
143
144
145
146
	(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
147
148
      };

149
150
151
      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
					  "GimpTransformTool", 
                                          &tool_info, 0);
Nate Summers's avatar
Nate Summers committed
152
153
154
155
156
157
158
159
    }

  return tool_type;
}

static void
gimp_transform_tool_class_init (GimpTransformToolClass *klass)
{
160
  GObjectClass      *object_class;
Nate Summers's avatar
Nate Summers committed
161
162
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_class;
Nate Summers's avatar
Nate Summers committed
163

164
165
166
  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
167

168
  parent_class = g_type_class_peek_parent (klass);
Nate Summers's avatar
Nate Summers committed
169

170
  object_class->finalize     = gimp_transform_tool_finalize;
Nate Summers's avatar
Nate Summers committed
171

172
  tool_class->control        = gimp_transform_tool_control;
Nate Summers's avatar
Nate Summers committed
173
174
175
  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;
176
  tool_class->modifier_key   = gimp_transform_tool_modifier_key;
177
  tool_class->oper_update    = gimp_transform_tool_oper_update;
Nate Summers's avatar
Nate Summers committed
178
  tool_class->cursor_update  = gimp_transform_tool_cursor_update;
Nate Summers's avatar
Nate Summers committed
179
180

  draw_class->draw           = gimp_transform_tool_draw;
Nate Summers's avatar
Nate Summers committed
181
182
183
}

static void
Michael Natterer's avatar
Michael Natterer committed
184
gimp_transform_tool_init (GimpTransformTool *transform_tool)
Nate Summers's avatar
Nate Summers committed
185
{
Michael Natterer's avatar
Michael Natterer committed
186
  GimpTool *tool;
187
  gint      i;
Nate Summers's avatar
Nate Summers committed
188

Michael Natterer's avatar
Michael Natterer committed
189
190
191
192
  tool = GIMP_TOOL (transform_tool);

  transform_tool->function = TRANSFORM_CREATING;
  transform_tool->original = NULL;
Nate Summers's avatar
Nate Summers committed
193
194

  for (i = 0; i < TRAN_INFO_SIZE; i++)
195
196
197
198
    {
      transform_tool->trans_info[i]     = 0.0;
      transform_tool->old_trans_info[i] = 0.0;
    }
Nate Summers's avatar
Nate Summers committed
199

Michael Natterer's avatar
Michael Natterer committed
200
  gimp_matrix3_identity (transform_tool->transform);
Nate Summers's avatar
Nate Summers committed
201

Michael Natterer's avatar
Michael Natterer committed
202
  transform_tool->use_grid     = TRUE;
203
  transform_tool->use_center   = TRUE;
Michael Natterer's avatar
Michael Natterer committed
204
205
206
207
  transform_tool->ngx          = 0;
  transform_tool->ngy          = 0;
  transform_tool->grid_coords  = NULL;
  transform_tool->tgrid_coords = NULL;
208

209
210
  transform_tool->info_dialog  = NULL;

Nate Summers's avatar
Nate Summers committed
211
212
  tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
Nate Summers's avatar
Nate Summers committed
213
214
}

215
static void
216
gimp_transform_tool_finalize (GObject *object)
Nate Summers's avatar
Nate Summers committed
217
{
218
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
219

220
221
222
  tr_tool = GIMP_TRANSFORM_TOOL (object);

  if (tr_tool->original)
223
224
225
226
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
227

228
  if (tr_tool->info_dialog)
229
    {
230
231
      info_dialog_free (tr_tool->info_dialog);
      tr_tool->info_dialog = NULL;
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    }

  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
250
251
252
gimp_transform_tool_control (GimpTool    *tool,
			     ToolAction   action,
			     GimpDisplay *gdisp)
253
{
Michael Natterer's avatar
Michael Natterer committed
254
  GimpTransformTool *transform_tool;
255

Michael Natterer's avatar
Michael Natterer committed
256
  transform_tool = GIMP_TRANSFORM_TOOL (tool);
257

258
259
260
261
  switch (action)
    {
    case PAUSE:
      break;
262

263
    case RESUME:
Michael Natterer's avatar
Michael Natterer committed
264
      gimp_transform_tool_recalc (transform_tool, gdisp);
265
      break;
266

267
    case HALT:
Michael Natterer's avatar
Michael Natterer committed
268
      gimp_transform_tool_reset (transform_tool, gdisp);
269
      return; /* don't upchain */
270
      break;
271

272
273
274
275
    default:
      break;
    }

Michael Natterer's avatar
Michael Natterer committed
276
  GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
277
278
279
}

static void
280
281
282
283
284
gimp_transform_tool_button_press (GimpTool        *tool,
                                  GimpCoords      *coords,
                                  guint32          time,
                                  GdkModifierType  state,
			          GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
285
{
Michael Natterer's avatar
Michael Natterer committed
286
  GimpTransformTool *tr_tool;
287
  GimpDrawTool      *draw_tool;
Michael Natterer's avatar
Michael Natterer committed
288
289
  GimpDrawable      *drawable;
  gint               off_x, off_y;
Nate Summers's avatar
Nate Summers committed
290

Michael Natterer's avatar
Michael Natterer committed
291
  tr_tool   = GIMP_TRANSFORM_TOOL (tool);
292
  draw_tool = GIMP_DRAW_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
293
294
295

  drawable = gimp_image_active_drawable (gdisp->gimage);

296
297
298
299
300
301
302
303
304
305
306
307
  if (gdisp != tool->gdisp)
    {
      /*  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);

      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)))
        {
308
309
          if (gimp_image_mask_is_empty (gdisp->gimage) ||
              gimp_image_mask_value (gdisp->gimage, coords->x, coords->y))
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
            {
              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)
                {
                  g_warning ("%s: tool_already ACTIVE", G_GNUC_FUNCTION);

                  gimp_transform_tool_reset (tr_tool, gdisp);
                }

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

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

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

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

              /*  start drawing the bounding box and handles...  */
348
              gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), gdisp);
349
350
351
352
353
354
355

              /*  find which handle we're dragging  */
              gimp_transform_tool_oper_update (tool, coords, state, gdisp);
            }
        }
    }

Michael Natterer's avatar
Michael Natterer committed
356
  if (tr_tool->function == TRANSFORM_CREATING && tool->state == ACTIVE)
Nate Summers's avatar
Nate Summers committed
357
    {
358
359
      gint i;

Nate Summers's avatar
Nate Summers committed
360
361
      /*  Save the current transformation info  */
      for (i = 0; i < TRAN_INFO_SIZE; i++)
362
	tr_tool->old_trans_info[i] = tr_tool->trans_info[i];
Nate Summers's avatar
Nate Summers committed
363
364
365
366
367
368
    }

  /*  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
   */
Michael Natterer's avatar
Michael Natterer committed
369
  if (gdisp == tool->gdisp)
Nate Summers's avatar
Nate Summers committed
370
371
    {
      /*  Save the current pointer position  */
Michael Natterer's avatar
Michael Natterer committed
372
373
      tr_tool->lastx = tr_tool->startx = coords->x;
      tr_tool->lasty = tr_tool->starty = coords->y;
Nate Summers's avatar
Nate Summers committed
374
375

      tool->state = ACTIVE;
376
    }
Nate Summers's avatar
Nate Summers committed
377
378
}

379
static void
380
381
382
383
384
gimp_transform_tool_button_release (GimpTool        *tool,
                                    GimpCoords      *coords,
                                    guint32          time,
			            GdkModifierType  state,
			            GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
385
{
Michael Natterer's avatar
Michael Natterer committed
386
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
387
  gint               i;
Nate Summers's avatar
Nate Summers committed
388

Michael Natterer's avatar
Michael Natterer committed
389
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
390
391

  /*  if we are creating, there is nothing to be done...exit  */
Michael Natterer's avatar
Michael Natterer committed
392
  if (tr_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
393
394
395
    return;

  /*  if the 3rd button isn't pressed, transform the selected mask  */
396
  if (! (state & GDK_BUTTON3_MASK))
Nate Summers's avatar
Nate Summers committed
397
398
    {
      /* Shift-clicking is another way to approve the transform  */
399
      if ((state & GDK_SHIFT_MASK) || ! tr_tool->use_grid)
Nate Summers's avatar
Nate Summers committed
400
	{
Michael Natterer's avatar
Michael Natterer committed
401
	  gimp_transform_tool_doit (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
402
403
404
405
406
	}
      else
	{
	  /*  Only update the paths preview */
	  path_transform_current_path (gdisp->gimage,
Michael Natterer's avatar
Michael Natterer committed
407
				       tr_tool->transform, TRUE);
Nate Summers's avatar
Nate Summers committed
408
409
410
411
	}
    }
  else
    {
412
      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
413
414
415

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

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

421
      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
422
423
424

      /* Update the paths preview */
      path_transform_current_path (gdisp->gimage,
Michael Natterer's avatar
Michael Natterer committed
425
				   tr_tool->transform, TRUE);
Nate Summers's avatar
Nate Summers committed
426
427
428
    }
}

429
static void
430
431
432
433
434
gimp_transform_tool_motion (GimpTool        *tool,
                            GimpCoords      *coords,
                            guint32          time,
		            GdkModifierType  state,
		            GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
435
{
Michael Natterer's avatar
Michael Natterer committed
436
  GimpTransformTool *transform_tool;
Nate Summers's avatar
Nate Summers committed
437

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

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

444
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
445

Michael Natterer's avatar
Michael Natterer committed
446
447
448
  transform_tool->curx  = coords->x;
  transform_tool->cury  = coords->y;
  transform_tool->state = state;
Nate Summers's avatar
Nate Summers committed
449
450

  /*  recalculate the tool's transformation matrix  */
Michael Natterer's avatar
Michael Natterer committed
451
  gimp_transform_tool_transform (transform_tool, gdisp, TRANSFORM_MOTION);
Nate Summers's avatar
Nate Summers committed
452

Michael Natterer's avatar
Michael Natterer committed
453
454
  transform_tool->lastx = transform_tool->curx;
  transform_tool->lasty = transform_tool->cury;
Nate Summers's avatar
Nate Summers committed
455

456
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
457
458
}

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
static void
gimp_transform_tool_modifier_key (GimpTool        *tool,
                                  GdkModifierType  key,
                                  gboolean         press,
                                  GdkModifierType  state,
                                  GimpDisplay     *gdisp)
{
  TransformOptions *options;

  options = (TransformOptions *) tool->tool_info->tool_options;

  if (key == GDK_CONTROL_MASK && options->constrain_1_w)
    {
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->constrain_1_w),
                                    ! options->constrain_1);
    }
  else if (key == GDK_MOD1_MASK && options->constrain_2_w)
    {
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->constrain_2_w),
                                    ! options->constrain_2);
    }
}

482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
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);

  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,
                                    HANDLE, HANDLE,
                                    GTK_ANCHOR_CENTER,
                                    FALSE))
	{
	  tr_tool->function = TRANSFORM_HANDLE_CENTER;
	}
    }
}

544
static void
545
546
547
548
gimp_transform_tool_cursor_update (GimpTool        *tool,
                                   GimpCoords      *coords,
			           GdkModifierType  state,
			           GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
549
{
550
551
552
553
554
555
  GimpTransformTool  *tr_tool;
  GimpDrawable       *drawable;
  GdkCursorType       ctype     = GDK_TOP_LEFT_ARROW;
  GimpCursorModifier  cmodifier = GIMP_CURSOR_MODIFIER_NONE;

  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
556
557
558

  if ((drawable = gimp_image_active_drawable (gdisp->gimage)))
    {
559
560
561
562
      gint off_x, off_y;

      gimp_drawable_offsets (drawable, &off_x, &off_y);

Nate Summers's avatar
Nate Summers committed
563
      if (GIMP_IS_LAYER (drawable) &&
564
          gimp_layer_get_mask (GIMP_LAYER (drawable)))
Nate Summers's avatar
Nate Summers committed
565
566
567
	{
	  ctype = GIMP_BAD_CURSOR;
	}
568
569
570
571
      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
572
	{
573
574
	  if (gimp_image_mask_is_empty (gdisp->gimage) ||
	      gimp_image_mask_value (gdisp->gimage, coords->x, coords->y))
Nate Summers's avatar
Nate Summers committed
575
576
577
578
579
580
	    {
	      ctype = GIMP_MOUSE_CURSOR;
	    }
	}
    }

581
582
583
584
585
  if (tr_tool->use_center && tr_tool->function == TRANSFORM_HANDLE_CENTER)
    {
      cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
    }

586
587
588
589
  tool->cursor          = ctype;
  tool->cursor_modifier = cmodifier;

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

592
static void
593
gimp_transform_tool_draw (GimpDrawTool *draw_tool)
Nate Summers's avatar
Nate Summers committed
594
{
595
  GimpTransformTool *tr_tool;
Michael Natterer's avatar
Michael Natterer committed
596
  TransformOptions  *options;
597
598
599
  gint               i, k, gci;

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

601
602
603
  if (! tr_tool->use_grid)
    return;

Michael Natterer's avatar
Michael Natterer committed
604
605
  options = (TransformOptions *) GIMP_TOOL (draw_tool)->tool_info->tool_options;

Nate Summers's avatar
Nate Summers committed
606
  /*  draw the bounding box  */
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  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
623
624
625

  /*  Draw the grid */

626
  if ((tr_tool->grid_coords != NULL) && (tr_tool->tgrid_coords != NULL))
Nate Summers's avatar
Nate Summers committed
627
628
    {
      gci = 0;
Nate Summers's avatar
Nate Summers committed
629
      k = tr_tool->ngx + tr_tool->ngy;
630

Nate Summers's avatar
Nate Summers committed
631
632
      for (i = 0; i < k; i++)
	{
633
634
635
636
637
638
          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
639
640
641
642
643
	  gci += 4;
	}
    }

  /*  draw the tool handles  */
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx1, tr_tool->ty1,
                              HANDLE, HANDLE,
                              GTK_ANCHOR_CENTER,
                              FALSE);
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx2, tr_tool->ty2,
                              HANDLE, HANDLE,
                              GTK_ANCHOR_CENTER,
                              FALSE);
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx3, tr_tool->ty3,
                              HANDLE, HANDLE,
                              GTK_ANCHOR_CENTER,
                              FALSE);
  gimp_draw_tool_draw_handle (draw_tool,
                              GIMP_HANDLE_SQUARE,
                              tr_tool->tx4, tr_tool->ty4,
                              HANDLE, HANDLE,
                              GTK_ANCHOR_CENTER,
                              FALSE);
Nate Summers's avatar
Nate Summers committed
668
669

  /*  draw the center  */
670
671
672
673
674
675
676
677
678
  if (tr_tool->use_center)
    {
      gimp_draw_tool_draw_handle (draw_tool,
                                  GIMP_HANDLE_FILLED_CIRCLE,
                                  tr_tool->tcx, tr_tool->tcy,
                                  HANDLE, HANDLE,
                                  GTK_ANCHOR_CENTER,
                                  FALSE);
    }
Nate Summers's avatar
Nate Summers committed
679

Michael Natterer's avatar
Michael Natterer committed
680
  if (options->show_path)
Nate Summers's avatar
Nate Summers committed
681
682
683
    {
      GimpMatrix3 tmp_matrix;

Michael Natterer's avatar
Michael Natterer committed
684
      if (options->direction == GIMP_TRANSFORM_BACKWARD)
Nate Summers's avatar
Nate Summers committed
685
	{
Nate Summers's avatar
Nate Summers committed
686
	  gimp_matrix3_invert (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
687
688
689
	}
      else
	{
Nate Summers's avatar
Nate Summers committed
690
	  gimp_matrix3_duplicate (tr_tool->transform, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
691
692
	}

693
694
      path_transform_draw_current (GIMP_TOOL (draw_tool)->gdisp,
                                   draw_tool, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
695
696
697
    }
}

Michael Natterer's avatar
Michael Natterer committed
698
699
700
701
702
703
704
static TileManager *
gimp_transform_tool_transform (GimpTransformTool   *tool,
                               GimpDisplay         *gdisp,
			       TransformState       state)
{
  g_return_val_if_fail (GIMP_IS_TRANSFORM_TOOL (tool), NULL);

705
  return GIMP_TRANSFORM_TOOL_GET_CLASS (tool)->transform (tool, gdisp, state);
Michael Natterer's avatar
Michael Natterer committed
706
707
708
709
710
711
}

static void
gimp_transform_tool_doit (GimpTransformTool  *tr_tool,
		          GimpDisplay        *gdisp)
{
712
713
714
715
716
717
  GimpTool      *tool;
  TileManager   *new_tiles;
  TransformUndo *tu;
  PathUndo      *pundo;
  gboolean       new_layer;
  gint           i;
Michael Natterer's avatar
Michael Natterer committed
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773

  gimp_set_busy (gdisp->gimage->gimp);

  tool = GIMP_TOOL (tr_tool);

  /* undraw the tool before we muck around with the transform matrix */
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));

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

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

  tr_tool->original = gimp_drawable_transform_cut (tool->drawable,
                                                   &new_layer);

  pundo = path_transform_start_undo (gdisp->gimage);

  /*  Send the request for the transformation to the tool...
   */
  new_tiles = gimp_transform_tool_transform (tr_tool, gdisp, TRANSFORM_FINISH);

  gimp_transform_tool_transform (tr_tool, gdisp, TRANSFORM_INIT);

  gimp_transform_tool_recalc (tr_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_drawable_transform_paste (tool->drawable,
                                     new_tiles,
                                     new_layer);

      /*  create and initialize the transform_undo structure  */
      tu = g_new0 (TransformUndo, 1);
      tu->tool_ID   = tool->ID;
      tu->tool_type = G_TYPE_FROM_INSTANCE (tool);

      for (i = 0; i < TRAN_INFO_SIZE; i++)
774
	tu->trans_info[i] = tr_tool->old_trans_info[i];
Michael Natterer's avatar
Michael Natterer committed
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813

      tu->original  = NULL;
      tu->path_undo = pundo;

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

      undo_push_transform (gdisp->gimage, tu);
    }

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

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

  gimp_unset_busy (gdisp->gimage->gimp);

  gdisplays_flush ();

  gimp_transform_tool_reset (tr_tool, gdisp);
}

TileManager *
gimp_transform_tool_transform_tiles (GimpTransformTool *transform_tool,
                                     const gchar       *progress_text)
{
  GimpTool         *tool;
  TransformOptions *options;
  GimpProgress     *progress;
  TileManager      *ret;

  g_return_val_if_fail (GIMP_IS_TRANSFORM_TOOL (transform_tool), NULL);
  g_return_val_if_fail (progress_text != NULL, NULL);

814
  if (transform_tool->info_dialog)
815
816
    gtk_widget_set_sensitive (GTK_WIDGET (transform_tool->info_dialog->shell),
                              FALSE);
Michael Natterer's avatar
Michael Natterer committed
817
818
819
820
821
822
823
824
825

  tool = GIMP_TOOL (transform_tool);

  options = (TransformOptions *) tool->tool_info->tool_options;

  progress = progress_start (tool->gdisp, progress_text, FALSE, NULL, NULL);

  ret = gimp_drawable_transform_tiles_affine (gimp_image_active_drawable (tool->gdisp->gimage),
                                              transform_tool->original,
826
                                              options->interpolation,
Michael Natterer's avatar
Michael Natterer committed
827
828
829
830
831
832
833
834
835
836
837
838
839
                                              options->clip,
                                              transform_tool->transform,
                                              options->direction,
                                              progress ? progress_update_and_flush :
                                              (GimpProgressFunc) NULL,
                                              progress);

  if (progress)
    progress_end (progress);

  return ret;
}

Nate Summers's avatar
Nate Summers committed
840
void
Nate Summers's avatar
Nate Summers committed
841
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
842
{
843
  g_return_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
844
845
846
847
848
849
850
851
852
853
854
855
856

  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
857

858
859
860
  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
861

862
  if (tr_tool->grid_coords != NULL && tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
863
    {
864
865
866
      gint i, k;
      gint gci;

Nate Summers's avatar
Nate Summers committed
867
      gci = 0;
868
      k   = (tr_tool->ngx + tr_tool->ngy) * 2;
869

Nate Summers's avatar
Nate Summers committed
870
871
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
872
873
874
875
876
	  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
877
878
879
880
881
	  gci += 2;
	}
    }
}

882
static void
883
gimp_transform_tool_reset (GimpTransformTool *tr_tool,
884
		           GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
885
{
Nate Summers's avatar
Nate Summers committed
886
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
887

888
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
889

Nate Summers's avatar
Nate Summers committed
890
  if (tr_tool->original)
891
892
893
894
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
Nate Summers's avatar
Nate Summers committed
895
896

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

899
  gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
900
901
902

  if (tr_tool->info_dialog)
    info_dialog_popdown (tr_tool->info_dialog);
Nate Summers's avatar
Nate Summers committed
903
904
905
906
907
908
909

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

static void
910
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
911
		            GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
912
{
913
914
915
  TileManager  *tiles;
  GimpDrawable *drawable;
  gint          offset_x, offset_y;
Nate Summers's avatar
Nate Summers committed
916

917
918
  tiles    = tr_tool->original;
  drawable = gimp_image_active_drawable (gdisp->gimage);
Nate Summers's avatar
Nate Summers committed
919
920
921
922
923

  /*  find the boundaries  */
  if (tiles)
    {
      tile_manager_get_offsets (tiles,
Nate Summers's avatar
Nate Summers committed
924
925
926
927
				&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
928
929
930
931
932
    }
  else
    {
      gimp_drawable_offsets (drawable, &offset_x, &offset_y);
      gimp_drawable_mask_bounds (drawable,
Nate Summers's avatar
Nate Summers committed
933
934
935
936
937
938
				 &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
939
    }
Nate Summers's avatar
Nate Summers committed
940
941
942

  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
943

Michael Natterer's avatar
Michael Natterer committed
944
945
946
947
948
  if (tr_tool->use_grid)
    {
      /*  changing the bounds invalidates any grid we may have  */
      gimp_transform_tool_grid_recalc (tr_tool);
    }
Nate Summers's avatar
Nate Summers committed
949
950
}

951
952
953
954
955
956
957
958
959
960
961
void
gimp_transform_tool_info_dialog_connect (GimpTransformTool *tr_tool,
                                         const gchar       *ok_button)
{
  g_return_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool));
  g_return_if_fail (ok_button != NULL);

  if (tr_tool->info_dialog)
    {
      gimp_dialog_create_action_area (GIMP_DIALOG (tr_tool->info_dialog->shell),

962
                                      GIMP_STOCK_RESET, transform_reset_callback,
963
964
                                      tr_tool, NULL, NULL, FALSE, FALSE,

965
966
967
                                      ok_button, transform_ok_callback,
                                      tr_tool, NULL, NULL, TRUE, FALSE,

968
969
970
971
                                      NULL);
    }
}

Nate Summers's avatar
Nate Summers committed
972
void
Michael Natterer's avatar
Michael Natterer committed
973
gimp_transform_tool_grid_density_changed (GimpTransformTool *transform_tool)
Nate Summers's avatar
Nate Summers committed
974
{
Michael Natterer's avatar
Michael Natterer committed
975
  if (transform_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
976
977
    return;

Michael Natterer's avatar
Michael Natterer committed
978
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (transform_tool));
979

Michael Natterer's avatar
Michael Natterer committed
980
981
  gimp_transform_tool_grid_recalc (transform_tool);
  gimp_transform_tool_transform_bounding_box (transform_tool);
982

Michael Natterer's avatar
Michael Natterer committed
983
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (transform_tool));
Nate Summers's avatar
Nate Summers committed
984
985
986
}

void
Michael Natterer's avatar
Michael Natterer committed
987
988
gimp_transform_tool_show_path_changed (GimpTransformTool *transform_tool,
                                       gint               type /* a truly undescriptive name */)
Nate Summers's avatar
Nate Summers committed
989
{
Michael Natterer's avatar
Michael Natterer committed
990
  if (transform_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
991
992
993
    return;

  if (type)
Michael Natterer's avatar
Michael Natterer committed
994
    gimp_draw_tool_pause (GIMP_DRAW_TOOL (transform_tool));
Nate Summers's avatar
Nate Summers committed
995
  else
Michael Natterer's avatar
Michael Natterer committed
996
    gimp_draw_tool_resume (GIMP_DRAW_TOOL (transform_tool));
Nate Summers's avatar
Nate Summers committed
997
998
999
}

static void
Nate Summers's avatar
Nate Summers committed
1000
gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
1001
{
Michael Natterer's avatar
Michael Natterer committed
1002
1003
1004
1005
  TransformOptions *options;

  options = (TransformOptions *) GIMP_TOOL (tr_tool)->tool_info->tool_options;

Nate Summers's avatar
Nate Summers committed
1006
  if (tr_tool->grid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1007
    {
Nate Summers's avatar
Nate Summers committed
1008
1009
      g_free (tr_tool->grid_coords);
      tr_tool->grid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1010
    }
1011

Nate Summers's avatar
Nate Summers committed
1012
  if (tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1013
    {
Nate Summers's avatar
Nate Summers committed
1014
1015
      g_free (tr_tool->tgrid_coords);
      tr_tool->tgrid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1016
    }
1017

Michael Natterer's avatar
Michael Natterer committed
1018
1019
1020
1021
  if (options->show_grid)
    {
      gimp_transform_tool_setup_grid (tr_tool, options);
    }
Nate Summers's avatar
Nate Summers committed
1022
1023
1024
}

static void
Michael Natterer's avatar
Michael Natterer committed
1025
1026
gimp_transform_tool_setup_grid (GimpTransformTool *tr_tool,
                                TransformOptions  *options)
Nate Summers's avatar
Nate Summers committed
1027
{
1028
1029
1030
  GimpTool *tool;
  gint      i, gci;
  gdouble  *coords;
Nate Summers's avatar
Nate Summers committed
1031

1032
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1033

Nate Summers's avatar
Nate Summers committed
1034
  /*  We use the gimp_transform_tool_grid_size function only here, even
Nate Summers's avatar
Nate Summers committed
1035
1036
1037
   *  if the user changes the grid size in the middle of an
   *  operation, nothing happens.
   */
Michael Natterer's avatar
Michael Natterer committed
1038
  tr_tool->ngx = (tr_tool->x2 - tr_tool->x1) / options->grid_size;
Nate Summers's avatar
Nate Summers committed
1039
1040
  if (tr_tool->ngx > 0)
    tr_tool->ngx--;
Nate Summers's avatar
Nate Summers committed
1041

Michael Natterer's avatar
Michael Natterer committed
1042
  tr_tool->ngy = (tr_tool->y2 - tr_tool->y1) / options->grid_size;
Nate Summers's avatar
Nate Summers committed
1043
1044
  if (tr_tool->ngy > 0)
    tr_tool->ngy--;
Nate Summers's avatar
Nate Summers committed
1045

Nate Summers's avatar
Nate Summers committed
1046
  tr_tool->grid_coords = coords =
1047
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1048

Nate Summers's avatar
Nate Summers committed
1049
  tr_tool->tgrid_coords =
1050
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1051
1052

  gci = 0;
1053

Nate Summers's avatar
Nate Summers committed
1054
  for (i = 1; i <= tr_tool->ngx; i++)
Nate Summers's avatar
Nate Summers committed
1055
    {
Nate Summers's avatar
Nate Summers committed
1056
      coords[gci] = tr_tool->x1 +
1057
	((gdouble) i) / (tr_tool->ngx + 1) *
Nate Summers's avatar
Nate Summers committed
1058
1059
	(tr_tool->x2 - tr_tool->x1);
      coords[gci+1] = tr_tool->y1;
Nate Summers's avatar
Nate Summers committed
1060
      coords[gci+2] = coords[gci];
Nate Summers's avatar
Nate Summers committed
1061
      coords[gci+3] = tr_tool->y2;
Nate Summers's avatar
Nate Summers committed
1062
1063
      gci += 4;
    }
1064

Nate Summers's avatar
Nate Summers committed
1065
  for (i = 1; i <= tr_tool->ngy; i++)
Nate Summers's avatar
Nate Summers committed
1066
    {
Nate Summers's avatar
Nate Summers committed
1067
1068
      coords[gci] = tr_tool->x1;
      coords[gci+1] = tr_tool->y1 +
1069
	((gdouble) i) / (tr_tool->ngy + 1) *
Nate Summers's avatar
Nate Summers committed
1070
1071
	(tr_tool->y2 - tr_tool->y1);
      coords[gci+2] = tr_tool->x2;
Nate Summers's avatar
Nate Summers committed
1072
1073
1074
1075
1076
1077
      coords[gci+3] = coords[gci+1];
      gci += 4;
    }
}

static void
1078
gimp_transform_tool_recalc (GimpTransformTool *tr_tool,
1079
		            GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
1080
{
Nate Summers's avatar
Nate Summers committed
1081
  gimp_transform_tool_bounds (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
1082

1083
  gimp_transform_tool_transform (tr_tool, gdisp, TRANSFORM_RECALC);
Nate Summers's avatar
Nate Summers committed
1084
1085
}

Michael Natterer's avatar
Michael Natterer committed
1086
1087
1088
static void
transform_ok_callback (GtkWidget *widget,
		       gpointer   data)
Nate Summers's avatar
Nate Summers committed
1089
{
Michael Natterer's avatar
Michael Natterer committed
1090
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
1091

Michael Natterer's avatar
Michael Natterer committed
1092
1093
  tool = GIMP_TOOL(data);
  gimp_transform_tool_doit (GIMP_TRANSFORM_TOOL(tool), tool->gdisp);
Nate Summers's avatar
Nate Summers committed
1094
1095
}

Michael Natterer's avatar
Michael Natterer committed
1096
1097
1098
static void
transform_reset_callback (GtkWidget *widget,
			  gpointer   data)
Nate Summers's avatar
Nate Summers committed
1099
{
Michael Natterer's avatar
Michael Natterer committed
1100
1101
1102
  GimpTransformTool *transform_tool;
  GimpTool          *tool;
  gint               i;
Nate Summers's avatar
Nate Summers committed
1103

Michael Natterer's avatar
Michael Natterer committed
1104
1105
  transform_tool = GIMP_TRANSFORM_TOOL (data);
  tool           = GIMP_TOOL (data);
Nate Summers's avatar
Nate Summers committed
1106

Michael Natterer's avatar
Michael Natterer committed
1107
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
1108