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.
This commit is contained in:
Ell 2017-06-16 20:15:56 -04:00
parent 40dccbddd8
commit c83f0e88af
4 changed files with 443 additions and 314 deletions

View File

@ -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,15 +522,56 @@ 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;
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 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;
/* don't push an undo here because undo will call us again */
@ -540,19 +583,8 @@ gimp_group_layer_translate (GimpItem *item,
{
GimpItem *child = list->data;
gimp_item_translate (child, offset_x, offset_y, push_undo);
}
mask = gimp_layer_get_mask (GIMP_LAYER (group));
if (mask)
{
gint off_x, off_y;
gimp_item_get_offset (item, &off_x, &off_y);
gimp_item_set_offset (GIMP_ITEM (mask), off_x, off_y);
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 *

View File

@ -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;
GimpLayer *layer = GIMP_LAYER (drawable);
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));
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)
{

View File

@ -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);
};

View File

@ -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,
@ -314,44 +317,6 @@ gimp_text_layer_rename (GimpItem *item,
return FALSE;
}
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,
@ -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 */