[goffice] Add support for svg images inside gnumeric sheets.



commit 74dc9b514983ee2af7fa232414520c9e9fb51961
Author: Jean Brefort <jean brefort normalesup org>
Date:   Thu Oct 27 17:24:22 2011 +0200

    Add support for svg images inside gnumeric sheets.

 ChangeLog                     |   20 ++++
 goffice/canvas/goc-canvas.c   |   13 +++
 goffice/canvas/goc-canvas.h   |    3 +
 goffice/canvas/goc-image.c    |   92 ++++++++++++++---
 goffice/canvas/goc-image.h    |    1 +
 goffice/goffice.c             |    1 +
 goffice/graph/gog-plot-impl.h |    1 +
 goffice/graph/gog-plot.c      |    9 ++
 goffice/graph/gog-plot.h      |    1 +
 goffice/utils/Makefile.am     |    2 +
 goffice/utils/go-emf.c        |  236 +++++++++++++++++++++++++++++++++++++++++
 goffice/utils/go-emf.h        |   41 +++++++
 goffice/utils/go-image.c      |   38 +++++--
 goffice/utils/go-image.h      |    5 +-
 goffice/utils/go-svg.c        |   29 +++++
 goffice/utils/go-svg.h        |    1 +
 goffice/utils/goffice-utils.h |    2 +
 po/ChangeLog                  |    4 +
 po/POTFILES.in                |    4 +
 tests/mf-demo.c               |    2 +-
 20 files changed, 480 insertions(+), 25 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 3a94486..e318501 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2011-10-27  Jean Brefort  <jean brefort normalesup org>
+
+	* goffice/canvas/goc-canvas.c: new helper functions.
+	* goffice/canvas/goc-canvas.h: ditto.
+	* goffice/canvas/goc-image.c: add crop.
+	* goffice/canvas/goc-image.h: ditto.
+	* goffice/goffice.c: initialize new type.
+	* goffice/graph/gog-plot-impl.h: add get_percent method.
+	* goffice/graph/gog-plot.c: ditto.
+	* goffice/graph/gog-plot.h: ditto.
+	* goffice/utils/Makefile.am: new files.
+	* goffice/utils/go-emf.c: added for a future support of WMF images.
+	* goffice/utils/go-emf.h: ditto.
+	* goffice/utils/go-image.c: add go_image_from_data().
+	* goffice/utils/go-image.h: ditto.
+	* goffice/utils/go-svg.c: ditto.
+	* goffice/utils/go-svg.h: ditto.
+	* goffice/utils/goffice-utils.h: add GOEmf.
+	* tests/mf-demo.c: fixed GOImage usage.
+
 2011-10-26  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* goffice/utils/go-pango-extras.c (go_pango_translate_here): allow for
diff --git a/goffice/canvas/goc-canvas.c b/goffice/canvas/goc-canvas.c
index 5bcf781..eab614e 100644
--- a/goffice/canvas/goc-canvas.c
+++ b/goffice/canvas/goc-canvas.c
@@ -639,3 +639,16 @@ goc_canvas_c2w (GocCanvas *canvas, double x, double y, int *x_, int *y_)
 	if (y_)
 		*y_ = go_fake_round ((y - canvas->scroll_y1) * canvas->pixels_per_unit);
 }
+
+void
+goc_canvas_render (GocCanvas *canvas, cairo_t *cr, double x0, double y0, double x1, double y1)
+{
+	goc_item_draw_region (GOC_ITEM (canvas->root), cr, x0, y0, x1, y1);
+}
+
+void
+goc_canvas_get_bounds (GocCanvas *canvas, double *x0, double *y0, int *x1, int *y1)
+{
+	goc_item_get_bounds (GOC_ITEM (canvas->root), x0, y0, x1, y1);
+}
+                       
diff --git a/goffice/canvas/goc-canvas.h b/goffice/canvas/goc-canvas.h
index c6923a3..e6ab301 100644
--- a/goffice/canvas/goc-canvas.h
+++ b/goffice/canvas/goc-canvas.h
@@ -74,6 +74,9 @@ void		 goc_canvas_set_direction (GocCanvas *canvas, GocDirection direction);
 GocDirection     goc_canvas_get_direction (GocCanvas *canvas);
 void		 goc_canvas_w2c (GocCanvas *canvas, int x, int y, double *x_, double *y_);
 void		 goc_canvas_c2w (GocCanvas *canvas, double x, double y, int *x_, int *y_);
