app: add saving/loading of link layers.

This commit is contained in:
Jehan 2019-07-08 16:48:56 +02:00
parent 20083bcabe
commit 6e91826865
6 changed files with 168 additions and 2 deletions

View file

@ -71,6 +71,7 @@
#include "gimplayer-floating-selection.h"
#include "gimplayermask.h"
#include "gimplayerstack.h"
#include "gimplinklayer.h"
#include "gimpmarshal.h"
#include "gimppalette.h"
#include "gimpparasitelist.h"
@ -3024,6 +3025,14 @@ gimp_image_get_xcf_version (GimpImage *image,
"GIMP 3.2"));
version = MAX (24, version);
}
/* Need version 25 for link layers. */
if (GIMP_IS_LINK_LAYER (layer))
{
ADD_REASON (g_strdup_printf (_("Link layers were added in %s"),
"GIMP 3.2"));
version = MAX (25, version);
}
}
g_list_free (items);
@ -3204,6 +3213,7 @@ gimp_image_get_xcf_version (GimpImage *image,
if (version_string) *version_string = "GIMP 3.0";
break;
case 24:
case 25:
if (gimp_version) *gimp_version = 320;
if (version_string) *version_string = "GIMP 3.2";
break;

View file

@ -49,6 +49,13 @@
#include "gimp-intl.h"
enum
{
LINK_LAYER_XCF_NONE = 0,
LINK_LAYER_XCF_DONT_AUTO_RENAME = 1 << 0,
LINK_LAYER_XCF_MODIFIED = 1 << 1
};
enum
{
PROP_0,
@ -112,6 +119,8 @@ static gboolean gimp_link_layer_render (GimpLinkLayer *layer);
static void gimp_link_layer_render_buffer (GimpLinkLayer *layer,
GeglBuffer *buffer);
static void gimp_link_layer_set_xcf_flags (GimpLinkLayer *layer,
guint32 flags);
G_DEFINE_TYPE_WITH_PRIVATE (GimpLinkLayer, gimp_link_layer, GIMP_TYPE_LAYER)
@ -523,6 +532,80 @@ gimp_item_is_link_layer (GimpItem *item)
! GIMP_LINK_LAYER (item)->p->modified);
}
guint32
gimp_link_layer_get_xcf_flags (GimpLinkLayer *link_layer)
{
guint flags = 0;
g_return_val_if_fail (GIMP_IS_LINK_LAYER (link_layer), 0);
if (! link_layer->p->auto_rename)
flags |= LINK_LAYER_XCF_DONT_AUTO_RENAME;
if (link_layer->p->modified)
flags |= LINK_LAYER_XCF_MODIFIED;
return flags;
}
/**
* gimp_link_layer_from_layer:
* @layer: a #GimpLayer object
* @link: a #GimpLink object
* @flags: flags as retrieved from the XCF file.
*
* Converts a standard #GimpLayer into a #GimpLinkLayer.
* The new link layer takes ownership of the @link.
* The old @layer object is freed and replaced in-place by the new
* #GimpLinkLayer.
*
* This is a hack similar to the one used to load text layers from XCF,
* since at first they are loaded as normal layers, and only later
* promoted to link layers when the corresponding property is read from
* the file.
**/
void
gimp_link_layer_from_layer (GimpLayer **layer,
GimpLink *link,
guint32 flags)
{
GimpLinkLayer *link_layer;
GimpDrawable *drawable;
g_return_if_fail (GIMP_IS_LAYER (*layer));
g_return_if_fail (GIMP_IS_LINK (link));
link_layer = g_object_new (GIMP_TYPE_LINK_LAYER,
"image", gimp_item_get_image (GIMP_ITEM (*layer)),
NULL);
gimp_item_replace_item (GIMP_ITEM (link_layer), GIMP_ITEM (*layer));
drawable = GIMP_DRAWABLE (link_layer);
gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (*layer));
gimp_layer_set_opacity (GIMP_LAYER (link_layer),
gimp_layer_get_opacity (*layer), FALSE);
gimp_layer_set_mode (GIMP_LAYER (link_layer),
gimp_layer_get_mode (*layer), FALSE);
gimp_layer_set_blend_space (GIMP_LAYER (link_layer),
gimp_layer_get_blend_space (*layer), FALSE);
gimp_layer_set_composite_space (GIMP_LAYER (link_layer),
gimp_layer_get_composite_space (*layer), FALSE);
gimp_layer_set_composite_mode (GIMP_LAYER (link_layer),
gimp_layer_get_composite_mode (*layer), FALSE);
gimp_layer_set_lock_alpha (GIMP_LAYER (link_layer),
gimp_layer_get_lock_alpha (*layer), FALSE);
gimp_link_layer_set_link (link_layer, link, FALSE);
gimp_link_layer_set_xcf_flags (link_layer, flags);
g_object_unref (link);
g_object_unref (*layer);
*layer = GIMP_LAYER (link_layer);
}
/* private functions */
static void
@ -649,3 +732,15 @@ gimp_link_layer_render_buffer (GimpLinkLayer *layer,
gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE,
gimp_drawable_get_buffer (drawable), NULL);
}
static void
gimp_link_layer_set_xcf_flags (GimpLinkLayer *layer,
guint32 flags)
{
g_return_if_fail (GIMP_IS_LINK_LAYER (layer));
g_object_set (layer,
"auto-rename", (flags & LINK_LAYER_XCF_DONT_AUTO_RENAME) == 0,
"modified", (flags & LINK_LAYER_XCF_MODIFIED) != 0,
NULL);
}

