/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
 *
 * 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 3 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, see <https://www.gnu.org/licenses/>.
 */

/* NOTE: This file is auto-generated by pdbgen.pl. */

#include "config.h"

#include <gegl.h>

#include <gdk-pixbuf/gdk-pixbuf.h>

#include "libgimpmath/gimpmath.h"

#include "libgimpbase/gimpbase.h"

#include "pdb-types.h"

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

#include "gimppdb.h"
#include "gimppdb-utils.h"
#include "gimpprocedure.h"
#include "internal-procs.h"

#include "gimp-intl.h"


static GimpValueArray *
drawable_transform_flip_simple_invoker (GimpProcedure         *procedure,
                                        Gimp                  *gimp,
                                        GimpContext           *context,
                                        GimpProgress          *progress,
                                        const GimpValueArray  *args,
                                        GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 flip_type;
  gboolean auto_center;
  gdouble axis;
  gboolean clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  flip_type = g_value_get_enum (gimp_value_array_index (args, 1));
  auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
  axis = g_value_get_double (gimp_value_array_index (args, 3));
  clip_result = g_value_get_boolean (gimp_value_array_index (args, 4));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                           GIMP_PDB_ITEM_CONTENT |
                                           GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);

          gimp_transform_get_flip_axis (x, y, width, height,
                                        flip_type, auto_center, &axis);

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_flip (drawable, context,
                                                  flip_type, axis, clip_result))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_flip (GIMP_ITEM (drawable), context,
                              flip_type, axis, clip_result);
            }
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_flip_invoker (GimpProcedure         *procedure,
                                 Gimp                  *gimp,
                                 GimpContext           *context,
                                 GimpProgress          *progress,
                                 const GimpValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gint32 transform_direction;
  gint32 interpolation;
  gboolean clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  x0 = g_value_get_double (gimp_value_array_index (args, 1));
  y0 = g_value_get_double (gimp_value_array_index (args, 2));
  x1 = g_value_get_double (gimp_value_array_index (args, 3));
  y1 = g_value_get_double (gimp_value_array_index (args, 4));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 5));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 6));
  clip_result = g_value_get_boolean (gimp_value_array_index (args, 9));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION,
                                                        error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

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

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_flip_default_invoker (GimpProcedure         *procedure,
                                         Gimp                  *gimp,
                                         GimpContext           *context,
                                         GimpProgress          *progress,
                                         const GimpValueArray  *args,
                                         GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gboolean interpolate;
  gboolean clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  x0 = g_value_get_double (gimp_value_array_index (args, 1));
  y0 = g_value_get_double (gimp_value_array_index (args, 2));
  x1 = g_value_get_double (gimp_value_array_index (args, 3));
  y1 = g_value_get_double (gimp_value_array_index (args, 4));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 5));
  clip_result = g_value_get_boolean (gimp_value_array_index (args, 6));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

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

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_perspective_invoker (GimpProcedure         *procedure,
                                        Gimp                  *gimp,
                                        GimpContext           *context,
                                        GimpProgress          *progress,
                                        const GimpValueArray  *args,
                                        GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gdouble x2;
  gdouble y2;
  gdouble x3;
  gdouble y3;
  gint32 transform_direction;
  gint32 interpolation;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  x0 = g_value_get_double (gimp_value_array_index (args, 1));
  y0 = g_value_get_double (gimp_value_array_index (args, 2));
  x1 = g_value_get_double (gimp_value_array_index (args, 3));
  y1 = g_value_get_double (gimp_value_array_index (args, 4));
  x2 = g_value_get_double (gimp_value_array_index (args, 5));
  y2 = g_value_get_double (gimp_value_array_index (args, 6));
  x3 = g_value_get_double (gimp_value_array_index (args, 7));
  y3 = g_value_get_double (gimp_value_array_index (args, 8));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 9));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 10));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 13));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION,
                                                        error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

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

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_perspective_default_invoker (GimpProcedure         *procedure,
                                                Gimp                  *gimp,
                                                GimpContext           *context,
                                                GimpProgress          *progress,
                                                const GimpValueArray  *args,
                                                GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gdouble x2;
  gdouble y2;
  gdouble x3;
  gdouble y3;
  gboolean interpolate;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  x0 = g_value_get_double (gimp_value_array_index (args, 1));
  y0 = g_value_get_double (gimp_value_array_index (args, 2));
  x1 = g_value_get_double (gimp_value_array_index (args, 3));
  y1 = g_value_get_double (gimp_value_array_index (args, 4));
  x2 = g_value_get_double (gimp_value_array_index (args, 5));
  y2 = g_value_get_double (gimp_value_array_index (args, 6));
  x3 = g_value_get_double (gimp_value_array_index (args, 7));
  y3 = g_value_get_double (gimp_value_array_index (args, 8));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 9));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 10));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

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

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_rotate_simple_invoker (GimpProcedure         *procedure,
                                          Gimp                  *gimp,
                                          GimpContext           *context,
                                          GimpProgress          *progress,
                                          const GimpValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 rotate_type;
  gboolean auto_center;
  gint32 center_x;
  gint32 center_y;
  gboolean clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  rotate_type = g_value_get_enum (gimp_value_array_index (args, 1));
  auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
  center_x = g_value_get_int (gimp_value_array_index (args, 3));
  center_y = g_value_get_int (gimp_value_array_index (args, 4));
  clip_result = g_value_get_boolean (gimp_value_array_index (args, 5));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                           GIMP_PDB_ITEM_CONTENT |
                                           GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          gdouble      cx    = center_x;
          gdouble      cy    = center_y;

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_rotate (drawable, context,
                                                    rotate_type, cx, cy,
                                                    clip_result))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_rotate (GIMP_ITEM (drawable), context,
                                rotate_type, cx, cy,
                                clip_result);
            }
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_rotate_invoker (GimpProcedure         *procedure,
                                   Gimp                  *gimp,
                                   GimpContext           *context,
                                   GimpProgress          *progress,
                                   const GimpValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble angle;
  gboolean auto_center;
  gint32 center_x;
  gint32 center_y;
  gint32 transform_direction;
  gint32 interpolation;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  angle = g_value_get_double (gimp_value_array_index (args, 1));
  auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
  center_x = g_value_get_int (gimp_value_array_index (args, 3));
  center_y = g_value_get_int (gimp_value_array_index (args, 4));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 5));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 6));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 9));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION,
                                                        error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          gimp_matrix3_identity (&matrix);
          if (auto_center)
            gimp_transform_matrix_rotate_rect (&matrix,
                                               x, y, width, height, angle);
          else
            gimp_transform_matrix_rotate_center (&matrix,
                                                 center_x, center_y, angle);

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_rotate_default_invoker (GimpProcedure         *procedure,
                                           Gimp                  *gimp,
                                           GimpContext           *context,
                                           GimpProgress          *progress,
                                           const GimpValueArray  *args,
                                           GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble angle;
  gboolean auto_center;
  gint32 center_x;
  gint32 center_y;
  gboolean interpolate;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  angle = g_value_get_double (gimp_value_array_index (args, 1));
  auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
  center_x = g_value_get_int (gimp_value_array_index (args, 3));
  center_y = g_value_get_int (gimp_value_array_index (args, 4));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 5));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 6));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          gimp_matrix3_identity (&matrix);
          if (auto_center)
            gimp_transform_matrix_rotate_rect (&matrix,
                                               x, y, width, height, angle);
          else
            gimp_transform_matrix_rotate_center (&matrix,
                                                 center_x, center_y, angle);

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_scale_invoker (GimpProcedure         *procedure,
                                  Gimp                  *gimp,
                                  GimpContext           *context,
                                  GimpProgress          *progress,
                                  const GimpValueArray  *args,
                                  GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gint32 transform_direction;
  gint32 interpolation;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  x0 = g_value_get_double (gimp_value_array_index (args, 1));
  y0 = g_value_get_double (gimp_value_array_index (args, 2));
  x1 = g_value_get_double (gimp_value_array_index (args, 3));
  y1 = g_value_get_double (gimp_value_array_index (args, 4));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 5));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 6));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 9));

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

      success = (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                          GIMP_PDB_ITEM_CONTENT |
                                                          GIMP_PDB_ITEM_POSITION, error) && x0 < x1 && y0 < y1);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

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

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_scale_default_invoker (GimpProcedure         *procedure,
                                          Gimp                  *gimp,
                                          GimpContext           *context,
                                          GimpProgress          *progress,
                                          const GimpValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble x0;
  gdouble y0;
  gdouble x1;
  gdouble y1;
  gboolean interpolate;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  x0 = g_value_get_double (gimp_value_array_index (args, 1));
  y0 = g_value_get_double (gimp_value_array_index (args, 2));
  x1 = g_value_get_double (gimp_value_array_index (args, 3));
  y1 = g_value_get_double (gimp_value_array_index (args, 4));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 5));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 6));

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

      success = (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                          GIMP_PDB_ITEM_CONTENT |
                                                          GIMP_PDB_ITEM_POSITION, error) && x0 < x1 && y0 < y1);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

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

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_shear_invoker (GimpProcedure         *procedure,
                                  Gimp                  *gimp,
                                  GimpContext           *context,
                                  GimpProgress          *progress,
                                  const GimpValueArray  *args,
                                  GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 shear_type;
  gdouble magnitude;
  gint32 transform_direction;
  gint32 interpolation;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  shear_type = g_value_get_enum (gimp_value_array_index (args, 1));
  magnitude = g_value_get_double (gimp_value_array_index (args, 2));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 3));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 4));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 7));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION,
                                                        error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_shear (&matrix,
                                       x, y, width, height,
                                       shear_type, magnitude);

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_shear_default_invoker (GimpProcedure         *procedure,
                                          Gimp                  *gimp,
                                          GimpContext           *context,
                                          GimpProgress          *progress,
                                          const GimpValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 shear_type;
  gdouble magnitude;
  gboolean interpolate;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  shear_type = g_value_get_enum (gimp_value_array_index (args, 1));
  magnitude = g_value_get_double (gimp_value_array_index (args, 2));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 3));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 4));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          gimp_matrix3_identity (&matrix);
          gimp_transform_matrix_shear (&matrix,
                                       x, y, width, height,
                                       shear_type, magnitude);

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

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

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_2d_invoker (GimpProcedure         *procedure,
                               Gimp                  *gimp,
                               GimpContext           *context,
                               GimpProgress          *progress,
                               const GimpValueArray  *args,
                               GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  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;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  source_x = g_value_get_double (gimp_value_array_index (args, 1));
  source_y = g_value_get_double (gimp_value_array_index (args, 2));
  scale_x = g_value_get_double (gimp_value_array_index (args, 3));
  scale_y = g_value_get_double (gimp_value_array_index (args, 4));
  angle = g_value_get_double (gimp_value_array_index (args, 5));
  dest_x = g_value_get_double (gimp_value_array_index (args, 6));
  dest_y = g_value_get_double (gimp_value_array_index (args, 7));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 8));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 9));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 12));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION,
                                                        error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          gimp_matrix3_identity  (&matrix);
          gimp_matrix3_translate (&matrix, -source_x, -source_y);
          gimp_matrix3_scale     (&matrix, scale_x, scale_y);
          gimp_matrix3_rotate    (&matrix, angle);
          gimp_matrix3_translate (&matrix, dest_x, dest_y);

          if (progress)
            gimp_progress_start (progress, FALSE, _("2D Transform"));

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_2d_default_invoker (GimpProcedure         *procedure,
                                       Gimp                  *gimp,
                                       GimpContext           *context,
                                       GimpProgress          *progress,
                                       const GimpValueArray  *args,
                                       GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble source_x;
  gdouble source_y;
  gdouble scale_x;
  gdouble scale_y;
  gdouble angle;
  gdouble dest_x;
  gdouble dest_y;
  gboolean interpolate;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  source_x = g_value_get_double (gimp_value_array_index (args, 1));
  source_y = g_value_get_double (gimp_value_array_index (args, 2));
  scale_x = g_value_get_double (gimp_value_array_index (args, 3));
  scale_y = g_value_get_double (gimp_value_array_index (args, 4));
  angle = g_value_get_double (gimp_value_array_index (args, 5));
  dest_x = g_value_get_double (gimp_value_array_index (args, 6));
  dest_y = g_value_get_double (gimp_value_array_index (args, 7));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 8));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 9));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          gimp_matrix3_identity  (&matrix);
          gimp_matrix3_translate (&matrix, -source_x, -source_y);
          gimp_matrix3_scale     (&matrix, scale_x, scale_y);
          gimp_matrix3_rotate    (&matrix, angle);
          gimp_matrix3_translate (&matrix, dest_x, dest_y);

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
            gimp_progress_start (progress, FALSE, _("2D Transforming"));

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_matrix_invoker (GimpProcedure         *procedure,
                                   Gimp                  *gimp,
                                   GimpContext           *context,
                                   GimpProgress          *progress,
                                   const GimpValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble coeff_0_0;
  gdouble coeff_0_1;
  gdouble coeff_0_2;
  gdouble coeff_1_0;
  gdouble coeff_1_1;
  gdouble coeff_1_2;
  gdouble coeff_2_0;
  gdouble coeff_2_1;
  gdouble coeff_2_2;
  gint32 transform_direction;
  gint32 interpolation;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  coeff_0_0 = g_value_get_double (gimp_value_array_index (args, 1));
  coeff_0_1 = g_value_get_double (gimp_value_array_index (args, 2));
  coeff_0_2 = g_value_get_double (gimp_value_array_index (args, 3));
  coeff_1_0 = g_value_get_double (gimp_value_array_index (args, 4));
  coeff_1_1 = g_value_get_double (gimp_value_array_index (args, 5));
  coeff_1_2 = g_value_get_double (gimp_value_array_index (args, 6));
  coeff_2_0 = g_value_get_double (gimp_value_array_index (args, 7));
  coeff_2_1 = g_value_get_double (gimp_value_array_index (args, 8));
  coeff_2_2 = g_value_get_double (gimp_value_array_index (args, 9));
  transform_direction = g_value_get_enum (gimp_value_array_index (args, 10));
  interpolation = g_value_get_enum (gimp_value_array_index (args, 11));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 14));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION,
                                                        error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage   *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel *mask  = gimp_image_get_mask (image);
          GimpMatrix3  matrix;
          gint         off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          matrix.coeff[0][0] = coeff_0_0;
          matrix.coeff[0][1] = coeff_0_1;
          matrix.coeff[0][2] = coeff_0_2;
          matrix.coeff[1][0] = coeff_1_0;
          matrix.coeff[1][1] = coeff_1_1;
          matrix.coeff[1][2] = coeff_1_2;
          matrix.coeff[2][0] = coeff_2_0;
          matrix.coeff[2][1] = coeff_2_1;
          matrix.coeff[2][2] = coeff_2_2;

          if (progress)
            gimp_progress_start (progress, FALSE, _("2D Transforming"));

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, transform_direction,
                                                    interpolation,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   transform_direction,
                                   interpolation,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static GimpValueArray *
