[gimp/wip/wormnest/vector-layers] Vector Layers from GSoC 2006 by Hendrik Boom




commit fb0a8b6163fa4fabc4d98154e4e0981baca75d3f
Author: Jacob Boerema <jgboerema gmail com>
Date:   Mon Aug 30 19:25:02 2021 -0400

    Vector Layers from GSoC 2006 by Hendrik Boom
    
    Adaption of patch 1 from issue #282.
    Author according to patch: Martin Nordholts <martinn src gnome org>
    
    A whole lot of changes needed to be made to make it build on master.
    Several assumptions have been made, parts have been disabled, just
    to make it compile - Wormnest.
    
    January 2022:
    There's a large #if 0 part in app/tools/gimpvectortool.c. I think most of
    that code was already integrated into GIMP in app/display/gimptoolpath.c,
    but I didn't get around to checking if that is true for all of it.

 app/actions/layers-actions.c                  |  34 +-
 app/actions/layers-commands.c                 |  91 ++-
 app/actions/layers-commands.h                 |   9 +
 app/actions/vectors-actions.c                 |  10 +-
 app/actions/vectors-commands.c                |  25 +-
 app/actions/vectors-commands.h                |   9 +
 app/dialogs/Makefile.am                       |   2 +
 app/dialogs/meson.build                       |   2 +
 app/dialogs/vector-layer-options-dialog.c     | 237 +++++++
 app/dialogs/vector-layer-options-dialog.h     |  33 +
 app/tools/gimpvectoroptions.c                 |  33 +-
 app/tools/gimpvectoroptions.h                 |   1 +
 app/tools/gimpvectortool.c                    | 938 ++++++++++++++++++++++++++
 app/vectors/Makefile.am                       |  62 +-
 app/vectors/gimpvectorlayer-xcf.c             | 255 +++++++
 app/vectors/gimpvectorlayer-xcf.h             |  34 +
 app/vectors/gimpvectorlayer.c                 | 442 ++++++++++++
 app/vectors/gimpvectorlayer.h                 |  63 ++
 app/vectors/gimpvectorlayeroptions-parasite.c |  95 +++
 app/vectors/gimpvectorlayeroptions-parasite.h |  33 +
 app/vectors/gimpvectorlayeroptions.c          | 367 ++++++++++
 app/vectors/gimpvectorlayeroptions.h          |  64 ++
 app/vectors/meson.build                       |   4 +
 app/vectors/vectors-types.h                   |  11 +-
 app/xcf/xcf-load.c                            |  14 +-
 app/xcf/xcf-save.c                            |   8 +
 menus/image-menu.xml.in                       |   4 +
 menus/layers-menu.xml                         |   5 +
 menus/vectors-menu.xml                        |   1 +
 29 files changed, 2837 insertions(+), 49 deletions(-)
---
diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index 6e491cc634..443ab3142e 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"
@@ -97,6 +99,13 @@ static const GimpActionEntry layers_actions[] =
     layers_edit_text_cmd_callback,
     GIMP_HELP_LAYER_EDIT },
 
+  { "layers-edit-vector", GIMP_ICON_TOOL_PATH,
+    NC_("layers-action", "Edit Vector layer"), NULL,
+    NC_("layers-action",
+        "Activate the path tool to edit 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,
     NC_("layers-action", "Edit the layer's name"),
@@ -228,6 +237,18 @@ static const GimpActionEntry layers_actions[] =
     layers_text_along_vectors_cmd_callback,
     GIMP_HELP_LAYER_TEXT_ALONG_PATH },
 
+  { "layers-vector-fill-stroke", NULL,
+    N_("Fill / Stroke"), NULL,
+    N_("Edit the fill and stroke of this vector layer"),
+    layers_vector_fill_stroke_cmd_callback,
+    NULL },
+
+  { "layers-vector-discard", NULL,
+    N_("Discard Vector Information"), NULL,
+    N_("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,
     NC_("layers-action", "Adjust the layer dimensions"),
@@ -766,6 +787,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.  */
@@ -983,8 +1005,9 @@ 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));
+         }
     }
 
 #define SET_VISIBLE(action,condition) \
