[gimp] app: add virtual transform/type-conversion functions to GimpLayer



commit c83f0e88afa5575d7b19873175a98c9b2622719c
Author: Ell <ell_se yahoo com>
Date:   Fri Jun 16 20:15:56 2017 -0400

    app: add virtual transform/type-conversion functions to GimpLayer
    
    The GimpLayer implementation of the GimpItem transform functions,
    and the GimpDrawable convert_type() function, apply their operation
    to both the layer and its mask.  The subclasses of GimpLayer --
    GimpGroupLayer and GimpTextLayer -- override some of these
    functions, providing their own logic for the layer part, and
    duplicating the mask part.
    
    Avoid this duplication by adding a set of virtual transform and
    type-conversion functions to GimpLayer.  Have the GimpLayer
    implementaion of the corresponding GimpItem and GimpDrawable
    functions use these functions to apply the operation to the layer,
    while taking care of the mask themselves.  Have GimpLayer's
    subclasses override the new virtual functions, instead of the
    GimpItem and GimpDrawable ones.
    
    Note that the existing implementation of convert_type() in
    GimpTextLayer neglected to convert the mask, hence text layer masks
    retained their old format after conversion.  This issue is fixed as
    a side effect of this commit.

 app/core/gimpgrouplayer.c |  269 ++++++++++++++-----------------------
 app/core/gimplayer.c      |  322 +++++++++++++++++++++++++++++++++------------
 app/core/gimplayer.h      |   67 ++++++++--
 app/text/gimptextlayer.c  |   97 +++++++-------
 4 files changed, 442 insertions(+), 313 deletions(-)
---
diff --git a/app/core/gimpgrouplayer.c b/app/core/gimpgrouplayer.c
index 2be8de7..331e872 100644
--- a/app/core/gimpgrouplayer.c
+++ b/app/core/gimpgrouplayer.c
@@ -96,48 +96,48 @@ static GimpItem      * gimp_group_layer_duplicate    (GimpItem        *item,
 static void            gimp_group_layer_convert      (GimpItem        *item,
                                                       GimpImage       *dest_image,
                                                       GType            old_type);
-static void            gimp_group_layer_translate    (GimpItem        *item,
+
+static gint64      gimp_group_layer_estimate_memsize (GimpDrawable      *drawable,
+                                                      GimpComponentType  component_type,
+                                                      gint               width,
+                                                      gint               height);
+
+static void            gimp_group_layer_translate    (GimpLayer       *layer,
                                                       gint             offset_x,
-                                                      gint             offset_y,
-                                                      gboolean         push_undo);
-static void            gimp_group_layer_scale        (GimpItem        *item,
+                                                      gint             offset_y);
+static void            gimp_group_layer_scale        (GimpLayer       *layer,
                                                       gint             new_width,
                                                       gint             new_height,
                                                       gint             new_offset_x,
                                                       gint             new_offset_y,
                                                       GimpInterpolationType  interp_type,
                                                       GimpProgress    *progress);
-static void            gimp_group_layer_resize       (GimpItem        *item,
+static void            gimp_group_layer_resize       (GimpLayer       *layer,
                                                       GimpContext     *context,
                                                       GimpFillType     fill_type,
                                                       gint             new_width,
                                                       gint             new_height,
                                                       gint             offset_x,
                                                       gint             offset_y);
-static void            gimp_group_layer_flip         (GimpItem        *item,
+static void            gimp_group_layer_flip         (GimpLayer       *layer,
                                                       GimpContext     *context,
                                                       GimpOrientationType flip_type,
                                                       gdouble          axis,
                                                       gboolean         clip_result);
-static void            gimp_group_layer_rotate       (GimpItem        *item,
+static void            gimp_group_layer_rotate       (GimpLayer       *layer,
                                                       GimpContext     *context,
                                                       GimpRotationType rotate_type,
                                                       gdouble          center_x,
                                                       gdouble          center_y,
                                                       gboolean         clip_result);
-static void            gimp_group_layer_transform    (GimpItem        *item,
+static void            gimp_group_layer_transform    (GimpLayer       *layer,
                                                       GimpContext     *context,
                                                       const GimpMatrix3 *matrix,
                                                       GimpTransformDirection direction,
                                                       GimpInterpolationType  interpolation_type,
                                                       GimpTransformResize clip_result,
-                                                      GimpProgress    *progress);
-
-static gint64      gimp_group_layer_estimate_memsize (GimpDrawable      *drawable,
-                                                      GimpComponentType  component_type,
-                                                      gint               width,
-                                                      gint               height);
-static void            gimp_group_layer_convert_type (GimpDrawable      *drawable,
+                                                      GimpProgress      *progress);
+static void            gimp_group_layer_convert_type (GimpLayer         *layer,
                                                       GimpImage         *dest_image,
                                                       const Babl        *new_format,
                                                       GimpColorProfile  *dest_profile,
@@ -201,6 +201,7 @@ gimp_group_layer_class_init (GimpGroupLayerClass *klass)
   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
   GimpDrawableClass *drawable_class    = GIMP_DRAWABLE_CLASS (klass);
+  GimpLayerClass    *layer_class       = GIMP_LAYER_CLASS (klass);
 
   object_class->set_property        = gimp_group_layer_set_property;
   object_class->get_property        = gimp_group_layer_get_property;
@@ -217,12 +218,6 @@ gimp_group_layer_class_init (GimpGroupLayerClass *klass)
   item_class->is_position_locked    = gimp_group_layer_is_position_locked;
   item_class->duplicate             = gimp_group_layer_duplicate;
   item_class->convert               = gimp_group_layer_convert;
-  item_class->translate             = gimp_group_layer_translate;
-  item_class->scale                 = gimp_group_layer_scale;
-  item_class->resize                = gimp_group_layer_resize;
-  item_class->flip                  = gimp_group_layer_flip;
-  item_class->rotate                = gimp_group_layer_rotate;
-  item_class->transform             = gimp_group_layer_transform;
 
   item_class->default_name          = _("Layer Group");
   item_class->rename_desc           = C_("undo-type", "Rename Layer Group");
@@ -234,7 +229,14 @@ gimp_group_layer_class_init (GimpGroupLayerClass *klass)
   item_class->transform_desc        = C_("undo-type", "Transform Layer Group");
 
   drawable_class->estimate_memsize  = gimp_group_layer_estimate_memsize;
-  drawable_class->convert_type      = gimp_group_layer_convert_type;
+
+  layer_class->translate            = gimp_group_layer_translate;
+  layer_class->scale                = gimp_group_layer_scale;
+  layer_class->resize               = gimp_group_layer_resize;
+  layer_class->flip                 = gimp_group_layer_flip;
+  layer_class->rotate               = gimp_group_layer_rotate;
+  layer_class->transform            = gimp_group_layer_transform;
+  layer_class->convert_type         = gimp_group_layer_convert_type;
 
   g_type_class_add_private (klass, sizeof (GimpGroupLayerPrivate));
 }
@@ -520,39 +522,69 @@ gimp_group_layer_convert (GimpItem  *item,
   GIMP_ITEM_CLASS (parent_class)->convert (item, dest_image, old_type);
 }
 
-static void
-gimp_group_layer_translate (GimpItem *item,
-                            gint      offset_x,
-                            gint      offset_y,
-                            gboolean  push_undo)
+static gint64
+gimp_group_layer_estimate_memsize (GimpDrawable      *drawable,
+                                   GimpComponentType  component_type,
+                                   gint               width,
+                                   gint               height)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (item);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GimpLayerMask         *mask;
+  GimpGroupLayerPrivate *private = GET_PRIVATE (drawable);
   GList                 *list;
-
-  /*  don't push an undo here because undo will call us again  */
-  gimp_group_layer_suspend_resize (group, FALSE);
+  GimpImageBaseType      base_type;
+  gint64                 memsize = 0;
 
   for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children));
        list;
        list = g_list_next (list))
     {
-      GimpItem *child = list->data;
+      GimpDrawable *child = list->data;
+      gint          child_width;
+      gint          child_height;
 
-      gimp_item_translate (child, offset_x, offset_y, push_undo);
+      child_width  = (gimp_item_get_width (GIMP_ITEM (child)) *
+                      width /
+                      gimp_item_get_width (GIMP_ITEM (drawable)));
+      child_height = (gimp_item_get_height (GIMP_ITEM (child)) *
+                      height /
+                      gimp_item_get_height (GIMP_ITEM (drawable)));
+
+      memsize += gimp_drawable_estimate_memsize (child,
+                                                 component_type,
+                                                 child_width,
+                                                 child_height);
     }
 
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
+  base_type = gimp_drawable_get_base_type (drawable);
 
-  if (mask)
-    {
-      gint off_x, off_y;
+  memsize += gimp_projection_estimate_memsize (base_type, component_type,
+                                               width, height);
+
+  return memsize +
+         GIMP_DRAWABLE_CLASS (parent_class)->estimate_memsize (drawable,
+                                                               component_type,
+                                                               width, height);
+}
+
+static void
+gimp_group_layer_translate (GimpLayer *layer,
+                            gint       offset_x,
+                            gint       offset_y)
+{
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
+  GList                 *list;
 
-      gimp_item_get_offset (item, &off_x, &off_y);
-      gimp_item_set_offset (GIMP_ITEM (mask), off_x, off_y);
+  /*  don't push an undo here because undo will call us again  */
+  gimp_group_layer_suspend_resize (group, FALSE);
+
+  for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children));
+       list;
+       list = g_list_next (list))
+    {
+      GimpItem *child = list->data;
 
-      gimp_viewable_invalidate_preview (GIMP_VIEWABLE (mask));
+      /*  don't push an undo here because undo will call us again  */
+      gimp_item_translate (child, offset_x, offset_y, FALSE);
     }
 
   /*  don't push an undo here because undo will call us again  */
@@ -560,7 +592,7 @@ gimp_group_layer_translate (GimpItem *item,
 }
 
 static void
-gimp_group_layer_scale (GimpItem              *item,
+gimp_group_layer_scale (GimpLayer             *layer,
                         gint                   new_width,
                         gint                   new_height,
                         gint                   new_offset_x,
@@ -568,9 +600,9 @@ gimp_group_layer_scale (GimpItem              *item,
                         GimpInterpolationType  interpolation_type,
                         GimpProgress          *progress)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (item);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GimpLayerMask         *mask;
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
+  GimpItem              *item    = GIMP_ITEM (layer);
   GList                 *list;
   gdouble                width_factor;
   gdouble                height_factor;
@@ -626,19 +658,11 @@ gimp_group_layer_scale (GimpItem              *item,
         }
     }
 
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
-
-  if (mask)
-    gimp_item_scale (GIMP_ITEM (mask),
-                     new_width, new_height,
-                     new_offset_x, new_offset_y,
-                     interpolation_type, progress);
-
   gimp_group_layer_resume_resize (group, TRUE);
 }
 
 static void
-gimp_group_layer_resize (GimpItem     *item,
+gimp_group_layer_resize (GimpLayer    *layer,
                          GimpContext  *context,
                          GimpFillType  fill_type,
                          gint          new_width,
@@ -646,14 +670,13 @@ gimp_group_layer_resize (GimpItem     *item,
                          gint          offset_x,
                          gint          offset_y)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (item);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GimpLayerMask         *mask;
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
   GList                 *list;
   gint                   x, y;
 
-  x = gimp_item_get_offset_x (item) - offset_x;
-  y = gimp_item_get_offset_y (item) - offset_y;
+  x = gimp_item_get_offset_x (GIMP_ITEM (group)) - offset_x;
+  y = gimp_item_get_offset_y (GIMP_ITEM (group)) - offset_y;
 
   gimp_group_layer_suspend_resize (group, TRUE);
 
@@ -689,9 +712,9 @@ gimp_group_layer_resize (GimpItem     *item,
                             child_width, child_height,
                             child_offset_x, child_offset_y);
         }
-      else if (gimp_item_is_attached (item))
+      else if (gimp_item_is_attached (GIMP_ITEM (group)))
         {
-          gimp_image_remove_layer (gimp_item_get_image (item),
+          gimp_image_remove_layer (gimp_item_get_image (GIMP_ITEM (group)),
                                    GIMP_LAYER (child),
                                    TRUE, NULL);
         }
@@ -701,25 +724,18 @@ gimp_group_layer_resize (GimpItem     *item,
         }
     }
 
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
-
-  if (mask)
-    gimp_item_resize (GIMP_ITEM (mask), context, GIMP_FILL_TRANSPARENT,
-                      new_width, new_height, offset_x, offset_y);
-
   gimp_group_layer_resume_resize (group, TRUE);
 }
 
 static void
-gimp_group_layer_flip (GimpItem            *item,
+gimp_group_layer_flip (GimpLayer           *layer,
                        GimpContext         *context,
                        GimpOrientationType  flip_type,
                        gdouble              axis,
                        gboolean             clip_result)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (item);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GimpLayerMask         *mask;
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
   GList                 *list;
 
   gimp_group_layer_suspend_resize (group, TRUE);
@@ -734,26 +750,19 @@ gimp_group_layer_flip (GimpItem            *item,
                       flip_type, axis, clip_result);
     }
 
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
-
-  if (mask)
-    gimp_item_flip (GIMP_ITEM (mask), context,
-                    flip_type, axis, clip_result);
-
   gimp_group_layer_resume_resize (group, TRUE);
 }
 
 static void