+void		 goc_canvas_render (GocCanvas *canvas, cairo_t *cr, double x0, double y0, double x1, double y1);
+void		 goc_canvas_get_bounds (GocCanvas *canvas, double *x0, double *y0, int *x1, int *y1);
+
 G_END_DECLS
 
 #endif  /* GOC_CANVAS_H */
diff --git a/goffice/canvas/goc-image.c b/goffice/canvas/goc-image.c
index 2629207..e0d3ba2 100644
--- a/goffice/canvas/goc-image.c
+++ b/goffice/canvas/goc-image.c
@@ -39,7 +39,11 @@ enum {
 	IMAGE_PROP_W,
 	IMAGE_PROP_H,
 	IMAGE_PROP_ROTATION,
-	IMAGE_PROP_IMAGE
+	IMAGE_PROP_IMAGE,
+	IMAGE_PROP_CROP_BOTTOM,
+	IMAGE_PROP_CROP_LEFT,
+	IMAGE_PROP_CROP_RIGHT,
+	IMAGE_PROP_CROP_TOP
 };
 
 static GocItemClass *parent_class;
@@ -77,6 +81,19 @@ goc_image_set_property (GObject *gobject, guint param_id,
 		image->image = GO_IMAGE (g_object_ref (g_value_get_object (value)));
 		break;
 
+	case IMAGE_PROP_CROP_BOTTOM:
+		image->crop_bottom = g_value_get_double (value);
+		break;
+	case IMAGE_PROP_CROP_LEFT:
+		image->crop_left = g_value_get_double (value);
+		break;
+	case IMAGE_PROP_CROP_RIGHT:
+		image->crop_right = g_value_get_double (value);
+		break;
+	case IMAGE_PROP_CROP_TOP:
+		image->crop_top = g_value_get_double (value);
+		break;
+
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
 		return; /* NOTE : RETURN */
 	}
@@ -116,6 +133,22 @@ goc_image_get_property (GObject *gobject, guint param_id,
 			g_value_set_object (value, G_OBJECT (image->image));
 		break;
 
+	case IMAGE_PROP_CROP_BOTTOM:
+		g_value_set_double (value, image->crop_bottom);
+		break;
+
+	case IMAGE_PROP_CROP_LEFT:
+		g_value_set_double (value, image->crop_left);
+		break;
+
+	case IMAGE_PROP_CROP_RIGHT:
+		g_value_set_double (value, image->crop_right);
+		break;
+
+	case IMAGE_PROP_CROP_TOP:
+		g_value_set_double (value, image->crop_top);
+		break;
+
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
 		return; /* NOTE : RETURN */
 	}
@@ -135,13 +168,21 @@ static void
 goc_image_update_bounds (GocItem *item)
 {
 	GocImage *image = GOC_IMAGE (item);
+	double w, h;
 	if (!image->image)
 		return;
 	/* FIXME: take rotation into account */
+	w = go_image_get_width (image->image) - image->crop_left - image->crop_right;
+	h = go_image_get_height (image->image) - image->crop_top - image->crop_bottom;
+	if (w <= 0 || h <= 0) {
+		/* nothing visible, put it at origin */
+		item->x0 = item->x1 = image->x;
+		item->y0 = item->y1 = image->y;
+	}
 	item->x0 = floor (image->x);
 	item->y0 = floor (image->y);
-	item->x1 = ceil (image->x + ((image->width > 0.)? image->width: go_image_get_width (image->image)));
-	item->y1 = ceil (image->y + ((image->height > 0.)? image->height: go_image_get_height (image->image)));
+	item->x1 = ceil (image->x + ((image->width > 0.)? image->width: w));
+	item->y1 = ceil (image->y + ((image->height > 0.)? image->height: h));
 }
 
 static double
@@ -149,24 +190,22 @@ goc_image_distance (GocItem *item, double x, double y, GocItem **near_item)
 {
 	GocImage *image = GOC_IMAGE (item);
 	/* FIXME: take rotation into account */
-	double dx, dy, w, h;
+	double dx, dy;
 	if (image->image == NULL)
 		return G_MAXDOUBLE;
-	w = (image->width >= 0.)? image->width: go_image_get_width (image->image);
-	h = (image->height >= 0.)? image->height: go_image_get_height (image->image);
-	if (x < image->x) {
-		dx = image->x - x;
-	} else if (x < image->x + w) {
+	if (x < item->x0) {
+		dx = item->x0 - x;
+	} else if (x < item->x1) {
 		dx = 0;
 	} else {
-		dx = x - image->x - w;
+		dx = x - item->x1;
 	}
-	if (y < image->y) {
-		dy = image->y - y;
-	} else if (y < image->y + h) {
+	if (y < item->y0) {
+		dy = item->y0 - y;
+	} else if (y < item->y1) {
 		dy = 0;
 	} else {
-		dy = y - image->y - h;
+		dy = y - item->y1;
 	}
 	*near_item = item;
 	return hypot (dx, dy);
@@ -202,6 +241,11 @@ goc_image_draw (GocItem const *item, cairo_t *cr)
 	cairo_rotate (cr, image->rotation);
 	if (scalex != 1. || scaley != 1.)
 		cairo_scale (cr, scalex, scaley);
+	cairo_translate (cr, -image->crop_left, -image->crop_top);
+	cairo_rectangle (cr, 0, 0,
+	                 go_image_get_width (image->image) - image->crop_left -  image->crop_right,
+	                 go_image_get_height (image->image) - image->crop_top -  image->crop_bottom);
+	cairo_clip (cr);
 	cairo_move_to (cr, 0, 0);
 	go_image_draw (image->image, cr);
 	cairo_restore (cr);
@@ -251,6 +295,26 @@ goc_image_class_init (GocItemClass *item_klass)
 	                _("The GOImage to display"),
 	                GO_TYPE_IMAGE,
 			GSF_PARAM_STATIC | G_PARAM_READWRITE));
+	g_object_class_install_property (obj_klass, IMAGE_PROP_CROP_BOTTOM,
+	        g_param_spec_double ("crop-bottom", _("Cropped bottom"),
+	                _("The cropped area at the image bottom"),
+	                0., G_MAXDOUBLE, 0.,
+			GSF_PARAM_STATIC | G_PARAM_READWRITE));
+	g_object_class_install_property (obj_klass, IMAGE_PROP_CROP_LEFT,
+	        g_param_spec_double ("crop-left", _("Cropped left"),
+	                _("The cropped area at the image left"),
+	                0., G_MAXDOUBLE, 0.,
+			GSF_PARAM_STATIC | G_PARAM_READWRITE));
+	g_object_class_install_property (obj_klass, IMAGE_PROP_CROP_RIGHT,
+	        g_param_spec_double ("crop-right", _("Cropped right"),
+	                _("The cropped area at the image right"),
+	                0., G_MAXDOUBLE, 0.,
+			GSF_PARAM_STATIC | G_PARAM_READWRITE));
+	g_object_class_install_property (obj_klass, IMAGE_PROP_CROP_TOP,
+	        g_param_spec_double ("crop-top", _("Cropped top"),
+	                _("The cropped area at the image top"),
+	                0., G_MAXDOUBLE, 0.,
+			GSF_PARAM_STATIC | G_PARAM_READWRITE));
 
 	item_klass->update_bounds = goc_image_update_bounds;
 	item_klass->distance = goc_image_distance;
diff --git a/goffice/canvas/goc-image.h b/goffice/canvas/goc-image.h
index d1859a4..d3c8c7d 100644
--- a/goffice/canvas/goc-image.h
+++ b/goffice/canvas/goc-image.h
@@ -31,6 +31,7 @@ struct _GocImage {
 	GocItem base;
 
 	double x, y, width, height, rotation;
+	double crop_left, crop_right, crop_top, crop_bottom;
 	GOImage *image;
 };
 typedef GocItemClass GocImageClass;
diff --git a/goffice/goffice.c b/goffice/goffice.c
index ccef860..83a3571 100644
--- a/goffice/goffice.c
+++ b/goffice/goffice.c
@@ -213,6 +213,7 @@ libgoffice_init (void)
 	(void) GO_TYPE_DATA_SCALAR_VAL;
 	(void) GO_TYPE_DATA_SCALAR_STR;
 	(void) GOG_3D_BOX_TYPE;
+	(void) GO_TYPE_EMF;
 	(void) GO_TYPE_PIXBUF;
 	(void) GO_TYPE_SVG;
 	_gog_themes_init ();
diff --git a/goffice/graph/gog-plot-impl.h b/goffice/graph/gog-plot-impl.h
index cf9d7e1..994b8f3 100644
--- a/goffice/graph/gog-plot-impl.h
+++ b/goffice/graph/gog-plot-impl.h
@@ -77,6 +77,7 @@ typedef struct {
 
 	void       (*update_3d)		(GogPlot *plot);
 	void	   (*guru_helper)	(GogPlot *plot, char const *hint);
+	double	   (*get_percent)       (GogPlot *plot, unsigned series, unsigned index);
 } GogPlotClass;
 
 #define GOG_PLOT_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST ((k), GOG_TYPE_PLOT, GogPlotClass))
diff --git a/goffice/graph/gog-plot.c b/goffice/graph/gog-plot.c
index 59f2b94..badf84e 100644
--- a/goffice/graph/gog-plot.c
+++ b/goffice/graph/gog-plot.c
@@ -942,6 +942,15 @@ void gog_plot_clear_series (GogPlot *plot)
 	}
 }
 
+double
+gog_plot_get_percent_value (GogPlot *plot, unsigned series, unsigned index)
+{
+	GogPlotClass *klass;
+	g_return_val_if_fail (GOG_IS_PLOT (plot), go_nan);
+	klass = GOG_PLOT_GET_CLASS (plot);
+	return (klass->get_percent)? klass->get_percent (plot, series, index): go_nan;
+}
+
 /*****************************************************************************/
 
 #ifdef GOFFICE_WITH_GTK
diff --git a/goffice/graph/gog-plot.h b/goffice/graph/gog-plot.h
index 768f95e..6989d8c 100644
--- a/goffice/graph/gog-plot.h
+++ b/goffice/graph/gog-plot.h
@@ -73,6 +73,7 @@ void	   gog_plot_clear_series	(GogPlot *plot);
 
 int        gog_plot_view_get_data_at_point (GogPlotView *view,
 					    double x, double y, GogSeries **series);
+double	   gog_plot_get_percent_value   (GogPlot *plot, unsigned series, unsigned index);
 
 G_END_DECLS
 
diff --git a/goffice/utils/Makefile.am b/goffice/utils/Makefile.am
index 6142123..7b55bc6 100644
--- a/goffice/utils/Makefile.am
+++ b/goffice/utils/Makefile.am
@@ -14,6 +14,7 @@ libgoffice_utils_la_SOURCES =	\
 	go-image.c		\
 	go-pixbuf.c		\
 	go-svg.c		\
+	go-emf.c		\
 	go-line.c		\
 	go-locale.c		\
 	go-marker.c		\
@@ -48,6 +49,7 @@ libgoffice_utils_la_HEADERS = 	\
 	go-image.h		\
 	go-pixbuf.h		\
 	go-svg.h		\
+	go-emf.h		\
 	go-line.h		\
 	go-locale.h		\
 	go-marker.h		\
