drawable-transform-cmds.c 130 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3
 * Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7 8 9 10 11 12 13 14
 * (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
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 17
 */

18
/* NOTE: This file is auto-generated by pdbgen.pl. */
19 20 21

#include "config.h"

22
#include <gegl.h>
23 24 25 26 27 28 29 30 31 32 33

#include "libgimpmath/gimpmath.h"

#include "pdb-types.h"

#include "config/gimpcoreconfig.h"
#include "core/gimp-transform-utils.h"
#include "core/gimp.h"
#include "core/gimpdrawable-transform.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
34
#include "core/gimpparamspecs.h"
35 36
#include "core/gimpprogress.h"

37 38 39
#include "gimppdb.h"
#include "gimppdb-utils.h"
#include "gimpprocedure.h"
40
#include "internal-procs.h"
41

42 43
#include "gimp-intl.h"

44

45
static GValueArray *
46 47 48 49 50 51
drawable_transform_flip_simple_invoker (GimpProcedure      *procedure,
                                        Gimp               *gimp,
                                        GimpContext        *context,
                                        GimpProgress       *progress,
                                        const GValueArray  *args,
                                        GError            **error)
52 53
{
  gboolean success = TRUE;
54
  GValueArray *return_vals;
55 56
  GimpDrawable *drawable;
  gint32 flip_type;
57
  gboolean auto_center;
58 59
  gdouble axis;
  gboolean clip_result;
60

61 62 63 64 65
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  flip_type = g_value_get_enum (&args->values[1]);
  auto_center = g_value_get_boolean (&args->values[2]);
  axis = g_value_get_double (&args->values[3]);
  clip_result = g_value_get_boolean (&args->values[4]);
66 67 68

  if (success)
    {
69 70
      gint x, y, width, height;

71
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
72

73
      if (success &&
74
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
75
        {
76 77 78
          gimp_transform_get_flip_axis (x, y, width, height,
                                        flip_type, auto_center, &axis);

79 80 81 82 83 84 85
          if (! gimp_drawable_transform_flip (drawable, context,
                                              flip_type,
                                              axis,
                                              clip_result))
            {
              success = FALSE;
            }
86
        }
87 88
    }

89 90
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
91 92

  if (success)
93
    gimp_value_set_drawable (&return_vals->values[1], drawable);
94

95
  return return_vals;
96 97
}

98
static GValueArray *
99 100 101 102 103 104
drawable_transform_flip_invoker (GimpProcedure      *procedure,
                                 Gimp               *gimp,
                                 GimpContext        *context,
                                 GimpProgress       *progress,
                                 const GValueArray  *args,
                                 GError            **error)
105 106
{
  gboolean success = TRUE;
107
  GValueArray *return_vals;
108
  GimpDrawable *drawable;
109 110
  gdouble x0;
  gdouble y0;
111 112 113 114 115 116 117
  gdouble x1;
  gdouble y1;
  gint32 transform_direction;
  gint32 interpolation;
  gboolean supersample;
  gint32 recursion_level;
  gboolean clip_result;
118

119 120 121 122 123 124 125 126 127 128
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  x0 = g_value_get_double (&args->values[1]);
  y0 = g_value_get_double (&args->values[2]);
  x1 = g_value_get_double (&args->values[3]);
  y1 = g_value_get_double (&args->values[4]);
  transform_direction = g_value_get_enum (&args->values[5]);
  interpolation = g_value_get_enum (&args->values[6]);
  supersample = g_value_get_boolean (&args->values[7]);
  recursion_level = g_value_get_int (&args->values[8]);
  clip_result = g_value_get_boolean (&args->values[9]);
129 130 131

  if (success)
    {
132 133
      gint x, y, width, height;

134
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
135

136
      if (success &&
137
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
138
        {
139
          GimpMatrix3 matrix;
140 141
          gint        off_x, off_y;

142
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
143 144 145

          x += off_x;
          y += off_y;
146 147

          /* Assemble the transformation matrix */
148 149
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_flip_free (&matrix,
150
                                           x0, y0, x1, y1);
151 152

          if (progress)
153
            gimp_progress_start (progress, _("Flipping"), FALSE);
154

155 156 157 158 159 160 161
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, transform_direction,
                                                interpolation, recursion_level,
                                                clip_result, progress))
            {
              success = FALSE;
            }
162

163 164
          if (progress)
            gimp_progress_end (progress);
165 166 167
        }
    }

168 169
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
170 171

  if (success)
172
    gimp_value_set_drawable (&return_vals->values[1], drawable);
173

174
  return return_vals;
175 176
}

177
static GValueArray *
178 179 180 181 182 183
drawable_transform_flip_default_invoker (GimpProcedure      *procedure,
                                         Gimp               *gimp,
                                         GimpContext        *context,
                                         GimpProgress       *progress,
                                         const GValueArray  *args,
                                         GError            **error)
184 185
{
  gboolean success = TRUE;
186
  GValueArray *return_vals;
187 188 189 190 191
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
192
  gboolean interpolate;
193 194
  gboolean clip_result;

195 196 197 198 199 200 201
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  x0 = g_value_get_double (&args->values[1]);
  y0 = g_value_get_double (&args->values[2]);
  x1 = g_value_get_double (&args->values[3]);
  y1 = g_value_get_double (&args->values[4]);
  interpolate = g_value_get_boolean (&args->values[5]);
  clip_result = g_value_get_boolean (&args->values[6]);
202 203 204 205 206

  if (success)
    {
      gint x, y, width, height;

207
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
208 209

      if (success &&
210
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
211 212 213
        {
          GimpMatrix3           matrix;
          GimpInterpolationType interpolation_type = GIMP_INTERPOLATION_NONE;
214 215
          gint                  off_x, off_y;

216
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
217 218 219

          x += off_x;
          y += off_y;
220 221

          /* Assemble the transformation matrix */
222 223
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_flip_free (&matrix,
224
                                           x0, y0, x1, y1);
225

226
          if (interpolate)
227 228 229
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
230
            gimp_progress_start (progress, _("Flipping"), FALSE);
231

232 233 234 235 236 237 238
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, GIMP_TRANSFORM_FORWARD,
                                                interpolation_type, 3,
                                                clip_result, progress))
            {
              success = FALSE;
            }
239

240 241 242 243 244
          if (progress)
            gimp_progress_end (progress);
        }
    }

245 246
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
247 248

  if (success)
249
    gimp_value_set_drawable (&return_vals->values[1], drawable);
250

251
  return return_vals;
252 253
}