-gimp_group_layer_rotate (GimpItem         *item,
+gimp_group_layer_rotate (GimpLayer        *layer,
                          GimpContext      *context,
                          GimpRotationType  rotate_type,
                          gdouble           center_x,
                          gdouble           center_y,
                          gboolean          clip_result)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (item);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GimpLayerMask         *mask;
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
   GList                 *list;
 
   gimp_group_layer_suspend_resize (group, TRUE);
@@ -768,17 +777,11 @@ gimp_group_layer_rotate (GimpItem         *item,
                         rotate_type, center_x, center_y, clip_result);
     }
 
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
-
-  if (mask)
-    gimp_item_rotate (GIMP_ITEM (mask), context,
-                      rotate_type, center_x, center_y, clip_result);
-
   gimp_group_layer_resume_resize (group, TRUE);
 }
 
 static void
-gimp_group_layer_transform (GimpItem               *item,
+gimp_group_layer_transform (GimpLayer              *layer,
                             GimpContext            *context,
                             const GimpMatrix3      *matrix,
                             GimpTransformDirection  direction,
@@ -786,9 +789,8 @@ gimp_group_layer_transform (GimpItem               *item,
                             GimpTransformResize     clip_result,
                             GimpProgress           *progress)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (item);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GimpLayerMask         *mask;
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
   GList                 *list;
 
   gimp_group_layer_suspend_resize (group, TRUE);
@@ -805,60 +807,9 @@ gimp_group_layer_transform (GimpItem               *item,
                            clip_result, progress);
     }
 
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
-
-  if (mask)
-    gimp_item_transform (GIMP_ITEM (mask), context,
-                         matrix, direction,
-                         interpolation_type,
-                         clip_result, progress);
-
   gimp_group_layer_resume_resize (group, TRUE);
 }
 