diff --git a/goffice/utils/go-emf.c b/goffice/utils/go-emf.c
new file mode 100644
index 0000000..a157713
--- /dev/null
+++ b/goffice/utils/go-emf.c
@@ -0,0 +1,236 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-emf.c - EMF/WMF image support
+ *
+ * Copyright (C) 2011 Jean Brefort (jean brefort normalesup org)
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include "go-emf.h"
+#include <gsf/gsf-utils.h>
+#include <gsf/gsf-impl-utils.h>
+#include <gsf/gsf-input-memory.h>
+#include <gsf/gsf-input-stdio.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+
+struct _GOEmf {
+	GOImage parent;
+	GocCanvas *canvas;
+	gsize data_length;
+};
+
+typedef GOImageClass GOEmfClass;
+
+static GObjectClass *parent_klass;
+
+static gboolean go_emf_parse (GOEmf *emf, GsfInput *input, GError **error);
+
+static void
+go_emf_save (GOImage *image, GsfXMLOut *output)
+{
+	GOEmf *emf = GO_EMF (image);
+	g_return_if_fail (emf);
+	gsf_xml_out_add_base64 (output, NULL,
+			image->data, emf->data_length);
+}
+
+static void
+go_emf_load_attr (G_GNUC_UNUSED GOImage *image, G_GNUC_UNUSED xmlChar const *attr_name, G_GNUC_UNUSED xmlChar const *attr_value)
+{
+	/* nothing to do */
+}
+
+static void
+go_emf_load_data (GOImage *image, GsfXMLIn *xin)
+{
+	GOEmf *emf = GO_EMF (image);
+	emf->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+	image->data = g_malloc (emf->data_length);
+	memcpy (image->data, xin->content->str, emf->data_length);
+	/* FIXME: build the canvas */
+}
+
+static void
+go_emf_draw (GOImage *image, cairo_t *cr)
+{
+	GOEmf *emf = GO_EMF (image);
+	g_return_if_fail (emf && emf->canvas);
+	goc_canvas_render (emf->canvas, cr, 0, 0, image->width, image->height);
+}
+
+static GdkPixbuf *
+go_emf_get_pixbuf (GOImage *image)
+{
+	GOEmf *emf = GO_EMF (image);
+	cairo_surface_t *surface;
+	cairo_t *cr;
+	GdkPixbuf *res = NULL;
+	g_return_val_if_fail (emf, NULL);
+	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, image->width, image->height);
+	cr = cairo_create (surface);
+	goc_canvas_render (emf->canvas, cr, 0, 0, image->width, image->height);
+	cairo_destroy (cr);
+	res = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, image->width, image->height);
+	go_cairo_convert_data_from_pixbuf (gdk_pixbuf_get_pixels (res),
+	                                   cairo_image_surface_get_data (surface),
+	                                   image->width, image->height,
+	                                   cairo_image_surface_get_stride (surface));
+	return res;
+	return NULL; /* FIXME */
+}
+
+static GdkPixbuf *
+go_emf_get_scaled_pixbuf (GOImage *image, int width, int height)
+{
+	GOEmf *emf = GO_EMF (image);
+	cairo_surface_t *surface;
+	cairo_t *cr;
+	GdkPixbuf *res = NULL;
+	g_return_val_if_fail (emf, NULL);
+	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+	cr = cairo_create (surface);
+	cairo_scale (cr, width / image->width, height / image->height);
+	goc_canvas_render (emf->canvas, cr, 0, 0, image->width, image->height);
+	cairo_destroy (cr);
+	res = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+	go_cairo_convert_data_from_pixbuf (gdk_pixbuf_get_pixels (res),
+	                                   cairo_image_surface_get_data (surface),
+	                                   width, height,
+	                                   cairo_image_surface_get_stride (surface));
+	return res;
+}
+
+static gboolean
+go_emf_differ (GOImage *first, GOImage *second)
+{
+	GOEmf *sfirst = GO_EMF (first), *ssecond = GO_EMF (second);
+	if (sfirst->data_length != ssecond->data_length)
+		return TRUE;
+	return memcmp (first->data, second->data, sfirst->data_length);
+}
+
+static void
+go_emf_finalize (GObject *obj)
+{
+	GOEmf *emf = GO_EMF (obj);
+	if (emf->canvas != NULL)
+		g_object_unref (emf->canvas);
+	(parent_klass->finalize) (obj);
+}
+
+static void
+go_emf_class_init (GObjectClass *klass)
+{
+	GOImageClass *image_klass = (GOImageClass *) klass;
+
+	klass->finalize = go_emf_finalize;
+	parent_klass = g_type_class_peek_parent (klass);
+
+	image_klass->save = go_emf_save;
+	image_klass->load_attr = go_emf_load_attr;
+	image_klass->load_data = go_emf_load_data;
+	image_klass->get_pixbuf = go_emf_get_pixbuf;
+	image_klass->get_scaled_pixbuf = go_emf_get_scaled_pixbuf;
+	image_klass->draw = go_emf_draw;
+	image_klass->differ = go_emf_differ;
+}
+
+GSF_CLASS (GOEmf, go_emf,
+	   go_emf_class_init, NULL,
+	   GO_TYPE_IMAGE)
+
+GOEmf *
+go_emf_new_from_file (char const *filename, GError **error)
+{
+#ifdef GOFFICE_EMF_SUPPORT
+	GOEmf *emf = NULL;
+	GOImage *image;
+	GsfInput *input = gsf_input_stdio_new (filename, error);
+	guint8 *data;
+
+	if (input == NULL)
+		return NULL;
+	data = g_malloc (gsf_input_size (input));
+	if (!data || !gsf_input_read (input, emf->data_length, data)) {
+		g_object_unref (emf);
+		g_free (data);
+		if (error)
+			*error = g_error_new (go_error_invalid (), 0,
+			                      _("Could not load the image data"));
+		return NULL;
+	}
+	g_object_unref (input);
+	emf = g_object_new (GO_TYPE_EMF, NULL);
+	emf->data_length = gsf_input_size (input);
+	g_object_unref (input);
+
+	image = GO_IMAGE (emf);
+	image->data = data;
+	input = gsf_input_memory_new (data, emf->data_length, FALSE);
+	if (!go_emf_parse (emf, input, error)) {
+		g_object_unref (emf);
+		emf = NULL;
+	}
+	g_object_unref (input);
+
+	return emf;
+#else
+	return NULL;
+#endif
+}
+
+GOEmf *
+go_emf_new_from_data (char const *data, size_t length, GError **error)
+{
+#ifdef GOFFICE_EMF_SUPPORT
+	GOEmf *emf = NULL;
+	GsfInput *input = gsf_input_memory_new (data, length, FALSE);
+
+	if (input == NULL) {
+		if (error)
+			*error = g_error_new (go_error_invalid (), 0,
+			                      _("Could not input the image data"));
+		return NULL;
+	}
+	emf = g_object_new (GO_TYPE_EMF, NULL);
+	emf->data_length = gsf_input_size (input);
+	if (!go_emf_parse (emf, input, error)) {
+		g_object_unref (emf);
+		emf = NULL;
+	} else {
+		GOImage *image = GO_IMAGE (emf);
+		image->data = g_malloc (length);
+		memcpy (image->data, data, length);
+	}
+	g_object_unref (input);
+	return emf;
+#else
+	return NULL;
+#endif
+}
+
+/******************************************************************************
+ * Parsing code                                                               *
+ * ****************************************************************************/
+
+static gboolean go_emf_parse (GOEmf *emf, GsfInput *input, GError **error)
+{
+	/* FIXME: implement */
+	return FALSE;
+}
diff --git a/goffice/utils/go-emf.h b/goffice/utils/go-emf.h
new file mode 100644
index 0000000..6cd3960
--- /dev/null
+++ b/goffice/utils/go-emf.h
@@ -0,0 +1,41 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-emf.h - EMF/WMF image support
+ *
+ * Copyright (C) 2011 Jean Brefort (jean brefort normalesup org)
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
+ * USA
+ */
+ 
+#ifndef GO_EMF_H
+#define GO_EMF_H
+
+#include <goffice/goffice.h>
+
+G_BEGIN_DECLS
+
+#define GO_TYPE_EMF	(go_emf_get_type ())
+#define GO_EMF(o)	(G_TYPE_CHECK_INSTANCE_CAST ((o), GO_TYPE_EMF, GOEmf))
+#define GO_IS_EMF(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GO_TYPE_EMF))
+
+GType go_emf_get_type (void);
+
+GOEmf *go_emf_new_from_file (char const *filename, GError **error);
+GOEmf *go_emf_new_from_data (char const *data, size_t length, GError **error);
+
+G_END_DECLS
+
+#endif /* GO_EMF_H */
diff --git a/goffice/utils/go-image.c b/goffice/utils/go-image.c
index 5be0fba..2c61d89 100644
--- a/goffice/utils/go-image.c
+++ b/goffice/utils/go-image.c
@@ -362,10 +362,9 @@ go_image_class_init (GObjectClass *klass)
 							    0, G_MAXUINT16, 0, G_PARAM_READWRITE));
 }
 
