gimptransformtool.c 34.5 KB
Newer Older
Nate Summers's avatar
Nate Summers committed
1
/* The GIMP -- an image manipulation program
Nate Summers's avatar
Nate Summers committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * 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"
Michael Natterer's avatar
Michael Natterer committed
48
#include "display/gimpprogress.h"
Nate Summers's avatar
Nate Summers committed
49

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

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

#include "libgimp/gimpintl.h"

59

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

62

Michael Natterer's avatar
Michael Natterer committed
63
64
65
66
67
68
69
70
/*  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,
71
                                                    GimpToolAction     action,
Michael Natterer's avatar
Michael Natterer committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
                                                    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);
88
89
90
91
92
static void   gimp_transform_tool_modifier_key     (GimpTool          *tool,
                                                    GdkModifierType    key,
                                                    gboolean           press,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
93
94
95
96
static void   gimp_transform_tool_oper_update      (GimpTool          *tool,
                                                    GimpCoords        *coords,
                                                    GdkModifierType    state,
                                                    GimpDisplay       *gdisp);
Michael Natterer's avatar
Michael Natterer committed
97
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
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);
123
124


125
static GimpDrawToolClass *parent_class = NULL;
126

127
128

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

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

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

  return tool_type;
}

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

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

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

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

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

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

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

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

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

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

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

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

208
209
  transform_tool->info_dialog  = NULL;

Nate Summers's avatar
Nate Summers committed
210
211
}

212
static void
213
gimp_transform_tool_finalize (GObject *object)
Nate Summers's avatar
Nate Summers committed
214
{
215
  GimpTransformTool *tr_tool;
Nate Summers's avatar
Nate Summers committed
216

217
218
219
  tr_tool = GIMP_TRANSFORM_TOOL (object);

  if (tr_tool->original)
220
221
222
223
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
224

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

  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
247
248
249
gimp_transform_tool_control (GimpTool       *tool,
			     GimpToolAction  action,
			     GimpDisplay    *gdisp)
250
{
Michael Natterer's avatar
Michael Natterer committed
251
  GimpTransformTool *transform_tool;
252

Michael Natterer's avatar
Michael Natterer committed
253
  transform_tool = GIMP_TRANSFORM_TOOL (tool);
254

255
256
257
258
  switch (action)
    {
    case PAUSE:
      break;
259

260
    case RESUME:
Michael Natterer's avatar
Michael Natterer committed
261
      gimp_transform_tool_recalc (transform_tool, gdisp);
262
      break;
263

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

269
270
271
272
    default:
      break;
    }

Michael Natterer's avatar
Michael Natterer committed
273
  GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
274
275
276
}

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

Michael Natterer's avatar
Michael Natterer committed
288
  tr_tool   = GIMP_TRANSFORM_TOOL (tool);
289
  draw_tool = GIMP_DRAW_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
290
291
292

  drawable = gimp_image_active_drawable (gdisp->gimage);

293
294
295
296
297
298
299
300
301
302
303
304
  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)))
        {
305
306
          if (gimp_image_mask_is_empty (gdisp->gimage) ||
              gimp_image_mask_value (gdisp->gimage, coords->x, coords->y))
307
308
309
310
311
312
            {
              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."));
Nate Summers's avatar
Nate Summers committed
313
                  gimp_tool_control_halt(tool->control);    /* sets paused_count to 0 -- is this ok? */
314
315
316
317
318
319
                  return;
                }

              /*  If the tool is already active, clear the current state
               *  and reset
               */
Nate Summers's avatar
Nate Summers committed
320
              if (gimp_tool_control_is_active(tool->control))
321
322
323
324
325
326
327
328
329
                {
                  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;
Nate Summers's avatar
Nate Summers committed
330
              gimp_tool_control_activate(tool->control);
331
332
333
334
335
336
337
338
339
340
341
342
343
344

              /*  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...  */
345
              gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), gdisp);
346
347
348
349
350
351
352

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

Nate Summers's avatar
Nate Summers committed
353
  if (tr_tool->function == TRANSFORM_CREATING && gimp_tool_control_is_active(tool->control))
Nate Summers's avatar
Nate Summers committed
354
    {
355
356
      gint i;

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

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

Nate Summers's avatar
Nate Summers committed
372
      gimp_tool_control_activate(tool->control);
373
    }
Nate Summers's avatar
Nate Summers committed
374
375
}

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

Michael Natterer's avatar
Michael Natterer committed
386
  tr_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
