[gimp] Implement saving and loading of layer trees in the XCF
- From: Michael Natterer <mitch src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gimp] Implement saving and loading of layer trees in the XCF
- Date: Sun, 30 Aug 2009 19:34:47 +0000 (UTC)
commit c6fa4f7206daa28a374ba12820bb82755c87919e
Author: Michael Natterer <mitch gimp org>
Date: Sun Aug 30 21:28:59 2009 +0200
Implement saving and loading of layer trees in the XCF
* app/xcf/xcf-private.h: add properties PROP_GROUP_ITEM and
PROP_ITEM_PATH
* app/xcf/xcf-save.c: when saving a group layer, save a
PROP_GROUP_ITEM. When saving a child item, save a PROP_ITEM_PATH
which contains the path indices returned by gimp_item_get_path().
* app/xcf/xcf-load.c: when loading a PROP_GROUP_ITEM, replace the
layer that is being loaded by a GimpGroupLayer, also ignore that
layer's hierarchy (it makes no sense to load the tiles of a layer
that's generated from its children). When loading a PROP_ITEM_PATH,
pass the loaded path up to xcf_load_image() so it can add the loaded
layer at the right place in the tree.
app/xcf/xcf-load.c | 103 +++++++++++++++++++++++++++++++++++++++++--------
app/xcf/xcf-private.h | 4 +-
app/xcf/xcf-save.c | 35 +++++++++++++++++
3 files changed, 124 insertions(+), 18 deletions(-)
---
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index fcc0899..21ccf8f 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -37,12 +37,13 @@
#include "core/gimpcontainer.h"
#include "core/gimpdrawable-private.h" /* eek */
#include "core/gimpgrid.h"
+#include "core/gimpgrouplayer.h"
#include "core/gimpimage.h"
#include "core/gimpimage-colormap.h"
#include "core/gimpimage-grid.h"
#include "core/gimpimage-guides.h"
#include "core/gimpimage-sample-points.h"
-#include "core/gimplayer.h"
+#include "core/gimpitemstack.h"
#include "core/gimplayer-floating-sel.h"
#include "core/gimplayermask.h"
#include "core/gimpparasitelist.h"
@@ -75,6 +76,7 @@ static gboolean xcf_load_image_props (XcfInfo *info,
static gboolean xcf_load_layer_props (XcfInfo *info,
GimpImage *image,
GimpLayer **layer,
+ GList **item_path,
gboolean *apply_mask,
gboolean *edit_mask,
gboolean *show_mask,
@@ -86,7 +88,8 @@ static gboolean xcf_load_prop (XcfInfo *info,
PropType *prop_type,
guint32 *prop_size);
static GimpLayer * xcf_load_layer (XcfInfo *info,
- GimpImage *image);
+ GimpImage *image,
+ GList **item_path);
static GimpChannel * xcf_load_channel (XcfInfo *info,
GimpImage *image);
static GimpLayerMask * xcf_load_layer_mask (XcfInfo *info,
@@ -169,6 +172,7 @@ xcf_load_image (Gimp *gimp,
while (TRUE)
{
GimpLayer *layer;
+ GList *item_path = NULL;
/* read in the offset of the next layer */
info->cp += xcf_read_int32 (info->fp, &offset, 1);
@@ -189,7 +193,7 @@ xcf_load_image (Gimp *gimp,
goto error;
/* read in the layer */
- layer = xcf_load_layer (info, image);
+ layer = xcf_load_layer (info, image, &item_path);
if (!layer)
goto error;
@@ -199,10 +203,31 @@ xcf_load_image (Gimp *gimp,
/* add the layer to the image if its not the floating selection */
if (layer != info->floating_sel)
- gimp_image_add_layer (image, layer,
- NULL, /* FIXME tree */
- gimp_container_get_n_children (image->layers),
- FALSE);
+ {
+ GimpContainer *layers = gimp_image_get_layers (image);
+ GimpContainer *container;
+ GimpLayer *parent;
+
+ if (item_path)
+ {
+ parent = GIMP_LAYER
+ (gimp_item_stack_get_parent_by_path (GIMP_ITEM_STACK (layers),
+ item_path,
+ NULL));
+
+ container = gimp_viewable_get_children (GIMP_VIEWABLE (parent));
+ }
+ else
+ {
+ parent = NULL;
+ container = layers;
+ }
+
+ gimp_image_add_layer (image, layer,
+ parent,
+ gimp_container_get_n_children (container),
+ FALSE);
+ }
/* restore the saved position so we'll be ready to
* read the next offset.
@@ -614,6 +639,7 @@ static gboolean
xcf_load_layer_props (XcfInfo *info,
GimpImage *image,
GimpLayer **layer,
+ GList **item_path,
gboolean *apply_mask,
gboolean *edit_mask,
gboolean *show_mask,
@@ -758,6 +784,42 @@ xcf_load_layer_props (XcfInfo *info,
info->cp += xcf_read_int32 (info->fp, text_layer_flags, 1);
break;
+ case PROP_GROUP_ITEM:
+ {
+ GimpLayer *group;
+
+ group = gimp_group_layer_new (image);
+
+ gimp_object_set_name (GIMP_OBJECT (group),
+ gimp_object_get_name (*layer));
+
+ GIMP_DRAWABLE (group)->type =
+ gimp_drawable_type (GIMP_DRAWABLE (*layer));
+
+ g_object_ref_sink (*layer);
+ g_object_unref (*layer);
+ *layer = group;
+ }
+ break;
+
+ case PROP_ITEM_PATH:
+ {
+ glong base = info->cp;
+ GList *path = NULL;
+
+ while (info->cp - base < prop_size)
+ {
+ guint32 index;
+
+ info->cp += xcf_read_int32 (info->fp, &index, 1);
+
+ path = g_list_append (path, GUINT_TO_POINTER (index));
+ }
+
+ *item_path = path;
+ }
+ break;
+
default:
#ifdef GIMP_UNSTABLE
g_printerr ("unexpected/unknown layer property: %d (skipping)\n",
@@ -961,8 +1023,9 @@ xcf_load_prop (XcfInfo *info,
}
static GimpLayer *
-xcf_load_layer (XcfInfo *info,
- GimpImage *image)
+xcf_load_layer (XcfInfo *info,
+ GimpImage *image,
+ GList **item_path)
{
GimpLayer *layer;
GimpLayerMask *layer_mask;
@@ -999,7 +1062,7 @@ xcf_load_layer (XcfInfo *info,
return NULL;
/* read in the layer properties */
- if (! xcf_load_layer_props (info, image, &layer,
+ if (! xcf_load_layer_props (info, image, &layer, item_path,
&apply_mask, &edit_mask, &show_mask,
&text_layer_flags))
goto error;
@@ -1025,15 +1088,21 @@ xcf_load_layer (XcfInfo *info,
info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1);
info->cp += xcf_read_int32 (info->fp, &layer_mask_offset, 1);
- /* read in the hierarchy */
- if (! xcf_seek_pos (info, hierarchy_offset, NULL))
- goto error;
+ /* read in the hierarchy (ignore it for group layers, both as an
+ * optimization and because the hierarchy's extents don't match
+ * the group layer's tiles)
+ */
+ if (! gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
+ {
+ if (! xcf_seek_pos (info, hierarchy_offset, NULL))
+ goto error;
- if (! xcf_load_hierarchy (info,
- gimp_drawable_get_tiles (GIMP_DRAWABLE (layer))))
- goto error;
+ if (! xcf_load_hierarchy (info,
+ gimp_drawable_get_tiles (GIMP_DRAWABLE (layer))))
+ goto error;
- xcf_progress_update (info);
+ xcf_progress_update (info);
+ }
/* read in the layer mask */
if (layer_mask_offset != 0)
diff --git a/app/xcf/xcf-private.h b/app/xcf/xcf-private.h
index 8fa9161..b539d31 100644
--- a/app/xcf/xcf-private.h
+++ b/app/xcf/xcf-private.h
@@ -49,7 +49,9 @@ typedef enum
PROP_VECTORS = 25,
PROP_TEXT_LAYER_FLAGS = 26,
PROP_SAMPLE_POINTS = 27,
- PROP_LOCK_CONTENT = 28
+ PROP_LOCK_CONTENT = 28,
+ PROP_GROUP_ITEM = 29,
+ PROP_ITEM_PATH = 30
} PropType;
typedef enum
diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c
index 79eb39c..88031b8 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -453,6 +453,19 @@ xcf_save_layer_props (XcfInfo *info,
gint offset_x;
gint offset_y;
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
+ xcf_check_error (xcf_save_prop (info, image, PROP_GROUP_ITEM, error));
+
+ if (gimp_viewable_get_parent (GIMP_VIEWABLE (layer)))
+ {
+ GList *path;
+
+ path = gimp_item_get_path (GIMP_ITEM (layer));
+ xcf_check_error (xcf_save_prop (info, image, PROP_ITEM_PATH, error,
+ path));
+ g_list_free (path);
+ }
+
if (layer == gimp_image_get_active_layer (image))
xcf_check_error (xcf_save_prop (info, image, PROP_ACTIVE_LAYER, error));
@@ -617,6 +630,7 @@ xcf_save_prop (XcfInfo *info,
case PROP_ACTIVE_LAYER:
case PROP_ACTIVE_CHANNEL:
case PROP_SELECTION:
+ case PROP_GROUP_ITEM:
size = 0;
xcf_write_prop_type_check_error (info, prop_type);
@@ -1071,6 +1085,27 @@ xcf_save_prop (XcfInfo *info,
xcf_write_int32_check_error (info, &flags, 1);
}
break;
+
+ case PROP_ITEM_PATH:
+ {
+ GList *path;
+
+ path = va_arg (args, GList *);
+ size = 4 * g_list_length (path);
+
+ xcf_write_prop_type_check_error (info, prop_type);
+ xcf_write_int32_check_error (info, &size, 1);
+
+ while (path)
+ {
+ guint32 index = GPOINTER_TO_UINT (path->data);
+
+ xcf_write_int32_check_error (info, &index, 1);
+
+ path = g_list_next (path);
+ }
+ }
+ break;
}
va_end (args);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]