[gnumeric] GUI: Create separate rendered values cache.



commit 988d9892cb2e2e2d70d4159c7c6beb245dc68ee0
Author: Morten Welinder <terra gnome org>
Date:   Fri Sep 11 13:34:28 2009 -0400

    GUI: Create separate rendered values cache.

 ChangeLog            |    8 +++++
 NEWS                 |    1 +
 src/cell.c           |   11 ++----
 src/cell.h           |    1 -
 src/gnumeric.h       |    1 +
 src/preview-grid.c   |    9 ++++--
 src/rendered-value.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/rendered-value.h |   25 ++++++++++++++--
 src/sheet.c          |    3 ++
 src/sheet.h          |    1 +
 10 files changed, 126 insertions(+), 14 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 66d3c48..84686ab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2009-09-11  Morten Welinder  <terra gnome org>
 
+	* src/rendered-value.c (gnm_rvc_new, gnm_rvc_free, gnm_rvc_query,
+	gnm_rvc_store, gnm_rvc_remove): New functions.
+
+	* src/cell.c (gnm_cell_unrender, gnm_cell_get_rendered_value,
+	gnm_cell_fetch_rendered_value): Hook into above.
+
+2009-09-11  Morten Welinder  <terra gnome org>
+
 	* src/mstyle.c (gnm_style_get_pango_attrs): Don't scale if zoom is
 	1.
 
