diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index 1153737a2d..be16535ca2 100644
--- a/app/actions/layers-actions.c
+++ b/app/actions/layers-actions.c
@@ -33,6 +33,8 @@
#include "text/gimptextlayer.h"
+#include "vectors/gimpvectorlayer.h"
+
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpactiongroup.h"
#include "widgets/gimpwidgets-utils.h"
@@ -60,6 +62,12 @@ static const GimpActionEntry layers_actions[] =
layers_edit_text_cmd_callback,
GIMP_HELP_LAYER_EDIT },
+{ "layers-edit-vector", GIMP_ICON_TOOL_PATH,
+ N_("Path Tool"), NULL, { NULL },
+ N_("Activate the path tool on this vector layer's path"),
+ layers_edit_vector_cmd_callback,
+ GIMP_HELP_TOOL_PATH },
+
{ "layers-edit-attributes", GIMP_ICON_EDIT,
NC_("layers-action", "_Edit Layer Attributes..."), NULL, { NULL },
NC_("layers-action", "Edit the layer's name"),
@@ -191,6 +199,18 @@ static const GimpActionEntry layers_actions[] =
layers_text_along_vectors_cmd_callback,
GIMP_HELP_LAYER_TEXT_ALONG_PATH },
+ { "layers-vector-fill-stroke", NULL,
+ NC_("layers-action", "Fill / Stroke"), NULL, { NULL },
+ NC_("layers-action", "Edit the fill and stroke of this vector layer"),
+ layers_vector_fill_stroke_cmd_callback,
+ NULL },
+
+ { "layers-vector-discard", NULL,
+ NC_("layers-action", "Discard Vector Information"), NULL, { NULL },
+ NC_("layers-action", "Turn this vector layer into a normal layer"),
+ layers_vector_discard_cmd_callback,
+ NULL },
+
{ "layers-resize", GIMP_ICON_OBJECT_RESIZE,
NC_("layers-action", "Layer B_oundary Size..."), NULL, { NULL },
NC_("layers-action", "Adjust the layer dimensions"),
@@ -757,6 +777,7 @@ layers_actions_update (GimpActionGroup *group,
gboolean lock_alpha = TRUE;
gboolean can_lock_alpha = FALSE;
gboolean text_layer = FALSE;
+ gboolean vector_layer = FALSE;
gboolean bs_mutable = FALSE; /* At least 1 selected layers' blend space is mutable. */
gboolean cs_mutable = FALSE; /* At least 1 selected layers' composite space is mutable. */
gboolean cm_mutable = FALSE; /* At least 1 selected layers' composite mode is mutable. */
@@ -977,7 +998,8 @@ layers_actions_update (GimpActionGroup *group,
gimp_action_group_set_action_active (group, action, TRUE);
- text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
+ text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
+ vector_layer = gimp_item_is_vector_layer (GIMP_ITEM (layer));
}
}
@@ -993,6 +1015,7 @@ layers_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("layers-edit", !ac && ((layer && !fs) || text_layer));
SET_VISIBLE ("layers-edit-text", text_layer && !ac);
SET_SENSITIVE ("layers-edit-text", text_layer && !ac);
+ SET_VISIBLE ("layers-edit-vector", vector_layer && !ac);
SET_SENSITIVE ("layers-edit-attributes", layer && !fs && !ac);
if (layer && gimp_layer_is_floating_sel (layer))
@@ -1042,6 +1065,9 @@ layers_actions_update (GimpActionGroup *group,
SET_VISIBLE ("layers-text-to-vectors", n_text_layers > 0 && !ac);
SET_VISIBLE ("layers-text-along-vectors", text_layer && !ac);
+ SET_VISIBLE ("layers-vector-fill-stroke", vector_layer && !ac);
+ SET_VISIBLE ("layers-vector-discard", vector_layer && !ac);
+
SET_SENSITIVE ("layers-resize", n_selected_layers == 1 && all_writable && all_movable && !ac);
SET_SENSITIVE ("layers-resize-to-image", all_writable && all_movable && !ac);
SET_SENSITIVE ("layers-scale", n_selected_layers == 1 && all_writable && all_movable && !ac);
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index bde74e484a..8bf4d6b429 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -62,6 +62,8 @@
#include "vectors/gimppath.h"
#include "vectors/gimppath-warp.h"
#include "vectors/gimpstroke.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayeroptions.h"
#include "widgets/gimpaction.h"
#include "widgets/gimpdock.h"
@@ -73,6 +75,7 @@
#include "display/gimpimagewindow.h"
#include "tools/gimptexttool.h"
+#include "tools/gimpvectortool.h"
#include "tools/tool_manager.h"
#include "dialogs/dialogs.h"
@@ -80,6 +83,7 @@
#include "dialogs/layer-options-dialog.h"
#include "dialogs/resize-dialog.h"
#include "dialogs/scale-dialog.h"
+#include "dialogs/vector-layer-options-dialog.h"
#include "actions.h"
#include "items-commands.h"
@@ -200,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);
@@ -251,6 +259,52 @@ layers_edit_text_cmd_callback (GimpAction *action,
}
}
+void
+layers_edit_vector_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GList *layers;
+ GtkWidget *widget;
+ GimpTool *active_tool;
+ return_if_no_layers (image, layers, data);
+ return_if_no_widget (widget, data);
+
+ if (g_list_length (layers) != 1)
+ return;
+
+ layer = layers->data;
+
+ if (! gimp_item_is_vector_layer (GIMP_ITEM (layer)))
+ {
+ layers_edit_attributes_cmd_callback (action, value, data);
+ return;
+ }
+
+ active_tool = tool_manager_get_active (image->gimp);
+
+ if (! GIMP_IS_VECTOR_TOOL (active_tool))
+ {
+ GimpToolInfo *tool_info;
+
+ tool_info = (GimpToolInfo *)
+ gimp_container_get_child_by_name (image->gimp->tool_info_list,
+ "gimp-vector-tool");
+
+ if (GIMP_IS_TOOL_INFO (tool_info))
+ {
+ gimp_context_set_tool (action_data_get_context (data), tool_info);
+ active_tool = tool_manager_get_active (image->gimp);
+ }
+ }
+
+ if (GIMP_IS_VECTOR_TOOL (active_tool))
+ gimp_vector_tool_set_vectors (GIMP_VECTOR_TOOL (active_tool),
+ GIMP_VECTOR_LAYER (layer)->options->path);
+}
+
void
layers_edit_attributes_cmd_callback (GimpAction *action,
GVariant *value,
@@ -2591,6 +2645,56 @@ layers_scale_callback (GtkWidget *dialog,
}
}
+void
+layers_vector_fill_stroke_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GList *layers;
+ GtkWidget *widget;
+ return_if_no_layers (image, layers, data);
+ return_if_no_widget (widget, data);
+
+ if (g_list_length (layers) != 1)
+ return;
+
+ layer = layers->data;
+
+ if (GIMP_IS_VECTOR_LAYER (layer))
+ {
+ GtkWidget *dialog;
+
+ dialog = vector_layer_options_dialog_new (GIMP_VECTOR_LAYER (layer),
+ action_data_get_context (data),
+ _("Fill / Stroke"),
+ "gimp-vector-layer-stroke",
+ NULL,
+ widget);
+ gtk_widget_show (dialog);
+ }
+}
+
+void
+layers_vector_discard_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GList *layers;
+ return_if_no_layers (image, layers, data);
+
+ if (g_list_length (layers) != 1)
+ return;
+
+ layer = layers->data;
+
+ if (GIMP_IS_VECTOR_LAYER (layer))
+ gimp_vector_layer_discard (GIMP_VECTOR_LAYER (layer));
+}
+
static void
layers_resize_callback (GtkWidget *dialog,
GimpViewable *viewable,
diff --git a/app/actions/layers-commands.h b/app/actions/layers-commands.h
index 6e28d641e5..f29fd7b3e3 100644
--- a/app/actions/layers-commands.h
+++ b/app/actions/layers-commands.h
@@ -25,6 +25,9 @@ void layers_edit_cmd_callback (GimpAction *action,
void layers_edit_text_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
+void layers_edit_vector_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
void layers_edit_attributes_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
@@ -84,6 +87,12 @@ void layers_text_to_vectors_cmd_callback (GimpAction *action,
void layers_text_along_vectors_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
+void layers_vector_fill_stroke_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_vector_discard_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
void layers_resize_cmd_callback (GimpAction *action,
GVariant *value,
diff --git a/app/actions/paths-actions.c b/app/actions/paths-actions.c
index 3d3c1ff58c..8a1366995e 100644
--- a/app/actions/paths-actions.c
+++ b/app/actions/paths-actions.c
@@ -149,7 +149,12 @@ static const GimpActionEntry paths_actions[] =
{ "paths-import", GIMP_ICON_DOCUMENT_OPEN,
NC_("paths-action", "I_mport Path..."), NULL, { NULL }, NULL,
paths_import_cmd_callback,
- GIMP_HELP_PATH_IMPORT }
+ GIMP_HELP_PATH_IMPORT },
+
+ { "paths-to-vector-layer", NULL,
+ NC_("paths-action", "Path to Vector Layer"), NULL, { NULL }, NULL,
+ path_to_vector_layer_cmd_callback,
+ NULL },
};
static const GimpToggleActionEntry paths_toggle_actions[] =
@@ -429,6 +434,8 @@ paths_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("paths-export", n_selected_paths > 0);
SET_SENSITIVE ("paths-import", image);
+ SET_SENSITIVE ("paths-to-vector-layer", n_selected_paths > 0);
+
SET_SENSITIVE ("paths-selection-to-path", image && !mask_empty);
SET_SENSITIVE ("paths-selection-to-path-advanced", image && !mask_empty);
SET_SENSITIVE ("paths-fill", n_selected_paths > 0 &&
diff --git a/app/actions/paths-commands.c b/app/actions/paths-commands.c
index d273f42c55..a85f29b6e5 100644
--- a/app/actions/paths-commands.c
+++ b/app/actions/paths-commands.c
@@ -47,6 +47,7 @@
#include "vectors/gimppath.h"
#include "vectors/gimppath-export.h"
#include "vectors/gimppath-import.h"
+#include "vectors/gimpvectorlayer.h"
#include "widgets/gimpaction.h"
#include "widgets/gimpclipboard.h"
@@ -509,6 +510,28 @@ paths_merge_visible_cmd_callback (GimpAction *action,
gimp_image_flush (image);
}
+void
+path_to_vector_layer_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GList *paths;
+ GimpVectorLayer *layer;
+ return_if_no_paths (image, paths, data);
+
+ layer = gimp_vector_layer_new (image, paths->data,
+ gimp_get_user_context (image->gimp));
+ gimp_image_add_layer (image,
+ GIMP_LAYER (layer),
+ GIMP_IMAGE_ACTIVE_PARENT,
+ -1,
+ TRUE);
+ gimp_vector_layer_refresh (layer);
+
+ gimp_image_flush (image);
+}
+
void
paths_to_selection_cmd_callback (GimpAction *action,
GVariant *value,
diff --git a/app/actions/paths-commands.h b/app/actions/paths-commands.h
index 8d071f93d4..5ea6fc2cb1 100644
--- a/app/actions/paths-commands.h
+++ b/app/actions/paths-commands.h
@@ -51,6 +51,9 @@ void paths_duplicate_cmd_callback (GimpAction *action,
void paths_delete_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
+void path_to_vector_layer_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
void paths_merge_visible_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
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 5db3dfd541..f84626986b 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -621,6 +621,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 468146e13a..7d723fc95c 100644
--- a/app/core/gimpimage-undo-push.c
+++ b/app/core/gimpimage-undo-push.c
@@ -60,6 +60,8 @@
#include "vectors/gimppathmodundo.h"
#include "vectors/gimppathpropundo.h"
#include "vectors/gimppathundo.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayerundo.h"
#include "gimp-intl.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 c13850ce98..8c7f7497d3 100644
--- a/app/core/gimpimage-undo-push.h
+++ b/app/core/gimpimage-undo-push.h
@@ -216,6 +216,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/dialogs/meson.build b/app/dialogs/meson.build
index 2555e12752..f70c7926c6 100644
--- a/app/dialogs/meson.build
+++ b/app/dialogs/meson.build
@@ -56,6 +56,7 @@ libappdialogs_sources = [
'tips-dialog.c',
'tips-parser.c',
'user-install-dialog.c',
+ 'vector-layer-options-dialog.c',
'welcome-dialog.c',
gitversion_h,
welcome_dialog_data_c,
diff --git a/app/dialogs/vector-layer-options-dialog.c b/app/dialogs/vector-layer-options-dialog.c
new file mode 100644
index 0000000000..d5bbd7dc3a
--- /dev/null
+++ b/app/dialogs/vector-layer-options-dialog.c
@@ -0,0 +1,301 @@
+/* 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/gimpcontainercombobox.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimppropwidgets.h"
+#include "widgets/gimpviewabledialog.h"
+#include "widgets/gimpstrokeeditor.h"
+
+#include "vectors/gimppath.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);
+static void vector_layer_options_dialog_path_selected (GtkWidget *widget,
+ GList *items,
+ GList *paths,
+ 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,
+ _("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);
+
+
+ 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_select_item (GIMP_CONTAINER_VIEW (combo),
+ GIMP_VIEWABLE (saved_options->path));
+ g_signal_connect_object (combo, "select-items",
+ 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;
+
+ 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;
+ 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)
+ {
+ 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 (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 (GtkWidget *widget,
+ GList *items,
+ GList *paths,
+ GtkWidget *dialog)
+{
+ GimpPath *path = NULL;
+ GimpVectorLayer *layer;
+
+ layer = g_object_get_data (G_OBJECT (dialog), "layer");
+
+ if (items)
+ path = items->data;
+
+ 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
new file mode 100644
index 0000000000..c7294366f7
--- /dev/null
+++ b/app/dialogs/vector-layer-options-dialog.h
@@ -0,0 +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__ */
diff --git a/app/tools/gimpvectoroptions.c b/app/tools/gimpvectoroptions.c
index 01dd3f7ff5..aed1ed071b 100644
--- a/app/tools/gimpvectoroptions.c
+++ b/app/tools/gimpvectoroptions.c
@@ -192,7 +192,7 @@ gimp_vector_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
gimp_help_set_help_data (button, str, GIMP_HELP_PATH_SELECTION_REPLACE);
- gtk_widget_show (button);
+ gtk_widget_set_visible (button, TRUE);
g_free (str);
@@ -202,7 +202,7 @@ gimp_vector_options_gui (GimpToolOptions *tool_options)
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_show (button);
+ gtk_widget_set_visible (button, TRUE);
options->fill_button = button;
@@ -210,9 +210,17 @@ gimp_vector_options_gui (GimpToolOptions *tool_options)
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_show (button);
+ gtk_widget_set_visible (button, TRUE);
options->stroke_button = button;
+ button = gtk_button_new_with_label (_("Create 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);
+ gtk_widget_set_visible (button, TRUE);
+
+ options->vector_layer_button = button;
+
return vbox;
}
diff --git a/app/tools/gimpvectoroptions.h b/app/tools/gimpvectoroptions.h
index e13e8f3207..a69d3a3d4c 100644
--- a/app/tools/gimpvectoroptions.h
+++ b/app/tools/gimpvectoroptions.h
@@ -44,6 +44,7 @@ struct _GimpVectorOptions
GtkWidget *to_selection_button;
GtkWidget *fill_button;
GtkWidget *stroke_button;
+ GtkWidget *vector_layer_button;
};
diff --git a/app/tools/gimpvectortool.c b/app/tools/gimpvectortool.c
index 7bf9c60e47..0eb25cb800 100644
--- a/app/tools/gimpvectortool.c
+++ b/app/tools/gimpvectortool.c
@@ -41,6 +41,8 @@
#include "paint/gimppaintoptions.h" /* GIMP_PAINT_OPTIONS_CONTEXT_MASK */
#include "vectors/gimppath.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayeroptions.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockcontainer.h"
@@ -70,6 +72,7 @@
/* local function prototypes */
+static void gimp_vector_tool_constructed (GObject *object);
static void gimp_vector_tool_dispose (GObject *object);
static void gimp_vector_tool_control (GimpTool *tool,
@@ -106,6 +109,12 @@ static void gimp_vector_tool_start (GimpVectorTool *vector_
GimpDisplay *display);
static void gimp_vector_tool_halt (GimpVectorTool *vector_tool);
+static void gimp_vector_tool_image_changed (GimpVectorTool *vector_tool,
+ GimpImage *image,
+ GimpContext *context);
+static void gimp_vector_tool_image_selected_layers_changed
+ (GimpVectorTool *vector_tool);
+
static void gimp_vector_tool_path_changed (GimpToolWidget *path,
GimpVectorTool *vector_tool);
static void gimp_vector_tool_path_begin_change
@@ -147,6 +156,10 @@ static void gimp_vector_tool_stroke_callback (GtkWidget *dialog,
GimpStrokeOptions *options,
gpointer data);
+static void gimp_vector_tool_create_vector_layer
+ (GimpVectorTool *vector_tool,
+ GtkWidget *button);
+
G_DEFINE_TYPE (GimpVectorTool, gimp_vector_tool, GIMP_TYPE_DRAW_TOOL)
@@ -178,6 +191,7 @@ gimp_vector_tool_class_init (GimpVectorToolClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
+ object_class->constructed = gimp_vector_tool_constructed;
object_class->dispose = gimp_vector_tool_dispose;
tool_class->control = gimp_vector_tool_control;
@@ -202,6 +216,29 @@ gimp_vector_tool_init (GimpVectorTool *vector_tool)
vector_tool->saved_mode = GIMP_VECTOR_MODE_DESIGN;
}
+static void
+gimp_vector_tool_constructed (GObject *object)
+{
+ GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (object);
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ tool_info = GIMP_TOOL (vector_tool)->tool_info;
+
+ context = gimp_get_user_context (tool_info->gimp);
+
+ g_signal_connect_object (context, "image-changed",
+ G_CALLBACK (gimp_vector_tool_image_changed),
+ vector_tool, G_CONNECT_SWAPPED);
+
+ gimp_vector_tool_image_changed (vector_tool,
+ gimp_context_get_image (context),
+ context);
+}
+
+
static void
gimp_vector_tool_dispose (GObject *object)
{
@@ -210,6 +247,8 @@ gimp_vector_tool_dispose (GObject *object)
gimp_vector_tool_set_vectors (vector_tool, NULL);
g_clear_object (&vector_tool->widget);
+ gimp_vector_tool_image_changed (vector_tool, NULL, NULL);
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -444,6 +483,51 @@ gimp_vector_tool_halt (GimpVectorTool *vector_tool)
tool->display = NULL;
}
+static void
+gimp_vector_tool_image_changed (GimpVectorTool *vector_tool,
+ GimpImage *image,
+ GimpContext *context)
+{
+ if (vector_tool->current_image)
+ g_signal_handlers_disconnect_by_func (vector_tool->current_image,
+ gimp_vector_tool_image_selected_layers_changed,
+ NULL);
+
+ g_set_weak_pointer (&vector_tool->current_image, image);
+
+ if (vector_tool->current_image)
+ g_signal_connect_object (vector_tool->current_image, "selected-layers-changed",
+ G_CALLBACK (gimp_vector_tool_image_selected_layers_changed),
+ vector_tool, G_CONNECT_SWAPPED);
+
+ gimp_vector_tool_image_selected_layers_changed (vector_tool);
+}
+
+static void
+gimp_vector_tool_image_selected_layers_changed (GimpVectorTool *vector_tool)
+{
+ GList *current_layers = NULL;
+
+ if (vector_tool->current_image)
+ current_layers =
+ gimp_image_get_selected_layers (vector_tool->current_image);
+
+ if (current_layers)
+ {
+ /* If we've selected a single vector layer, make its path editable */
+ if (g_list_length (current_layers) == 1 &&
+ GIMP_IS_VECTOR_LAYER (current_layers->data))
+ {
+ GimpVectorLayer *vector_layer = current_layers->data;
+
+ if (vector_layer->options && vector_layer->options->path)
+ gimp_vector_tool_set_vectors (vector_tool,
+ vector_layer->options->path);
+ }
+ }
+}
+
+
static void
gimp_vector_tool_path_changed (GimpToolWidget *path,
GimpVectorTool *vector_tool)
@@ -609,6 +693,14 @@ gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool,
gimp_vector_tool_stroke_vectors,
tool);
}
+
+ if (options->vector_layer_button)
+ {
+ gtk_widget_set_sensitive (options->vector_layer_button, FALSE);
+ g_signal_handlers_disconnect_by_func (options->vector_layer_button,
+ gimp_vector_tool_create_vector_layer,
+ tool);
+ }
}
if (! vectors ||
@@ -657,6 +749,15 @@ gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool,
gtk_widget_set_sensitive (options->stroke_button, TRUE);
}
+ if (options->vector_layer_button)
+ {
+ g_signal_connect_swapped (options->vector_layer_button, "clicked",
+ G_CALLBACK (gimp_vector_tool_create_vector_layer),
+ tool);
+
+ gtk_widget_set_sensitive (options->vector_layer_button, TRUE);
+ }
+
if (tool->display)
{
gimp_tool_path_set_vectors (GIMP_TOOL_PATH (vector_tool->widget), vectors);
@@ -898,3 +999,30 @@ gimp_vector_tool_stroke_callback (GtkWidget *dialog,
gimp_image_flush (image);
gtk_widget_destroy (dialog);
}
+
+
+static void
+gimp_vector_tool_create_vector_layer (GimpVectorTool *vector_tool,
+ GtkWidget *button)
+{
+ GimpImage *image;
+ GimpVectorLayer *layer;
+
+ if (! vector_tool->vectors)
+ return;
+
+ image = gimp_item_get_image (GIMP_ITEM (vector_tool->vectors));
+
+ layer = gimp_vector_layer_new (image, vector_tool->vectors,
+ gimp_get_user_context (image->gimp));
+
+ gimp_image_add_layer (image,
+ GIMP_LAYER (layer),
+ GIMP_IMAGE_ACTIVE_PARENT,
+ -1,
+ TRUE);
+
+ gimp_vector_layer_refresh (layer);
+
+ gimp_image_flush (image);
+}
diff --git a/app/tools/gimpvectortool.h b/app/tools/gimpvectortool.h
index d08910e216..05316147ed 100644
--- a/app/tools/gimpvectortool.h
+++ b/app/tools/gimpvectortool.h
@@ -42,6 +42,8 @@ struct _GimpVectorTool
{
GimpDrawTool parent_instance;
+ GimpImage *current_image;
+
GimpPath *vectors; /* the current Path data */
GimpVectorMode saved_mode; /* used by modifier_key() */
diff --git a/app/vectors/gimpvectorlayer-xcf.c b/app/vectors/gimpvectorlayer-xcf.c
new file mode 100644
index 0000000000..6b5637db63
--- /dev/null
+++ b/app/vectors/gimpvectorlayer-xcf.c
@@ -0,0 +1,171 @@
+/* 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 "vectors-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/vectors/gimpvectorlayer-xcf.h b/app/vectors/gimpvectorlayer-xcf.h
new file mode 100644
index 0000000000..5757c7baa3
--- /dev/null
+++ b/app/vectors/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/vectors/gimpvectorlayer.c b/app/vectors/gimpvectorlayer.c
new file mode 100644
index 0000000000..a1ba0901c2
--- /dev/null
+++ b/app/vectors/gimpvectorlayer.c
@@ -0,0 +1,712 @@
+/* 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 "vectors-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,
+ GimpPath *path);
+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";
+
+ 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->default_name = _("Vector Layer");
+ 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));
+
+ 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);
+ gint x, y;
+
+ if (vector_layer->options && vector_layer->options->path)
+ gimp_item_translate (GIMP_ITEM (vector_layer->options->path),
+ offset_x, offset_y, FALSE);
+
+ /* Correct offset for vector layer after moving path */
+ gimp_item_get_offset (GIMP_ITEM (layer), &x, &y);
+
+ x += offset_x;
+ y += offset_y;
+
+ gimp_item_set_offset (GIMP_ITEM (layer), x, 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);
+ }
+}
+
+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);
+ }
+}
+
+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);
+ }
+}
+
+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);
+ }
+}
+
+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 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);
+
+ layer =
+ GIMP_VECTOR_LAYER (gimp_drawable_new (GIMP_TYPE_VECTOR_LAYER,
+ image, NULL,
+ 0, 0, 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;
+}
+
+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);
+}
+
+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);
+ GimpItem *item = GIMP_ITEM (layer);
+ GimpImage *image = gimp_item_get_image (item);
+
+ g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
+
+ g_object_freeze_notify (G_OBJECT (drawable));
+
+ /* 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, layer->options->path);
+
+ g_object_thaw_notify (G_OBJECT (drawable));
+
+ return TRUE;
+}
+
+static void
+gimp_vector_layer_render_path (GimpVectorLayer *layer,
+ GimpPath *path)
+{
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
+ GimpChannel *selection = gimp_image_get_mask (image);
+ GList *drawables;
+ GimpCustomStyle style;
+
+ /* 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 (layer->options->fill_options);
+ if (style == GIMP_CUSTOM_STYLE_SOLID_COLOR ||
+ ! gimp_context_get_pattern (GIMP_CONTEXT (layer->options->fill_options)))
+ gimp_fill_options_set_style (layer->options->fill_options,
+ GIMP_FILL_STYLE_FG_COLOR);
+ else
+ gimp_fill_options_set_style (layer->options->fill_options,
+ GIMP_FILL_STYLE_PATTERN);
+
+ style =
+ gimp_fill_options_get_custom_style (GIMP_FILL_OPTIONS (layer->options->stroke_options));
+ if (style == GIMP_CUSTOM_STYLE_SOLID_COLOR ||
+ ! gimp_context_get_pattern (GIMP_CONTEXT (layer->options->stroke_options)))
+ gimp_fill_options_set_style (GIMP_FILL_OPTIONS (layer->options->stroke_options),
+ GIMP_FILL_STYLE_FG_COLOR);
+ else
+ gimp_fill_options_set_style (GIMP_FILL_OPTIONS (layer->options->stroke_options),
+ GIMP_FILL_STYLE_PATTERN);
+
+ /* Fill the path object onto the layer */
+ gimp_drawable_fill_path (GIMP_DRAWABLE (layer),
+ layer->options->fill_options,
+ path, FALSE, NULL);
+
+ drawables = g_list_prepend (NULL, GIMP_DRAWABLE (layer));
+ /* stroke the path object onto the layer */
+ gimp_item_stroke (GIMP_ITEM (path),
+ drawables,
+ gimp_get_user_context (gimp_item_get_image (GIMP_ITEM (layer))->gimp),
+ layer->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/vectors/gimpvectorlayer.h b/app/vectors/gimpvectorlayer.h
new file mode 100644
index 0000000000..d4d86cf2a4
--- /dev/null
+++ b/app/vectors/gimpvectorlayer.h
@@ -0,0 +1,66 @@
+/* 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);
+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/vectors/gimpvectorlayeroptions-parasite.c b/app/vectors/gimpvectorlayeroptions-parasite.c
new file mode 100644
index 0000000000..6303bc3653
--- /dev/null
+++ b/app/vectors/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 "vectors-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/vectors/gimpvectorlayeroptions-parasite.h b/app/vectors/gimpvectorlayeroptions-parasite.h
new file mode 100644
index 0000000000..7765cb6c67
--- /dev/null
+++ b/app/vectors/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/vectors/gimpvectorlayeroptions.c b/app/vectors/gimpvectorlayeroptions.c
new file mode 100644
index 0000000000..da787c9487
--- /dev/null
+++ b/app/vectors/gimpvectorlayeroptions.c
@@ -0,0 +1,339 @@
+/* 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 "vectors-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_FILL_OPTIONS,
+ 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_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_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_FILL_OPTIONS:
+ g_value_set_object (value, options->fill_options);
+ 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_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_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->stroke_options,
+ "width", 3.0,
+ NULL);
+
+ g_object_set (options,
+ "path", path,
+ NULL);
+
+ return options;
+}
diff --git a/app/vectors/gimpvectorlayeroptions.h b/app/vectors/gimpvectorlayeroptions.h
new file mode 100644
index 0000000000..73657853ae
--- /dev/null
+++ b/app/vectors/gimpvectorlayeroptions.h
@@ -0,0 +1,64 @@
+/* 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;
+
+ 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/vectors/gimpvectorlayerundo.c b/app/vectors/gimpvectorlayerundo.c
new file mode 100644
index 0000000000..2475546249
--- /dev/null
+++ b/app/vectors/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 "vectors-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/vectors/gimpvectorlayerundo.h b/app/vectors/gimpvectorlayerundo.h
new file mode 100644
index 0000000000..37894a3b92
--- /dev/null
+++ b/app/vectors/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/vectors/meson.build b/app/vectors/meson.build
index 46cb025d43..b6a5a26980 100644
--- a/app/vectors/meson.build
+++ b/app/vectors/meson.build
@@ -12,6 +12,11 @@ libappvectors_sources = [
'gimppathundo.c',
'gimpstroke-new.c',
'gimpstroke.c',
+ 'gimpvectorlayer.c',
+ 'gimpvectorlayer-xcf.c',
+ 'gimpvectorlayeroptions.c',
+ 'gimpvectorlayeroptions-parasite.c',
+ 'gimpvectorlayerundo.c',
]
libappvectors = static_library('appvectors',
diff --git a/app/vectors/vectors-types.h b/app/vectors/vectors-types.h
index 37193a0055..e7963f5c25 100644
--- a/app/vectors/vectors-types.h
+++ b/app/vectors/vectors-types.h
@@ -33,5 +33,9 @@ typedef struct _GimpPath GimpPath;
typedef struct _GimpStroke GimpStroke;
typedef struct _GimpBezierStroke GimpBezierStroke;
+typedef struct _GimpVectorLayer GimpVectorLayer;
+typedef struct _GimpVectorLayerOptions GimpVectorLayerOptions;
+typedef struct _GimpVectorLayerUndo GimpVectorLayerUndo;
+
#endif /* __VECTORS_TYPES_H__ */
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index a530db281c..73ba3bb4a4 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -76,6 +76,8 @@
#include "vectors/gimpbezierstroke.h"
#include "vectors/gimppath.h"
#include "vectors/gimppath-compat.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayer-xcf.h"
#include "xcf-private.h"
#include "xcf-load.h"
@@ -3149,7 +3151,7 @@ xcf_load_layer (XcfInfo *info,
xcf_progress_update (info);
- /* call the evil text layer hack that might change our layer pointer */
+ /* call the evil text and vector layer hack that might change our layer pointer */
selected = g_list_find (info->selected_layers, layer);
linked = g_list_find (info->linked_layers, layer);
floating = (info->floating_sel == layer);
@@ -3172,6 +3174,16 @@ xcf_load_layer (XcfInfo *info,
if (floating)
info->floating_sel = layer;
}
+ else if (gimp_vector_layer_xcf_load_hack (&layer))
+ {
+ if (selected)
+ {
+ info->selected_layers = g_list_delete_link (info->selected_layers, selected);
+ info->selected_layers = g_list_prepend (info->selected_layers, layer);
+ }
+ if (floating)
+ info->floating_sel = layer;
+ }
/* if this is not the floating selection, we can fix the layer's
* space already now, the function will do nothing if we already
diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c
index 39b162b7a6..ce587f9121 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -70,6 +70,8 @@
#include "vectors/gimppath.h"
#include "vectors/gimpstroke.h"
#include "vectors/gimppath-compat.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayer-xcf.h"
#include "xcf-private.h"
#include "xcf-read.h"
@@ -720,6 +722,12 @@ xcf_save_layer_props (XcfInfo *info,
image, PROP_TEXT_LAYER_FLAGS, error,
flags), ;);
}
+ else if (GIMP_IS_VECTOR_LAYER (layer) && GIMP_VECTOR_LAYER (layer)->options)
+ {
+ GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (layer);
+
+ gimp_vector_layer_xcf_save_prepare (vector_layer);
+ }
if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
{
diff --git a/menus/image-menu.ui.in.in b/menus/image-menu.ui.in.in
index 633c4dfff4..2df5d65761 100644
--- a/menus/image-menu.ui.in.in
+++ b/menus/image-menu.ui.in.in
@@ -433,6 +433,10 @@
- app.layers-text-to-vectors
- app.layers-text-along-vectors
+
+ - app.layers-vector-fill-stroke
+ - app.layers-vector-discard
+
Stac_k
diff --git a/menus/layers-menu.ui b/menus/layers-menu.ui
index e780d64387..69e4270a9b 100644
--- a/menus/layers-menu.ui
+++ b/menus/layers-menu.ui
@@ -7,6 +7,7 @@
gimp-layers
- app.layers-edit-text
+ - app.layers-edit-vector
- app.layers-edit-attributes
Blend Space
@@ -63,6 +64,10 @@
- app.layers-text-to-vectors
- app.layers-text-along-vectors
+
+ - app.layers-vector-fill-stroke
+ - app.layers-vector-discard
+
- app.layers-resize
- app.layers-resize-to-image
diff --git a/menus/paths-menu.ui b/menus/paths-menu.ui
index 11570eb1fd..b6fafd2e58 100644
--- a/menus/paths-menu.ui
+++ b/menus/paths-menu.ui
@@ -29,6 +29,7 @@
- app.paths-merge-visible
+ - app.paths-to-vector-layer
- app.paths-selection-replace
- app.paths-selection-add
- app.paths-selection-subtract