254
static GValueArray *
255 256 257 258 259 260
drawable_transform_perspective_invoker (GimpProcedure      *procedure,
                                        Gimp               *gimp,
                                        GimpContext        *context,
                                        GimpProgress       *progress,
                                        const GValueArray  *args,
                                        GError            **error)
261 262
{
  gboolean success = TRUE;
263
  GValueArray *return_vals;
264
  GimpDrawable *drawable;
265 266 267 268 269 270 271 272
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gdouble x2;
  gdouble y2;
  gdouble x3;
  gdouble y3;
273 274 275 276
  gint32 transform_direction;
  gint32 interpolation;
  gboolean supersample;
  gint32 recursion_level;
277
  gint32 clip_result;
278

279 280 281 282 283 284 285 286 287 288 289 290 291
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  x0 = g_value_get_double (&args->values[1]);
  y0 = g_value_get_double (&args->values[2]);
  x1 = g_value_get_double (&args->values[3]);
  y1 = g_value_get_double (&args->values[4]);
  x2 = g_value_get_double (&args->values[5]);
  y2 = g_value_get_double (&args->values[6]);
  x3 = g_value_get_double (&args->values[7]);
  y3 = g_value_get_double (&args->values[8]);
  transform_direction = g_value_get_enum (&args->values[9]);
  interpolation = g_value_get_enum (&args->values[10]);
  supersample = g_value_get_boolean (&args->values[11]);
  recursion_level = g_value_get_int (&args->values[12]);
292
  clip_result = g_value_get_enum (&args->values[13]);
293 294 295

  if (success)
    {
296 297
      gint x, y, width, height;

298
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
299

300
      if (success &&
301
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
302
        {
303
          GimpMatrix3 matrix;
304 305
          gint        off_x, off_y;

306
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
307 308 309

          x += off_x;
          y += off_y;
310 311

          /* Assemble the transformation matrix */
312 313 314
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_perspective (&matrix,
                                             x, y, width, height,
315 316
                                             x0, y0, x1, y1,
                                             x2, y2, x3, y3);
317 318

          if (progress)
319
            gimp_progress_start (progress, _("Perspective"), FALSE);
320

321 322 323 324 325 326 327
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, transform_direction,
                                                interpolation, recursion_level,
                                                clip_result, progress))
            {
              success = FALSE;
            }
328 329 330

          if (progress)
            gimp_progress_end (progress);
331 332 333
        }
    }

334 335
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
336 337

  if (success)
338
    gimp_value_set_drawable (&return_vals->values[1], drawable);
339

340
  return return_vals;
341 342
}

343
static GValueArray *
344 345 346 347 348 349
drawable_transform_perspective_default_invoker (GimpProcedure      *procedure,
                                                Gimp               *gimp,
                                                GimpContext        *context,
                                                GimpProgress       *progress,
                                                const GValueArray  *args,
                                                GError            **error)
350 351
{
  gboolean success = TRUE;
352
  GValueArray *return_vals;
353
  GimpDrawable *drawable;
354 355 356 357 358 359 360 361
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gdouble x2;
  gdouble y2;
  gdouble x3;
  gdouble y3;
362
  gboolean interpolate;
363
  gint32 clip_result;
364

365 366 367 368 369 370 371 372 373 374
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  x0 = g_value_get_double (&args->values[1]);
  y0 = g_value_get_double (&args->values[2]);
  x1 = g_value_get_double (&args->values[3]);
  y1 = g_value_get_double (&args->values[4]);
  x2 = g_value_get_double (&args->values[5]);
  y2 = g_value_get_double (&args->values[6]);
  x3 = g_value_get_double (&args->values[7]);
  y3 = g_value_get_double (&args->values[8]);
  interpolate = g_value_get_boolean (&args->values[9]);
375
  clip_result = g_value_get_enum (&args->values[10]);
376 377 378 379 380

  if (success)
    {
      gint x, y, width, height;

381
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
382 383

      if (success &&
384
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
385
        {
386 387
          GimpMatrix3           matrix;
          GimpInterpolationType interpolation_type = GIMP_INTERPOLATION_NONE;
388 389
          gint                  off_x, off_y;

390
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
391 392 393

          x += off_x;
          y += off_y;
394 395

          /* Assemble the transformation matrix */
396 397 398
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_perspective (&matrix,
                                             x, y, width, height,
399 400
                                             x0, y0, x1, y1,
                                             x2, y2, x3, y3);
401

402
          if (interpolate)
403 404 405
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
406
            gimp_progress_start (progress, _("Perspective"), FALSE);
407

408 409 410 411 412 413 414
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, GIMP_TRANSFORM_FORWARD,
                                                interpolation_type, 3,
                                                clip_result, progress))
            {
              success = FALSE;
            }
415 416 417

          if (progress)
            gimp_progress_end (progress);
418 419 420
        }
    }

421 422
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
423 424

  if (success)
425
    gimp_value_set_drawable (&return_vals->values[1], drawable);
426

427
  return return_vals;
428 429
}

430
static GValueArray *
431 432 433 434 435 436
drawable_transform_rotate_simple_invoker (GimpProcedure      *procedure,
                                          Gimp               *gimp,
                                          GimpContext        *context,
                                          GimpProgress       *progress,
                                          const GValueArray  *args,
                                          GError            **error)
437 438
{
  gboolean success = TRUE;
439
  GValueArray *return_vals;
440
  GimpDrawable *drawable;
441
  gint32 rotate_type;
442
  gboolean auto_center;
443 444
  gint32 center_x;
  gint32 center_y;
445
  gboolean clip_result;
446

447 448 449 450 451 452
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  rotate_type = g_value_get_enum (&args->values[1]);
  auto_center = g_value_get_boolean (&args->values[2]);
  center_x = g_value_get_int (&args->values[3]);
  center_y = g_value_get_int (&args->values[4]);
  clip_result = g_value_get_boolean (&args->values[5]);
453

454 455 456 457
  if (success)
    {
      gint x, y, width, height;

458
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, FALSE, error);
459 460

      if (success &&
461
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
462
        {
463 464 465 466 467 468
          gdouble cx = center_x;
          gdouble cy = center_y;

          gimp_transform_get_rotate_center (x, y, width, height,
                                            auto_center, &cx, &cy);

469 470 471 472 473 474 475
          if (! gimp_drawable_transform_rotate (drawable, context,
                                                rotate_type,
                                                cx, cy,
                                                clip_result))
            {
              success = FALSE;
            }
476 477 478
        }
    }

479 480
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
481 482

  if (success)
483
    gimp_value_set_drawable (&return_vals->values[1], drawable);
484

485
  return return_vals;
486 487
}

488
static GValueArray *
489 490 491 492 493 494
drawable_transform_rotate_invoker (GimpProcedure      *procedure,
                                   Gimp               *gimp,
                                   GimpContext        *context,
                                   GimpProgress       *progress,
                                   const GValueArray  *args,
                                   GError            **error)
495 496
{
  gboolean success = TRUE;
497
  GValueArray *return_vals;
498 499 500 501 502 503 504 505 506
  GimpDrawable *drawable;
  gdouble angle;
  gboolean auto_center;
  gint32 center_x;
  gint32 center_y;
  gint32 transform_direction;
  gint32 interpolation;
  gboolean supersample;
  gint32 recursion_level;
507
  gint32 clip_result;
508

509 510 511 512 513 514 515 516 517
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  angle = g_value_get_double (&args->values[1]);
  auto_center = g_value_get_boolean (&args->values[2]);
  center_x = g_value_get_int (&args->values[3]);
  center_y = g_value_get_int (&args->values[4]);
  transform_direction = g_value_get_enum (&args->values[5]);
  interpolation = g_value_get_enum (&args->values[6]);
  supersample = g_value_get_boolean (&args->values[7]);
  recursion_level = g_value_get_int (&args->values[8]);
518
  clip_result = g_value_get_enum (&args->values[9]);
519 520 521

  if (success)
    {
522 523
      gint x, y, width, height;

524
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
525

526
      if (success &&
527
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
528
        {
529
          GimpMatrix3 matrix;
530 531
          gint        off_x, off_y;

532
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
533 534 535

          x += off_x;
          y += off_y;
536 537

          /* Assemble the transformation matrix */
538
          gimp_matrix3_identity (&matrix);
539
          if (auto_center)
540 541
            gimp_transform_matrix_rotate_rect (&matrix,
                                               x, y, width, height, angle);
542
          else
543 544
            gimp_transform_matrix_rotate_center (&matrix,
                                                 center_x, center_y, angle);
545 546

          if (progress)
547
            gimp_progress_start (progress, _("Rotating"), FALSE);
548

549 550 551 552 553 554 555
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, transform_direction,
                                                interpolation, recursion_level,
                                                clip_result, progress))
            {
              success = FALSE;
            }
556 557 558 559 560 561

          if (progress)
            gimp_progress_end (progress);
        }
    }

562 563
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
564 565

  if (success)
566
    gimp_value_set_drawable (&return_vals->values[1], drawable);
567

568
  return return_vals;
569 570
}

571
static GValueArray *
572 573 574 575 576 577
drawable_transform_rotate_default_invoker (GimpProcedure      *procedure,
                                           Gimp               *gimp,
                                           GimpContext        *context,
                                           GimpProgress       *progress,
                                           const GValueArray  *args,
                                           GError            **error)