diff --git a/NEWS b/NEWS
index 251c60d..d16a8a2 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Morten:
 	* Fixes text export GUI issue.  [#594155]
 	* Fix minor status line issue.  [#594469]
 	* Fix print crash for sheet object.  [#594862]
+	* Limit memory usage for rendered values.
 
 --------------------------------------------------------------------------
 Gnumeric 1.9.12
diff --git a/src/cell.c b/src/cell.c
index 4a1d6dd..96fa80a 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -458,7 +458,7 @@ gnm_cell_get_rendered_value (GnmCell const *cell)
 {
 	g_return_val_if_fail (cell != NULL, NULL);
 
-	return cell->rendered_value;
+	return gnm_rvc_query (cell->base.sheet->rendered_values, cell);
 }
 
 GnmRenderedValue *
@@ -479,10 +479,7 @@ gnm_cell_fetch_rendered_value (GnmCell const *cell,
 void
 gnm_cell_unrender (GnmCell const *cell)
 {
-	if (cell->rendered_value) {
-		gnm_rendered_value_destroy (cell->rendered_value);
-		((GnmCell *)cell)->rendered_value = NULL;
-	}
+	gnm_rvc_remove (cell->base.sheet->rendered_values, cell);
 }
 
 /**
@@ -503,8 +500,8 @@ gnm_cell_render_value (GnmCell const *cell, gboolean allow_variable_width)
 				     allow_variable_width,
 				     sheet->context,
 				     sheet->last_zoom_factor_used);
-	gnm_cell_unrender (cell);
-	((GnmCell*)cell)->rendered_value = rv;
+
+	gnm_rvc_store (sheet->rendered_values, cell, rv);
 
 	return rv;
 }
diff --git a/src/cell.h b/src/cell.h
index 47c7bb7..7ebf8f3 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -28,7 +28,6 @@ struct _GnmCell {
 	ColRowInfo    *row_info;
 
 	GnmValue      *value;	/* computed or entered (Must be non NULL) */
-	GnmRenderedValue *rendered_value;
 };
 
 /**
diff --git a/src/gnumeric.h b/src/gnumeric.h
index 0e8484d..818a54f 100644
--- a/src/gnumeric.h
+++ b/src/gnumeric.h
@@ -71,6 +71,7 @@ typedef enum {
 
 typedef struct _GnmRenderedValue	GnmRenderedValue;
 typedef struct _GnmRenderedRotatedValue	GnmRenderedRotatedValue;
+typedef struct _GnmRenderedValueCollection GnmRenderedValueCollection;
 
 typedef GSList				GnmExprList;
 typedef union  _GnmExpr			GnmExpr;
diff --git a/src/preview-grid.c b/src/preview-grid.c
index f3a5d3b..9278efe 100644
--- a/src/preview-grid.c
+++ b/src/preview-grid.c
@@ -77,8 +77,9 @@ pg_fetch_cell (PreviewGrid *pg, int col, int row, PangoContext *context,
 	       GnmStyle const *style)
 {
 	PreviewGridClass *klass = PREVIEW_GRID_GET_CLASS (pg);
-	GnmCell  *cell;
+	GnmCell *cell;
 	GnmValue *v = NULL;
+	GnmRenderedValue *rv;
 
 	g_return_val_if_fail (klass != NULL, NULL);
 	g_return_val_if_fail (pg != NULL, NULL);
@@ -92,8 +93,10 @@ pg_fetch_cell (PreviewGrid *pg, int col, int row, PangoContext *context,
 
 	cell = sheet_cell_fetch (pg->sheet, col, row);
 	gnm_cell_set_value (cell, v);
-	cell->rendered_value = gnm_rendered_value_new (cell, style,
-		TRUE, context, pg->sheet->last_zoom_factor_used);
+
+	rv = gnm_rendered_value_new (cell, style, TRUE, context,
+				     pg->sheet->last_zoom_factor_used);
+	gnm_rvc_store (pg->sheet->rendered_values, cell, rv);
 
 	return cell;
 }
diff --git a/src/rendered-value.c b/src/rendered-value.c
index e45374f..27508f7 100644
--- a/src/rendered-value.c
+++ b/src/rendered-value.c
@@ -38,6 +38,7 @@
 #include "value.h"
 #include "parse-util.h"
 #include "workbook.h"
+#include "gutils.h"
 
 #include <string.h>
 #include <goffice/goffice.h>
@@ -516,6 +517,85 @@ gnm_rendered_value_get_text (GnmRenderedValue const *rv)
 	return pango_layout_get_text (rv->layout);
 }
 
+/* ------------------------------------------------------------------------- */
+
+static gboolean
+debug_rvc (void)
+{
+	static int res = -1;
+	if (res == -1) {
+		res = gnm_debug_flag ("rvc");
+	}
+	return res > 0;
+}
+
+GnmRenderedValueCollection *
+gnm_rvc_new (PangoContext *context, gsize size)
+{
+	GnmRenderedValueCollection *res = g_new0 (GnmRenderedValueCollection, 1);
+
+	res->context = g_object_ref (context);
+
+	res->size = size;
+	res->values = g_hash_table_new_full
+		(g_direct_hash, g_direct_equal,
+		 NULL,
+		 (GDestroyNotify)gnm_rendered_value_destroy);
+
+	if (debug_rvc ())
+		g_printerr ("Created rendered value cache %p of size %u\n",
+			    res, (unsigned)size);
+
+	return res;
+}
+
+void
+gnm_rvc_free (GnmRenderedValueCollection *rvc)
+{
+	g_return_if_fail (rvc != NULL);
+
+	if (debug_rvc ())
+		g_printerr ("Destroying rendered value cache %p\n", rvc);
+
+	g_object_unref (rvc->context);
+	g_hash_table_destroy (rvc->values);
+	g_free (rvc);
+}
+
+GnmRenderedValue *
+gnm_rvc_query (GnmRenderedValueCollection *rvc, GnmCell const *cell)
+{
+	g_return_val_if_fail (rvc != NULL, NULL);
+
+	return g_hash_table_lookup (rvc->values, cell);
+}
+
+void
+gnm_rvc_store (GnmRenderedValueCollection *rvc,
+	       GnmCell const *cell,
+	       GnmRenderedValue *rv)
+{
+	g_return_if_fail (rvc != NULL);
+
+	/* Crude cache management:  */
+	if (g_hash_table_size (rvc->values) >= rvc->size) {
+		if (debug_rvc ())
+			g_printerr ("Clearing rendered value cache %p\n", rvc);
+		g_hash_table_remove_all (rvc->values);
+	}
+
+	g_hash_table_insert (rvc->values, (gpointer)cell, rv);
+}
+
+void
+gnm_rvc_remove (GnmRenderedValueCollection *rvc, GnmCell const *cell)
+{
+	g_return_if_fail (rvc != NULL);
+	g_hash_table_remove (rvc->values, (gpointer)cell);
+}
+
+/* ------------------------------------------------------------------------- */
+
 void
 gnm_rendered_value_init (void)
 {
diff --git a/src/rendered-value.h b/src/rendered-value.h
index c9f25ed..c6ee8c7 100644
--- a/src/rendered-value.h
+++ b/src/rendered-value.h
@@ -7,9 +7,6 @@
 
 G_BEGIN_DECLS
 
-/**
- * GnmRenderedValue:
- */
 struct _GnmRenderedValue {
 	PangoLayout *layout;
 
@@ -57,6 +54,28 @@ void              gnm_rendered_value_remeasure (GnmRenderedValue *rv);
 /* Return the value as a single string without format infomation.  */
 char const *gnm_rendered_value_get_text (GnmRenderedValue const * rv);
 
+/* ------------------------------------------------------------------------- */
+
+struct _GnmRenderedValueCollection {
+	PangoContext *context;
+
+	gsize size;
+	GHashTable *values;
+};
+
+GnmRenderedValueCollection *gnm_rvc_new (PangoContext *context,
+					 gsize size);
+void gnm_rvc_free (GnmRenderedValueCollection *rvc);
+GnmRenderedValue *gnm_rvc_query (GnmRenderedValueCollection *rvc,
+				 GnmCell const *cell);
+void gnm_rvc_store (GnmRenderedValueCollection *rvc,
+		    GnmCell const *cell,
+		    GnmRenderedValue *rv);
+void gnm_rvc_remove (GnmRenderedValueCollection *rvc,
+		     GnmCell const *cell);
+
+/* ------------------------------------------------------------------------- */
+
 void gnm_rendered_value_init (void);
 void gnm_rendered_value_shutdown (void);
 
diff --git a/src/sheet.c b/src/sheet.c
index 3238baa..536b859 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -783,6 +783,7 @@ gnm_sheet_init (Sheet *sheet)
 	/* See also gtk_widget_create_pango_context ().  */
 	sheet->context = gnm_pango_context_get ();
 	sheet->last_zoom_factor_used = -1;  /* Overridden later */
+	sheet->rendered_values = gnm_rvc_new (sheet->context, 5000);
 
 	/* Init menu states */
 	sheet->priv->enable_showhide_detail = TRUE;
@@ -3982,6 +3983,8 @@ gnm_sheet_finalize (GObject *obj)
 	g_free (sheet->priv);
 	g_ptr_array_free (sheet->sheet_views, TRUE);
 
+	gnm_rvc_free (sheet->rendered_values);
+
 	G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
diff --git a/src/sheet.h b/src/sheet.h
index 51c42b9..739d01c 100644
--- a/src/sheet.h
+++ b/src/sheet.h
@@ -54,6 +54,7 @@ struct _Sheet {
 	/* This should eventually be moved to the views.  */
 	double      last_zoom_factor_used;
 	PangoContext *context;
+	GnmRenderedValueCollection *rendered_values;
 
 	GSList      *sheet_objects;	/* List of objects in this sheet */
 	GnmCellPos   max_object_extent;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]