387
388

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

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

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

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

418
      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
419
420
421

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

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

Michael Natterer's avatar
Michael Natterer committed
435
  transform_tool = GIMP_TRANSFORM_TOOL (tool);
Nate Summers's avatar
Nate Summers committed
436

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

441
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
442

Michael Natterer's avatar
Michael Natterer committed
443
444
445
  transform_tool->curx  = coords->x;
  transform_tool->cury  = coords->y;
  transform_tool->state = state;
Nate Summers's avatar
Nate Summers committed
446
447

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

Michael Natterer's avatar
Michael Natterer committed
450
451
  transform_tool->lastx = transform_tool->curx;
  transform_tool->lasty = transform_tool->cury;
Nate Summers's avatar
Nate Summers committed
452

453
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
454
455
}

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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);
    }
}

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

541
static void
542
543
544
545
gimp_transform_tool_cursor_update (GimpTool        *tool,
                                   GimpCoords      *coords,
			           GdkModifierType  state,
			           GimpDisplay     *gdisp)
Nate Summers's avatar
Nate Summers committed
546
{
547
548
549
550
551
552
  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
553
554
555

  if ((drawable = gimp_image_active_drawable (gdisp->gimage)))
    {
556
557
558
559
      gint off_x, off_y;

      gimp_drawable_offsets (drawable, &off_x, &off_y);

Nate Summers's avatar
Nate Summers committed
560
      if (GIMP_IS_LAYER (drawable) &&
561
          gimp_layer_get_mask (GIMP_LAYER (drawable)))
Nate Summers's avatar
Nate Summers committed
562
563
564
	{
	  ctype = GIMP_BAD_CURSOR;
	}
565
566
567
568
      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
569
	{
570
571
	  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
572
573
574
575
576
577
	    {
	      ctype = GIMP_MOUSE_CURSOR;
	    }
	}
    }

578
579
580
581
582
  if (tr_tool->use_center && tr_tool->function == TRANSFORM_HANDLE_CENTER)
    {
      cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
    }

Nate Summers's avatar
Nate Summers committed
583
584
  gimp_tool_control_set_cursor(tool->control, ctype);
  gimp_tool_control_set_cursor_modifier(tool->control, cmodifier);
585
586

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

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

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

598
599
600
  if (! tr_tool->use_grid)
    return;

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

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

  /*  Draw the grid */

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

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

  /*  draw the tool handles  */
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
  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
665
666

  /*  draw the center  */
667
668
669
670
671
672
673
674
675
  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
676

Michael Natterer's avatar
Michael Natterer committed
677
  if (options->show_path)
Nate Summers's avatar
Nate Summers committed
678
679
680
    {
      GimpMatrix3 tmp_matrix;

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

690
691
      path_transform_draw_current (GIMP_TOOL (draw_tool)->gdisp,
                                   draw_tool, tmp_matrix);
Nate Summers's avatar
Nate Summers committed
692
693
694
    }
}

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

702
  return GIMP_TRANSFORM_TOOL_GET_CLASS (tool)->transform (tool, gdisp, state);
Michael Natterer's avatar
Michael Natterer committed
703
704
705
706
707
708
}

static void
gimp_transform_tool_doit (GimpTransformTool  *tr_tool,
		          GimpDisplay        *gdisp)
{
Michael Natterer's avatar
Michael Natterer committed
709
710
711
712
  GimpTool    *tool;
  TileManager *new_tiles;
  GSList      *path_undo;
  gboolean     new_layer;
Michael Natterer's avatar
Michael Natterer committed
713
714
715
716
717
718
719
720
721
722
723

  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
   */
Nate Summers's avatar
Nate Summers committed
724
  gimp_tool_control_set_preserve(tool->control, TRUE);
Michael Natterer's avatar
Michael Natterer committed
725
726

  /*  Start a transform undo group  */
Michael Natterer's avatar
Michael Natterer committed
727
  undo_push_group_start (gdisp->gimage, TRANSFORM_UNDO_GROUP);
Michael Natterer's avatar
Michael Natterer committed
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

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

Michael Natterer's avatar
Michael Natterer committed
743
  path_undo = path_transform_start_undo (gdisp->gimage);
Michael Natterer's avatar
Michael Natterer committed
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

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

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

Michael Natterer's avatar
Michael Natterer committed
768
769
770
771
772
773
      undo_push_transform (gdisp->gimage,
                           tool->ID,
                           G_TYPE_FROM_INSTANCE (tool),
                           tr_tool->old_trans_info,
                           NULL,
                           path_undo);
Michael Natterer's avatar
Michael Natterer committed
774
775
776
777
778
779
780
781
    }

  /*  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
   */