View file

@ -63,4 +63,12 @@ void gimp_link_layer_discard (GimpLinkLayer *layer);
void gimp_link_layer_monitor (GimpLinkLayer *layer);
gboolean gimp_item_is_link_layer (GimpItem *item);
/* Only to be used for XCF loading/saving. */
guint32 gimp_link_layer_get_xcf_flags (GimpLinkLayer *layer);
void gimp_link_layer_from_layer (GimpLayer **layer,
GimpLink *link,
guint32 flags);
#endif /* __GIMP_LINK_LAYER_H__ */

View file

@ -63,6 +63,8 @@
#include "core/gimplayer-new.h"
#include "core/gimplayer-xcf.h"
#include "core/gimplayermask.h"
#include "core/gimplink.h"
#include "core/gimplinklayer.h"
#include "core/gimpparasitelist.h"
#include "core/gimppattern.h"
#include "core/gimpprogress.h"
@ -163,7 +165,8 @@ static gboolean xcf_load_layer_props (XcfInfo *info,
static gboolean xcf_check_layer_props (XcfInfo *info,
GList **item_path,
gboolean *is_group_layer,
gboolean *is_text_layer);
gboolean *is_text_layer,
gboolean *is_link_layer);
static gboolean xcf_load_channel_props (XcfInfo *info,
GimpImage *image,
GimpChannel **channel,
@ -2172,6 +2175,29 @@ xcf_load_layer_props (XcfInfo *info,
"gimp-vector-layer-data", data,
(GDestroyNotify) xcf_load_free_vector_data);
}
case PROP_LINK_LAYER_DATA:
{
GimpLink *link;
gchar *path;
guint32 flags;
gboolean is_selected_layer;
xcf_read_int32 (info, &flags, 1);
xcf_read_string (info, &path, 1);
link = gimp_link_new (info->gimp, g_file_new_for_path (path));
g_free (path);
is_selected_layer = (g_list_find (info->selected_layers, *layer ) != NULL);
if (is_selected_layer)
info->selected_layers = g_list_remove (info->selected_layers, *layer);
gimp_link_layer_from_layer (layer, link, flags);
if (is_selected_layer)
info->selected_layers = g_list_prepend (info->selected_layers, *layer);
}
break;
case PROP_GROUP_ITEM:

View file

@ -72,7 +72,8 @@ typedef enum
PROP_FILTER_REGION = 44,
PROP_FILTER_ARGUMENT = 45,
PROP_FILTER_CLIP = 46,
PROP_VECTOR_LAYER = 47
PROP_VECTOR_LAYER = 47,
PROP_LINK_LAYER_DATA = 48,
} PropType;
typedef enum

View file

@ -57,6 +57,8 @@
#include "core/gimpitemlist.h"
#include "core/gimplayer.h"
#include "core/gimplayermask.h"
#include "core/gimplink.h"
#include "core/gimplinklayer.h"
#include "core/gimplist.h"
#include "core/gimpparasitelist.h"
#include "core/gimpprogress.h"
@ -740,6 +742,9 @@ xcf_save_layer_props (XcfInfo *info,
xcf_check_error (xcf_save_prop (info, image, PROP_VECTOR_LAYER, error, layer), ;);
}
if (GIMP_IS_LINK_LAYER (layer))
xcf_check_error (xcf_save_prop (info, image, PROP_LINK_LAYER_DATA, error, layer));
if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
{
gint32 flags = 0;
@ -1722,6 +1727,27 @@ xcf_save_prop (XcfInfo *info,
xcf_write_int32_check_error (info, &size, 1, va_end (args));
xcf_check_error (xcf_seek_pos (info, base + size, error), va_end (args));
}
break;
case PROP_LINK_LAYER_DATA:
{
GimpLinkLayer *layer = va_arg (args, GimpLinkLayer *);
GFile *file;
const gchar *path;
guint32 flags;
flags = gimp_link_layer_get_xcf_flags (layer);
file = gimp_link_get_file (gimp_link_layer_get_link (layer));
path = g_file_peek_path (file);
size = 4 + strlen (path) ? strlen (path) + 5 : 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &flags, 1);
xcf_write_string_check_error (info, (gchar **) &path, 1);
}
break;
case PROP_ITEM_PATH: