From 6b5e42def39c3314e67ba1bdbcc0b305d76416fd Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Tue, 24 Jun 2003 13:58:34 +0000 Subject: [PATCH] Added persistent storage of text layers in XCF files. We use a parasite in 2003-06-24 Sven Neumann Added persistent storage of text layers in XCF files. We use a parasite in order to keep the file format backwards compatible. Fixes bug #111781. * app/text/Makefile.am * app/text/gimptext-parasite.[ch]: new files that hold functions to convert a GimpText object to a GimpParasite and back. * app/text/gimptextlayer.[ch]: added an ugly hack that allows to convert a normal layer to a text layer. * app/xcf/xcf-save.c: when saving a text layer, store an extra parasite that holds all information about the text. * app/xcf/xcf-load.c: if a "gimp-text-layer" parasite is found and it can be successfully deserialized to a GimpText object, convert the layer to a text layer and remove the parasite. * app/Makefile.am: had to change linkage order. * devel-docs/parasites.txt: documented the new "gimp-text-layer" parasite. * app/text/gimptext-parasite.[ch] * app/gui/session.c (session_save): plugged minor memory leaks. --- ChangeLog | 28 +++++++++++ app/Makefile.am | 2 +- app/gui/session.c | 1 + app/text/Makefile.am | 2 + app/text/gimptext-parasite.c | 90 ++++++++++++++++++++++++++++++++++++ app/text/gimptext-parasite.h | 32 +++++++++++++ app/text/gimptextlayer.c | 90 ++++++++++++++++++++++++++++++++++-- app/text/gimptextlayer.h | 8 ++-- 8 files changed, 244 insertions(+), 9 deletions(-) create mode 100644 app/text/gimptext-parasite.c create mode 100644 app/text/gimptext-parasite.h diff --git a/ChangeLog b/ChangeLog index 735f8f224e..af41e6b23a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2003-06-24 Sven Neumann + + Added persistent storage of text layers in XCF files. We use a + parasite in order to keep the file format backwards compatible. + Fixes bug #111781. + + * app/text/Makefile.am + * app/text/gimptext-parasite.[ch]: new files that hold functions + to convert a GimpText object to a GimpParasite and back. + + * app/text/gimptextlayer.[ch]: added an ugly hack that allows to + convert a normal layer to a text layer. + + * app/xcf/xcf-save.c: when saving a text layer, store an extra + parasite that holds all information about the text. + + * app/xcf/xcf-load.c: if a "gimp-text-layer" parasite is found and + it can be successfully deserialized to a GimpText object, convert + the layer to a text layer and remove the parasite. + + * app/Makefile.am: had to change linkage order. + + * devel-docs/parasites.txt: documented the new "gimp-text-layer" + parasite. + + * app/text/gimptext-parasite.[ch] + * app/gui/session.c (session_save): plugged minor memory leaks. + 2003-06-24 Sven Neumann * app/config/gimpscanner.c: store file descriptor and filename in diff --git a/app/Makefile.am b/app/Makefile.am index b8a6c45c1e..dfec776bfc 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -73,8 +73,8 @@ gimp_1_3_LDADD = \ core/libappcore.a \ pdb/libapppdb.a \ paint/libapppaint.a \ - text/libapptext.a \ xcf/libappxcf.a \ + text/libapptext.a \ vectors/libappvectors.a \ file/libappfile.a \ plug-in/libappplug-in.a \ diff --git a/app/gui/session.c b/app/gui/session.c index 9eb478d4ae..014731d11c 100644 --- a/app/gui/session.c +++ b/app/gui/session.c @@ -218,6 +218,7 @@ session_save (Gimp *gimp) "every time you quit the gimp. If this " "file isn't found, defaults are used.", NULL); + g_free (filename); if (!writer) return; diff --git a/app/text/Makefile.am b/app/text/Makefile.am index 90dcd91bc2..b74aff9a47 100644 --- a/app/text/Makefile.am +++ b/app/text/Makefile.am @@ -25,6 +25,8 @@ libapptext_a_sources = \ gimptext.h \ gimptext-compat.c \ gimptext-compat.h \ + gimptext-parasite.c \ + gimptext-parasite.h \ gimptextlayer.c \ gimptextlayer.h \ gimptextlayout.c \ diff --git a/app/text/gimptext-parasite.c b/app/text/gimptext-parasite.c new file mode 100644 index 0000000000..7d042b7a0b --- /dev/null +++ b/app/text/gimptext-parasite.c @@ -0,0 +1,90 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpText + * Copyright (C) 2003 Sven Neumann + * + * 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 + +#include + +#include "libgimpbase/gimpbase.h" + +#include "text/text-types.h" + +#include "config/gimpconfig.h" + +#include "gimptext.h" +#include "gimptext-parasite.h" + + +GimpParasite * +gimp_text_to_parasite (const GimpText *text) +{ + GimpParasite *parasite; + gchar *str; + + g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); + + str = gimp_config_serialize_to_string (G_OBJECT (text), NULL); + g_return_val_if_fail (str != NULL, NULL); + + parasite = gimp_parasite_new (gimp_text_parasite_name (), + GIMP_PARASITE_PERSISTENT, + strlen (str) + 1, str); + g_free (str); + + return parasite; +} + +GimpText * +gimp_text_from_parasite (const GimpParasite *parasite) +{ + GimpText *text; + const gchar *str; + GError *error = NULL; + + g_return_val_if_fail (parasite != NULL, NULL); + g_return_val_if_fail (strcmp (gimp_parasite_name (parasite), + gimp_text_parasite_name ()) == 0, NULL); + + str = gimp_parasite_data (parasite); + g_return_val_if_fail (str != NULL, NULL); + + text = g_object_new (GIMP_TYPE_TEXT, NULL); + + if (! gimp_config_deserialize_string (G_OBJECT (text), + str, + gimp_parasite_data_size (parasite), + NULL, + &error)) + { + g_warning ("Failed to deserialize text parasite: %s", error->message); + g_error_free (error); + } + + return text; +} + +const gchar * +gimp_text_parasite_name (void) +{ + return "gimp-text-layer"; +} diff --git a/app/text/gimptext-parasite.h b/app/text/gimptext-parasite.h new file mode 100644 index 0000000000..037f610413 --- /dev/null +++ b/app/text/gimptext-parasite.h @@ -0,0 +1,32 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * GimpText + * Copyright (C) 2003 Sven Neumann + * + * 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_TEXT_PARASITE_H__ +#define __GIMP_TEXT_PARASITE_H__ + + +GimpParasite * gimp_text_to_parasite (const GimpText *text); +GimpText * gimp_text_from_parasite (const GimpParasite *parasite); + +const gchar * gimp_text_parasite_name (void) G_GNUC_CONST; + + +#endif /* __GIMP_TEXT_PARASITE_H__ */ diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c index ef8923f8cf..c87597b1ed 100644 --- a/app/text/gimptextlayer.c +++ b/app/text/gimptextlayer.c @@ -57,7 +57,8 @@ static GimpItem * gimp_text_layer_duplicate (GimpItem *item, static void gimp_text_layer_rename (GimpItem *item, const gchar *new_name, const gchar *undo_desc); - +static void gimp_text_layer_set_text (GimpTextLayer *layer, + GimpText *text); static void gimp_text_layer_notify_text (GimpTextLayer *layer); static gboolean gimp_text_layer_idle_render (GimpTextLayer *layer); static gboolean gimp_text_layer_render (GimpTextLayer *layer); @@ -224,7 +225,7 @@ GimpLayer * gimp_text_layer_new (GimpImage *image, GimpText *text) { - GimpTextLayer *layer; + GimpTextLayer *layer; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); @@ -240,7 +241,7 @@ gimp_text_layer_new (GimpImage *image, gimp_image_base_type_with_alpha (image), NULL); - layer->text = g_object_ref (text); + gimp_text_layer_set_text (layer, text); if (! gimp_text_layer_render (layer)) { @@ -248,11 +249,90 @@ gimp_text_layer_new (GimpImage *image, return NULL; } + return GIMP_LAYER (layer); +} + +/** + * gimp_text_layer_from_layer: + * @layer: a #GimpLayer object + * @text: a #GimpText object + * + * Converts a standard #GimpLayer and a #GimpText object into a + * #GimpTextLayer. The new text layer takes ownership of the @text 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 text layers + * from XCF files in a backwards-compatible way. Please don't use it + * for anything else! + * + * Return value: a newly allocated #GimpTextLayer object + **/ +GimpLayer * +gimp_text_layer_from_layer (GimpLayer *layer, + GimpText *text) +{ + GimpTextLayer *text_layer; + GimpItem *item; + GimpDrawable *drawable; + + g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL); + g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); + + text_layer = g_object_new (GIMP_TYPE_TEXT_LAYER, NULL); + + item = GIMP_ITEM (text_layer); + drawable = GIMP_DRAWABLE (text_layer); + + gimp_object_set_name (GIMP_OBJECT (text_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)); + item->gimage = gimp_item_get_image (GIMP_ITEM (layer)); + + item->parasites = GIMP_ITEM (layer)->parasites; + GIMP_ITEM (layer)->parasites = NULL; + + item->width = gimp_item_width (GIMP_ITEM (layer)); + item->height = gimp_item_height (GIMP_ITEM (layer)); + + gimp_item_offsets (GIMP_ITEM (layer), &item->offset_x, &item->offset_y); + + item->linked = gimp_item_get_linked (GIMP_ITEM (layer)); + + drawable->tiles = GIMP_DRAWABLE (layer)->tiles; + GIMP_DRAWABLE (layer)->tiles = NULL; + + drawable->visible = gimp_drawable_get_visible (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 (text_layer)->opacity = gimp_layer_get_opacity (layer); + GIMP_LAYER (text_layer)->mode = gimp_layer_get_mode (layer); + GIMP_LAYER (text_layer)->preserve_trans = gimp_layer_get_preserve_trans (layer); + + gimp_text_layer_set_text (text_layer, text); + + g_object_unref (layer); + g_object_unref (text); + + return GIMP_LAYER (text_layer); +} + +static void +gimp_text_layer_set_text (GimpTextLayer *layer, + GimpText *text) +{ + g_return_if_fail (GIMP_IS_TEXT_LAYER (layer)); + g_return_if_fail (GIMP_IS_TEXT (text)); + g_return_if_fail (layer->text == NULL); + + layer->text = g_object_ref (text); g_signal_connect_object (text, "notify", G_CALLBACK (gimp_text_layer_notify_text), layer, G_CONNECT_SWAPPED); - - return GIMP_LAYER (layer); } GimpText * diff --git a/app/text/gimptextlayer.h b/app/text/gimptextlayer.h index 49fde59e7f..7044d80dcb 100644 --- a/app/text/gimptextlayer.h +++ b/app/text/gimptextlayer.h @@ -55,9 +55,11 @@ struct _GimpTextLayerClass GType gimp_text_layer_get_type (void) G_GNUC_CONST; -GimpLayer * gimp_text_layer_new (GimpImage *image, - GimpText *text); -GimpText * gimp_text_layer_get_text (GimpTextLayer *layer); +GimpLayer * gimp_text_layer_new (GimpImage *image, + GimpText *text); +GimpLayer * gimp_text_layer_from_layer (GimpLayer *layer, + GimpText *text); +GimpText * gimp_text_layer_get_text (GimpTextLayer *layer); #endif /* __GIMP_TEXT_LAYER_H__ */