-static gint64
-gimp_group_layer_estimate_memsize (GimpDrawable      *drawable,
-                                   GimpComponentType  component_type,
-                                   gint               width,
-                                   gint               height)
-{
-  GimpGroupLayerPrivate *private = GET_PRIVATE (drawable);
-  GList                 *list;
-  GimpImageBaseType      base_type;
-  gint64                 memsize = 0;
-
-  for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children));
-       list;
-       list = g_list_next (list))
-    {
-      GimpDrawable *child = list->data;
-      gint          child_width;
-      gint          child_height;
-
-      child_width  = (gimp_item_get_width (GIMP_ITEM (child)) *
-                      width /
-                      gimp_item_get_width (GIMP_ITEM (drawable)));
-      child_height = (gimp_item_get_height (GIMP_ITEM (child)) *
-                      height /
-                      gimp_item_get_height (GIMP_ITEM (drawable)));
-
-      memsize += gimp_drawable_estimate_memsize (child,
-                                                 component_type,
-                                                 child_width,
-                                                 child_height);
-    }
-
-  base_type = gimp_drawable_get_base_type (drawable);
-
-  memsize += gimp_projection_estimate_memsize (base_type, component_type,
-                                               width, height);
-
-  return memsize +
-         GIMP_DRAWABLE_CLASS (parent_class)->estimate_memsize (drawable,
-                                                               component_type,
-                                                               width, height);
-}
-
 static const Babl *
 get_projection_format (GimpProjectable   *projectable,
                        GimpImageBaseType  base_type,
@@ -882,7 +833,7 @@ get_projection_format (GimpProjectable   *projectable,
 }
 
 static void
-gimp_group_layer_convert_type (GimpDrawable     *drawable,
+gimp_group_layer_convert_type (GimpLayer        *layer,
                                GimpImage        *dest_image,
                                const Babl       *new_format,
                                GimpColorProfile *dest_profile,
@@ -891,9 +842,8 @@ gimp_group_layer_convert_type (GimpDrawable     *drawable,
                                gboolean          push_undo,
                                GimpProgress     *progress)
 {
-  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (drawable);
-  GimpGroupLayerPrivate *private = GET_PRIVATE (drawable);
-  GimpLayerMask         *mask;
+  GimpGroupLayer        *group   = GIMP_GROUP_LAYER (layer);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (layer);
   GeglBuffer            *buffer;
 
   if (push_undo)
@@ -908,37 +858,22 @@ gimp_group_layer_convert_type (GimpDrawable     *drawable,
    *  depth
    */
   private->convert_format =
-    get_projection_format (GIMP_PROJECTABLE (drawable),
+    get_projection_format (GIMP_PROJECTABLE (group),
                            gimp_babl_format_get_base_type (new_format),
                            gimp_babl_format_get_precision (new_format));
-  gimp_projectable_structure_changed (GIMP_PROJECTABLE (drawable));
+  gimp_projectable_structure_changed (GIMP_PROJECTABLE (group));
   gimp_pickable_flush (GIMP_PICKABLE (private->projection));
 
   buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (private->projection));
 
-  gimp_drawable_set_buffer_full (drawable,
+  gimp_drawable_set_buffer_full (GIMP_DRAWABLE (group),
                                  FALSE, NULL,
                                  buffer,
-                                 gimp_item_get_offset_x (GIMP_ITEM (drawable)),
-                                 gimp_item_get_offset_y (GIMP_ITEM (drawable)));
+                                 gimp_item_get_offset_x (GIMP_ITEM (group)),
+                                 gimp_item_get_offset_y (GIMP_ITEM (group)));
 
   /*  reset, the actual format is right now  */
   private->convert_format = NULL;
-
-  mask = gimp_layer_get_mask (GIMP_LAYER (group));
-
-  if (mask &&
-      gimp_babl_format_get_precision (new_format) !=
-      gimp_drawable_get_precision (GIMP_DRAWABLE (mask)))
-    {
-      gimp_drawable_convert_type (GIMP_DRAWABLE (mask), dest_image,
-                                  GIMP_GRAY,
-                                  gimp_babl_format_get_precision (new_format),
-                                  gimp_drawable_has_alpha (GIMP_DRAWABLE (mask)),
-                                  NULL,
-                                  layer_dither_type, mask_dither_type,
-                                  push_undo, progress);
-    }
 }
 
 static const Babl *
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index ff5a740..b8d61b4 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -210,6 +210,49 @@ static void    gimp_layer_srgb_to_pixel         (GimpPickable       *pickable,
                                                  const Babl         *format,
                                                  gpointer            pixel);
 
+static void       gimp_layer_real_translate     (GimpLayer          *layer,
+                                                 gint                offset_x,
+                                                 gint                offset_y);
+static void       gimp_layer_real_scale         (GimpLayer          *layer,
+                                                 gint                new_width,
+                                                 gint                new_height,
+                                                 gint                new_offset_x,
+                                                 gint                new_offset_y,
+                                                 GimpInterpolationType  interp_type,
+                                                 GimpProgress       *progress);
+static void       gimp_layer_real_resize        (GimpLayer          *layer,
+                                                 GimpContext        *context,
+                                                 GimpFillType        fill_type,
+                                                 gint                new_width,
+                                                 gint                new_height,
+                                                 gint                offset_x,
+                                                 gint                offset_y);
+static void       gimp_layer_real_flip          (GimpLayer          *layer,
+                                                 GimpContext        *context,
+                                                 GimpOrientationType flip_type,
+                                                 gdouble             axis,
+                                                 gboolean            clip_result);
+static void       gimp_layer_real_rotate        (GimpLayer          *layer,
+                                                 GimpContext        *context,
+                                                 GimpRotationType    rotate_type,
+                                                 gdouble             center_x,
+                                                 gdouble             center_y,
+                                                 gboolean            clip_result);
+static void       gimp_layer_real_transform     (GimpLayer          *layer,
+                                                 GimpContext        *context,
+                                                 const GimpMatrix3  *matrix,
+                                                 GimpTransformDirection direction,
+                                                 GimpInterpolationType  interpolation_type,
+                                                 GimpTransformResize clip_result,
+                                                 GimpProgress       *progress);
+static void       gimp_layer_real_convert_type  (GimpLayer          *layer,
+                                                 GimpImage          *dest_image,
+                                                 const Babl         *new_format,
+                                                 GimpColorProfile   *dest_profile,
+                                                 GeglDitherMethod    layer_dither_type,
+                                                 GeglDitherMethod    mask_dither_type,
+                                                 gboolean            push_undo,
+                                                 GimpProgress       *progress);
 static gboolean
           gimp_layer_real_get_excludes_backdrop (GimpLayer          *layer);
 
@@ -406,6 +449,13 @@ gimp_layer_class_init (GimpLayerClass *klass)
   klass->apply_mask_changed           = NULL;
   klass->edit_mask_changed            = NULL;
   klass->show_mask_changed            = NULL;
+  klass->translate                    = gimp_layer_real_translate;
+  klass->scale                        = gimp_layer_real_scale;
+  klass->resize                       = gimp_layer_real_resize;
+  klass->flip                         = gimp_layer_real_flip;
+  klass->rotate                       = gimp_layer_real_rotate;
+  klass->transform                    = gimp_layer_real_transform;
+  klass->convert_type                 = gimp_layer_real_convert_type;
   klass->get_excludes_backdrop        = gimp_layer_real_get_excludes_backdrop;
 
   g_object_class_install_property (object_class, PROP_OPACITY,
@@ -995,17 +1045,7 @@ gimp_layer_translate (GimpItem *item,
   if (push_undo)
     gimp_image_undo_push_item_displace (gimp_item_get_image (item), NULL, item);
 
-  /*  update the old region  */
-  gimp_drawable_update (GIMP_DRAWABLE (layer), 0, 0, -1, -1);
-
-  /*  invalidate the selection boundary because of a layer modification  */
-  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));
-
-  GIMP_ITEM_CLASS (parent_class)->translate (item, offset_x, offset_y,
-                                             push_undo);
-
-  /*  update the new region  */
-  gimp_drawable_update (GIMP_DRAWABLE (layer), 0, 0, -1, -1);
+  GIMP_LAYER_GET_CLASS (layer)->translate (layer, offset_x, offset_y);
 
   if (layer->mask)
     {
@@ -1029,9 +1069,9 @@ gimp_layer_scale (GimpItem              *item,
 {
   GimpLayer *layer = GIMP_LAYER (item);
 
-  GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
-                                         new_offset_x, new_offset_y,
-                                         interpolation_type, progress);
+  GIMP_LAYER_GET_CLASS (layer)->scale (layer, new_width, new_height,
+                                       new_offset_x, new_offset_y,
+                                       interpolation_type, progress);
 
   if (layer->mask)
     gimp_item_scale (GIMP_ITEM (layer->mask),
@@ -1051,15 +1091,9 @@ gimp_layer_resize (GimpItem     *item,
 {
   GimpLayer *layer  = GIMP_LAYER (item);
 
-  if (fill_type == GIMP_FILL_TRANSPARENT &&
-      ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
-    {
-      fill_type = GIMP_FILL_BACKGROUND;
-    }
-
-  GIMP_ITEM_CLASS (parent_class)->resize (item, context, fill_type,
-                                          new_width, new_height,
-                                          offset_x, offset_y);
+  GIMP_LAYER_GET_CLASS (layer)->resize (layer, context, fill_type,
+                                        new_width, new_height,
+                                        offset_x, offset_y);
 
   if (layer->mask)
     gimp_item_resize (GIMP_ITEM (layer->mask), context, GIMP_FILL_TRANSPARENT,
@@ -1075,8 +1109,8 @@ gimp_layer_flip (GimpItem            *item,
 {
   GimpLayer *layer = GIMP_LAYER (item);
 
-  GIMP_ITEM_CLASS (parent_class)->flip (item, context, flip_type, axis,
-                                        clip_result);
+  GIMP_LAYER_GET_CLASS (layer)->flip (layer, context, flip_type, axis,
+                                      clip_result);
 
   if (layer->mask)
     gimp_item_flip (GIMP_ITEM (layer->mask), context,
@@ -1093,9 +1127,9 @@ gimp_layer_rotate (GimpItem         *item,
 {
   GimpLayer *layer = GIMP_LAYER (item);
 
-  GIMP_ITEM_CLASS (parent_class)->rotate (item, context,
-                                          rotate_type, center_x, center_y,
-                                          clip_result);
+  GIMP_LAYER_GET_CLASS (layer)->rotate (layer, context,
+                                        rotate_type, center_x, center_y,
+                                        clip_result);
 
   if (layer->mask)
     gimp_item_rotate (GIMP_ITEM (layer->mask), context,
@@ -1113,15 +1147,10 @@ gimp_layer_transform (GimpItem               *item,
 {
   GimpLayer *layer = GIMP_LAYER (item);
 
-  /* FIXME: make interpolated transformations work on layers without alpha */
-  if (interpolation_type != GIMP_INTERPOLATION_NONE &&
-      ! gimp_drawable_has_alpha (GIMP_DRAWABLE (item)))
-    gimp_layer_add_alpha (layer);
-
-  GIMP_ITEM_CLASS (parent_class)->transform (item, context, matrix, direction,
-                                             interpolation_type,
-                                             clip_result,
-                                             progress);
+  GIMP_LAYER_GET_CLASS (layer)->transform (layer, context, matrix, direction,
+                                           interpolation_type,
+                                           clip_result,
+                                           progress);
 
   if (layer->mask)
     gimp_item_transform (GIMP_ITEM (layer->mask), context,
@@ -1190,57 +1219,12 @@ gimp_layer_convert_type (GimpDrawable     *drawable,
                          gboolean          push_undo,
                          GimpProgress     *progress)
 {
-  GimpLayer  *layer = GIMP_LAYER (drawable);
-  GeglBuffer *src_buffer;
-  GeglBuffer *dest_buffer;
-
-  if (layer_dither_type == GEGL_DITHER_NONE)
-    {
-      src_buffer = g_object_ref (gimp_drawable_get_buffer (drawable));
-    }
-  else
-    {
-      gint bits;
-
-      src_buffer =
-        gegl_buffer_new (GEGL_RECTANGLE (0, 0,
-                                         gimp_item_get_width  (GIMP_ITEM (drawable)),
-                                         gimp_item_get_height (GIMP_ITEM (drawable))),
-                         gimp_drawable_get_format (drawable));
-
-      bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
-              babl_format_get_n_components (new_format));
-
-      gimp_gegl_apply_dither (gimp_drawable_get_buffer (drawable),
-                              NULL, NULL,
-                              src_buffer, 1 << bits, layer_dither_type);
-    }
-
-  dest_buffer =
-    gegl_buffer_new (GEGL_RECTANGLE (0, 0,
-                                     gimp_item_get_width  (GIMP_ITEM (drawable)),
-                                     gimp_item_get_height (GIMP_ITEM (drawable))),
-                     new_format);
-
-  if (dest_profile)
-    {
-      GimpColorProfile *src_profile =
-        gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
+  GimpLayer *layer = GIMP_LAYER (drawable);
 
-      gimp_gegl_convert_color_profile (src_buffer,  NULL, src_profile,
-                                       dest_buffer, NULL, dest_profile,
-                                       GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
-                                       TRUE, progress);
-    }
-  else
-    {
-      gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE, dest_buffer, NULL);
-    }
-
-  gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
-
-  g_object_unref (src_buffer);
-  g_object_unref (dest_buffer);
+  GIMP_LAYER_GET_CLASS (layer)->convert_type (layer, dest_image, new_format,
+                                              dest_profile, layer_dither_type,
+                                              mask_dither_type, push_undo,
+                                              progress);
 
   if (layer->mask &&
       gimp_babl_format_get_precision (new_format) !=
@@ -1403,6 +1387,170 @@ gimp_layer_srgb_to_pixel (GimpPickable  *pickable,
   gimp_pickable_srgb_to_pixel (GIMP_PICKABLE (image), color, format, pixel);
 }
 
+static void
+gimp_layer_real_translate (GimpLayer *layer,
+                           gint       offset_x,
+                           gint       offset_y)
+{
+  /*  update the old region  */
+  gimp_drawable_update (GIMP_DRAWABLE (layer), 0, 0, -1, -1);
+
+  /*  invalidate the selection boundary because of a layer modification  */
+  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));
+
+  GIMP_ITEM_CLASS (parent_class)->translate (GIMP_ITEM (layer),
+                                             offset_x, offset_y,
+                                             FALSE);
+
+  /*  update the new region  */
+  gimp_drawable_update (GIMP_DRAWABLE (layer), 0, 0, -1, -1);
+}
+
+static void
+gimp_layer_real_scale (GimpLayer             *layer,
+                       gint                   new_width,
+                       gint                   new_height,
+                       gint                   new_offset_x,
+                       gint                   new_offset_y,
+                       GimpInterpolationType  interpolation_type,
+                       GimpProgress          *progress)
+{
+  GIMP_ITEM_CLASS (parent_class)->scale (GIMP_ITEM (layer),
+                                         new_width, new_height,
+                                         new_offset_x, new_offset_y,
+                                         interpolation_type, progress);
+}
+
+static void
+gimp_layer_real_resize (GimpLayer    *layer,
+                        GimpContext  *context,
+                        GimpFillType  fill_type,
+                        gint          new_width,
+                        gint          new_height,
+                        gint          offset_x,
+                        gint          offset_y)
+{
+  if (fill_type == GIMP_FILL_TRANSPARENT &&
+      ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
+    {
+      fill_type = GIMP_FILL_BACKGROUND;
+    }
+
+  GIMP_ITEM_CLASS (parent_class)->resize (GIMP_ITEM (layer),
+                                          context, fill_type,
+                                          new_width, new_height,
+                                          offset_x, offset_y);
+}
+
+static void
+gimp_layer_real_flip (GimpLayer           *layer,
+                      GimpContext         *context,
+                      GimpOrientationType  flip_type,
+                      gdouble              axis,
+                      gboolean             clip_result)
+{
+  GIMP_ITEM_CLASS (parent_class)->flip (GIMP_ITEM (layer),
+                                        context, flip_type, axis, clip_result);
+}
+
+static void
+gimp_layer_real_rotate (GimpLayer        *layer,
+                        GimpContext      *context,
+                        GimpRotationType  rotate_type,
+                        gdouble           center_x,
+                        gdouble           center_y,
+                        gboolean          clip_result)
+{
+  GIMP_ITEM_CLASS (parent_class)->rotate (GIMP_ITEM (layer),
+                                          context, rotate_type,
+                                          center_x, center_y,
+                                          clip_result);
+}
+
+static void
+gimp_layer_real_transform (GimpLayer              *layer,
+                           GimpContext            *context,
+                           const GimpMatrix3      *matrix,
+                           GimpTransformDirection  direction,
+                           GimpInterpolationType   interpolation_type,
+                           GimpTransformResize     clip_result,
+                           GimpProgress           *progress)
+{
+  /* FIXME: make interpolated transformations work on layers without alpha */
+  if (interpolation_type != GIMP_INTERPOLATION_NONE &&
+      ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
+    gimp_layer_add_alpha (layer);
+
+  GIMP_ITEM_CLASS (parent_class)->transform (GIMP_ITEM (layer),
+                                             context, matrix, direction,
+                                             interpolation_type,
+                                             clip_result,
+                                             progress);
+}
+
+static void
+gimp_layer_real_convert_type (GimpLayer        *layer,
+                              GimpImage        *dest_image,
+                              const Babl       *new_format,
+                              GimpColorProfile *dest_profile,
+                              GeglDitherMethod  layer_dither_type,
+                              GeglDitherMethod  mask_dither_type,
+                              gboolean          push_undo,
+                              GimpProgress     *progress)
+{
+  GimpDrawable *drawable = GIMP_DRAWABLE (layer);
+  GeglBuffer   *src_buffer;
+  GeglBuffer   *dest_buffer;
+
+  if (layer_dither_type == GEGL_DITHER_NONE)
+    {
+      src_buffer = g_object_ref (gimp_drawable_get_buffer (drawable));
+    }
+  else
+    {
+      gint bits;
+
+      src_buffer =
+        gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+                                         gimp_item_get_width  (GIMP_ITEM (layer)),
+                                         gimp_item_get_height (GIMP_ITEM (layer))),
+                         gimp_drawable_get_format (drawable));
+
+      bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
+              babl_format_get_n_components (new_format));
+
+      gimp_gegl_apply_dither (gimp_drawable_get_buffer (drawable),
+                              NULL, NULL,
+                              src_buffer, 1 << bits, layer_dither_type);
+    }
+
+  dest_buffer =
+    gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+                                     gimp_item_get_width  (GIMP_ITEM (layer)),
+                                     gimp_item_get_height (GIMP_ITEM (layer))),
+                     new_format);
+
+  if (dest_profile)
+    {
+      GimpColorProfile *src_profile =
+        gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
+
+      gimp_gegl_convert_color_profile (src_buffer,  NULL, src_profile,
+                                       dest_buffer, NULL, dest_profile,
+                                       GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
+                                       TRUE, progress);
+    }
+  else
+    {
+      gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE, dest_buffer, NULL);
+    }
+
+  gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
+
+  g_object_unref (src_buffer);
+  g_object_unref (dest_buffer);
+}
+
 static gboolean
 gimp_layer_real_get_excludes_backdrop (GimpLayer *layer)
 {
diff --git a/app/core/gimplayer.h b/app/core/gimplayer.h
index c222a5c..42a1246 100644
--- a/app/core/gimplayer.h
+++ b/app/core/gimplayer.h
@@ -67,20 +67,63 @@ struct _GimpLayerClass
   GimpDrawableClass  parent_class;
 
   /*  signals  */
-  void     (* opacity_changed)           (GimpLayer *layer);
-  void     (* mode_changed)              (GimpLayer *layer);
-  void     (* blend_space_changed)       (GimpLayer *layer);
-  void     (* composite_space_changed)   (GimpLayer *layer);
-  void     (* composite_mode_changed)    (GimpLayer *layer);
-  void     (* excludes_backdrop_changed) (GimpLayer *layer);
-  void     (* lock_alpha_changed)        (GimpLayer *layer);
-  void     (* mask_changed)              (GimpLayer *layer);
-  void     (* apply_mask_changed)        (GimpLayer *layer);
-  void     (* edit_mask_changed)         (GimpLayer *layer);
-  void     (* show_mask_changed)         (GimpLayer *layer);
+  void     (* opacity_changed)           (GimpLayer              *layer);
+  void     (* mode_changed)              (GimpLayer              *layer);
+  void     (* blend_space_changed)       (GimpLayer              *layer);
+  void     (* composite_space_changed)   (GimpLayer              *layer);
+  void     (* composite_mode_changed)    (GimpLayer              *layer);
+  void     (* excludes_backdrop_changed) (GimpLayer              *layer);
+  void     (* lock_alpha_changed)        (GimpLayer              *layer);
+  void     (* mask_changed)              (GimpLayer              *layer);
+  void     (* apply_mask_changed)        (GimpLayer              *layer);
+  void     (* edit_mask_changed)         (GimpLayer              *layer);
+  void     (* show_mask_changed)         (GimpLayer              *layer);
 
   /*  virtual functions  */
-  gboolean (* get_excludes_backdrop)     (GimpLayer *layer);
+  void     (* translate)                 (GimpLayer              *layer,
+                                          gint                    offset_x,
+                                          gint                    offset_y);
+  void     (* scale)                     (GimpLayer              *layer,
+                                          gint                    new_width,
+                                          gint                    new_height,
+                                          gint                    new_offset_x,
+                                          gint                    new_offset_y,
+                                          GimpInterpolationType   interpolation_type,
+                                          GimpProgress           *progress);
+  void     (* resize)                    (GimpLayer              *layer,
+                                          GimpContext            *context,
+                                          GimpFillType            fill_type,
+                                          gint                    new_width,
+                                          gint                    new_height,
+                                          gint                    offset_x,
+                                          gint                    offset_y);
+  void     (* flip)                      (GimpLayer              *layer,
+                                          GimpContext            *context,
+                                          GimpOrientationType     flip_type,
+                                          gdouble                 axis,
+                                          gboolean                clip_result);
+  void     (* rotate)                    (GimpLayer              *layer,
+                                          GimpContext            *context,
+                                          GimpRotationType        rotate_type,
+                                          gdouble                 center_x,
+                                          gdouble                 center_y,
+                                          gboolean                clip_result);
+  void     (* transform)                 (GimpLayer              *layer,
+                                          GimpContext            *context,
+                                          const GimpMatrix3      *matrix,
+                                          GimpTransformDirection  direction,
+                                          GimpInterpolationType   interpolation_type,
+                                          GimpTransformResize     clip_result,
+                                          GimpProgress           *progress);
+  void     (* convert_type)              (GimpLayer              *layer,
+                                          GimpImage              *dest_image,
+                                          const Babl             *new_format,
+                                          GimpColorProfile       *dest_profile,
+                                          GeglDitherMethod        layer_dither_type,
+                                          GeglDitherMethod        mask_dither_type,
+                                          gboolean                push_undo,
+                                          GimpProgress           *progress);
+  gboolean (* get_excludes_backdrop)     (GimpLayer              *layer);
 };
 
 
diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c
index cbd7338..2c1b39b 100644
--- a/app/text/gimptextlayer.c
+++ b/app/text/gimptextlayer.c
@@ -85,14 +85,6 @@ static gboolean   gimp_text_layer_rename         (GimpItem          *item,
                                                   const gchar       *undo_desc,
                                                   GError           **error);
 
-static void       gimp_text_layer_convert_type   (GimpDrawable      *drawable,
-                                                  GimpImage         *dest_image,
-                                                  const Babl        *new_format,
-                                                  GimpColorProfile  *dest_profile,
-                                                  GeglDitherMethod   layer_dither_type,
-                                                  GeglDitherMethod   mask_dither_type,
-                                                  gboolean           push_undo,
-                                                  GimpProgress      *progress);
 static void       gimp_text_layer_set_buffer     (GimpDrawable      *drawable,
                                                   gboolean           push_undo,
                                                   const gchar       *undo_desc,
@@ -107,6 +99,15 @@ static void       gimp_text_layer_push_undo      (GimpDrawable      *drawable,
                                                   gint               width,
                                                   gint               height);
 
+static void       gimp_text_layer_convert_type   (GimpLayer         *layer,
+                                                  GimpImage         *dest_image,
+                                                  const Babl        *new_format,
+                                                  GimpColorProfile  *dest_profile,
+                                                  GeglDitherMethod   layer_dither_type,
+                                                  GeglDitherMethod   mask_dither_type,
+                                                  gboolean           push_undo,
+                                                  GimpProgress      *progress);
+
 static void       gimp_text_layer_text_changed   (GimpTextLayer     *layer);
 static gboolean   gimp_text_layer_render         (GimpTextLayer     *layer);
 static void       gimp_text_layer_render_layout  (GimpTextLayer     *layer,
@@ -126,6 +127,7 @@ gimp_text_layer_class_init (GimpTextLayerClass *klass)
   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
   GimpDrawableClass *drawable_class    = GIMP_DRAWABLE_CLASS (klass);
+  GimpLayerClass    *layer_class       = GIMP_LAYER_CLASS (klass);
 
   object_class->finalize            = gimp_text_layer_finalize;
   object_class->get_property        = gimp_text_layer_get_property;
@@ -154,10 +156,11 @@ gimp_text_layer_class_init (GimpTextLayerClass *klass)
   item_class->rotate_desc           = _("Rotate Text Layer");
   item_class->transform_desc        = _("Transform Text Layer");
 
-  drawable_class->convert_type      = gimp_text_layer_convert_type;
   drawable_class->set_buffer        = gimp_text_layer_set_buffer;
   drawable_class->push_undo         = gimp_text_layer_push_undo;
 
+  layer_class->convert_type         = gimp_text_layer_convert_type;
+
   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_TEXT,
                            "text",
                            NULL, NULL,
@@ -315,44 +318,6 @@ gimp_text_layer_rename (GimpItem     *item,
 }
 
 static void
-gimp_text_layer_convert_type (GimpDrawable      *drawable,
-                              GimpImage         *dest_image,
-                              const Babl        *new_format,
-                              GimpColorProfile  *dest_profile,
-                              GeglDitherMethod   layer_dither_type,
-                              GeglDitherMethod   mask_dither_type,
-                              gboolean           push_undo,
-                              GimpProgress      *progress)
-{
-  GimpTextLayer *layer = GIMP_TEXT_LAYER (drawable);
-  GimpImage     *image = gimp_item_get_image (GIMP_ITEM (layer));
-
-  if (! layer->text   ||
-      layer->modified ||
-      layer_dither_type != GEGL_DITHER_NONE)
-    {
-      GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
-                                                        new_format,
-                                                        dest_profile,
-                                                        layer_dither_type,
-                                                        mask_dither_type,
-                                                        push_undo,
-                                                        progress);
-    }
-  else
-    {
-      if (push_undo)
-        gimp_image_undo_push_text_layer_convert (image, NULL, layer);
-
-      layer->convert_format = new_format;
-
-      gimp_text_layer_render (layer);
-
-      layer->convert_format = NULL;
-    }
-}
-
-static void
 gimp_text_layer_set_buffer (GimpDrawable *drawable,
                             gboolean      push_undo,
                             const gchar  *undo_desc,
@@ -411,6 +376,44 @@ gimp_text_layer_push_undo (GimpDrawable *drawable,
     }
 }
 
+static void
+gimp_text_layer_convert_type (GimpLayer         *layer,
+                              GimpImage         *dest_image,
+                              const Babl        *new_format,
+                              GimpColorProfile  *dest_profile,
+                              GeglDitherMethod   layer_dither_type,
+                              GeglDitherMethod   mask_dither_type,
+                              gboolean           push_undo,
+                              GimpProgress      *progress)
+{
+  GimpTextLayer *text_layer = GIMP_TEXT_LAYER (layer);
+  GimpImage     *image      = gimp_item_get_image (GIMP_ITEM (text_layer));
+
+  if (! text_layer->text   ||
+      text_layer->modified ||
+      layer_dither_type != GEGL_DITHER_NONE)
+    {
+      GIMP_LAYER_CLASS (parent_class)->convert_type (layer, dest_image,
+                                                     new_format,
+                                                     dest_profile,
+                                                     layer_dither_type,
+                                                     mask_dither_type,
+                                                     push_undo,
+                                                     progress);
+    }
+  else
+    {
+      if (push_undo)
+        gimp_image_undo_push_text_layer_convert (image, NULL, text_layer);
+
+      text_layer->convert_format = new_format;
+
+      gimp_text_layer_render (text_layer);
+
+      text_layer->convert_format = NULL;
+    }
+}
+
 
 /*  public functions  */
 


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