-GSF_CLASS_FULL (GOImage, go_image,
-		NULL, NULL,
-		go_image_class_init, NULL, NULL,
-		G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {})
+GSF_CLASS_ABSTRACT (GOImage, go_image,
+		go_image_class_init, NULL,
+		G_TYPE_OBJECT)
 
 void
 go_image_draw (GOImage *image, cairo_t *cr)
@@ -405,7 +404,7 @@ go_image_get_scaled_pixbuf (GOImage *image, int width, int height)
 }
 
 GOImage *
-go_image_new_from_file (const char *filename, GError **error)
+go_image_new_from_file (char const *filename, GError **error)
 {
 	char *mime, *name;
 	GOImageFormat format;
@@ -427,12 +426,12 @@ go_image_new_from_file (const char *filename, GError **error)
 	switch (format) {
 	case GO_IMAGE_FORMAT_SVG:
 		return GO_IMAGE (go_svg_new_from_file (filename, error));
-	case GO_IMAGE_FORMAT_PDF:
-	case GO_IMAGE_FORMAT_PS:
 	case GO_IMAGE_FORMAT_EMF:
 	case GO_IMAGE_FORMAT_WMF:
+		return GO_IMAGE (go_emf_new_from_file (filename, error));
+	case GO_IMAGE_FORMAT_PDF:
+	case GO_IMAGE_FORMAT_PS:
 	case GO_IMAGE_FORMAT_EPS:
-		break;
 	case GO_IMAGE_FORMAT_UNKNOWN:
 		break;
 	default: {
@@ -447,6 +446,29 @@ go_image_new_from_file (const char *filename, GError **error)
 	return NULL;
 }
 
+GOImage	*
+go_image_new_from_data (char const *type, guint8 const *data, gsize length, GError **error)
+{
+	char *real_type = NULL;
+	GOImage *image = NULL;
+	if (type == NULL || *type == 0) {
+		char *mime_type = go_get_mime_type_for_data (data, length);
+		real_type = go_mime_to_image_format (mime_type);
+		g_free (mime_type);
+		type = real_type;
+	}
+	g_return_val_if_fail (type != NULL, NULL);
+	if (!strcmp (type, "svg")) {
+		image = GO_IMAGE (go_svg_new_from_data (data, length, error));
+	} else if (!strcmp (type, "emf") || !strcmp (type, "wmf")) {
+		image = GO_IMAGE (go_emf_new_from_data (data, length, error));
+	} else {
+		/* FIXME: pixbuf */
+	}
+	g_free (real_type);
+	return image;
+}
+
 guint8 *
 go_image_get_pixels (GOImage *image)
 {
diff --git a/goffice/utils/go-image.h b/goffice/utils/go-image.h
index 6c1f7e1..59a0a8f 100644
--- a/goffice/utils/go-image.h
+++ b/goffice/utils/go-image.h
@@ -89,13 +89,14 @@ typedef struct {
 	gboolean (*differ) (GOImage *first, GOImage *second);
 } GOImageClass;
 
-GOImage 	*go_image_new_from_pixbuf 	(GdkPixbuf *pixbuf);
 GdkPixbuf const *go_image_get_thumbnail		(GOImage *image);
 GdkPixbuf       *go_image_get_pixbuf		(GOImage *image);
 GdkPixbuf       *go_image_get_scaled_pixbuf	(GOImage *image, int width, int height);
 void		 go_image_draw			(GOImage *image, cairo_t *cr);
 
-GOImage 	*go_image_new_from_file 	(const char *filename, GError **error);
+GOImage 	*go_image_new_from_file 	(char const *filename, GError **error);
+GOImage 	*go_image_new_from_data 	(char const *type, guint8 const *data, gsize length, GError **error);
+
 guint8 		*go_image_get_pixels 		(GOImage *image);
 void 		 go_image_fill 			(GOImage *image, GOColor color);
 
diff --git a/goffice/utils/go-svg.c b/goffice/utils/go-svg.c
index c2c84a3..712a0aa 100644
--- a/goffice/utils/go-svg.c
+++ b/goffice/utils/go-svg.c
@@ -166,6 +166,7 @@ go_svg_new_from_file (char const *filename, GError **error)
 	data = g_malloc (svg->data_length);
 	if (!data || !gsf_input_read (input, svg->data_length, data)) {
 		g_object_unref (svg);
+		g_free (data);
 		return NULL;
 	}
 	image = GO_IMAGE (svg);
@@ -180,3 +181,31 @@ go_svg_new_from_file (char const *filename, GError **error)
 	image->height = dim.height;
 	return svg;
 }
+
+GOSvg *
+go_svg_new_from_data (char const *data, size_t length, GError **error)
+{
+	GOSvg *svg;
+	GOImage *image;
+	RsvgDimensionData dim;
+
+	g_return_val_if_fail (data != NULL && length != 0, NULL);
+	svg = g_object_new (GO_TYPE_SVG, NULL);
+	svg->data_length = length;
+	image = GO_IMAGE (svg);
+	image->data = g_malloc (length);
+	if (image->data == NULL) {
+		g_object_unref (svg);
+		return NULL;
+	}
+	memcpy (image->data, data, length);
+	svg->handle = rsvg_handle_new_from_data (image->data, svg->data_length, error);
+	if (svg->handle == NULL) {
+		g_object_unref (svg);
+		return NULL;
+	}
+	rsvg_handle_get_dimensions (svg->handle, &dim);
+	image->width = dim.width;
+	image->height = dim.height;
+	return svg;
+}
diff --git a/goffice/utils/go-svg.h b/goffice/utils/go-svg.h
index baa8395..2cadb24 100644
--- a/goffice/utils/go-svg.h
+++ b/goffice/utils/go-svg.h
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
 GType go_svg_get_type (void);
 
 GOSvg *go_svg_new_from_file (char const *filename, GError **error);
+GOSvg *go_svg_new_from_data (char const *data, size_t length, GError **error);
 
 G_END_DECLS
 
diff --git a/goffice/utils/goffice-utils.h b/goffice/utils/goffice-utils.h
index 58208f2..7030a16 100644
--- a/goffice/utils/goffice-utils.h
+++ b/goffice/utils/goffice-utils.h
@@ -37,6 +37,7 @@ typedef struct _GODateConventions	GODateConventions;
 typedef struct _GOImage			GOImage;
 typedef struct _GOPixbuf		GOPixbuf;
 typedef struct _GOSvg			GOSvg;
+typedef struct _GOEmf			GOEmf;
 typedef struct _GOPath GOPath;
 typedef struct _GOString GOString;
 typedef struct _GOStyle			GOStyle;
@@ -117,6 +118,7 @@ G_END_DECLS
 #include <goffice/utils/go-image.h>
 #include <goffice/utils/go-pixbuf.h>
 #include <goffice/utils/go-svg.h>
+#include <goffice/utils/go-emf.h>
 #include <goffice/utils/go-libxml-extras.h>
 #include <goffice/utils/go-line.h>
 #include <goffice/utils/go-locale.h>
diff --git a/po/ChangeLog b/po/ChangeLog
index 6b0e3d0..70c9a34 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,7 @@
+2011-10-27  Jean Brefort  <jean brefort normalesup org>
+
+	* POTFILES.in: fixed file list.
+
 2011-07-31  Morten Welinder <terra gnome org>
 
 	* Release 0.8.17
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 91b55dc..4f357fc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -43,6 +43,7 @@ goffice/canvas/goc-component.c
 goffice/canvas/goc-ellipse.c
 goffice/canvas/goc-graph.c
 goffice/canvas/goc-group.c
+goffice/canvas/goc-image.c
 goffice/canvas/goc-item.c
 goffice/canvas/goc-line.c
 goffice/canvas/goc-path.c
@@ -186,6 +187,7 @@ goffice/gtk/go-format-sel.c
 goffice/gtk/go-format-sel.h
 [type: gettext/glade]goffice/gtk/go-image-save-dialog-extra.ui
 [type: gettext/glade]goffice/gtk/go-image-sel.ui
+goffice/gtk/go-image-sel.c
 goffice/gtk/go-locale-sel.c
 goffice/gtk/go-locale-sel.h
 goffice/gtk/go-optionmenu.c
@@ -222,6 +224,7 @@ goffice/utils/datetime.h
 goffice/utils/formats.c
 goffice/utils/go-color.c
 goffice/utils/go-color.h
+goffice/utils/go-emf.c
 goffice/utils/go-file.c
 goffice/utils/go-file.h
 goffice/utils/go-font.c
@@ -246,6 +249,7 @@ goffice/utils/go-marker.c
 goffice/utils/go-marker.h
 goffice/utils/go-pattern.c
 goffice/utils/go-pattern.h
+goffice/utils/go-pixbuf.c
 goffice/utils/go-style.c
 goffice/utils/go-style.h
 [type: gettext/glade]goffice/utils/go-style-prefs.ui
diff --git a/tests/mf-demo.c b/tests/mf-demo.c
index c35bc03..ca15d81 100644
--- a/tests/mf-demo.c
+++ b/tests/mf-demo.c
@@ -644,7 +644,7 @@ fill (Page *pg, GocItem *item)
 		style->fill.pattern.fore = GO_COLOR_FROM_RGB (b->clr.r, b->clr.g, b->clr.b);
 		break;
 	case 3:
-		style->fill.image.image = go_image_new_from_pixbuf (b->bdata.data);
+		style->fill.image.image = GO_IMAGE (go_pixbuf_new_from_pixbuf (b->bdata.data));
 		style->fill.image.type = GO_IMAGE_WALLPAPER;
 		style->fill.type = GO_STYLE_FILL_IMAGE;
 		break;



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