Nate Summers's avatar
Nate Summers committed
782
  gimp_tool_control_set_preserve(tool->control, FALSE);
Michael Natterer's avatar
Michael Natterer committed
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802

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

803
  if (transform_tool->info_dialog)
804
805
    gtk_widget_set_sensitive (GTK_WIDGET (transform_tool->info_dialog->shell),
                              FALSE);
Michael Natterer's avatar
Michael Natterer committed
806
807
808
809
810

  tool = GIMP_TOOL (transform_tool);

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

Michael Natterer's avatar
Michael Natterer committed
811
812
  progress = gimp_progress_start (tool->gdisp, progress_text, FALSE,
                                  NULL, NULL);
Michael Natterer's avatar
Michael Natterer committed
813
814
815

  ret = gimp_drawable_transform_tiles_affine (gimp_image_active_drawable (tool->gdisp->gimage),
                                              transform_tool->original,
816
                                              options->interpolation,
Michael Natterer's avatar
Michael Natterer committed
817
818
819
                                              options->clip,
                                              transform_tool->transform,
                                              options->direction,
Michael Natterer's avatar
Michael Natterer committed
820
821
822
                                              progress ?
                                              gimp_progress_update_and_flush : 
                                              NULL,
Michael Natterer's avatar
Michael Natterer committed
823
824
825
                                              progress);

  if (progress)
Michael Natterer's avatar
Michael Natterer committed
826
    gimp_progress_end (progress);
Michael Natterer's avatar
Michael Natterer committed
827
828
829
830

  return ret;
}

Nate Summers's avatar
Nate Summers committed
831
void
Nate Summers's avatar
Nate Summers committed
832
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
833
{
834
  g_return_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool));
Nate Summers's avatar
Nate Summers committed
835
836
837
838
839
840
841
842
843
844
845
846
847

  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
848

849
850
851
  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
852

853
  if (tr_tool->grid_coords != NULL && tr_tool->tgrid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
854
    {
855
856
857
      gint i, k;
      gint gci;

Nate Summers's avatar
Nate Summers committed
858
      gci = 0;
859
      k   = (tr_tool->ngx + tr_tool->ngy) * 2;
860

Nate Summers's avatar
Nate Summers committed
861
862
      for (i = 0; i < k; i++)
	{
Nate Summers's avatar
Nate Summers committed
863
864
865
866
867
	  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
868
869
870
871
872
	  gci += 2;
	}
    }
}

873
static void
874
gimp_transform_tool_reset (GimpTransformTool *tr_tool,
875
		           GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
876
{
Nate Summers's avatar
Nate Summers committed
877
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
878

879
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
880

Nate Summers's avatar
Nate Summers committed
881
  if (tr_tool->original)
882
883
884
885
    {
      tile_manager_destroy (tr_tool->original);
      tr_tool->original = NULL;
    }
Nate Summers's avatar
Nate Summers committed
886
887

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

890
  gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
891
892
893

  if (tr_tool->info_dialog)
    info_dialog_popdown (tr_tool->info_dialog);
Nate Summers's avatar
Nate Summers committed
894

Nate Summers's avatar
Nate Summers committed
895
  gimp_tool_control_halt(tool->control);    /* sets paused_count to 0 -- is this ok? */
Nate Summers's avatar
Nate Summers committed
896
897
898
899
900
  tool->gdisp    = NULL;
  tool->drawable = NULL;
}

static void
901
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
902
		            GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
903
{
904
905
  TileManager  *tiles;
  GimpDrawable *drawable;
Nate Summers's avatar
Nate Summers committed
906

907
908
  tiles    = tr_tool->original;
  drawable = gimp_image_active_drawable (gdisp->gimage);
Nate Summers's avatar
Nate Summers committed
909
910
911
912
913

  /*  find the boundaries  */
  if (tiles)
    {
      tile_manager_get_offsets (tiles,
Nate Summers's avatar
Nate Summers committed
914
915
916
917
				&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
918
919
920
    }
  else
    {
921
922
      gint offset_x, offset_y;

Nate Summers's avatar
Nate Summers committed
923
      gimp_drawable_offsets (drawable, &offset_x, &offset_y);
924

Nate Summers's avatar
Nate Summers committed
925
      gimp_drawable_mask_bounds (drawable,
Nate Summers's avatar
Nate Summers committed
926
927
928
929
930
931
				 &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
932
    }
Nate Summers's avatar
Nate Summers committed
933

934
935
  tr_tool->cx = (gdouble) (tr_tool->x1 + tr_tool->x2) / 2.0;
  tr_tool->cy = (gdouble) (tr_tool->y1 + tr_tool->y2) / 2.0;
Nate Summers's avatar
Nate Summers committed
936

Michael Natterer's avatar
Michael Natterer committed
937
938
939
940
941
  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
942
943
}

944
945
946
947
948
949
950
951
952
953
954
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),

955
                                      GIMP_STOCK_RESET, transform_reset_callback,
956
957
                                      tr_tool, NULL, NULL, FALSE, FALSE,

958
959
960
                                      ok_button, transform_ok_callback,
                                      tr_tool, NULL, NULL, TRUE, FALSE,

961
962
963
964
                                      NULL);
    }
}

