diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c index 160f8c4e37..d9e4b254e0 100644 --- a/app/xcf/xcf-save.c +++ b/app/xcf/xcf-save.c @@ -556,6 +556,9 @@ xcf_save_image_props (XcfInfo *info, { GimpGrid *grid = gimp_image_get_grid (image); + /* Set the XCF version so that the grid colors are written as GimpRGB + * values when saving in legacy (2.10 and below) XCF formats */ + gimp_config_set_xcf_version (GIMP_CONFIG (grid), info->file_version); grid_parasite = gimp_grid_to_parasite (grid); gimp_parasite_list_add (private->parasites, grid_parasite); } diff --git a/libgimpconfig/gimpconfig-iface.c b/libgimpconfig/gimpconfig-iface.c index 131693e487..84907c7c47 100644 --- a/libgimpconfig/gimpconfig-iface.c +++ b/libgimpconfig/gimpconfig-iface.c @@ -40,6 +40,16 @@ #include "libgimp/libgimp-intl.h" +typedef struct _GimpConfigInterfacePrivate GimpConfigInterfacePrivate; + +struct _GimpConfigInterfacePrivate +{ + guint xcf_version; +}; + +#define GIMP_CONFIG_INTERFACE_GET_PRIVATE(obj) (gimp_config_iface_get_private ((GimpConfigInterface *) (obj))) + + /* * GimpConfigIface: * @@ -49,23 +59,26 @@ /* local function prototypes */ -static void gimp_config_iface_default_init (GimpConfigInterface *iface); -static void gimp_config_iface_base_init (GimpConfigInterface *iface); +static GimpConfigInterfacePrivate * gimp_config_iface_get_private (GimpConfigInterface *iface); +static void gimp_config_iface_private_finalize (GimpConfigInterfacePrivate *private); -static gboolean gimp_config_iface_serialize (GimpConfig *config, - GimpConfigWriter *writer, - gpointer data); -static gboolean gimp_config_iface_deserialize (GimpConfig *config, - GScanner *scanner, - gint nest_level, - gpointer data); -static GimpConfig * gimp_config_iface_duplicate (GimpConfig *config); -static gboolean gimp_config_iface_equal (GimpConfig *a, - GimpConfig *b); -static void gimp_config_iface_reset (GimpConfig *config); -static gboolean gimp_config_iface_copy (GimpConfig *src, - GimpConfig *dest, - GParamFlags flags); +static void gimp_config_iface_default_init (GimpConfigInterface *iface); +static void gimp_config_iface_base_init (GimpConfigInterface *iface); + +static gboolean gimp_config_iface_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data); +static gboolean gimp_config_iface_deserialize (GimpConfig *config, + GScanner *scanner, + gint nest_level, + gpointer data); +static GimpConfig * gimp_config_iface_duplicate (GimpConfig *config); +static gboolean gimp_config_iface_equal (GimpConfig *a, + GimpConfig *b); +static void gimp_config_iface_reset (GimpConfig *config); +static gboolean gimp_config_iface_copy (GimpConfig *src, + GimpConfig *dest, + GParamFlags flags); /* private functions */ @@ -266,6 +279,37 @@ gimp_config_iface_copy (GimpConfig *src, return gimp_config_sync (G_OBJECT (src), G_OBJECT (dest), flags); } +static GimpConfigInterfacePrivate * +gimp_config_iface_get_private (GimpConfigInterface *iface) +{ + GimpConfigInterfacePrivate *private; + + static GQuark private_key = 0; + + if (! private_key) + private_key = g_quark_from_static_string ("gimp-config-iface-private"); + + private = g_object_get_qdata ((GObject *) iface, private_key); + + if (! private) + { + private = g_slice_new0 (GimpConfigInterfacePrivate); + + private->xcf_version = G_MAXUINT32; + + g_object_set_qdata_full ((GObject *) iface, private_key, private, + (GDestroyNotify) gimp_config_iface_private_finalize); + } + + return private; +} + +static void +gimp_config_iface_private_finalize (GimpConfigInterfacePrivate *private) +{ + g_slice_free (GimpConfigInterfacePrivate, private); +} + /* public functions */ @@ -402,7 +446,7 @@ gimp_config_serialize_to_string (GimpConfig *config, g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL); - str = g_string_new (NULL); + str = g_string_new (NULL); writer = gimp_config_writer_new_from_string (str); GIMP_CONFIG_GET_IFACE (config)->serialize (config, writer, data); @@ -837,3 +881,49 @@ gimp_config_copy (GimpConfig *src, return changed; } + +/** + * gimp_config_get_xcf_version: + * @config: a #GObject that implements the #GimpConfigInterface. + * + * Returns the current XCF version of the @config. + * + * Returns: the XCF version associated with the @config. + * + * Since: 3.2 + **/ +guint +gimp_config_get_xcf_version (GimpConfig *config) +{ + GimpConfigInterfacePrivate *private; + + g_return_val_if_fail (GIMP_IS_CONFIG (config), G_MAXUINT32); + + private = GIMP_CONFIG_INTERFACE_GET_PRIVATE (config); + + return private->xcf_version; +} + +/** + * gimp_config_set_xcf_version: + * @config: a #GObject that implements the #GimpConfigInterface. + * @xcf_version: a mask of GParamFlags + * + * Sets the current XCF version of the @config. This information can be used + * to adjust how properties are serialized depending on the version of the XCF + * that it is being saved to. + * + * Since: 3.2 + **/ +void +gimp_config_set_xcf_version (GimpConfig *config, + guint xcf_version) +{ + GimpConfigInterfacePrivate *private; + + g_return_if_fail (GIMP_IS_CONFIG (config)); + + private = GIMP_CONFIG_INTERFACE_GET_PRIVATE (config); + + private->xcf_version = xcf_version; +} diff --git a/libgimpconfig/gimpconfig-iface.h b/libgimpconfig/gimpconfig-iface.h index c142ee6c52..fef3def071 100644 --- a/libgimpconfig/gimpconfig-iface.h +++ b/libgimpconfig/gimpconfig-iface.h @@ -129,6 +129,10 @@ gboolean gimp_config_copy (GimpConfig *src, GimpConfig *dest, GParamFlags flags); +guint gimp_config_get_xcf_version (GimpConfig *config); +void gimp_config_set_xcf_version (GimpConfig *config, + guint xcf_version); + G_END_DECLS diff --git a/libgimpconfig/gimpconfig-serialize.c b/libgimpconfig/gimpconfig-serialize.c index ce5617bb49..930d71f93f 100644 --- a/libgimpconfig/gimpconfig-serialize.c +++ b/libgimpconfig/gimpconfig-serialize.c @@ -309,61 +309,81 @@ gimp_config_serialize_property (GimpConfig *config, if (color) { - const gchar *encoding; - const Babl *format = gegl_color_get_format (color); - const Babl *space; - GBytes *bytes; - gconstpointer data; - gsize data_length; - int profile_length = 0; + guint xcf_version = gimp_config_get_xcf_version (config); - gimp_config_writer_open (writer, "color"); - - if (babl_format_is_palette (format)) + /* If XCF version is before GIMP 3.0, then colors should be saved + * in legacy GimpRGB format for backwards compatibility */ + if (xcf_version >= 14) { - guint8 pixel[40]; + const gchar *encoding; + const Babl *format = gegl_color_get_format (color); + const Babl *space; + GBytes *bytes; + gconstpointer data; + gsize data_length; + int profile_length = 0; - /* As a special case, we don't want to serialize - * palette colors, because they are just too much - * dependent on external data and cannot be - * deserialized back safely. So we convert them first. - */ - free_color = TRUE; - color = gegl_color_duplicate (color); + gimp_config_writer_open (writer, "color"); - format = babl_format_with_space ("R'G'B'A u8", format); - gegl_color_get_pixel (color, format, pixel); - gegl_color_set_pixel (color, format, pixel); - } + if (babl_format_is_palette (format)) + { + guint8 pixel[40]; - encoding = babl_format_get_encoding (format); - gimp_config_writer_string (writer, encoding); + /* As a special case, we don't want to serialize + * palette colors, because they are just too much + * dependent on external data and cannot be + * deserialized back safely. So we convert them first. + */ + free_color = TRUE; + color = gegl_color_duplicate (color); - bytes = gegl_color_get_bytes (color, format); - data = g_bytes_get_data (bytes, &data_length); + format = babl_format_with_space ("R'G'B'A u8", format); + gegl_color_get_pixel (color, format, pixel); + gegl_color_set_pixel (color, format, pixel); + } - gimp_config_writer_printf (writer, "%" G_GSIZE_FORMAT, data_length); - gimp_config_writer_data (writer, data_length, data); + encoding = babl_format_get_encoding (format); + gimp_config_writer_string (writer, encoding); - space = babl_format_get_space (format); - if (space != babl_space ("sRGB")) - { - guint8 *profile_data; + bytes = gegl_color_get_bytes (color, format); + data = g_bytes_get_data (bytes, &data_length); - profile_data = (guint8 *) babl_space_get_icc (babl_format_get_space (format), - &profile_length); - gimp_config_writer_printf (writer, "%u", profile_length); - if (profile_data) - gimp_config_writer_data (writer, profile_length, profile_data); + gimp_config_writer_printf (writer, "%" G_GSIZE_FORMAT, + data_length); + gimp_config_writer_data (writer, data_length, data); + + space = babl_format_get_space (format); + if (space != babl_space ("sRGB")) + { + guint8 *profile_data; + + profile_data = + (guint8 *) babl_space_get_icc (babl_format_get_space (format), + &profile_length); + gimp_config_writer_printf (writer, "%u", profile_length); + if (profile_data) + gimp_config_writer_data (writer, profile_length, + profile_data); + } + else + { + gimp_config_writer_printf (writer, "%u", profile_length); + } + + g_bytes_unref (bytes); + gimp_config_writer_close (writer); } else { - gimp_config_writer_printf (writer, "%u", profile_length); + gdouble rgba[4]; + + gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), rgba); + + gimp_config_writer_printf (writer, + "(color-rgba %f %f %f %f)", + rgba[0], rgba[1], rgba[2], + rgba[3]); } - - g_bytes_unref (bytes); - - gimp_config_writer_close (writer); } else { diff --git a/libgimpconfig/gimpconfig.def b/libgimpconfig/gimpconfig.def index a23ddf04a6..2d7068482b 100644 --- a/libgimpconfig/gimpconfig.def +++ b/libgimpconfig/gimpconfig.def @@ -34,6 +34,7 @@ EXPORTS gimp_config_duplicate gimp_config_error_quark gimp_config_get_type + gimp_config_get_xcf_version gimp_config_is_equal_to gimp_config_param_spec_duplicate gimp_config_path_expand @@ -54,6 +55,7 @@ EXPORTS gimp_config_serialize_to_stream gimp_config_serialize_to_string gimp_config_serialize_value + gimp_config_set_xcf_version gimp_config_string_append_escaped gimp_config_sync gimp_config_type_register