diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index b52d0a5d38..2dd69ba7a2 100644
--- a/app/actions/layers-actions.c
+++ b/app/actions/layers-actions.c
@@ -33,7 +33,7 @@
#include "text/gimptextlayer.h"
-#include "vectors/gimpvectorlayer.h"
+#include "path/gimpvectorlayer.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpactiongroup.h"
@@ -999,7 +999,7 @@ layers_actions_update (GimpActionGroup *group,
gimp_action_group_set_action_active (group, action, TRUE);
text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
- vector_layer = gimp_drawable_is_vector_layer (GIMP_DRAWABLE (layer));
+ vector_layer = gimp_item_is_vector_layer (GIMP_ITEM (layer));
}
}
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index 939a27d3ea..0ec271a799 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -74,8 +74,8 @@
#include "display/gimpdisplayshell.h"
#include "display/gimpimagewindow.h"
+#include "tools/gimppathtool.h"
#include "tools/gimptexttool.h"
-#include "tools/gimpvectortool.h"
#include "tools/tool_manager.h"
#include "dialogs/dialogs.h"
@@ -204,6 +204,10 @@ layers_edit_cmd_callback (GimpAction *action,
{
layers_edit_text_cmd_callback (action, value, data);
}
+ else if (gimp_item_is_vector_layer (GIMP_ITEM (layers->data)))
+ {
+ layers_vector_fill_stroke_cmd_callback (action, value, data);
+ }
else
{
layers_edit_attributes_cmd_callback (action, value, data);
@@ -273,7 +277,7 @@ layers_edit_vector_cmd_callback (GimpAction *action,
layer = layers->data;
- if (! gimp_drawable_is_vector_layer (GIMP_DRAWABLE (layer)))
+ if (! gimp_item_is_vector_layer (GIMP_ITEM (layer)))
{
layers_edit_attributes_cmd_callback (action, value, data);
return;
@@ -281,13 +285,13 @@ layers_edit_vector_cmd_callback (GimpAction *action,
active_tool = tool_manager_get_active (image->gimp);
- if (! GIMP_IS_VECTOR_TOOL (active_tool))
+ if (! GIMP_IS_PATH_TOOL (active_tool))
{
GimpToolInfo *tool_info;
tool_info = (GimpToolInfo *)
gimp_container_get_child_by_name (image->gimp->tool_info_list,
- "gimp-vector-tool");
+ "gimp-path-tool");
if (GIMP_IS_TOOL_INFO (tool_info))
{
@@ -296,9 +300,9 @@ layers_edit_vector_cmd_callback (GimpAction *action,
}
}
- if (GIMP_IS_VECTOR_TOOL (active_tool))
- gimp_vector_tool_set_vectors (GIMP_VECTOR_TOOL (active_tool),
- GIMP_VECTOR_LAYER (layer)->options->path);
+ if (GIMP_IS_PATH_TOOL (active_tool))
+ gimp_path_tool_set_path (GIMP_PATH_TOOL (active_tool),
+ GIMP_VECTOR_LAYER (layer)->options->path);
}
void
diff --git a/app/actions/paths-commands.c b/app/actions/paths-commands.c
index 717c467569..e36831ad6c 100644
--- a/app/actions/paths-commands.c
+++ b/app/actions/paths-commands.c
@@ -470,6 +470,7 @@ paths_delete_cmd_callback (GimpAction *action,
{
GimpImage *image;
GList *paths;
+ gboolean attached_to_vector_layer = FALSE;
return_if_no_paths (image, paths, data);
paths = g_list_copy (paths);
@@ -479,11 +480,21 @@ paths_delete_cmd_callback (GimpAction *action,
_("Remove Paths"));
for (GList *iter = paths; iter; iter = iter->next)
- gimp_image_remove_path (image, iter->data, TRUE, NULL);
+ {
+ /* Verify path is not attached to vector layer */
+ if (! gimp_path_attached_to_vector_layer (GIMP_PATH (iter->data), image))
+ gimp_image_remove_path (image, iter->data, TRUE, NULL);
+ else
+ attached_to_vector_layer = TRUE;
+ }
gimp_image_undo_group_end (image);
gimp_image_flush (image);
g_list_free (paths);
+
+ if (attached_to_vector_layer)
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ _("Paths attached to vector layers weren't deleted"));
}
void
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 827f0b5f11..db511084d8 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -1267,6 +1267,8 @@ gimp_undo_type_get_type (void)
{ GIMP_UNDO_TEXT_LAYER, "GIMP_UNDO_TEXT_LAYER", "text-layer" },
{ GIMP_UNDO_TEXT_LAYER_MODIFIED, "GIMP_UNDO_TEXT_LAYER_MODIFIED", "text-layer-modified" },
{ GIMP_UNDO_TEXT_LAYER_CONVERT, "GIMP_UNDO_TEXT_LAYER_CONVERT", "text-layer-convert" },
+ { GIMP_UNDO_VECTOR_LAYER, "GIMP_UNDO_VECTOR_LAYER", "vector-layer" },
+ { GIMP_UNDO_VECTOR_LAYER_MODIFIED, "GIMP_UNDO_VECTOR_LAYER_MODIFIED", "vector-layer-modified" },
{ GIMP_UNDO_LAYER_MASK_ADD, "GIMP_UNDO_LAYER_MASK_ADD", "layer-mask-add" },
{ GIMP_UNDO_LAYER_MASK_REMOVE, "GIMP_UNDO_LAYER_MASK_REMOVE", "layer-mask-remove" },
{ GIMP_UNDO_LAYER_MASK_APPLY, "GIMP_UNDO_LAYER_MASK_APPLY", "layer-mask-apply" },
@@ -1380,6 +1382,8 @@ gimp_undo_type_get_type (void)
{ GIMP_UNDO_TEXT_LAYER, NC_("undo-type", "Text layer"), NULL },
{ GIMP_UNDO_TEXT_LAYER_MODIFIED, NC_("undo-type", "Text layer modification"), NULL },
{ GIMP_UNDO_TEXT_LAYER_CONVERT, NC_("undo-type", "Convert text layer"), NULL },
+ { GIMP_UNDO_VECTOR_LAYER, NC_("undo-type", "Vector layer"), NULL },
+ { GIMP_UNDO_VECTOR_LAYER_MODIFIED, NC_("undo-type", "Vector layer modification"), NULL },
{ GIMP_UNDO_LAYER_MASK_ADD, NC_("undo-type", "Add layer masks"), NULL },
{ GIMP_UNDO_LAYER_MASK_REMOVE, NC_("undo-type", "Delete layer masks"), NULL },
{ GIMP_UNDO_LAYER_MASK_APPLY, NC_("undo-type", "Apply layer masks"), NULL },
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index 972e0ce725..227251102b 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -619,6 +619,8 @@ typedef enum /*< pdb-skip >*/
GIMP_UNDO_TEXT_LAYER, /*< desc="Text layer" >*/
GIMP_UNDO_TEXT_LAYER_MODIFIED, /*< desc="Text layer modification" >*/
GIMP_UNDO_TEXT_LAYER_CONVERT, /*< desc="Convert text layer" >*/
+ GIMP_UNDO_VECTOR_LAYER, /*< desc="Vector layer" >*/
+ GIMP_UNDO_VECTOR_LAYER_MODIFIED, /*< desc="Vector layer modification" >*/
GIMP_UNDO_LAYER_MASK_ADD, /*< desc="Add layer masks" >*/
GIMP_UNDO_LAYER_MASK_REMOVE, /*< desc="Delete layer masks" >*/
GIMP_UNDO_LAYER_MASK_APPLY, /*< desc="Apply layer masks" >*/
diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c
index b8d6a377bf..e6850df9a4 100644
--- a/app/core/gimpimage-undo-push.c
+++ b/app/core/gimpimage-undo-push.c
@@ -57,6 +57,8 @@
#include "path/gimppathmodundo.h"
#include "path/gimppathpropundo.h"
#include "path/gimppathundo.h"
+#include "path/gimpvectorlayer.h"
+#include "path/gimpvectorlayerundo.h"
#include "text/gimptextlayer.h"
#include "text/gimptextundo.h"
@@ -877,6 +879,45 @@ gimp_image_undo_push_text_layer_convert (GimpImage *image,
}
+/************************/
+/* Vector Layer Undos */
+/************************/
+
+GimpUndo *
+gimp_image_undo_push_vector_layer (GimpImage *image,
+ const gchar *undo_desc,
+ GimpVectorLayer *layer,
+ const GParamSpec *pspec)
+{
+ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+ g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
+ g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)), NULL);
+
+ return gimp_image_undo_push (image, GIMP_TYPE_VECTOR_LAYER_UNDO,
+ GIMP_UNDO_VECTOR_LAYER, undo_desc,
+ GIMP_DIRTY_ITEM | GIMP_DIRTY_DRAWABLE,
+ "item", layer,
+ "param", pspec,
+ NULL);
+}
+
+GimpUndo *
+gimp_image_undo_push_vector_layer_modified (GimpImage *image,
+ const gchar *undo_desc,
+ GimpVectorLayer *layer)
+{
+ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+ g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
+ g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)), NULL);
+
+ return gimp_image_undo_push (image, GIMP_TYPE_VECTOR_LAYER_UNDO,
+ GIMP_UNDO_VECTOR_LAYER_MODIFIED, undo_desc,
+ GIMP_DIRTY_ITEM_META,
+ "item", layer,
+ NULL);
+}
+
+
/**********************/
/* Layer Mask Undos */
/**********************/
diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h
index d50d355f8c..6e0404c740 100644
--- a/app/core/gimpimage-undo-push.h
+++ b/app/core/gimpimage-undo-push.h
@@ -215,6 +215,17 @@ GimpUndo * gimp_image_undo_push_text_layer_convert (GimpImage *image,
GimpTextLayer *layer);
+/* vector layer undos */
+
+GimpUndo * gimp_image_undo_push_vector_layer (GimpImage *image,
+ const gchar *undo_desc,
+ GimpVectorLayer *layer,
+ const GParamSpec *pspec);
+GimpUndo * gimp_image_undo_push_vector_layer_modified
+ (GimpImage *image,
+ const gchar *undo_desc,
+ GimpVectorLayer *layer);
+
/* layer mask undos */
GimpUndo * gimp_image_undo_push_layer_mask_add (GimpImage *image,
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index ed7e7be4a3..946e8db3d2 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -87,6 +87,7 @@
#include "text/gimptextlayer.h"
#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
#include "gimp-log.h"
#include "gimp-intl.h"
@@ -5457,6 +5458,17 @@ gimp_image_add_layer (GimpImage *image,
gimp_drawable_attach_floating_sel (gimp_layer_get_floating_sel_drawable (layer),
layer);
+ /* If the layer is a vector layer, also add its path to the image */
+ if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
+ {
+ GimpPath *path = gimp_vector_layer_get_path (GIMP_VECTOR_LAYER (layer));
+
+ if (path &&
+ (! gimp_item_is_attached (GIMP_ITEM (path))) &&
+ gimp_item_get_image (GIMP_ITEM (path)) == image)
+ gimp_image_add_path (image, path, NULL, -1, FALSE);
+ }
+
if (old_has_alpha != gimp_image_has_alpha (image))
private->flush_accum.alpha_changed = TRUE;
diff --git a/app/core/gimpparamspecs.c b/app/core/gimpparamspecs.c
index fece6f1b43..79dc7463e1 100644
--- a/app/core/gimpparamspecs.c
+++ b/app/core/gimpparamspecs.c
@@ -42,6 +42,7 @@
#include "gimpselection.h"
#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
#include "text/gimpfont.h"
#include "text/gimptextlayer.h"
diff --git a/app/dialogs/vector-layer-options-dialog.c b/app/dialogs/vector-layer-options-dialog.c
index 91ae832923..23028e87ed 100644
--- a/app/dialogs/vector-layer-options-dialog.c
+++ b/app/dialogs/vector-layer-options-dialog.c
@@ -1,248 +1,326 @@
-/* GIMP - The GNU Image Manipulation Program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * vector-layer-options-dialog.h
- *
- * Copyright 2006 Hendrik Boom
- *
- * 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 "libgimpconfig/gimpconfig.h"
-#include "libgimpwidgets/gimpwidgets.h"
-
-#include "dialogs-types.h"
-
-#include "core/gimp.h"
-#include "core/gimpdrawable.h"
-#include "core/gimpimage.h"
-#include "core/gimpimage-undo-push.h"
-#include "core/gimpstrokeoptions.h"
-
-#include "widgets/gimpcolorpanel.h"
-#include "widgets/gimppropwidgets.h"
-#include "widgets/gimpviewabledialog.h"
-#include "widgets/gimpstrokeeditor.h"
-
-#include "vectors/gimpvectorlayer.h"
-#include "vectors/gimpvectorlayeroptions.h"
-
-#include "vector-layer-options-dialog.h"
-
-#include "gimp-intl.h"
-
-
-#define RESPONSE_RESET 1
-
-
-/* local functions */
-
-static void vector_layer_options_dialog_notify (GObject *options,
- const GParamSpec *pspec,
- GtkWidget *dialog);
-static void vector_layer_options_dialog_response (GtkWidget *widget,
- gint response_id,
- GtkWidget *dialog);
-
-
-/* public function */
-
-GtkWidget *
-vector_layer_options_dialog_new (GimpVectorLayer *layer,
- GimpContext *context,
- const gchar *title,
- const gchar *icon_name,
- const gchar *help_id,
- GtkWidget *parent)
-{
- GimpVectorLayerOptions *saved_options;
- GimpFillOptions *fill_options;
- GimpStrokeOptions *stroke_options;
- GtkWidget *dialog;
- GtkWidget *main_vbox;
-
- g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
- g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
- g_return_val_if_fail (icon_name != NULL, NULL);
- g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
-
- saved_options = gimp_config_duplicate (GIMP_CONFIG (layer->options));
- fill_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->fill_options));
- stroke_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->stroke_options));
-
- dialog = gimp_viewable_dialog_new (g_list_prepend (NULL, GIMP_VIEWABLE (layer)),
- context,
- title, "gimp-vectorlayer-options",
- icon_name,
- _("Choose vector layer options"),
- parent,
- gimp_standard_help_func,
- help_id,
- _("_Reset"), RESPONSE_RESET,
- _("_Cancel"), GTK_RESPONSE_CANCEL,
- _("_Apply"), GTK_RESPONSE_OK,
-
- NULL);
-
- gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
- RESPONSE_RESET,
- GTK_RESPONSE_OK,
- GTK_RESPONSE_CANCEL,
- -1);
-
- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-
- g_signal_connect (dialog, "response",
- G_CALLBACK (vector_layer_options_dialog_response),
- dialog);
-
- g_object_set_data (G_OBJECT (dialog), "layer", layer);
-
- g_object_set_data_full (G_OBJECT (dialog), "saved-options",
- saved_options,
- (GDestroyNotify) g_object_unref);
- g_object_set_data_full (G_OBJECT (dialog), "fill-options",
- fill_options,
- (GDestroyNotify) g_object_unref);
- g_object_set_data_full (G_OBJECT (dialog), "stroke-options",
- stroke_options,
- (GDestroyNotify) g_object_unref);
-
- g_signal_connect_object (fill_options, "notify",
- G_CALLBACK (vector_layer_options_dialog_notify),
- dialog, 0);
- g_signal_connect_object (stroke_options, "notify",
- G_CALLBACK (vector_layer_options_dialog_notify),
- dialog, 0);
-
- 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))),
- main_vbox, TRUE, TRUE, 0);
- gtk_widget_set_visible (main_vbox, TRUE);
-
- /* The fill editor */
- {
- GtkWidget *frame;
- GtkWidget *fill_editor;
-
- frame = gimp_frame_new (_("Fill Style"));
- gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
- gtk_widget_set_visible (frame, TRUE);
-
- fill_editor = gimp_fill_editor_new (fill_options, TRUE, TRUE);
- gtk_container_add (GTK_CONTAINER (frame), fill_editor);
- gtk_widget_set_visible (fill_editor, TRUE);
- }
-
- /* The stroke editor */
- {
- GtkWidget *frame;
- GtkWidget *stroke_editor;
- gdouble xres;
- gdouble yres;
-
- frame = gimp_frame_new (_("Stroke Style"));
- gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
- gtk_widget_set_visible (frame, TRUE);
-
- gimp_image_get_resolution (gimp_item_get_image (GIMP_ITEM (layer)),
- &xres, &yres);
-
- stroke_editor = gimp_stroke_editor_new (stroke_options, yres, TRUE, TRUE);
- gtk_container_add (GTK_CONTAINER (frame), stroke_editor);
- gtk_widget_set_visible (stroke_editor, TRUE);
- }
-
- return dialog;
-}
-
-static void
-vector_layer_options_dialog_notify (GObject *options,
- const GParamSpec *pspec,
- GtkWidget *dialog)
-{
- GimpVectorLayer *layer;
- GimpFillOptions *fill_options;
- GimpStrokeOptions *stroke_options;
-
- layer = g_object_get_data (G_OBJECT (dialog), "layer");
-
- fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
- stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
-
- gimp_config_sync (G_OBJECT (fill_options),
- G_OBJECT (layer->options->fill_options), 0);
- gimp_config_sync (G_OBJECT (stroke_options),
- G_OBJECT (layer->options->stroke_options), 0);
-
- gimp_vector_layer_refresh (layer);
- gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
-}
-
-static void
-vector_layer_options_dialog_response (GtkWidget *widget,
- gint response_id,
- GtkWidget *dialog)
-{
- GimpVectorLayer *layer;
- GimpVectorLayerOptions *saved_options;
- GimpFillOptions *fill_options;
- GimpStrokeOptions *stroke_options;
-
- layer = g_object_get_data (G_OBJECT (dialog), "layer");
-
- saved_options = g_object_get_data (G_OBJECT (dialog), "saved-options");
- fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
- stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
-
- switch (response_id)
- {
- case GTK_RESPONSE_OK:
- if (layer && layer->options )
- {
- gimp_config_sync (G_OBJECT (saved_options->fill_options),
- G_OBJECT (layer->options->fill_options), 0);
- gimp_config_sync (G_OBJECT (saved_options->stroke_options),
- G_OBJECT (layer->options->stroke_options), 0);
-
- gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
- _("Fill/Stroke Vector Layer"),
- layer, NULL);
-
- gimp_config_sync (G_OBJECT (fill_options),
- G_OBJECT (layer->options->fill_options), 0);
- gimp_config_sync (G_OBJECT (stroke_options),
- G_OBJECT (layer->options->stroke_options), 0);
- }
-
- gtk_widget_destroy (dialog);
- break;
-
- default:
- gimp_config_sync (G_OBJECT (saved_options->fill_options),
- G_OBJECT (fill_options), 0);
- gimp_config_sync (G_OBJECT (saved_options->stroke_options),
- G_OBJECT (stroke_options), 0);
-
- if (response_id != RESPONSE_RESET)
- gtk_widget_destroy (dialog);
- break;
- }
-}
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * vector-layer-options-dialog.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "dialogs-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo-push.h"
+#include "core/gimpstrokeoptions.h"
+
+#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
+#include "path/gimpvectorlayeroptions.h"
+
+#include "widgets/gimpcolorpanel.h"
+#include "widgets/gimpcontainercombobox.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimppropwidgets.h"
+#include "widgets/gimpviewabledialog.h"
+#include "widgets/gimpstrokeeditor.h"
+
+#include "vector-layer-options-dialog.h"
+
+#include "gimp-intl.h"
+
+
+#define RESPONSE_RESET 1
+
+
+/* local functions */
+
+static void vector_layer_options_dialog_notify (GObject *options,
+ const GParamSpec *pspec,
+ GtkWidget *dialog);
+static void vector_layer_options_dialog_response (GtkWidget *widget,
+ gint response_id,
+ GtkWidget *dialog);
+static void vector_layer_options_dialog_path_selected (GimpContainerView *view,
+ GtkWidget *dialog);
+
+
+/* public function */
+
+GtkWidget *
+vector_layer_options_dialog_new (GimpVectorLayer *layer,
+ GimpContext *context,
+ const gchar *title,
+ const gchar *icon_name,
+ const gchar *help_id,
+ GtkWidget *parent)
+{
+ GimpVectorLayerOptions *saved_options;
+ GimpFillOptions *fill_options;
+ GimpStrokeOptions *stroke_options;
+ GtkWidget *dialog;
+ GtkWidget *main_vbox;
+ GtkWidget *combo;
+
+ g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+ g_return_val_if_fail (icon_name != NULL, NULL);
+ g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
+
+ saved_options = gimp_config_duplicate (GIMP_CONFIG (layer->options));
+ fill_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->fill_options));
+ stroke_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->stroke_options));
+
+ dialog = gimp_viewable_dialog_new (g_list_prepend (NULL, GIMP_VIEWABLE (layer)),
+ context,
+ title, "gimp-vectorlayer-options",
+ icon_name,
+ _("Edit Vector Layer Attributes"),
+ parent,
+ gimp_standard_help_func,
+ help_id,
+ _("_Reset"), RESPONSE_RESET,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Apply"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ RESPONSE_RESET,
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (vector_layer_options_dialog_response),
+ dialog);
+
+ g_object_set_data (G_OBJECT (dialog), "layer", layer);
+
+ g_object_set_data_full (G_OBJECT (dialog), "saved-options",
+ saved_options,
+ (GDestroyNotify) g_object_unref);
+ g_object_set_data_full (G_OBJECT (dialog), "fill-options",
+ fill_options,
+ (GDestroyNotify) g_object_unref);
+ g_object_set_data_full (G_OBJECT (dialog), "stroke-options",
+ stroke_options,
+ (GDestroyNotify) g_object_unref);
+
+ g_signal_connect_object (saved_options, "notify::enable-fill",
+ G_CALLBACK (vector_layer_options_dialog_notify),
+ dialog, 0);
+ g_signal_connect_object (saved_options, "notify::enable-stroke",
+ G_CALLBACK (vector_layer_options_dialog_notify),
+ dialog, 0);
+
+ g_signal_connect_object (fill_options, "notify",
+ G_CALLBACK (vector_layer_options_dialog_notify),
+ dialog, 0);
+ g_signal_connect_object (stroke_options, "notify",
+ G_CALLBACK (vector_layer_options_dialog_notify),
+ dialog, 0);
+
+ 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))),
+ main_vbox, TRUE, TRUE, 0);
+ gtk_widget_set_visible (main_vbox, TRUE);
+
+
+ combo = gimp_container_combo_box_new (gimp_image_get_paths (gimp_item_get_image (GIMP_ITEM (layer))),
+ context,
+ GIMP_VIEW_SIZE_SMALL, 1);
+ gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo),
+ GIMP_VIEWABLE (saved_options->path));
+ g_signal_connect_object (combo, "selection-changed",
+ G_CALLBACK (vector_layer_options_dialog_path_selected),
+ dialog, 0);
+
+ gtk_box_pack_start (GTK_BOX (main_vbox), combo, FALSE, FALSE, 0);
+ gtk_widget_set_visible (combo, TRUE);
+
+ /* The fill editor */
+ {
+ GtkWidget *frame;
+ GtkWidget *fill_editor;
+
+ fill_editor = gimp_fill_editor_new (fill_options, TRUE, TRUE);
+ gtk_widget_set_visible (fill_editor, TRUE);
+
+ frame = gimp_prop_expanding_frame_new (G_OBJECT (saved_options),
+ "enable-fill", NULL, fill_editor,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+ }
+
+ /* The stroke editor */
+ {
+ GtkWidget *frame;
+ GtkWidget *stroke_editor;
+ gdouble xres;
+ gdouble yres;
+
+ gimp_image_get_resolution (gimp_item_get_image (GIMP_ITEM (layer)),
+ &xres, &yres);
+
+ stroke_editor = gimp_stroke_editor_new (stroke_options, yres, TRUE, TRUE);
+ gtk_widget_set_visible (stroke_editor, TRUE);
+
+ frame = gimp_prop_expanding_frame_new (G_OBJECT (saved_options),
+ "enable-stroke", NULL, stroke_editor,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+ }
+
+ return dialog;
+}
+
+static void
+vector_layer_options_dialog_notify (GObject *options,
+ const GParamSpec *pspec,
+ GtkWidget *dialog)
+{
+ GimpVectorLayer *layer;
+ GimpFillOptions *fill_options;
+ GimpStrokeOptions *stroke_options;
+ gboolean enable_fill;
+ gboolean enable_stroke;
+
+ layer = g_object_get_data (G_OBJECT (dialog), "layer");
+
+ enable_fill = layer->options->enable_fill;
+ enable_stroke = layer->options->enable_stroke;
+
+ fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
+ stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
+
+ gimp_config_sync (G_OBJECT (fill_options),
+ G_OBJECT (layer->options->fill_options), 0);
+ gimp_config_sync (G_OBJECT (stroke_options),
+ G_OBJECT (layer->options->stroke_options), 0);
+
+ if (! strcmp (pspec->name, "enable-fill") ||
+ ! strcmp (pspec->name, "enable-stroke"))
+ {
+ GimpVectorLayerOptions *vector_options;
+
+ vector_options = GIMP_VECTOR_LAYER_OPTIONS (options);
+
+ layer->options->enable_fill = vector_options->enable_fill;
+ layer->options->enable_stroke = vector_options->enable_stroke;
+ }
+
+ gimp_vector_layer_refresh (layer);
+ gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
+
+ layer->options->enable_fill = enable_fill;
+ layer->options->enable_stroke = enable_stroke;
+}
+
+static void
+vector_layer_options_dialog_response (GtkWidget *widget,
+ gint response_id,
+ GtkWidget *dialog)
+{
+ GimpVectorLayer *layer;
+ GimpPath *path;
+ GimpVectorLayerOptions *saved_options;
+ GimpFillOptions *fill_options;
+ GimpStrokeOptions *stroke_options;
+
+ layer = g_object_get_data (G_OBJECT (dialog), "layer");
+
+ saved_options = g_object_get_data (G_OBJECT (dialog), "saved-options");
+ fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
+ stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
+
+ switch (response_id)
+ {
+ case GTK_RESPONSE_OK:
+ if (layer && layer->options)
+ {
+ layer->options->enable_fill = saved_options->enable_fill;
+ gimp_config_sync (G_OBJECT (saved_options->fill_options),
+ G_OBJECT (layer->options->fill_options), 0);
+ layer->options->enable_stroke = saved_options->enable_stroke;
+ gimp_config_sync (G_OBJECT (saved_options->stroke_options),
+ G_OBJECT (layer->options->stroke_options), 0);
+
+ gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
+ _("Fill/Stroke Vector Layer"),
+ layer, NULL);
+
+ gimp_config_sync (G_OBJECT (fill_options),
+ G_OBJECT (layer->options->fill_options), 0);
+ gimp_config_sync (G_OBJECT (stroke_options),
+ G_OBJECT (layer->options->stroke_options), 0);
+ }
+
+ gtk_widget_destroy (dialog);
+ break;
+
+ default:
+ gimp_config_sync (G_OBJECT (saved_options->fill_options),
+ G_OBJECT (fill_options), 0);
+ gimp_config_sync (G_OBJECT (saved_options->stroke_options),
+ G_OBJECT (stroke_options), 0);
+ if (layer && layer->options)
+ {
+ g_object_get (saved_options, "path", &path, NULL);
+ g_object_set (layer->options, "path", path, NULL);
+
+ gimp_vector_layer_refresh (layer);
+ gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
+ }
+
+ if (response_id != RESPONSE_RESET)
+ gtk_widget_destroy (dialog);
+ break;
+ }
+}
+
+static void
+vector_layer_options_dialog_path_selected (GimpContainerView *view,
+ GtkWidget *dialog)
+{
+ GimpViewable *item = gimp_container_view_get_1_selected (view);
+ GimpPath *path = NULL;
+ GimpVectorLayer *layer;
+
+ layer = g_object_get_data (G_OBJECT (dialog), "layer");
+
+ if (item)
+ path = GIMP_PATH (item);
+
+ if (path && GIMP_IS_PATH (path))
+ {
+ g_object_set (layer->options, "path", path, NULL);
+
+ gimp_vector_layer_refresh (layer);
+ gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
+ }
+}
diff --git a/app/dialogs/vector-layer-options-dialog.h b/app/dialogs/vector-layer-options-dialog.h
index c7294366f7..e2ed040a1b 100644
--- a/app/dialogs/vector-layer-options-dialog.h
+++ b/app/dialogs/vector-layer-options-dialog.h
@@ -1,34 +1,34 @@
-/* GIMP - The GNU Image Manipulation Program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * vector-layer-options-dialog.h
- *
- * Copyright 2006 Hendrik Boom
- *
- * 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 .
- */
-
-#ifndef __VECTOR_LAYER_OPTIONS_DIALOG_H__
-#define __VECTOR_LAYER_OPTIONS_DIALOG_H__
-
-
-GtkWidget * vector_layer_options_dialog_new (GimpVectorLayer *layer,
- GimpContext *context,
- const gchar *title,
- const gchar *icon_name,
- const gchar *help_id,
- GtkWidget *parent);
-
-
-#endif /* __VECTOR_LAYER_OPTIONS_DIALOG_H__ */
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * vector-layer-options-dialog.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 .
+ */
+
+#ifndef __VECTOR_LAYER_OPTIONS_DIALOG_H__
+#define __VECTOR_LAYER_OPTIONS_DIALOG_H__
+
+
+GtkWidget * vector_layer_options_dialog_new (GimpVectorLayer *layer,
+ GimpContext *context,
+ const gchar *title,
+ const gchar *icon_name,
+ const gchar *help_id,
+ GtkWidget *parent);
+
+
+#endif /* __VECTOR_LAYER_OPTIONS_DIALOG_H__ */
diff --git a/app/display/gimpcanvas-style.c b/app/display/gimpcanvas-style.c
index 6991637697..7dd1a0485d 100644
--- a/app/display/gimpcanvas-style.c
+++ b/app/display/gimpcanvas-style.c
@@ -34,6 +34,8 @@
#include "core/gimpgrid.h"
#include "core/gimplayer.h"
+#include "path/gimpvectorlayer.h"
+
#include "gimpcanvas.h"
#include "gimpcanvas-style.h"
@@ -431,6 +433,15 @@ gimp_canvas_set_layer_style (GtkWidget *canvas,
pattern = gimp_cairo_pattern_create_stipple (layer_group_fg, layer_group_bg, 0,
offset_x, offset_y, render_space);
}
+ else if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
+ {
+ GeglColor *transparent = gegl_color_new ("transparent");
+
+ pattern = gimp_cairo_pattern_create_stipple (transparent, transparent, 0,
+ offset_x, offset_y, render_space);
+
+ g_clear_object (&transparent);
+ }
else
{
pattern = gimp_cairo_pattern_create_stipple (layer_fg, layer_bg, 0,
diff --git a/app/gimpcore.def b/app/gimpcore.def
index 9527b1473a..d243e4417c 100644
--- a/app/gimpcore.def
+++ b/app/gimpcore.def
@@ -398,6 +398,7 @@ EXPORTS
gimp_item_get_visible
gimp_item_height
gimp_item_is_text_layer
+ gimp_item_is_vector_layer
gimp_item_offsets
gimp_item_rename
gimp_item_resize
@@ -450,7 +451,7 @@ EXPORTS
gimp_marshal_VOID__OBJECT_OBJECT
gimp_marshal_VOID__OBJECT_POINTER
gimp_marshal_VOID__POINTER_BOXED
- gimp_marshal_VOID__POINTER_ENUM
+ gimp_marshal_VOID__POINTER_ENUM
gimp_marshal_VOID__STRING_BOOLEAN_UINT_FLAGS
gimp_marshal_VOID__STRING_FLAGS
gimp_message
diff --git a/app/path/gimppath.c b/app/path/gimppath.c
index 125bf53f2c..2f2a498cc8 100644
--- a/app/path/gimppath.c
+++ b/app/path/gimppath.c
@@ -40,6 +40,7 @@
#include "core/gimperror.h"
#include "core/gimpimage.h"
#include "core/gimpimage-undo-push.h"
+#include "core/gimpitemstack.h"
#include "core/gimppaintinfo.h"
#include "core/gimpstrokeoptions.h"
@@ -50,6 +51,8 @@
#include "gimppath.h"
#include "gimppath-preview.h"
#include "gimpstroke.h"
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayeroptions.h"
#include "gimp-intl.h"
@@ -164,6 +167,10 @@ static gint gimp_path_real_interpolate (GimpPath *path,
gint max_points,
GimpCoords *ret_coords);
+static gboolean gimp_path_attached_to_vector_layer_rec
+ (GimpPath *path,
+ GList *layers);
+
static GimpBezierDesc * gimp_path_make_bezier (GimpPath *path);
static GimpBezierDesc * gimp_path_real_make_bezier (GimpPath *path);
@@ -1200,6 +1207,84 @@ gimp_path_real_interpolate (GimpPath *path,
return 0;
}
+gboolean
+gimp_path_attached_to_vector_layer (GimpPath *path,
+ GimpImage *image)
+{
+ GList *layers;
+ GList *list;
+
+ g_return_val_if_fail (GIMP_IS_PATH (path), FALSE);
+ g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
+
+ layers = gimp_image_get_layer_iter (image);
+
+ for (list = layers; list; list = g_list_next (list))
+ {
+ if (GIMP_IS_VECTOR_LAYER (list->data))
+ {
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (list->data);
+
+ if (vector_layer->options &&
+ vector_layer->options->path &&
+ (path == vector_layer->options->path))
+ return TRUE;
+ }
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (list->data)))
+ {
+ GimpContainer *container;
+ GList *iter2;
+
+ container = gimp_viewable_get_children (GIMP_VIEWABLE (list->data));
+
+ iter2 =
+ gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container));
+
+ if (gimp_path_attached_to_vector_layer_rec (path, iter2))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gimp_path_attached_to_vector_layer_rec (GimpPath *path,
+ GList *layers)
+{
+ GList *list;
+
+ for (list = layers; list; list = g_list_next (list))
+ {
+ if (GIMP_IS_VECTOR_LAYER (list->data))
+ {
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (list->data);
+
+ if (vector_layer->options &&
+ vector_layer->options->path &&
+ (path == vector_layer->options->path))
+ return TRUE;
+ }
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (list->data)))
+ {
+ GimpContainer *container;
+ GList *iter2;
+
+ container = gimp_viewable_get_children (GIMP_VIEWABLE (list->data));
+
+ iter2 =
+ gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container));
+
+ if (gimp_path_attached_to_vector_layer_rec (path, iter2))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
const GimpBezierDesc *
gimp_path_get_bezier (GimpPath *path)
{
diff --git a/app/path/gimppath.h b/app/path/gimppath.h
index 1f8979b6e5..e92a569ff9 100644
--- a/app/path/gimppath.h
+++ b/app/path/gimppath.h
@@ -175,6 +175,9 @@ gint gimp_path_interpolate (GimpPath *path,
gint max_points,
GimpCoords *ret_coords);
+gboolean gimp_path_attached_to_vector_layer
+ (GimpPath *path,
+ GimpImage *image);
/* usually overloaded */
/* returns a bezier representation */
diff --git a/app/path/gimpvectorlayer-xcf.c b/app/path/gimpvectorlayer-xcf.c
new file mode 100644
index 0000000000..fadb64a37e
--- /dev/null
+++ b/app/path/gimpvectorlayer-xcf.c
@@ -0,0 +1,172 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayer-xcf.c
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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
+
+#include "libgimpbase/gimpbase.h"
+
+#include "path-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+#include "core/gimpparasitelist.h"
+
+#include "gimpvectorlayeroptions.h"
+#include "gimpvectorlayeroptions-parasite.h"
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayer-xcf.h"
+
+#include "gimp-intl.h"
+
+
+static GimpLayer * gimp_vector_layer_from_layer (GimpLayer *layer,
+ GimpVectorLayerOptions *options);
+
+
+gboolean
+gimp_vector_layer_xcf_load_hack (GimpLayer **layer)
+{
+ const gchar *name;
+ GimpVectorLayerOptions *options = NULL;
+ const GimpParasite *parasite;
+
+ g_return_val_if_fail (layer != NULL, FALSE);
+ g_return_val_if_fail (GIMP_IS_LAYER (*layer), FALSE);
+
+ name = gimp_vector_layer_options_parasite_name ();
+ parasite = gimp_item_parasite_find (GIMP_ITEM (*layer), name);
+
+ if (parasite)
+ {
+ GError *error = NULL;
+
+ options = gimp_vector_layer_options_from_parasite (
+ parasite, &error, gimp_item_get_image (GIMP_ITEM (*layer))->gimp);
+
+ g_object_set (G_OBJECT (options),
+ "path", gimp_image_get_path_by_tattoo (
+ gimp_item_get_image (GIMP_ITEM (*layer)),
+ options->path_tattoo),
+ NULL);
+
+ if (error)
+ {
+ g_message (_("Problems parsing the vector layer parasite for layer '%s':\n"
+ "%s\n\n"
+ "Some vector layer properties may be wrong. "),
+ gimp_object_get_name (GIMP_OBJECT (*layer)),
+ error->message);
+
+ g_error_free (error);
+ }
+ }
+
+ if (options)
+ {
+ *layer = gimp_vector_layer_from_layer (*layer, options);
+
+ /* let the text layer know what parasite was used to create it */
+ GIMP_VECTOR_LAYER (*layer)->parasite = name;
+ }
+
+ return (options != NULL);
+}
+
+void
+gimp_vector_layer_xcf_save_prepare (GimpVectorLayer *layer)
+{
+ GimpVectorLayerOptions *options;
+
+ g_return_if_fail (GIMP_IS_VECTOR_LAYER (layer));
+
+ /* If the layer has a text parasite already, it wasn't changed and we
+ * can simply save the original parasite back which is still attached.
+ */
+ if (layer->parasite)
+ return;
+
+ g_object_get (layer, "vector-layer-options", &options, NULL);
+ if (options)
+ {
+ GimpParasite *parasite = gimp_vector_layer_options_to_parasite (options);
+
+ gimp_parasite_list_add (gimp_item_get_parasites (GIMP_ITEM (layer)), parasite);
+ }
+}
+
+/**
+ * gimp_vector_layer_from_layer:
+ * @layer: a #GimpLayer object
+ * @options: a #GimpVectorLayerOptions object
+ *
+ * Converts a standard #GimpLayer and a #GimpVectorLayerOptions object
+ * into a #GimpVectorLayer. The new vector layer takes ownership of the
+ * @options and @layer objects. The @layer object is rendered unusable
+ * by this function. Don't even try to use it afterwards!
+ *
+ * This is a gross hack that is needed in order to load vector layers
+ * from XCF files in a backwards-compatible way. Please don't use it
+ * for anything else!
+ *
+ * Return value: a newly allocated #GimpVectorLayer object
+ **/
+static GimpLayer *
+gimp_vector_layer_from_layer (GimpLayer *layer,
+ GimpVectorLayerOptions *options)
+{
+ GimpVectorLayer *vector_layer;
+ GimpDrawable *drawable;
+
+ g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
+ g_return_val_if_fail (GIMP_IS_VECTOR_LAYER_OPTIONS (options), NULL);
+
+ vector_layer = g_object_new (GIMP_TYPE_VECTOR_LAYER,
+ "image", gimp_item_get_image (GIMP_ITEM (layer)),
+ "vector-layer-options", options,
+ NULL);
+
+ gimp_item_replace_item (GIMP_ITEM (vector_layer), GIMP_ITEM (layer));
+
+ drawable = GIMP_DRAWABLE (vector_layer);
+ gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (layer));
+
+ gimp_layer_set_opacity (GIMP_LAYER (vector_layer),
+ gimp_layer_get_opacity (layer), FALSE);
+ gimp_layer_set_mode (GIMP_LAYER (vector_layer),
+ gimp_layer_get_mode (layer), FALSE);
+ gimp_layer_set_blend_space (GIMP_LAYER (vector_layer),
+ gimp_layer_get_blend_space (layer), FALSE);
+ gimp_layer_set_composite_space (GIMP_LAYER (vector_layer),
+ gimp_layer_get_composite_space (layer), FALSE);
+ gimp_layer_set_composite_mode (GIMP_LAYER (vector_layer),
+ gimp_layer_get_composite_mode (layer), FALSE);
+ gimp_layer_set_lock_alpha (GIMP_LAYER (vector_layer),
+ gimp_layer_get_lock_alpha (layer), FALSE);
+
+ g_object_unref (options);
+ g_object_unref (layer);
+
+ return GIMP_LAYER (vector_layer);
+}
diff --git a/app/path/gimpvectorlayer-xcf.h b/app/path/gimpvectorlayer-xcf.h
new file mode 100644
index 0000000000..5757c7baa3
--- /dev/null
+++ b/app/path/gimpvectorlayer-xcf.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayer-xcf.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 .
+ */
+
+#ifndef __GIMP_VECTOR_LAYER_XCF_H__
+#define __GIMP_VECTOR_LAYER_XCF_H__
+
+
+const gchar * gimp_vector_layer_vector_parasite_name (void) G_GNUC_CONST;
+const gchar * gimp_vector_layer_fill_parasite_name (void) G_GNUC_CONST;
+const gchar * gimp_vector_layer_stroke_parasite_name (void) G_GNUC_CONST;
+gboolean gimp_vector_layer_xcf_load_hack (GimpLayer **layer);
+void gimp_vector_layer_xcf_save_prepare (GimpVectorLayer *layer);
+
+
+#endif /* __GIMP_VECTOR_LAYER_XCF_H__ */
diff --git a/app/path/gimpvectorlayer.c b/app/path/gimpvectorlayer.c
new file mode 100644
index 0000000000..70ea8b07c5
--- /dev/null
+++ b/app/path/gimpvectorlayer.c
@@ -0,0 +1,801 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayer.c
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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
+#include
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "path-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpdrawable-fill.h"
+#include "core/gimpdrawable-stroke.h"
+#include "core/gimpimage.h"
+#include "core/gimpselection.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpimage-undo-push.h"
+#include "core/gimpstrokeoptions.h"
+#include "core/gimpparasitelist.h"
+
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayeroptions.h"
+#include "gimppath.h"
+
+#include "gimp-intl.h"
+
+
+enum
+{
+ PROP_0,
+ PROP_VECTOR_LAYER_OPTIONS,
+ PROP_MODIFIED
+};
+
+
+/* local function declarations */
+
+static void gimp_vector_layer_finalize (GObject *object);
+static void gimp_vector_layer_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gimp_vector_layer_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_vector_layer_set_vector_options
+ (GimpVectorLayer *layer,
+ GimpVectorLayerOptions *options);
+
+static void gimp_vector_layer_set_buffer (GimpDrawable *drawable,
+ gboolean push_undo,
+ const gchar *undo_desc,
+ GeglBuffer *buffer,
+ const GeglRectangle *bounds);
+static void gimp_vector_layer_push_undo (GimpDrawable *drawable,
+ const gchar *undo_desc,
+ GeglBuffer *buffer,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+static gint64 gimp_vector_layer_get_memsize (GimpObject *object,
+ gint64 *gui_size);
+
+static GimpItem * gimp_vector_layer_duplicate (GimpItem *item,
+ GType new_type);
+
+static void gimp_vector_layer_translate (GimpLayer *layer,
+ gint offset_x,
+ gint offset_y);
+static void gimp_vector_layer_scale (GimpItem *item,
+ gint new_width,
+ gint new_height,
+ gint new_offset_x,
+ gint new_offset_y,
+ GimpInterpolationType interp_type,
+ GimpProgress *progress);
+static void gimp_vector_layer_flip (GimpItem *item,
+ GimpContext *context,
+ GimpOrientationType flip_type,
+ gdouble axis,
+ gboolean clip_result);
+static void gimp_vector_layer_rotate (GimpItem *item,
+ GimpContext *context,
+ GimpRotationType rotate_type,
+ gdouble center_x,
+ gdouble center_y,
+ gboolean clip_result);
+static void gimp_vector_layer_transform (GimpItem *item,
+ GimpContext *context,
+ const GimpMatrix3 *matrix,
+ GimpTransformDirection direction,
+ GimpInterpolationType interp_type,
+ GimpTransformResize clip_result,
+ GimpProgress *progress);
+
+static gboolean gimp_vector_layer_render (GimpVectorLayer *layer);
+static void gimp_vector_layer_render_path (GimpVectorLayer *layer);
+static void gimp_vector_layer_changed_options (GimpVectorLayer *layer);
+
+static void gimp_vector_layer_removed (GimpItem *item);
+
+static void gimp_vector_layer_removed_options_path
+ (GimpVectorLayer *layer);
+
+
+G_DEFINE_TYPE (GimpVectorLayer, gimp_vector_layer, GIMP_TYPE_LAYER)
+
+#define parent_class gimp_vector_layer_parent_class
+
+
+static void
+gimp_vector_layer_class_init (GimpVectorLayerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (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);
+
+ drawable_class->set_buffer = gimp_vector_layer_set_buffer;
+ drawable_class->push_undo = gimp_vector_layer_push_undo;
+
+ object_class->finalize = gimp_vector_layer_finalize;
+ object_class->set_property = gimp_vector_layer_set_property;
+ object_class->get_property = gimp_vector_layer_get_property;
+
+ gimp_object_class->get_memsize = gimp_vector_layer_get_memsize;
+
+ viewable_class->default_icon_name = "gimp-vector-layer";
+ viewable_class->default_name = _("Vector Layer");
+
+ layer_class->translate = gimp_vector_layer_translate;
+
+ item_class->removed = gimp_vector_layer_removed;
+ item_class->duplicate = gimp_vector_layer_duplicate;
+ item_class->scale = gimp_vector_layer_scale;
+ item_class->flip = gimp_vector_layer_flip;
+ item_class->rotate = gimp_vector_layer_rotate;
+ item_class->transform = gimp_vector_layer_transform;
+ item_class->rename_desc = _("Rename Vector Layer");
+ item_class->translate_desc = _("Move Vector Layer");
+ item_class->scale_desc = _("Scale Vector Layer");
+ item_class->resize_desc = _("Resize Vector Layer");
+ item_class->flip_desc = _("Flip Vector Layer");
+ item_class->rotate_desc = _("Rotate Vector Layer");
+ item_class->transform_desc = _("Transform Vector Layer");
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, PROP_VECTOR_LAYER_OPTIONS,
+ "vector-layer-options", NULL, NULL,
+ GIMP_TYPE_VECTOR_LAYER_OPTIONS,
+ G_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_MODIFIED,
+ "modified",
+ NULL, NULL,
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
+}
+
+static void
+gimp_vector_layer_init (GimpVectorLayer *layer)
+{
+ layer->options = NULL;
+ layer->parasite = NULL;
+ layer->modified = FALSE;
+}
+
+static void
+gimp_vector_layer_finalize (GObject *object)
+{
+ GimpVectorLayer *layer = GIMP_VECTOR_LAYER (object);
+
+ if (layer->options)
+ {
+ g_object_unref (layer->options);
+ layer->options = NULL;
+ }
+
+ if (layer->parasite)
+ {
+ gimp_parasite_list_remove (gimp_item_get_parasites (GIMP_ITEM (layer)),
+ layer->parasite);
+ layer->parasite = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_vector_layer_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (object);
+
+ switch (property_id)
+ {
+ case PROP_VECTOR_LAYER_OPTIONS:
+ g_value_set_object (value, vector_layer->options);
+ break;
+ case PROP_MODIFIED:
+ g_value_set_boolean (value, vector_layer->modified);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_vector_layer_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (object);
+
+ switch (property_id)
+ {
+ case PROP_VECTOR_LAYER_OPTIONS:
+ if (vector_layer->options)
+ {
+ g_signal_handlers_disconnect_by_func (vector_layer->options,
+ G_CALLBACK (gimp_vector_layer_changed_options),
+ vector_layer);
+ if (vector_layer->options->path)
+ g_signal_handlers_disconnect_by_func (vector_layer->options->path,
+ G_CALLBACK (gimp_vector_layer_removed_options_path),
+ vector_layer);
+
+ g_object_unref (vector_layer->options);
+ }
+
+ vector_layer->options = g_value_dup_object (value);
+
+ if (vector_layer->options)
+ {
+ if (vector_layer->options->path)
+ g_signal_connect_object (vector_layer->options->path, "removed",
+ G_CALLBACK (gimp_vector_layer_removed_options_path),
+ vector_layer, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (vector_layer->options, "notify",
+ G_CALLBACK (gimp_vector_layer_changed_options),
+ vector_layer, G_CONNECT_SWAPPED);
+
+ }
+ break;
+ case PROP_MODIFIED:
+ vector_layer->modified = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_vector_layer_set_vector_options (GimpVectorLayer *layer,
+ GimpVectorLayerOptions *options)
+{
+ if (layer->options)
+ {
+ g_signal_handlers_disconnect_by_func (layer->options,
+ G_CALLBACK (gimp_vector_layer_changed_options),
+ layer);
+ g_object_unref (layer->options);
+ }
+
+ layer->options = options;
+ gimp_vector_layer_changed_options (layer);
+
+ if (layer->options)
+ g_signal_connect_object (layer->options, "notify",
+ G_CALLBACK (gimp_vector_layer_changed_options),
+ layer, G_CONNECT_SWAPPED);
+}
+
+static void
+gimp_vector_layer_set_buffer (GimpDrawable *drawable,
+ gboolean push_undo,
+ const gchar *undo_desc,
+ GeglBuffer *buffer,
+ const GeglRectangle *bounds)
+{
+ GimpVectorLayer *layer = GIMP_VECTOR_LAYER (drawable);
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
+
+ if (push_undo && ! layer->modified)
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE_MOD,
+ undo_desc);
+
+ GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable,
+ push_undo, undo_desc,
+ buffer, bounds);
+
+ if (push_undo && ! layer->modified)
+ {
+ gimp_image_undo_push_vector_layer_modified (image, NULL, layer);
+
+ g_object_set (drawable, "modified", TRUE, NULL);
+
+ gimp_image_undo_group_end (image);
+ }
+}
+
+static void
+gimp_vector_layer_push_undo (GimpDrawable *drawable,
+ const gchar *undo_desc,
+ GeglBuffer *buffer,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GimpVectorLayer *layer = GIMP_VECTOR_LAYER (drawable);
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
+
+ if (! layer->modified)
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE, undo_desc);
+
+ GIMP_DRAWABLE_CLASS (parent_class)->push_undo (drawable, undo_desc,
+ buffer,
+ x, y, width, height);
+
+ if (! layer->modified)
+ {
+ gimp_image_undo_push_vector_layer_modified (image, NULL, layer);
+
+ g_object_set (drawable, "modified", TRUE, NULL);
+
+ gimp_image_undo_group_end (image);
+ }
+}
+
+static gint64
+gimp_vector_layer_get_memsize (GimpObject *object,
+ gint64 *gui_size)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (object);
+ gint64 memsize = 0;
+
+ memsize += gimp_object_get_memsize (GIMP_OBJECT (vector_layer->options),
+ gui_size);
+
+ return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+ gui_size);
+}
+
+static GimpItem *
+gimp_vector_layer_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);
+
+ if (GIMP_IS_VECTOR_LAYER (new_item))
+ {
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
+ GimpVectorLayer *new_vector_layer = GIMP_VECTOR_LAYER (new_item);
+
+ if (vector_layer->options)
+ {
+ GimpVectorLayerOptions *new_options =
+ gimp_config_duplicate (GIMP_CONFIG (vector_layer->options));
+
+ if (vector_layer->options->path)
+ {
+ GimpPath *path = gimp_vector_layer_get_path (vector_layer);
+ GimpPath *new_path;
+
+ new_path = GIMP_PATH (gimp_item_duplicate (GIMP_ITEM (path),
+ G_TYPE_FROM_INSTANCE (GIMP_ITEM (path))));
+
+ g_object_set (new_options, "path", new_path, NULL);
+ }
+
+ g_object_set (new_vector_layer,
+ "vector-layer-options", new_options,
+ NULL);
+ g_object_unref (new_options);
+ }
+ }
+
+ return new_item;
+}
+
+static void
+gimp_vector_layer_translate (GimpLayer *layer,
+ gint offset_x,
+ gint offset_y)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (layer);
+
+ if (vector_layer->options && vector_layer->options->path)
+ {
+ gimp_item_translate (GIMP_ITEM (vector_layer->options->path),
+ offset_x, offset_y, FALSE);
+ }
+ else
+ {
+ GIMP_LAYER_CLASS (parent_class)->translate (layer, offset_x, offset_y);
+ }
+}
+
+static void
+gimp_vector_layer_scale (GimpItem *item,
+ gint new_width,
+ gint new_height,
+ gint new_offset_x,
+ gint new_offset_y,
+ GimpInterpolationType interp_type,
+ GimpProgress *progress)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
+
+ if (vector_layer->options && vector_layer->options->path)
+ {
+ gimp_item_scale (GIMP_ITEM (vector_layer->options->path),
+ new_width, new_height, new_offset_x, new_offset_y,
+ interp_type, progress);
+ }
+ else
+ {
+ GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
+ new_offset_x, new_offset_y,
+ interp_type, progress);
+ }
+}
+
+static void
+gimp_vector_layer_flip (GimpItem *item,
+ GimpContext *context,
+ GimpOrientationType flip_type,
+ gdouble axis,
+ gboolean clip_result)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
+
+ if (vector_layer->options && vector_layer->options->path)
+ {
+ gimp_item_flip (GIMP_ITEM (vector_layer->options->path),
+ context, flip_type, axis, clip_result);
+ }
+ else
+ {
+ GIMP_ITEM_CLASS (parent_class)->flip (item, context, flip_type,
+ axis, clip_result);
+ }
+}
+
+static void
+gimp_vector_layer_rotate (GimpItem *item,
+ GimpContext *context,
+ GimpRotationType rotate_type,
+ gdouble center_x,
+ gdouble center_y,
+ gboolean clip_result)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
+
+ if (vector_layer->options && vector_layer->options->path)
+ {
+ gimp_item_rotate (GIMP_ITEM (vector_layer->options->path),
+ context, rotate_type, center_x, center_y, clip_result);
+ }
+ else
+ {
+ GIMP_ITEM_CLASS (parent_class)->rotate (item, context, rotate_type,
+ center_x, center_y, clip_result);
+ }
+}
+
+static void
+gimp_vector_layer_transform (GimpItem *item,
+ GimpContext *context,
+ const GimpMatrix3 *matrix,
+ GimpTransformDirection direction,
+ GimpInterpolationType interp_type,
+ GimpTransformResize clip_result,
+ GimpProgress *progress)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
+
+ if (vector_layer->options && vector_layer->options->path)
+ {
+ gimp_item_transform (GIMP_ITEM (vector_layer->options->path),
+ context, matrix, direction, interp_type,
+ clip_result, progress);
+ }
+ else
+ {
+ GIMP_ITEM_CLASS (parent_class)->transform (item, context, matrix,
+ direction, interp_type,
+ clip_result, progress);
+ }
+}
+
+static void
+gimp_vector_layer_removed_options_path (GimpVectorLayer *layer)
+{
+ if (layer->options)
+ {
+ gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
+ _("Discard Vector Informations"),
+ layer, NULL);
+
+ g_object_set (layer->options, "path", NULL, NULL);
+ }
+}
+
+static void
+gimp_vector_layer_removed (GimpItem *item)
+{
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
+
+ if (vector_layer->options && vector_layer->options->path)
+ g_signal_handlers_disconnect_by_func (vector_layer->options->path,
+ G_CALLBACK (gimp_vector_layer_removed_options_path),
+ vector_layer);
+
+ GIMP_ITEM_CLASS (parent_class)->removed (item);
+}
+
+
+/* public functions */
+
+/**
+ * gimp_vector_layer_new:
+ * @image: the #GimpImage the layer should belong to
+ * @path: the #GimpPath object the layer should render
+ * @context: the #GimpContext from which to pull context properties
+ *
+ * Creates a new vector layer.
+ *
+ * Return value: a new #GimpVectorLayer or %NULL in case of a problem
+ **/
+GimpVectorLayer *
+gimp_vector_layer_new (GimpImage *image,
+ GimpPath *path,
+ GimpContext *context)
+{
+ GimpVectorLayer *layer;
+ GimpVectorLayerOptions *options;
+ 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_IS_IMAGE (image), NULL);
+ g_return_val_if_fail (GIMP_IS_PATH (path), NULL);
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ options = gimp_vector_layer_options_new (image, path, context);
+
+ gimp_item_bounds (GIMP_ITEM (path), &x, &y, &width, &height);
+
+ /* Set boundaries to image size if it's a blank path */
+ if (width == 0 || height == 0)
+ {
+ width = gimp_image_get_width (image);
+ height = gimp_image_get_height (image);
+ }
+
+ layer =
+ GIMP_VECTOR_LAYER (gimp_drawable_new (GIMP_TYPE_VECTOR_LAYER,
+ image, NULL,
+ x, y, width, height,
+ gimp_image_get_layer_format (image,
+ TRUE)));
+
+ gimp_object_set_name (GIMP_OBJECT (layer),
+ gimp_object_get_name (GIMP_OBJECT (path)));
+
+ gimp_layer_set_mode (GIMP_LAYER (layer),
+ gimp_image_get_default_new_layer_mode (image),
+ FALSE);
+
+ gimp_vector_layer_set_vector_options (layer, options);
+
+ return layer;
+}
+
+/**
+ * gimp_vector_layer_get_path:
+ * @layer: a #GimpVectorLayer
+ *
+ * Gets the path from @layer if one is associated with it.
+ *
+ * Return value: a #GimpPath or %NULL if no path is set.
+ */
+GimpPath *
+gimp_vector_layer_get_path (GimpVectorLayer *layer)
+{
+ g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
+
+ if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
+ return layer->options->path;
+
+ return NULL;
+}
+
+void
+gimp_vector_layer_refresh (GimpVectorLayer *layer)
+{
+ if (layer->options)
+ gimp_vector_layer_render (layer);
+}
+
+/**
+ * gimp_vector_layer_discard:
+ * @layer: a #GimpVectorLayer
+ *
+ * Discards the vector information. This makes @layer behave like a
+ * normal layer.
+ */
+void
+gimp_vector_layer_discard (GimpVectorLayer *layer)
+{
+ g_return_if_fail (GIMP_IS_VECTOR_LAYER (layer));
+ g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)));
+
+ if (! layer->options)
+ return;
+
+ if (layer->options->path)
+ gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
+ _("Discard Vector Information"),
+ layer, NULL);
+
+ g_object_set (layer, "vector-layer-options", NULL, NULL);
+
+ gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer));
+ gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
+}
+
+gboolean
+gimp_item_is_vector_layer (GimpItem *item)
+{
+ return (GIMP_IS_VECTOR_LAYER (item) &&
+ GIMP_VECTOR_LAYER (item)->options);
+}
+
+
+/* private functions */
+
+static gboolean
+gimp_vector_layer_render (GimpVectorLayer *layer)
+{
+ GimpDrawable *drawable = GIMP_DRAWABLE (layer);
+ GeglBuffer *buffer = NULL;
+ GimpItem *item = GIMP_ITEM (layer);
+ GimpImage *image = gimp_item_get_image (item);
+ gint layer_x = 0;
+ gint layer_y = 0;
+ gint x = 0;
+ gint y = 0;
+ gint width = gimp_image_get_width (image);
+ gint height = gimp_image_get_height (image);
+ gdouble stroke = 0;
+
+ g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
+
+ g_object_freeze_notify (G_OBJECT (drawable));
+
+ if (layer->options->enable_stroke)
+ stroke = gimp_stroke_options_get_width (layer->options->stroke_options);
+
+ /* Resize layer according to path size */
+ gimp_item_get_offset (GIMP_ITEM (layer), &layer_x, &layer_y);
+ gimp_item_bounds (GIMP_ITEM (layer->options->path), &x, &y, &width, &height);
+
+ buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+ width + stroke, height + stroke),
+ gimp_drawable_get_format (drawable));
+ gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
+ g_object_unref (buffer);
+
+ gimp_item_set_offset (GIMP_ITEM (layer), x - (stroke / 2), y - (stroke / 2));
+
+ /* make the layer background transparent */
+ gimp_drawable_fill (GIMP_DRAWABLE (layer),
+ gimp_get_user_context (image->gimp),
+ GIMP_FILL_TRANSPARENT);
+
+ /* render path to the layer */
+ gimp_vector_layer_render_path (layer);
+
+ g_object_thaw_notify (G_OBJECT (drawable));
+
+ return TRUE;
+}
+
+static void
+gimp_vector_layer_render_path (GimpVectorLayer *layer)
+{
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
+ GimpVectorLayerOptions *options = layer->options;
+ GimpPath *path = NULL;
+ GimpChannel *selection = gimp_image_get_mask (image);
+ GList *drawables;
+ GimpCustomStyle style;
+
+ if (options)
+ path = options->path;
+
+ /* Don't mask these fill/stroke operations */
+ gimp_selection_suspend (GIMP_SELECTION (selection));
+
+ /* Convert from custom to standard styles */
+ style = gimp_fill_options_get_custom_style (options->fill_options);
+ if (style == GIMP_CUSTOM_STYLE_SOLID_COLOR ||
+ ! gimp_context_get_pattern (GIMP_CONTEXT (options->fill_options)))
+ gimp_fill_options_set_style (options->fill_options,
+ GIMP_FILL_STYLE_FG_COLOR);
+ else
+ gimp_fill_options_set_style (options->fill_options,
+ GIMP_FILL_STYLE_PATTERN);
+
+ style =
+ gimp_fill_options_get_custom_style (GIMP_FILL_OPTIONS (options->stroke_options));
+ if (style == GIMP_CUSTOM_STYLE_SOLID_COLOR ||
+ ! gimp_context_get_pattern (GIMP_CONTEXT (options->stroke_options)))
+ gimp_fill_options_set_style (GIMP_FILL_OPTIONS (options->stroke_options),
+ GIMP_FILL_STYLE_FG_COLOR);
+ else
+ gimp_fill_options_set_style (GIMP_FILL_OPTIONS (options->stroke_options),
+ GIMP_FILL_STYLE_PATTERN);
+
+ /* Fill the path object onto the layer */
+ if (options->enable_fill)
+ gimp_drawable_fill_path (GIMP_DRAWABLE (layer),
+ options->fill_options,
+ path, FALSE, NULL);
+
+ drawables = g_list_prepend (NULL, GIMP_DRAWABLE (layer));
+ /* stroke the path object onto the layer */
+ if (options->enable_stroke && gimp_item_is_attached (GIMP_ITEM (path)))
+ gimp_item_stroke (GIMP_ITEM (path), drawables,
+ gimp_get_user_context (image->gimp),
+ options->stroke_options,
+ FALSE, FALSE,
+ NULL, NULL);
+
+ g_list_free (drawables);
+
+ gimp_selection_resume (GIMP_SELECTION (selection));
+}
+
+static void
+gimp_vector_layer_changed_options (GimpVectorLayer *layer)
+{
+ GimpItem *item = GIMP_ITEM (layer);
+
+ if (layer->parasite)
+ {
+ /* parasite is out of date, discard it */
+ gimp_parasite_list_remove (gimp_item_get_parasites (GIMP_ITEM (layer)),
+ layer->parasite);
+ layer->parasite = NULL;
+ }
+
+ if (layer->options && !layer->options->path)
+ gimp_vector_layer_discard (layer);
+ else if (gimp_item_is_attached (item))
+ gimp_vector_layer_refresh (layer);
+}
diff --git a/app/path/gimpvectorlayer.h b/app/path/gimpvectorlayer.h
new file mode 100644
index 0000000000..ebca98d963
--- /dev/null
+++ b/app/path/gimpvectorlayer.h
@@ -0,0 +1,69 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayer.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 .
+ */
+
+#ifndef __GIMP_VECTOR_LAYER_H__
+#define __GIMP_VECTOR_LAYER_H__
+
+
+#include "core/gimplayer.h"
+
+
+#define GIMP_TYPE_VECTOR_LAYER (gimp_vector_layer_get_type ())
+#define GIMP_VECTOR_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTOR_LAYER, GimpVectorLayer))
+#define GIMP_VECTOR_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTOR_LAYER, GimpVectorLayerClass))
+#define GIMP_IS_VECTOR_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTOR_LAYER))
+#define GIMP_IS_VECTOR_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_VECTOR_LAYER))
+#define GIMP_VECTOR_LAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_VECTOR_LAYER, GimpVectorLayerClass))
+
+
+typedef struct _GimpVectorLayerClass GimpVectorLayerClass;
+
+struct _GimpVectorLayer
+{
+ GimpLayer parent_instance;
+
+ GimpVectorLayerOptions *options;
+ const gchar *parasite;
+
+ gboolean modified;
+};
+
+struct _GimpVectorLayerClass
+{
+ GimpLayerClass parent_class;
+};
+
+
+GType gimp_vector_layer_get_type (void) G_GNUC_CONST;
+
+GimpVectorLayer * gimp_vector_layer_new (GimpImage *image,
+ GimpPath *path,
+ GimpContext *context);
+
+GimpPath * gimp_vector_layer_get_path (GimpVectorLayer *layer);
+
+void gimp_vector_layer_refresh (GimpVectorLayer *layer);
+void gimp_vector_layer_discard (GimpVectorLayer *layer);
+
+gboolean gimp_item_is_vector_layer (GimpItem *item);
+
+
+#endif /* __GIMP_VECTOR_LAYER_H__ */
diff --git a/app/path/gimpvectorlayeroptions-parasite.c b/app/path/gimpvectorlayeroptions-parasite.c
new file mode 100644
index 0000000000..488174909b
--- /dev/null
+++ b/app/path/gimpvectorlayeroptions-parasite.c
@@ -0,0 +1,95 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayeroptions-parasite.c
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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
+#include
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "path-types.h"
+
+#include "gimpvectorlayeroptions.h"
+#include "gimpvectorlayeroptions-parasite.h"
+
+#include "gimp-intl.h"
+
+
+const gchar *
+gimp_vector_layer_options_parasite_name (void)
+{
+ return "gimp-vector-layer-options";
+}
+
+GimpParasite *
+gimp_vector_layer_options_to_parasite (GimpVectorLayerOptions *options)
+{
+ GimpParasite *parasite;
+ gchar *str;
+
+ g_return_val_if_fail (GIMP_IS_VECTOR_LAYER_OPTIONS (options), NULL);
+
+ str = gimp_config_serialize_to_string (GIMP_CONFIG (options), NULL);
+ g_return_val_if_fail (str != NULL, NULL);
+
+ parasite = gimp_parasite_new (gimp_vector_layer_options_parasite_name (),
+ GIMP_PARASITE_PERSISTENT,
+ strlen (str) + 1, str);
+ g_free (str);
+
+ return parasite;
+}
+
+GimpVectorLayerOptions *
+gimp_vector_layer_options_from_parasite (const GimpParasite *parasite,
+ GError **error,
+ Gimp *gimp)
+{
+ GimpVectorLayerOptions *options;
+ const gchar *str;
+ guint32 parasite_length;
+
+ g_return_val_if_fail (parasite != NULL, NULL);
+ g_return_val_if_fail (strcmp (gimp_parasite_get_name (parasite),
+ gimp_vector_layer_options_parasite_name ()) == 0,
+ NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ str = gimp_parasite_get_data (parasite, ¶site_length);
+ g_return_val_if_fail (str != NULL, NULL);
+
+ options = g_object_new (GIMP_TYPE_VECTOR_LAYER_OPTIONS,
+ "gimp", gimp,
+ NULL);
+
+ gimp_config_deserialize_string (GIMP_CONFIG (options),
+ str,
+ parasite_length,
+ NULL,
+ error);
+
+ return options;
+}
diff --git a/app/path/gimpvectorlayeroptions-parasite.h b/app/path/gimpvectorlayeroptions-parasite.h
new file mode 100644
index 0000000000..7765cb6c67
--- /dev/null
+++ b/app/path/gimpvectorlayeroptions-parasite.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayeroptions-parasite.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 .
+ */
+
+#ifndef __GIMP_VECTOR_LAYER_OPTIONS_PARASITE_H__
+#define __GIMP_VECTOR_LAYER_OPTIONS_PARASITE_H__
+
+
+const gchar * gimp_vector_layer_options_parasite_name (void) G_GNUC_CONST;
+GimpParasite * gimp_vector_layer_options_to_parasite (GimpVectorLayerOptions *text);
+GimpVectorLayerOptions * gimp_vector_layer_options_from_parasite (const GimpParasite *parasite,
+ GError **error,
+ Gimp *gimp);
+
+
+#endif /* __GIMP_VECTOR_LAYER_OPTIONS_PARASITE_H__ */
diff --git a/app/path/gimpvectorlayeroptions.c b/app/path/gimpvectorlayeroptions.c
new file mode 100644
index 0000000000..eda0f68ab5
--- /dev/null
+++ b/app/path/gimpvectorlayeroptions.c
@@ -0,0 +1,364 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayers.c
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpcolor/gimpcolor.h"
+
+#include "path-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+#include "core/gimpstrokeoptions.h"
+
+#include "gimppath.h"
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayeroptions.h"
+
+#include "gimp-intl.h"
+
+
+enum
+{
+ PROP_0,
+ PROP_GIMP,
+ PROP_PATH,
+ PROP_PATH_TATTOO,
+ PROP_ENABLE_FILL,
+ PROP_FILL_OPTIONS,
+ PROP_ENABLE_STROKE,
+ PROP_STROKE_OPTIONS
+};
+
+
+/* local function declarations */
+
+static GObject *gimp_vector_layer_options_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params);
+static void gimp_vector_layer_options_finalize (GObject *object);
+
+static void gimp_vector_layer_options_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gimp_vector_layer_options_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_vector_layer_options_path_changed (GimpVectorLayerOptions *options);
+
+
+G_DEFINE_TYPE_WITH_CODE (GimpVectorLayerOptions,
+ gimp_vector_layer_options,
+ GIMP_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG, NULL))
+
+#define parent_class gimp_vector_layer_options_parent_class
+
+
+static void
+gimp_vector_layer_options_class_init (GimpVectorLayerOptionsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = gimp_vector_layer_options_constructor;
+ object_class->finalize = gimp_vector_layer_options_finalize;
+ object_class->set_property = gimp_vector_layer_options_set_property;
+ object_class->get_property = gimp_vector_layer_options_get_property;
+
+ g_object_class_install_property (object_class, PROP_GIMP,
+ g_param_spec_object ("gimp",
+ NULL, NULL,
+ GIMP_TYPE_GIMP,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, PROP_PATH,
+ "path", NULL, NULL,
+ GIMP_TYPE_PATH,
+ GIMP_PARAM_READWRITE |
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_UINT (object_class, PROP_PATH_TATTOO,
+ "path-tattoo", NULL, NULL,
+ 0, G_MAXUINT32, 0,
+ G_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_FILL,
+ "enable-fill",
+ _("Fill Style"), NULL,
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FILL_OPTIONS,
+ "fill-options", NULL, NULL,
+ GIMP_TYPE_FILL_OPTIONS,
+ G_PARAM_STATIC_STRINGS |
+ GIMP_CONFIG_PARAM_AGGREGATE);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_STROKE,
+ "enable-stroke",
+ _("Stroke Style"), NULL,
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, PROP_STROKE_OPTIONS,
+ "stroke-options", NULL, NULL,
+ GIMP_TYPE_STROKE_OPTIONS,
+ G_PARAM_STATIC_STRINGS |
+ GIMP_CONFIG_PARAM_AGGREGATE);
+}
+
+static void
+gimp_vector_layer_options_init (GimpVectorLayerOptions *options)
+{
+ options->path = NULL;
+ options->path_tattoo = 0;
+}
+
+static GObject *
+gimp_vector_layer_options_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
+{
+ GObject *object;
+ GimpVectorLayerOptions *options;
+
+ object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
+
+ options = GIMP_VECTOR_LAYER_OPTIONS (object);
+ g_assert (GIMP_IS_GIMP (options->gimp));
+
+ options->fill_options = gimp_fill_options_new (options->gimp, NULL, FALSE);
+ options->stroke_options = gimp_stroke_options_new (options->gimp, NULL, FALSE);
+
+ return object;
+}
+
+static void
+gimp_vector_layer_options_finalize (GObject *object)
+{
+ GimpVectorLayerOptions *options = GIMP_VECTOR_LAYER_OPTIONS (object);
+
+ if (options->path)
+ {
+ g_object_unref (options->path);
+ options->path = NULL;
+ }
+
+ if (options->fill_options)
+ {
+ g_object_unref (options->fill_options);
+ options->fill_options = NULL;
+ }
+
+ if (options->stroke_options)
+ {
+ g_object_unref (options->stroke_options);
+ options->stroke_options = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_vector_layer_options_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpVectorLayerOptions *options = GIMP_VECTOR_LAYER_OPTIONS (object);
+
+ switch (property_id)
+ {
+ case PROP_GIMP:
+ g_value_set_object (value, options->gimp);
+ break;
+ case PROP_PATH:
+ g_value_set_object (value, options->path);
+ break;
+ case PROP_PATH_TATTOO:
+ g_value_set_uint (value, options->path_tattoo);
+ break;
+ case PROP_ENABLE_FILL:
+ g_value_set_boolean (value, options->enable_fill);
+ break;
+ case PROP_FILL_OPTIONS:
+ g_value_set_object (value, options->fill_options);
+ break;
+ case PROP_ENABLE_STROKE:
+ g_value_set_boolean (value, options->enable_stroke);
+ break;
+ case PROP_STROKE_OPTIONS:
+ g_value_set_object (value, options->stroke_options);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_vector_layer_options_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpVectorLayerOptions *options = GIMP_VECTOR_LAYER_OPTIONS (object);
+
+ switch (property_id)
+ {
+ case PROP_GIMP:
+ options->gimp = g_value_get_object (value);
+ break;
+
+ case PROP_PATH:
+ if (options->path)
+ {
+ g_signal_handlers_disconnect_by_func (options->path,
+ G_CALLBACK (gimp_vector_layer_options_path_changed),
+ options);
+ g_object_unref (options->path);
+ }
+
+ options->path = g_value_dup_object (value);
+
+ if (options->path)
+ {
+ g_signal_connect_object (options->path, "invalidate-preview",
+ G_CALLBACK (gimp_vector_layer_options_path_changed),
+ options, G_CONNECT_SWAPPED);
+ g_signal_connect_object (options->path, "name-changed",
+ G_CALLBACK (gimp_vector_layer_options_path_changed),
+ options, G_CONNECT_SWAPPED);
+
+ /* update the tattoo */
+ options->path_tattoo = gimp_item_get_tattoo (GIMP_ITEM (options->path));
+ }
+ break;
+
+ case PROP_PATH_TATTOO:
+ options->path_tattoo = g_value_get_uint (value);
+
+ if (options->path &&
+ gimp_item_get_tattoo (GIMP_ITEM (options->path)) != options->path_tattoo)
+ {
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (options->path));
+
+ g_object_set (options,
+ "path", gimp_image_get_path_by_tattoo
+ (image, options->path_tattoo),
+ NULL);
+ }
+ break;
+
+ case PROP_ENABLE_FILL:
+ options->enable_fill = g_value_get_boolean (value);
+ break;
+
+ case PROP_FILL_OPTIONS:
+ if (g_value_get_object (value))
+ gimp_config_sync (g_value_get_object (value),
+ G_OBJECT (options->fill_options), 0);
+ break;
+
+ case PROP_ENABLE_STROKE:
+ options->enable_stroke = g_value_get_boolean (value);
+ break;
+
+ case PROP_STROKE_OPTIONS:
+ if (g_value_get_object (value))
+ {
+ if (options->stroke_options)
+ g_object_unref (options->stroke_options);
+ options->stroke_options = gimp_config_duplicate (g_value_get_object (value));
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_vector_layer_options_path_changed (GimpVectorLayerOptions *options)
+{
+ g_object_notify (G_OBJECT (options), "path");
+}
+
+
+/* public functions */
+
+/**
+ * gimp_vector_layer_options_new:
+ * @image: the #GimpImage the layer belongs to
+ * @path: the #GimpPath object for the layer to render
+ * @context: the #GimpContext from which to pull context properties
+ *
+ * Creates a new vector layer options.
+ *
+ * Return value: a new #GimpVectorLayerOptions or %NULL in case of a problem
+ **/
+GimpVectorLayerOptions *
+gimp_vector_layer_options_new (GimpImage *image,
+ GimpPath *path,
+ GimpContext *context)
+{
+ GimpVectorLayerOptions *options;
+ GimpPattern *pattern;
+ GeglColor *stroke_color;
+ GeglColor *fill_color;
+
+ 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 (GIMP_IS_CONTEXT (context), NULL);
+
+ options = g_object_new (GIMP_TYPE_VECTOR_LAYER_OPTIONS,
+ "gimp", image->gimp,
+ NULL);
+
+ stroke_color = gimp_context_get_foreground (context);
+ fill_color = gimp_context_get_background (context);
+ pattern = gimp_context_get_pattern (context);
+
+ gimp_context_set_foreground (GIMP_CONTEXT (options->fill_options),
+ fill_color);
+ gimp_context_set_pattern (GIMP_CONTEXT (options->fill_options), pattern);
+
+ gimp_context_set_foreground (GIMP_CONTEXT (options->stroke_options),
+ stroke_color);
+ gimp_context_set_pattern (GIMP_CONTEXT (options->stroke_options), pattern);
+
+ g_object_set (options,
+ "path", path,
+ NULL);
+
+ return options;
+}
diff --git a/app/path/gimpvectorlayeroptions.h b/app/path/gimpvectorlayeroptions.h
new file mode 100644
index 0000000000..97a90515a4
--- /dev/null
+++ b/app/path/gimpvectorlayeroptions.h
@@ -0,0 +1,66 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayeroptions.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 .
+ */
+
+#ifndef __GIMP_VECTOR_LAYER_OPTIONS_H__
+#define __GIMP_VECTOR_LAYER_OPTIONS_H__
+
+
+#include "core/gimpobject.h"
+
+
+#define GIMP_TYPE_VECTOR_LAYER_OPTIONS (gimp_vector_layer_options_get_type ())
+#define GIMP_VECTOR_LAYER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTOR_LAYER_OPTIONS, GimpVectorLayerOptions))
+#define GIMP_VECTOR_LAYER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTOR_LAYER_OPTIONS, GimpVectorLayerOptionsClass))
+#define GIMP_IS_VECTOR_LAYER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTOR_LAYER_OPTIONS))
+#define GIMP_IS_VECTOR_LAYER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_VECTOR_LAYER_OPTIONS))
+#define GIMP_VECTOR_LAYER_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_VECTOR_LAYER_OPTIONS, GimpVectorLayerOptionsClass))
+
+
+typedef struct _GimpVectorLayerOptionsClass GimpVectorLayerOptionsClass;
+
+struct _GimpVectorLayerOptions
+{
+ GimpObject parent_instance;
+
+ Gimp *gimp;
+
+ GimpTattoo path_tattoo;
+ GimpPath *path;
+
+ gboolean enable_fill;
+ gboolean enable_stroke;
+ GimpFillOptions *fill_options;
+ GimpStrokeOptions *stroke_options;
+};
+
+struct _GimpVectorLayerOptionsClass
+{
+ GimpObjectClass parent_class;
+};
+
+GType gimp_vector_layer_options_get_type (void) G_GNUC_CONST;
+
+GimpVectorLayerOptions * gimp_vector_layer_options_new (GimpImage *image,
+ GimpPath *path,
+ GimpContext *context);
+
+
+#endif /* __GIMP_VECTOR_LAYER_OPTIONS_H__ */
diff --git a/app/path/gimpvectorlayerundo.c b/app/path/gimpvectorlayerundo.c
new file mode 100644
index 0000000000..c002d9aed0
--- /dev/null
+++ b/app/path/gimpvectorlayerundo.c
@@ -0,0 +1,288 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayerundo.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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
+
+#include "libgimpconfig/gimpconfig.h"
+
+#include "path-types.h"
+
+#include "core/gimp-memsize.h"
+#include "core/gimpitem.h"
+#include "core/gimpitemundo.h"
+#include "core/gimp-utils.h"
+
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayeroptions.h"
+#include "gimpvectorlayerundo.h"
+
+enum
+{
+ PROP_0,
+ PROP_PARAM
+};
+
+
+static void gimp_vector_layer_undo_constructed (GObject *object);
+static void gimp_vector_layer_undo_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_vector_layer_undo_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+static gint64 gimp_vector_layer_undo_get_memsize (GimpObject *object,
+ gint64 *gui_size);
+static void gimp_vector_layer_undo_pop (GimpUndo *undo,
+ GimpUndoMode undo_mode,
+ GimpUndoAccumulator *accum);
+static void gimp_vector_layer_undo_free (GimpUndo *undo,
+ GimpUndoMode undo_mode);
+
+
+
+G_DEFINE_TYPE (GimpVectorLayerUndo, gimp_vector_layer_undo, GIMP_TYPE_ITEM_UNDO)
+
+#define parent_class gimp_vector_layer_undo_parent_class
+
+
+static void
+gimp_vector_layer_undo_class_init (GimpVectorLayerUndoClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
+ GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass);
+
+ object_class->constructed = gimp_vector_layer_undo_constructed;
+ object_class->set_property = gimp_vector_layer_undo_set_property;
+ object_class->get_property = gimp_vector_layer_undo_get_property;
+
+ gimp_object_class->get_memsize = gimp_vector_layer_undo_get_memsize;
+
+ undo_class->pop = gimp_vector_layer_undo_pop;
+ undo_class->free = gimp_vector_layer_undo_free;
+
+ g_object_class_install_property (object_class, PROP_PARAM,
+ g_param_spec_param ("param", NULL, NULL,
+ G_TYPE_PARAM,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gimp_vector_layer_undo_init (GimpVectorLayerUndo *undo)
+{
+}
+
+static void
+gimp_vector_layer_undo_constructed (GObject *object)
+{
+ GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (object);
+ GimpVectorLayer *vector_layer;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ g_assert (GIMP_IS_VECTOR_LAYER (GIMP_ITEM_UNDO (vector_undo)->item));
+
+ vector_layer = GIMP_VECTOR_LAYER (GIMP_ITEM_UNDO (vector_undo)->item);
+
+ switch (GIMP_UNDO (object)->undo_type)
+ {
+ case GIMP_UNDO_VECTOR_LAYER:
+ if (vector_undo->pspec)
+ {
+ g_assert (vector_undo->pspec->owner_type == GIMP_TYPE_VECTOR_LAYER_OPTIONS);
+
+ vector_undo->value = g_slice_new0 (GValue);
+
+ g_value_init (vector_undo->value, vector_undo->pspec->value_type);
+ g_object_get_property (G_OBJECT (vector_layer->options),
+ vector_undo->pspec->name, vector_undo->value);
+ }
+ else if (vector_layer->options)
+ {
+ vector_undo->vector_layer_options = gimp_config_duplicate (GIMP_CONFIG (vector_layer->options));
+ }
+ break;
+
+ case GIMP_UNDO_VECTOR_LAYER_MODIFIED:
+ vector_undo->modified = vector_layer->modified;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+gimp_vector_layer_undo_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (object);
+
+ switch (property_id)
+ {
+ case PROP_PARAM:
+ vector_undo->pspec = g_value_get_param (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_vector_layer_undo_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (object);
+
+ switch (property_id)
+ {
+ case PROP_PARAM:
+ g_value_set_param (value, (GParamSpec *) vector_undo->pspec);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gint64
+gimp_vector_layer_undo_get_memsize (GimpObject *object,
+ gint64 *gui_size)
+{
+ GimpVectorLayerUndo *undo = GIMP_VECTOR_LAYER_UNDO (object);
+ gint64 memsize = 0;
+
+ memsize += gimp_g_value_get_memsize (undo->value);
+ memsize += gimp_object_get_memsize (GIMP_OBJECT (undo->vector_layer_options), NULL);
+
+ return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+ gui_size);
+}
+
+static void
+gimp_vector_layer_undo_pop (GimpUndo *undo,
+ GimpUndoMode undo_mode,
+ GimpUndoAccumulator *accum)
+{
+ GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (undo);
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (GIMP_ITEM_UNDO (undo)->item);
+
+ GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
+
+ switch (undo->undo_type)
+ {
+ case GIMP_UNDO_VECTOR_LAYER:
+ if (vector_undo->pspec)
+ {
+ GValue *value;
+
+ g_return_if_fail (vector_layer->options != NULL);
+
+ value = g_slice_new0 (GValue);
+ g_value_init (value, vector_undo->pspec->value_type);
+
+ g_object_get_property (G_OBJECT (vector_layer->options),
+ vector_undo->pspec->name, value);
+
+ g_object_set_property (G_OBJECT (vector_layer->options),
+ vector_undo->pspec->name, vector_undo->value);
+
+ g_value_unset (vector_undo->value);
+ g_slice_free (GValue, vector_undo->value);
+
+ vector_undo->value = value;
+ }
+ else
+ {
+ GimpVectorLayerOptions *vector_layer_options;
+
+ vector_layer_options = (vector_layer->options ?
+ gimp_config_duplicate (GIMP_CONFIG (vector_layer->options)) : NULL);
+
+ if (vector_layer->options && vector_undo->vector_layer_options)
+ gimp_config_sync (G_OBJECT (vector_undo->vector_layer_options),
+ G_OBJECT (vector_layer->options), 0);
+ else
+ g_object_set (vector_layer,
+ "vector-layer-options", vector_undo->vector_layer_options,
+ NULL);
+
+ if (vector_undo->vector_layer_options)
+ g_object_unref (vector_undo->vector_layer_options);
+
+ vector_undo->vector_layer_options = vector_layer_options;
+ }
+ break;
+
+ case GIMP_UNDO_VECTOR_LAYER_MODIFIED:
+ {
+ gboolean modified;
+
+ modified = vector_layer->modified;
+ g_object_set (vector_layer, "modified", vector_undo->modified, NULL);
+ vector_undo->modified = modified;
+
+ gimp_viewable_invalidate_preview (GIMP_VIEWABLE (vector_layer));
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+gimp_vector_layer_undo_free (GimpUndo *undo,
+ GimpUndoMode undo_mode)
+{
+ GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (undo);
+
+ if (vector_undo->vector_layer_options)
+ {
+ g_object_unref (vector_undo->vector_layer_options);
+ vector_undo->vector_layer_options = NULL;
+ }
+
+ if (vector_undo->pspec)
+ {
+ g_value_unset (vector_undo->value);
+ g_slice_free (GValue, vector_undo->value);
+
+ vector_undo->value = NULL;
+ vector_undo->pspec = NULL;
+ }
+
+ GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode);
+}
diff --git a/app/path/gimpvectorlayerundo.h b/app/path/gimpvectorlayerundo.h
new file mode 100644
index 0000000000..37894a3b92
--- /dev/null
+++ b/app/path/gimpvectorlayerundo.h
@@ -0,0 +1,58 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpvectorlayerundo.h
+ *
+ * Copyright 2006 Hendrik Boom
+ *
+ * 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 .
+ */
+
+#ifndef __GIMP_VECTOR_LAYER_UNDO_H__
+#define __GIMP_VECTOR_LAYER_UNDO_H__
+
+
+#include "core/gimpitemundo.h"
+
+
+#define GIMP_TYPE_VECTOR_LAYER_UNDO (gimp_vector_layer_undo_get_type ())
+#define GIMP_VECTOR_LAYER_UNDO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTOR_LAYER_UNDO, GimpVectorLayerUndo))
+#define GIMP_VECTOR_LAYER_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTOR_LAYER_UNDO, GimpVectorLayerUndoClass))
+#define GIMP_IS_VECTOR_LAYER_UNDO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTOR_LAYER_UNDO))
+#define GIMP_IS_VECTOR_LAYER_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_VECTOR_LAYER_UNDO))
+#define GIMP_VECTOR_LAYER_UNDO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_VECTOR_LAYER_UNDO, GimpVectorLayerUndoClass))
+
+
+typedef struct _GimpVectorLayerUndoClass GimpVectorLayerUndoClass;
+
+struct _GimpVectorLayerUndo
+{
+ GimpItemUndo parent_instance;
+
+ GimpVectorLayerOptions *vector_layer_options;
+ const GParamSpec *pspec;
+ GValue *value;
+ gboolean modified;
+};
+
+struct _GimpVectorLayerUndoClass
+{
+ GimpItemClass parent_class;
+};
+
+
+GType gimp_vector_layer_undo_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_VECTOR_LAYER_UNDO_H__ */
diff --git a/app/path/meson.build b/app/path/meson.build
index aafc83890a..feb5b2081e 100644
--- a/app/path/meson.build
+++ b/app/path/meson.build
@@ -12,6 +12,11 @@ libapppath_sources = [
'gimppathundo.c',
'gimpstroke-new.c',
'gimpstroke.c',
+ 'gimpvectorlayer.c',
+ 'gimpvectorlayer-xcf.c',
+ 'gimpvectorlayeroptions.c',
+ 'gimpvectorlayeroptions-parasite.c',
+ 'gimpvectorlayerundo.c',
]
libapppath = static_library('apppath',
diff --git a/app/path/path-types.h b/app/path/path-types.h
index ab5a69f1ce..b2f9217748 100644
--- a/app/path/path-types.h
+++ b/app/path/path-types.h
@@ -25,8 +25,12 @@
#include "path-enums.h"
-typedef struct _GimpAnchor GimpAnchor;
+typedef struct _GimpAnchor GimpAnchor;
-typedef struct _GimpPath GimpPath;
-typedef struct _GimpStroke GimpStroke;
-typedef struct _GimpBezierStroke GimpBezierStroke;
+typedef struct _GimpPath GimpPath;
+typedef struct _GimpStroke GimpStroke;
+typedef struct _GimpBezierStroke GimpBezierStroke;
+
+typedef struct _GimpVectorLayer GimpVectorLayer;
+typedef struct _GimpVectorLayerOptions GimpVectorLayerOptions;
+typedef struct _GimpVectorLayerUndo GimpVectorLayerUndo;
diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c
index 124df49769..6e60775639 100644
--- a/app/pdb/internal-procs.c
+++ b/app/pdb/internal-procs.c
@@ -30,7 +30,7 @@
#include "internal-procs.h"
-/* 721 procedures registered total */
+/* 725 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)
@@ -94,4 +94,5 @@ internal_procs_init (GimpPDB *pdb)
register_text_layer_procs (pdb);
register_text_tool_procs (pdb);
register_unit_procs (pdb);
+ register_vector_layer_procs (pdb);
}
diff --git a/app/pdb/internal-procs.h b/app/pdb/internal-procs.h
index ac6aadd206..2bddfd3bd7 100644
--- a/app/pdb/internal-procs.h
+++ b/app/pdb/internal-procs.h
@@ -81,3 +81,4 @@ void register_selection_procs (GimpPDB *pdb);
void register_text_layer_procs (GimpPDB *pdb);
void register_text_tool_procs (GimpPDB *pdb);
void register_unit_procs (GimpPDB *pdb);
+void register_vector_layer_procs (GimpPDB *pdb);
diff --git a/app/pdb/item-cmds.c b/app/pdb/item-cmds.c
index 4edccd6871..3c4ee01ac1 100644
--- a/app/pdb/item-cmds.c
+++ b/app/pdb/item-cmds.c
@@ -39,6 +39,7 @@
#include "core/gimpparamspecs.h"
#include "core/gimpselection.h"
#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
#include "text/gimptextlayer.h"
#include "gimppdb.h"
@@ -179,6 +180,39 @@ item_id_is_text_layer_invoker (GimpProcedure *procedure,
return return_vals;
}
+static GimpValueArray *
+item_id_is_vector_layer_invoker (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ const GimpValueArray *args,
+ GError **error)
+{
+ gboolean success = TRUE;
+ GimpValueArray *return_vals;
+ gint item_id;
+ gboolean vector_layer = FALSE;
+
+ item_id = g_value_get_int (gimp_value_array_index (args, 0));
+
+ if (success)
+ {
+ GimpItem *item = gimp_item_get_by_id (gimp, item_id);
+
+ vector_layer = (GIMP_IS_LAYER (item) &&
+ ! gimp_item_is_removed (item) &&
+ gimp_item_is_vector_layer (item));
+ }
+
+ return_vals = gimp_procedure_get_return_values (procedure, success,
+ error ? *error : NULL);
+
+ if (success)
+ g_value_set_boolean (gimp_value_array_index (return_vals, 1), vector_layer);
+
+ return return_vals;
+}
+
static GimpValueArray *
item_id_is_group_layer_invoker (GimpProcedure *procedure,
Gimp *gimp,
@@ -1191,6 +1225,37 @@ register_item_procs (GimpPDB *pdb)
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
+ /*
+ * gimp-item-id-is-vector-layer
+ */
+ procedure = gimp_procedure_new (item_id_is_vector_layer_invoker, FALSE);
+ gimp_object_set_static_name (GIMP_OBJECT (procedure),
+ "gimp-item-id-is-vector-layer");
+ gimp_procedure_set_static_help (procedure,
+ "Returns whether the item ID is a vector layer.",
+ "This procedure returns %TRUE if the specified item ID is a vector layer.\n"
+ "\n"
+ "*Note*: in most use cases, you should not use this function. See [func@Gimp.Item.id_is_layer] for a discussion on alternatives.",
+ NULL);
+ gimp_procedure_set_static_attribution (procedure,
+ "Alex S.",
+ "Alex S.",
+ "2025");
+ gimp_procedure_add_argument (procedure,
+ g_param_spec_int ("item-id",
+ "item id",
+ "The item ID",
+ G_MININT32, G_MAXINT32, 0,
+ GIMP_PARAM_READWRITE));
+ gimp_procedure_add_return_value (procedure,
+ g_param_spec_boolean ("vector-layer",
+ "vector layer",
+ "TRUE if the item is a vector layer, FALSE otherwise.",
+ FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_pdb_register_procedure (pdb, procedure);
+ g_object_unref (procedure);
+
/*
* gimp-item-id-is-group-layer
*/
diff --git a/app/pdb/meson.build b/app/pdb/meson.build
index a02af884e1..3b8fb0500b 100644
--- a/app/pdb/meson.build
+++ b/app/pdb/meson.build
@@ -66,6 +66,7 @@ libappinternalprocs_sources = [
'text-layer-cmds.c',
'text-tool-cmds.c',
'unit-cmds.c',
+ 'vector-layer-cmds.c',
]
libapppdb = static_library('apppdb',
diff --git a/app/pdb/vector-layer-cmds.c b/app/pdb/vector-layer-cmds.c
new file mode 100644
index 0000000000..64e55b1d53
--- /dev/null
+++ b/app/pdb/vector-layer-cmds.c
@@ -0,0 +1,232 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-2003 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 .
+ */
+
+/* NOTE: This file is auto-generated by pdbgen.pl. */
+
+#include "config.h"
+
+#include "stamp-pdbgen.h"
+
+#include
+
+#include
+
+#include "libgimpbase/gimpbase.h"
+
+#include "libgimpbase/gimpbase.h"
+
+#include "pdb-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpparamspecs.h"
+#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
+
+#include "gimppdb.h"
+#include "gimppdberror.h"
+#include "gimppdb-utils.h"
+#include "gimpprocedure.h"
+#include "internal-procs.h"
+
+#include "gimp-intl.h"
+
+
+static GimpValueArray *
+vector_layer_new_invoker (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ const GimpValueArray *args,
+ GError **error)
+{
+ gboolean success = TRUE;
+ GimpValueArray *return_vals;
+ GimpImage *image;
+ GimpPath *path;
+ GimpVectorLayer *layer = NULL;
+
+ image = g_value_get_object (gimp_value_array_index (args, 0));
+ path = g_value_get_object (gimp_value_array_index (args, 1));
+
+ if (success)
+ {
+ if (path == NULL)
+ {
+ g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
+ _("Failed to create vector layer"));
+
+ success = FALSE;
+ }
+
+ if (success)
+ {
+ layer = GIMP_VECTOR_LAYER (gimp_vector_layer_new (image, path, context));
+
+ if (! layer)
+ {
+ g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
+ _("Failed to create vector layer"));
+
+ success = FALSE;
+ }
+ }
+ }
+
+ return_vals = gimp_procedure_get_return_values (procedure, success,
+ error ? *error : NULL);
+
+ if (success)
+ g_value_set_object (gimp_value_array_index (return_vals, 1), layer);
+
+ return return_vals;
+}
+
+static GimpValueArray *
+vector_layer_refresh_invoker (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ const GimpValueArray *args,
+ GError **error)
+{
+ gboolean success = TRUE;
+ GimpVectorLayer *layer;
+
+ layer = g_value_get_object (gimp_value_array_index (args, 0));
+
+ if (success)
+ {
+ gimp_vector_layer_refresh (layer);
+ }
+
+ return gimp_procedure_get_return_values (procedure, success,
+ error ? *error : NULL);
+}
+
+static GimpValueArray *
+vector_layer_discard_invoker (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ const GimpValueArray *args,
+ GError **error)
+{
+ gboolean success = TRUE;
+ GimpVectorLayer *layer;
+
+ layer = g_value_get_object (gimp_value_array_index (args, 0));
+
+ if (success)
+ {
+ gimp_vector_layer_discard (layer);
+ }
+
+ return gimp_procedure_get_return_values (procedure, success,
+ error ? *error : NULL);
+}
+
+void
+register_vector_layer_procs (GimpPDB *pdb)
+{
+ GimpProcedure *procedure;
+
+ /*
+ * gimp-vector-layer-new
+ */
+ procedure = gimp_procedure_new (vector_layer_new_invoker, FALSE);
+ gimp_object_set_static_name (GIMP_OBJECT (procedure),
+ "gimp-vector-layer-new");
+ gimp_procedure_set_static_help (procedure,
+ "Creates a new vector layer.",
+ "This procedure creates a new path layer displaying the specified @path. By default, the fill and stroke properties will be defined by the context.\n"
+ "\n"
+ "The new layer still needs to be added to the image as this is not automatic. Add the new layer with the [method@Image.insert_layer] method.\n"
+ "\n"
+ "The arguments are kept as simple as necessary for the basic case. All vector attributes, however, can be modified with the appropriate `gimp_vector_layer_set_*()` procedures.",
+ NULL);
+ gimp_procedure_set_static_attribution (procedure,
+ "Alex S.",
+ "Alex S.",
+ "2025");
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_image ("image",
+ "image",
+ "The image",
+ FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_path ("path",
+ "path",
+ "The path to create the layer from",
+ FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_procedure_add_return_value (procedure,
+ gimp_param_spec_vector_layer ("layer",
+ "layer",
+ "The new vector layer. The object belongs to libgimp and you should not free it.",
+ FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_pdb_register_procedure (pdb, procedure);
+ g_object_unref (procedure);
+
+ /*
+ * gimp-vector-layer-refresh
+ */
+ procedure = gimp_procedure_new (vector_layer_refresh_invoker, FALSE);
+ gimp_object_set_static_name (GIMP_OBJECT (procedure),
+ "gimp-vector-layer-refresh");
+ gimp_procedure_set_static_help (procedure,
+ "Rerender the vector layer",
+ "This procedure causes the vector layer to refresh itself after changes.",
+ NULL);
+ gimp_procedure_set_static_attribution (procedure,
+ "Alex S.",
+ "Alex S.",
+ "2025");
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_vector_layer ("layer",
+ "layer",
+ "The vector layer",
+ FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_pdb_register_procedure (pdb, procedure);
+ g_object_unref (procedure);
+
+ /*
+ * gimp-vector-layer-discard
+ */
+ procedure = gimp_procedure_new (vector_layer_discard_invoker, FALSE);
+ gimp_object_set_static_name (GIMP_OBJECT (procedure),
+ "gimp-vector-layer-discard");
+ gimp_procedure_set_static_help (procedure,
+ "Discard the vector layer information.",
+ "Discards the vector information. This makes the layer behave like a normal layer.",
+ NULL);
+ gimp_procedure_set_static_attribution (procedure,
+ "Alex S.",
+ "Alex S.",
+ "2025");
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_vector_layer ("layer",
+ "layer",
+ "The vector layer",
+ FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_pdb_register_procedure (pdb, procedure);
+ g_object_unref (procedure);
+}
diff --git a/app/plug-in/gimpgpparams.c b/app/plug-in/gimpgpparams.c
index 4dad05f7f7..292580b566 100644
--- a/app/plug-in/gimpgpparams.c
+++ b/app/plug-in/gimpgpparams.c
@@ -46,6 +46,7 @@
#include "core/gimpunit.h"
#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
#include "text/gimpfont.h"
#include "text/gimptextlayer.h"
diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c
index ccd967b8c1..30271b9c0d 100644
--- a/app/tools/gimppainttool.c
+++ b/app/tools/gimppainttool.c
@@ -41,6 +41,8 @@
#include "paint/gimppaintcore.h"
#include "paint/gimppaintoptions.h"
+#include "path/gimpvectorlayer.h"
+
#include "widgets/gimpdevices.h"
#include "widgets/gimpwidgets-utils.h"
@@ -342,6 +344,24 @@ gimp_paint_tool_button_press (GimpTool *tool,
}
}
+ if (gimp_item_is_vector_layer (GIMP_ITEM (drawable)))
+ {
+ gboolean constrain_only;
+
+ /* Allow vector layers to be set as sources */
+ constrain_only = (state & gimp_get_constrain_behavior_mask () &&
+ ! (state & gimp_get_extend_selection_mask ()));
+ if (! (GIMP_IS_SOURCE_TOOL (tool) && constrain_only))
+ {
+ gimp_tool_message_literal (tool, display,
+ _("Vector layers must be rasterized "
+ "before they can be painted on."));
+ g_list_free (drawables);
+
+ return;
+ }
+ }
+
if (! gimp_paint_tool_check_alpha (paint_tool, drawable, display, &error))
{
GtkWidget *options_gui;
diff --git a/app/tools/gimppathoptions.c b/app/tools/gimppathoptions.c
index 5a150b6265..57c458298a 100644
--- a/app/tools/gimppathoptions.c
+++ b/app/tools/gimppathoptions.c
@@ -24,12 +24,21 @@
#include
#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpdatafactory.h"
+#include "core/gimppattern.h"
+#include "core/gimpstrokeoptions.h"
+
#include "widgets/gimphelp-ids.h"
+#include "widgets/gimppropwidgets.h"
+#include "widgets/gimpstrokeeditor.h"
#include "widgets/gimpwidgets-utils.h"
#include "gimppathoptions.h"
@@ -42,28 +51,68 @@ enum
{
PROP_0,
PROP_PATH_EDIT_MODE,
- PROP_PATH_POLYGONAL
+ PROP_PATH_POLYGONAL,
+ PROP_ENABLE_FILL,
+ PROP_ENABLE_STROKE,
+ PROP_FILL_STYLE,
+ PROP_FILL_FOREGROUND,
+ PROP_FILL_PATTERN,
+ PROP_FILL_ANTIALIAS,
+ PROP_STROKE_STYLE,
+ PROP_STROKE_FOREGROUND,
+ PROP_STROKE_PATTERN,
+ PROP_STROKE_WIDTH,
+ PROP_STROKE_UNIT,
+ PROP_STROKE_ANTIALIAS,
+ PROP_STROKE_CAP_STYLE,
+ PROP_STROKE_JOIN_STYLE,
+ PROP_STROKE_MITER_LIMIT,
+ PROP_STROKE_DASH_OFFSET
};
+static void gimp_path_options_config_iface_init (GimpConfigInterface *config_iface);
+static gboolean gimp_path_options_serialize_property (GimpConfig *config,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec,
+ GimpConfigWriter *writer);
+static gboolean gimp_path_options_deserialize_property (GimpConfig *config,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec,
+ GScanner *scanner,
+ GTokenType *expected);
-static void gimp_path_options_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gimp_path_options_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec);
+static void gimp_path_options_finalize (GObject *object);
+static void gimp_path_options_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_path_options_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
-G_DEFINE_TYPE (GimpPathOptions, gimp_path_options, GIMP_TYPE_TOOL_OPTIONS)
+G_DEFINE_TYPE_WITH_CODE (GimpPathOptions, gimp_path_options,
+ GIMP_TYPE_TOOL_OPTIONS,
+ G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
+ gimp_path_options_config_iface_init))
+
+
+#define parent_class gimp_path_options_parent_class
+
+static GimpConfigInterface *parent_config_iface = NULL;
static void
gimp_path_options_class_init (GimpPathOptionsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GeglColor *black = gegl_color_new ("black");
+ GeglColor *white = gegl_color_new ("white");
+ object_class->finalize = gimp_path_options_finalize;
object_class->set_property = gimp_path_options_set_property;
object_class->get_property = gimp_path_options_get_property;
@@ -81,11 +130,140 @@ gimp_path_options_class_init (GimpPathOptionsClass *klass)
_("Restrict editing to polygons"),
FALSE,
GIMP_PARAM_STATIC_STRINGS);
+
+ /* Vector layer specific properties */
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_FILL,
+ "enable-fill",
+ _("Enable Fill"), NULL,
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_STROKE,
+ "enable-stroke",
+ _("Enable Stroke"), NULL,
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_FILL_STYLE,
+ "fill-custom-style",
+ NULL, NULL,
+ GIMP_TYPE_CUSTOM_STYLE,
+ GIMP_CUSTOM_STYLE_SOLID_COLOR,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_COLOR (object_class, PROP_FILL_FOREGROUND,
+ "fill-foreground",
+ NULL, NULL,
+ TRUE, white,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FILL_PATTERN,
+ "fill-pattern",
+ NULL, NULL,
+ GIMP_TYPE_PATTERN,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_FILL_ANTIALIAS,
+ "fill-antialias",
+ NULL, NULL,
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_STROKE_STYLE,
+ "stroke-custom-style",
+ NULL, NULL,
+ GIMP_TYPE_CUSTOM_STYLE,
+ GIMP_CUSTOM_STYLE_SOLID_COLOR,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_COLOR (object_class, PROP_STROKE_FOREGROUND,
+ "stroke-foreground",
+ NULL, NULL,
+ TRUE, black,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, PROP_STROKE_PATTERN,
+ "stroke-pattern",
+ NULL, NULL,
+ GIMP_TYPE_PATTERN,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_WIDTH,
+ "stroke-width",
+ NULL, NULL,
+ 0.0, 2000.0, 6.0,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_UNIT (object_class, PROP_STROKE_UNIT,
+ "stroke-unit",
+ NULL, NULL,
+ TRUE, FALSE, gimp_unit_pixel (),
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_STROKE_ANTIALIAS,
+ "stroke-antialias",
+ NULL, NULL,
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_STROKE_CAP_STYLE,
+ "stroke-cap-style",
+ NULL, NULL,
+ GIMP_TYPE_CAP_STYLE, GIMP_CAP_BUTT,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_STROKE_JOIN_STYLE,
+ "stroke-join-style",
+ NULL, NULL,
+ GIMP_TYPE_JOIN_STYLE, GIMP_JOIN_MITER,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_MITER_LIMIT,
+ "stroke-miter-limit",
+ NULL, NULL,
+ 0.0, 100.0, 10.0,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_DASH_OFFSET,
+ "stroke-dash-offset",
+ NULL, NULL,
+ 0.0, 2000.0, 0.0,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ g_clear_object (&white);
+ g_clear_object (&black);
+}
+
+static void
+gimp_path_options_config_iface_init (GimpConfigInterface *config_iface)
+{
+ parent_config_iface = g_type_interface_peek_parent (config_iface);
+
+ config_iface->serialize_property = gimp_path_options_serialize_property;
+ config_iface->deserialize_property = gimp_path_options_deserialize_property;
}
static void
gimp_path_options_init (GimpPathOptions *options)
{
+ GeglColor *black = gegl_color_new ("black");
+ GeglColor *white = gegl_color_new ("white");
+
+ options->fill_foreground = white;
+ options->stroke_foreground = black;
+}
+
+static void
+gimp_path_options_finalize (GObject *object)
+{
+ GimpPathOptions *options = GIMP_PATH_OPTIONS (object);
+
+ g_clear_object (&options->fill_options);
+ g_clear_object (&options->stroke_options);
+ g_clear_object (&options->fill_foreground);
+ g_clear_object (&options->stroke_foreground);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
@@ -104,13 +282,84 @@ gimp_path_options_set_property (GObject *object,
case PROP_PATH_POLYGONAL:
options->polygonal = g_value_get_boolean (value);
break;
+
+ case PROP_ENABLE_FILL:
+ options->enable_fill = g_value_get_boolean (value);
+ break;
+ case PROP_ENABLE_STROKE:
+ options->enable_stroke = g_value_get_boolean (value);
+ break;
+
+ case PROP_FILL_STYLE:
+ options->fill_style = g_value_get_enum (value);
+ break;
+ case PROP_FILL_FOREGROUND:
+ g_set_object (&options->fill_foreground, g_value_get_object (value));
+ break;
+ case PROP_FILL_PATTERN:
+ {
+ GimpPattern *pattern = g_value_get_object (value);
+
+ if (options->fill_pattern != pattern)
+ {
+ if (options->fill_pattern)
+ g_object_unref (options->fill_pattern);
+
+ options->fill_pattern = pattern ? g_object_ref (pattern) : pattern;
+ }
+ break;
+ }
+ case PROP_FILL_ANTIALIAS:
+ options->fill_antialias = g_value_get_boolean (value);
+ break;
+ case PROP_STROKE_STYLE:
+ options->stroke_style = g_value_get_enum (value);
+ break;
+ case PROP_STROKE_FOREGROUND:
+ g_set_object (&options->stroke_foreground, g_value_get_object (value));
+ break;
+ case PROP_STROKE_PATTERN:
+ {
+ GimpPattern *pattern = g_value_get_object (value);
+
+ if (options->stroke_pattern != pattern)
+ {
+ if (options->stroke_pattern)
+ g_object_unref (options->stroke_pattern);
+
+ options->stroke_pattern = pattern ?
+ g_object_ref (pattern) : pattern;
+ }
+ break;
+ }
+ case PROP_STROKE_WIDTH:
+ options->stroke_width = g_value_get_double (value);
+ break;
+ case PROP_STROKE_UNIT:
+ options->stroke_unit = g_value_get_object (value);
+ break;
+ case PROP_STROKE_ANTIALIAS:
+ options->stroke_antialias = g_value_get_boolean (value);
+ break;
+ case PROP_STROKE_CAP_STYLE:
+ options->stroke_cap_style = g_value_get_enum (value);
+ break;
+ case PROP_STROKE_JOIN_STYLE:
+ options->stroke_join_style = g_value_get_enum (value);
+ break;
+ case PROP_STROKE_MITER_LIMIT:
+ options->stroke_miter_limit = g_value_get_double (value);
+ break;
+ case PROP_STROKE_DASH_OFFSET:
+ options->stroke_dash_offset = g_value_get_double (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
-
static void
gimp_path_options_get_property (GObject *object,
guint property_id,
@@ -127,12 +376,138 @@ gimp_path_options_get_property (GObject *object,
case PROP_PATH_POLYGONAL:
g_value_set_boolean (value, options->polygonal);
break;
+
+ case PROP_ENABLE_FILL:
+ g_value_set_boolean (value, options->enable_fill);
+ break;
+ case PROP_ENABLE_STROKE:
+ g_value_set_boolean (value, options->enable_stroke);
+ break;
+
+ case PROP_FILL_STYLE:
+ g_value_set_enum (value, options->fill_style);
+ break;
+ case PROP_FILL_FOREGROUND:
+ g_value_set_object (value, options->fill_foreground);
+ break;
+ case PROP_FILL_PATTERN:
+ g_value_set_object (value, options->fill_pattern);
+ break;
+ case PROP_FILL_ANTIALIAS:
+ g_value_set_boolean (value, options->fill_antialias);
+ break;
+ case PROP_STROKE_STYLE:
+ g_value_set_enum (value, options->stroke_style);
+ break;
+ case PROP_STROKE_FOREGROUND:
+ g_value_set_object (value, options->stroke_foreground);
+ break;
+ case PROP_STROKE_PATTERN:
+ g_value_set_object (value, options->stroke_pattern);
+ break;
+ case PROP_STROKE_WIDTH:
+ g_value_set_double (value, options->stroke_width);
+ break;
+ case PROP_STROKE_UNIT:
+ g_value_set_object (value, options->stroke_unit);
+ break;
+ case PROP_STROKE_ANTIALIAS:
+ g_value_set_boolean (value, options->stroke_antialias);
+ break;
+ case PROP_STROKE_CAP_STYLE:
+ g_value_set_enum (value, options->stroke_cap_style);
+ break;
+ case PROP_STROKE_JOIN_STYLE:
+ g_value_set_enum (value, options->stroke_join_style);
+ break;
+ case PROP_STROKE_MITER_LIMIT:
+ g_value_set_double (value, options->stroke_miter_limit);
+ break;
+ case PROP_STROKE_DASH_OFFSET:
+ g_value_set_double (value, options->stroke_dash_offset);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
+static gboolean
+gimp_path_options_serialize_property (GimpConfig *config,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec,
+ GimpConfigWriter *writer)
+{
+ if (property_id == PROP_FILL_PATTERN ||
+ property_id == PROP_STROKE_PATTERN)
+ {
+ GimpObject *serialize_obj = g_value_get_object (value);
+
+ gimp_config_writer_open (writer, pspec->name);
+
+ if (serialize_obj)
+ gimp_config_writer_string (writer,
+ gimp_object_get_name (serialize_obj));
+ else
+ gimp_config_writer_print (writer, "NULL", 4);
+
+ gimp_config_writer_close (writer);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gimp_path_options_deserialize_property (GimpConfig *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec,
+ GScanner *scanner,
+ GTokenType *expected)
+{
+ if (property_id == PROP_FILL_PATTERN ||
+ property_id == PROP_STROKE_PATTERN)
+ {
+ gchar *object_name;
+
+ if (gimp_scanner_parse_identifier (scanner, "NULL"))
+ {
+ g_value_set_object (value, NULL);
+ }
+ else if (gimp_scanner_parse_string (scanner, &object_name))
+ {
+ GimpContext *context = GIMP_CONTEXT (object);
+ GimpContainer *container;
+ GimpObject *deserialize_obj;
+
+ if (! object_name)
+ object_name = g_strdup ("");
+
+ container =
+ gimp_data_factory_get_container (context->gimp->pattern_factory);
+
+ deserialize_obj = gimp_container_get_child_by_name (container,
+ object_name);
+
+ g_value_set_object (value, deserialize_obj);
+
+ g_free (object_name);
+ }
+ else
+ {
+ *expected = G_TOKEN_STRING;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
button_append_modifier (GtkWidget *button,
GdkModifierType modifiers)
@@ -149,7 +524,7 @@ GtkWidget *
gimp_path_options_gui (GimpToolOptions *tool_options)
{
GObject *config = G_OBJECT (tool_options);
- GimpPathOptions *options = GIMP_PATH_OPTIONS (tool_options);
+ GimpPathOptions *options = GIMP_PATH_OPTIONS (tool_options);
GtkWidget *vbox = gimp_tool_options_gui (tool_options);
GtkWidget *frame;
GtkWidget *button;
@@ -198,23 +573,7 @@ gimp_path_options_gui (GimpToolOptions *tool_options)
options->to_selection_button = button;
- button = gtk_button_new_with_label (_("Fill Path"));
- gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
- gtk_widget_set_sensitive (button, FALSE);
- gimp_help_set_help_data (button, NULL, GIMP_HELP_PATH_FILL);
- gtk_widget_set_visible (button, TRUE);
-
- options->fill_button = button;
-
- button = gtk_button_new_with_label (_("Stroke Path"));
- gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
- gtk_widget_set_sensitive (button, FALSE);
- gimp_help_set_help_data (button, NULL, GIMP_HELP_PATH_STROKE);
- gtk_widget_set_visible (button, TRUE);
-
- options->stroke_button = button;
-
- button = gtk_button_new_with_label (_("Create Vector Layer"));
+ button = gtk_button_new_with_label (_("Create New Vector Layer"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
gimp_help_set_help_data (button, NULL, NULL);
@@ -222,5 +581,64 @@ gimp_path_options_gui (GimpToolOptions *tool_options)
options->vector_layer_button = button;
+ /* The fill editor */
+ {
+ GtkWidget *frame;
+ GtkWidget *fill_editor;
+
+ options->fill_options =
+ gimp_fill_options_new (GIMP_CONTEXT (options)->gimp,
+ NULL, FALSE);
+
+#define FILL_BIND(a) \
+ g_object_bind_property (options, "fill-" #a, \
+ options->fill_options, #a, \
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE)
+ FILL_BIND (custom-style);
+ FILL_BIND (foreground);
+ FILL_BIND (pattern);
+
+ fill_editor = gimp_fill_editor_new (options->fill_options,
+ TRUE, TRUE);
+ gtk_widget_set_visible (fill_editor, TRUE);
+
+ frame = gimp_prop_expanding_frame_new (config, "enable-fill", NULL,
+ fill_editor, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+ }
+
+ /* The stroke editor */
+ {
+ GtkWidget *frame;
+ GtkWidget *stroke_editor;
+
+ options->stroke_options =
+ gimp_stroke_options_new (GIMP_CONTEXT (options)->gimp,
+ NULL, FALSE);
+
+#define STROKE_BIND(a) \
+ g_object_bind_property (options, "stroke-" #a, \
+ options->stroke_options, #a, \
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE)
+ STROKE_BIND (custom-style);
+ STROKE_BIND (foreground);
+ STROKE_BIND (pattern);
+ STROKE_BIND (width);
+ STROKE_BIND (unit);
+ STROKE_BIND (cap-style);
+ STROKE_BIND (join-style);
+ STROKE_BIND (miter-limit);
+ STROKE_BIND (antialias);
+ STROKE_BIND (dash-offset);
+
+ stroke_editor = gimp_stroke_editor_new (options->stroke_options, 72.0,
+ TRUE, TRUE);
+ gtk_widget_set_visible (stroke_editor, TRUE);
+
+ frame = gimp_prop_expanding_frame_new (config, "enable-stroke", NULL,
+ stroke_editor, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+ }
+
return vbox;
}
diff --git a/app/tools/gimppathoptions.h b/app/tools/gimppathoptions.h
index 71655cc9bc..ec20b38d3a 100644
--- a/app/tools/gimppathoptions.h
+++ b/app/tools/gimppathoptions.h
@@ -28,20 +28,41 @@
#define GIMP_PATH_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PATH_OPTIONS, GimpPathOptionsClass))
-typedef struct _GimpPathOptions GimpPathOptions;
+typedef struct _GimpPathOptions GimpPathOptions;
typedef struct _GimpToolOptionsClass GimpPathOptionsClass;
struct _GimpPathOptions
{
- GimpToolOptions parent_instance;
+ GimpToolOptions parent_instance;
- GimpPathMode edit_mode;
- gboolean polygonal;
+ GimpPathMode edit_mode;
+ gboolean polygonal;
+
+ /* vector layer */
+ gboolean enable_fill;
+ gboolean enable_stroke;
+ GimpFillOptions *fill_options;
+ GimpStrokeOptions *stroke_options;
+
+ GimpCustomStyle fill_style;
+ GeglColor *fill_foreground;
+ GimpPattern *fill_pattern;
+ gboolean fill_antialias;
+
+ GimpCustomStyle stroke_style;
+ GeglColor *stroke_foreground;
+ GimpPattern *stroke_pattern;
+ gboolean stroke_antialias;
+ gdouble stroke_width;
+ GimpUnit *stroke_unit;
+ GimpCapStyle stroke_cap_style;
+ GimpJoinStyle stroke_join_style;
+ gdouble stroke_miter_limit;
+ gdouble stroke_dash_offset;
/* options gui */
- GtkWidget *to_selection_button;
- GtkWidget *fill_button;
- GtkWidget *stroke_button;
+ GtkWidget *to_selection_button;
+ GtkWidget *vector_layer_button;
};
diff --git a/app/tools/gimppathtool.c b/app/tools/gimppathtool.c
index 48b5573257..9565c3a0a3 100644
--- a/app/tools/gimppathtool.c
+++ b/app/tools/gimppathtool.c
@@ -35,12 +35,15 @@
#include "core/gimpimage-pick-item.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
+#include "core/gimpstrokeoptions.h"
#include "core/gimptoolinfo.h"
#include "core/gimpundostack.h"
#include "paint/gimppaintoptions.h" /* GIMP_PAINT_OPTIONS_CONTEXT_MASK */
#include "path/gimppath.h"
+#include "path/gimpvectorlayer.h"
+#include "path/gimpvectorlayeroptions.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockcontainer.h"
@@ -70,6 +73,7 @@
/* local function prototypes */
+static void gimp_path_tool_constructed (GObject *object);
static void gimp_path_tool_dispose (GObject *object);
static void gimp_path_tool_control (GimpTool *tool,
@@ -106,6 +110,12 @@ static void gimp_path_tool_start (GimpPathTool *path_t
GimpDisplay *display);
static void gimp_path_tool_halt (GimpPathTool *path_tool);
+static void gimp_path_tool_image_changed (GimpPathTool *path_tool,
+ GimpImage *image,
+ GimpContext *context);
+static void gimp_path_tool_image_selected_layers_changed
+ (GimpPathTool *path_tool);
+
static void gimp_path_tool_tool_path_changed (GimpToolWidget *tool_path,
GimpPathTool *path_tool);
static void gimp_path_tool_tool_path_begin_change
@@ -130,23 +140,12 @@ static void gimp_path_tool_to_selection_extended
(GimpPathTool *path_tool,
GdkModifierType state);
-static void gimp_path_tool_fill_path (GimpPathTool *path_tool,
- GtkWidget *button);
-static void gimp_path_tool_fill_callback (GtkWidget *dialog,
- GList *items,
- GList *drawables,
- GimpContext *context,
- GimpFillOptions *options,
- gpointer data);
-
-static void gimp_path_tool_stroke_path (GimpPathTool *path_tool,
- GtkWidget *button);
-static void gimp_path_tool_stroke_callback (GtkWidget *dialog,
- GList *items,
- GList *drawables,
- GimpContext *context,
- GimpStrokeOptions *options,
- gpointer data);
+static void gimp_path_tool_create_vector_layer(GimpPathTool *path_tool,
+ GtkWidget *button);
+static void gimp_path_tool_vector_change_notify
+ (GObject *options,
+ const GParamSpec *pspec,
+ GimpVectorLayer *layer);
G_DEFINE_TYPE (GimpPathTool, gimp_path_tool, GIMP_TYPE_DRAW_TOOL)
@@ -179,6 +178,7 @@ gimp_path_tool_class_init (GimpPathToolClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
+ object_class->constructed = gimp_path_tool_constructed;
object_class->dispose = gimp_path_tool_dispose;
tool_class->control = gimp_path_tool_control;
@@ -203,6 +203,28 @@ gimp_path_tool_init (GimpPathTool *path_tool)
path_tool->saved_mode = GIMP_PATH_MODE_DESIGN;
}
+static void
+gimp_path_tool_constructed (GObject *object)
+{
+ GimpPathTool *path_tool = GIMP_PATH_TOOL (object);
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ tool_info = GIMP_TOOL (path_tool)->tool_info;
+
+ context = gimp_get_user_context (tool_info->gimp);
+
+ g_signal_connect_object (context, "image-changed",
+ G_CALLBACK (gimp_path_tool_image_changed),
+ path_tool, G_CONNECT_SWAPPED);
+
+ gimp_path_tool_image_changed (path_tool,
+ gimp_context_get_image (context),
+ context);
+}
+
static void
gimp_path_tool_dispose (GObject *object)
{
@@ -211,6 +233,8 @@ gimp_path_tool_dispose (GObject *object)
gimp_path_tool_set_path (path_tool, NULL);
g_clear_object (&path_tool->widget);
+ gimp_path_tool_image_changed (path_tool, NULL, NULL);
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -445,6 +469,87 @@ gimp_path_tool_halt (GimpPathTool *path_tool)
tool->display = NULL;
}
+static void
+gimp_path_tool_image_changed (GimpPathTool *path_tool,
+ GimpImage *image,
+ GimpContext *context)
+{
+ if (path_tool->current_image)
+ g_signal_handlers_disconnect_by_func (path_tool->current_image,
+ gimp_path_tool_image_selected_layers_changed,
+ NULL);
+
+ g_set_weak_pointer (&path_tool->current_image, image);
+
+ if (path_tool->current_image)
+ g_signal_connect_object (path_tool->current_image, "selected-layers-changed",
+ G_CALLBACK (gimp_path_tool_image_selected_layers_changed),
+ path_tool, G_CONNECT_SWAPPED);
+
+ gimp_path_tool_image_selected_layers_changed (path_tool);
+}
+
+static void
+gimp_path_tool_image_selected_layers_changed (GimpPathTool *path_tool)
+{
+ GimpPathOptions *options = GIMP_PATH_TOOL_GET_OPTIONS (path_tool);
+ GList *current_layers = NULL;
+
+ if (path_tool->current_vector_layer)
+ {
+ g_signal_handlers_disconnect_by_func (options,
+ gimp_path_tool_vector_change_notify,
+ path_tool->current_vector_layer);
+ g_signal_handlers_disconnect_by_func (options->fill_options,
+ gimp_path_tool_vector_change_notify,
+ path_tool->current_vector_layer);
+ 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 = NULL;
+ gimp_path_tool_set_path (path_tool, 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_item_is_vector_layer (GIMP_ITEM (current_layers->data)))
+ {
+ GimpVectorLayer *vector_layer = current_layers->data;
+
+ gimp_path_tool_set_path (path_tool,
+ gimp_vector_layer_get_path (vector_layer));
+
+ g_object_set (options,
+ "enable-fill", vector_layer->options->enable_fill,
+ "enable_stroke", vector_layer->options->enable_stroke,
+ NULL);
+ gimp_config_sync (G_OBJECT (vector_layer->options->stroke_options),
+ G_OBJECT (options->stroke_options), 0);
+ gimp_config_sync (G_OBJECT (vector_layer->options->fill_options),
+ G_OBJECT (options->fill_options), 0);
+
+ g_signal_connect_object (options, "notify::enable-fill",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ vector_layer, 0);
+ g_signal_connect_object (options, "notify::enable-stroke",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ vector_layer, 0);
+ g_signal_connect_object (options->fill_options, "notify",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ vector_layer, 0);
+ g_signal_connect_object (options->stroke_options, "notify",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ vector_layer, 0);
+
+ path_tool->current_vector_layer = vector_layer;
+ }
+}
+
static void
gimp_path_tool_tool_path_changed (GimpToolWidget *tool_path,
GimpPathTool *path_tool)
@@ -453,9 +558,7 @@ gimp_path_tool_tool_path_changed (GimpToolWidget *tool_path,
GimpImage *image = gimp_display_get_image (shell->display);
GimpPath *path;
- g_object_get (tool_path,
- "path", &path,
- NULL);
+ g_object_get (tool_path, "path", &path, NULL);
if (path != path_tool->path)
{
@@ -595,19 +698,11 @@ gimp_path_tool_set_path (GimpPathTool *path_tool,
tool);
}
- if (options->fill_button)
+ if (options->vector_layer_button)
{
- gtk_widget_set_sensitive (options->fill_button, FALSE);
- g_signal_handlers_disconnect_by_func (options->fill_button,
- gimp_path_tool_fill_path,
- tool);
- }
-
- if (options->stroke_button)
- {
- gtk_widget_set_sensitive (options->stroke_button, FALSE);
- g_signal_handlers_disconnect_by_func (options->stroke_button,
- gimp_path_tool_stroke_path,
+ gtk_widget_set_sensitive (options->vector_layer_button, FALSE);
+ g_signal_handlers_disconnect_by_func (options->vector_layer_button,
+ gimp_path_tool_create_vector_layer,
tool);
}
}
@@ -642,20 +737,13 @@ gimp_path_tool_set_path (GimpPathTool *path_tool,
gtk_widget_set_sensitive (options->to_selection_button, TRUE);
}
- if (options->fill_button)
+ if (options->vector_layer_button)
{
- g_signal_connect_swapped (options->fill_button, "clicked",
- G_CALLBACK (gimp_path_tool_fill_path),
- tool);
- gtk_widget_set_sensitive (options->fill_button, TRUE);
- }
+ g_signal_connect_swapped (options->vector_layer_button, "clicked",
+ G_CALLBACK (gimp_path_tool_create_vector_layer),
+ tool);
- if (options->stroke_button)
- {
- g_signal_connect_swapped (options->stroke_button, "clicked",
- G_CALLBACK (gimp_path_tool_stroke_path),
- tool);
- gtk_widget_set_sensitive (options->stroke_button, TRUE);
+ gtk_widget_set_sensitive (options->vector_layer_button, TRUE);
}
if (tool->display)
@@ -722,180 +810,126 @@ gimp_path_tool_to_selection_extended (GimpPathTool *path_tool,
gimp_image_flush (image);
}
-
static void
-gimp_path_tool_fill_path (GimpPathTool *path_tool,
- GtkWidget *button)
+gimp_path_tool_create_vector_layer (GimpPathTool *path_tool,
+ GtkWidget *button)
{
- GimpDialogConfig *config;
- GimpImage *image;
- GList *drawables;
- GList *path_list = NULL;
- GtkWidget *dialog;
+ GimpImage *image;
+ GimpVectorLayer *layer;
+ GimpPathOptions *options = GIMP_PATH_TOOL_GET_OPTIONS (path_tool);
if (! path_tool->path)
return;
image = gimp_item_get_image (GIMP_ITEM (path_tool->path));
- config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ g_signal_handlers_block_by_func (image,
+ gimp_path_tool_image_selected_layers_changed,
+ path_tool);
- drawables = gimp_image_get_selected_drawables (image);
-
- if (! drawables)
+ /* If there's already an active vector layer, create a new blank path */
+ if (path_tool->current_vector_layer)
{
- gimp_tool_message (GIMP_TOOL (path_tool),
- GIMP_TOOL (path_tool)->display,
- _("There are no selected layers or channels to fill."));
- return;
+ GimpPath *new_path = gimp_path_new (image, _("Vector Layer"));
+
+ gimp_image_add_path (image, new_path, GIMP_IMAGE_ACTIVE_PARENT, -1,
+ TRUE);
+
+ g_signal_handlers_disconnect_by_func (options,
+ gimp_path_tool_vector_change_notify,
+ path_tool->current_vector_layer);
+ g_signal_handlers_disconnect_by_func (options->fill_options,
+ gimp_path_tool_vector_change_notify,
+ path_tool->current_vector_layer);
+ g_signal_handlers_disconnect_by_func (options->stroke_options,
+ gimp_path_tool_vector_change_notify,
+ path_tool->current_vector_layer);
}
- if (g_list_length (drawables) == 1 &&
- gimp_item_is_content_locked (GIMP_ITEM (drawables->data), NULL))
- {
- gimp_tool_message (GIMP_TOOL (path_tool),
- GIMP_TOOL (path_tool)->display,
- _("A selected layer's pixels are locked."));
- return;
- }
+ layer = gimp_vector_layer_new (image, path_tool->path,
+ gimp_get_user_context (image->gimp));
+ path_tool->current_vector_layer = layer;
- path_list = g_list_prepend (NULL, path_tool->path);
- dialog = fill_dialog_new (path_list, drawables,
- GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (path_tool)),
- _("Fill Path"),
- GIMP_ICON_TOOL_BUCKET_FILL,
- GIMP_HELP_PATH_FILL,
- button,
- config->fill_options,
- gimp_path_tool_fill_callback,
- path_tool);
- gtk_widget_show (dialog);
- g_list_free (path_list);
- g_list_free (drawables);
-}
+ gimp_image_add_layer (image,
+ GIMP_LAYER (layer),
+ GIMP_IMAGE_ACTIVE_PARENT,
+ -1,
+ TRUE);
-static void
-gimp_path_tool_fill_callback (GtkWidget *dialog,
- GList *items,
- GList *drawables,
- GimpContext *context,
- GimpFillOptions *options,
- gpointer data)
-{
- GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
- GimpImage *image = gimp_item_get_image (items->data);
- GError *error = NULL;
+ g_object_set (layer->options,
+ "enable-fill", options->enable_fill,
+ "enable-stroke", options->enable_stroke,
+ NULL);
- gimp_config_sync (G_OBJECT (options),
- G_OBJECT (config->fill_options), 0);
+ gimp_config_sync (G_OBJECT (options->fill_options),
+ G_OBJECT (layer->options->fill_options), 0);
+ gimp_config_sync (G_OBJECT (options->stroke_options),
+ G_OBJECT (layer->options->stroke_options), 0);
- gimp_image_undo_group_start (image,
- GIMP_UNDO_GROUP_DRAWABLE_MOD,
- "Fill");
+ g_signal_connect_object (options, "notify::enable-fill",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ layer, 0);
+ g_signal_connect_object (options, "notify::enable-stroke",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ layer, 0);
+ g_signal_connect_object (options->fill_options, "notify",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ layer, 0);
+ g_signal_connect_object (options->stroke_options, "notify",
+ G_CALLBACK (gimp_path_tool_vector_change_notify),
+ layer, 0);
- for (GList *iter = items; iter; iter = iter->next)
- if (! gimp_item_fill (iter->data, drawables, options,
- TRUE, NULL, &error))
- {
- gimp_message_literal (context->gimp,
- G_OBJECT (dialog),
- GIMP_MESSAGE_WARNING,
- error ? error->message : "NULL");
-
- g_clear_error (&error);
- break;
- }
-
- gimp_image_undo_group_end (image);
+ gimp_vector_layer_refresh (layer);
gimp_image_flush (image);
- gtk_widget_destroy (dialog);
-}
-
-static void
-gimp_path_tool_stroke_path (GimpPathTool *path_tool,
- GtkWidget *button)
-{
- GimpDialogConfig *config;
- GimpImage *image;
- GList *drawables;
- GList *path_list = NULL;
- GtkWidget *dialog;
-
- if (! path_tool->path)
- return;
-
- image = gimp_item_get_image (GIMP_ITEM (path_tool->path));
-
- config = GIMP_DIALOG_CONFIG (image->gimp->config);
-
- drawables = gimp_image_get_selected_drawables (image);
-
- if (! drawables)
- {
- gimp_tool_message (GIMP_TOOL (path_tool),
- GIMP_TOOL (path_tool)->display,
- _("There are no selected layers or channels to stroke to."));
- return;
- }
-
- if (g_list_length (drawables) == 1 &&
- gimp_item_is_content_locked (GIMP_ITEM (drawables->data), NULL))
- {
- gimp_tool_message (GIMP_TOOL (path_tool),
- GIMP_TOOL (path_tool)->display,
- _("A selected layer's pixels are locked."));
- return;
- }
-
- path_list = g_list_prepend (NULL, path_tool->path);
- dialog = stroke_dialog_new (path_list, drawables,
- GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (path_tool)),
- _("Stroke Path"),
- GIMP_ICON_PATH_STROKE,
- GIMP_HELP_PATH_STROKE,
- button,
- config->stroke_options,
- gimp_path_tool_stroke_callback,
- path_tool);
- gtk_widget_show (dialog);
- g_list_free (path_list);
- g_list_free (drawables);
+ g_signal_handlers_unblock_by_func (image,
+ gimp_path_tool_image_selected_layers_changed,
+ path_tool);
}
static void
-gimp_path_tool_stroke_callback (GtkWidget *dialog,
- GList *items,
- GList *drawables,
- GimpContext *context,
- GimpStrokeOptions *options,
- gpointer data)
+gimp_path_tool_vector_change_notify (GObject *options,
+ const GParamSpec *pspec,
+ GimpVectorLayer *layer)
{
- GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
- GimpImage *image = gimp_item_get_image (items->data);
- GError *error = NULL;
+ GimpImage *image;
+ gboolean needs_update = FALSE;
- gimp_config_sync (G_OBJECT (options),
- G_OBJECT (config->stroke_options), 0);
+ image = gimp_item_get_image (GIMP_ITEM (layer));
- gimp_image_undo_group_start (image,
- GIMP_UNDO_GROUP_DRAWABLE_MOD,
- "Stroke");
+ if (GIMP_IS_STROKE_OPTIONS (options))
+ {
+ GimpStrokeOptions *stroke_options = GIMP_STROKE_OPTIONS (options);
- for (GList *iter = items; iter; iter = iter->next)
- if (! gimp_item_stroke (iter->data, drawables, context, options, NULL,
- TRUE, NULL, &error))
- {
- gimp_message_literal (context->gimp,
- G_OBJECT (dialog),
- GIMP_MESSAGE_WARNING,
- error ? error->message : "NULL");
+ gimp_config_sync (G_OBJECT (stroke_options),
+ G_OBJECT (layer->options->stroke_options), 0);
- g_clear_error (&error);
- break;
- }
+ needs_update = TRUE;
+ }
+ else if (GIMP_IS_FILL_OPTIONS (options))
+ {
+ GimpFillOptions *fill_options = GIMP_FILL_OPTIONS (options);
- gimp_image_undo_group_end (image);
- gimp_image_flush (image);
- gtk_widget_destroy (dialog);
+ gimp_config_sync (G_OBJECT (fill_options),
+ G_OBJECT (layer->options->fill_options), 0);
+
+ 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);
+
+ needs_update = TRUE;
+ }
+
+ if (needs_update)
+ {
+ gimp_vector_layer_refresh (layer);
+ gimp_image_flush (image);
+ }
}
diff --git a/app/tools/gimppathtool.h b/app/tools/gimppathtool.h
index 5c9f761bb7..da65773700 100644
--- a/app/tools/gimppathtool.h
+++ b/app/tools/gimppathtool.h
@@ -38,13 +38,16 @@ typedef struct _GimpPathToolClass GimpPathToolClass;
struct _GimpPathTool
{
- GimpDrawTool parent_instance;
+ GimpDrawTool parent_instance;
- GimpPath *path; /* the current Path data */
- GimpPathMode saved_mode; /* used by modifier_key() */
+ GimpImage *current_image;
+ GimpVectorLayer *current_vector_layer;
- GimpToolWidget *widget;
- GimpToolWidget *grab_widget;
+ GimpPath *path; /* the current Path data */
+ GimpPathMode saved_mode; /* used by modifier_key() */
+
+ GimpToolWidget *widget;
+ GimpToolWidget *grab_widget;
};
struct _GimpPathToolClass
diff --git a/libgimp/gimp.c b/libgimp/gimp.c
index b768bc4295..cc7f1359d8 100644
--- a/libgimp/gimp.c
+++ b/libgimp/gimp.c
@@ -449,6 +449,7 @@ gimp_main (GType plug_in_type,
GIMP_TYPE_DRAWABLE, GIMP_TYPE_PARAM_DRAWABLE,
GIMP_TYPE_LAYER, GIMP_TYPE_PARAM_LAYER,
GIMP_TYPE_TEXT_LAYER, GIMP_TYPE_PARAM_TEXT_LAYER,
+ GIMP_TYPE_VECTOR_LAYER, GIMP_TYPE_PARAM_VECTOR_LAYER,
GIMP_TYPE_GROUP_LAYER, GIMP_TYPE_PARAM_GROUP_LAYER,
GIMP_TYPE_CHANNEL, GIMP_TYPE_PARAM_CHANNEL,
GIMP_TYPE_LAYER_MASK, GIMP_TYPE_PARAM_LAYER_MASK,
diff --git a/libgimp/gimp.def b/libgimp/gimp.def
index 789b84ae2b..991dfe79cf 100644
--- a/libgimp/gimp.def
+++ b/libgimp/gimp.def
@@ -601,6 +601,7 @@ EXPORTS
gimp_item_id_is_selection
gimp_item_id_is_text_layer
gimp_item_id_is_valid
+ gimp_item_id_is_vector_layer
gimp_item_is_channel
gimp_item_is_drawable
gimp_item_is_group
@@ -749,7 +750,9 @@ EXPORTS
gimp_param_spec_resource_none_allowed
gimp_param_spec_selection
gimp_param_spec_text_layer
+ gimp_param_spec_vector_layer
gimp_param_text_layer_get_type
+ gimp_param_vector_layer_get_type
gimp_path_bezier_stroke_conicto
gimp_path_bezier_stroke_cubicto
gimp_path_bezier_stroke_lineto
@@ -912,6 +915,9 @@ EXPORTS
gimp_procedure_add_unit_argument
gimp_procedure_add_unit_aux_argument
gimp_procedure_add_unit_return_value
+ gimp_procedure_add_vector_layer_argument
+ gimp_procedure_add_vector_layer_aux_argument
+ gimp_procedure_add_vector_layer_return_value
gimp_procedure_config_get_choice_id
gimp_procedure_config_get_color_array
gimp_procedure_config_get_core_object_array
@@ -1063,6 +1069,11 @@ EXPORTS
gimp_unit_new
gimp_update_metadata
gimp_user_time
+ gimp_vector_layer_discard
+ gimp_vector_layer_get_by_id
+ gimp_vector_layer_get_type
+ gimp_vector_layer_new
+ gimp_vector_layer_refresh
gimp_vector_load_procedure_extract_dimensions
gimp_vector_load_procedure_get_type
gimp_vector_load_procedure_new
diff --git a/libgimp/gimp.h b/libgimp/gimp.h
index 840d2efcb4..9b9abfcc00 100644
--- a/libgimp/gimp.h
+++ b/libgimp/gimp.h
@@ -71,6 +71,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/libgimp/gimp_pdb_headers.h b/libgimp/gimp_pdb_headers.h
index 65ef2e9104..7e4bb5322b 100644
--- a/libgimp/gimp_pdb_headers.h
+++ b/libgimp/gimp_pdb_headers.h
@@ -82,5 +82,6 @@
#include
#include
#include
+#include
#endif /* __GIMP_PDB_HEADERS_H__ */
diff --git a/libgimp/gimpgpparams-body.c b/libgimp/gimpgpparams-body.c
index afed740c41..f2b10ace67 100644
--- a/libgimp/gimpgpparams-body.c
+++ b/libgimp/gimpgpparams-body.c
@@ -284,6 +284,11 @@ _gimp_gp_param_def_to_param_spec (const GPParamDef *param_def)
param_def->meta.m_id.none_ok,
flags);
+ if (! strcmp (param_def->type_name, "GimpParamVectorLayer"))
+ return gimp_param_spec_vector_layer (name, nick, blurb,
+ param_def->meta.m_id.none_ok,
+ flags);
+
if (! strcmp (param_def->type_name, "GimpParamGroupLayer"))
return gimp_param_spec_group_layer (name, nick, blurb,
param_def->meta.m_id.none_ok,
@@ -716,6 +721,10 @@ _gimp_param_spec_to_gp_param_def (GParamSpec *pspec,
{
type_name = "GimpParamTextLayer";
}
+ else if (value_type == GIMP_TYPE_VECTOR_LAYER)
+ {
+ type_name = "GimpParamVectorLayer";
+ }
else if (value_type == GIMP_TYPE_GROUP_LAYER)
{
type_name = "GimpParamGroupLayer";
diff --git a/libgimp/gimpitem_pdb.c b/libgimp/gimpitem_pdb.c
index b4c57d2c99..e7672d22f7 100644
--- a/libgimp/gimpitem_pdb.c
+++ b/libgimp/gimpitem_pdb.c
@@ -211,6 +211,46 @@ gimp_item_id_is_text_layer (gint item_id)
return text_layer;
}
+/**
+ * gimp_item_id_is_vector_layer:
+ * @item_id: The item ID.
+ *
+ * Returns whether the item ID is a vector layer.
+ *
+ * This procedure returns %TRUE if the specified item ID is a vector
+ * layer.
+ *
+ * *Note*: in most use cases, you should not use this function. See
+ * [func@Gimp.Item.id_is_layer] for a discussion on alternatives.
+ *
+ * Returns: TRUE if the item is a vector layer, FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+gimp_item_id_is_vector_layer (gint item_id)
+{
+ GimpValueArray *args;
+ GimpValueArray *return_vals;
+ gboolean vector_layer = FALSE;
+
+ args = gimp_value_array_new_from_types (NULL,
+ G_TYPE_INT, item_id,
+ G_TYPE_NONE);
+
+ return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
+ "gimp-item-id-is-vector-layer",
+ args);
+ gimp_value_array_unref (args);
+
+ if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
+ vector_layer = GIMP_VALUES_GET_BOOLEAN (return_vals, 1);
+
+ gimp_value_array_unref (return_vals);
+
+ return vector_layer;
+}
+
/**
* gimp_item_id_is_group_layer:
* @item_id: The item ID.
diff --git a/libgimp/gimpitem_pdb.h b/libgimp/gimpitem_pdb.h
index 58a858ef4e..0b1bb166c7 100644
--- a/libgimp/gimpitem_pdb.h
+++ b/libgimp/gimpitem_pdb.h
@@ -36,6 +36,7 @@ gboolean gimp_item_id_is_valid (gint item_id);
gboolean gimp_item_id_is_drawable (gint item_id);
gboolean gimp_item_id_is_layer (gint item_id);
gboolean gimp_item_id_is_text_layer (gint item_id);
+gboolean gimp_item_id_is_vector_layer (gint item_id);
gboolean gimp_item_id_is_group_layer (gint item_id);
gboolean gimp_item_id_is_channel (gint item_id);
gboolean gimp_item_id_is_layer_mask (gint item_id);
diff --git a/libgimp/gimpparamspecs-body.c b/libgimp/gimpparamspecs-body.c
index 60946ff90d..1f388dbd49 100644
--- a/libgimp/gimpparamspecs-body.c
+++ b/libgimp/gimpparamspecs-body.c
@@ -532,6 +532,86 @@ gimp_param_spec_text_layer (const gchar *name,
}
+/*
+ * GIMP_TYPE_PARAM_VECTOR_LAYER
+ */
+
+static void gimp_param_vector_layer_class_init (GParamSpecClass *klass);
+static void gimp_param_vector_layer_init (GParamSpec *pspec);
+
+GType
+gimp_param_vector_layer_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type)
+ {
+ const GTypeInfo info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_vector_layer_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecItem),
+ 0,
+ (GInstanceInitFunc) gimp_param_vector_layer_init
+ };
+
+ type = g_type_register_static (GIMP_TYPE_PARAM_LAYER,
+ "GimpParamVectorLayer", &info, 0);
+ }
+
+ return type;
+}
+
+static void
+gimp_param_vector_layer_class_init (GParamSpecClass *klass)
+{
+ klass->value_type = GIMP_TYPE_VECTOR_LAYER;
+}
+
+static void
+gimp_param_vector_layer_init (GParamSpec *pspec)
+{
+}
+
+/**
+ * gimp_param_spec_vector_layer:
+ * @name: Canonical name of the property specified.
+ * @nick: Nick name of the property specified.
+ * @blurb: Description of the property specified.
+ * @none_ok: Whether no is a valid value.
+ * @flags: Flags for the property specified.
+ *
+ * Creates a new #GimpParamSpecVectorLayer specifying a
+ * [type@VectorLayer] property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer floating): The newly created #GimpParamSpecVectorLayer.
+ *
+ * Since: 3.2
+ **/
+GParamSpec *
+gimp_param_spec_vector_layer (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags)
+{
+ GimpParamSpecItem *ispec;
+
+ ispec = g_param_spec_internal (GIMP_TYPE_PARAM_VECTOR_LAYER,
+ name, nick, blurb, flags);
+
+ g_return_val_if_fail (ispec, NULL);
+
+ ispec->none_ok = none_ok ? TRUE : FALSE;
+
+ return G_PARAM_SPEC (ispec);
+}
+
+
/*
* GIMP_TYPE_PARAM_GROUP_LAYER
*/
diff --git a/libgimp/gimpparamspecs.h b/libgimp/gimpparamspecs.h
index d5e5ecfdca..1d9b2f2679 100644
--- a/libgimp/gimpparamspecs.h
+++ b/libgimp/gimpparamspecs.h
@@ -129,6 +129,25 @@ GParamSpec * gimp_param_spec_text_layer (const gchar *name,
GParamFlags flags);
+/*
+ * GIMP_TYPE_PARAM_VECTOR_LAYER
+ */
+
+#define GIMP_VALUE_HOLDS_VECTOR_LAYER(value) (G_TYPE_CHECK_VALUE_TYPE ((value),\
+ GIMP_TYPE_VECTOR_LAYER))
+
+#define GIMP_TYPE_PARAM_VECTOR_LAYER (gimp_param_vector_layer_get_type ())
+#define GIMP_IS_PARAM_SPEC_VECTOR_LAYER(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_VECTOR_LAYER))
+
+GType gimp_param_vector_layer_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_vector_layer (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags);
+
+
/*
* GIMP_TYPE_PARAM_GROUP_LAYER
*/
diff --git a/libgimp/gimpplugin.c b/libgimp/gimpplugin.c
index 309cfd34d2..21c3d7295e 100644
--- a/libgimp/gimpplugin.c
+++ b/libgimp/gimpplugin.c
@@ -1801,6 +1801,12 @@ _gimp_plug_in_get_item (GimpPlugIn *plug_in,
"id", item_id,
NULL);
}
+ else if (gimp_item_id_is_vector_layer (item_id))
+ {
+ item = g_object_new (GIMP_TYPE_VECTOR_LAYER,
+ "id", item_id,
+ NULL);
+ }
else if (gimp_item_id_is_group_layer (item_id))
{
item = g_object_new (GIMP_TYPE_GROUP_LAYER,
diff --git a/libgimp/gimpprocedure-params.c b/libgimp/gimpprocedure-params.c
index 48a1dbf8d2..b74aee30a7 100644
--- a/libgimp/gimpprocedure-params.c
+++ b/libgimp/gimpprocedure-params.c
@@ -1884,6 +1884,84 @@ gimp_procedure_add_text_layer_return_value (GimpProcedure *procedure,
none_ok, flags));
}
+/**
+ * gimp_procedure_add_vector_layer_argument:
+ * @procedure: the #GimpProcedure.
+ * @name: the name of the argument to be created.
+ * @nick: the label used in #GimpProcedureDialog.
+ * @blurb: (nullable): a more detailed help description.
+ * @none_ok: Whether no is a valid value.
+ * @flags: argument flags.
+ *
+ * Add a new #GimpVectorLayer argument to @procedure.
+ *
+ * Since: 3.0
+ **/
+void
+gimp_procedure_add_vector_layer_argument (GimpProcedure *procedure,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags)
+{
+ _gimp_procedure_add_argument (procedure,
+ gimp_param_spec_vector_layer (name, nick, blurb,
+ none_ok, flags));
+}
+
+/**
+ * gimp_procedure_add_vector_layer_aux_argument:
+ * @procedure: the #GimpProcedure.
+ * @name: the name of the argument to be created.
+ * @nick: the label used in #GimpProcedureDialog.
+ * @blurb: (nullable): a more detailed help description.
+ * @none_ok: Whether no is a valid value.
+ * @flags: argument flags.
+ *
+ * Add a new #GimpVectorLayer auxiliary argument to @procedure.
+ *
+ * Since: 3.0
+ **/
+void
+gimp_procedure_add_vector_layer_aux_argument (GimpProcedure *procedure,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags)
+{
+ _gimp_procedure_add_aux_argument (procedure,
+ gimp_param_spec_vector_layer (name, nick, blurb,
+ none_ok, flags));
+}
+
+/**
+ * gimp_procedure_add_vector_layer_return_value:
+ * @procedure: the #GimpProcedure.
+ * @name: the name of the argument to be created.
+ * @nick: the label used in #GimpProcedureDialog.
+ * @blurb: (nullable): a more detailed help description.
+ * @none_ok: Whether no is a valid value.
+ * @flags: argument flags.
+ *
+ * Add a new #GimpVectorLayer return value to @procedure.
+ *
+ * Since: 3.0
+ **/
+void
+gimp_procedure_add_vector_layer_return_value (GimpProcedure *procedure,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags)
+{
+ _gimp_procedure_add_return_value (procedure,
+ gimp_param_spec_vector_layer (name, nick, blurb,
+ none_ok, flags));
+}
+
/**
* gimp_procedure_add_group_layer_argument:
* @procedure: the #GimpProcedure.
diff --git a/libgimp/gimpprocedure-params.h b/libgimp/gimpprocedure-params.h
index e92b09a94f..899d8c5f2f 100644
--- a/libgimp/gimpprocedure-params.h
+++ b/libgimp/gimpprocedure-params.h
@@ -313,6 +313,18 @@ G_BEGIN_DECLS
g_value_set_object (gimp_value_array_index (args, n), value)
+/* vector layer */
+
+#define GIMP_VALUES_GET_VECTOR_LAYER(args, n) \
+ g_value_get_object (gimp_value_array_index (args, n))
+
+#define GIMP_VALUES_GET_VECTOR_LAYER_ID(args, n) \
+ gimp_item_get_id (g_value_get_object (gimp_value_array_index (args, n)))
+
+#define GIMP_VALUES_SET_VECTOR_LAYER(args, n, value) \
+ g_value_set_object (gimp_value_array_index (args, n), value)
+
+
/* group layer */
#define GIMP_VALUES_GET_GROUP_LAYER(args, n) \
@@ -899,6 +911,25 @@ void gimp_procedure_add_text_layer_return_value (GimpProcedure *procedure
gboolean none_ok,
GParamFlags flags);
+void gimp_procedure_add_vector_layer_argument (GimpProcedure *procedure,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags);
+void gimp_procedure_add_vector_layer_aux_argument (GimpProcedure *procedure,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags);
+void gimp_procedure_add_vector_layer_return_value (GimpProcedure *procedure,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean none_ok,
+ GParamFlags flags);
+
void gimp_procedure_add_group_layer_argument (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
diff --git a/libgimp/gimptypes.h b/libgimp/gimptypes.h
index e1afbe1541..23da350321 100644
--- a/libgimp/gimptypes.h
+++ b/libgimp/gimptypes.h
@@ -52,6 +52,7 @@ typedef struct _GimpTextLayer GimpTextLayer;
typedef struct _GimpPath GimpPath;
typedef struct _GimpDrawableFilter GimpDrawableFilter;
typedef struct _GimpDrawableFilterConfig GimpDrawableFilterConfig;
+typedef struct _GimpVectorLayer GimpVectorLayer;
typedef struct _GimpDisplay GimpDisplay;
diff --git a/libgimp/gimpvectorlayer.c b/libgimp/gimpvectorlayer.c
new file mode 100644
index 0000000000..dbf3832626
--- /dev/null
+++ b/libgimp/gimpvectorlayer.c
@@ -0,0 +1,75 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
+ *
+ * gimpvectorlayer.c
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * .
+ */
+
+#include "config.h"
+
+#include "gimp.h"
+
+
+struct _GimpVectorLayer
+{
+ GimpLayer parent_instance;
+};
+
+
+
+G_DEFINE_TYPE (GimpVectorLayer, gimp_vector_layer, GIMP_TYPE_LAYER)
+
+#define parent_class gimp_vector_layer_parent_class
+
+
+static void
+gimp_vector_layer_class_init (GimpVectorLayerClass *klass)
+{
+}
+
+static void
+gimp_vector_layer_init (GimpVectorLayer *layer)
+{
+}
+
+
+/* Public API. */
+
+/**
+ * gimp_vector_layer_get_by_id:
+ * @layer_id: The layer id.
+ *
+ * Returns a #GimpVectorLayer representing @layer_id. This function calls
+ * gimp_item_get_by_id() and returns the item if it is layer or %NULL
+ * otherwise.
+ *
+ * Returns: (nullable) (transfer none): a #GimpVectorLayer for @layer_id or
+ * %NULL if @layer_id does not represent a valid layer. The
+ * object belongs to libgimp and you must not modify or unref
+ * it.
+ *
+ * Since: 3.0
+ **/
+GimpVectorLayer *
+gimp_vector_layer_get_by_id (gint32 layer_id)
+{
+ GimpItem *item = gimp_item_get_by_id (layer_id);
+
+ if (GIMP_IS_VECTOR_LAYER (item))
+ return (GimpVectorLayer *) item;
+
+ return NULL;
+}
diff --git a/libgimp/gimpvectorlayer.h b/libgimp/gimpvectorlayer.h
new file mode 100644
index 0000000000..b9a9447a7d
--- /dev/null
+++ b/libgimp/gimpvectorlayer.h
@@ -0,0 +1,45 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
+ *
+ * gimpvectorlayer.h
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * .
+ */
+
+#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __GIMP_VECTOR_LAYER_H__
+#define __GIMP_VECTOR_LAYER_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+#include
+
+
+#define GIMP_TYPE_VECTOR_LAYER (gimp_vector_layer_get_type ())
+G_DECLARE_FINAL_TYPE (GimpVectorLayer, gimp_vector_layer, GIMP, VECTOR_LAYER, GimpLayer)
+
+
+GimpVectorLayer * gimp_vector_layer_get_by_id (gint32 layer_id);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_VECTOR_LAYER_H__ */
diff --git a/libgimp/gimpvectorlayer_pdb.c b/libgimp/gimpvectorlayer_pdb.c
new file mode 100644
index 0000000000..0b748ca53b
--- /dev/null
+++ b/libgimp/gimpvectorlayer_pdb.c
@@ -0,0 +1,159 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpvectorlayer_pdb.c
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * .
+ */
+
+/* NOTE: This file is auto-generated by pdbgen.pl */
+
+#include "config.h"
+
+#include "stamp-pdbgen.h"
+
+#include "gimp.h"
+
+
+/**
+ * SECTION: gimpvectorlayer
+ * @title: gimpvectorlayer
+ * @short_description: Functions for querying and manipulating vector layers.
+ *
+ * Functions for querying and manipulating vector layers.
+ **/
+
+
+/**
+ * gimp_vector_layer_new:
+ * @image: The image.
+ * @path: The path to create the layer from.
+ *
+ * Creates a new vector layer.
+ *
+ * This procedure creates a new path layer displaying the specified
+ * @path. By default, the fill and stroke properties will be defined by
+ * the context.
+ *
+ * The new layer still needs to be added to the image as this is not
+ * automatic. Add the new layer with the [method@Image.insert_layer]
+ * method.
+ *
+ * The arguments are kept as simple as necessary for the basic case.
+ * All vector attributes, however, can be modified with the appropriate
+ * `gimp_vector_layer_set_*()` procedures.
+ *
+ * Returns: (transfer none):
+ * The new vector layer. The object belongs to libgimp and you should not free it.
+ *
+ * Since: 3.2
+ **/
+GimpVectorLayer *
+gimp_vector_layer_new (GimpImage *image,
+ GimpPath *path)
+{
+ GimpValueArray *args;
+ GimpValueArray *return_vals;
+ GimpVectorLayer *layer = NULL;
+
+ args = gimp_value_array_new_from_types (NULL,
+ GIMP_TYPE_IMAGE, image,
+ GIMP_TYPE_PATH, path,
+ G_TYPE_NONE);
+
+ return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
+ "gimp-vector-layer-new",
+ args);
+ gimp_value_array_unref (args);
+
+ if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
+ layer = GIMP_VALUES_GET_VECTOR_LAYER (return_vals, 1);
+
+ gimp_value_array_unref (return_vals);
+
+ return layer;
+}
+
+/**
+ * gimp_vector_layer_refresh:
+ * @layer: The vector layer.
+ *
+ * Rerender the vector layer
+ *
+ * This procedure causes the vector layer to refresh itself after
+ * changes.
+ *
+ * Returns: TRUE on success.
+ *
+ * Since: 3.2
+ **/
+gboolean
+gimp_vector_layer_refresh (GimpVectorLayer *layer)
+{
+ GimpValueArray *args;
+ GimpValueArray *return_vals;
+ gboolean success = TRUE;
+
+ args = gimp_value_array_new_from_types (NULL,
+ GIMP_TYPE_VECTOR_LAYER, layer,
+ G_TYPE_NONE);
+
+ return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
+ "gimp-vector-layer-refresh",
+ args);
+ gimp_value_array_unref (args);
+
+ success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
+
+ gimp_value_array_unref (return_vals);
+
+ return success;
+}
+
+/**
+ * gimp_vector_layer_discard:
+ * @layer: The vector layer.
+ *
+ * Discard the vector layer information.
+ *
+ * Discards the vector information. This makes the layer behave like a
+ * normal layer.
+ *
+ * Returns: TRUE on success.
+ *
+ * Since: 3.2
+ **/
+gboolean
+gimp_vector_layer_discard (GimpVectorLayer *layer)
+{
+ GimpValueArray *args;
+ GimpValueArray *return_vals;
+ gboolean success = TRUE;
+
+ args = gimp_value_array_new_from_types (NULL,
+ GIMP_TYPE_VECTOR_LAYER, layer,
+ G_TYPE_NONE);
+
+ return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
+ "gimp-vector-layer-discard",
+ args);
+ gimp_value_array_unref (args);
+
+ success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
+
+ gimp_value_array_unref (return_vals);
+
+ return success;
+}
diff --git a/libgimp/gimpvectorlayer_pdb.h b/libgimp/gimpvectorlayer_pdb.h
new file mode 100644
index 0000000000..0424adc343
--- /dev/null
+++ b/libgimp/gimpvectorlayer_pdb.h
@@ -0,0 +1,43 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpvectorlayer_pdb.h
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * .
+ */
+
+/* NOTE: This file is auto-generated by pdbgen.pl */
+
+#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __GIMP_VECTOR_LAYER_PDB_H__
+#define __GIMP_VECTOR_LAYER_PDB_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+GimpVectorLayer* gimp_vector_layer_new (GimpImage *image,
+ GimpPath *path);
+gboolean gimp_vector_layer_refresh (GimpVectorLayer *layer);
+gboolean gimp_vector_layer_discard (GimpVectorLayer *layer);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_VECTOR_LAYER_PDB_H__ */
diff --git a/libgimp/meson.build b/libgimp/meson.build
index e1915765cd..6e1d974e10 100644
--- a/libgimp/meson.build
+++ b/libgimp/meson.build
@@ -114,6 +114,7 @@ pdb_wrappers_sources = [
'gimptextlayer_pdb.c',
'gimptexttool_pdb.c',
'gimpunit_pdb.c',
+ 'gimpvectorlayer_pdb.c',
]
pdb_wrappers_headers = [
@@ -173,6 +174,7 @@ pdb_wrappers_headers = [
'gimptextlayer_pdb.h',
'gimptexttool_pdb.h',
'gimpunit_pdb.h',
+ 'gimpvectorlayer_pdb.h',
]
libgimp_sources_introspectable = [
@@ -214,6 +216,7 @@ libgimp_sources_introspectable = [
'gimpselection.c',
'gimptextlayer.c',
'gimpthumbnailprocedure.c',
+ 'gimpvectorlayer.c',
'gimpvectorloadprocedure.c',
gimpenums,
pdb_wrappers_sources,
@@ -276,6 +279,7 @@ libgimp_headers_introspectable = [
'gimpselection.h',
'gimptextlayer.h',
'gimpthumbnailprocedure.h',
+ 'gimpvectorlayer.h',
'gimpvectorloadprocedure.h',
pdb_wrappers_headers,
]
diff --git a/pdb/app.pl b/pdb/app.pl
index c4de9552af..133bc70ab1 100644
--- a/pdb/app.pl
+++ b/pdb/app.pl
@@ -381,6 +381,16 @@ gimp_param_spec_text_layer ("$name",
"$blurb",
$none_ok,
$flags)
+CODE
+ }
+ elsif ($pdbtype eq 'vector_layer') {
+ $none_ok = exists $arg->{none_ok} ? 'TRUE' : 'FALSE';
+ $pspec = < 'item_id', type => 'int32',
+ desc => 'The item ID' }
+ );
+
+ @outargs = (
+ { name => 'vector_layer', type => 'boolean',
+ desc => 'TRUE if the item is a vector layer, FALSE otherwise.' }
+ );
+
+ %invoke = (
+ code => <<'CODE'
+{
+ GimpItem *item = gimp_item_get_by_id (gimp, item_id);
+
+ vector_layer = (GIMP_IS_LAYER (item) &&
+ ! gimp_item_is_removed (item) &&
+ gimp_item_is_vector_layer (item));
+}
+CODE
+ );
+}
+
sub item_id_is_group_layer {
$blurb = 'Returns whether the item ID is a group layer.';
@@ -1056,7 +1092,8 @@ CODE
"core/gimplayermask.h"
"core/gimplist.h"
"core/gimpselection.h"
- "path/gimppath.h"
+ "path/gimppath.h"
+ "path/gimpvectorlayer.h"
"text/gimptextlayer.h"
"gimppdb-utils.h"
"gimppdbcontext.h"
@@ -1066,6 +1103,7 @@ CODE
item_id_is_drawable
item_id_is_layer
item_id_is_text_layer
+ item_id_is_vector_layer
item_id_is_group_layer
item_id_is_channel
item_id_is_layer_mask
diff --git a/pdb/groups/vector_layer.pdb b/pdb/groups/vector_layer.pdb
new file mode 100644
index 0000000000..607be35eb8
--- /dev/null
+++ b/pdb/groups/vector_layer.pdb
@@ -0,0 +1,144 @@
+# GIMP - The GNU Image Manipulation Program
+# Copyright (C) 1995 Spencer Kimball and Peter Mattis
+
+# New Vector Layer PDB API
+
+# 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 .
+
+
+sub vector_layer_new {
+ $blurb = 'Creates a new vector layer.';
+
+ $help = <<'HELP';
+This procedure creates a new path layer displaying the specified @path. By
+default, the fill and stroke properties will be defined by the context.
+
+
+The new layer still needs to be added to the image as this is not
+automatic. Add the new layer with the [method@Image.insert_layer]
+method.
+
+
+The arguments are kept as simple as necessary for the basic case. All
+vector attributes, however, can be modified with the appropriate
+`gimp_vector_layer_set_*()` procedures.
+HELP
+
+ &alxsa_pdb_misc('2025', '3.2');
+
+ @inargs = (
+ { name => 'image', type => 'image',
+ desc => 'The image' },
+ { name => 'path', type => 'path',
+ desc => 'The path to create the layer from' }
+ );
+
+ @outargs = (
+ { name => 'layer', type => 'vector_layer',
+ desc => 'The new vector layer. The object belongs to libgimp and you should not free it.' }
+ );
+
+ %invoke = (
+ code => <<'CODE'
+{
+ if (path == NULL)
+ {
+ g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
+ _("Failed to create vector layer"));
+
+ success = FALSE;
+ }
+
+ if (success)
+ {
+ layer = GIMP_VECTOR_LAYER (gimp_vector_layer_new (image, path, context));
+
+ if (! layer)
+ {
+ g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
+ _("Failed to create vector layer"));
+
+ success = FALSE;
+ }
+ }
+}
+CODE
+ );
+}
+
+sub vector_layer_refresh {
+ $blurb = 'Rerender the vector layer';
+
+ $help = <<'HELP';
+This procedure causes the vector layer to refresh itself after changes.
+HELP
+
+ &alxsa_pdb_misc('2025', '3.2');
+
+ @inargs = (
+ { name => 'layer', type => 'vector_layer',
+ desc => 'The vector layer' }
+ );
+
+ %invoke = (
+ code => <<'CODE'
+{
+ gimp_vector_layer_refresh (layer);
+}
+CODE
+ );
+}
+
+sub vector_layer_discard {
+ $blurb = 'Discard the vector layer information.';
+
+ $help = <<'HELP';
+Discards the vector information. This makes the layer behave like a normal layer.
+HELP
+
+ &alxsa_pdb_misc('2025', '3.2');
+
+ @inargs = (
+ { name => 'layer', type => 'vector_layer',
+ desc => 'The vector layer' }
+ );
+
+ %invoke = (
+ code => <<'CODE'
+{
+ gimp_vector_layer_discard (layer);
+}
+CODE
+ );
+}
+
+@headers = qw("libgimpbase/gimpbase.h"
+ "core/gimpcontext.h"
+ "path/gimpvectorlayer.h"
+ "gimppdb-utils.h"
+ "gimppdberror.h"
+ "gimp-intl.h");
+
+@procs = qw(vector_layer_new
+ vector_layer_refresh
+ vector_layer_discard);
+
+%exports = (app => [@procs], lib => [@procs]);
+
+$desc = 'Vector layer procedures';
+$doc_title = 'gimpvectorlayer';
+$doc_short_desc = 'Functions for querying and manipulating vector layers.';
+$doc_long_desc = 'Functions for querying and manipulating vector layers.';
+
+1;
diff --git a/pdb/meson.build b/pdb/meson.build
index 0ec68d25b9..d0c0a5f20c 100644
--- a/pdb/meson.build
+++ b/pdb/meson.build
@@ -59,6 +59,7 @@ pdb_names = [
'text_layer',
'text_tool',
'unit',
+ 'vector_layer',
]
pdb_sources = []
diff --git a/pdb/pdb.pl b/pdb/pdb.pl
index 68fd0fe1c8..aa8591d575 100644
--- a/pdb/pdb.pl
+++ b/pdb/pdb.pl
@@ -371,6 +371,18 @@ package Gimp::CodeGen::pdb;
take_value_func => 'g_value_set_object ($value, $var)',
headers => [ qw("text/gimptextlayer.h") ] },
+ vector_layer => { name => 'VECTOR_LAYER',
+ gtype => 'GIMP_TYPE_VECTOR_LAYER',
+ type => 'GimpVectorLayer *',
+ const_type => 'GimpVectorLayer *',
+ init_value => 'NULL',
+ out_annotate => '(transfer none)',
+ get_value_func => '$var = g_value_get_object ($value)',
+ dup_value_func => '$var = GIMP_VALUES_GET_VECTOR_LAYER ($value)',
+ set_value_func => 'g_value_set_object ($value, $var)',
+ take_value_func => 'g_value_set_object ($value, $var)',
+ headers => [ qw("path/gimpvectorlayer.h") ] },
+
group_layer => { name => 'GROUP_LAYER',
gtype => 'GIMP_TYPE_GROUP_LAYER',
type => 'GimpGroupLayer *',