Nate Summers's avatar
Nate Summers committed
965
void
Michael Natterer's avatar
Michael Natterer committed
966
gimp_transform_tool_grid_density_changed (GimpTransformTool *transform_tool)
Nate Summers's avatar
Nate Summers committed
967
{
Michael Natterer's avatar
Michael Natterer committed
968
  if (transform_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
969
970
    return;

Michael Natterer's avatar
Michael Natterer committed
971
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (transform_tool));
972

Michael Natterer's avatar
Michael Natterer committed
973
974
  gimp_transform_tool_grid_recalc (transform_tool);
  gimp_transform_tool_transform_bounding_box (transform_tool);
975

Michael Natterer's avatar
Michael Natterer committed
976
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (transform_tool));
Nate Summers's avatar
Nate Summers committed
977
978
979
}

void
Michael Natterer's avatar
Michael Natterer committed
980
981
gimp_transform_tool_show_path_changed (GimpTransformTool *transform_tool,
                                       gint               type /* a truly undescriptive name */)
Nate Summers's avatar
Nate Summers committed
982
{
Michael Natterer's avatar
Michael Natterer committed
983
  if (transform_tool->function == TRANSFORM_CREATING)
Nate Summers's avatar
Nate Summers committed
984
985
986
    return;

  if (type)
Michael Natterer's avatar
Michael Natterer committed
987
    gimp_draw_tool_pause (GIMP_DRAW_TOOL (transform_tool));
Nate Summers's avatar
Nate Summers committed
988
  else
Michael Natterer's avatar
Michael Natterer committed
989
    gimp_draw_tool_resume (GIMP_DRAW_TOOL (transform_tool));
Nate Summers's avatar
Nate Summers committed
990
991
992
}

static void
Nate Summers's avatar
Nate Summers committed
993
gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool)
Nate Summers's avatar
Nate Summers committed
994
{
Michael Natterer's avatar
Michael Natterer committed
995
996
997
998
  TransformOptions *options;

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

Nate Summers's avatar
Nate Summers committed
999
  if (tr_tool->grid_coords != NULL)
Nate Summers's avatar
Nate Summers committed
1000
    {
Nate Summers's avatar
Nate Summers committed
1001
1002
      g_free (tr_tool->grid_coords);
      tr_tool->grid_coords = NULL;
Nate Summers's avatar
Nate Summers committed
1003
    }
1004

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

Michael Natterer's avatar
Michael Natterer committed
1011
1012
1013
1014
  if (options->show_grid)
    {
      gimp_transform_tool_setup_grid (tr_tool, options);
    }
Nate Summers's avatar
Nate Summers committed
1015
1016
1017
}

static void
Michael Natterer's avatar
Michael Natterer committed
1018
1019
gimp_transform_tool_setup_grid (GimpTransformTool *tr_tool,
                                TransformOptions  *options)
