mirror of https://github.com/GNOME/gimp.git
app: new storage format for the text layer parasite implies XCF version bump.
The new parasite format cannot be loaded by old versions of GIMP. This means we must bump the XCF version (even though technically we didn't really touch the XCF format itself because text layers are stored in a hackish way, yet text layers are just too important nowadays to not care). Nevertheless if an old XCF with text layers was loaded and the text layers left untouched, the old parasite will be saved back as-is. Therefore no need to bump the XCF version in this specific case. Only when we created new text layers or edited existing ones.
This commit is contained in:
parent
bd9eb1d8ff
commit
6d5aaa995f
|
@ -82,6 +82,8 @@
|
||||||
#include "gimptemplate.h"
|
#include "gimptemplate.h"
|
||||||
#include "gimpundostack.h"
|
#include "gimpundostack.h"
|
||||||
|
|
||||||
|
#include "text/gimptextlayer.h"
|
||||||
|
|
||||||
#include "vectors/gimpvectors.h"
|
#include "vectors/gimpvectors.h"
|
||||||
|
|
||||||
#include "gimp-log.h"
|
#include "gimp-log.h"
|
||||||
|
@ -2961,6 +2963,17 @@ gimp_image_get_xcf_version (GimpImage *image,
|
||||||
"GIMP 3.0"));
|
"GIMP 3.0"));
|
||||||
version = MAX (17, version);
|
version = MAX (17, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GIMP_IS_TEXT_LAYER (layer) &&
|
||||||
|
/* If we loaded an old XCF and didn't touch the text layers, then we
|
||||||
|
* just resave the text layer as-is. No need to bump the XCF version.
|
||||||
|
*/
|
||||||
|
! GIMP_TEXT_LAYER (layer)->text_parasite_is_old)
|
||||||
|
{
|
||||||
|
ADD_REASON (g_strdup_printf (_("Format of font information in text layer was changed in %s"),
|
||||||
|
"GIMP 3.0"));
|
||||||
|
version = MAX (19, version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_list_free (items);
|
g_list_free (items);
|
||||||
|
|
||||||
|
@ -3127,6 +3140,7 @@ gimp_image_get_xcf_version (GimpImage *image,
|
||||||
case 16:
|
case 16:
|
||||||
case 17:
|
case 17:
|
||||||
case 18:
|
case 18:
|
||||||
|
case 19:
|
||||||
if (gimp_version) *gimp_version = 300;
|
if (gimp_version) *gimp_version = 300;
|
||||||
if (version_string) *version_string = "GIMP 3.0";
|
if (version_string) *version_string = "GIMP 3.0";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -67,6 +67,7 @@ gimp_text_to_parasite (GimpText *text)
|
||||||
GimpText *
|
GimpText *
|
||||||
gimp_text_from_parasite (const GimpParasite *parasite,
|
gimp_text_from_parasite (const GimpParasite *parasite,
|
||||||
Gimp *gimp,
|
Gimp *gimp,
|
||||||
|
gboolean *before_xcf_v19,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GimpText *text;
|
GimpText *text;
|
||||||
|
@ -83,17 +84,17 @@ gimp_text_from_parasite (const GimpParasite *parasite,
|
||||||
parasite_data = (gchar *) gimp_parasite_get_data (parasite, ¶site_data_size);
|
parasite_data = (gchar *) gimp_parasite_get_data (parasite, ¶site_data_size);
|
||||||
if (parasite_data)
|
if (parasite_data)
|
||||||
{
|
{
|
||||||
gboolean is_old = strstr (parasite_data, "\"GimpFont\"") == NULL;
|
|
||||||
gboolean has_markup = g_str_has_prefix (parasite_data, "(markup ");
|
gboolean has_markup = g_str_has_prefix (parasite_data, "(markup ");
|
||||||
GimpParasite *new_parasite = NULL;
|
GimpParasite *new_parasite = NULL;
|
||||||
GString *new_data;
|
GString *new_data;
|
||||||
|
|
||||||
|
*before_xcf_v19 = (strstr (parasite_data, "\"GimpFont\"") == NULL);
|
||||||
/* This is for backward compatibility with older xcf files.
|
/* This is for backward compatibility with older xcf files.
|
||||||
* font used to be serialized as a string, but now it is serialized/deserialized as
|
* font used to be serialized as a string, but now it is serialized/deserialized as
|
||||||
* GimpFont, so the object Type name is inserted for the GimpFont deserialization function to be called.
|
* GimpFont, so the object Type name is inserted for the GimpFont deserialization function to be called.
|
||||||
* And more importantly, fonts in the markup are extracted into their own fields for deserialization.
|
* And more importantly, fonts in the markup are extracted into their own fields for deserialization.
|
||||||
*/
|
*/
|
||||||
if (is_old)
|
if (*before_xcf_v19)
|
||||||
{
|
{
|
||||||
new_data = g_string_new (parasite_data);
|
new_data = g_string_new (parasite_data);
|
||||||
g_string_replace (new_data, "\")\n(font", "\")\n(font \"GimpFont\"", 1);
|
g_string_replace (new_data, "\")\n(font", "\")\n(font \"GimpFont\"", 1);
|
||||||
|
|
|
@ -26,6 +26,7 @@ const gchar * gimp_text_parasite_name (void) G_GNUC_CONST;
|
||||||
GimpParasite * gimp_text_to_parasite (GimpText *text);
|
GimpParasite * gimp_text_to_parasite (GimpText *text);
|
||||||
GimpText * gimp_text_from_parasite (const GimpParasite *parasite,
|
GimpText * gimp_text_from_parasite (const GimpParasite *parasite,
|
||||||
Gimp *gimp,
|
Gimp *gimp,
|
||||||
|
gboolean *before_xcf_v19,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
const gchar * gimp_text_gdyntext_parasite_name (void) G_GNUC_CONST;
|
const gchar * gimp_text_gdyntext_parasite_name (void) G_GNUC_CONST;
|
||||||
|
|
|
@ -58,6 +58,7 @@ gimp_text_layer_xcf_load_hack (GimpLayer **layer)
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
GimpText *text = NULL;
|
GimpText *text = NULL;
|
||||||
const GimpParasite *parasite;
|
const GimpParasite *parasite;
|
||||||
|
gboolean before_xcf_v19 = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (layer != NULL, FALSE);
|
g_return_val_if_fail (layer != NULL, FALSE);
|
||||||
g_return_val_if_fail (GIMP_IS_LAYER (*layer), FALSE);
|
g_return_val_if_fail (GIMP_IS_LAYER (*layer), FALSE);
|
||||||
|
@ -71,6 +72,7 @@ gimp_text_layer_xcf_load_hack (GimpLayer **layer)
|
||||||
|
|
||||||
text = gimp_text_from_parasite (parasite,
|
text = gimp_text_from_parasite (parasite,
|
||||||
gimp_item_get_image (GIMP_ITEM (*layer))->gimp,
|
gimp_item_get_image (GIMP_ITEM (*layer))->gimp,
|
||||||
|
&before_xcf_v19,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -94,7 +96,10 @@ gimp_text_layer_xcf_load_hack (GimpLayer **layer)
|
||||||
parasite = gimp_item_parasite_find (GIMP_ITEM (*layer), name);
|
parasite = gimp_item_parasite_find (GIMP_ITEM (*layer), name);
|
||||||
|
|
||||||
if (parasite)
|
if (parasite)
|
||||||
text = gimp_text_from_gdyntext_parasite (parasite);
|
{
|
||||||
|
text = gimp_text_from_gdyntext_parasite (parasite);
|
||||||
|
before_xcf_v19 = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text)
|
if (text)
|
||||||
|
@ -102,7 +107,8 @@ gimp_text_layer_xcf_load_hack (GimpLayer **layer)
|
||||||
*layer = gimp_text_layer_from_layer (*layer, text);
|
*layer = gimp_text_layer_from_layer (*layer, text);
|
||||||
|
|
||||||
/* let the text layer knows what parasite was used to create it */
|
/* let the text layer knows what parasite was used to create it */
|
||||||
GIMP_TEXT_LAYER (*layer)->text_parasite = name;
|
GIMP_TEXT_LAYER (*layer)->text_parasite = name;
|
||||||
|
GIMP_TEXT_LAYER (*layer)->text_parasite_is_old = before_xcf_v19;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (text != NULL);
|
return (text != NULL);
|
||||||
|
|
|
@ -191,9 +191,10 @@ gimp_text_layer_class_init (GimpTextLayerClass *klass)
|
||||||
static void
|
static void
|
||||||
gimp_text_layer_init (GimpTextLayer *layer)
|
gimp_text_layer_init (GimpTextLayer *layer)
|
||||||
{
|
{
|
||||||
layer->text = NULL;
|
layer->text = NULL;
|
||||||
layer->text_parasite = NULL;
|
layer->text_parasite = NULL;
|
||||||
layer->private = gimp_text_layer_get_instance_private (layer);
|
layer->text_parasite_is_old = FALSE;
|
||||||
|
layer->private = gimp_text_layer_get_instance_private (layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -300,7 +301,10 @@ gimp_text_layer_duplicate (GimpItem *item,
|
||||||
|
|
||||||
/* this is just the parasite name, not a pointer to the parasite */
|
/* this is just the parasite name, not a pointer to the parasite */
|
||||||
if (layer->text_parasite)
|
if (layer->text_parasite)
|
||||||
new_layer->text_parasite = layer->text_parasite;
|
{
|
||||||
|
new_layer->text_parasite = layer->text_parasite;
|
||||||
|
new_layer->text_parasite_is_old = layer->text_parasite_is_old;
|
||||||
|
}
|
||||||
|
|
||||||
new_layer->private->base_dir = layer->private->base_dir;
|
new_layer->private->base_dir = layer->private->base_dir;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +621,8 @@ gimp_text_layer_text_changed (GimpTextLayer *layer)
|
||||||
*/
|
*/
|
||||||
gimp_item_parasite_detach (GIMP_ITEM (layer), layer->text_parasite,
|
gimp_item_parasite_detach (GIMP_ITEM (layer), layer->text_parasite,
|
||||||
FALSE);
|
FALSE);
|
||||||
layer->text_parasite = NULL;
|
layer->text_parasite = NULL;
|
||||||
|
layer->text_parasite_is_old = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer->text->box_mode == GIMP_TEXT_BOX_DYNAMIC)
|
if (layer->text->box_mode == GIMP_TEXT_BOX_DYNAMIC)
|
||||||
|
|
|
@ -41,10 +41,11 @@ struct _GimpTextLayer
|
||||||
GimpLayer layer;
|
GimpLayer layer;
|
||||||
|
|
||||||
GimpText *text;
|
GimpText *text;
|
||||||
const gchar *text_parasite; /* parasite name that this text was set from,
|
const gchar *text_parasite; /* parasite name that this text was set from,
|
||||||
* and that should be removed when the text
|
* and that should be removed when the text
|
||||||
* is changed.
|
* is changed.
|
||||||
*/
|
*/
|
||||||
|
gboolean text_parasite_is_old; /* Format before XCF 19. */
|
||||||
gboolean auto_rename;
|
gboolean auto_rename;
|
||||||
gboolean modified;
|
gboolean modified;
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ static GimpXcfLoaderFunc * const xcf_loaders[] =
|
||||||
xcf_load_image, /* version 16 */
|
xcf_load_image, /* version 16 */
|
||||||
xcf_load_image, /* version 17 */
|
xcf_load_image, /* version 17 */
|
||||||
xcf_load_image, /* version 18 */
|
xcf_load_image, /* version 18 */
|
||||||
|
xcf_load_image, /* version 19 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue