Gimp/app/core/gimplayermask.c
Michael Natterer d4933b3052 Bug 674160 - Redesign of "Lock panel"
Apply and heavily modify patch from remyDev which adds "lock position"
to GimpItem, similar to "lock content". Lock position disables all
sorts of translation and transform, from the GUI and the PDB.

Cleaned up some aspects of the lock content code as well because a
second instance of similar code always shows what went wrong the first
time.
2012-11-09 11:17:25 +01:00

244 lines
8.3 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <gegl.h>
#include "libgimpmath/gimpmath.h"
#include "core-types.h"
#include "gegl/gimp-babl.h"
#include "gimperror.h"
#include "gimpimage.h"
#include "gimpimage-undo-push.h"
#include "gimplayer.h"
#include "gimplayermask.h"
#include "gimp-intl.h"
static gboolean gimp_layer_mask_is_attached (const GimpItem *item);
static gboolean gimp_layer_mask_is_content_locked (const GimpItem *item);
static gboolean gimp_layer_mask_is_position_locked (const GimpItem *item);
static GimpItemTree * gimp_layer_mask_get_tree (GimpItem *item);
static GimpItem * gimp_layer_mask_duplicate (GimpItem *item,
GType new_type);
static gboolean gimp_layer_mask_rename (GimpItem *item,
const gchar *new_name,
const gchar *undo_desc,
GError **error);
static void gimp_layer_mask_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpImageBaseType new_base_type,
GimpPrecision new_precision,
gint layer_dither_type,
gint mask_dither_type,
gboolean push_undo);
G_DEFINE_TYPE (GimpLayerMask, gimp_layer_mask, GIMP_TYPE_CHANNEL)
#define parent_class gimp_layer_mask_parent_class
static void
gimp_layer_mask_class_init (GimpLayerMaskClass *klass)
{
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
GimpItemClass *item_class = GIMP_ITEM_CLASS (klass);
GimpDrawableClass *drawable_class = GIMP_DRAWABLE_CLASS (klass);
viewable_class->default_stock_id = "gimp-layer-mask";
item_class->is_attached = gimp_layer_mask_is_attached;
item_class->is_content_locked = gimp_layer_mask_is_content_locked;
item_class->is_position_locked = gimp_layer_mask_is_position_locked;
item_class->get_tree = gimp_layer_mask_get_tree;
item_class->duplicate = gimp_layer_mask_duplicate;
item_class->rename = gimp_layer_mask_rename;
item_class->translate_desc = C_("undo-type", "Move Layer Mask");
item_class->to_selection_desc = C_("undo-type", "Layer Mask to Selection");
drawable_class->convert_type = gimp_layer_mask_convert_type;
}
static void
gimp_layer_mask_init (GimpLayerMask *layer_mask)
{
layer_mask->layer = NULL;
}
static gboolean
gimp_layer_mask_is_content_locked (const GimpItem *item)
{
GimpLayerMask *mask = GIMP_LAYER_MASK (item);
GimpLayer *layer = gimp_layer_mask_get_layer (mask);
if (layer)
return gimp_item_is_content_locked (GIMP_ITEM (layer));
return FALSE;
}
static gboolean
gimp_layer_mask_is_position_locked (const GimpItem *item)
{
GimpLayerMask *mask = GIMP_LAYER_MASK (item);
GimpLayer *layer = gimp_layer_mask_get_layer (mask);
if (layer)
return gimp_item_is_position_locked (GIMP_ITEM (layer));
return FALSE;
}
static gboolean
gimp_layer_mask_is_attached (const GimpItem *item)
{
GimpLayerMask *mask = GIMP_LAYER_MASK (item);
GimpLayer *layer = gimp_layer_mask_get_layer (mask);
return (GIMP_IS_IMAGE (gimp_item_get_image (item)) &&
GIMP_IS_LAYER (layer) &&
gimp_layer_get_mask (layer) == mask &&
gimp_item_is_attached (GIMP_ITEM (layer)));
}
static GimpItemTree *
gimp_layer_mask_get_tree (GimpItem *item)
{
return NULL;
}
static GimpItem *
gimp_layer_mask_duplicate (GimpItem *item,
GType new_type)
{
GimpItem *new_item;
g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type);
return new_item;
}
static gboolean
gimp_layer_mask_rename (GimpItem *item,
const gchar *new_name,
const gchar *undo_desc,
GError **error)
{
/* reject renaming, layer masks are always named "<layer name> mask" */
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("Cannot rename layer masks."));
return FALSE;
}
static void
gimp_layer_mask_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpImageBaseType new_base_type,
GimpPrecision new_precision,
gint layer_dither_type,
gint mask_dither_type,
gboolean push_undo)
{
new_format = gimp_babl_mask_format (new_precision);
GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
new_format,
new_base_type,
new_precision,
layer_dither_type,
mask_dither_type,
push_undo);
}
GimpLayerMask *
gimp_layer_mask_new (GimpImage *image,
gint width,
gint height,
const gchar *name,
const GimpRGB *color)
{
GimpLayerMask *layer_mask;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
g_return_val_if_fail (color != NULL, NULL);
layer_mask =
GIMP_LAYER_MASK (gimp_drawable_new (GIMP_TYPE_LAYER_MASK,
image, name,
0, 0, width, height,
gimp_image_get_mask_format (image)));
/* set the layer_mask color and opacity */
gimp_channel_set_color (GIMP_CHANNEL (layer_mask), color, FALSE);
gimp_channel_set_show_masked (GIMP_CHANNEL (layer_mask), TRUE);
/* selection mask variables */
GIMP_CHANNEL (layer_mask)->x2 = width;
GIMP_CHANNEL (layer_mask)->y2 = height;
return layer_mask;
}
void
gimp_layer_mask_set_layer (GimpLayerMask *layer_mask,
GimpLayer *layer)
{
g_return_if_fail (GIMP_IS_LAYER_MASK (layer_mask));
g_return_if_fail (layer == NULL || GIMP_IS_LAYER (layer));
layer_mask->layer = layer;
if (layer)
{
gchar *mask_name;
gint offset_x;
gint offset_y;
gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
gimp_item_set_offset (GIMP_ITEM (layer_mask), offset_x, offset_y);
mask_name = g_strdup_printf (_("%s mask"), gimp_object_get_name (layer));
gimp_object_take_name (GIMP_OBJECT (layer_mask), mask_name);
}
}
GimpLayer *
gimp_layer_mask_get_layer (const GimpLayerMask *layer_mask)
{
g_return_val_if_fail (GIMP_IS_LAYER_MASK (layer_mask), NULL);
return layer_mask->layer;
}