diff --git a/ChangeLog b/ChangeLog index 4b2889f11f..58e4a85b12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-03-20 Sven Neumann + + * app/widgets/gimppropwidgets.c (gimp_prop_size_entry_callback): + avoid to set the unit property with every size change; only set it + if it actually changed. + + * app/core/gimpimage-undo-push.c (gimp_image_undo_push_text_layer): + allow to pass a GParamSpec that identifies a single text property + to be changed. In this case, don't store a GimpText object on the + undo stack but only the changed value. + + * app/tools/gimptexttool.c: use the new undo feature to reduce the + memory footprint of text undo for the common case. + + * app/text/gimptextlayer.c: changed accordingly. + 2004-03-20 Simon Budig * app/core/gimpimage-qmask.c: Applied slightly modified patch diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index a1d9e102f1..f850c7bb93 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -49,6 +49,7 @@ #include "gimplist.h" #include "gimpparasitelist.h" +#include "text/gimptext.h" #include "text/gimptextlayer.h" #include "vectors/gimpvectors.h" @@ -1740,7 +1741,9 @@ typedef struct _TextUndo TextUndo; struct _TextUndo { - GimpText *text; + GimpText *text; + const GParamSpec *pspec; + GValue *value; }; static gboolean undo_pop_text_layer (GimpUndo *undo, @@ -1751,20 +1754,34 @@ static void undo_free_text_layer (GimpUndo *undo, gboolean -gimp_image_undo_push_text_layer (GimpImage *gimage, - const gchar *undo_desc, - GimpTextLayer *layer) +gimp_image_undo_push_text_layer (GimpImage *gimage, + const gchar *undo_desc, + GimpTextLayer *layer, + const GParamSpec *pspec) { GimpUndo *undo; gssize size; g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE); g_return_val_if_fail (GIMP_IS_TEXT_LAYER (layer), FALSE); + g_return_val_if_fail (pspec == NULL || pspec->owner_type == GIMP_TYPE_TEXT, + FALSE); + g_return_val_if_fail (pspec == NULL || layer->text != NULL, FALSE); size = sizeof (TextUndo); - if (layer->text) - size += gimp_object_get_memsize (GIMP_OBJECT (layer->text), NULL); + g_printerr ("gimp_image_undo_push_text_layer (%s)\n", + pspec ? pspec->name : NULL); + + if (pspec) + { + /* this is incorrect, but how can it be done better? */ + size += sizeof (GValue); + } + else if (layer->text) + { + size += gimp_object_get_memsize (GIMP_OBJECT (layer->text), NULL); + } undo = gimp_image_undo_push_item (gimage, GIMP_ITEM (layer), size, sizeof (TextUndo), @@ -1777,8 +1794,19 @@ gimp_image_undo_push_text_layer (GimpImage *gimage, { TextUndo *tu = undo->data; - tu->text = (layer->text ? - gimp_config_duplicate (GIMP_CONFIG (layer->text)) : NULL); + if (pspec) + { + tu->pspec = pspec; + tu->value = g_new0 (GValue, 1); + + g_value_init (tu->value, pspec->value_type); + g_object_get_property (G_OBJECT (layer->text), + pspec->name, tu->value); + } + else if (layer->text) + { + tu->text = gimp_config_duplicate (GIMP_CONFIG (layer->text)); + } return TRUE; } @@ -1793,26 +1821,51 @@ undo_pop_text_layer (GimpUndo *undo, { TextUndo *tu = undo->data; GimpTextLayer *layer = GIMP_TEXT_LAYER (GIMP_ITEM_UNDO (undo)->item); - GimpText *text; - if (tu->text) - undo->size -= gimp_object_get_memsize (GIMP_OBJECT (tu->text), NULL); + if (tu->pspec) + { + GValue *value; - text = (layer->text ? - gimp_config_duplicate (GIMP_CONFIG (layer->text)) : NULL); + g_return_val_if_fail (layer->text != NULL, FALSE); - if (layer->text && tu->text) - gimp_config_sync (GIMP_CONFIG (tu->text), GIMP_CONFIG (layer->text), 0); + value = g_new0 (GValue, 1); + g_value_init (value, tu->pspec->value_type); + + g_object_get_property (G_OBJECT (layer->text), + tu->pspec->name, value); + + g_object_set_property (G_OBJECT (layer->text), + tu->pspec->name, tu->value); + + g_value_unset (tu->value); + g_free (tu->value); + + tu->value = value; + } else - gimp_text_layer_set_text (layer, tu->text); + { + GimpText *text; - if (tu->text) - g_object_unref (tu->text); + if (tu->text) + undo->size -= gimp_object_get_memsize (GIMP_OBJECT (tu->text), NULL); - tu->text = text; + text = (layer->text ? + gimp_config_duplicate (GIMP_CONFIG (layer->text)) : NULL); - if (tu->text) - undo->size += gimp_object_get_memsize (GIMP_OBJECT (tu->text), NULL); + if (layer->text && tu->text) + gimp_config_sync (GIMP_CONFIG (tu->text), + GIMP_CONFIG (layer->text), 0); + else + gimp_text_layer_set_text (layer, tu->text); + + if (tu->text) + g_object_unref (tu->text); + + tu->text = text; + + if (tu->text) + undo->size += gimp_object_get_memsize (GIMP_OBJECT (tu->text), NULL); + } return TRUE; } @@ -1826,6 +1879,12 @@ undo_free_text_layer (GimpUndo *undo, if (tu->text) g_object_unref (tu->text); + if (tu->pspec) + { + g_value_unset (tu->value); + g_free (tu->value); + } + g_free (tu); } diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h index 99733c57ea..e24cbf8c02 100644 --- a/app/core/gimpimage-undo-push.h +++ b/app/core/gimpimage-undo-push.h @@ -111,9 +111,10 @@ gboolean gimp_image_undo_push_layer_preserve_trans (GimpImage *gimage, GimpLayer *layer); /* text layer undo */ -gboolean gimp_image_undo_push_text_layer (GimpImage *gimage, - const gchar *undo_desc, - GimpTextLayer *layer); +gboolean gimp_image_undo_push_text_layer (GimpImage *gimage, + const gchar *undo_desc, + GimpTextLayer *layer, + const GParamSpec *pspec); /* channel undos */ diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c index fd44c2f3d7..0a2c31a5f9 100644 --- a/app/text/gimptextlayer.c +++ b/app/text/gimptextlayer.c @@ -500,7 +500,7 @@ gimp_text_layer_set (GimpTextLayer *layer, if (undo_group) gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TEXT, undo_desc); - gimp_image_undo_push_text_layer (image, undo_desc, layer); + gimp_image_undo_push_text_layer (image, undo_desc, layer, NULL); va_start (var_args, first_property_name); @@ -529,7 +529,7 @@ gimp_text_layer_discard (GimpTextLayer *layer) gimp_image_undo_push_text_layer (gimp_item_get_image (GIMP_ITEM (layer)), _("Discard Text Information"), - layer); + layer, NULL); gimp_text_layer_set_text (layer, NULL); } diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c index 064242d4cd..f23eb29896 100644 --- a/app/tools/gimptexttool.c +++ b/app/tools/gimptexttool.c @@ -479,12 +479,13 @@ gimp_text_tool_idle_apply (GimpTextTool *text_tool) static void gimp_text_tool_apply (GimpTextTool *text_tool) { - GimpImage *image; - GimpTextLayer *text_layer; - GObject *src; - GObject *dest; - GList *list; - gboolean undo_group; + const GParamSpec *pspec = NULL; + GimpImage *image; + GimpTextLayer *text_layer; + GObject *src; + GObject *dest; + GList *list; + gboolean undo_group; if (text_tool->idle_id) { @@ -500,6 +501,17 @@ gimp_text_tool_apply (GimpTextTool *text_tool) g_return_if_fail (text_layer->text == text_tool->text); + /* Walk over the list of changes and figure out if we are changing + * a single property or need to push a full text undo. + */ + for (list = text_tool->pending; + list && list->next && list->next->data == list->data; + list = list->next) + /* do nothing */; + + if (g_list_length (list) == 1) + pspec = list->data; + gimp_tool_control_set_preserve (GIMP_TOOL (text_tool)->control, TRUE); /* If the layer contains a mask, @@ -513,7 +525,7 @@ gimp_text_tool_apply (GimpTextTool *text_tool) gimp_image_undo_push_drawable_mod (image, NULL, GIMP_DRAWABLE (text_layer)); - gimp_image_undo_push_text_layer (image, NULL, text_layer); + gimp_image_undo_push_text_layer (image, NULL, text_layer, pspec); src = G_OBJECT (text_tool->proxy); dest = G_OBJECT (text_tool->text); @@ -523,15 +535,18 @@ gimp_text_tool_apply (GimpTextTool *text_tool) g_object_freeze_notify (dest); - for (list = text_tool->pending; list; list = list->next) + for (; list; list = list->next) { - GParamSpec *pspec = list->data; - GValue value = { 0, }; + GValue value = { 0, }; /* look ahead and compress changes */ if (list->next && list->next->data == list->data) continue; + pspec = list->data; + + g_printerr ("gimp_text_tool_apply: changing %s\n", pspec->name); + g_value_init (&value, pspec->value_type); g_object_get_property (src, pspec->name, &value); diff --git a/app/widgets/gimppropwidgets.c b/app/widgets/gimppropwidgets.c index 5093aa5659..f1efba024e 100644 --- a/app/widgets/gimppropwidgets.c +++ b/app/widgets/gimppropwidgets.c @@ -1778,6 +1778,18 @@ gimp_prop_size_entry_callback (GimpSizeEntry *sizeentry, value = gimp_size_entry_get_value (sizeentry, 0); unit_value = gimp_size_entry_get_unit (sizeentry); + if (unit_param_spec) + { + GimpUnit old_unit; + + g_object_get (config, + unit_param_spec->name, &old_unit, + NULL); + + if (unit_value == old_unit) + unit_param_spec = NULL; + } + if (G_IS_PARAM_SPEC_INT (param_spec)) { g_object_set (config, diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c index 5093aa5659..f1efba024e 100644 --- a/libgimpwidgets/gimppropwidgets.c +++ b/libgimpwidgets/gimppropwidgets.c @@ -1778,6 +1778,18 @@ gimp_prop_size_entry_callback (GimpSizeEntry *sizeentry, value = gimp_size_entry_get_value (sizeentry, 0); unit_value = gimp_size_entry_get_unit (sizeentry); + if (unit_param_spec) + { + GimpUnit old_unit; + + g_object_get (config, + unit_param_spec->name, &old_unit, + NULL); + + if (unit_value == old_unit) + unit_param_spec = NULL; + } + if (G_IS_PARAM_SPEC_INT (param_spec)) { g_object_set (config,