@@ -996,9 +1019,11 @@ layers_actions_update (GimpActionGroup *group,
 #define SET_LABEL(action,label) \
         gimp_action_group_set_action_label (group, action, label)
 
-  SET_SENSITIVE ("layers-edit",             !ac && ((layer && !fs) || text_layer));
+  SET_SENSITIVE ("layers-edit",             !ac && ((layer && !fs) || text_layer || vector_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-vector",      vector_layer && !ac);
   SET_SENSITIVE ("layers-edit-attributes",  layer && !fs && !ac);
 
   if (layer && gimp_layer_is_floating_sel (layer))
@@ -1048,6 +1073,9 @@ layers_actions_update (GimpActionGroup *group,
   SET_VISIBLE   ("layers-text-to-vectors",    text_layer && !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 29da45f223..6a7b6153cb 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -59,6 +59,8 @@
 #include "text/gimptextlayer.h"
 
 #include "vectors/gimpstroke.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayeroptions.h"
 #include "vectors/gimpvectors.h"
 #include "vectors/gimpvectors-warp.h"
 
@@ -72,6 +74,7 @@
 #include "display/gimpimagewindow.h"
 
 #include "tools/gimptexttool.h"
+#include "tools/gimpvectortool.h"
 #include "tools/tool_manager.h"
 
 #include "dialogs/dialogs.h"
@@ -79,6 +82,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"
@@ -240,10 +244,55 @@ layers_edit_text_cmd_callback (GimpAction *action,
     }
 }
 
+void
+layers_edit_vector_cmd_callback (GimpAction *action,
+                                 GVariant   *value,
+                                 gpointer   data)
+{
+  GimpImage *image;
+  GimpLayer *layer;
+  GtkWidget *widget;
+  GimpTool  *active_tool;
+  return_if_no_layer (image, layer, data);
+  return_if_no_widget (widget, data);
+
+  g_return_if_fail (gimp_item_is_vector_layer (GIMP_ITEM (layer)));
+
+  /*if (! gimp_drawable_is_vector_layer (GIMP_DRAWABLE (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");*/
+      GimpToolInfo *tool_info = gimp_get_tool_info (image->gimp,
+                                                    "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->vectors);
+//                                  layer->options->vectors);
+}
+
 void
 layers_edit_attributes_cmd_callback (GimpAction *action,
                                      GVariant   *value,
-                                     gpointer    data)
+                                     gpointer   data)
 {
   GimpImage *image;
   GimpLayer *layer;
@@ -1058,10 +1107,48 @@ layers_text_along_vectors_cmd_callback (GimpAction *action,
     }
 }
 
+void
+layers_vector_fill_stroke_cmd_callback (GimpAction *action,
+                                        GVariant   *value,
+                                        gpointer   data)
+{
+  GimpImage *image;
+  GimpLayer *layer;
+  GtkWidget *widget;
+  return_if_no_layer (image, layer, data);
+  return_if_no_widget (widget, 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"),
+                                                _("_OK"),
+                                                NULL, /* FIXME: help id */
+                                                widget);
+      gtk_widget_show (dialog);
+    }
+}
+
+void
+layers_vector_discard_cmd_callback (GimpAction *action,
+                                    GVariant   *value,
+                                    gpointer     data)
+{
+  GimpImage *image;
+  GimpLayer *layer;
+  return_if_no_layer (image, layer, data);
+
+  if (GIMP_IS_VECTOR_LAYER (layer))
+    gimp_vector_layer_discard (GIMP_VECTOR_LAYER (layer));
+}
+
 void
 layers_resize_cmd_callback (GimpAction *action,
                             GVariant   *value,
-                            gpointer    data)
+                            gpointer   data)
 {
   GimpImage *image;
   GimpLayer *layer;
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/vectors-actions.c b/app/actions/vectors-actions.c
index c3bf9bb205..27519b8042 100644
--- a/app/actions/vectors-actions.c
+++ b/app/actions/vectors-actions.c
@@ -157,7 +157,12 @@ static const GimpActionEntry vectors_actions[] =
   { "vectors-import", GIMP_ICON_DOCUMENT_OPEN,
     NC_("vectors-action", "I_mport Path..."), "", NULL,
     vectors_import_cmd_callback,
-    GIMP_HELP_PATH_IMPORT }
+    GIMP_HELP_PATH_IMPORT },
+
+  { "vectors-to-vector-layer", NULL,
+    N_("Path to Vector Layer"), "", NULL,
+    vectors_to_vector_layer_cmd_callback,
+    NULL }
 };
 
 static const GimpToggleActionEntry vectors_toggle_actions[] =
@@ -427,6 +432,9 @@ vectors_actions_update (GimpActionGroup *group,
   SET_SENSITIVE ("vectors-export", n_selected_vectors == 1);
   SET_SENSITIVE ("vectors-import", image);
 
+  /* Wormnest: not sure if the condition here is correct (it was vectors) */
+  SET_SENSITIVE ("vectors-to-vector-layer", n_selected_vectors > 0);
+
   SET_SENSITIVE ("vectors-selection-to-vectors",          image && !mask_empty);
   SET_SENSITIVE ("vectors-selection-to-vectors-short",    image && !mask_empty);
   SET_SENSITIVE ("vectors-selection-to-vectors-advanced", image && !mask_empty);
diff --git a/app/actions/vectors-commands.c b/app/actions/vectors-commands.c
index 6dd7845afa..c80749cb27 100644
--- a/app/actions/vectors-commands.c
+++ b/app/actions/vectors-commands.c
@@ -47,6 +47,7 @@
 #include "vectors/gimpvectors.h"
 #include "vectors/gimpvectors-export.h"
 #include "vectors/gimpvectors-import.h"
+#include "vectors/gimpvectorlayer.h"
 
 #include "widgets/gimpaction.h"
 #include "widgets/gimpclipboard.h"
@@ -348,10 +349,32 @@ vectors_merge_visible_cmd_callback (GimpAction *action,
   gimp_image_flush (image);
 }
 
+void
+vectors_to_vector_layer_cmd_callback (GimpAction *action,
+                                      GVariant   *value,
+                                      gpointer   data)
+{
+  GimpImage       *image;
+  GimpVectors     *vectors;
+  GimpVectorLayer *layer;
+  return_if_no_vectors (image, vectors, data);
+
+  layer = gimp_vector_layer_new (image, 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);
+}
+
 void
 vectors_to_selection_cmd_callback (GimpAction *action,
                                    GVariant   *value,
-                                   gpointer    data)
+                                   gpointer   data)
 {
   GimpImage      *image;
   GimpVectors    *vectors;
diff --git a/app/actions/vectors-commands.h b/app/actions/vectors-commands.h
index 25383dd8e6..293cca1172 100644
--- a/app/actions/vectors-commands.h
+++ b/app/actions/vectors-commands.h
@@ -54,12 +54,21 @@ void   vectors_delete_cmd_callback               (GimpAction *action,
 void   vectors_merge_visible_cmd_callback        (GimpAction *action,
                                                   GVariant   *value,
                                                   gpointer    data);
+void   vectors_to_vector_layer_cmd_callback      (GimpAction *action,
+                                                  GVariant   *value,
+                                                  gpointer    data);
 void   vectors_to_selection_cmd_callback         (GimpAction *action,
                                                   GVariant   *value,
                                                   gpointer    data);
 void   vectors_selection_to_vectors_cmd_callback (GimpAction *action,
                                                   GVariant   *value,
                                                   gpointer    data);
+void   vectors_stroke_cmd_callback               (GimpAction *action,
+                                                  GVariant   *value,
+                                                  gpointer    data);
+void   vectors_stroke_last_vals_cmd_callback     (GimpAction *action,
+                                                  GVariant   *value,
+                                                  gpointer    data);
 
 void   vectors_fill_cmd_callback                 (GimpAction *action,
                                                   GVariant   *value,
diff --git a/app/dialogs/Makefile.am b/app/dialogs/Makefile.am
index 49abd913de..801ea44cac 100644
--- a/app/dialogs/Makefile.am
+++ b/app/dialogs/Makefile.am
@@ -97,6 +97,8 @@ libappdialogs_a_sources = \
        tips-parser.h                   \
        user-install-dialog.c           \
        user-install-dialog.h           \
+       vector-layer-options-dialog.c   \
+       vector-layer-options-dialog.h   \
        vectors-export-dialog.c         \
        vectors-export-dialog.h         \
        vectors-import-dialog.c         \
diff --git a/app/dialogs/meson.build b/app/dialogs/meson.build
index d934dadecf..65766d03e5 100644
--- a/app/dialogs/meson.build
+++ b/app/dialogs/meson.build
@@ -40,6 +40,8 @@ libappdialogs_sources = [
   'tips-dialog.c',
   'tips-parser.c',
   'user-install-dialog.c',
+  'vector-layer-options-dialog.c',
+  'vector-layer-options-dialog.h',
   'vectors-export-dialog.c',
   'vectors-import-dialog.c',
   'vectors-options-dialog.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..bf20ef71aa
--- /dev/null
+++ b/app/dialogs/vector-layer-options-dialog.c
@@ -0,0 +1,237 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * Copyright (C) 2006 Henk 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#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/gimpstrokeoptions.h"
+
+#include "widgets/gimpcolorpanel.h"
+#include "widgets/gimppropwidgets.h"
+#include "widgets/gimpviewabledialog.h"
+#include "widgets/gimpstrokeeditor.h"
+
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayeroptions.h"
+
+#include "vector-layer-options-dialog.h"
+
+#include "gimp-intl.h"
+
+
+#define RESPONSE_RESET 1
+
+
+/*  local functions  */
+
+static void  vector_layer_options_dialog_notify   (GObject          *options,
+                                                   const GParamSpec *pspec,
+                                                   GtkWidget        *dialog);
+static void  vector_layer_options_dialog_response (GtkWidget        *widget,
+                                                   gint              response_id,
+                                                   GtkWidget        *dialog);
+
+
+/*  public function  */
+
+GtkWidget *
+vector_layer_options_dialog_new (GimpVectorLayer *layer,
+                                 GimpContext     *context,
+                                 const gchar     *title,
+                                 const gchar     *stock_id,
+                                 const gchar     *help_id,
+                                 GtkWidget       *parent)
+{
+  GimpVectorLayerOptions *saved_options;
+  GimpFillOptions        *fill_options;
+  GimpStrokeOptions      *stroke_options;
+  GtkWidget              *dialog;
+  GtkWidget              *main_vbox;
+
+  g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
+  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (stock_id != NULL, NULL);
+  /* g_return_val_if_fail (help_id != NULL, NULL); */
+  g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
+
+  g_printerr ("--> vector_layer_options_dialog_new\n");
+
+  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, layer),
+                                     context,
+                                     title, "gimp-vectorlayer-options",
+                                     stock_id,
+                                     _("Choose vector layer options"),
+                                     parent,
+                                     gimp_standard_help_func,
+                                     help_id,
+
+                                     _("_Reset"),  RESPONSE_RESET,
+                                     _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                     stock_id,     GTK_RESPONSE_OK,
+
+                                     NULL);
+
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), RESPONSE_RESET);
+  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);
+  // Wormnest - next copied, check last 3 parameters!
+//  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+//                      main_vbox, TRUE, TRUE, 0);
+  //gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->box), main_vbox);
+  gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), main_vbox);
+  gtk_widget_show (main_vbox);
+
+  /* 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_show (frame);
+
+    fill_editor = gimp_fill_editor_new (fill_options, TRUE);
+    gtk_container_add (GTK_CONTAINER (frame), fill_editor);
+    gtk_widget_show (fill_editor);
+  }
+
+  /* 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_show (frame);
+
+    gimp_image_get_resolution (gimp_item_get_image (GIMP_ITEM (layer)),
+                               &xres, &yres);
+
+    stroke_editor = gimp_stroke_editor_new (stroke_options, yres, TRUE);
+    gtk_container_add (GTK_CONTAINER (frame), stroke_editor);
+    gtk_widget_show (stroke_editor);
+  }
+
+  return dialog;
+}
+
+static void
+vector_layer_options_dialog_notify (GObject          *options,
+                                    const GParamSpec *pspec,
+                                    GtkWidget        *dialog)
+{
+  GimpVectorLayer   *layer;
+  GimpFillOptions   *fill_options;
+  GimpStrokeOptions *stroke_options;
+
+  layer = g_object_get_data (G_OBJECT (dialog), "layer");
+
+  fill_options   = g_object_get_data (G_OBJECT (dialog), "fill-options");
+  stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
+
+  gimp_config_sync (G_OBJECT (fill_options),
+                    G_OBJECT (layer->options->fill_options), 0);
+  gimp_config_sync (G_OBJECT (stroke_options),
+                    G_OBJECT (layer->options->stroke_options), 0);
+
+  gimp_vector_layer_refresh (layer);
+  gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
+}
+
+static void
+vector_layer_options_dialog_response (GtkWidget *widget,
+                                      gint       response_id,
+                                      GtkWidget *dialog)
+{
+  //GimpVectorLayer        *layer;
+  GimpVectorLayerOptions *saved_options;
+  GimpFillOptions        *fill_options;
+  GimpStrokeOptions      *stroke_options;
+
+  //layer = g_object_get_data (G_OBJECT (dialog), "layer");
+
+  saved_options  = g_object_get_data (G_OBJECT (dialog), "saved-options");
+  fill_options   = g_object_get_data (G_OBJECT (dialog), "fill-options");
+  stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
+
+  switch (response_id)
+    {
+    case GTK_RESPONSE_OK:
+      gtk_widget_destroy (dialog);
+      break;
+
+    default:
+      gimp_config_sync (G_OBJECT (saved_options->fill_options),
+                        G_OBJECT (fill_options), 0);
+      gimp_config_sync (G_OBJECT (saved_options->stroke_options),
+                        G_OBJECT (stroke_options), 0);
+
+      if (response_id != RESPONSE_RESET)
+        gtk_widget_destroy (dialog);
+      break;
+    }
+}
diff --git a/app/dialogs/vector-layer-options-dialog.h b/app/dialogs/vector-layer-options-dialog.h
new file mode 100644
index 0000000000..28947838cb
--- /dev/null
+++ b/app/dialogs/vector-layer-options-dialog.h
@@ -0,0 +1,33 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * Copyright (C) 2006 Henk 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#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     *stock_id,
+                                             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..1e8e843467 100644
--- a/app/tools/gimpvectoroptions.c
+++ b/app/tools/gimpvectoroptions.c
@@ -89,20 +89,20 @@ gimp_vector_options_init (GimpVectorOptions *options)
 }
 
 static void
-gimp_vector_options_set_property (GObject      *object,
-                                  guint         property_id,
-                                  const GValue *value,
-                                  GParamSpec   *pspec)
+gimp_vector_options_get_property (GObject    *object,
+                                  guint       property_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
 {
   GimpVectorOptions *options = GIMP_VECTOR_OPTIONS (object);
 
   switch (property_id)
     {
     case PROP_VECTORS_EDIT_MODE:
-      options->edit_mode = g_value_get_enum (value);
+      g_value_set_enum (value, options->edit_mode);
       break;
     case PROP_VECTORS_POLYGONAL:
-      options->polygonal = g_value_get_boolean (value);
+      g_value_set_boolean (value, options->polygonal);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -110,22 +110,21 @@ gimp_vector_options_set_property (GObject      *object,
     }
 }
 
-
 static void
-gimp_vector_options_get_property (GObject    *object,
-                                  guint       property_id,
-                                  GValue     *value,
-                                  GParamSpec *pspec)
+gimp_vector_options_set_property (GObject      *object,
+                                  guint         property_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
 {
   GimpVectorOptions *options = GIMP_VECTOR_OPTIONS (object);
 
   switch (property_id)
     {
     case PROP_VECTORS_EDIT_MODE:
-      g_value_set_enum (value, options->edit_mode);
+      options->edit_mode = g_value_get_enum (value);
       break;
     case PROP_VECTORS_POLYGONAL:
-      g_value_set_boolean (value, options->polygonal);
+      options->polygonal = g_value_get_boolean (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -214,5 +213,13 @@ gimp_vector_options_gui (GimpToolOptions *tool_options)
 
   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 /* FIXME */);
