Beispiel #1
0
gboolean
gimp_pdb_item_is_in_tree (GimpItem           *item,
                          GimpImage          *image,
                          GimpPDBItemModify   modify,
                          GError            **error)
{
  g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
  g_return_val_if_fail (image == NULL || GIMP_IS_IMAGE (image), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (! gimp_pdb_item_is_attached (item, image, modify, error))
    return FALSE;

  if (! gimp_item_get_tree (item))
    {
      g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
                   _("Item '%s' (%d) cannot be used because it is not "
                     "a direct child of an item tree"),
                   gimp_object_get_name (item),
                   gimp_item_get_ID (item));
      return FALSE;
    }

  return TRUE;
}
Beispiel #2
0
static GimpValueArray *
selection_combine_invoker (GimpProcedure         *procedure,
                           Gimp                  *gimp,
                           GimpContext           *context,
                           GimpProgress          *progress,
                           const GimpValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  GimpChannel *channel;
  gint32 operation;

  channel = gimp_value_get_channel (gimp_value_array_index (args, 0), gimp);
  operation = g_value_get_enum (gimp_value_array_index (args, 1));

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (channel), NULL, 0, error))
        gimp_item_to_selection (GIMP_ITEM (channel),
                                operation,
                                TRUE, FALSE, 0.0, 0.0);
      else
        success = FALSE;
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
Beispiel #3
0
static GValueArray *
floating_sel_attach_invoker (GimpProcedure      *procedure,
                             Gimp               *gimp,
                             GimpContext        *context,
                             GimpProgress       *progress,
                             const GValueArray  *args,
                             GError            **error)
{
  gboolean success = TRUE;
  GimpLayer *layer;
  GimpDrawable *drawable;

  layer = gimp_value_get_layer (&args->values[0], gimp);
  drawable = gimp_value_get_drawable (&args->values[1], gimp);

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error) &&
          gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
        floating_sel_attach (layer, drawable);
      else
        success = FALSE;
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
Beispiel #4
0
static GimpValueArray *
selection_layer_alpha_invoker (GimpProcedure         *procedure,
                               Gimp                  *gimp,
                               GimpContext           *context,
                               GimpProgress          *progress,
                               const GimpValueArray  *args,
                               GError               **error)
{
  gboolean success = TRUE;
  GimpLayer *layer;

  layer = gimp_value_get_layer (gimp_value_array_index (args, 0), gimp);

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (layer), NULL, 0, error))
        gimp_item_to_selection (GIMP_ITEM (layer),
                                GIMP_CHANNEL_OP_REPLACE,
                                TRUE, FALSE, 0.0, 0.0);
      else
        success = FALSE;
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
Beispiel #5
0
static GimpValueArray *
text_fontname_invoker (GimpProcedure         *procedure,
                       Gimp                  *gimp,
                       GimpContext           *context,
                       GimpProgress          *progress,
                       const GimpValueArray  *args,
                       GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpImage *image;
  GimpDrawable *drawable;
  gdouble x;
  gdouble y;
  const gchar *text;
  gint32 border;
  gboolean antialias;
  gdouble size;
  const gchar *fontname;
  GimpLayer *text_layer = NULL;

  image = gimp_value_get_image (gimp_value_array_index (args, 0), gimp);
  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 1), gimp);
  x = g_value_get_double (gimp_value_array_index (args, 2));
  y = g_value_get_double (gimp_value_array_index (args, 3));
  text = g_value_get_string (gimp_value_array_index (args, 4));
  border = g_value_get_int (gimp_value_array_index (args, 5));
  antialias = g_value_get_boolean (gimp_value_array_index (args, 6));
  size = g_value_get_double (gimp_value_array_index (args, 7));
  fontname = g_value_get_string (gimp_value_array_index (args, 9));

  if (success)
    {
      if (drawable &&
          (! gimp_pdb_item_is_attached (GIMP_ITEM (drawable), image,
                                        GIMP_PDB_ITEM_CONTENT, error) ||
           ! gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)))
        success = FALSE;

      if (success)
        {
          gchar *real_fontname = g_strdup_printf ("%s %d", fontname, (gint) size);

          text_layer = text_render (image, drawable, context,
                                    x, y, real_fontname, text,
                                    border, antialias);

          g_free (real_fontname);
        }
    }

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

  if (success)
    gimp_value_set_layer (gimp_value_array_index (return_vals, 1), text_layer);

  return return_vals;
}
Beispiel #6
0
static GimpValueArray *
flip_invoker (GimpProcedure         *procedure,
              Gimp                  *gimp,
              GimpContext           *context,
              GimpProgress          *progress,
              const GimpValueArray  *args,
              GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 flip_type;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  flip_type = g_value_get_enum (gimp_value_array_index (args, 1));

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

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

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          gdouble axis;

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

          if (! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (gimp_image_get_mask (gimp_item_get_image (GIMP_ITEM (drawable)))))
            {
              if (! gimp_drawable_transform_flip (drawable, context,
                                                  flip_type, axis, FALSE))
                {
                  success = FALSE;
                }
            }
          else
            {
              gimp_item_flip (GIMP_ITEM (drawable), context,
                              flip_type, axis, FALSE);
            }
        }
    }

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

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

  return return_vals;
}
Beispiel #7
0
static GimpValueArray *
edit_named_cut_invoker (GimpProcedure         *procedure,
                        Gimp                  *gimp,
                        GimpContext           *context,
                        GimpProgress          *progress,
                        const GimpValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  const gchar *buffer_name;
  gchar *real_name = NULL;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  buffer_name = g_value_get_string (gimp_value_array_index (args, 1));

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                     GIMP_PDB_ITEM_CONTENT, error) &&
          gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
        {
          GimpImage *image    = gimp_item_get_image (GIMP_ITEM (drawable));
          GError    *my_error = NULL;

          real_name = (gchar *) gimp_edit_named_cut (image, buffer_name,
                                                     drawable, context, &my_error);

          if (real_name)
            {
              real_name = g_strdup (real_name);
            }
          else
            {
              gimp_message_literal (gimp,
                                    G_OBJECT (progress), GIMP_MESSAGE_WARNING,
                                    my_error->message);
              g_clear_error (&my_error);
            }
        }
      else
        success = FALSE;
    }

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

  if (success)
    g_value_take_string (gimp_value_array_index (return_vals, 1), real_name);

  return return_vals;
}
Beispiel #8
0
static GimpValueArray *
image_select_contiguous_color_invoker (GimpProcedure         *procedure,
                                       Gimp                  *gimp,
                                       GimpContext           *context,
                                       GimpProgress          *progress,
                                       const GimpValueArray  *args,
                                       GError               **error)
{
  gboolean success = TRUE;
  GimpImage *image;
  gint32 operation;
  GimpDrawable *drawable;
  gdouble x;
  gdouble y;

  image = gimp_value_get_image (gimp_value_array_index (args, 0), gimp);
  operation = g_value_get_enum (gimp_value_array_index (args, 1));
  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp);
  x = g_value_get_double (gimp_value_array_index (args, 3));
  y = g_value_get_double (gimp_value_array_index (args, 4));

  if (success)
    {
      GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);

      if (pdb_context->sample_merged ||
          gimp_pdb_item_is_attached (GIMP_ITEM (drawable), image, 0, error))
        {

          gimp_channel_select_fuzzy (gimp_image_get_mask (image),
                                     drawable,
                                     pdb_context->sample_merged,
                                     x, y,
                                     pdb_context->sample_threshold,
                                     pdb_context->sample_transparent,
                                     pdb_context->sample_criterion,
                                     pdb_context->diagonal_neighbors,
                                     operation,
                                     pdb_context->antialias,
                                     pdb_context->feather,
                                     pdb_context->feather_radius_x,
                                     pdb_context->feather_radius_y);
        }
      else
        success = FALSE;
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
Beispiel #9
0
static GimpValueArray *
edit_named_paste_invoker (GimpProcedure         *procedure,
                          Gimp                  *gimp,
                          GimpContext           *context,
                          GimpProgress          *progress,
                          const GimpValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  const gchar *buffer_name;
  gboolean paste_into;
  GimpLayer *floating_sel = NULL;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  buffer_name = g_value_get_string (gimp_value_array_index (args, 1));
  paste_into = g_value_get_boolean (gimp_value_array_index (args, 2));

  if (success)
    {
      GimpBuffer *buffer = gimp_pdb_get_buffer (gimp, buffer_name, error);

      if (buffer &&
          gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                     GIMP_PDB_ITEM_CONTENT, error) &&
          gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
        {
          floating_sel = gimp_edit_paste (gimp_item_get_image (GIMP_ITEM (drawable)),
                                          drawable, GIMP_OBJECT (buffer),
                                          paste_into ?
                                          GIMP_PASTE_TYPE_FLOATING_INTO :
                                          GIMP_PASTE_TYPE_FLOATING,
                                          -1, -1, -1, -1);
          if (! floating_sel)
            success = FALSE;
        }
      else
        success = FALSE;
    }

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

  if (success)
    gimp_value_set_layer (gimp_value_array_index (return_vals, 1), floating_sel);

  return return_vals;
}
Beispiel #10
0
static GimpValueArray *
edit_cut_invoker (GimpProcedure         *procedure,
                  Gimp                  *gimp,
                  GimpContext           *context,
                  GimpProgress          *progress,
                  const GimpValueArray  *args,
                  GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gboolean non_empty = FALSE;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                     GIMP_PDB_ITEM_CONTENT, error) &&
          gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
        {
          GimpImage *image    = gimp_item_get_image (GIMP_ITEM (drawable));
          GError    *my_error = NULL;

          non_empty = gimp_edit_cut (image, drawable, context, &my_error) != NULL;

          if (! non_empty)
            {
              gimp_message_literal (gimp,
                                    G_OBJECT (progress), GIMP_MESSAGE_WARNING,
                                    my_error->message);
              g_clear_error (&my_error);
            }
        }
      else
        success = FALSE;
    }

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

  if (success)
    g_value_set_boolean (gimp_value_array_index (return_vals, 1), non_empty);

  return return_vals;
}
Beispiel #11
0
static GimpValueArray *
selection_float_invoker (GimpProcedure         *procedure,
                         Gimp                  *gimp,
                         GimpContext           *context,
                         GimpProgress          *progress,
                         const GimpValueArray  *args,
                         GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 offx;
  gint32 offy;
  GimpLayer *layer = NULL;

  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
  offx = g_value_get_int (gimp_value_array_index (args, 1));
  offy = g_value_get_int (gimp_value_array_index (args, 2));

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL,
                                     GIMP_PDB_ITEM_CONTENT, error) &&
          gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
        {
          GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));

          layer = gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
                                        drawable, context, TRUE, offx, offy,
                                        error);
          if (! layer)
            success = FALSE;
        }
      else
        success = FALSE;
    }

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

  if (success)
    gimp_value_set_layer (gimp_value_array_index (return_vals, 1), layer);

  return return_vals;
}
static GValueArray *
image_select_color_invoker (GimpProcedure      *procedure,
                            Gimp               *gimp,
                            GimpContext        *context,
                            GimpProgress       *progress,
                            const GValueArray  *args,
                            GError            **error)
{
  gboolean success = TRUE;
  GimpImage *image;
  gint32 operation;
  GimpDrawable *drawable;
  GimpRGB color;

  image = gimp_value_get_image (&args->values[0], gimp);
  operation = g_value_get_enum (&args->values[1]);
  drawable = gimp_value_get_drawable (&args->values[2], gimp);
  gimp_value_get_rgb (&args->values[3], &color);

  if (success)
    {
      GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);

      if (pdb_context->sample_merged ||
          gimp_pdb_item_is_attached (GIMP_ITEM (drawable), image, FALSE, error))
        {
          gimp_channel_select_by_color (gimp_image_get_mask (image), drawable,
                                        pdb_context->sample_merged,
                                        &color,
                                        (gint) (pdb_context->sample_threshold * 255.99),
                                        pdb_context->sample_transparent,
                                        pdb_context->sample_criterion,
                                        operation,
                                        pdb_context->antialias,
                                        pdb_context->feather,
                                        pdb_context->feather_radius_x,
                                        pdb_context->feather_radius_y);
        }
      else
        success = FALSE;
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
Beispiel #13
0
static GValueArray *
selection_float_invoker (GimpProcedure      *procedure,
                         Gimp               *gimp,
                         GimpContext        *context,
                         GimpProgress       *progress,
                         const GValueArray  *args,
                         GError            **error)
{
  gboolean success = TRUE;
  GValueArray *return_vals;
  GimpDrawable *drawable;
  gint32 offx;
  gint32 offy;
  GimpLayer *layer = NULL;

  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  offx = g_value_get_int (&args->values[1]);
  offy = g_value_get_int (&args->values[2]);

  if (success)
    {
      if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), error))
        {
          GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));

          layer = gimp_selection_float (gimp_image_get_mask (image),
                                        drawable, context, TRUE, offx, offy,
                                        error);
          if (! layer)
            success = FALSE;
        }
      else
        success = FALSE;
    }

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

  if (success)
    gimp_value_set_layer (&return_vals->values[1], layer);

  return return_vals;
}
Beispiel #14
0
gboolean
gimp_pdb_layer_is_text_layer (GimpLayer          *layer,
                              GimpPDBItemModify   modify,
                              GError            **error)
{
  g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (! gimp_item_is_text_layer (GIMP_ITEM (layer)))
    {
      g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
                   _("Layer '%s' (%d) cannot be used because it is not "
                     "a text layer"),
                   gimp_object_get_name (layer),
                   gimp_item_get_ID (GIMP_ITEM (layer)));

      return FALSE;
    }

  return gimp_pdb_item_is_attached (GIMP_ITEM (layer), NULL, modify, error);
}
Beispiel #15
0
static GimpValueArray *
image_select_item_invoker (GimpProcedure         *procedure,
                           Gimp                  *gimp,
                           GimpContext           *context,
                           GimpProgress          *progress,
                           const GimpValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  GimpImage *image;
  gint32 operation;
  GimpItem *item;

  image = gimp_value_get_image (gimp_value_array_index (args, 0), gimp);
  operation = g_value_get_enum (gimp_value_array_index (args, 1));
  item = gimp_value_get_item (gimp_value_array_index (args, 2), gimp);

  if (success)
    {
      if (gimp_pdb_item_is_attached (item, image, 0, error))
        {
          GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);

          gimp_item_to_selection (item, operation,
                                  pdb_context->antialias,
                                  pdb_context->feather,
                                  pdb_context->feather_radius_x,
                                  pdb_context->feather_radius_y);
        }
      else
        success = FALSE;
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
Beispiel #16
0
static GimpValueArray *
shear_invoker (GimpProcedure         *procedure,
               Gimp                  *gimp,
               GimpContext           *context,
               GimpProgress          *progress,
               const GimpValueArray  *args,
               GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gboolean interpolation;
  gint32 shear_type;
  gdouble magnitude;

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

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

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

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

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

          x += off_x;
          y += off_y;

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

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

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

          if (! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (gimp_image_get_mask (gimp_item_get_image (GIMP_ITEM (drawable)))))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix,
                                                    GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type, 3,
                                                    FALSE, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation, 3,
                                   FALSE, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

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

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

  return return_vals;
}
Beispiel #17
0
static GimpValueArray *
transform_2d_invoker (GimpProcedure         *procedure,
                      Gimp                  *gimp,
                      GimpContext           *context,
                      GimpProgress          *progress,
                      const GimpValueArray  *args,
                      GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpDrawable *drawable;
  gboolean interpolation;
  gdouble source_x;
  gdouble source_y;
  gdouble scale_x;
  gdouble scale_y;
  gdouble angle;
  gdouble dest_x;
  gdouble dest_y;

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

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

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

      if (success &&
          gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
        {
          GimpMatrix3           matrix;
          GimpInterpolationType interpolation_type = GIMP_INTERPOLATION_NONE;

          /* 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 (interpolation)
            interpolation_type = gimp->config->interpolation_type;

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

          if (! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
              ! gimp_channel_is_empty (gimp_image_get_mask (gimp_item_get_image (GIMP_ITEM (drawable)))))
            {
              if (! gimp_drawable_transform_affine (drawable, context,
                                                    &matrix, GIMP_TRANSFORM_FORWARD,
                                                    interpolation_type, 3,
                                                    FALSE, progress))
                {
                  success = FALSE;
                }
            }
          else
            {
              gimp_item_transform (GIMP_ITEM (drawable), context, &matrix,
                                   GIMP_TRANSFORM_FORWARD,
                                   interpolation, 3,
                                   FALSE, progress);
            }

          if (progress)
            gimp_progress_end (progress);
        }
    }

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

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

  return return_vals;
}