Nate Summers's avatar
Nate Summers committed
1020
{
1021
1022
1023
  GimpTool *tool;
  gint      i, gci;
  gdouble  *coords;
Nate Summers's avatar
Nate Summers committed
1024

1025
  tool = GIMP_TOOL (tr_tool);
Nate Summers's avatar
Nate Summers committed
1026

Nate Summers's avatar
Nate Summers committed
1027
  /*  We use the gimp_transform_tool_grid_size function only here, even
Nate Summers's avatar
Nate Summers committed
1028
1029
1030
   *  if the user changes the grid size in the middle of an
   *  operation, nothing happens.
   */
Michael Natterer's avatar
Michael Natterer committed
1031
  tr_tool->ngx = (tr_tool->x2 - tr_tool->x1) / options->grid_size;
Nate Summers's avatar
Nate Summers committed
1032
1033
  if (tr_tool->ngx > 0)
    tr_tool->ngx--;
Nate Summers's avatar
Nate Summers committed
1034

Michael Natterer's avatar
Michael Natterer committed
1035
  tr_tool->ngy = (tr_tool->y2 - tr_tool->y1) / options->grid_size;
Nate Summers's avatar
Nate Summers committed
1036
1037
  if (tr_tool->ngy > 0)
    tr_tool->ngy--;
Nate Summers's avatar
Nate Summers committed
1038

Nate Summers's avatar
Nate Summers committed
1039
  tr_tool->grid_coords = coords =
1040
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1041

Nate Summers's avatar
Nate Summers committed
1042
  tr_tool->tgrid_coords =
1043
    g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
Nate Summers's avatar
Nate Summers committed
1044
1045

  gci = 0;
1046

Nate Summers's avatar
Nate Summers committed
1047
  for (i = 1; i <= tr_tool->ngx; i++)
Nate Summers's avatar
Nate Summers committed
1048
    {
1049
1050
1051
1052
1053
1054
      coords[gci]     = tr_tool->x1 + (((gdouble) i) / (tr_tool->ngx + 1) *
                                       (tr_tool->x2 - tr_tool->x1));
      coords[gci + 1] = tr_tool->y1;
      coords[gci + 2] = coords[gci];
      coords[gci + 3] = tr_tool->y2;

Nate Summers's avatar
Nate Summers committed
1055
1056
      gci += 4;
    }
1057

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

Nate Summers's avatar
Nate Summers committed
1066
1067
1068
1069
1070
      gci += 4;
    }
}

static void
1071
gimp_transform_tool_recalc (GimpTransformTool *tr_tool,
1072
		            GimpDisplay       *gdisp)
Nate Summers's avatar
Nate Summers committed
1073
{
Nate Summers's avatar
Nate Summers committed
1074
  gimp_transform_tool_bounds (tr_tool, gdisp);
Nate Summers's avatar
Nate Summers committed
1075

1076
  gimp_transform_tool_transform (tr_tool, gdisp, TRANSFORM_RECALC);
Nate Summers's avatar
Nate Summers committed
1077
1078
}

Michael Natterer's avatar
Michael Natterer committed
1079
1080
1081
static void
transform_ok_callback (GtkWidget *widget,
		       gpointer   data)
Nate Summers's avatar
Nate Summers committed
1082
{
Michael Natterer's avatar
Michael Natterer committed
1083
  GimpTool *tool;
Nate Summers's avatar
Nate Summers committed
1084

Michael Natterer's avatar
Michael Natterer committed
1085
1086
  tool = GIMP_TOOL(data);
  gimp_transform_tool_doit (GIMP_TRANSFORM_TOOL(tool), tool->gdisp);
Nate Summers's avatar
Nate Summers committed
1087
1088
}

Michael Natterer's avatar
Michael Natterer committed
1089
1090
1091
static void
transform_reset_callback (GtkWidget *widget,
			  gpointer   data)
Nate Summers's avatar
Nate Summers committed
1092
{
Michael Natterer's avatar
Michael Natterer committed
1093
1094
1095
  GimpTransformTool *transform_tool;
  GimpTool          *tool;
  gint               i;
Nate Summers's avatar
Nate Summers committed
1096

Michael Natterer's avatar
Michael Natterer committed
1097
1098
  transform_tool = GIMP_TRANSFORM_TOOL (data);
  tool           = GIMP_TOOL (data);
Nate Summers's avatar
Nate Summers committed
1099

Michael Natterer's avatar
Michael Natterer committed
1100
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
1101

Michael Natterer's avatar
Michael Natterer committed
1102
1103
  /*  Restore the previous transformation info  */
  for (i = 0; i < TRAN_INFO_SIZE; i++)
1104
    transform_tool->trans_info[i] = transform_tool->old_trans_info[i];
Nate Summers's avatar
Nate Summers committed
1105

Michael Natterer's avatar
Michael Natterer committed
1106
1107
  /*  recalculate the tool's transformation matrix  */
  gimp_transform_tool_recalc (transform_tool, tool->gdisp);
Nate Summers's avatar
Nate Summers committed
1108

Michael Natterer's avatar
Michael Natterer committed
1109
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Nate Summers's avatar
Nate Summers committed
1110
}