drawable_transform_matrix_default_invoker (GimpProcedure         *procedure,
                                           Gimp                  *gimp,
                                           GimpContext           *context,
                                           GimpProgress          *progress,
                                           const GimpValueArray  *args,
                                           GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gdouble coeff_0_0;
  gdouble coeff_0_1;
  gdouble coeff_0_2;
  gdouble coeff_1_0;
  gdouble coeff_1_1;
  gdouble coeff_1_2;
  gdouble coeff_2_0;
  gdouble coeff_2_1;
  gdouble coeff_2_2;
  gboolean interpolate;
  gint32 clip_result;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  coeff_0_0 = g_value_get_double (gimp_value_array_index (args, 1));
  coeff_0_1 = g_value_get_double (gimp_value_array_index (args, 2));
  coeff_0_2 = g_value_get_double (gimp_value_array_index (args, 3));
  coeff_1_0 = g_value_get_double (gimp_value_array_index (args, 4));
  coeff_1_1 = g_value_get_double (gimp_value_array_index (args, 5));
  coeff_1_2 = g_value_get_double (gimp_value_array_index (args, 6));
  coeff_2_0 = g_value_get_double (gimp_value_array_index (args, 7));
  coeff_2_1 = g_value_get_double (gimp_value_array_index (args, 8));
  coeff_2_2 = g_value_get_double (gimp_value_array_index (args, 9));
  interpolate = g_value_get_boolean (gimp_value_array_index (args, 10));
  clip_result = g_value_get_enum (gimp_value_array_index (args, 11));

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

      success = gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                                        GIMP_PDB_ITEM_CONTENT |
                                                        GIMP_PDB_ITEM_POSITION, error);

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpImage             *image = gimp_item_get_image (GIMP_ITEM (drawable));
          GimpChannel           *mask  = gimp_image_get_mask (image);
          GimpMatrix3            matrix;
          GimpInterpolationType  interpolation_type = GIMP_INTERPOLATION_NONE;
          gint                   off_x, off_y;

          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

          x += off_x;
          y += off_y;

          /* Assemble the transformation matrix */
          matrix.coeff[0][0] = coeff_0_0;
          matrix.coeff[0][1] = coeff_0_1;
          matrix.coeff[0][2] = coeff_0_2;
          matrix.coeff[1][0] = coeff_1_0;
          matrix.coeff[1][1] = coeff_1_1;
          matrix.coeff[1][2] = coeff_1_2;
          matrix.coeff[2][0] = coeff_2_0;
          matrix.coeff[2][1] = coeff_2_1;
          matrix.coeff[2][2] = coeff_2_2;

          if (interpolate)
            interpolation_type = gimp->config->interpolation_type;

          if (progress)
            gimp_progress_start (progress, FALSE, _("2D Transforming"));

          if (drawable != GIMP_DRAWABLE (mask)                        &&
              ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (mask))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type,
                                                    clip_result, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              clip_result = gimp_item_get_clip (GIMP_ITEM (drawable), clip_result);

              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation_type,
                                   clip_result, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_drawable (gimp_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

void
register_drawable_transform_procs (GimpPDB *pdb)
{
  GimpProcedure *procedure;

  /*
   * gimp-drawable-transform-flip-simple
   */
  procedure = gimp_procedure_new (drawable_transform_flip_simple_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-flip-simple");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-flip-simple",
                                     "Deprecated: Use 'gimp-item-transform-flip-simple' instead.",
                                     "Deprecated: Use 'gimp-item-transform-flip-simple' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-flip-simple");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_enum ("flip-type",
                                                     "flip type",
                                                     "Type of flip",
                                                     GIMP_TYPE_ORIENTATION_TYPE,
                                                     GIMP_ORIENTATION_HORIZONTAL,
                                                     GIMP_PARAM_READWRITE));
  gimp_param_spec_enum_exclude_value (GIMP_PARAM_SPEC_ENUM (procedure->args[1]),
                                      GIMP_ORIENTATION_UNKNOWN);
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("auto-center",
                                                     "auto center",
                                                     "Whether to automatically position the axis in the selection center",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("axis",
                                                    "axis",
                                                    "coord. of flip axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("clip-result",
                                                     "clip result",
                                                     "Whether to clip results",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The flipped drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-flip
   */
  procedure = gimp_procedure_new (drawable_transform_flip_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-flip");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-flip",
                                     "Deprecated: Use 'gimp-item-transform-flip' instead.",
                                     "Deprecated: Use 'gimp-item-transform-flip' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-flip");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x0",
                                                    "x0",
                                                    "horz. coord. of one end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y0",
                                                    "y0",
                                                    "vert. coord. of one end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x1",
                                                    "x1",
                                                    "horz. coord. of other end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y1",
                                                    "y1",
                                                    "vert. coord. of other end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("clip-result",
                                                     "clip result",
                                                     "Whether to clip results",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The flipped drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-flip-default
   */
  procedure = gimp_procedure_new (drawable_transform_flip_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-flip-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-flip-default",
                                     "Deprecated: Use 'gimp-item-transform-flip' instead.",
                                     "Deprecated: Use 'gimp-item-transform-flip' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-flip");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x0",
                                                    "x0",
                                                    "horz. coord. of one end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y0",
                                                    "y0",
                                                    "vert. coord. of one end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x1",
                                                    "x1",
                                                    "horz. coord. of other end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y1",
                                                    "y1",
                                                    "vert. coord. of other end of axis",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("clip-result",
                                                     "clip result",
                                                     "Whether to clip results",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The flipped drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-perspective
   */
  procedure = gimp_procedure_new (drawable_transform_perspective_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-perspective");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-perspective",
                                     "Deprecated: Use 'gimp-item-transform-perspective' instead.",
                                     "Deprecated: Use 'gimp-item-transform-perspective' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-perspective");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x0",
                                                    "x0",
                                                    "The new x coordinate of upper-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y0",
                                                    "y0",
                                                    "The new y coordinate of upper-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x1",
                                                    "x1",
                                                    "The new x coordinate of upper-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y1",
                                                    "y1",
                                                    "The new y coordinate of upper-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x2",
                                                    "x2",
                                                    "The new x coordinate of lower-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y2",
                                                    "y2",
                                                    "The new y coordinate of lower-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x3",
                                                    "x3",
                                                    "The new x coordinate of lower-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y3",
                                                    "y3",
                                                    "The new y coordinate of lower-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The newly mapped drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-perspective-default
   */
  procedure = gimp_procedure_new (drawable_transform_perspective_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-perspective-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-perspective-default",
                                     "Deprecated: Use 'gimp-item-transform-perspective' instead.",
                                     "Deprecated: Use 'gimp-item-transform-perspective' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-perspective");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x0",
                                                    "x0",
                                                    "The new x coordinate of upper-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y0",
                                                    "y0",
                                                    "The new y coordinate of upper-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x1",
                                                    "x1",
                                                    "The new x coordinate of upper-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y1",
                                                    "y1",
                                                    "The new y coordinate of upper-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x2",
                                                    "x2",
                                                    "The new x coordinate of lower-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y2",
                                                    "y2",
                                                    "The new y coordinate of lower-left corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x3",
                                                    "x3",
                                                    "The new x coordinate of lower-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y3",
                                                    "y3",
                                                    "The new y coordinate of lower-right corner of original bounding box",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The newly mapped drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-rotate-simple
   */
  procedure = gimp_procedure_new (drawable_transform_rotate_simple_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-rotate-simple");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-rotate-simple",
                                     "Deprecated: Use 'gimp-item-transform-rotate-simple' instead.",
                                     "Deprecated: Use 'gimp-item-transform-rotate-simple' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-rotate-simple");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("rotate-type",
                                                  "rotate type",
                                                  "Type of rotation",
                                                  GIMP_TYPE_ROTATION_TYPE,
                                                  GIMP_ROTATE_90,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("auto-center",
                                                     "auto center",
                                                     "Whether to automatically rotate around the selection center",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("center-x",
                                                      "center x",
                                                      "The hor. coordinate of the center of rotation",
                                                      G_MININT32, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("center-y",
                                                      "center y",
                                                      "The vert. coordinate of the center of rotation",
                                                      G_MININT32, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("clip-result",
                                                     "clip result",
                                                     "Whether to clip results",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The rotated drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-rotate
   */
  procedure = gimp_procedure_new (drawable_transform_rotate_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-rotate");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-rotate",
                                     "Deprecated: Use 'gimp-item-transform-rotate' instead.",
                                     "Deprecated: Use 'gimp-item-transform-rotate' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-rotate");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("angle",
                                                    "angle",
                                                    "The angle of rotation (radians)",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("auto-center",
                                                     "auto center",
                                                     "Whether to automatically rotate around the selection center",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("center-x",
                                                      "center x",
                                                      "The hor. coordinate of the center of rotation",
                                                      G_MININT32, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("center-y",
                                                      "center y",
                                                      "The vert. coordinate of the center of rotation",
                                                      G_MININT32, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The rotated drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-rotate-default
   */
  procedure = gimp_procedure_new (drawable_transform_rotate_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-rotate-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-rotate-default",
                                     "Deprecated: Use 'gimp-item-transform-rotate' instead.",
                                     "Deprecated: Use 'gimp-item-transform-rotate' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-rotate");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("angle",
                                                    "angle",
                                                    "The angle of rotation (radians)",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("auto-center",
                                                     "auto center",
                                                     "Whether to automatically rotate around the selection center",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("center-x",
                                                      "center x",
                                                      "The hor. coordinate of the center of rotation",
                                                      G_MININT32, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("center-y",
                                                      "center y",
                                                      "The vert. coordinate of the center of rotation",
                                                      G_MININT32, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The rotated drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-scale
   */
  procedure = gimp_procedure_new (drawable_transform_scale_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-scale");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-scale",
                                     "Deprecated: Use 'gimp-item-transform-scale' instead.",
                                     "Deprecated: Use 'gimp-item-transform-scale' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-scale");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x0",
                                                    "x0",
                                                    "The new x coordinate of the upper-left corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y0",
                                                    "y0",
                                                    "The new y coordinate of the upper-left corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x1",
                                                    "x1",
                                                    "The new x coordinate of the lower-right corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y1",
                                                    "y1",
                                                    "The new y coordinate of the lower-right corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The scaled drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-scale-default
   */
  procedure = gimp_procedure_new (drawable_transform_scale_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-scale-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-scale-default",
                                     "Deprecated: Use 'gimp-item-transform-scale' instead.",
                                     "Deprecated: Use 'gimp-item-transform-scale' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-scale");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x0",
                                                    "x0",
                                                    "The new x coordinate of the upper-left corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y0",
                                                    "y0",
                                                    "The new y coordinate of the upper-left corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("x1",
                                                    "x1",
                                                    "The new x coordinate of the lower-right corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("y1",
                                                    "y1",
                                                    "The new y coordinate of the lower-right corner of the scaled region",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The scaled drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-shear
   */
  procedure = gimp_procedure_new (drawable_transform_shear_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-shear");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-shear",
                                     "Deprecated: Use 'gimp-item-transform-shear' instead.",
                                     "Deprecated: Use 'gimp-item-transform-shear' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-shear");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_enum ("shear-type",
                                                     "shear type",
                                                     "Type of shear",
                                                     GIMP_TYPE_ORIENTATION_TYPE,
                                                     GIMP_ORIENTATION_HORIZONTAL,
                                                     GIMP_PARAM_READWRITE));
  gimp_param_spec_enum_exclude_value (GIMP_PARAM_SPEC_ENUM (procedure->args[1]),
                                      GIMP_ORIENTATION_UNKNOWN);
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("magnitude",
                                                    "magnitude",
                                                    "The magnitude of the shear",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The sheared drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-shear-default
   */
  procedure = gimp_procedure_new (drawable_transform_shear_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-shear-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-shear-default",
                                     "Deprecated: Use 'gimp-item-transform-shear' instead.",
                                     "Deprecated: Use 'gimp-item-transform-shear' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-shear");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_enum ("shear-type",
                                                     "shear type",
                                                     "Type of shear",
                                                     GIMP_TYPE_ORIENTATION_TYPE,
                                                     GIMP_ORIENTATION_HORIZONTAL,
                                                     GIMP_PARAM_READWRITE));
  gimp_param_spec_enum_exclude_value (GIMP_PARAM_SPEC_ENUM (procedure->args[1]),
                                      GIMP_ORIENTATION_UNKNOWN);
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("magnitude",
                                                    "magnitude",
                                                    "The magnitude of the shear",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The sheared drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-2d
   */
  procedure = gimp_procedure_new (drawable_transform_2d_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-2d");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-2d",
                                     "Deprecated: Use 'gimp-item-transform-2d' instead.",
                                     "Deprecated: Use 'gimp-item-transform-2d' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-2d");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("source-x",
                                                    "source x",
                                                    "X coordinate of the transformation center",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("source-y",
                                                    "source y",
                                                    "Y coordinate of the transformation center",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("scale-x",
                                                    "scale x",
                                                    "Amount to scale in x direction",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("scale-y",
                                                    "scale y",
                                                    "Amount to scale in y direction",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("angle",
                                                    "angle",
                                                    "The angle of rotation (radians)",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("dest-x",
                                                    "dest x",
                                                    "X coordinate of where the center goes",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("dest-y",
                                                    "dest y",
                                                    "Y coordinate of where the center goes",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The transformed drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-2d-default
   */
  procedure = gimp_procedure_new (drawable_transform_2d_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-2d-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-2d-default",
                                     "Deprecated: Use 'gimp-item-transform-2d' instead.",
                                     "Deprecated: Use 'gimp-item-transform-2d' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-2d");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("source-x",
                                                    "source x",
                                                    "X coordinate of the transformation center",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("source-y",
                                                    "source y",
                                                    "Y coordinate of the transformation center",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("scale-x",
                                                    "scale x",
                                                    "Amount to scale in x direction",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("scale-y",
                                                    "scale y",
                                                    "Amount to scale in y direction",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("angle",
                                                    "angle",
                                                    "The angle of rotation (radians)",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("dest-x",
                                                    "dest x",
                                                    "X coordinate of where the center goes",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("dest-y",
                                                    "dest y",
                                                    "Y coordinate of where the center goes",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The transformed drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-matrix
   */
  procedure = gimp_procedure_new (drawable_transform_matrix_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-matrix");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-matrix",
                                     "Deprecated: Use 'gimp-item-transform-matrix' instead.",
                                     "Deprecated: Use 'gimp-item-transform-matrix' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-matrix");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-0-0",
                                                    "coeff 0 0",
                                                    "coefficient (0,0) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-0-1",
                                                    "coeff 0 1",
                                                    "coefficient (0,1) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-0-2",
                                                    "coeff 0 2",
                                                    "coefficient (0,2) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-1-0",
                                                    "coeff 1 0",
                                                    "coefficient (1,0) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-1-1",
                                                    "coeff 1 1",
                                                    "coefficient (1,1) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-1-2",
                                                    "coeff 1 2",
                                                    "coefficient (1,2) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-2-0",
                                                    "coeff 2 0",
                                                    "coefficient (2,0) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-2-1",
                                                    "coeff 2 1",
                                                    "coefficient (2,1) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-2-2",
                                                    "coeff 2 2",
                                                    "coefficient (2,2) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transform-direction",
                                                  "transform direction",
                                                  "Direction of transformation",
                                                  GIMP_TYPE_TRANSFORM_DIRECTION,
                                                  GIMP_TRANSFORM_FORWARD,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("interpolation",
                                                  "interpolation",
                                                  "Type of interpolation",
                                                  GIMP_TYPE_INTERPOLATION_TYPE,
                                                  GIMP_INTERPOLATION_NONE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("supersample",
                                                     "supersample",
                                                     "This parameter is ignored",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("recursion-level",
                                                      "recursion level",
                                                      "This parameter is ignored",
                                                      1, G_MAXINT32, 1,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The transformed drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * gimp-drawable-transform-matrix-default
   */
  procedure = gimp_procedure_new (drawable_transform_matrix_default_invoker);
  gimp_object_set_static_name (GIMP_OBJECT (procedure),
                               "gimp-drawable-transform-matrix-default");
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-drawable-transform-matrix-default",
                                     "Deprecated: Use 'gimp-item-transform-matrix' instead.",
                                     "Deprecated: Use 'gimp-item-transform-matrix' instead.",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "Jo\xc3\xa3o S. O. Bueno",
                                     "2004",
                                     "gimp-item-transform-matrix");
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The affected drawable",
                                                            pdb->gimp, FALSE,
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-0-0",
                                                    "coeff 0 0",
                                                    "coefficient (0,0) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-0-1",
                                                    "coeff 0 1",
                                                    "coefficient (0,1) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-0-2",
                                                    "coeff 0 2",
                                                    "coefficient (0,2) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-1-0",
                                                    "coeff 1 0",
                                                    "coefficient (1,0) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-1-1",
                                                    "coeff 1 1",
                                                    "coefficient (1,1) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-1-2",
                                                    "coeff 1 2",
                                                    "coefficient (1,2) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-2-0",
                                                    "coeff 2 0",
                                                    "coefficient (2,0) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-2-1",
                                                    "coeff 2 1",
                                                    "coefficient (2,1) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("coeff-2-2",
                                                    "coeff 2 2",
                                                    "coefficient (2,2) of the transformation matrix",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interpolate",
                                                     "interpolate",
                                                     "Whether to use interpolation and supersampling",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("clip-result",
                                                  "clip result",
                                                  "How to clip results",
                                                  GIMP_TYPE_TRANSFORM_RESIZE,
                                                  GIMP_TRANSFORM_RESIZE_ADJUST,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_return_value (procedure,
                                   gimp_param_spec_drawable_id ("drawable",
                                                                "drawable",
                                                                "The transformed drawable",
                                                                pdb->gimp, FALSE,
                                                                GIMP_PARAM_READWRITE));
  gimp_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);
}