578 579
{
  gboolean success = TRUE;
580
  GValueArray *return_vals;
581 582 583 584 585
  GimpDrawable *drawable;
  gdouble angle;
  gboolean auto_center;
  gint32 center_x;
  gint32 center_y;
586
  gboolean interpolate;
587
  gint32 clip_result;
588

589 590 591 592 593 594
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  angle = g_value_get_double (&args->values[1]);
  auto_center = g_value_get_boolean (&args->values[2]);
  center_x = g_value_get_int (&args->values[3]);
  center_y = g_value_get_int (&args->values[4]);
  interpolate = g_value_get_boolean (&args->values[5]);
595
  clip_result = g_value_get_enum (&args->values[6]);
596 597 598 599 600

  if (success)
    {
      gint x, y, width, height;

601
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
602 603

      if (success &&
604
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
605 606 607
        {
          GimpMatrix3           matrix;
          GimpInterpolationType interpolation_type = GIMP_INTERPOLATION_NONE;
608 609
          gint                  off_x, off_y;

610
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
611 612 613

          x += off_x;
          y += off_y;
614 615

          /* Assemble the transformation matrix */
616
          gimp_matrix3_identity (&matrix);
617
          if (auto_center)
618 619
            gimp_transform_matrix_rotate_rect (&matrix,
                                               x, y, width, height, angle);
620
          else
621 622
            gimp_transform_matrix_rotate_center (&matrix,
                                                 center_x, center_y, angle);
623

624
          if (interpolate)
625 626 627
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
628
            gimp_progress_start (progress, _("Rotating"), FALSE);
629

630 631 632 633 634 635 636
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, GIMP_TRANSFORM_FORWARD,
                                                interpolation_type, 3,
                                                clip_result, progress))
            {
              success = FALSE;
            }
637 638 639 640 641 642

          if (progress)
            gimp_progress_end (progress);
        }
    }

643 644
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
645 646

  if (success)
647
    gimp_value_set_drawable (&return_vals->values[1], drawable);
648

649
  return return_vals;
650 651
}

652
static GValueArray *
653 654 655 656 657 658
drawable_transform_scale_invoker (GimpProcedure      *procedure,
                                  Gimp               *gimp,
                                  GimpContext        *context,
                                  GimpProgress       *progress,
                                  const GValueArray  *args,
                                  GError            **error)
659 660
{
  gboolean success = TRUE;
661
  GValueArray *return_vals;
662
  GimpDrawable *drawable;
663 664 665 666
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
667 668 669 670
  gint32 transform_direction;
  gint32 interpolation;
  gboolean supersample;
  gint32 recursion_level;
671
  gint32 clip_result;
672

673 674 675 676 677 678 679 680 681
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  x0 = g_value_get_double (&args->values[1]);
  y0 = g_value_get_double (&args->values[2]);
  x1 = g_value_get_double (&args->values[3]);
  y1 = g_value_get_double (&args->values[4]);
  transform_direction = g_value_get_enum (&args->values[5]);
  interpolation = g_value_get_enum (&args->values[6]);
  supersample = g_value_get_boolean (&args->values[7]);
  recursion_level = g_value_get_int (&args->values[8]);
682
  clip_result = g_value_get_enum (&args->values[9]);
683 684 685

  if (success)
    {
686 687
      gint x, y, width, height;

688
      success = (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error) && x0 < x1 && y0 < y1);
689

690
      if (success &&
691
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
692
        {
693
          GimpMatrix3 matrix;
694 695
          gint        off_x, off_y;

696
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
697 698 699

          x += off_x;
          y += off_y;
700

701
          /* Assemble the transformation matrix */
702 703 704
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_scale (&matrix,
                                       x, y, width, height,
705
                                       x0, y0, x1 - x0, y1 - y0);
706

707
          if (progress)
708
            gimp_progress_start (progress, _("Scaling"), FALSE);
709

710 711 712 713 714 715 716
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, transform_direction,
                                                interpolation, recursion_level,
                                                clip_result, progress))
            {
              success = FALSE;
            }
717

718 719
          if (progress)
            gimp_progress_end (progress);
720 721 722
        }
    }

723 724
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
725 726

  if (success)
727
    gimp_value_set_drawable (&return_vals->values[1], drawable);
728

729
  return return_vals;
730 731
}

