goffice r2165 - in trunk: . goffice/app goffice/graph goffice/utils
- From: jbrefort svn gnome org
- To: svn-commits-list gnome org
- Subject: goffice r2165 - in trunk: . goffice/app goffice/graph goffice/utils
- Date: Sun, 3 Aug 2008 10:08:28 +0000 (UTC)
Author: jbrefort
Date: Sun Aug 3 10:08:28 2008
New Revision: 2165
URL: http://svn.gnome.org/viewvc/goffice?rev=2165&view=rev
Log:
2008-08-03 Jean Brefort <jean brefort normalesup org>
* configure.in: add a test for g_hash_table_iter_init.
* goffice/app/go-doc-impl.h: serialize images in charts. [#348780]
* goffice/app/go-doc.c: ditto.
* goffice/app/go-doc.h: ditto.
* goffice/graph/gog-chart-impl.h: removed unused 3d params.
* goffice/graph/gog-graph.c: serialize images in charts.
* goffice/graph/gog-object.c: ditto.
* goffice/graph/gog-object.h:ditto.
* goffice/graph/gog-style.c: ditto.
* goffice/graph/gog-styled-object.c: ditto.
* goffice/utils/go-image.c: ditto.
* goffice/utils/go-image.h: ditto.
Modified:
trunk/ChangeLog
trunk/NEWS
trunk/configure.in
trunk/goffice/app/go-doc-impl.h
trunk/goffice/app/go-doc.c
trunk/goffice/app/go-doc.h
trunk/goffice/graph/gog-chart-impl.h
trunk/goffice/graph/gog-graph.c
trunk/goffice/graph/gog-object.c
trunk/goffice/graph/gog-object.h
trunk/goffice/graph/gog-style.c
trunk/goffice/graph/gog-styled-object.c
trunk/goffice/utils/go-image.c
trunk/goffice/utils/go-image.h
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Aug 3 10:08:28 2008
@@ -1,6 +1,7 @@
goffice 0.7.1:
Jean:
+ * Serialize images used as background in charts. [#348780]
* Fix plot engines memory leaks. [#542506]
* Fix gog_style_font_sax_save() writes unescaped font name. [#543986]
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Sun Aug 3 10:08:28 2008
@@ -371,7 +371,7 @@
SAVE_LIBS=$LIBS
LIBS="$GOFFICE_LIBS $LIBS"
AC_CHECK_FUNCS(cairo_surface_set_fallback_resolution cairo_ps_surface_set_eps)
-AC_CHECK_FUNCS(g_file_new_for_commandline_arg g_file_new_for_uri)
+AC_CHECK_FUNCS(g_file_new_for_commandline_arg g_file_new_for_uri g_hash_table_iter_init)
LIBS=$SAVE_LIBS
SAVE_CFLAGS=$CFLAGS
Modified: trunk/goffice/app/go-doc-impl.h
==============================================================================
--- trunk/goffice/app/go-doc-impl.h (original)
+++ trunk/goffice/app/go-doc-impl.h Sun Aug 3 10:08:28 2008
@@ -33,6 +33,7 @@
gboolean modified;
gboolean pristine;
GHashTable *images;
+ GHashTable *imagebuf; /* used when loading/saving images */
};
typedef struct {
Modified: trunk/goffice/app/go-doc.c
==============================================================================
--- trunk/goffice/app/go-doc.c (original)
+++ trunk/goffice/app/go-doc.c Sun Aug 3 10:08:28 2008
@@ -26,8 +26,11 @@
#include <gsf/gsf-doc-meta-data.h>
#include <gsf/gsf-impl-utils.h>
+#include <gsf/gsf-libxml.h>
#include <glib/gi18n.h>
+#include <string.h>
+
enum {
PROP_0,
PROP_URI,
@@ -292,6 +295,7 @@
NULL;
}
+#ifndef HAVE_G_HASH_TABLE_ITER_INIT
struct check_for_pixbuf {
GOImage *src_image;
GOImage *dst_image;
@@ -308,6 +312,7 @@
cl->dst_image = img;
}
}
+#endif
GOImage *
go_doc_add_image (GODoc *doc, char const *id, GOImage *image)
@@ -315,19 +320,33 @@
GOImage *img;
int i = 0;
char *new_id;
+#ifdef HAVE_G_HASH_TABLE_ITER_INIT
+ GHashTableIter iter;
+ char const *key;
+#else
struct check_for_pixbuf cl;
+#endif
if (doc->images == NULL)
doc->images = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
/* check if the image is already there */
+#ifdef HAVE_G_HASH_TABLE_ITER_INIT
+ g_hash_table_iter_init (&iter, doc->images);
+ while (g_hash_table_iter_next (&iter, (void**) &key, (void**) &img))
+ if (go_image_same_pixbuf (image, img))
+ return img;
+#else
cl.src_image = image;
cl.dst_image = NULL;
g_hash_table_foreach (doc->images, check_for_pixbuf, &img);
if (cl.dst_image)
return cl.dst_image;
+#endif
+ if (!id || !*id)
+ id = _("Image");
/* now check if the id is not a duplicate */
if (g_hash_table_lookup (doc->images, id)) {
while (1) {
@@ -350,14 +369,128 @@
return doc->images;
}
+void
+go_doc_init_write (GODoc *doc, GsfXMLOut *output)
+{
+ if (doc->imagebuf != NULL)
+ g_critical ("Images buffer should be NULL");
+ doc->imagebuf = g_hash_table_new (g_str_hash, g_str_equal);
+ g_object_set_data (G_OBJECT (gsf_xml_out_get_output (output)), "document", doc);
+}
+
+void
+go_doc_init_read (GODoc *doc, GsfInput *input)
+{
+ if (doc->imagebuf != NULL)
+ g_critical ("Images buffer should be NULL");
+ doc->imagebuf = g_hash_table_new (g_str_hash, g_str_equal);
+ g_object_set_data (G_OBJECT (input), "document", doc);
+}
+
+static void
+save_image_cb (gpointer key, gpointer img_, gpointer user)
+{
+ go_image_save ((GOImage *) img_, (GsfXMLOut *) user);
+}
+
+void
+go_doc_write (GODoc *doc, GsfXMLOut *output)
+{
+ gsf_xml_out_start_element (output, "GODoc");
+ g_hash_table_foreach (doc->imagebuf, save_image_cb, output);
+ gsf_xml_out_end_element (output);
+ g_hash_table_destroy (doc->imagebuf);
+ doc->imagebuf = NULL;
+}
+
+void
+go_doc_save_image (GODoc *doc, char const *id)
+{
+ if (!doc)
+ return;
+ if (!g_hash_table_lookup (doc->imagebuf, id)) {
+ GOImage *image = g_hash_table_lookup (doc->images, id);
+ if (image)
+ g_hash_table_insert (doc->imagebuf, (gpointer) id, image);
+ }
+}
+
static void
-init_func (gpointer key, gpointer value, gpointer data)
+load_image (GsfXMLIn *xin, xmlChar const **attrs)
{
- //go_image_init_save ((GOImage*) value);
+ GODoc *doc = GO_DOC (xin->user_state);
+ GOImage *image;
+ xmlChar const **attr = attrs;
+ while (*attr && strcmp (*attr, "name"))
+ attr += 2;
+ if (!attr)
+ return;
+ image = (GOImage *) g_hash_table_lookup (doc->imagebuf, attr[1]);
+ if (!image) /* this should not occur, but if it does, we might want to load the image? */
+ return;
+ go_image_load_attrs (image, xin, attrs);
+ g_object_set_data (G_OBJECT (doc), "new image", image);
+}
+
+static void
+load_image_data (GsfXMLIn *xin, GsfXMLBlob *unknown)
+{
+ GODoc *doc = GO_DOC (xin->user_state);
+ GOImage *image = GO_IMAGE (g_object_get_data (G_OBJECT (doc), "new image")), *real;
+ g_return_if_fail (image != NULL);
+ go_image_load_data (image, xin);
+ real = go_doc_add_image (doc, go_image_get_name (image), image);
+ g_hash_table_remove (doc->imagebuf, (gpointer) go_image_get_name (image));
+ /* We have an issue if the image already existed and this can happen on pasting
+ or if one day, we implement merging two documents (import a workbook as new sheets
+ in an existing workbook). At the moment, I don't see any way to tell the clients
+ to reference the image stored in the document instead of the one created by
+ go_doc_image_fetch, so let's just make certain they share the same id. Anyway
+ this should not happen very often (may be with a company logo?) and it is not so harmful
+ since the duplicationwill not survive serialization. (Jean)
+ */
+ if (real == image)
+ g_object_unref (image);
+ else
+ go_image_set_name (image, go_image_get_name (real));
+ g_object_set_data (G_OBJECT (doc), "new image", NULL);
+
+}
+
+void
+go_doc_read (GODoc *doc, GsfXMLIn *xin, xmlChar const **attrs)
+{
+ static GsfXMLInNode const dtd[] = {
+ GSF_XML_IN_NODE (DOC, DOC,
+ -1, "GODoc",
+ FALSE, NULL, NULL),
+ GSF_XML_IN_NODE (DOC, IMAGE,
+ -1, "GOImage",
+ GSF_XML_CONTENT,
+ &load_image, &load_image_data),
+ GSF_XML_IN_NODE_END
+ };
+ static GsfXMLInDoc *xmldoc = NULL;
+ if (NULL == xmldoc)
+ xmldoc = gsf_xml_in_doc_new (dtd, NULL);
+ gsf_xml_in_push_state (xin, xmldoc, doc, NULL, attrs);
}
void
-go_doc_init_write (GODoc *doc)
+go_doc_end_read (GODoc *doc)
{
- g_hash_table_foreach (doc->images, init_func, NULL);
+ g_hash_table_destroy (doc->imagebuf);
+ doc->imagebuf = NULL;
+}
+
+GOImage*
+go_doc_image_fetch (GODoc *doc, char const *id)
+{
+ GOImage *image = g_hash_table_lookup (doc->imagebuf, id);
+ if (!image) {
+ image = g_object_new (GO_IMAGE_TYPE, NULL);
+ go_image_set_name (image, id);
+ g_hash_table_insert (doc->imagebuf, (gpointer) go_image_get_name (image), image);
+ }
+ return image;
}
Modified: trunk/goffice/app/go-doc.h
==============================================================================
--- trunk/goffice/app/go-doc.h (original)
+++ trunk/goffice/app/go-doc.h Sun Aug 3 10:08:28 2008
@@ -66,7 +66,13 @@
GOImage *go_doc_get_image (GODoc *doc, char const *id);
GOImage *go_doc_add_image (GODoc *doc, char const *id, GOImage *image);
GHashTable *go_doc_get_images (GODoc *doc);
-void go_doc_init_write (GODoc *doc);
+void go_doc_init_write (GODoc *doc, GsfXMLOut *output);
+void go_doc_write (GODoc *doc, GsfXMLOut *output);
+void go_doc_save_image (GODoc *doc, char const *id);
+void go_doc_init_read (GODoc *doc, GsfInput *input);
+void go_doc_read (GODoc *doc, GsfXMLIn *xin, xmlChar const **attrs);
+void go_doc_end_read (GODoc *doc);
+GOImage *go_doc_image_fetch (GODoc *doc, char const *id);
G_END_DECLS
Modified: trunk/goffice/graph/gog-chart-impl.h
==============================================================================
--- trunk/goffice/graph/gog-chart-impl.h (original)
+++ trunk/goffice/graph/gog-chart-impl.h Sun Aug 3 10:08:28 2008
@@ -29,8 +29,6 @@
G_BEGIN_DECLS
-typedef struct _GogChart3dParms GogChart3dParms;
-
struct _GogChart {
GogOutlinedObject base;
@@ -47,7 +45,6 @@
GogViewAllocation plot_area;
gboolean is_plot_area_manual;
- GogChart3dParms *p3d;
};
typedef GogOutlinedObjectClass GogChartClass;
Modified: trunk/goffice/graph/gog-graph.c
==============================================================================
--- trunk/goffice/graph/gog-graph.c (original)
+++ trunk/goffice/graph/gog-graph.c Sun Aug 3 10:08:28 2008
@@ -89,14 +89,18 @@
break;
case GRAPH_PROP_DOCUMENT: {
GObject *obj = g_value_get_object (value);
+ if ((GODoc *) obj == graph->doc)
+ break;
/* if (graph->doc) {
g_object_unref (graph->doc);
graph->doc = NULL;
}
if (IS_GO_DOC (obj))
graph->doc = (GODoc *) g_object_ref (obj);*/
- if (IS_GO_DOC (obj))
+ if (IS_GO_DOC (obj)) {
graph->doc = (GODoc *) obj;
+ gog_object_document_changed (GOG_OBJECT (graph), graph->doc);
+ }
break;
}
Modified: trunk/goffice/graph/gog-object.c
==============================================================================
--- trunk/goffice/graph/gog-object.c (original)
+++ trunk/goffice/graph/gog-object.c Sun Aug 3 10:08:28 2008
@@ -1937,3 +1937,13 @@
(gpointer )roles[i].id, (gpointer) (roles + i));
}
}
+
+void
+gog_object_document_changed (GogObject *obj, GODoc *doc)
+{
+ GSList *ptr;
+ if (GOG_OBJECT_GET_CLASS (obj)->document_changed != NULL)
+ GOG_OBJECT_GET_CLASS (obj)->document_changed (obj, doc);
+ for (ptr = obj->children; ptr != NULL; ptr = ptr->next)
+ gog_object_document_changed (GOG_OBJECT (ptr->data), doc);
+}
Modified: trunk/goffice/graph/gog-object.h
==============================================================================
--- trunk/goffice/graph/gog-object.h (original)
+++ trunk/goffice/graph/gog-object.h Sun Aug 3 10:08:28 2008
@@ -119,6 +119,7 @@
GogEditor *editor,
GogDataAllocator *dalloc,
GOCmdContext *cc);
+ void (*document_changed)(GogObject *obj, GODoc *doc);
/* signals */
void (*changed) (GogObject *obj, gboolean size);
@@ -198,6 +199,8 @@
GogObjectRole const *roles, unsigned int n_roles);
void gog_object_request_editor_update (GogObject *obj);
+void gog_object_document_changed (GogObject *obj, GODoc *doc);
+
G_END_DECLS
#endif /* GOG_OBJECT_H */
Modified: trunk/goffice/graph/gog-style.c
==============================================================================
--- trunk/goffice/graph/gog-style.c (original)
+++ trunk/goffice/graph/gog-style.c Sun Aug 3 10:08:28 2008
@@ -21,6 +21,7 @@
*/
#include <goffice/goffice-config.h>
+#include <goffice/app/go-doc.h>
#include <goffice/graph/gog-style.h>
#include <goffice/graph/gog-styled-object.h>
#include <goffice/math/go-math.h>
@@ -1399,7 +1400,8 @@
/* FIXME : type is not a good characterization */
gsf_xml_out_add_cstr_unchecked (output, "type",
image_tiling_as_str (style->fill.image.type));
-/* TODO save the pixels */
+ gsf_xml_out_add_cstr (output, "name", go_image_get_name (style->fill.image.image));
+ go_doc_save_image ((GODoc *) g_object_get_data (G_OBJECT (gsf_xml_out_get_output (output)), "document"), go_image_get_name (style->fill.image.image));
gsf_xml_out_end_element (output);
break;
default:
@@ -1717,13 +1719,15 @@
gog_style_sax_load_fill_image (GsfXMLIn *xin, xmlChar const **attrs)
{
GogStyle *style = GOG_STYLE (xin->user_state);
+ GODoc *doc = (GODoc *) g_object_get_data (G_OBJECT (gsf_xml_in_get_input (xin)), "document");
g_return_if_fail (style->fill.type == GOG_FILL_STYLE_IMAGE);
+ g_return_if_fail (IS_GO_DOC (doc));
/* TODO: load the pixels */
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (0 == strcmp (attrs[0], "type")) {
style->fill.image.type = str_as_image_tiling (attrs[1]);
- break;
- }
+ } else if (0 == strcmp (attrs[0], "name"))
+ style->fill.image.image = g_object_ref (go_doc_image_fetch (doc, attrs[1]));
}
static void
@@ -1843,7 +1847,7 @@
&gog_style_sax_load_fill_gradient, NULL),
GSF_XML_IN_NODE (STYLE_FILL, FILL_IMAGE,
-1, "image",
- GSF_XML_CONTENT,
+ GSF_XML_NO_CONTENT,
&gog_style_sax_load_fill_image, NULL),
GSF_XML_IN_NODE (STYLE, STYLE_MARKER,
-1, "marker",
@@ -2116,6 +2120,11 @@
return cairo_pattern_create_rgba (1, 1, 1, 1);
cr_pattern = go_image_create_cairo_pattern (style->fill.image.image);
+ if (cr_pattern == NULL) {
+ /* don't reference anymore an invalid image */
+ ((GogStyle *) style)->fill.image.image = NULL;
+ return cairo_pattern_create_rgba (1, 1, 1, 1);
+ }
g_object_get (style->fill.image.image, "width", &w, "height", &h, NULL);
cairo_pattern_set_extend (cr_pattern, CAIRO_EXTEND_REPEAT);
switch (style->fill.image.type) {
Modified: trunk/goffice/graph/gog-styled-object.c
==============================================================================
--- trunk/goffice/graph/gog-styled-object.c (original)
+++ trunk/goffice/graph/gog-styled-object.c Sun Aug 3 10:08:28 2008
@@ -44,6 +44,32 @@
static GObjectClass *parent_klass;
static void
+gog_styled_object_document_changed (GogObject *obj, GODoc *doc)
+{
+ GogStyledObject *gso = GOG_STYLED_OBJECT (obj);
+ GogStyle *style = gso->style;
+ if ((style->interesting_fields & GOG_STYLE_FILL) &&
+ (style->fill.type == GOG_FILL_STYLE_IMAGE) &&
+ (style->fill.image.image != NULL)) {
+ GOImage *image;
+ char *id = g_strdup (go_image_get_name (style->fill.image.image));
+ /* remove the (nnn) modifier if any */
+ int i = strlen (id) - 1;
+ if (id[i] == ')') {
+ i--;
+ while (id[i] >= '0' && id[i] <= '9')
+ i--;
+ if (id[i] == '(')
+ id[i] = 0;
+ }
+ image = go_doc_add_image (doc, id, style->fill.image.image);
+ g_free (id);
+ g_object_unref (style->fill.image.image);
+ style->fill.image.image = image;
+ }
+}
+
+static void
gog_styled_object_set_property (GObject *obj, guint param_id,
GValue const *value, GParamSpec *pspec)
{
@@ -154,6 +180,7 @@
gobject_klass->finalize = gog_styled_object_finalize;
gog_klass->populate_editor = styled_object_populate_editor;
gog_klass->parent_changed = gog_styled_object_parent_changed;
+ gog_klass->document_changed = gog_styled_object_document_changed;
style_klass->init_style = gog_styled_object_init_style;
g_object_class_install_property (gobject_klass, STYLED_OBJECT_PROP_STYLE,
Modified: trunk/goffice/utils/go-image.c
==============================================================================
--- trunk/goffice/utils/go-image.c (original)
+++ trunk/goffice/utils/go-image.c Sun Aug 3 10:08:28 2008
@@ -25,6 +25,7 @@
#include <goffice/utils/go-cairo.h>
#include <glib/gi18n-lib.h>
#include <string.h>
+#include <gsf/gsf-utils.h>
#include <gsf/gsf-impl-utils.h>
#include <glib/gi18n-lib.h>
@@ -571,7 +572,9 @@
{
g_return_val_if_fail (image != NULL, NULL);
if (!image->pixbuf)
- return NULL; /* we might build the pixbuf if necessary */
+ go_image_get_pixbuf (image);
+ if (!image->pixbuf)
+ return NULL;
if (!image->thumbnail) {
int w, h;
if (image->width <= THUMBNAIL_SIZE && image->height <= THUMBNAIL_SIZE)
@@ -664,6 +667,10 @@
int size;
g_return_val_if_fail (IS_GO_IMAGE (first), FALSE);
g_return_val_if_fail (IS_GO_IMAGE (second), FALSE);
+ if (!first->pixbuf)
+ go_image_get_pixbuf (first);
+ if (!second->pixbuf)
+ go_image_get_pixbuf (second);
if (!first->pixbuf || !second->pixbuf)
return FALSE;
if (gdk_pixbuf_get_n_channels (first->pixbuf) != gdk_pixbuf_get_n_channels (second->pixbuf))
@@ -688,3 +695,41 @@
return FALSE;
#endif
}
+
+void
+go_image_save (GOImage *image, GsfXMLOut *output)
+{
+ g_return_if_fail (IS_GO_IMAGE (image) && image->name);
+ gsf_xml_out_start_element (output, "GOImage");
+ gsf_xml_out_add_cstr (output, "name", image->name);
+ gsf_xml_out_add_int (output, "width", image->width);
+ gsf_xml_out_add_int (output, "height", image->height);
+ gsf_xml_out_add_int (output, "rowstride", image->rowstride);
+ gsf_xml_out_add_base64 (output, NULL,
+ go_image_get_pixels (image), image->height * image->rowstride);
+ gsf_xml_out_end_element (output);
+}
+
+void
+go_image_load_attrs (GOImage *image, GsfXMLIn *xin, xmlChar const **attrs)
+{
+ xmlChar const **attr;
+ g_return_if_fail (image != NULL);
+ for (attr = attrs; attr != NULL && attr[0] && attr[1] ; attr += 2)
+ if (0 == strcmp (attr[0], "width"))
+ image->width = strtol (attr[1], NULL, 10);
+ else if (0 == strcmp (attr[0], "height"))
+ image->height= strtol (attr[1], NULL, 10);
+ else if (0 == strcmp (attr[0], "rowstride"))
+ image->rowstride = strtol (attr[1], NULL, 10);
+}
+
+void
+go_image_load_data (GOImage *image, GsfXMLIn *xin)
+{
+ int length;
+ length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+ image->data = g_memdup (xin->content->str, length);
+ image->target_cairo = TRUE;
+}
+
Modified: trunk/goffice/utils/go-image.h
==============================================================================
--- trunk/goffice/utils/go-image.h (original)
+++ trunk/goffice/utils/go-image.h Sun Aug 3 10:08:28 2008
@@ -89,6 +89,10 @@
gboolean go_image_same_pixbuf (GOImage *first, GOImage *second);
+void go_image_save (GOImage *image, GsfXMLOut *output);
+void go_image_load_attrs (GOImage *image, GsfXMLIn *xin, xmlChar const **attrs);
+void go_image_load_data (GOImage *image, GsfXMLIn *xin);
+
G_END_DECLS
#endif /* GO_IMAGE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]