+  gtk_widget_show (button);
+
+  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 baafd6e33d..f962df8db4 100644
--- a/app/tools/gimpvectortool.c
+++ b/app/tools/gimpvectortool.c
@@ -40,6 +40,7 @@
 
 #include "paint/gimppaintoptions.h" /* GIMP_PAINT_OPTIONS_CONTEXT_MASK */
 
+#include "vectors/gimpvectorlayer.h"
 #include "vectors/gimpvectors.h"
 
 #include "widgets/gimpdialogfactory.h"
@@ -147,6 +148,8 @@ 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)
 
@@ -558,6 +561,897 @@ gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool,
   if (vectors == vector_tool->vectors)
     return;
 
+#if 0
+  if (!vector_tool->modifier_lock)
+    {
+      if (state & TOGGLE_MASK)
+        {
+          vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;
+        }
+      else
+        {
+          vector_tool->restriction = GIMP_ANCHOR_FEATURE_NONE;
+        }
+    }
+
+  switch (vector_tool->function)
+    {
+    case VECTORS_MOVE_ANCHOR:
+    case VECTORS_MOVE_HANDLE:
+      anchor = vector_tool->cur_anchor;
+
+      if (anchor)
+        {
+          gimp_stroke_anchor_move_absolute (vector_tool->cur_stroke,
+                                            vector_tool->cur_anchor,
+                                            &position,
+                                            vector_tool->restriction);
+          vector_tool->undo_motion = TRUE;
+        }
+      break;
+
+    case VECTORS_MOVE_CURVE:
+      if (options->polygonal)
+        {
+          gimp_vector_tool_move_selected_anchors (vector_tool,
+                                                  coords->x - vector_tool->last_x,
+                                                  coords->y - vector_tool->last_y);
+          vector_tool->undo_motion = TRUE;
+        }
+      else
+        {
+          gimp_stroke_point_move_absolute (vector_tool->cur_stroke,
+                                           vector_tool->cur_anchor,
+                                           vector_tool->cur_position,
+                                           &position,
+                                           vector_tool->restriction);
+          vector_tool->undo_motion = TRUE;
+        }
+      break;
+
+    case VECTORS_MOVE_ANCHORSET:
+      gimp_vector_tool_move_selected_anchors (vector_tool,
+                                              coords->x - vector_tool->last_x,
+                                              coords->y - vector_tool->last_y);
+      vector_tool->undo_motion = TRUE;
+      break;
+
+    case VECTORS_MOVE_STROKE:
+      if (vector_tool->cur_stroke)
+        {
+          gimp_stroke_translate (vector_tool->cur_stroke,
+                                 coords->x - vector_tool->last_x,
+                                 coords->y - vector_tool->last_y);
+          vector_tool->undo_motion = TRUE;
+        }
+      else if (vector_tool->sel_stroke)
+        {
+          gimp_stroke_translate (vector_tool->sel_stroke,
+                                 coords->x - vector_tool->last_x,
+                                 coords->y - vector_tool->last_y);
+          vector_tool->undo_motion = TRUE;
+        }
+      break;
+
+    case VECTORS_MOVE_VECTORS:
+      gimp_item_translate (GIMP_ITEM (vector_tool->vectors),
+                           coords->x - vector_tool->last_x,
+                           coords->y - vector_tool->last_y, FALSE);
+      vector_tool->undo_motion = TRUE;
+      break;
+
+    default:
+      break;
+    }
+
+  vector_tool->last_x = coords->x;
+  vector_tool->last_y = coords->y;
+
+  gimp_vectors_thaw (vector_tool->vectors);
+
+  image = gimp_item_get_image (GIMP_ITEM (vector_tool->vectors));
+  gimp_image_flush (image);
+}
+
+static gboolean
+gimp_vector_tool_key_press (GimpTool     *tool,
+                            GdkEventKey  *kevent,
+                            GimpDisplay  *display)
+{
+  GimpVectorTool    *vector_tool = GIMP_VECTOR_TOOL (tool);
+  GimpDrawTool      *draw_tool   = GIMP_DRAW_TOOL (tool);
+  GimpVectorOptions *options     = GIMP_VECTOR_TOOL_GET_OPTIONS (tool);
+  GimpDisplayShell  *shell;
+  gdouble            xdist, ydist;
+  gdouble            pixels = 1.0;
+
+  if (! vector_tool->vectors)
+    return FALSE;
+
+  if (display != draw_tool->display)
+    return FALSE;
+
+  shell = GIMP_DISPLAY_SHELL (draw_tool->display->shell);
+
+  if (kevent->state & GDK_SHIFT_MASK)
+    pixels = 10.0;
+
+  if (kevent->state & GDK_CONTROL_MASK)
+    pixels = 50.0;
+
+  switch (kevent->keyval)
+    {
+    case GDK_Return:
+    case GDK_KP_Enter:
+    case GDK_ISO_Enter:
+      gimp_vector_tool_to_selection_extended (vector_tool, kevent->state);
+      break;
+
+    case GDK_BackSpace:
+    case GDK_Delete:
+      gimp_vector_tool_delete_selected_anchors (vector_tool);
+      break;
+
+    case GDK_Left:
+    case GDK_Right:
+    case GDK_Up:
+    case GDK_Down:
+      xdist = FUNSCALEX (shell, pixels);
+      ydist = FUNSCALEY (shell, pixels);
+
+      gimp_vector_tool_undo_push (vector_tool, _("Move Anchors"));
+
+      gimp_vectors_freeze (vector_tool->vectors);
+
+      switch (kevent->keyval)
+        {
+        case GDK_Left:
+          gimp_vector_tool_move_selected_anchors (vector_tool, -xdist, 0);
+          break;
+
+        case GDK_Right:
+          gimp_vector_tool_move_selected_anchors (vector_tool, xdist, 0);
+          break;
+
+        case GDK_Up:
+          gimp_vector_tool_move_selected_anchors (vector_tool, 0, -ydist);
+          break;
+
+        case GDK_Down:
+          gimp_vector_tool_move_selected_anchors (vector_tool, 0, ydist);
+          break;
+
+        default:
+          break;
+        }
+
+      gimp_vectors_thaw (vector_tool->vectors);
+      vector_tool->have_undo = FALSE;
+      break;
+
+    case GDK_Escape:
+      if (options->edit_mode != GIMP_VECTOR_MODE_DESIGN)
+        g_object_set (options, "vectors-edit-mode",
+                      GIMP_VECTOR_MODE_DESIGN, NULL);
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  gimp_image_flush (display->image);
+
+  return TRUE;
+}
+
+static void
+gimp_vector_tool_modifier_key (GimpTool        *tool,
+                               GdkModifierType  key,
+                               gboolean         press,
+                               GdkModifierType  state,
+                               GimpDisplay     *display)
+{
+  GimpVectorTool    *vector_tool = GIMP_VECTOR_TOOL (tool);
+  GimpVectorOptions *options     = GIMP_VECTOR_TOOL_GET_OPTIONS (tool);
+
+  if (key == TOGGLE_MASK)
+    return;
+
+  if (key == INSDEL_MASK || key == MOVE_MASK)
+    {
+      GimpVectorMode button_mode = options->edit_mode;
+
+      if (press)
+        {
+          if (key == (state & (INSDEL_MASK | MOVE_MASK)))
+            {
+              /*  first modifier pressed  */
+
+              vector_tool->saved_mode = options->edit_mode;
+            }
+        }
+      else
+        {
+          if (! (state & (INSDEL_MASK | MOVE_MASK)))
+            {
+              /*  last modifier released  */
+
+              button_mode = vector_tool->saved_mode;
+            }
+        }
+
+      if (state & MOVE_MASK)
+        {
+          button_mode = GIMP_VECTOR_MODE_MOVE;
+        }
+      else if (state & INSDEL_MASK)
+        {
+          button_mode = GIMP_VECTOR_MODE_EDIT;
+        }
+
+      if (button_mode != options->edit_mode)
+        {
+          g_object_set (options, "vectors-edit-mode", button_mode, NULL);
+        }
+    }
+}
+
+static void
+gimp_vector_tool_oper_update (GimpTool         *tool,
+                              const GimpCoords *coords,
+                              GdkModifierType   state,
+                              gboolean          proximity,
+                              GimpDisplay      *display)
+{
+  GimpVectorTool    *vector_tool = GIMP_VECTOR_TOOL (tool);
+  GimpDrawTool      *draw_tool   = GIMP_DRAW_TOOL (tool);
+  GimpVectorOptions *options     = GIMP_VECTOR_TOOL_GET_OPTIONS (tool);
+  GimpAnchor        *anchor      = NULL;
+  GimpAnchor        *anchor2     = NULL;
+  GimpStroke        *stroke      = NULL;
+  gdouble            position    = -1;
+  gboolean           on_handle   = FALSE;
+  gboolean           on_curve    = FALSE;
+  gboolean           on_vectors  = FALSE;
+
+  vector_tool->modifier_lock = FALSE;
+
+  /* are we hovering the current vectors on the current display? */
+  if (vector_tool->vectors && GIMP_DRAW_TOOL (tool)->display == display)
+    {
+      on_handle = gimp_draw_tool_on_vectors_handle (GIMP_DRAW_TOOL (tool),
+                                                    display,
+                                                    vector_tool->vectors,
+                                                    coords,
+                                                    TARGET, TARGET,
+                                                    GIMP_ANCHOR_ANCHOR,
+                                                    vector_tool->sel_count > 2,
+                                                    &anchor, &stroke);
+
+      if (! on_handle)
+        on_curve = gimp_draw_tool_on_vectors_curve (GIMP_DRAW_TOOL (tool),
+                                                    display,
+                                                    vector_tool->vectors,
+                                                    coords,
+                                                    TARGET, TARGET,
+                                                    NULL,
+                                                    &position, &anchor,
+                                                    &anchor2, &stroke);
+    }
+
+  if (on_handle || on_curve)
+    {
+      vector_tool->cur_vectors = NULL;
+    }
+  else
+    {
+      on_vectors = gimp_draw_tool_on_vectors (draw_tool, display, coords,
+                                              TARGET, TARGET,
+                                              NULL, NULL, NULL, NULL, NULL,
+                                              &(vector_tool->cur_vectors));
+    }
+
+  vector_tool->cur_position   = position;
+  vector_tool->cur_anchor     = anchor;
+  vector_tool->cur_anchor2    = anchor2;
+  vector_tool->cur_stroke     = stroke;
+
+  switch (options->edit_mode)
+    {
+    case GIMP_VECTOR_MODE_DESIGN:
+      if (! vector_tool->vectors || GIMP_DRAW_TOOL (tool)->display != display)
+        {
+          if (on_vectors)
+            {
+              vector_tool->function = VECTORS_SELECT_VECTOR;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_CREATE_VECTOR;
+              vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;
+              vector_tool->modifier_lock = TRUE;
+            }
+        }
+      else if (on_handle)
+        {
+          if (anchor->type == GIMP_ANCHOR_ANCHOR)
+            {
+              if (state & TOGGLE_MASK)
+                {
+                  vector_tool->function = VECTORS_MOVE_ANCHORSET;
+                }
+              else
+                {
+                  if (vector_tool->sel_count >= 2 && anchor->selected)
+                    vector_tool->function = VECTORS_MOVE_ANCHORSET;
+                  else
+                    vector_tool->function = VECTORS_MOVE_ANCHOR;
+                }
+            }
+          else
+            {
+              vector_tool->function = VECTORS_MOVE_HANDLE;
+
+              if (state & TOGGLE_MASK)
+                vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;
+              else
+                vector_tool->restriction = GIMP_ANCHOR_FEATURE_NONE;
+            }
+        }
+      else if (on_curve)
+        {
+          if (gimp_stroke_point_is_movable (stroke, anchor, position))
+            {
+              vector_tool->function = VECTORS_MOVE_CURVE;
+
+              if (state & TOGGLE_MASK)
+                vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;
+              else
+                vector_tool->restriction = GIMP_ANCHOR_FEATURE_NONE;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_FINISHED;
+            }
+        }
+      else
+        {
+          if (vector_tool->sel_stroke && vector_tool->sel_anchor &&
+              gimp_stroke_is_extendable (vector_tool->sel_stroke,
+                                         vector_tool->sel_anchor) &&
+              !(state & TOGGLE_MASK))
+            vector_tool->function = VECTORS_ADD_ANCHOR;
+          else
+            vector_tool->function = VECTORS_CREATE_STROKE;
+
+          vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;
+          vector_tool->modifier_lock = TRUE;
+        }
+
+      break;
+
+    case GIMP_VECTOR_MODE_EDIT:
+      if (! vector_tool->vectors || GIMP_DRAW_TOOL (tool)->display != display)
+        {
+          if (on_vectors)
+            {
+              vector_tool->function = VECTORS_SELECT_VECTOR;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_FINISHED;
+            }
+        }
+      else if (on_handle)
+        {
+          if (anchor->type == GIMP_ANCHOR_ANCHOR)
+            {
+              if (!(state & TOGGLE_MASK) && vector_tool->sel_anchor &&
+                  vector_tool->sel_anchor != anchor &&
+                  gimp_stroke_is_extendable (vector_tool->sel_stroke,
+                                             vector_tool->sel_anchor) &&
+                  gimp_stroke_is_extendable (stroke, anchor))
+                {
+                  vector_tool->function = VECTORS_CONNECT_STROKES;
+                }
+              else
+                {
+                  if (state & TOGGLE_MASK)
+                    {
+                      vector_tool->function = VECTORS_DELETE_ANCHOR;
+                    }
+                  else
+                    {
+                      if (options->polygonal)
+                        vector_tool->function = VECTORS_MOVE_ANCHOR;
+                      else
+                        vector_tool->function = VECTORS_MOVE_HANDLE;
+                    }
+                }
+            }
+          else
+            {
+              if (state & TOGGLE_MASK)
+                vector_tool->function = VECTORS_CONVERT_EDGE;
+              else
+                vector_tool->function = VECTORS_MOVE_HANDLE;
+            }
+        }
+      else if (on_curve)
+        {
+          if (state & TOGGLE_MASK)
+            {
+              vector_tool->function = VECTORS_DELETE_SEGMENT;
+            }
+          else if (gimp_stroke_anchor_is_insertable (stroke, anchor, position))
+            {
+              vector_tool->function = VECTORS_INSERT_ANCHOR;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_FINISHED;
+            }
+        }
+      else
+        {
+          vector_tool->function = VECTORS_FINISHED;
+        }
+
+      break;
+
+    case GIMP_VECTOR_MODE_MOVE:
+      if (! vector_tool->vectors || GIMP_DRAW_TOOL (tool)->display != display)
+        {
+          if (on_vectors)
+            {
+              vector_tool->function = VECTORS_SELECT_VECTOR;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_FINISHED;
+            }
+        }
+      else if (on_handle || on_curve)
+        {
+          if (state & TOGGLE_MASK)
+            {
+              vector_tool->function = VECTORS_MOVE_VECTORS;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_MOVE_STROKE;
+            }
+        }
+      else
+        {
+          if (on_vectors)
+            {
+              vector_tool->function = VECTORS_SELECT_VECTOR;
+            }
+          else
+            {
+              vector_tool->function = VECTORS_MOVE_VECTORS;
+            }
+        }
+      break;
+    }
+
+  gimp_vector_tool_status_update (tool, display, state, proximity);
+}
+
+
+static void
+gimp_vector_tool_status_update (GimpTool        *tool,
+                                GimpDisplay     *display,
+                                GdkModifierType  state,
+                                gboolean         proximity)
+{
+  GimpVectorTool    *vector_tool = GIMP_VECTOR_TOOL (tool);
+  GimpVectorOptions *options     = GIMP_VECTOR_TOOL_GET_OPTIONS (tool);
+
+  gimp_tool_pop_status (tool, display);
+
+  if (proximity)
+    {
+      const gchar *status      = NULL;
+      gboolean     free_status = FALSE;
+
+      switch (vector_tool->function)
+        {
+        case VECTORS_SELECT_VECTOR:
+          status = _("Click to pick path to edit");
+          break;
+
+        case VECTORS_CREATE_VECTOR:
+          status = _("Click to create a new path");
+          break;
+
+        case VECTORS_CREATE_STROKE:
+          status = _("Click to create a new component of the path");
+          break;
+
+        case VECTORS_ADD_ANCHOR:
+          status = gimp_suggest_modifiers (_("Click or Click-Drag to create "
+                                             "a new anchor"),
+                                           GDK_SHIFT_MASK & ~state,
+                                           NULL, NULL, NULL);
+          free_status = TRUE;
+          break;
+
+        case VECTORS_MOVE_ANCHOR:
+          if (options->edit_mode != GIMP_VECTOR_MODE_EDIT)
+            {
+              status = gimp_suggest_modifiers (_("Click-Drag to move the "
+                                                 "anchor around"),
+                                               GDK_CONTROL_MASK & ~state,
+                                               NULL, NULL, NULL);
+              free_status = TRUE;
+            }
+          else
+            status = _("Click-Drag to move the anchor around");
+          break;
+
+        case VECTORS_MOVE_ANCHORSET:
+          status = _("Click-Drag to move the anchors around");
+          break;
+
+        case VECTORS_MOVE_HANDLE:
+          status = gimp_suggest_modifiers (_("Click-Drag to move the handle "
+                                             "around"),
+                                           GDK_SHIFT_MASK & ~state,
+                                           NULL, NULL, NULL);
+          free_status = TRUE;
+          break;
+
+        case VECTORS_MOVE_CURVE:
+          if (GIMP_VECTOR_TOOL_GET_OPTIONS (tool)->polygonal)
+            status = gimp_suggest_modifiers (_("Click-Drag to move the "
+                                               "anchors around"),
+                                             GDK_SHIFT_MASK & ~state,
+                                             NULL, NULL, NULL);
+          else
+            status = gimp_suggest_modifiers (_("Click-Drag to change the "
+                                               "shape of the curve"),
+                                             GDK_SHIFT_MASK & ~state,
+                                             _("%s: symmetrical"), NULL, NULL);
+          free_status = TRUE;
+          break;
+
+        case VECTORS_MOVE_STROKE:
+          status = gimp_suggest_modifiers (_("Click-Drag to move the "
+                                             "component around"),
+                                           GDK_SHIFT_MASK & ~state,
+                                           NULL, NULL, NULL);
+          free_status = TRUE;
+          break;
+
+        case VECTORS_MOVE_VECTORS:
+          status = _("Click-Drag to move the path around");
+          break;
+
+        case VECTORS_INSERT_ANCHOR:
+          status = gimp_suggest_modifiers (_("Click-Drag to insert an anchor "
+                                             "on the path"),
+                                           GDK_SHIFT_MASK & ~state,
+                                           NULL, NULL, NULL);
+          free_status = TRUE;
+          break;
+
+        case VECTORS_DELETE_ANCHOR:
+          status = _("Click to delete this anchor");
+          break;
+
+        case VECTORS_CONNECT_STROKES:
+          status = _("Click to connect this anchor "
+                     "with the selected endpoint");
+          break;
+
+        case VECTORS_DELETE_SEGMENT:
+          status = _("Click to open up the path");
+          break;
+
+        case VECTORS_CONVERT_EDGE:
+          status = _("Click to make this node angular");
+          break;
+
+        case VECTORS_FINISHED:
+          status = NULL;
+          break;
+      }
+
+      if (status)
+        gimp_tool_push_status (tool, display, "%s", status);
+
+      if (free_status)
+        g_free ((gchar *) status);
+    }
+}
+
+static void
+gimp_vector_tool_cursor_update (GimpTool         *tool,
+                                const GimpCoords *coords,
+                                GdkModifierType   state,
+                                GimpDisplay      *display)
+{
+  GimpVectorTool     *vector_tool = GIMP_VECTOR_TOOL (tool);
+  GimpToolCursorType  tool_cursor = GIMP_TOOL_CURSOR_PATHS;
+  GimpCursorModifier  modifier    = GIMP_CURSOR_MODIFIER_NONE;
+
+  switch (vector_tool->function)
+    {
+    case VECTORS_SELECT_VECTOR:
+      tool_cursor = GIMP_TOOL_CURSOR_HAND;
+      break;
+
+    case VECTORS_CREATE_VECTOR:
+    case VECTORS_CREATE_STROKE:
+      modifier = GIMP_CURSOR_MODIFIER_CONTROL;
+      break;
+
+    case VECTORS_ADD_ANCHOR:
+    case VECTORS_INSERT_ANCHOR:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_ANCHOR;
+      modifier    = GIMP_CURSOR_MODIFIER_PLUS;
+      break;
+
+    case VECTORS_DELETE_ANCHOR:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_ANCHOR;
+      modifier    = GIMP_CURSOR_MODIFIER_MINUS;
+      break;
+
+    case VECTORS_DELETE_SEGMENT:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_SEGMENT;
+      modifier    = GIMP_CURSOR_MODIFIER_MINUS;
+      break;
+
+    case VECTORS_MOVE_HANDLE:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_CONTROL;
+      modifier    = GIMP_CURSOR_MODIFIER_MOVE;
+      break;
+
+    case VECTORS_CONVERT_EDGE:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_CONTROL;
+      modifier    = GIMP_CURSOR_MODIFIER_MINUS;
+      break;
+
+    case VECTORS_MOVE_ANCHOR:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_ANCHOR;
+      modifier    = GIMP_CURSOR_MODIFIER_MOVE;
+      break;
+
+    case VECTORS_MOVE_CURVE:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_SEGMENT;
+      modifier    = GIMP_CURSOR_MODIFIER_MOVE;
+      break;
+
+    case VECTORS_MOVE_STROKE:
+    case VECTORS_MOVE_VECTORS:
+      modifier = GIMP_CURSOR_MODIFIER_MOVE;
+      break;
+
+    case VECTORS_MOVE_ANCHORSET:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_ANCHOR;
+      modifier    = GIMP_CURSOR_MODIFIER_MOVE;
+      break;
+
+    case VECTORS_CONNECT_STROKES:
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS_SEGMENT;
+      modifier    = GIMP_CURSOR_MODIFIER_JOIN;
+      break;
+
+    default:
+      modifier = GIMP_CURSOR_MODIFIER_BAD;
+      break;
+    }
+
+  gimp_tool_control_set_tool_cursor     (tool->control, tool_cursor);
+  gimp_tool_control_set_cursor_modifier (tool->control, modifier);
+
+  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
+}
+
+static void
+gimp_vector_tool_draw (GimpDrawTool *draw_tool)
+{
+  GimpVectorTool  *vector_tool = GIMP_VECTOR_TOOL (draw_tool);
+  GimpAnchor      *cur_anchor  = NULL;
+  GimpStroke      *cur_stroke  = NULL;
+  GimpVectors     *vectors;
+  GArray          *coords;
+  gboolean         closed;
+  GList           *draw_anchors;
+  GList           *list;
+
+  vectors = vector_tool->vectors;
+
+  if (!vectors)
+    return;
+
+  while ((cur_stroke = gimp_vectors_stroke_get_next (vectors, cur_stroke)))
+    {
+      /* anchor handles */
+      draw_anchors = gimp_stroke_get_draw_anchors (cur_stroke);
+
+      for (list = draw_anchors; list; list = g_list_next (list))
+        {
+          cur_anchor = GIMP_ANCHOR (list->data);
+
+          if (cur_anchor->type == GIMP_ANCHOR_ANCHOR)
+            {
+              gimp_draw_tool_draw_handle (draw_tool,
+                                          cur_anchor->selected ?
+                                          GIMP_HANDLE_CIRCLE :
+                                          GIMP_HANDLE_FILLED_CIRCLE,
+                                          cur_anchor->position.x,
+                                          cur_anchor->position.y,
+                                          TARGET,
+                                          TARGET,
+                                          GTK_ANCHOR_CENTER,
+                                          FALSE);
+            }
+        }
+
+      g_list_free (draw_anchors);
+
+      if (vector_tool->sel_count <= 2)
+        {
+          /* control handles */
+          draw_anchors = gimp_stroke_get_draw_controls (cur_stroke);
+
+          for (list = draw_anchors; list; list = g_list_next (list))
+            {
+              cur_anchor = GIMP_ANCHOR (list->data);
+
+              gimp_draw_tool_draw_handle (draw_tool,
+                                          GIMP_HANDLE_SQUARE,
+                                          cur_anchor->position.x,
+                                          cur_anchor->position.y,
+                                          TARGET - 3,
+                                          TARGET - 3,
+                                          GTK_ANCHOR_CENTER,
+                                          FALSE);
+            }
+
+          g_list_free (draw_anchors);
+
+          /* the lines to the control handles */
+          coords = gimp_stroke_get_draw_lines (cur_stroke);
+
+          if (coords)
+            {
+              if (coords->len % 2 == 0)
+                {
+                  gint i;
+
+                  for (i = 0; i < coords->len; i += 2)
+                    {
+                      gimp_draw_tool_draw_dashed_line (draw_tool,
+                                    g_array_index (coords, GimpCoords, i).x,
+                                    g_array_index (coords, GimpCoords, i).y,
+                                    g_array_index (coords, GimpCoords, i + 1).x,
+                                    g_array_index (coords, GimpCoords, i + 1).y,
+                                    FALSE);
+                    }
+                }
+
+              g_array_free (coords, TRUE);
+            }
+        }
+
+      /* the stroke itself */
+      if (! gimp_item_get_visible (GIMP_ITEM (vectors)))
+        {
+          coords = gimp_stroke_interpolate (cur_stroke, 1.0, &closed);
+
+          if (coords)
+            {
+              if (coords->len)
+                gimp_draw_tool_draw_strokes (draw_tool,
+                                             &g_array_index (coords,
+                                                             GimpCoords, 0),
+                                             coords->len, FALSE, FALSE);
+
+              g_array_free (coords, TRUE);
+            }
+        }
+    }
+}
+
+static void
+gimp_vector_tool_vectors_changed (GimpImage      *image,
+                                  GimpVectorTool *vector_tool)
+{
+  gimp_vector_tool_set_vectors (vector_tool,
+                                gimp_image_get_active_vectors (image));
+}
+
+static void
+gimp_vector_tool_vectors_removed (GimpVectors    *vectors,
+                                  GimpVectorTool *vector_tool)
+{
+  gimp_vector_tool_set_vectors (vector_tool, NULL);
+}
+
+static void
+gimp_vector_tool_vectors_visible (GimpVectors    *vectors,
+                                  GimpVectorTool *vector_tool)
+{
+  GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (vector_tool);
+
+  if (gimp_draw_tool_is_active (draw_tool) && draw_tool->paused_count == 0)
+    {
+      GimpStroke *stroke = NULL;
+
+      while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
+        {
+          GArray   *coords;
+          gboolean  closed;
+
+          coords = gimp_stroke_interpolate (stroke, 1.0, &closed);
+
+          if (coords)
+            {
+              if (coords->len)
+                gimp_draw_tool_draw_strokes (draw_tool,
+                                             &g_array_index (coords,
+                                                             GimpCoords, 0),
+                                             coords->len, FALSE, FALSE);
+
+              g_array_free (coords, TRUE);
+            }
+        }
+    }
+}
+
+static void
+gimp_vector_tool_vectors_freeze (GimpVectors    *vectors,
+                                 GimpVectorTool *vector_tool)
+{
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (vector_tool));
+}
+
+static void
+gimp_vector_tool_vectors_thaw (GimpVectors    *vectors,
+                               GimpVectorTool *vector_tool)
+{
+  /* Ok, the vector might have changed externally (e.g. Undo)
+   * we need to validate our internal state. */
+  gimp_vector_tool_verify_state (vector_tool);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (vector_tool));
+}
+
+void
+gimp_vector_tool_set_vectors (GimpVectorTool *vector_tool,
+                              GimpVectors    *vectors)
+{
+  GimpDrawTool      *draw_tool;
+  GimpTool          *tool;
+  GimpItem          *item = NULL;
+  GimpVectorOptions *options;
+
+  g_return_if_fail (GIMP_IS_VECTOR_TOOL (vector_tool));
+  g_return_if_fail (vectors == NULL || GIMP_IS_VECTORS (vectors));
+
+  draw_tool = GIMP_DRAW_TOOL (vector_tool);
+  tool      = GIMP_TOOL (vector_tool);
+  options   = GIMP_VECTOR_TOOL_GET_OPTIONS (vector_tool);
+
+  if (vectors)
+    item = GIMP_ITEM (vectors);
+
+  if (vectors == vector_tool->vectors)
+    return;
+
+  gimp_draw_tool_pause (draw_tool);
+
+  if (gimp_draw_tool_is_active (draw_tool) &&
+      (! vectors || draw_tool->display->image != gimp_item_get_image (item)))
+    {
+      gimp_draw_tool_stop (draw_tool);
+    }
+#endif
+
   if (vector_tool->vectors)
     {
       GimpImage *old_image;
@@ -599,6 +1493,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 ||
@@ -647,6 +1549,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);
@@ -857,3 +1768,30 @@ gimp_vector_tool_stroke_callback (GtkWidget         *dialog,
 
   gtk_widget_destroy (dialog);
 }
+
+static void
+gimp_vector_tool_create_vector_layer (GimpVectorTool *vector_tool,
+                                      GtkWidget      *button)
+{
+  GimpImage       *image;
+  //GtkWidget       *dialog;
+  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/vectors/Makefile.am b/app/vectors/Makefile.am
index aa6e10d9e1..66cfd0e7c6 100644
--- a/app/vectors/Makefile.am
+++ b/app/vectors/Makefile.am
@@ -14,31 +14,39 @@ AM_CPPFLAGS = \
 noinst_LIBRARIES = libappvectors.a
 
 libappvectors_a_SOURCES = \
-       vectors-enums.h         \
-       vectors-types.h         \
-       gimpanchor.c            \
-       gimpanchor.h            \
-       gimpbezierstroke.h      \
-       gimpbezierstroke.c      \
-       gimpstroke.h            \
-       gimpstroke.c            \
-       gimpstroke-new.h        \
-       gimpstroke-new.c        \
-       gimpvectors.c           \
-       gimpvectors.h           \
-       gimpvectors-compat.c    \
-       gimpvectors-compat.h    \
-       gimpvectors-export.c    \
-       gimpvectors-export.h    \
-       gimpvectors-import.c    \
-       gimpvectors-import.h    \
-       gimpvectors-preview.c   \
-       gimpvectors-preview.h   \
-       gimpvectors-warp.c      \
-       gimpvectors-warp.h      \
-       gimpvectorsmodundo.c    \
-       gimpvectorsmodundo.h    \
-       gimpvectorspropundo.c   \
-       gimpvectorspropundo.h   \
-       gimpvectorsundo.c       \
+       vectors-enums.h                         \
+       vectors-types.h                         \
+       gimpanchor.c                            \
+       gimpanchor.h                            \
+       gimpbezierstroke.h                      \
+       gimpbezierstroke.c                      \
+       gimpstroke.h                            \
+       gimpstroke.c                            \
+       gimpstroke-new.h                        \
+       gimpstroke-new.c                        \
+       gimpvectorlayer.h                       \
+       gimpvectorlayer.c                       \
+       gimpvectorlayer-xcf.h                   \
+       gimpvectorlayer-xcf.c                   \
+       gimpvectorlayeroptions.h                \
+       gimpvectorlayeroptions.c                \
+       gimpvectorlayeroptions-parasite.h       \
+       gimpvectorlayeroptions-parasite.c       \
+       gimpvectors.c                           \
+       gimpvectors.h                           \
+       gimpvectors-compat.c                    \
+       gimpvectors-compat.h                    \
+       gimpvectors-export.c                    \
+       gimpvectors-export.h                    \
+       gimpvectors-import.c                    \
+       gimpvectors-import.h                    \
+       gimpvectors-preview.c                   \
+       gimpvectors-preview.h                   \
+       gimpvectors-warp.c                      \
+       gimpvectors-warp.h                      \
+       gimpvectorsmodundo.c                    \
+       gimpvectorsmodundo.h                    \
+       gimpvectorspropundo.c                   \
+       gimpvectorspropundo.h                   \
+       gimpvectorsundo.c                       \
        gimpvectorsundo.h
diff --git a/app/vectors/gimpvectorlayer-xcf.c b/app/vectors/gimpvectorlayer-xcf.c
new file mode 100644
index 0000000000..88d050c7fc
--- /dev/null
+++ b/app/vectors/gimpvectorlayer-xcf.c
@@ -0,0 +1,255 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayer-xcf
+ * Copyright (C) 2003  Sven Neumann <sven gimp org>
+ * Copyright (C) 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
+#include <gegl.h>
+
+#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"
+
+/* FIXME Maybe TextLayer and VectorLayers should have a common ancestor?
+ * There is a lot of duplicate code between the two - Wormnest.
+ */
+
+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),
+                    "vectors", gimp_image_get_vectors_by_tattoo (
+                                 gimp_item_get_image (GIMP_ITEM (*layer)),
+                                 options->vectors_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 vector 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 vector 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);
+      // Wormnest: changed to the way TextLayer does it, not sure of implications yet!
+      /*  Don't push an undo because the parasite only exists temporarily
+       *  while the text layer is saved to XCF.
+       */
+      gimp_item_parasite_attach (GIMP_ITEM (layer), parasite, FALSE);
+
+      gimp_parasite_free (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 if 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!
+ *
+ * Returns: a newly allocated #GimpVectorLayer object
+ **/
+static GimpLayer *
+gimp_vector_layer_from_layer (GimpLayer              *layer,
+                              GimpVectorLayerOptions *options)
+{
+  GimpVectorLayer *vector_layer;
+//  GimpItem        *item;
+  GimpDrawable    *drawable;
+//  gint             offset_x, offset_y;
+
+  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,
+//                               "vector-layer-options", options,
+//                               NULL);
+// Wormnest: text layer uses the below form instead, lets follow that for now:
+  vector_layer = g_object_new (GIMP_TYPE_VECTOR_LAYER,
+                               "image", gimp_item_get_image (GIMP_ITEM (layer)),
+                               NULL);
+
+  gimp_item_replace_item (GIMP_ITEM (vector_layer), GIMP_ITEM (layer));
+
+//  item     = GIMP_ITEM (vector_layer);
+  drawable = GIMP_DRAWABLE (vector_layer);
+  gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (layer));
+
+/* Wormnest: replacing this with what text layer does...
+  gimp_object_set_name (GIMP_OBJECT (vector_layer),
+                        gimp_object_get_name (GIMP_OBJECT (layer)));
+
+  //item->ID        = gimp_item_get_ID (GIMP_ITEM (layer));
+  //item->tattoo    = gimp_item_get_tattoo (GIMP_ITEM (layer));
+  gimp_item_set_tattoo (GIMP_ITEM (item),
+                        gimp_item_get_tattoo (GIMP_ITEM (layer)));
+  //  item->image     = gimp_item_get_image (GIMP_ITEM (layer));
+  gimp_item_set_image (GIMP_ITEM (item),
+                       gimp_item_get_image (GIMP_ITEM (layer)));
+
+  gimp_item_set_image (GIMP_ITEM (layer), NULL);
+
+  // Wormnest: is this still necessary or does GimpItem handle this internally?
+  g_hash_table_replace (item->image->gimp->item_table,
+                        GINT_TO_POINTER (item->ID),
+                        item);
+
+  //item->parasites = GIMP_ITEM (layer)->parasites;
+  //GIMP_ITEM (layer)->parasites = NULL;
+  gimp_item_set_parasites (GIMP_ITEM (item),
+                           gimp_item_get_parasites (GIMP_ITEM (layer)));
+  gimp_item_set_parasites (GIMP_ITEM (layer), NULL);
+
+  //item->width     = gimp_item_get_width (GIMP_ITEM (layer));
+  //item->height    = gimp_item_get_height (GIMP_ITEM (layer));
+  gimp_item_set_size (GIMP_ITEM (item),
+                      gimp_item_get_width (GIMP_ITEM (layer)),
+                      gimp_item_get_height (GIMP_ITEM (layer)));
+
+  gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
+  gimp_item_set_offset (GIMP_ITEM (item), offset_x, offset_y);
+
+  //item->visible   = gimp_item_get_visible (GIMP_ITEM (layer));
+  //item->linked    = gimp_item_get_linked (GIMP_ITEM (layer));
+  gimp_item_set_visible (GIMP_ITEM (item),
+                         gimp_item_get_visible (GIMP_ITEM (layer)),
+                         FALSE);
+  gimp_item_set_linked (GIMP_ITEM (item),
+                        gimp_item_get_linked (GIMP_ITEM (layer)),
+                         FALSE);
+
+  gimp_drawable_set_tiles (drawable,
+                           FALSE,
+                           NULL,
+                           gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
+                           gimp_drawable_type (GIMP_DRAWABLE (layer)));
+  gimp_drawable_set_tiles (GIMP_DRAWABLE (layer),
+                           FALSE,
+                           NULL,
+                           NULL,
+                           gimp_drawable_type (GIMP_DRAWABLE (layer)));
+
+  drawable->bytes     = gimp_drawable_bytes (GIMP_DRAWABLE (layer));
+  drawable->type      = gimp_drawable_type (GIMP_DRAWABLE (layer));
+  drawable->has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer));
+
+  GIMP_LAYER (vector_layer)->opacity    = gimp_layer_get_opacity (layer);
+  GIMP_LAYER (vector_layer)->mode       = gimp_layer_get_mode (layer);
+  GIMP_LAYER (vector_layer)->lock_alpha = gimp_layer_get_lock_alpha (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);
+
+  /* Wormnest: FIXME below add version for vector layer
+   * Needs get/set functions in gimpvectorlayer like for gimptextlayer */
+  //gimp_text_layer_set_text (text_layer, text);
+
+  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..2e10fc4b1b
--- /dev/null
+++ b/app/vectors/gimpvectorlayer-xcf.h
@@ -0,0 +1,34 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayer-xcf
+ * Copyright (C) 2003  Sven Neumann <sven gimp org>
+ * Copyright (C) 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#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..a576198bc7
--- /dev/null
+++ b/app/vectors/gimpvectorlayer.c
@@ -0,0 +1,442 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayer
+ * Copyright (C) 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
+#include <cairo.h>
+#include <gegl.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "vectors-types.h"
+
+// #include "base/tile-manager.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/gimpstrokeoptions.h"
+#include "core/gimpparasitelist.h"
+
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayeroptions.h"
+#include "gimpvectors.h"
+#include "vectors-types.h"
+
+#include "gimp-intl.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_VECTOR_LAYER_OPTIONS
+};
+
+
+/* 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 GimpItem * gimp_vector_layer_duplicate       (GimpItem        *item,
+                                                     GType            new_type);
+
+static gboolean   gimp_vector_layer_render          (GimpVectorLayer *layer);
+static void       gimp_vector_layer_render_vectors  (GimpVectorLayer *layer,
+                                                     GimpVectors     *vectors);
+static void       gimp_vector_layer_refresh_name    (GimpVectorLayer *layer);
+static void       gimp_vector_layer_changed_options (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);
+  GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
+  GimpItemClass     *item_class     = GIMP_ITEM_CLASS (klass);
+
+  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;
+
+  viewable_class->default_icon_name = "gimp-vector-layer";
+
+  item_class->duplicate             = gimp_vector_layer_duplicate;
+  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,
+                           GIMP_PARAM_STATIC_STRINGS);
+}
+
+static void
+gimp_vector_layer_init (GimpVectorLayer *layer)
+{
+  layer->options  = NULL;
+  layer->parasite = NULL;
+}
+
+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;
+
+    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);
+          g_object_unref (vector_layer->options);
+        }
+
+      vector_layer->options = g_value_dup_object (value);
+      gimp_vector_layer_changed_options (vector_layer);
+
+      if (vector_layer->options)
+        g_signal_connect_object (vector_layer->options, "notify",
+                                 G_CALLBACK  (gimp_vector_layer_changed_options),
+                                 vector_layer, G_CONNECT_SWAPPED);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+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);
+      GimpVectorLayerOptions *new_options;
+
+      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;
+}
+
+
+/*  public functions  */
+
+/**
+ * gimp_vector_layer_new:
+ * @image: the #GimpImage the layer should belong to
+ * @vectors: the #GimpVectors object the layer should render
+ * @context: the #GimpContext from which to pull context properties
+ *
+ * Creates a new vector layer.
+ *
+ * Returns: (nullable) a new #GimpVectorLayer or %NULL in case of a problem
+ **/
+GimpVectorLayer *
+gimp_vector_layer_new (GimpImage   *image,
+                       GimpVectors *vectors,
+                       GimpContext *context)
+{
+  GimpVectorLayer        *layer;
+  GimpVectorLayerOptions *options;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
+  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+  options = gimp_vector_layer_options_new (image, vectors, context);
+
+/* Wormnest: for now mostly following gimp_text_layer_new... */
+  layer =
+    GIMP_VECTOR_LAYER (gimp_drawable_new (GIMP_TYPE_VECTOR_LAYER,
+                                          image, NULL,
+                                          0, 0, 1, 1,
+                                          gimp_image_get_layer_format (image,
+                                                                       TRUE)));
+
+  gimp_layer_set_mode (GIMP_LAYER (layer),
+                       gimp_image_get_default_new_layer_mode (image),
+                       FALSE);
+
+  // FIXME: Add gimp_vector_layer_set_vector_options...
+/*
+  layer = g_object_new (GIMP_TYPE_VECTOR_LAYER,
+                        "vector-layer-options", options,
+                        NULL);
+*/
+  g_object_unref (options);
+/*
+  gimp_drawable_configure (GIMP_DRAWABLE (layer), image,
+                           0, 0, 1, 1,
+                           gimp_image_base_type_with_alpha (image),
+                           NULL);
+*/
+  return layer;
+}
+
+/**
+ * gimp_vector_layer_refresh:
+ * @layer: a #GimpVectorLayer
+ *
+ * Updates the display of the vector layer. Sets the layer name to the name
+ * of the vectors and re renders the vector layer.
+ */
+void
+gimp_vector_layer_refresh (GimpVectorLayer *layer)
+{
+  if (layer->options)
+    {
+      gimp_vector_layer_refresh_name (layer);
+      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;
+
+  /* TODO: undo step here */
+
+  g_object_set (layer, "vector-layer-options", NULL, NULL);
+}
+
+/**
+ * gimp_item_is_vector_layer:
+ * @item: a #GimpItem
+ *
+ * Discards the vector information. This makes @layer behave like a
+ * normal layer.
+ *
+ * Returns: whether the item is a vector layer or not.
+ */
+gboolean
+gimp_item_is_vector_layer (GimpItem *item)
+{
+  return (GIMP_IS_VECTOR_LAYER (item) &&
+          GIMP_VECTOR_LAYER (item)->options);
+// TODO: Text layer has:
+//  return gimp_item_id_is_text_layer (gimp_item_get_id (item));
+
+}
+
+
+/* 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);
+  //gint          width    = gimp_image_get_width (image);
+  //gint          height   = gimp_image_get_height (image);
+  //GimpRGB       blank;
+
+  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
+
+  g_object_freeze_notify (G_OBJECT (drawable));
+
+/* FIXME - Wormnest...
+  gimp_drawable_configure (GIMP_DRAWABLE (layer), image,
+                           0, 0, width, height,
+                           gimp_image_base_type_with_alpha (image),
+                           NULL);
+*/
+  /* make the layer background transparent */
+  //gimp_rgba_set (&blank, 1.0, 1.0, 1.0, 0.0);
+
+  // Wormnest: is user context here the right thing?
+  gimp_drawable_fill (GIMP_DRAWABLE (layer),
+                      gimp_get_user_context (image->gimp),
+                      GIMP_FILL_TRANSPARENT);
+
+  /* render vectors to the layer */
+  gimp_vector_layer_render_vectors (layer, layer->options->vectors);
+
+  g_object_thaw_notify (G_OBJECT (drawable));
+
+  return TRUE;
+}
+
+static void
+gimp_vector_layer_render_vectors (GimpVectorLayer *layer,
+                                  GimpVectors     *vectors)
+{
+  GimpImage   *image     = gimp_item_get_image (GIMP_ITEM (layer));
+  GimpChannel *selection = gimp_image_get_mask (image);
+  GList       *drawables = g_list_prepend (NULL, GIMP_DRAWABLE (layer));
+
+  /*  don't mask these fill/stroke operations  */
+  //gimp_selection_push_stroking (GIMP_SELECTION (selection));
+  // Wormnest I think the above is replaced by:
+  gimp_selection_suspend (GIMP_SELECTION (selection));
+
+  /* fill the vectors object onto the layer */
+  gimp_drawable_fill_vectors (GIMP_DRAWABLE (layer),
+                              layer->options->fill_options,
+                              vectors,
+                              FALSE,   /* undo */
+                              NULL);   /* error */
+
+  /* stroke the vectors object onto the layer */
+  gimp_item_stroke (GIMP_ITEM (vectors),
+                    drawables,
+                    gimp_get_user_context (image->gimp),
+                    layer->options->stroke_options,
+                    FALSE, FALSE,
+                    NULL, NULL);
+
+  g_list_free (drawables);
+
+  //gimp_selection_pop_stroking (GIMP_SELECTION (selection));
+  gimp_selection_resume (GIMP_SELECTION (selection));
+}
+
+/* sets the layer's name to be the same as the vector's name */
+static void
+gimp_vector_layer_refresh_name (GimpVectorLayer  *layer)
+{
+  gimp_object_set_name_safe (GIMP_OBJECT (layer),
+                             gimp_object_get_name (GIMP_OBJECT (layer->options->vectors)));
+}
+
+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->vectors)
+    {
+      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..4bcb5810aa
--- /dev/null
+++ b/app/vectors/gimpvectorlayer.h
@@ -0,0 +1,63 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayer
+ * Copyright (C) 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 2 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 <https://www.gnu.org/licenses/>.
+ */
+
+#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;
+};
+
+struct _GimpVectorLayerClass
+{
+  GimpLayerClass  parent_class;
+};
+
+
+GType             gimp_vector_layer_get_type    (void) G_GNUC_CONST;
+
+GimpVectorLayer * gimp_vector_layer_new         (GimpImage       *image,
+                                                 GimpVectors     *vectors,
+                                                 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..d42547f6fe
--- /dev/null
+++ b/app/vectors/gimpvectorlayeroptions-parasite.c
@@ -0,0 +1,95 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayerOptions-parasite
+ * Copyright (C) 2003  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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#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 (const 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, &parasite_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..d42f776e8c
--- /dev/null
+++ b/app/vectors/gimpvectorlayeroptions-parasite.h
@@ -0,0 +1,33 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayerOptions-parasite
+ * Copyright (C) 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#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   (const 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..b01e77e9e2
--- /dev/null
+++ b/app/vectors/gimpvectorlayeroptions.c
@@ -0,0 +1,367 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayerOptions
+ * Copyright (C) 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
+#include <cairo.h>
+#include <gegl.h>
+
+#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 "gimpvectors.h"
+#include "gimpvectorlayer.h"
+#include "gimpvectorlayeroptions.h"
+
+#include "gimp-intl.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_GIMP,
+  PROP_VECTORS,
+  PROP_VECTORS_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_vectors_changed
+                                                       (GimpVectorLayerOptions *options);
+static void     gimp_vector_layer_options_vectors_removed
+                                                       (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,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class, PROP_VECTORS,
+                                   g_param_spec_object ("vectors",
+                                                        NULL, NULL,
+                                                        GIMP_TYPE_VECTORS,
+                                                        G_PARAM_CONSTRUCT |
+                                                        GIMP_PARAM_READWRITE |
+                                                        GIMP_PARAM_STATIC_STRINGS));
+
+#if 0
+  g_object_class_install_property (object_class, PROP_VECTORS_TATTOO,
+                                   g_param_spec_uint ("vectors-tattoo",
+                                                      NULL, NULL,
+                                                      0, G_MAXUINT32, 0,
+                                                      GIMP_PARAM_READABLE |
+                                                      GIMP_CONFIG_PARAM_SERIALIZE |
+                                                      GIMP_PARAM_STATIC_STRINGS));
+#endif
+
+  GIMP_CONFIG_PROP_UINT   (object_class, PROP_VECTORS_TATTOO,
+                           "vectors-tattoo", NULL, NULL,
+                           0, G_MAXUINT32, 0,
+                           GIMP_PARAM_STATIC_STRINGS);
+
+  GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FILL_OPTIONS,
+                           "fill-options", NULL, NULL,
+                           GIMP_TYPE_FILL_OPTIONS,
+                           GIMP_PARAM_STATIC_STRINGS |
+                           GIMP_CONFIG_PARAM_AGGREGATE);
+
+  GIMP_CONFIG_PROP_OBJECT (object_class, PROP_STROKE_OPTIONS,
+                           "stroke-options", NULL, NULL,
+                           GIMP_TYPE_STROKE_OPTIONS,
+                           GIMP_PARAM_STATIC_STRINGS |
+                           GIMP_CONFIG_PARAM_AGGREGATE);
+}
+
+static void
+gimp_vector_layer_options_init (GimpVectorLayerOptions *options)
+{
+  options->vectors        = NULL;
+  options->vectors_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->vectors)
+    {
+      g_object_unref (options->vectors);
+      options->vectors = 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_VECTORS:
+      g_value_set_object (value, options->vectors);
+      break;
+    case PROP_VECTORS_TATTOO:
+      g_value_set_uint (value, options->vectors_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_VECTORS:
+      if (options->vectors)
+        {
+          g_signal_handlers_disconnect_by_func (options->vectors,
+                                                G_CALLBACK (gimp_vector_layer_options_vectors_changed),
+                                                options);
+          g_signal_handlers_disconnect_by_func (options->vectors,
+                                                G_CALLBACK (gimp_vector_layer_options_vectors_removed),
+                                                options);
+          g_object_unref (options->vectors);
+        }
+
+      options->vectors = g_value_dup_object (value);
+
+      if (options->vectors)
+        {
+          g_signal_connect_object (options->vectors, "invalidate-preview",
+                                   G_CALLBACK (gimp_vector_layer_options_vectors_changed),
+                                   options, G_CONNECT_SWAPPED);
+          g_signal_connect_object (options->vectors, "name-changed",
+                                   G_CALLBACK (gimp_vector_layer_options_vectors_changed),
+                                   options, G_CONNECT_SWAPPED);
+          g_signal_connect_object (options->vectors, "removed",
+                                   G_CALLBACK (gimp_vector_layer_options_vectors_removed),
+                                   options, G_CONNECT_SWAPPED);
+
+          /* update the tattoo */
+          options->vectors_tattoo = gimp_item_get_tattoo (GIMP_ITEM (options->vectors));
+        }
+      break;
+    case PROP_VECTORS_TATTOO:
+      options->vectors_tattoo = g_value_get_uint (value);
+
+      if (options->vectors &&
+          gimp_item_get_tattoo (GIMP_ITEM (options->vectors)) != options->vectors_tattoo)
+        {
+          GimpImage *image = gimp_item_get_image (GIMP_ITEM (options->vectors));
+
+          g_object_set (options,
+                        "vectors", gimp_image_get_vectors_by_tattoo
+                        (image, options->vectors_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_vectors_changed (GimpVectorLayerOptions *options)
+{
+  g_object_notify (G_OBJECT (options), "vectors");
+}
+
+static void
+gimp_vector_layer_options_vectors_removed (GimpVectorLayerOptions *options)
+{
+  g_object_set (options, "vectors", NULL, NULL);
+}
+
+
+/* public functions */
+
+/**
+ * gimp_vector_layer_options_new:
+ * @image: the #GimpImage the layer belongs to
+ * @vectors: the #GimpVectors 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,
+                               GimpVectors   *vectors,
+                               GimpContext   *context)
+{
+  GimpVectorLayerOptions *options;
+  GimpPattern            *pattern;
+  GimpRGB                 stroke_color;
+  GimpRGB                 fill_color;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
+  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+  options = g_object_new (GIMP_TYPE_VECTOR_LAYER_OPTIONS,
+                          "gimp", image->gimp,
+                          NULL);
+
+  gimp_context_get_foreground (context, &stroke_color);
+  gimp_context_get_background (context, &fill_color);
+  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,
+                "vectors", vectors,
+                NULL);
+
+  return options;
+}
diff --git a/app/vectors/gimpvectorlayeroptions.h b/app/vectors/gimpvectorlayeroptions.h
new file mode 100644
index 0000000000..e600fccdfb
--- /dev/null
+++ b/app/vectors/gimpvectorlayeroptions.h
@@ -0,0 +1,64 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * GimpVectorLayerOptions
+ * Copyright (C) 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#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         vectors_tattoo;
+  GimpVectors       *vectors;
+
+  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,
+                                                             GimpVectors  *vectors,
+                                                             GimpContext  *context);
+
+
+#endif /* __GIMP_VECTOR_LAYER_OPTIONS_H__ */
diff --git a/app/vectors/meson.build b/app/vectors/meson.build
index 356d88bffb..394a61827c 100644
--- a/app/vectors/meson.build
+++ b/app/vectors/meson.build
@@ -3,6 +3,10 @@ libappvectors_sources = [
   'gimpbezierstroke.c',
   'gimpstroke-new.c',
   'gimpstroke.c',
+  'gimpvectorlayer.c',
+  'gimpvectorlayer-xcf.c',
+  'gimpvectorlayeroptions.c',
+  'gimpvectorlayeroptions-parasite.c',
   'gimpvectors-compat.c',
   'gimpvectors-export.c',
   'gimpvectors-import.c',
diff --git a/app/vectors/vectors-types.h b/app/vectors/vectors-types.h
index 7c0d2d381a..9569a948cc 100644
--- a/app/vectors/vectors-types.h
+++ b/app/vectors/vectors-types.h
@@ -27,7 +27,16 @@
 #include "vectors/vectors-enums.h"
 
 
-typedef struct _GimpAnchor       GimpAnchor;
+typedef struct _GimpAnchor             GimpAnchor;
+typedef struct _GimpVectors            GimpVectors;
+typedef struct _GimpVectorsUndo        GimpVectorsUndo;
+typedef struct _GimpVectorsModUndo     GimpVectorsModUndo;
+typedef struct _GimpVectorsPropUndo    GimpVectorsPropUndo;
+typedef struct _GimpStroke             GimpStroke;
+typedef struct _GimpBezierStroke       GimpBezierStroke;
+
+typedef struct _GimpVectorLayer        GimpVectorLayer;
+typedef struct _GimpVectorLayerOptions GimpVectorLayerOptions;
 
 typedef struct _GimpVectors      GimpVectors;
 typedef struct _GimpStroke       GimpStroke;
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index 2a30ba9222..cf3acfb28a 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -69,6 +69,8 @@
 #include "vectors/gimpbezierstroke.h"
 #include "vectors/gimpvectors.h"
 #include "vectors/gimpvectors-compat.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayer-xcf.h"
 
 #include "xcf-private.h"
 #include "xcf-load.h"
@@ -2204,7 +2206,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 hacks 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);
@@ -2227,6 +2229,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 56b773788b..2fd6b3639f 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -64,6 +64,8 @@
 #include "vectors/gimpbezierstroke.h"
 #include "vectors/gimpvectors.h"
 #include "vectors/gimpvectors-compat.h"
+#include "vectors/gimpvectorlayer.h"
+#include "vectors/gimpvectorlayer-xcf.h"
 
 #include "xcf-private.h"
 #include "xcf-read.h"
@@ -599,6 +601,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.xml.in b/menus/image-menu.xml.in
index 785ef2d305..53cdfaac85 100644
--- a/menus/image-menu.xml.in
+++ b/menus/image-menu.xml.in
@@ -460,6 +460,10 @@
         <menuitem action="layers-text-to-vectors" />
         <menuitem action="layers-text-along-vectors" />
       </placeholder>
+      <placeholder name="Vector">
+        <menuitem action="layers-vector-fill-stroke" />
+        <menuitem action="layers-vector-discard" />
+      </placeholder>
       <separator />
       <menu action="layers-stack-menu" name="Stack">
         <placeholder name="Select">
diff --git a/menus/layers-menu.xml b/menus/layers-menu.xml
index 03ecfd564d..025d4290ca 100644
--- a/menus/layers-menu.xml
+++ b/menus/layers-menu.xml
@@ -4,6 +4,8 @@
 <ui>
   <popup action="layers-popup">
     <menuitem action="layers-edit-text" />
+    <menuitem action="layers-edit-vector" />
+
     <menuitem action="layers-edit-attributes" />
     <menu action="layers-blend-space-menu" name="Blend Space">
       <menuitem action="layers-blend-space-auto" />
@@ -53,6 +55,9 @@
     <menuitem action="layers-text-to-vectors" />
     <menuitem action="layers-text-along-vectors" />
     <separator />
+    <menuitem action="layers-vector-fill-stroke" />
+    <menuitem action="layers-vector-discard" />
+    <separator />
     <menuitem action="layers-resize" />
     <menuitem action="layers-resize-to-image" />
     <menuitem action="layers-scale" />
diff --git a/menus/vectors-menu.xml b/menus/vectors-menu.xml
index e947c8fa42..ba2dcc7303 100644
--- a/menus/vectors-menu.xml
+++ b/menus/vectors-menu.xml
@@ -24,6 +24,7 @@
     <menuitem action="vectors-delete" />
     <menuitem action="vectors-merge-visible" />
     <separator />
+    <menuitem action="vectors-to-vector-layer" />
     <menuitem action="vectors-selection-replace" />
     <menuitem action="vectors-selection-add" />
     <menuitem action="vectors-selection-subtract" />


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]