732
static GValueArray *
733 734 735 736 737 738
drawable_transform_scale_default_invoker (GimpProcedure      *procedure,
                                          Gimp               *gimp,
                                          GimpContext        *context,
                                          GimpProgress       *progress,
                                          const GValueArray  *args,
                                          GError            **error)
739 740
{
  gboolean success = TRUE;
741
  GValueArray *return_vals;
742
  GimpDrawable *drawable;
743 744 745 746
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
747
  gboolean interpolate;
748
  gint32 clip_result;
749

750 751 752 753 754 755
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  x0 = g_value_get_double (&args->values[1]);
  y0 = g_value_get_double (&args->values[2]);
  x1 = g_value_get_double (&args->values[3]);
  y1 = g_value_get_double (&args->values[4]);
  interpolate = g_value_get_boolean (&args->values[5]);
756
  clip_result = g_value_get_enum (&args->values[6]);
757 758 759 760 761

  if (success)
    {
      gint x, y, width, height;

762
      success = (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error) && x0 < x1 && y0 < y1);
763 764

      if (success &&
765
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
766 767 768
        {
          GimpMatrix3           matrix;
          GimpInterpolationType interpolation_type = GIMP_INTERPOLATION_NONE;
769 770
          gint                  off_x, off_y;

771
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
772 773 774

          x += off_x;
          y += off_y;
775 776

          /* Assemble the transformation matrix */
777 778 779
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_scale (&matrix,
                                       x, y, width, height,
780
                                       x0, y0, x1 - x0, y1 - y0);
781

782
          if (interpolate)
783 784 785
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
786
            gimp_progress_start (progress, _("Scaling"), FALSE);
787

788 789 790 791 792 793 794
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, GIMP_TRANSFORM_FORWARD,
                                                interpolation_type, 3,
                                                clip_result, progress))
            {
              success = FALSE;
            }
795 796 797 798 799 800

          if (progress)
            gimp_progress_end (progress);
        }
    }

801 802
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
803 804

  if (success)
805
    gimp_value_set_drawable (&return_vals->values[1], drawable);
806

807
  return return_vals;
808 809
}

810
static GValueArray *
811 812 813 814 815 816
drawable_transform_shear_invoker (GimpProcedure      *procedure,
                                  Gimp               *gimp,
                                  GimpContext        *context,
                                  GimpProgress       *progress,
                                  const GValueArray  *args,
                                  GError            **error)
817 818
{
  gboolean success = TRUE;
819
  GValueArray *return_vals;
820 821 822 823 824 825 826
  GimpDrawable *drawable;
  gint32 shear_type;
  gdouble magnitude;
  gint32 transform_direction;
  gint32 interpolation;
  gboolean supersample;
  gint32 recursion_level;
827
  gint32 clip_result;
828

829 830 831 832 833 834 835
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  shear_type = g_value_get_enum (&args->values[1]);
  magnitude = g_value_get_double (&args->values[2]);
  transform_direction = g_value_get_enum (&args->values[3]);
  interpolation = g_value_get_enum (&args->values[4]);
  supersample = g_value_get_boolean (&args->values[5]);
  recursion_level = g_value_get_int (&args->values[6]);
836
  clip_result = g_value_get_enum (&args->values[7]);
837 838 839

  if (success)
    {
840 841
      gint x, y, width, height;

842
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
843

844
      if (success &&
845
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
846
        {
847
          GimpMatrix3 matrix;
848 849
          gint        off_x, off_y;

850
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
851 852 853

          x += off_x;
          y += off_y;
854

855
          /* Assemble the transformation matrix */
856 857 858 859
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_shear (&matrix,
                                       x, y, width, height,
                                       shear_type, magnitude);
860

861
          if (progress)
862
            gimp_progress_start (progress, _("Shearing"), FALSE);
863

864 865 866 867 868 869 870
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, transform_direction,
                                                interpolation, recursion_level,
                                                clip_result, progress))
            {
              success = FALSE;
            }
871

872 873
          if (progress)
            gimp_progress_end (progress);
874 875 876
        }
    }

877 878
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
879 880

  if (success)
