[gimp] pdb: add transform API for items



commit e8f4d4b449635f3842090b8f946b1a030fc51ff1
Author: Michael Natterer <mitch gimp org>
Date:   Wed Sep 8 02:48:37 2010 +0200

    pdb: add transform API for items
    
    Works for all item types, and has much less functions and parameters
    than the drawable transform API because it uses the new context
    states. Untested and not finished!

 app/pdb/Makefile.am                 |    1 +
 app/pdb/internal-procs.c            |    3 +-
 app/pdb/internal-procs.h            |    1 +
 app/pdb/item-transform-cmds.c       | 1320 +++++++++++++++++++++++++++++++++++
 libgimp/Makefile.am                 |    2 +
 libgimp/gimp_pdb.h                  |    1 +
 libgimp/gimpitemtransform_pdb.c     |  541 ++++++++++++++
 libgimp/gimpitemtransform_pdb.h     |   89 +++
 tools/pdbgen/Makefile.am            |    1 +
 tools/pdbgen/groups.pl              |    1 +
 tools/pdbgen/pdb/item_transform.pdb |  626 +++++++++++++++++
 11 files changed, 2585 insertions(+), 1 deletions(-)
---
diff --git a/app/pdb/Makefile.am b/app/pdb/Makefile.am
index f59e5b3..5e2a42b 100644
--- a/app/pdb/Makefile.am
+++ b/app/pdb/Makefile.am
@@ -60,6 +60,7 @@ libappinternal_procs_a_SOURCES = \
 	help-cmds.c			\
 	image-cmds.c			\
 	item-cmds.c			\
+	item-transform-cmds.c		\
 	layer-cmds.c			\
 	message-cmds.c			\
 	misc-cmds.c			\
diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c
index 88bdb4e..3427196 100644
--- a/app/pdb/internal-procs.c
+++ b/app/pdb/internal-procs.c
@@ -28,7 +28,7 @@
 #include "internal-procs.h"
 
 
-/* 648 procedures registered total */
+/* 657 procedures registered total */
 
 void
 internal_procs_init (GimpPDB *pdb)
@@ -60,6 +60,7 @@ internal_procs_init (GimpPDB *pdb)
   register_help_procs (pdb);
   register_image_procs (pdb);
   register_item_procs (pdb);
+  register_item_transform_procs (pdb);
   register_layer_procs (pdb);
   register_message_procs (pdb);
   register_misc_procs (pdb);
diff --git a/app/pdb/internal-procs.h b/app/pdb/internal-procs.h
index 3f79f5a..b256f9d 100644
--- a/app/pdb/internal-procs.h
+++ b/app/pdb/internal-procs.h
@@ -49,6 +49,7 @@ void   register_guides_procs             (GimpPDB *pdb);
 void   register_help_procs               (GimpPDB *pdb);
 void   register_image_procs              (GimpPDB *pdb);
 void   register_item_procs               (GimpPDB *pdb);
+void   register_item_transform_procs     (GimpPDB *pdb);
 void   register_layer_procs              (GimpPDB *pdb);
 void   register_message_procs            (GimpPDB *pdb);
 void   register_misc_procs               (GimpPDB *pdb);
diff --git a/app/pdb/item-transform-cmds.c b/app/pdb/item-transform-cmds.c
new file mode 100644
index 0000000..f4bb834
--- /dev/null
+++ b/app/pdb/item-transform-cmds.c
@@ -0,0 +1,1320 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* NOTE: This file is auto-generated by pdbgen.pl. */
+
+#include "config.h"
+
+#include <gegl.h>
+
+#include "libgimpmath/gimpmath.h"
+
+#include "pdb-types.h"
+
+#include "core/gimp-transform-utils.h"
+#include "core/gimpdrawable-transform.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpitem.h"
+#include "core/gimpparamspecs.h"
+#include "core/gimpprogress.h"
+
+#include "gimppdb.h"
+#include "gimppdb-utils.h"
+#include "gimppdbcontext.h"
+#include "gimpprocedure.h"
+#include "internal-procs.h"
+
+#include "gimp-intl.h"
+
+
+static GValueArray *
+item_transform_flip_simple_invoker (GimpProcedure      *procedure,
+                                    Gimp               *gimp,
+                                    GimpContext        *context,
+                                    GimpProgress       *progress,
+                                    const GValueArray  *args,
+                                    GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gint32 flip_type;
+  gboolean auto_center;
+  gdouble axis;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  flip_type = g_value_get_enum (&args->values[1]);
+  auto_center = g_value_get_boolean (&args->values[2]);
+  axis = g_value_get_double (&args->values[3]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &off_x, &off_y);
+          x += off_x;
+          y += off_y;
+
+          gimp_transform_get_flip_axis (x, y, width, height,
+                                        flip_type, auto_center, &axis);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_flip (GIMP_DRAWABLE (item), context,
+                                                      flip_type, axis,
+                                                      pdb_context->transform_resize);
+            }
+          else
+            {
+              gimp_item_flip (item, context,
+                              flip_type, axis,
+                              pdb_context->transform_resize);
+            }
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_flip_invoker (GimpProcedure      *procedure,
+                             Gimp               *gimp,
+                             GimpContext        *context,
+                             GimpProgress       *progress,
+                             const GValueArray  *args,
+                             GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gdouble x0;
+  gdouble y0;
+  gdouble x1;
+  gdouble y1;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  x0 = g_value_get_double (&args->values[1]);
+  y0 = g_value_get_double (&args->values[2]);
+  x1 = g_value_get_double (&args->values[3]);
+  y1 = g_value_get_double (&args->values[4]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("Flipping"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_perspective_invoker (GimpProcedure      *procedure,
+                                    Gimp               *gimp,
+                                    GimpContext        *context,
+                                    GimpProgress       *progress,
+                                    const GValueArray  *args,
+                                    GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gdouble x0;
+  gdouble y0;
+  gdouble x1;
+  gdouble y1;
+  gdouble x2;
+  gdouble y2;
+  gdouble x3;
+  gdouble y3;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  x0 = g_value_get_double (&args->values[1]);
+  y0 = g_value_get_double (&args->values[2]);
+  x1 = g_value_get_double (&args->values[3]);
+  y1 = g_value_get_double (&args->values[4]);
+  x2 = g_value_get_double (&args->values[5]);
+  y2 = g_value_get_double (&args->values[6]);
+  x3 = g_value_get_double (&args->values[7]);
+  y3 = g_value_get_double (&args->values[8]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("Perspective"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_rotate_simple_invoker (GimpProcedure      *procedure,
+                                      Gimp               *gimp,
+                                      GimpContext        *context,
+                                      GimpProgress       *progress,
+                                      const GValueArray  *args,
+                                      GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gint32 rotate_type;
+  gboolean auto_center;
+  gdouble center_x;
+  gdouble center_y;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  rotate_type = g_value_get_enum (&args->values[1]);
+  auto_center = g_value_get_boolean (&args->values[2]);
+  center_x = g_value_get_double (&args->values[3]);
+  center_y = g_value_get_double (&args->values[4]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, FALSE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &off_x, &off_y);
+          x += off_x;
+          y += off_y;
+
+          gimp_transform_get_rotate_center (x, y, width, height,
+                                            auto_center, &center_x, &center_y);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_rotate (GIMP_DRAWABLE (item),
+                                                        context,
+                                                        rotate_type,
+                                                        center_x, center_y,
+                                                        pdb_context->transform_resize);
+            }
+          else
+            {
+              gimp_item_rotate (item, context,
+                                rotate_type,
+                                center_x, center_y,
+                                pdb_context->transform_resize);
+            }
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_rotate_invoker (GimpProcedure      *procedure,
+                               Gimp               *gimp,
+                               GimpContext        *context,
+                               GimpProgress       *progress,
+                               const GValueArray  *args,
+                               GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gdouble angle;
+  gboolean auto_center;
+  gdouble center_x;
+  gdouble center_y;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  angle = g_value_get_double (&args->values[1]);
+  auto_center = g_value_get_boolean (&args->values[2]);
+  center_x = g_value_get_double (&args->values[3]);
+  center_y = g_value_get_double (&args->values[4]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("Rotating"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_scale_invoker (GimpProcedure      *procedure,
+                              Gimp               *gimp,
+                              GimpContext        *context,
+                              GimpProgress       *progress,
+                              const GValueArray  *args,
+                              GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gdouble x0;
+  gdouble y0;
+  gdouble x1;
+  gdouble y1;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  x0 = g_value_get_double (&args->values[1]);
+  y0 = g_value_get_double (&args->values[2]);
+  x1 = g_value_get_double (&args->values[3]);
+  y1 = g_value_get_double (&args->values[4]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = (gimp_pdb_item_is_attached (item, NULL, TRUE, error) && x0 < x1 && y0 < y1);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("Scaling"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_shear_invoker (GimpProcedure      *procedure,
+                              Gimp               *gimp,
+                              GimpContext        *context,
+                              GimpProgress       *progress,
+                              const GValueArray  *args,
+                              GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gint32 shear_type;
+  gdouble magnitude;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  shear_type = g_value_get_enum (&args->values[1]);
+  magnitude = g_value_get_double (&args->values[2]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("Shearing"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_2d_invoker (GimpProcedure      *procedure,
+                           Gimp               *gimp,
+                           GimpContext        *context,
+                           GimpProgress       *progress,
+                           const GValueArray  *args,
+                           GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  gdouble source_x;
+  gdouble source_y;
+  gdouble scale_x;
+  gdouble scale_y;
+  gdouble angle;
+  gdouble dest_x;
+  gdouble dest_y;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  source_x = g_value_get_double (&args->values[1]);
+  source_y = g_value_get_double (&args->values[2]);
+  scale_x = g_value_get_double (&args->values[3]);
+  scale_y = g_value_get_double (&args->values[4]);
+  angle = g_value_get_double (&args->values[5]);
+  dest_x = g_value_get_double (&args->values[6]);
+  dest_y = g_value_get_double (&args->values[7]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("2D Transform"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+static GValueArray *
+item_transform_matrix_invoker (GimpProcedure      *procedure,
+                               Gimp               *gimp,
+                               GimpContext        *context,
+                               GimpProgress       *progress,
+                               const GValueArray  *args,
+                               GError            **error)
+{
+  gboolean success = TRUE;
+  GValueArray *return_vals;
+  GimpItem *item;
+  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;
+
+  item = gimp_value_get_item (&args->values[0], gimp);
+  coeff_0_0 = g_value_get_double (&args->values[1]);
+  coeff_0_1 = g_value_get_double (&args->values[2]);
+  coeff_0_2 = g_value_get_double (&args->values[3]);
+  coeff_1_0 = g_value_get_double (&args->values[4]);
+  coeff_1_1 = g_value_get_double (&args->values[5]);
+  coeff_1_2 = g_value_get_double (&args->values[6]);
+  coeff_2_0 = g_value_get_double (&args->values[7]);
+  coeff_2_1 = g_value_get_double (&args->values[8]);
+  coeff_2_2 = g_value_get_double (&args->values[9]);
+
+  if (success)
+    {
+      gint x, y, width, height;
+
+      success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+      if (success &&
+          gimp_item_mask_intersect (item, &x, &y, &width, &height))
+        {
+          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+          GimpMatrix3     matrix;
+          gint            off_x, off_y;
+
+          gimp_item_get_offset (item, &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, _("2D Transforming"), FALSE);
+
+          if (GIMP_IS_DRAWABLE (item))
+            {
+              success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                        context, &matrix,
+                                                        pdb_context->transform_direction,
+                                                        pdb_context->interpolation,
+                                                        pdb_context->transform_recursion,
+                                                        pdb_context->transform_resize,
+                                                        progress);
+            }
+          else
+            {
+              gimp_item_transform (item, context, &matrix,
+                                   pdb_context->transform_direction,
+                                   pdb_context->interpolation,
+                                   pdb_context->transform_recursion,
+                                   pdb_context->transform_resize,
+                                   progress);
+            }
+
+          if (progress)
+            gimp_progress_end (progress);
+        }
+    }
+
+  return_vals = gimp_procedure_get_return_values (procedure, success,
+                                                  error ? *error : NULL);
+
+  if (success)
+    gimp_value_set_item (&return_vals->values[1], item);
+
+  return return_vals;
+}
+
+void
+register_item_transform_procs (GimpPDB *pdb)
+{
+  GimpProcedure *procedure;
+
+  /*
+   * gimp-item-transform-flip-simple
+   */
+  procedure = gimp_procedure_new (item_transform_flip_simple_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-flip-simple");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-flip-simple",
+                                     "Flip the specified item either vertically or horizontally.",
+                                     "This procedure flips the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then flipped. If auto_center is set to TRUE, the flip is around the selection's center. Otherwise, the coordinate of the axis needs to be specified. The return value is the ID of the flipped item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and flipped drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2004",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The flipped item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-flip
+   */
+  procedure = gimp_procedure_new (item_transform_flip_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-flip");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-flip",
+                                     "Flip the specified item around a given line.",
+                                     "This procedure flips the specified item. If a selection exists and the item is a drawable , the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then flipped. The axis to flip around is specified by specifying two points from that line. The return value is the ID of the flipped item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and flipped drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The flipped item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-perspective
+   */
+  procedure = gimp_procedure_new (item_transform_perspective_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-perspective");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-perspective",
+                                     "Perform a possibly non-affine transformation on the specified item.",
+                                     "This procedure performs a possibly non-affine transformation on the specified item by allowing the corners of the original bounding box to be arbitrarily remapped to any values. The specified item is remapped if no selection exists or it is not a drawable. However, if a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then remapped as specified. The return value is the ID of the remapped item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and remapped drawable. The 4 coordinates specify the new locations of each corner of the original bounding box. By specifying these values, any affine transformation (rotation, scaling, translation) can be affected. Additionally, these values can be specified such that the resu
 lting transformed item will appear to have"
+  "been projected via a perspective transform.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The newly mapped item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-rotate-simple
+   */
+  procedure = gimp_procedure_new (item_transform_rotate_simple_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-rotate-simple");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-rotate-simple",
+                                     "Rotate the specified item about given coordinates through the specified angle.",
+                                     "This function rotates the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then rotated by the specified amount. The return value is the ID of the rotated item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and rotated drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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,
+                               g_param_spec_double ("center-x",
+                                                    "center x",
+                                                    "The hor. coordinate of the center of rotation",
+                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
+                                                    GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               g_param_spec_double ("center-y",
+                                                    "center y",
+                                                    "The vert. coordinate of the center of rotation",
+                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
+                                                    GIMP_PARAM_READWRITE));
+  gimp_procedure_add_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The rotated item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-rotate
+   */
+  procedure = gimp_procedure_new (item_transform_rotate_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-rotate");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-rotate",
+                                     "Rotate the specified item about given coordinates through the specified angle.",
+                                     "This function rotates the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then rotated by the specified amount. The return value is the ID of the rotated item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and rotated drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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,
+                               g_param_spec_double ("center-x",
+                                                    "center x",
+                                                    "The hor. coordinate of the center of rotation",
+                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
+                                                    GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               g_param_spec_double ("center-y",
+                                                    "center y",
+                                                    "The vert. coordinate of the center of rotation",
+                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
+                                                    GIMP_PARAM_READWRITE));
+  gimp_procedure_add_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The rotated item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-scale
+   */
+  procedure = gimp_procedure_new (item_transform_scale_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-scale");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-scale",
+                                     "Scale the specified item.",
+                                     "This procedure scales the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then scaled by the specified amount. The return value is the ID of the scaled item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and scaled drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The scaled item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-shear
+   */
+  procedure = gimp_procedure_new (item_transform_shear_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-shear");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-shear",
+                                     "Shear the specified item about its center by the specified magnitude.",
+                                     "This procedure shears the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then sheard by the specified amount. The return value is the ID of the sheard item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and sheard drawable. The shear type parameter indicates whether the shear will be applied horizontally or vertically. The magnitude can be either positive or negative and indicates the extent (in pixels) to shear by.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The sheared item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-2d
+   */
+  procedure = gimp_procedure_new (item_transform_2d_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-2d");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-2d",
+                                     "Transform the specified item in 2d.",
+                                     "This procedure transforms the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then transformed. The transformation is done by scaling the image by the x and y scale factors about the point (source_x, source_y), then rotating around the same point, then translating that point to the new position (dest_x, dest_y). The return value is the ID of the rotated drawable. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and transformed drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The transformed item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+
+  /*
+   * gimp-item-transform-matrix
+   */
+  procedure = gimp_procedure_new (item_transform_matrix_invoker);
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "gimp-item-transform-matrix");
+  gimp_procedure_set_static_strings (procedure,
+                                     "gimp-item-transform-matrix",
+                                     "Transform the specified item in 2d.",
+                                     "This procedure transforms the specified item. If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then transformed. The transformation is done by assembling a 3x3 matrix from the coefficients passed. The return value is the ID of the transformed item. If there was no selection or the item is not a drawable, this will be equal to the item ID supplied as input. Otherwise, this will be the newly created and transformed drawable.",
+                                     "Michael Natterer <mitch gimp org>",
+                                     "Michael Natterer",
+                                     "2010",
+                                     NULL);
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_item_id ("item",
+                                                        "item",
+                                                        "The affected item",
+                                                        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_return_value (procedure,
+                                   gimp_param_spec_item_id ("item",
+                                                            "item",
+                                                            "The transformed item",
+                                                            pdb->gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_pdb_register_procedure (pdb, procedure);
+  g_object_unref (procedure);
+}
diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am
index 403630e..bffefc1 100644
--- a/libgimp/Makefile.am
+++ b/libgimp/Makefile.am
@@ -93,6 +93,7 @@ PDB_WRAPPERS_C = \
 	gimphelp_pdb.c			\
 	gimpimage_pdb.c			\
 	gimpitem_pdb.c			\
+	gimpitemtransform_pdb.c		\
 	gimplayer_pdb.c			\
 	gimpmessage_pdb.c		\
 	gimpmisc_pdb.c			\
@@ -144,6 +145,7 @@ PDB_WRAPPERS_H = \
 	gimphelp_pdb.h			\
 	gimpimage_pdb.h			\
 	gimpitem_pdb.h			\
+	gimpitemtransform_pdb.h		\
 	gimplayer_pdb.h			\
 	gimpmessage_pdb.h		\
 	gimpmisc_pdb.h			\
diff --git a/libgimp/gimp_pdb.h b/libgimp/gimp_pdb.h
index 4a40f63..d7b7d18 100644
--- a/libgimp/gimp_pdb.h
+++ b/libgimp/gimp_pdb.h
@@ -48,6 +48,7 @@
 #include <libgimp/gimphelp_pdb.h>
 #include <libgimp/gimpimage_pdb.h>
 #include <libgimp/gimpitem_pdb.h>
+#include <libgimp/gimpitemtransform_pdb.h>
 #include <libgimp/gimplayer_pdb.h>
 #include <libgimp/gimpmessage_pdb.h>
 #include <libgimp/gimpmisc_pdb.h>
diff --git a/libgimp/gimpitemtransform_pdb.c b/libgimp/gimpitemtransform_pdb.c
new file mode 100644
index 0000000..d26a95f
--- /dev/null
+++ b/libgimp/gimpitemtransform_pdb.c
@@ -0,0 +1,541 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpitemtransform_pdb.c
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/* NOTE: This file is auto-generated by pdbgen.pl */
+
+#include "config.h"
+
+#include "gimp.h"
+
+
+/**
+ * SECTION: gimpitemtransform
+ * @title: gimpitemtransform
+ * @short_description: Functions to perform transformations on items.
+ *
+ * Functions to perform transformations on items.
+ **/
+
+
+/**
+ * gimp_item_transform_flip_simple:
+ * @item_ID: The affected item.
+ * @flip_type: Type of flip.
+ * @auto_center: Whether to automatically position the axis in the selection center.
+ * @axis: coord. of flip axis.
+ *
+ * Flip the specified item either vertically or horizontally.
+ *
+ * This procedure flips the specified item. If a selection exists and
+ * the item is a drawable, the portion of the drawable which lies under
+ * the selection is cut from the drawable and made into a floating
+ * selection which is then flipped. If auto_center is set to TRUE, the
+ * flip is around the selection's center. Otherwise, the coordinate of
+ * the axis needs to be specified. The return value is the ID of the
+ * flipped item. If there was no selection or the item is not a
+ * drawable, this will be equal to the item ID supplied as input.
+ * Otherwise, this will be the newly created and flipped drawable.
+ *
+ * Returns: The flipped item.
+ *
+ * Since: GIMP 2.2
+ */
+gint32
+gimp_item_transform_flip_simple (gint32              item_ID,
+                                 GimpOrientationType flip_type,
+                                 gboolean            auto_center,
+                                 gdouble             axis)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-flip-simple",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_INT32, flip_type,
+                                    GIMP_PDB_INT32, auto_center,
+                                    GIMP_PDB_FLOAT, axis,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_flip:
+ * @item_ID: The affected item.
+ * @x0: horz. coord. of one end of axis.
+ * @y0: vert. coord. of one end of axis.
+ * @x1: horz. coord. of other end of axis.
+ * @y1: vert. coord. of other end of axis.
+ *
+ * Flip the specified item around a given line.
+ *
+ * This procedure flips the specified item. If a selection exists and
+ * the item is a drawable , the portion of the drawable which lies
+ * under the selection is cut from the drawable and made into a
+ * floating selection which is then flipped. The axis to flip around is
+ * specified by specifying two points from that line. The return value
+ * is the ID of the flipped item. If there was no selection or the item
+ * is not a drawable, this will be equal to the item ID supplied as
+ * input. Otherwise, this will be the newly created and flipped
+ * drawable.
+ *
+ * Returns: The flipped item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_flip (gint32  item_ID,
+                          gdouble x0,
+                          gdouble y0,
+                          gdouble x1,
+                          gdouble y1)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-flip",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_FLOAT, x0,
+                                    GIMP_PDB_FLOAT, y0,
+                                    GIMP_PDB_FLOAT, x1,
+                                    GIMP_PDB_FLOAT, y1,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_perspective:
+ * @item_ID: The affected item.
+ * @x0: The new x coordinate of upper-left corner of original bounding box.
+ * @y0: The new y coordinate of upper-left corner of original bounding box.
+ * @x1: The new x coordinate of upper-right corner of original bounding box.
+ * @y1: The new y coordinate of upper-right corner of original bounding box.
+ * @x2: The new x coordinate of lower-left corner of original bounding box.
+ * @y2: The new y coordinate of lower-left corner of original bounding box.
+ * @x3: The new x coordinate of lower-right corner of original bounding box.
+ * @y3: The new y coordinate of lower-right corner of original bounding box.
+ *
+ * Perform a possibly non-affine transformation on the specified item.
+ *
+ * This procedure performs a possibly non-affine transformation on the
+ * specified item by allowing the corners of the original bounding box
+ * to be arbitrarily remapped to any values. The specified item is
+ * remapped if no selection exists or it is not a drawable. However, if
+ * a selection exists and the item is a drawable, the portion of the
+ * drawable which lies under the selection is cut from the drawable and
+ * made into a floating selection which is then remapped as specified.
+ * The return value is the ID of the remapped item. If there was no
+ * selection or the item is not a drawable, this will be equal to the
+ * item ID supplied as input. Otherwise, this will be the newly created
+ * and remapped drawable. The 4 coordinates specify the new locations
+ * of each corner of the original bounding box. By specifying these
+ * values, any affine transformation (rotation, scaling, translation)
+ * can be affected. Additionally, these values can be specified such
+ * that the resulting transformed item will appear to have been
+ * projected via a perspective transform.
+ *
+ * Returns: The newly mapped item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_perspective (gint32  item_ID,
+                                 gdouble x0,
+                                 gdouble y0,
+                                 gdouble x1,
+                                 gdouble y1,
+                                 gdouble x2,
+                                 gdouble y2,
+                                 gdouble x3,
+                                 gdouble y3)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-perspective",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_FLOAT, x0,
+                                    GIMP_PDB_FLOAT, y0,
+                                    GIMP_PDB_FLOAT, x1,
+                                    GIMP_PDB_FLOAT, y1,
+                                    GIMP_PDB_FLOAT, x2,
+                                    GIMP_PDB_FLOAT, y2,
+                                    GIMP_PDB_FLOAT, x3,
+                                    GIMP_PDB_FLOAT, y3,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_rotate_simple:
+ * @item_ID: The affected item.
+ * @rotate_type: Type of rotation.
+ * @auto_center: Whether to automatically rotate around the selection center.
+ * @center_x: The hor. coordinate of the center of rotation.
+ * @center_y: The vert. coordinate of the center of rotation.
+ *
+ * Rotate the specified item about given coordinates through the
+ * specified angle.
+ *
+ * This function rotates the specified item. If a selection exists and
+ * the item is a drawable, the portion of the drawable which lies under
+ * the selection is cut from the drawable and made into a floating
+ * selection which is then rotated by the specified amount. The return
+ * value is the ID of the rotated item. If there was no selection or
+ * the item is not a drawable, this will be equal to the item ID
+ * supplied as input. Otherwise, this will be the newly created and
+ * rotated drawable.
+ *
+ * Returns: The rotated item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_rotate_simple (gint32           item_ID,
+                                   GimpRotationType rotate_type,
+                                   gboolean         auto_center,
+                                   gdouble          center_x,
+                                   gdouble          center_y)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-rotate-simple",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_INT32, rotate_type,
+                                    GIMP_PDB_INT32, auto_center,
+                                    GIMP_PDB_FLOAT, center_x,
+                                    GIMP_PDB_FLOAT, center_y,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_rotate:
+ * @item_ID: The affected item.
+ * @angle: The angle of rotation (radians).
+ * @auto_center: Whether to automatically rotate around the selection center.
+ * @center_x: The hor. coordinate of the center of rotation.
+ * @center_y: The vert. coordinate of the center of rotation.
+ *
+ * Rotate the specified item about given coordinates through the
+ * specified angle.
+ *
+ * This function rotates the specified item. If a selection exists and
+ * the item is a drawable, the portion of the drawable which lies under
+ * the selection is cut from the drawable and made into a floating
+ * selection which is then rotated by the specified amount. The return
+ * value is the ID of the rotated item. If there was no selection or
+ * the item is not a drawable, this will be equal to the item ID
+ * supplied as input. Otherwise, this will be the newly created and
+ * rotated drawable.
+ *
+ * Returns: The rotated item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_rotate (gint32   item_ID,
+                            gdouble  angle,
+                            gboolean auto_center,
+                            gdouble  center_x,
+                            gdouble  center_y)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-rotate",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_FLOAT, angle,
+                                    GIMP_PDB_INT32, auto_center,
+                                    GIMP_PDB_FLOAT, center_x,
+                                    GIMP_PDB_FLOAT, center_y,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_scale:
+ * @item_ID: The affected item.
+ * @x0: The new x coordinate of the upper-left corner of the scaled region.
+ * @y0: The new y coordinate of the upper-left corner of the scaled region.
+ * @x1: The new x coordinate of the lower-right corner of the scaled region.
+ * @y1: The new y coordinate of the lower-right corner of the scaled region.
+ *
+ * Scale the specified item.
+ *
+ * This procedure scales the specified item. If a selection exists and
+ * the item is a drawable, the portion of the drawable which lies under
+ * the selection is cut from the drawable and made into a floating
+ * selection which is then scaled by the specified amount. The return
+ * value is the ID of the scaled item. If there was no selection or the
+ * item is not a drawable, this will be equal to the item ID supplied
+ * as input. Otherwise, this will be the newly created and scaled
+ * drawable.
+ *
+ * Returns: The scaled item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_scale (gint32  item_ID,
+                           gdouble x0,
+                           gdouble y0,
+                           gdouble x1,
+                           gdouble y1)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-scale",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_FLOAT, x0,
+                                    GIMP_PDB_FLOAT, y0,
+                                    GIMP_PDB_FLOAT, x1,
+                                    GIMP_PDB_FLOAT, y1,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_shear:
+ * @item_ID: The affected item.
+ * @shear_type: Type of shear.
+ * @magnitude: The magnitude of the shear.
+ *
+ * Shear the specified item about its center by the specified
+ * magnitude.
+ *
+ * This procedure shears the specified item. If a selection exists and
+ * the item is a drawable, the portion of the drawable which lies under
+ * the selection is cut from the drawable and made into a floating
+ * selection which is then sheard by the specified amount. The return
+ * value is the ID of the sheard item. If there was no selection or the
+ * item is not a drawable, this will be equal to the item ID supplied
+ * as input. Otherwise, this will be the newly created and sheard
+ * drawable. The shear type parameter indicates whether the shear will
+ * be applied horizontally or vertically. The magnitude can be either
+ * positive or negative and indicates the extent (in pixels) to shear
+ * by.
+ *
+ * Returns: The sheared item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_shear (gint32              item_ID,
+                           GimpOrientationType shear_type,
+                           gdouble             magnitude)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-shear",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_INT32, shear_type,
+                                    GIMP_PDB_FLOAT, magnitude,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_2d:
+ * @item_ID: The affected item.
+ * @source_x: X coordinate of the transformation center.
+ * @source_y: Y coordinate of the transformation center.
+ * @scale_x: Amount to scale in x direction.
+ * @scale_y: Amount to scale in y direction.
+ * @angle: The angle of rotation (radians).
+ * @dest_x: X coordinate of where the center goes.
+ * @dest_y: Y coordinate of where the center goes.
+ *
+ * Transform the specified item in 2d.
+ *
+ * This procedure transforms the specified item. If a selection exists
+ * and the item is a drawable, the portion of the drawable which lies
+ * under the selection is cut from the drawable and made into a
+ * floating selection which is then transformed. The transformation is
+ * done by scaling the image by the x and y scale factors about the
+ * point (source_x, source_y), then rotating around the same point,
+ * then translating that point to the new position (dest_x, dest_y).
+ * The return value is the ID of the rotated drawable. If there was no
+ * selection or the item is not a drawable, this will be equal to the
+ * item ID supplied as input. Otherwise, this will be the newly created
+ * and transformed drawable.
+ *
+ * Returns: The transformed item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_2d (gint32  item_ID,
+                        gdouble source_x,
+                        gdouble source_y,
+                        gdouble scale_x,
+                        gdouble scale_y,
+                        gdouble angle,
+                        gdouble dest_x,
+                        gdouble dest_y)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-2d",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_FLOAT, source_x,
+                                    GIMP_PDB_FLOAT, source_y,
+                                    GIMP_PDB_FLOAT, scale_x,
+                                    GIMP_PDB_FLOAT, scale_y,
+                                    GIMP_PDB_FLOAT, angle,
+                                    GIMP_PDB_FLOAT, dest_x,
+                                    GIMP_PDB_FLOAT, dest_y,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
+
+/**
+ * gimp_item_transform_matrix:
+ * @item_ID: The affected item.
+ * @coeff_0_0: coefficient (0,0) of the transformation matrix.
+ * @coeff_0_1: coefficient (0,1) of the transformation matrix.
+ * @coeff_0_2: coefficient (0,2) of the transformation matrix.
+ * @coeff_1_0: coefficient (1,0) of the transformation matrix.
+ * @coeff_1_1: coefficient (1,1) of the transformation matrix.
+ * @coeff_1_2: coefficient (1,2) of the transformation matrix.
+ * @coeff_2_0: coefficient (2,0) of the transformation matrix.
+ * @coeff_2_1: coefficient (2,1) of the transformation matrix.
+ * @coeff_2_2: coefficient (2,2) of the transformation matrix.
+ *
+ * Transform the specified item in 2d.
+ *
+ * This procedure transforms the specified item. If a selection exists
+ * and the item is a drawable, the portion of the drawable which lies
+ * under the selection is cut from the drawable and made into a
+ * floating selection which is then transformed. The transformation is
+ * done by assembling a 3x3 matrix from the coefficients passed. The
+ * return value is the ID of the transformed item. If there was no
+ * selection or the item is not a drawable, this will be equal to the
+ * item ID supplied as input. Otherwise, this will be the newly created
+ * and transformed drawable.
+ *
+ * Returns: The transformed item.
+ *
+ * Since: GIMP 2.8
+ */
+gint32
+gimp_item_transform_matrix (gint32  item_ID,
+                            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)
+{
+  GimpParam *return_vals;
+  gint nreturn_vals;
+  gint32 ret_item_ID = -1;
+
+  return_vals = gimp_run_procedure ("gimp-item-transform-matrix",
+                                    &nreturn_vals,
+                                    GIMP_PDB_ITEM, item_ID,
+                                    GIMP_PDB_FLOAT, coeff_0_0,
+                                    GIMP_PDB_FLOAT, coeff_0_1,
+                                    GIMP_PDB_FLOAT, coeff_0_2,
+                                    GIMP_PDB_FLOAT, coeff_1_0,
+                                    GIMP_PDB_FLOAT, coeff_1_1,
+                                    GIMP_PDB_FLOAT, coeff_1_2,
+                                    GIMP_PDB_FLOAT, coeff_2_0,
+                                    GIMP_PDB_FLOAT, coeff_2_1,
+                                    GIMP_PDB_FLOAT, coeff_2_2,
+                                    GIMP_PDB_END);
+
+  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
+    ret_item_ID = return_vals[1].data.d_item;
+
+  gimp_destroy_params (return_vals, nreturn_vals);
+
+  return ret_item_ID;
+}
diff --git a/libgimp/gimpitemtransform_pdb.h b/libgimp/gimpitemtransform_pdb.h
new file mode 100644
index 0000000..03bd917
--- /dev/null
+++ b/libgimp/gimpitemtransform_pdb.h
@@ -0,0 +1,89 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpitemtransform_pdb.h
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/* NOTE: This file is auto-generated by pdbgen.pl */
+
+#ifndef __GIMP_ITEM_TRANSFORM_PDB_H__
+#define __GIMP_ITEM_TRANSFORM_PDB_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+gint32 gimp_item_transform_flip_simple   (gint32              item_ID,
+                                          GimpOrientationType flip_type,
+                                          gboolean            auto_center,
+                                          gdouble             axis);
+gint32 gimp_item_transform_flip          (gint32              item_ID,
+                                          gdouble             x0,
+                                          gdouble             y0,
+                                          gdouble             x1,
+                                          gdouble             y1);
+gint32 gimp_item_transform_perspective   (gint32              item_ID,
+                                          gdouble             x0,
+                                          gdouble             y0,
+                                          gdouble             x1,
+                                          gdouble             y1,
+                                          gdouble             x2,
+                                          gdouble             y2,
+                                          gdouble             x3,
+                                          gdouble             y3);
+gint32 gimp_item_transform_rotate_simple (gint32              item_ID,
+                                          GimpRotationType    rotate_type,
+                                          gboolean            auto_center,
+                                          gdouble             center_x,
+                                          gdouble             center_y);
+gint32 gimp_item_transform_rotate        (gint32              item_ID,
+                                          gdouble             angle,
+                                          gboolean            auto_center,
+                                          gdouble             center_x,
+                                          gdouble             center_y);
+gint32 gimp_item_transform_scale         (gint32              item_ID,
+                                          gdouble             x0,
+                                          gdouble             y0,
+                                          gdouble             x1,
+                                          gdouble             y1);
+gint32 gimp_item_transform_shear         (gint32              item_ID,
+                                          GimpOrientationType shear_type,
+                                          gdouble             magnitude);
+gint32 gimp_item_transform_2d            (gint32              item_ID,
+                                          gdouble             source_x,
+                                          gdouble             source_y,
+                                          gdouble             scale_x,
+                                          gdouble             scale_y,
+                                          gdouble             angle,
+                                          gdouble             dest_x,
+                                          gdouble             dest_y);
+gint32 gimp_item_transform_matrix        (gint32              item_ID,
+                                          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);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_ITEM_TRANSFORM_PDB_H__ */
diff --git a/tools/pdbgen/Makefile.am b/tools/pdbgen/Makefile.am
index 8acb485..b17b93c 100644
--- a/tools/pdbgen/Makefile.am
+++ b/tools/pdbgen/Makefile.am
@@ -27,6 +27,7 @@ pdb_sources = \
 	pdb/help.pdb			\
 	pdb/image.pdb			\
 	pdb/item.pdb			\
+	pdb/item_transform.pdb		\
 	pdb/layer.pdb			\
 	pdb/message.pdb			\
 	pdb/misc.pdb			\
diff --git a/tools/pdbgen/groups.pl b/tools/pdbgen/groups.pl
index 0579d02..9938405 100644
--- a/tools/pdbgen/groups.pl
+++ b/tools/pdbgen/groups.pl
@@ -25,6 +25,7 @@
     help
     image
     item
+    item_transform
     layer
     message
     misc
diff --git a/tools/pdbgen/pdb/item_transform.pdb b/tools/pdbgen/pdb/item_transform.pdb
new file mode 100644
index 0000000..f5dc223
--- /dev/null
+++ b/tools/pdbgen/pdb/item_transform.pdb
@@ -0,0 +1,626 @@
+# GIMP - The GNU Image Manipulation Program
+# Copyright (C) 1995 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 <http://www.gnu.org/licenses/>.
+
+# "Perlized" from C source by Manish Singh <yosh gimp org>
+
+# Item Transformations
+
+# shortcuts
+
+sub transform_invoke {
+    my ($progress_text, $assemble_matrix, $check) = @_;
+    my $success_check = 'gimp_pdb_item_is_attached (item, NULL, TRUE, error);';
+
+    if ($check) {
+        $success_check = "(gimp_pdb_item_is_attached (item, NULL, TRUE, error) && " . $check . ");";
+    }
+
+    %invoke = (
+        code => <<"CODE"
+{
+  gint x, y, width, height;
+
+  success = $success_check
+
+  if (success &&
+      gimp_item_mask_intersect (item, &x, &y, &width, &height))
+    {
+      GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+      GimpMatrix3     matrix;
+      gint            off_x, off_y;
+
+      gimp_item_get_offset (item, &off_x, &off_y);
+      x += off_x;
+      y += off_y;
+
+      /* Assemble the transformation matrix */
+$assemble_matrix
+
+      if (progress)
+        gimp_progress_start (progress, _(\"$progress_text\"), FALSE);
+
+      if (GIMP_IS_DRAWABLE (item))
+        {
+          success = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
+                                                    context, &matrix,
+                                                    pdb_context->transform_direction,
+                                                    pdb_context->interpolation,
+                                                    pdb_context->transform_recursion,
+                                                    pdb_context->transform_resize,
+                                                    progress);
+        }
+      else
+        {
+          gimp_item_transform (item, context, &matrix,
+                               pdb_context->transform_direction,
+                               pdb_context->interpolation,
+                               pdb_context->transform_recursion,
+                               pdb_context->transform_resize,
+                               progress);
+        }
+
+      if (progress)
+        gimp_progress_end (progress);
+    }
+}
+CODE
+    )
+}
+
+# The defs
+
+sub item_transform_flip_simple {
+    $blurb = <<'BLURB';
+Flip the specified item either vertically or horizontally.
+BLURB
+
+    $help = <<'HELP';
+This procedure flips the specified item. If a selection exists and the
+item is a drawable, the portion of the drawable which lies under the
+selection is cut from the drawable and made into a floating selection
+which is then flipped. If auto_center is set to TRUE, the flip is
+around the selection's center. Otherwise, the coordinate of the axis
+needs to be specified. The return value is the ID of the flipped
+item. If there was no selection or the item is not a drawable, this
+will be equal to the item ID supplied as input.  Otherwise, this will
+be the newly created and flipped drawable.
+HELP
+
+    &mitch_pdb_misc('2004', '2.2');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'flip_type',
+	  type => 'enum GimpOrientationType (no GIMP_ORIENTATION_UNKNOWN)',
+          desc => 'Type of flip' },
+        { name => 'auto_center', type => 'boolean',
+          desc => 'Whether to automatically position the axis in the selection center' },
+        { name => 'axis', type => 'float',
+          desc => 'coord. of flip axis' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The flipped item' }
+    );
+
+    %invoke = (
+        code => <<'CODE'
+{
+  gint x, y, width, height;
+
+  success = gimp_pdb_item_is_attached (item, NULL, TRUE, error);
+
+  if (success &&
+      gimp_item_mask_intersect (item, &x, &y, &width, &height))
+    {
+      GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+      gint            off_x, off_y;
+
+      gimp_item_get_offset (item, &off_x, &off_y);
+      x += off_x;
+      y += off_y;
+
+      gimp_transform_get_flip_axis (x, y, width, height,
+                                    flip_type, auto_center, &axis);
+
+      if (GIMP_IS_DRAWABLE (item))
+        {
+          success = gimp_drawable_transform_flip (GIMP_DRAWABLE (item), context,
+                                                  flip_type, axis,
+                                                  pdb_context->transform_resize);
+        }
+      else
+        {
+          gimp_item_flip (item, context,
+                          flip_type, axis,
+                          pdb_context->transform_resize);
+        }
+    }
+}
+CODE
+    );
+}
+
+
+sub item_transform_flip {
+    $blurb = <<'BLURB';
+Flip the specified item around a given line.
+BLURB
+
+    $help = <<'HELP';
+This procedure flips the specified item. If a selection exists and the
+item is a drawable , the portion of the drawable which lies under the
+selection is cut from the drawable and made into a floating selection
+which is then flipped. The axis to flip around is specified by
+specifying two points from that line. The return value is the ID of
+the flipped item. If there was no selection or the item is not a
+drawable, this will be equal to the item ID supplied as input.
+Otherwise, this will be the newly created and flipped drawable.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'x0', type => 'float',
+          desc => 'horz. coord. of one end of axis' },
+        { name => 'y0', type => 'float',
+          desc => 'vert. coord. of one end of axis' },
+        { name => 'x1', type => 'float',
+          desc => 'horz. coord. of other end of axis' },
+        { name => 'y1', type => 'float',
+          desc => 'vert. coord. of other end of axis' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The flipped item' }
+    );
+
+    transform_invoke ("Flipping", <<CODE);
+      gimp_matrix3_identity (&matrix);
+      gimp_transform_matrix_flip_free (&matrix, x0, y0, x1, y1);
+CODE
+}
+
+
+sub item_transform_perspective {
+    $blurb = <<'BLURB';
+Perform a possibly non-affine transformation on the specified item.
+BLURB
+
+    $help = <<'HELP';
+This procedure performs a possibly non-affine transformation on the
+specified item by allowing the corners of the original bounding box to
+be arbitrarily remapped to any values. The specified item is remapped
+if no selection exists or it is not a drawable. However, if a
+selection exists and the item is a drawable, the portion of the
+drawable which lies under the selection is cut from the drawable and
+made into a floating selection which is then remapped as
+specified. The return value is the ID of the remapped item. If there
+was no selection or the item is not a drawable, this will be equal to
+the item ID supplied as input. Otherwise, this will be the newly
+created and remapped drawable. The 4 coordinates specify the new
+locations of each corner of the original bounding box. By specifying
+these values, any affine transformation (rotation, scaling,
+translation) can be affected. Additionally, these values can be
+specified such that the resulting transformed item will appear to
+have been projected via a perspective transform.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+	{ name => 'x0', type => 'float',
+	  desc => 'The new x coordinate of upper-left corner of original
+		   bounding box' },
+	{ name => 'y0', type => 'float',
+	  desc => 'The new y coordinate of upper-left corner of original
+		   bounding box' },
+	{ name => 'x1', type => 'float',
+	  desc => 'The new x coordinate of upper-right corner of original
+		   bounding box' },
+	{ name => 'y1', type => 'float',
+	  desc => 'The new y coordinate of upper-right corner of original
+		   bounding box' },
+	{ name => 'x2', type => 'float',
+	  desc => 'The new x coordinate of lower-left corner of original
+		   bounding box' },
+	{ name => 'y2', type => 'float',
+	  desc => 'The new y coordinate of lower-left corner of original
+		   bounding box' },
+	{ name => 'x3', type => 'float',
+	  desc => 'The new x coordinate of lower-right corner of original
+		   bounding box' },
+	{ name => 'y3', type => 'float',
+	  desc => 'The new y coordinate of lower-right corner of original
+		   bounding box' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The newly mapped item' }
+    );
+
+    transform_invoke ("Perspective", <<CODE);
+      gimp_matrix3_identity (&matrix);
+      gimp_transform_matrix_perspective (&matrix,
+                                         x, y, width, height,
+                                         x0, y0, x1, y1,
+                                         x2, y2, x3, y3);
+CODE
+}
+
+
+sub item_transform_rotate_simple {
+    $blurb = <<'BLURB';
+Rotate the specified item about given coordinates through the specified angle.
+BLURB
+
+    $help = <<'HELP';
+This function rotates the specified item. If a selection exists and
+the item is a drawable, the portion of the drawable which lies under
+the selection is cut from the drawable and made into a floating
+selection which is then rotated by the specified amount. The return
+value is the ID of the rotated item. If there was no selection or the
+item is not a drawable, this will be equal to the item ID supplied as
+input. Otherwise, this will be the newly created and rotated drawable.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'rotate_type', type => 'enum GimpRotationType',
+          desc => 'Type of rotation' },
+        { name => 'auto_center', type => 'boolean',
+          desc => 'Whether to automatically rotate around the selection center' },
+        { name => 'center_x', type => 'float',
+          desc => 'The hor. coordinate of the center of rotation' },
+        { name => 'center_y', type => 'float',
+          desc => 'The vert. coordinate of the center of rotation' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The rotated item' }
+    );
+
+    %invoke = (
+        code => <<'CODE'
+{
+  gint x, y, width, height;
+
+  success = gimp_pdb_item_is_attached (item, NULL, FALSE, error);
+
+  if (success &&
+      gimp_item_mask_intersect (item, &x, &y, &width, &height))
+    {
+      GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
+      gint            off_x, off_y;
+
+      gimp_item_get_offset (item, &off_x, &off_y);
+      x += off_x;
+      y += off_y;
+
+      gimp_transform_get_rotate_center (x, y, width, height,
+                                        auto_center, &center_x, &center_y);
+
+      if (GIMP_IS_DRAWABLE (item))
+        {
+          success = gimp_drawable_transform_rotate (GIMP_DRAWABLE (item),
+                                                    context,
+                                                    rotate_type,
+                                                    center_x, center_y,
+                                                    pdb_context->transform_resize);
+        }
+      else
+        {
+          gimp_item_rotate (item, context,
+                            rotate_type,
+                            center_x, center_y,
+                            pdb_context->transform_resize);
+        }
+    }
+}
+CODE
+    );
+}
+
+
+sub item_transform_rotate {
+    $blurb = <<'BLURB';
+Rotate the specified item about given coordinates through the
+specified angle.
+BLURB
+
+    $help = <<'HELP';
+This function rotates the specified item. If a selection exists and
+the item is a drawable, the portion of the drawable which lies under
+the selection is cut from the drawable and made into a floating
+selection which is then rotated by the specified amount. The return
+value is the ID of the rotated item. If there was no selection or the
+item is not a drawable, this will be equal to the item ID supplied as
+input. Otherwise, this will be the newly created and rotated drawable.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'angle', type => 'float',
+          desc => 'The angle of rotation (radians)' },
+        { name => 'auto_center', type => 'boolean',
+          desc => 'Whether to automatically rotate around the selection center' },
+        { name => 'center_x', type => 'float',
+          desc => 'The hor. coordinate of the center of rotation' },
+        { name => 'center_y', type => 'float',
+          desc => 'The vert. coordinate of the center of rotation' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The rotated item' }
+    );
+
+    transform_invoke ("Rotating", <<CODE);
+      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);
+CODE
+}
+
+
+sub item_transform_scale {
+    $blurb = 'Scale the specified item.';
+
+    $help = <<'HELP';
+This procedure scales the specified item. If a selection exists and
+the item is a drawable, the portion of the drawable which lies under
+the selection is cut from the drawable and made into a floating
+selection which is then scaled by the specified amount. The return
+value is the ID of the scaled item. If there was no selection or the
+item is not a drawable, this will be equal to the item ID supplied as
+input. Otherwise, this will be the newly created and scaled drawable.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+	{ name => 'x0', type => 'float',
+	  desc => 'The new x coordinate of the upper-left corner of the
+		    scaled region' },
+	{ name => 'y0', type => 'float',
+	  desc => 'The new y coordinate of the upper-left corner of the
+		    scaled region' },
+	{ name => 'x1', type => 'float',
+	  desc => 'The new x coordinate of the lower-right corner of the
+		    scaled region' },
+	{ name => 'y1', type => 'float',
+	  desc => 'The new y coordinate of the lower-right corner of the
+		    scaled region' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The scaled item' }
+    );
+
+    transform_invoke ("Scaling", <<CODE, 'x0 < x1 && y0 < y1');
+      gimp_matrix3_identity (&matrix);
+      gimp_transform_matrix_scale (&matrix,
+                                   x, y, width, height,
+                                   x0, y0, x1 - x0, y1 - y0);
+CODE
+}
+
+
+sub item_transform_shear {
+    $blurb = <<'BLURB';
+Shear the specified item about its center by the specified magnitude.
+BLURB
+
+    $help = <<'HELP';
+This procedure shears the specified item. If a selection exists and
+the item is a drawable, the portion of the drawable which lies under
+the selection is cut from the drawable and made into a floating
+selection which is then sheard by the specified amount. The return
+value is the ID of the sheard item. If there was no selection or the
+item is not a drawable, this will be equal to the item ID supplied as
+input. Otherwise, this will be the newly created and sheard
+drawable. The shear type parameter indicates whether the shear will be
+applied horizontally or vertically. The magnitude can be either
+positive or negative and indicates the extent (in pixels) to shear by.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'shear_type',
+	  type => 'enum GimpOrientationType (no GIMP_ORIENTATION_UNKNOWN)',
+          desc => 'Type of shear' },
+        { name => 'magnitude', type => 'float',
+          desc => 'The magnitude of the shear' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The sheared item' }
+    );
+
+    transform_invoke ("Shearing", <<CODE);
+      gimp_matrix3_identity (&matrix);
+      gimp_transform_matrix_shear (&matrix,
+                                   x, y, width, height,
+                                   shear_type, magnitude);
+CODE
+}
+
+
+sub item_transform_2d {
+    $blurb = 'Transform the specified item in 2d.';
+
+    $help = <<'HELP';
+This procedure transforms the specified item. If a selection exists
+and the item is a drawable, the portion of the drawable which lies
+under the selection is cut from the drawable and made into a floating
+selection which is then transformed. The transformation is done by
+scaling the image by the x and y scale factors about the point
+(source_x, source_y), then rotating around the same point, then
+translating that point to the new position (dest_x, dest_y). The
+return value is the ID of the rotated drawable. If there was no
+selection or the item is not a drawable, this will be equal to the
+item ID supplied as input. Otherwise, this will be the newly created
+and transformed drawable.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'source_x', type => 'float',
+          desc => 'X coordinate of the transformation center' },
+        { name => 'source_y', type => 'float',
+          desc => 'Y coordinate of the transformation center' },
+        { name => 'scale_x', type => 'float',
+          desc => 'Amount to scale in x direction' },
+        { name => 'scale_y', type => 'float',
+          desc => 'Amount to scale in y direction' },
+        { name => 'angle', type => 'float',
+          desc => 'The angle of rotation (radians)' },
+        { name => 'dest_x', type => 'float',
+          desc => 'X coordinate of where the center goes' },
+        { name => 'dest_y', type => 'float',
+          desc => 'Y coordinate of where the center goes' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The transformed item' }
+    );
+
+    transform_invoke ("2D Transform", <<CODE);
+      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);
+CODE
+}
+
+
+sub item_transform_matrix {
+    $blurb = 'Transform the specified item in 2d.';
+
+    $help = <<'HELP';
+This procedure transforms the specified item. If a selection exists
+and the item is a drawable, the portion of the drawable which lies
+under the selection is cut from the drawable and made into a floating
+selection which is then transformed. The transformation is done by
+assembling a 3x3 matrix from the coefficients passed.  The return
+value is the ID of the transformed item. If there was no selection or
+the item is not a drawable, this will be equal to the item ID supplied
+as input. Otherwise, this will be the newly created and transformed
+drawable.
+HELP
+
+    &mitch_pdb_misc('2010', '2.8');
+
+    @inargs = (
+	{ name => 'item', type => 'item',
+	  desc => 'The affected item' },
+        { name => 'coeff_0_0', type => 'float',
+          desc => 'coefficient (0,0) of the transformation matrix' },
+        { name => 'coeff_0_1', type => 'float',
+          desc => 'coefficient (0,1) of the transformation matrix' },
+        { name => 'coeff_0_2', type => 'float',
+          desc => 'coefficient (0,2) of the transformation matrix' },
+        { name => 'coeff_1_0', type => 'float',
+          desc => 'coefficient (1,0) of the transformation matrix' },
+        { name => 'coeff_1_1', type => 'float',
+          desc => 'coefficient (1,1) of the transformation matrix' },
+        { name => 'coeff_1_2', type => 'float',
+          desc => 'coefficient (1,2) of the transformation matrix' },
+        { name => 'coeff_2_0', type => 'float',
+          desc => 'coefficient (2,0) of the transformation matrix' },
+        { name => 'coeff_2_1', type => 'float',
+          desc => 'coefficient (2,1) of the transformation matrix' },
+        { name => 'coeff_2_2', type => 'float',
+          desc => 'coefficient (2,2) of the transformation matrix' }
+    );
+
+    @outargs = (
+	{ name => 'item', type => 'item', no_declare => 1,
+	  desc => 'The transformed item' }
+    );
+
+    transform_invoke ("2D Transforming", <<CODE);
+      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;
+CODE
+}
+
+
+ headers = qw("libgimpmath/gimpmath.h"
+              "core/gimp-transform-utils.h"
+              "core/gimpdrawable.h"
+              "core/gimpdrawable-transform.h"
+              "core/gimpprogress.h"
+              "gimppdb-utils.h"
+              "gimppdbcontext.h"
+              "gimp-intl.h");
+
+ procs = qw(item_transform_flip_simple
+            item_transform_flip
+            item_transform_perspective
+            item_transform_rotate_simple
+            item_transform_rotate
+            item_transform_scale
+            item_transform_shear
+            item_transform_2d
+            item_transform_matrix);
+
+%exports = (app => [ procs], lib => [ procs]);
+
+$desc = 'Transformation procedures';
+$doc_title = 'gimpitemtransform';
+$doc_short_desc = 'Functions to perform transformations on items.';
+$doc_long_desc = 'Functions to perform transformations on items.';
+
+1;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]