diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index e8c72c595e25aafaa295967a074978b21b5cc82b..9b190a9036c4c3f8de7688f963befd0b2687f9a7 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -48,6 +48,8 @@
#include "core/gimplayerpropundo.h"
#include "core/gimplayer-floating-selection.h"
#include "core/gimplayer-new.h"
+#include "core/gimplayermask.h"
+#include "core/gimplayervectormask.h"
#include "core/gimplink.h"
#include "core/gimplinklayer.h"
#include "core/gimplist.h"
@@ -152,6 +154,7 @@ static void layers_add_mask_callback (GtkWidget *dialog,
GList *layers,
GimpAddMaskType add_mask_type,
GimpChannel *channel,
+ GimpPath *path,
gboolean invert,
gboolean edit_mask,
gpointer user_data);
@@ -304,7 +307,8 @@ layers_edit_vector_cmd_callback (GimpAction *action,
}
if (GIMP_IS_PATH_TOOL (active_tool))
- gimp_path_tool_set_path (GIMP_PATH_TOOL (active_tool), GIMP_VECTOR_LAYER (layer), NULL);
+ gimp_path_tool_set_path (GIMP_PATH_TOOL (active_tool),
+ GIMP_RASTERIZABLE (layer), NULL);
}
void
@@ -2604,6 +2608,7 @@ layers_add_mask_callback (GtkWidget *dialog,
GList *layers,
GimpAddMaskType add_mask_type,
GimpChannel *channel,
+ GimpPath *path,
gboolean invert,
gboolean edit_mask,
gpointer user_data)
@@ -2626,21 +2631,51 @@ layers_add_mask_callback (GtkWidget *dialog,
for (iter = layers; iter; iter = iter->next)
{
- mask = gimp_layer_create_mask (iter->data,
- config->layer_add_mask_type,
- channel);
+ if (! path)
+ {
+ mask = gimp_layer_create_mask (iter->data,
+ config->layer_add_mask_type,
+ channel);
- if (config->layer_add_mask_invert)
- gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
+ if (config->layer_add_mask_invert)
+ gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
- if (! gimp_layer_add_mask (iter->data, mask, edit_mask, TRUE, &error))
+ if (! gimp_layer_add_mask (iter->data, mask, edit_mask, TRUE,
+ &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_object_unref (mask);
+ g_clear_error (&error);
+ return;
+ }
+ }
+ else
{
- gimp_message_literal (image->gimp,
- G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
- error->message);
- g_object_unref (mask);
- g_clear_error (&error);
- return;
+ GimpImage *image;
+ GimpItem *item = GIMP_ITEM (iter->data);
+ GimpLayerVectorMask *vector_mask;
+
+ image = gimp_item_get_image (item);
+
+ vector_mask = gimp_layer_vector_mask_new (image, path,
+ gimp_item_get_width (item),
+ gimp_item_get_height (item),
+ "Vector Mask");
+
+ if (! gimp_layer_add_mask (iter->data, GIMP_LAYER_MASK (vector_mask),
+ edit_mask, TRUE, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_object_unref (vector_mask);
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_layer_vector_mask_render (vector_mask);
}
}
diff --git a/app/core/core-types.h b/app/core/core-types.h
index 990be94727e1428039e7b931f0c845af12dccae1..5e623bd2fbec3aa77d954147cc9324ea3d3ce037 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -166,6 +166,7 @@ typedef struct _GimpDrawableFilterMask GimpDrawableFilterMask;
typedef struct _GimpRasterizable GimpRasterizable;
typedef struct _GimpChannel GimpChannel;
typedef struct _GimpLayerMask GimpLayerMask;
+typedef struct _GimpLayerVectorMask GimpLayerVectorMask;
typedef struct _GimpSelection GimpSelection;
typedef struct _GimpLayer GimpLayer;
typedef struct _GimpGroupLayer GimpGroupLayer;
diff --git a/app/core/gimplayervectormask.c b/app/core/gimplayervectormask.c
new file mode 100644
index 0000000000000000000000000000000000000000..4836aeb3b7f13f651081454e90243610f47076c1
--- /dev/null
+++ b/app/core/gimplayervectormask.c
@@ -0,0 +1,230 @@
+/* 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 .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "libgimpmath/gimpmath.h"
+
+#include "core-types.h"
+
+#include "gegl/gimp-babl.h"
+
+#include "core/gimp.h"
+#include "core/gimpdrawable-fill.h"
+#include "core/gimpfilloptions.h"
+#include "core/gimpimage.h"
+#include "core/gimpselection.h"
+#include "core/gimprasterizable.h"
+
+#include "path/gimppath.h"
+
+#include "gimperror.h"
+#include "gimpimage.h"
+#include "gimplayer.h"
+#include "gimplayervectormask.h"
+
+#include "gimp-intl.h"
+
+static void gimp_layer_vector_mask_rasterizable_iface_init
+ (GimpRasterizableInterface *iface);
+
+static void gimp_layer_vector_mask_set_rasterized (GimpRasterizable *rasterizable,
+ gboolean rasterized);
+
+
+static void gimp_layer_vector_mask_render_path (GimpLayerVectorMask *layer_mask);
+
+G_DEFINE_TYPE_WITH_CODE (GimpLayerVectorMask, gimp_layer_vector_mask, GIMP_TYPE_LAYER_MASK,
+ G_IMPLEMENT_INTERFACE (GIMP_TYPE_RASTERIZABLE,
+ gimp_layer_vector_mask_rasterizable_iface_init))
+
+#define parent_class gimp_layer_vector_mask_parent_class
+
+
+static void
+gimp_layer_vector_mask_class_init (GimpLayerVectorMaskClass *klass)
+{
+ GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
+ GimpItemClass *item_class = GIMP_ITEM_CLASS (klass);
+
+ viewable_class->default_icon_name = "gimp-tool-path";
+ viewable_class->default_name = _("Vector Mask");
+
+ item_class->translate_desc = C_("undo-type", "Move Layer Vector Mask");
+ item_class->to_selection_desc = C_("undo-type", "Layer Vector Mask to Selection");
+}
+
+static void
+gimp_layer_vector_mask_init (GimpLayerVectorMask *layer_mask)
+{
+ layer_mask->layer = NULL;
+ layer_mask->path = NULL;
+}
+
+static void
+gimp_layer_vector_mask_rasterizable_iface_init (GimpRasterizableInterface *iface)
+{
+ iface->set_rasterized = gimp_layer_vector_mask_set_rasterized;
+}
+
+static void
+gimp_layer_vector_mask_set_rasterized (GimpRasterizable *rasterizable,
+ gboolean rasterized)
+{
+ if (! rasterized)
+ gimp_layer_vector_mask_render (GIMP_LAYER_VECTOR_MASK (rasterizable));
+}
+
+
+gboolean
+gimp_layer_vector_mask_render (GimpLayerVectorMask *layer_mask)
+{
+ GimpDrawable *drawable = GIMP_DRAWABLE (layer_mask);
+ GimpLayer *layer = NULL;
+ GeglBuffer *buffer = NULL;
+ GeglColor *color = NULL;
+ GimpItem *item = GIMP_ITEM (layer_mask);
+ GimpImage *image = gimp_item_get_image (item);
+ gint x = 0;
+ gint y = 0;
+ gint width = gimp_image_get_width (image);
+ gint height = gimp_image_get_height (image);
+
+ g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
+
+ layer = gimp_layer_mask_get_layer (GIMP_LAYER_MASK (layer_mask));
+
+ g_object_freeze_notify (G_OBJECT (drawable));
+
+ /* Resize layer according to path size */
+ gimp_item_bounds (GIMP_ITEM (layer), &x, &y, &width, &height);
+
+ buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
+ gimp_drawable_get_format (drawable));
+ gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
+ g_object_unref (buffer);
+
+ gimp_item_set_offset (GIMP_ITEM (layer_mask), x, y);
+
+ /* make the layer background transparent */
+ color = gegl_color_new ("black");
+ gimp_channel_set_color (GIMP_CHANNEL (layer_mask), color, FALSE);
+ g_clear_object (&color);
+
+ /* render path to the layer */
+ gimp_layer_vector_mask_render_path (layer_mask);
+
+ g_object_thaw_notify (G_OBJECT (drawable));
+
+ return TRUE;
+}
+
+static void
+gimp_layer_vector_mask_render_path (GimpLayerVectorMask *layer_mask)
+{
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer_mask));
+ GimpChannel *selection = gimp_image_get_mask (image);
+ GimpFillOptions *fill_options;
+ GeglColor *fill_color;
+ GList *drawables;
+
+ /* Don't mask these fill/stroke operations */
+ gimp_selection_suspend (GIMP_SELECTION (selection));
+
+ fill_color = gegl_color_new ("white");
+
+ fill_options = gimp_fill_options_new (image->gimp, NULL, FALSE);
+ gimp_fill_options_set_style (GIMP_FILL_OPTIONS (fill_options),
+ GIMP_FILL_STYLE_FG_COLOR);
+ gimp_context_set_foreground (GIMP_CONTEXT (fill_options),
+ fill_color);
+
+ /* Fill the path object onto the layer */
+ gimp_drawable_fill_path (GIMP_DRAWABLE (layer_mask),
+ fill_options,
+ layer_mask->path, FALSE, NULL);
+
+ drawables = g_list_prepend (NULL, GIMP_DRAWABLE (layer_mask));
+
+ g_list_free (drawables);
+
+ /*gimp_rasterizable_auto_rename (GIMP_RASTERIZABLE (layer_mask),
+ GIMP_OBJECT (layer_mask->path),
+ NULL);*/
+
+ gimp_selection_resume (GIMP_SELECTION (selection));
+
+ g_clear_object (&fill_color);
+ g_object_unref (fill_options);
+}
+
+/* Public Functions */
+
+GimpLayerVectorMask *
+gimp_layer_vector_mask_new (GimpImage *image,
+ GimpPath *path,
+ gint width,
+ gint height,
+ const gchar *name)
+{
+ GimpLayerVectorMask *layer_mask;
+
+ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+ g_return_val_if_fail (GIMP_IS_PATH (path), NULL);
+ g_return_val_if_fail (width > 0, NULL);
+ g_return_val_if_fail (height > 0, NULL);
+
+ layer_mask =
+ GIMP_LAYER_VECTOR_MASK (gimp_drawable_new (GIMP_TYPE_LAYER_VECTOR_MASK,
+ image, name,
+ 0, 0, width, height,
+ gimp_image_get_mask_format (image)));
+
+ layer_mask->path = path;
+
+ /* set the layer_mask opacity */
+ 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_vector_mask_set_path (GimpLayerVectorMask *layer_mask,
+ GimpPath *path)
+{
+ g_return_if_fail (GIMP_IS_LAYER_MASK (layer_mask));
+ g_return_if_fail (GIMP_IS_PATH (path));
+
+ layer_mask->path = path;
+
+ gimp_layer_vector_mask_render (layer_mask);
+}
+
+GimpPath *
+gimp_layer_vector_mask_get_path (GimpLayerVectorMask *layer_mask)
+{
+ g_return_val_if_fail (GIMP_IS_LAYER_VECTOR_MASK (layer_mask), NULL);
+
+ return layer_mask->path;
+}
diff --git a/app/core/gimplayervectormask.h b/app/core/gimplayervectormask.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c31d12f0b52bbcb86e50e7de5db6310d4d6f2c1
--- /dev/null
+++ b/app/core/gimplayervectormask.h
@@ -0,0 +1,59 @@
+/* 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 .
+ */
+
+#pragma once
+
+#include "gimplayermask.h"
+
+
+#define GIMP_TYPE_LAYER_VECTOR_MASK (gimp_layer_vector_mask_get_type ())
+#define GIMP_LAYER_VECTOR_MASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_LAYER_VECTOR_MASK, GimpLayerVectorMask))
+#define GIMP_LAYER_VECTOR_MASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_LAYER_VECTOR_MASK, GimpLayerVectorMaskClass))
+#define GIMP_IS_LAYER_VECTOR_MASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_LAYER_VECTOR_MASK))
+#define GIMP_IS_LAYER_VECTOR_MASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_LAYER_VECTOR_MASK))
+#define GIMP_LAYER_VECTOR_MASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_LAYER_VECTOR_MASK, GimpLayerVectorMaskClass))
+
+
+typedef struct _GimpLayerVectorMaskClass GimpLayerVectorMaskClass;
+
+struct _GimpLayerVectorMask
+{
+ GimpLayerMask parent_instance;
+
+ GimpLayer *layer;
+ GimpPath *path;
+};
+
+struct _GimpLayerVectorMaskClass
+{
+ GimpLayerMaskClass parent_class;
+};
+
+
+GType gimp_layer_vector_mask_get_type (void) G_GNUC_CONST;
+
+GimpLayerVectorMask * gimp_layer_vector_mask_new (GimpImage *image,
+ GimpPath *path,
+ gint width,
+ gint height,
+ const gchar *name);
+
+gboolean gimp_layer_vector_mask_render (GimpLayerVectorMask *layer_mask);
+
+void gimp_layer_vector_mask_set_path (GimpLayerVectorMask *layer_mask,
+ GimpPath *layer);
+GimpPath * gimp_layer_vector_mask_get_path (GimpLayerVectorMask *layer_mask);
diff --git a/app/core/meson.build b/app/core/meson.build
index 656d36a9c2a03d094d18c08e2d81fc3faa4e397f..0dad5e50af119d16b6354c107566f6fa6a6139ed 100644
--- a/app/core/meson.build
+++ b/app/core/meson.build
@@ -191,6 +191,7 @@ libappcore_sources = [
'gimplayermaskpropundo.c',
'gimplayermaskundo.c',
'gimplayerpropundo.c',
+ 'gimplayervectormask.c',
'gimplayerstack.c',
'gimplayerundo.c',
'gimplineart.c',
diff --git a/app/dialogs/layer-add-mask-dialog.c b/app/dialogs/layer-add-mask-dialog.c
index 1556fc8d4d4e140412bbf4716cc4585909eea89a..a48cc8b5c1cf4dc6e8f5eb5c08ca420f25d6409b 100644
--- a/app/dialogs/layer-add-mask-dialog.c
+++ b/app/dialogs/layer-add-mask-dialog.c
@@ -31,6 +31,8 @@
#include "core/gimpimage.h"
#include "core/gimplayer.h"
+#include "path/gimppath.h"
+
#include "widgets/gimpcontainercombobox.h"
#include "widgets/gimpcontainerview.h"
#include "widgets/gimphelp-ids.h"
@@ -49,10 +51,13 @@ struct _LayerAddMaskDialog
GList *layers;
GimpAddMaskType add_mask_type;
GimpChannel *channel;
+ GimpPath *path;
gboolean invert;
gboolean edit_mask;
GimpAddMaskCallback callback;
gpointer user_data;
+
+ GtkWidget *stack;
};
@@ -64,6 +69,8 @@ static void layer_add_mask_dialog_response (GtkWidget *dialog
LayerAddMaskDialog *private);
static void layer_add_mask_dialog_channel_selected (GimpContainerView *view,
LayerAddMaskDialog *private);
+static void layer_add_mask_dialog_path_selected (GimpContainerView *view,
+ LayerAddMaskDialog *private);
/* public functions */
@@ -80,14 +87,18 @@ layer_add_mask_dialog_new (GList *layers,
{
LayerAddMaskDialog *private;
GtkWidget *dialog;
+ GtkWidget *main_vbox;
GtkWidget *vbox;
GtkWidget *hbox;
+ GtkWidget *switcher;
GtkWidget *frame;
GtkWidget *combo;
GtkWidget *button;
GimpImage *image;
GimpChannel *channel;
GList *channels;
+ GimpPath *path;
+ GList *paths;
gchar *title;
gchar *desc;
gint n_layers = g_list_length (layers);
@@ -128,9 +139,9 @@ layer_add_mask_dialog_new (GList *layers,
g_free (desc);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
- GTK_RESPONSE_OK,
- GTK_RESPONSE_CANCEL,
- -1);
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
@@ -141,12 +152,24 @@ layer_add_mask_dialog_new (GList *layers,
G_CALLBACK (layer_add_mask_dialog_response),
private);
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
- vbox, TRUE, TRUE, 0);
- gtk_widget_show (vbox);
+ main_vbox, TRUE, TRUE, 0);
+ gtk_widget_set_visible (main_vbox, TRUE);
+ /* Switcher */
+ switcher = gtk_stack_switcher_new ();
+ gtk_box_pack_start (GTK_BOX (main_vbox), switcher, TRUE, TRUE, 0);
+ gtk_widget_set_visible (switcher, TRUE);
+
+ private->stack = gtk_stack_new ();
+ gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (switcher),
+ GTK_STACK (private->stack));
+ gtk_box_pack_start (GTK_BOX (main_vbox), private->stack, TRUE, TRUE, 0);
+ gtk_widget_set_visible (private->stack, TRUE);
+
+ /* Raster masks */
frame =
gimp_enum_radio_frame_new (GIMP_TYPE_ADD_MASK_TYPE,
gtk_label_new (_("Initialize Layer Mask to:")),
@@ -155,8 +178,9 @@ layer_add_mask_dialog_new (GList *layers,
&button);
gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (button),
private->add_mask_type);
-
- gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+ gtk_stack_add_titled (GTK_STACK (private->stack),
+ frame, "raster-mask",
+ _("Raster"));
gtk_widget_show (frame);
image = gimp_item_get_image (GIMP_ITEM (layers->data));
@@ -184,6 +208,38 @@ layer_add_mask_dialog_new (GList *layers,
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo),
GIMP_VIEWABLE (channel));
+ /* Vector masks */
+ frame = gimp_frame_new (_("Initialize Layer Mask to:"));
+ gtk_stack_add_titled (GTK_STACK (private->stack),
+ frame,
+ "vector-mask",
+ _("Vector"));
+ gtk_widget_set_visible (frame, TRUE);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_widget_set_visible (vbox, TRUE);
+
+ combo = gimp_container_combo_box_new (gimp_image_get_paths (image),
+ context,
+ GIMP_VIEW_SIZE_SMALL, 1);
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+ gtk_widget_set_visible (combo, TRUE);
+
+ g_signal_connect (combo, "selection-changed",
+ G_CALLBACK (layer_add_mask_dialog_path_selected),
+ private);
+
+ paths = gimp_image_get_selected_paths (image);
+ if (paths)
+ path = paths->data;
+ else
+ path = GIMP_PATH (gimp_container_get_first_child (gimp_image_get_paths (image)));
+
+ gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo),
+ GIMP_VIEWABLE (path));
+
+ /* General options */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
@@ -226,20 +282,40 @@ layer_add_mask_dialog_response (GtkWidget *dialog,
if (response_id == GTK_RESPONSE_OK)
{
GimpImage *image = gimp_item_get_image (GIMP_ITEM (private->layers->data));
+ GimpPath *path = NULL;
- if (private->add_mask_type == GIMP_ADD_MASK_CHANNEL &&
- ! private->channel)
+ if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (private->stack)),
+ "raster-mask") == 0)
{
- gimp_message_literal (image->gimp,
- G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
- _("Please select a channel first"));
- return;
+ if (private->add_mask_type == GIMP_ADD_MASK_CHANNEL &&
+ ! private->channel)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
+ _("Please select a channel first"));
+ return;
+ }
+ }
+ else
+ {
+ if (! private->path)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
+ _("Please select a path first"));
+ return;
+ }
+ else
+ {
+ path = private->path;
+ }
}
private->callback (dialog,
private->layers,
private->add_mask_type,
private->channel,
+ path,
private->invert,
private->edit_mask,
private->user_data);
@@ -256,3 +332,10 @@ layer_add_mask_dialog_channel_selected (GimpContainerView *view,
{
private->channel = GIMP_CHANNEL (gimp_container_view_get_1_selected (view));
}
+
+static void
+layer_add_mask_dialog_path_selected (GimpContainerView *view,
+ LayerAddMaskDialog *private)
+{
+ private->path = GIMP_PATH (gimp_container_view_get_1_selected (view));
+}
diff --git a/app/dialogs/layer-add-mask-dialog.h b/app/dialogs/layer-add-mask-dialog.h
index a34be60f34549790f0a257c44d510647ac8461ef..7aacb91289f3bc011d0068d484ce2f6ec82eae41 100644
--- a/app/dialogs/layer-add-mask-dialog.h
+++ b/app/dialogs/layer-add-mask-dialog.h
@@ -22,6 +22,7 @@ typedef void (* GimpAddMaskCallback) (GtkWidget *dialog,
GList *layers,
GimpAddMaskType add_mask_type,
GimpChannel *channel,
+ GimpPath *path,
gboolean invert,
gboolean edit_mask,
gpointer user_data);
diff --git a/app/tools/gimppathtool.c b/app/tools/gimppathtool.c
index 3564a79d99608c319a67598277a83d571e424e1d..47307b909654db8a29ae85cc0205aa87b28c6bec 100644
--- a/app/tools/gimppathtool.c
+++ b/app/tools/gimppathtool.c
@@ -35,6 +35,9 @@
#include "core/gimpimage-pick-item.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
+#include "core/gimplayer.h"
+#include "core/gimplayermask.h"
+#include "core/gimplayervectormask.h"
#include "core/gimprasterizable.h"
#include "core/gimpstrokeoptions.h"
#include "core/gimptoolinfo.h"
@@ -153,14 +156,14 @@ static void gimp_path_tool_vector_layer_path_changed
static void gimp_path_tool_vector_change_notify
(GObject *options,
const GParamSpec *pspec,
- GimpVectorLayer *layer);
+ GimpRasterizable *layer);
-static void gimp_path_tool_layer_rasterized (GimpVectorLayer *layer,
+static void gimp_path_tool_layer_rasterized (GimpRasterizable *layer,
gboolean is_rasterized,
GimpPathTool *tool);
static void gimp_path_tool_set_layer (GimpPathTool *path_tool,
- GimpVectorLayer *vector_layer);
+ GimpRasterizable *layer);
static void gimp_path_tool_confirm_dialog (GimpPathTool *path_tool,
GimpVectorLayer *layer);
@@ -532,22 +535,31 @@ gimp_path_tool_image_changed (GimpPathTool *path_tool,
static void
gimp_path_tool_image_selected_layers_changed (GimpPathTool *path_tool)
{
- GList *current_layers = NULL;
+ GList *current_layers = NULL;
+ GimpLayerMask *mask = NULL;
if (path_tool->current_image)
current_layers = gimp_image_get_selected_layers (path_tool->current_image);
/* If we've selected a single vector layer, make its path editable */
if (current_layers &&
- g_list_length (current_layers) == 1 &&
- GIMP_IS_VECTOR_LAYER (GIMP_ITEM (current_layers->data)))
+ g_list_length (current_layers) == 1)
{
- GimpVectorLayer *vector_layer = current_layers->data;
+ mask = gimp_layer_get_mask (GIMP_LAYER (current_layers->data));
- if (gimp_item_is_vector_layer (GIMP_ITEM (current_layers->data)))
- gimp_path_tool_set_layer (path_tool, vector_layer);
- else
- gimp_path_tool_confirm_dialog (path_tool, vector_layer);
+ if (GIMP_IS_VECTOR_LAYER (GIMP_ITEM (current_layers->data)))
+ {
+ GimpVectorLayer *vector_layer = current_layers->data;
+
+ if (gimp_item_is_vector_layer (GIMP_ITEM (current_layers->data)))
+ gimp_path_tool_set_layer (path_tool, GIMP_RASTERIZABLE (vector_layer));
+ else
+ gimp_path_tool_confirm_dialog (path_tool, vector_layer);
+ }
+ else if (mask && GIMP_IS_LAYER_VECTOR_MASK (mask))
+ {
+ gimp_path_tool_set_layer (path_tool, GIMP_RASTERIZABLE (mask));
+ }
}
else
{
@@ -626,6 +638,10 @@ gimp_path_tool_tool_path_end_change (GimpToolWidget *tool_path,
g_object_unref (undo);
}
+ if (path_tool->current_vector &&
+ GIMP_IS_LAYER_VECTOR_MASK (path_tool->current_vector))
+ gimp_layer_vector_mask_render (GIMP_LAYER_VECTOR_MASK (path_tool->current_vector));
+
gimp_image_flush (image);
}
@@ -658,9 +674,9 @@ gimp_path_tool_path_removed (GimpPath *path,
}
void
-gimp_path_tool_set_path (GimpPathTool *path_tool,
- GimpVectorLayer *layer,
- GimpPath *path)
+gimp_path_tool_set_path (GimpPathTool *path_tool,
+ GimpRasterizable *layer,
+ GimpPath *path)
{
GimpTool *tool;
GimpItem *item = NULL;
@@ -674,7 +690,12 @@ gimp_path_tool_set_path (GimpPathTool *path_tool,
options = GIMP_PATH_TOOL_GET_OPTIONS (path_tool);
if (layer != NULL)
- path = gimp_vector_layer_get_path (layer);
+ {
+ if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
+ path = gimp_vector_layer_get_path (GIMP_VECTOR_LAYER (layer));
+ else if (GIMP_IS_LAYER_VECTOR_MASK (layer))
+ path = gimp_layer_vector_mask_get_path (GIMP_LAYER_VECTOR_MASK (layer));
+ }
if (path)
item = GIMP_ITEM (path);
@@ -682,7 +703,7 @@ gimp_path_tool_set_path (GimpPathTool *path_tool,
if (path == path_tool->path)
return;
- if (path_tool->current_vector_layer && path && ! layer)
+ if (path_tool->current_vector && path && ! layer)
{
GimpImage *image = path_tool->current_image;
GList *all_layers = gimp_image_get_layer_list (image);
@@ -846,7 +867,7 @@ gimp_path_tool_create_vector_layer (GimpPathTool *path_tool)
/* If there's already an active vector layer, or no paths are
* selected, create a new blank path.
*/
- if (path_tool->current_vector_layer || ! path_tool->path)
+ if (path_tool->current_vector || ! path_tool->path)
{
GimpPath *new_path = gimp_path_new (image, _("Vector Layer"));
@@ -855,13 +876,13 @@ gimp_path_tool_create_vector_layer (GimpPathTool *path_tool)
g_signal_handlers_disconnect_by_func (options,
gimp_path_tool_vector_change_notify,
- path_tool->current_vector_layer);
+ path_tool->current_vector);
g_signal_handlers_disconnect_by_func (options->fill_options,
gimp_path_tool_vector_change_notify,
- path_tool->current_vector_layer);
+ path_tool->current_vector);
g_signal_handlers_disconnect_by_func (options->stroke_options,
gimp_path_tool_vector_change_notify,
- path_tool->current_vector_layer);
+ path_tool->current_vector);
}
layer = gimp_vector_layer_new (image, path_tool->path,
@@ -881,7 +902,7 @@ gimp_path_tool_create_vector_layer (GimpPathTool *path_tool)
-1,
TRUE);
- gimp_path_tool_set_layer (path_tool, layer);
+ gimp_path_tool_set_layer (path_tool, GIMP_RASTERIZABLE (layer));
gimp_vector_layer_refresh (layer);
gimp_image_flush (image);
@@ -896,60 +917,73 @@ gimp_path_tool_vector_layer_path_changed (GimpVectorLayerOptions *options,
const GParamSpec *pspec,
GimpPathTool *tool)
{
- gimp_path_tool_set_path (tool, tool->current_vector_layer, NULL);
+ gimp_path_tool_set_path (tool, tool->current_vector, NULL);
}
static void
gimp_path_tool_vector_change_notify (GObject *options,
const GParamSpec *pspec,
- GimpVectorLayer *layer)
+ GimpRasterizable *layer)
{
- GimpImage *image;
- gboolean needs_update = FALSE;
+ GimpImage *image;
+ GimpVectorLayer *vector_layer = NULL;
+ gboolean needs_update = FALSE;
image = gimp_item_get_image (GIMP_ITEM (layer));
- if (GIMP_IS_STROKE_OPTIONS (options))
+ if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
+ vector_layer = GIMP_VECTOR_LAYER (layer);
+
+ if (vector_layer)
{
- GimpStrokeOptions *stroke_options = GIMP_STROKE_OPTIONS (options);
+ if (GIMP_IS_STROKE_OPTIONS (options))
+ {
+ GimpStrokeOptions *stroke_options = GIMP_STROKE_OPTIONS (options);
- gimp_config_sync (G_OBJECT (stroke_options),
- G_OBJECT (layer->options->stroke_options), 0);
+ gimp_config_sync (G_OBJECT (stroke_options),
+ G_OBJECT (vector_layer->options->stroke_options),
+ 0);
- needs_update = TRUE;
- }
- else if (GIMP_IS_FILL_OPTIONS (options))
- {
- GimpFillOptions *fill_options = GIMP_FILL_OPTIONS (options);
+ needs_update = TRUE;
+ }
+ else if (GIMP_IS_FILL_OPTIONS (options))
+ {
+ GimpFillOptions *fill_options = GIMP_FILL_OPTIONS (options);
- gimp_config_sync (G_OBJECT (fill_options),
- G_OBJECT (layer->options->fill_options), 0);
+ gimp_config_sync (G_OBJECT (fill_options),
+ G_OBJECT (vector_layer->options->fill_options),
+ 0);
- needs_update = TRUE;
- }
- else if (GIMP_IS_PATH_OPTIONS (options))
- {
- GimpPathOptions *path_options = GIMP_PATH_OPTIONS (options);
+ needs_update = TRUE;
+ }
+ else if (GIMP_IS_PATH_OPTIONS (options))
+ {
+ GimpPathOptions *path_options = GIMP_PATH_OPTIONS (options);
- g_object_set (layer->options,
- "enable-fill", path_options->enable_fill,
- "enable-stroke", path_options->enable_stroke,
- NULL);
+ g_object_set (vector_layer->options,
+ "enable-fill", path_options->enable_fill,
+ "enable-stroke", path_options->enable_stroke,
+ NULL);
- needs_update = TRUE;
+ needs_update = TRUE;
+ }
}
if (needs_update)
{
- gimp_vector_layer_refresh (layer);
+ if (vector_layer)
+ gimp_vector_layer_refresh (vector_layer);
+ else if (GIMP_IS_LAYER_VECTOR_MASK (layer))
+ gimp_layer_vector_mask_render (GIMP_LAYER_VECTOR_MASK (layer));
+
gimp_image_flush (image);
}
}
static void
-gimp_path_tool_layer_rasterized (GimpVectorLayer *layer,
- gboolean is_rasterized,
- GimpPathTool *tool)
+gimp_path_tool_layer_rasterized (GimpRasterizable *layer,
+ gboolean is_rasterized,
+ GimpPathTool *tool)
{
if (! is_rasterized && ! GIMP_TOOL (tool)->display)
{
@@ -961,7 +995,7 @@ gimp_path_tool_layer_rasterized (GimpVectorLayer *layer,
if (current_layers &&
g_list_length (current_layers) == 1 &&
current_layers->data == layer)
- gimp_path_tool_set_layer (tool, layer);
+ gimp_path_tool_set_layer (tool, GIMP_RASTERIZABLE (layer));
}
else if (is_rasterized && GIMP_TOOL (tool)->display)
{
@@ -970,40 +1004,50 @@ gimp_path_tool_layer_rasterized (GimpVectorLayer *layer,
}
static void
-gimp_path_tool_set_layer (GimpPathTool *path_tool,
- GimpVectorLayer *vector_layer)
+gimp_path_tool_set_layer (GimpPathTool *path_tool,
+ GimpRasterizable *layer)
{
GimpPathOptions *options;
+ GimpVectorLayer *vector_layer = NULL;
GimpVectorLayerOptions *layer_options;
g_return_if_fail (GIMP_IS_PATH_TOOL (path_tool));
options = GIMP_PATH_TOOL_GET_OPTIONS (path_tool);
- if (path_tool->current_vector_layer)
+ if (path_tool->current_vector &&
+ gimp_item_is_vector_layer (GIMP_ITEM (path_tool->current_vector)))
+ vector_layer = GIMP_VECTOR_LAYER (path_tool->current_vector);
+
+ if (vector_layer)
{
- layer_options = gimp_vector_layer_get_options (path_tool->current_vector_layer);
+ layer_options = gimp_vector_layer_get_options (vector_layer);
g_signal_handlers_disconnect_by_func (layer_options,
gimp_path_tool_vector_layer_path_changed,
path_tool);
g_signal_handlers_disconnect_by_func (options,
gimp_path_tool_vector_change_notify,
- path_tool->current_vector_layer);
+ path_tool->current_vector);
g_signal_handlers_disconnect_by_func (options->fill_options,
gimp_path_tool_vector_change_notify,
- path_tool->current_vector_layer);
+ path_tool->current_vector);
g_signal_handlers_disconnect_by_func (options->stroke_options,
gimp_path_tool_vector_change_notify,
- path_tool->current_vector_layer);
+ path_tool->current_vector);
- g_signal_handlers_disconnect_by_func (path_tool->current_vector_layer,
+ g_signal_handlers_disconnect_by_func (path_tool->current_vector,
G_CALLBACK (gimp_path_tool_layer_rasterized),
path_tool);
}
- path_tool->current_vector_layer = vector_layer;
- gimp_path_tool_set_path (path_tool, vector_layer, NULL);
+ path_tool->current_vector = layer;
+ gimp_path_tool_set_path (path_tool, layer, NULL);
+
+ vector_layer = NULL;
+ if (path_tool->current_vector &&
+ gimp_item_is_vector_layer (GIMP_ITEM (path_tool->current_vector)))
+ vector_layer = GIMP_VECTOR_LAYER (path_tool->current_vector);
if (vector_layer)
{
@@ -1137,7 +1181,7 @@ gimp_path_tool_confirm_response (GimpViewableDialog *dialog,
case GTK_RESPONSE_ACCEPT:
gimp_rasterizable_restore (GIMP_RASTERIZABLE (layer));
- gimp_path_tool_set_layer (path_tool, layer);
+ gimp_path_tool_set_layer (path_tool, GIMP_RASTERIZABLE (layer));
break;
default:
diff --git a/app/tools/gimppathtool.h b/app/tools/gimppathtool.h
index 1b239836c8b83785a77ac4349a3a8e7b83a9ca12..7c7531ee11c8c9335f48fe79f7211d707cf37dc0 100644
--- a/app/tools/gimppathtool.h
+++ b/app/tools/gimppathtool.h
@@ -40,16 +40,16 @@ struct _GimpPathTool
{
GimpDrawTool parent_instance;
- GimpImage *current_image;
- GimpVectorLayer *current_vector_layer;
+ GimpImage *current_image;
+ GimpRasterizable *current_vector;
- GimpPath *path; /* the current Path data */
- GimpPathMode saved_mode; /* used by modifier_key() */
+ GimpPath *path; /* the current Path data */
+ GimpPathMode saved_mode; /* used by modifier_key() */
- GimpToolWidget *widget;
- GimpToolWidget *grab_widget;
+ GimpToolWidget *widget;
+ GimpToolWidget *grab_widget;
- GtkWidget *confirm_dialog;
+ GtkWidget *confirm_dialog;
};
struct _GimpPathToolClass
@@ -64,5 +64,5 @@ void gimp_path_tool_register (GimpToolRegisterCallback callback,
GType gimp_path_tool_get_type (void) G_GNUC_CONST;
void gimp_path_tool_set_path (GimpPathTool *path_tool,
- GimpVectorLayer *layer,
+ GimpRasterizable *layer,
GimpPath *path);
diff --git a/app/tools/gimptool.c b/app/tools/gimptool.c
index 727c8513915819bc7ee901c691ec30e6f393102e..66f60976bd64ee9f2e3b336888d803a60265cca7 100644
--- a/app/tools/gimptool.c
+++ b/app/tools/gimptool.c
@@ -28,6 +28,7 @@
#include "core/gimp.h"
#include "core/gimpcontainer.h"
#include "core/gimpimage.h"
+#include "core/gimplayervectormask.h"
#include "core/gimplinklayer.h"
#include "core/gimpprogress.h"
#include "core/gimptoolinfo.h"
@@ -739,12 +740,13 @@ gimp_tool_button_press (GimpTool *tool,
drawables = gimp_image_get_selected_drawables (image);
for (GList *iter = drawables; iter; iter = iter->next)
{
- GimpDrawable *drawable = iter->data;
- GimpItem *locked_item = NULL;
+ GimpDrawable *drawable = iter->data;
+ GimpItem *locked_item = NULL;
if (gimp_item_is_vector_layer (GIMP_ITEM (drawable)) ||
gimp_item_is_link_layer (GIMP_ITEM (drawable)) ||
gimp_item_is_text_layer (GIMP_ITEM (drawable)) ||
+ GIMP_IS_LAYER_VECTOR_MASK (drawable) ||
gimp_item_is_content_locked (GIMP_ITEM (drawable), &locked_item))
{
gboolean constrain_only;
@@ -778,6 +780,14 @@ gimp_tool_button_press (GimpTool *tool,
gimp_tool_message (tool, display, _("Vector layers must be rasterized (%s)."), menu_path);
gimp_tools_blink_item (display->gimp, GIMP_ITEM (drawable));
}
+ else if (GIMP_IS_LAYER_VECTOR_MASK (drawable))
+ {
+ GimpLayer *layer =
+ gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable));
+ /* TRANSLATORS: the string between parentheses will be a menu path. */
+ gimp_tool_message (tool, display, _("Vector masks must be rasterized (%s)."), menu_path);
+ gimp_tools_blink_item (display->gimp, GIMP_ITEM (layer));
+ }
else
{
gimp_tool_message_literal (tool, display,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f18e02e3fded13f060f40d72e0bc58b486ff25c9..7e3f29a1e0d10a24fee278a3c0d02df96ed1ca4d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -182,6 +182,7 @@ app/core/gimpitem-exclusive.c
app/core/gimplayer-floating-selection.c
app/core/gimplayer.c
app/core/gimplayermask.c
+app/core/gimplayervectormask.c
app/core/gimplineart.c
app/core/gimplink.c
app/core/gimplinklayer.c