881
    gimp_value_set_drawable (&return_vals->values[1], drawable);
882

883
  return return_vals;
884 885
}

886
static GValueArray *
887 888 889 890 891 892
drawable_transform_shear_default_invoker (GimpProcedure      *procedure,
                                          Gimp               *gimp,
                                          GimpContext        *context,
                                          GimpProgress       *progress,
                                          const GValueArray  *args,
                                          GError            **error)
893 894
{
  gboolean success = TRUE;
895
  GValueArray *return_vals;
896 897 898
  GimpDrawable *drawable;
  gint32 shear_type;
  gdouble magnitude;
899
  gboolean interpolate;
900
  gint32 clip_result;
901

902 903 904 905
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  shear_type = g_value_get_enum (&args->values[1]);
  magnitude = g_value_get_double (&args->values[2]);
  interpolate = g_value_get_boolean (&args->values[3]);
906
  clip_result = g_value_get_enum (&args->values[4]);
907 908 909 910 911

  if (success)
    {
      gint x, y, width, height;

912
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
913 914

      if (success &&
915
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
916 917 918
        {
          GimpMatrix3           matrix;
          GimpInterpolationType interpolation_type = GIMP_INTERPOLATION_NONE;
919 920
          gint                  off_x, off_y;

921
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
922 923 924

          x += off_x;
          y += off_y;
925 926

          /* Assemble the transformation matrix */
927 928 929 930
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_shear (&matrix,
                                       x, y, width, height,
                                       shear_type, magnitude);
931

932
          if (interpolate)
933 934 935
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
936
            gimp_progress_start (progress, _("Shearing"), FALSE);
937

938 939 940 941 942 943 944
          if (! gimp_drawable_transform_affine (drawable, context,
                                                &matrix, GIMP_TRANSFORM_FORWARD,
                                                interpolation_type, 3,
                                                clip_result, progress))
            {
              success = FALSE;
            }
945 946 947 948 949 950

          if (progress)
            gimp_progress_end (progress);
        }
    }

951 952
  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);
953 954

  if (success)
955
    gimp_value_set_drawable (&return_vals->values[1], drawable);
956

957
  return return_vals;
958 959
}

960
static GValueArray *
961 962 963 964 965 966
drawable_transform_2d_invoker (GimpProcedure      *procedure,
                               Gimp               *gimp,
                               GimpContext        *context,
                               GimpProgress       *progress,
                               const GValueArray  *args,
                               GError            **error)
967 968
{
  gboolean success = TRUE;
969
  GValueArray *return_vals;
970 971 972 973 974 975 976 977 978 979 980 981
  GimpDrawable *drawable;
  gdouble source_x;
  gdouble source_y;
  gdouble scale_x;
  gdouble scale_y;
  gdouble angle;
  gdouble dest_x;
  gdouble dest_y;
  gint32 transform_direction;
  gint32 interpolation;
  gboolean supersample;
  gint32 recursion_level;
982
  gint32 clip_result;
983

984 985 986 987 988 989 990 991 992 993 994 995
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  source_x = g_value_get_double (&args->values[1]);
  source_y = g_value_get_double (&args->values[2]);
  scale_x = g_value_get_double (&args->values[3]);
  scale_y = g_value_get_double (&args->values[4]);
  angle = g_value_get_double (&args->values[5]);
  dest_x = g_value_get_double (&args->values[6]);
  dest_y = g_value_get_double (&args->values[7]);
  transform_direction = g_value_get_enum (&args->values[8]);
  interpolation = g_value_get_enum (&args->values[9]);
  supersample = g_value_get_boolean (&args->values[10]);
  recursion_level = g_value_get_int (&args->values[11]);
996
  clip_result = g_value_get_enum (&args->values[12]);
997 998 999 1000 1001

  if (success)
    {
      gint x, y, width, height;

1002
      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error);
1003 1004

      if (success &&
1005
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
1006 1007
        {
          GimpMatrix3 matrix;
1008 1009
          gint        off_x, off_y;

1010
          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
1011 1012 1013

          x += off_x;
          y += off_y;
1014