[goffice] More work on EMF support.



commit b2198aac12cb885731cf02b6fd13d1c1b4b692c0
Author: Jean Brefort <jean brefort normalesup org>
Date:   Sat Mar 10 15:46:37 2012 +0100

    More work on EMF support.

 ChangeLog                        |   16 ++++++
 goffice/component/go-component.c |   39 +++++++++++++++-
 goffice/graph/gog-renderer.c     |    2 +-
 goffice/gtk/go-optionmenu.c      |    4 +-
 goffice/utils/go-emf.c           |   95 ++++++++++++++++++++++++++++++-------
 goffice/utils/go-image.c         |    6 ++-
 goffice/utils/go-image.h         |    3 +-
 goffice/utils/go-spectre.c       |   15 ++----
 goffice/utils/go-svg.c           |   33 ++++++-------
 9 files changed, 162 insertions(+), 51 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 95b69b9..9020a79 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2012-03-10  Jean Brefort  <jean brefort normalesup org>
 
+	* goffice/component/go-component.c: add some doc.
+	* goffice/utils/go-emf.c (go_emf_save), (go_emf_load_data),
+	(go_emf_differ), (go_emf_new_from_file), (go_emf_new_from_data),
+	(go_emf_setworldtransform), (go_emf_modifyworldtransform),
+	(go_emf_createpen), (go_emf_polygon16), (go_emf_polyline16),
+	(go_emf_extcreatepen): more implementations and fixes.
+	* goffice/utils/go-image.c (go_image_get_data): new function, replaces
+	obsolete go_image_get_pixels.
+	* goffice/utils/go-image.h: ditto.
+	* goffice/utils/go-spectre.c (go_spectre_save),
+	(go_spectre_load_data), (go_spectre_differ): ditto.
+	* goffice/utils/go-svg.c (go_svg_save), (go_svg_load_data),
+	(go_svg_differ), (go_svg_new_from_file), (go_svg_new_from_data): ditto.
+
+2012-03-10  Jean Brefort  <jean brefort normalesup org>
+
 	* configure.in: add a test for ghostscript to avoid crashes when using
 	libspectre.
 	* goffice/Makefile.am: make introspection build when libgoffice is not
diff --git a/goffice/component/go-component.c b/goffice/component/go-component.c
index b4d08dd..6648494 100644
--- a/goffice/component/go-component.c
+++ b/goffice/component/go-component.c
@@ -457,6 +457,13 @@ editor_destroy_cb (GOComponent *component)
 	component->editor = NULL;
 }
 
+/**
+ * go_component_edit:
+ * @component: #GOComponent
+ *
+ * Opens a top level window editor for the component if it can be edited.
+ * Returns: (transfer none): the editor window or NULL
+ */
 GtkWindow *
 go_component_edit (GOComponent *component)
 {
@@ -497,7 +504,7 @@ go_component_emit_changed (GOComponent *component)
 		go_component_signals [CHANGED], 0);
 }
 
-static GOCmdContext *goc_cc;
+static GOCmdContext *goc_cc = NULL;
 
 void
 go_component_set_command_context (GOCmdContext *cc)
@@ -509,6 +516,11 @@ go_component_set_command_context (GOCmdContext *cc)
 		g_object_ref (goc_cc);
 }
 
+/**
+ * go_component_get_command_context:
+ *
+ * Returns: (transfer none): the command context used for components.
+ */
 GOCmdContext *
 go_component_get_command_context (void)
 {
@@ -658,6 +670,15 @@ _go_component_sax_parser_done (GsfXMLIn *xin, GOCompXMLReadState *state)
 	g_free (state);
 }
 
+/**
+ * go_component_sax_push_parser:
+ * @xin: #GsfInput
+ * @attrs: the current node attributes.
+ * @handler: (scope call): #GOComponentSaxHandler
+ * @user_data: data to pass to @handler
+ *
+ * Loads the component from the xml stream. @handler will be called when done.
+ */
 void
 go_component_sax_push_parser (GsfXMLIn *xin, xmlChar const **attrs,
 				GOComponentSaxHandler handler, gpointer user_data)
@@ -778,6 +799,15 @@ go_component_new_from_uri (char const *uri)
 	return component;
 }
 
+/**
+ * go_component_get_snapshot:
+ * @component: #GOComponent
+ * @type: #GOSnapshotType
+ * @length: where to store the data length
+ *
+ * Returns a snapshot is either svg or png format for the component.
+ * Returns: (transfer none): the snapshot as an arry of bytes.
+ */
 void const *
 go_component_get_snapshot (GOComponent *component, GOSnapshotType *type, size_t *length)
 {
@@ -819,6 +849,13 @@ go_component_export_image (GOComponent *component, GOImageFormat format, GsfOutp
 	return FALSE;
 }
 
+/**
+ * go_component_duplicate:
+ * @component: a #GOComponent
+ *
+ * Duplicates the component.
+ * Returns: (transfer full): the duplicated component.
+ */
 GOComponent *
 go_component_duplicate (GOComponent const *component)
 {
diff --git a/goffice/graph/gog-renderer.c b/goffice/graph/gog-renderer.c
index 6fe9ba2..5fdd567 100644
--- a/goffice/graph/gog-renderer.c
+++ b/goffice/graph/gog-renderer.c
@@ -840,7 +840,7 @@ gog_renderer_draw_marker (GogRenderer *rend, double x, double y)
  * @str: the #GOString to draw
  * @pos: #GogViewAllocation
  * @anchor: #GOAnchorType how to draw relative to @pos
- * @width: if positive, the maximum width to get a multiline string if needed. 
+ * @width: if positive, the maximum width to get a multiline string if needed.
  *
  * Have @rend draw @layout in the at @pos.{x,y} anchored by the @anchor corner.
  * If @pos.w or @pos.h are >= 0 then clip the results to less than that size.
diff --git a/goffice/gtk/go-optionmenu.c b/goffice/gtk/go-optionmenu.c
index 0027750..4ce00dc 100644
--- a/goffice/gtk/go-optionmenu.c
+++ b/goffice/gtk/go-optionmenu.c
@@ -295,10 +295,10 @@ go_option_menu_set_menu (GOOptionMenu *option_menu,
 
 /**
  * go_option_menu_set_history:
- * @selection: a list of indices giving the menu to select. 
+ * @selection: a list of indices giving the menu to select.
  *
  * Selects an item. The last number in the list is the rank of the item to select
- * in its menu and the previous ones are the ranks of the submenus containing 
+ * in its menu and the previous ones are the ranks of the submenus containing
  * the item to select.
  **/
 void
diff --git a/goffice/utils/go-emf.c b/goffice/utils/go-emf.c
index 6067b24..6bdddfd 100644
--- a/goffice/utils/go-emf.c
+++ b/goffice/utils/go-emf.c
@@ -32,7 +32,6 @@
 struct _GOEmf {
 	GOImage parent;
 	GocCanvas *canvas;
-	gsize data_length;
 };
 
 typedef GOImageClass GOEmfClass;
@@ -49,7 +48,7 @@ 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);
+			image->data, image->data_length);
 }
 
 static void
@@ -62,10 +61,20 @@ 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 */
+	GError *error = NULL;
+	GsfInput *input;
+	image->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+	image->data = g_malloc (image->data_length);
+	memcpy (image->data, xin->content->str, image->data_length);
+#ifdef GOFFICE_EMF_SUPPORT
+	input = gsf_input_memory_new (image->data, image->data_length, FALSE);
+	go_emf_parse (emf, input, &error);
+	g_object_unref (input);
+	if (error) {
+		// FIXME: emit at least a warning
+		g_error_free (error);
+	}
+#endif
 }
 
 static void
@@ -121,10 +130,9 @@ go_emf_get_scaled_pixbuf (GOImage *image, int width, int height)
 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)
+	if (first->data_length != second->data_length)
 		return TRUE;
-	return memcmp (first->data, second->data, sfirst->data_length);
+	return memcmp (first->data, second->data, first->data_length);
 }
 
 static void
@@ -192,11 +200,11 @@ go_emf_new_from_file (char const *filename, GError **error)
 	}
 	g_object_unref (input);
 	emf = g_object_new (GO_TYPE_EMF, NULL);
-	emf->data_length = size;
 
 	image = GO_IMAGE (emf);
+	image->data_length = size;
 	image->data = data;
-	input = gsf_input_memory_new (data, emf->data_length, FALSE);
+	input = gsf_input_memory_new (data, image->data_length, FALSE);
 	if (!go_emf_parse (emf, input, error)) {
 		g_object_unref (emf);
 		emf = NULL;
@@ -231,13 +239,13 @@ go_emf_new_from_data (char const *data, size_t length, GError **error)
 		return NULL;
 	}
 	emf = g_object_new (GO_TYPE_EMF, NULL);
-	emf->data_length = gsf_input_size (input);
+	image = GO_IMAGE (emf);
+	image->data_length = gsf_input_size (input);
 	if (!go_emf_parse (emf, input, error)) {
 		g_object_unref (emf);
 		image = NULL;
 	} else {
 		double x0, y0, x1, y1;
-		image = GO_IMAGE (emf);
 		image->data = g_malloc (length);
 		memcpy (image->data, data, length);
 		goc_canvas_get_bounds (emf->canvas, &x0, &y0, &x1, &y1);
@@ -2953,14 +2961,45 @@ go_emf_restoredc (GOEmfState *state)
 static gboolean
 go_emf_setworldtransform (GOEmfState *state)
 {
+	double m11, m12, m21, m22, dx, dy;
 	d_(("setworldtransform\n"));
+	m11 = GSF_LE_GET_FLOAT (state->data);
+	m12 = GSF_LE_GET_FLOAT (state->data + 4);
+	m21 = GSF_LE_GET_FLOAT (state->data + 8);
+	m22 = GSF_LE_GET_FLOAT (state->data + 12);
+	dx = GSF_LE_GET_FLOAT (state->data + 16);
+	dy = GSF_LE_GET_FLOAT (state->data + 20);
+	d_(("\tm11 = %g m12 = %g dx=%g\n\tm21 = %g m22=%g dy=%g\n",
+	    m11, m12, dx, m21, m22, dy));
+	/* FIXME: do something with it */
 	return TRUE;
 }
 
 static gboolean
 go_emf_modifyworldtransform (GOEmfState *state)
 {
+#ifdef DEBUG_EMF_SUPPORT
+	char const *tmas[5] = {
+		NULL,
+		"MWT_IDENTITY",
+		"MWT_LEFTMULTIPLY",
+		"MWT_RIGHTMULTIPLY",
+		"MWT_SET"
+	};
+#endif
+	double m11, m12, m21, m22, dx, dy;
+	unsigned mode;
 	d_(("modifyworldtransform\n"));
+	m11 = GSF_LE_GET_FLOAT (state->data);
+	m12 = GSF_LE_GET_FLOAT (state->data + 4);
+	m21 = GSF_LE_GET_FLOAT (state->data + 8);
+	m22 = GSF_LE_GET_FLOAT (state->data + 12);
+	dx = GSF_LE_GET_FLOAT (state->data + 16);
+	dy = GSF_LE_GET_FLOAT (state->data + 20);
+	mode = GSF_LE_GET_GUINT32 (state + 24);
+	d_(("\tm11 = %g m12 = %g dx=%g\n\tm21 = %g m22=%g dy=%g\n\tmode = %s\n",
+	    m11, m12, dx, m21, m22, dy, tmas[mode]));
+	/* FIXME: do something with it */
 	return TRUE;
 }
 
@@ -3141,9 +3180,6 @@ go_emf_selectobject (GOEmfState *state)
 	return TRUE;
 }
 
-static gboolean
-go_emf_createpen (GOEmfState *state)
-{
 #ifdef DEBUG_EMF_SUPPORT
 char const *dashes[] = {
 "Solid",
@@ -3167,6 +3203,10 @@ char const *cap[]= {
 "flat"
 };
 #endif
+
+static gboolean
+go_emf_createpen (GOEmfState *state)
+{
 	unsigned index;
 	GOEmfPen *pen = g_new0 (GOEmfPen, 1);
 	pen->obj_type = GO_EMF_OBJ_TYPE_PEN;
@@ -3735,7 +3775,7 @@ go_emf_polygon16 (GOEmfState *state)
 	nb_pts = GSF_LE_GET_GUINT32 (state->data + 16);
 	d_(("\t%u points\n", nb_pts));
 	points = goc_points_new (nb_pts);
-	for (n = 0, offset = 20; n < nb_pts; n++, offset += 8) {
+	for (n = 0, offset = 20; n < nb_pts; n++, offset += 4) {
 		go_wmf_read_points (state->data + offset, &x, &y);
 		go_emf_convert_coords (state, &x, &y);
 		points->points[n].x = x;
@@ -3767,7 +3807,7 @@ go_emf_polyline16 (GOEmfState *state)
 	nb_pts = GSF_LE_GET_GUINT32 (state->data + 16);
 	d_(("\t%u points\n", nb_pts));
 	points = goc_points_new (nb_pts);
-	for (n = 0, offset = 20; n < nb_pts; n++, offset += 8) {
+	for (n = 0, offset = 20; n < nb_pts; n++, offset += 4) {
 		go_wmf_read_points (state->data + offset, &x, &y);
 		go_emf_convert_coords (state, &x, &y);
 		points->points[n].x = x;
@@ -3952,7 +3992,26 @@ go_emf_createdibpatternbrushpt (GOEmfState *state)
 static gboolean
 go_emf_extcreatepen (GOEmfState *state)
 {
+	unsigned index/*, offBmi, cbBmi, offBits, cbBits*/;
+	GOEmfPen *pen = g_new0 (GOEmfPen, 1);
+	pen->obj_type = GO_EMF_OBJ_TYPE_PEN;
 	d_(("extcreatepen\n"));
+	index = GSF_LE_GET_GUINT32 (state->data);
+/*	offBmi = GSF_LE_GET_GUINT32 (state->data + 4);
+	cbBmi = GSF_LE_GET_GUINT32 (state->data + 8);
+	offBits = GSF_LE_GET_GUINT32 (state->data + 12);
+	cbBits = GSF_LE_GET_GUINT32 (state->data + 16);
+	if (cbBmi != 0 || cbBits != NULL) {
+		FIXME: load DIB data if any
+	}*/
+	pen->style = GSF_LE_GET_GUINT32 (state->data + 20);
+	pen->width = GSF_LE_GET_GUINT32 (state->data + 24);
+	pen->clr = go_wmf_read_gocolor (state->data + 32);
+	d_(("\tpen index=%u style=%s width=%g color=%08x join=%s cap=%s%s\n",index,
+	    dashes[pen->style&0xf], pen->width, pen->clr,
+	    join[(pen->style&0xf000)>>24], cap[(pen->style&0xf00)>>16],
+	    pen->style&0x00010000? "Geometric": ""));
+	g_hash_table_replace (state->mfobjs, GUINT_TO_POINTER (index), pen);
 	return TRUE;
 }
 
diff --git a/goffice/utils/go-image.c b/goffice/utils/go-image.c
index 14ceb11..66f6286 100644
--- a/goffice/utils/go-image.c
+++ b/goffice/utils/go-image.c
@@ -540,10 +540,12 @@ go_image_type_for_format (char const *format)
 	return 0;
 }
 
-guint8 *
-go_image_get_pixels (GOImage *image)
+guint8 const *
+go_image_get_data (GOImage *image, gsize *length)
 {
 	g_return_val_if_fail (image, NULL);
+	if (length)
+		*length = image->data_length;
 	return image->data;
 }
 
diff --git a/goffice/utils/go-image.h b/goffice/utils/go-image.h
index 16ad5b9..a79e0fb 100644
--- a/goffice/utils/go-image.h
+++ b/goffice/utils/go-image.h
@@ -72,6 +72,7 @@ struct _GOImage {
 	GdkPixbuf *thumbnail;
 	GdkPixbuf *pixbuf;
 	char *name;
+	gsize data_length;
 };
 
 typedef struct {
@@ -97,7 +98,7 @@ GOImage 	*go_image_new_from_data 	(char const *type, guint8 const *data, gsize l
 GOImage 	*go_image_new_for_format   	(char const *format);
 GType		 go_image_type_for_format      	(char const *format);
 
-guint8 		*go_image_get_pixels 		(GOImage *image);
+guint8 const	*go_image_get_data 		(GOImage *image, gsize *length);
 void 		 go_image_fill 			(GOImage *image, GOColor color);
 
 void		 go_image_set_name		(GOImage *image, char const *name);
diff --git a/goffice/utils/go-spectre.c b/goffice/utils/go-spectre.c
index bad2d83..10b5dde 100644
--- a/goffice/utils/go-spectre.c
+++ b/goffice/utils/go-spectre.c
@@ -36,7 +36,6 @@ struct _GOSpectre {
 #ifdef GOFFICE_WITH_EPS
 	SpectreDocument *doc;
 #endif
-	gsize data_length;
 	cairo_surface_t *surface;
 };
 
@@ -51,7 +50,7 @@ go_spectre_save (GOImage *image, GsfXMLOut *output)
 		(image);
 	g_return_if_fail (spectre);
 	gsf_xml_out_add_base64 (output, NULL,
-			image->data, spectre->data_length);
+			image->data, image->data_length);
 }
 
 static void
@@ -63,16 +62,15 @@ go_spectre_load_attr (G_GNUC_UNUSED GOImage *image, G_GNUC_UNUSED xmlChar const
 static void
 go_spectre_load_data (GOImage *image, GsfXMLIn *xin)
 {
-	GOSpectre *spectre = GO_SPECTRE (image);
 #ifdef GOFFICE_WITH_EPS
 	int width, height;
 	char *tmpname;
 	int f;
 #endif
 
-	spectre->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
-	image->data = g_malloc (spectre->data_length);
-	memcpy (image->data, xin->content->str, spectre->data_length);
+	image->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+	image->data = g_malloc (image->data_length);
+	memcpy (image->data, xin->content->str, image->data_length);
 #ifdef GOFFICE_WITH_EPS
 	spectre->doc = spectre_document_new ();
 	if (spectre->doc == NULL)
@@ -190,10 +188,9 @@ go_spectre_get_scaled_pixbuf (GOImage *image, int width, int height)
 static gboolean
 go_spectre_differ (GOImage *first, GOImage *second)
 {
-	GOSpectre *sfirst = GO_SPECTRE (first), *ssecond = GO_SPECTRE (second);
-	if (sfirst->data_length != ssecond->data_length)
+	if (first->data_length != second->data_length)
 		return TRUE;
-	return memcmp (first->data, second->data, sfirst->data_length);
+	return memcmp (first->data, second->data, first->data_length);
 }
 
 static void
diff --git a/goffice/utils/go-svg.c b/goffice/utils/go-svg.c
index 603ffe5..bd304f2 100644
--- a/goffice/utils/go-svg.c
+++ b/goffice/utils/go-svg.c
@@ -32,7 +32,6 @@
 struct _GOSvg {
 	GOImage parent;
 	RsvgHandle *handle;
-	gsize data_length;
 };
 
 typedef GOImageClass GOSvgClass;
@@ -45,7 +44,7 @@ go_svg_save (GOImage *image, GsfXMLOut *output)
 	GOSvg *svg = GO_SVG (image);
 	g_return_if_fail (svg);
 	gsf_xml_out_add_base64 (output, NULL,
-			image->data, svg->data_length);
+			image->data, image->data_length);
 }
 
 static void
@@ -59,10 +58,10 @@ go_svg_load_data (GOImage *image, GsfXMLIn *xin)
 {
 	GOSvg *svg = GO_SVG (image);
 	double dpi_x, dpi_y;
-	svg->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
-	image->data = g_malloc (svg->data_length);
-	memcpy (image->data, xin->content->str, svg->data_length);
-	svg->handle = rsvg_handle_new_from_data (image->data, svg->data_length, NULL);
+	image->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+	image->data = g_malloc (image->data_length);
+	memcpy (image->data, xin->content->str, image->data_length);
+	svg->handle = rsvg_handle_new_from_data (image->data, image->data_length, NULL);
 	go_image_get_default_dpi (&dpi_x, &dpi_y);
 	rsvg_handle_set_dpi_x_y (svg->handle, dpi_x, dpi_y);
 }
@@ -120,10 +119,9 @@ go_svg_get_scaled_pixbuf (GOImage *image, int width, int height)
 static gboolean
 go_svg_differ (GOImage *first, GOImage *second)
 {
-	GOSvg *sfirst = GO_SVG (first), *ssecond = GO_SVG (second);
-	if (sfirst->data_length != ssecond->data_length)
+	if (first->data_length != second->data_length)
 		return TRUE;
-	return memcmp (first->data, second->data, sfirst->data_length);
+	return memcmp (first->data, second->data, first->data_length);
 }
 
 static void
@@ -160,7 +158,7 @@ GSF_CLASS (GOSvg, go_svg,
 GOImage *
 go_svg_new_from_file (char const *filename, GError **error)
 {
-	GOSvg *svg = g_object_new (GO_TYPE_SVG, NULL);
+	GOSvg *svg;
 	guint8 *data;
 	GsfInput *input = gsf_input_stdio_new (filename, error);
 	RsvgDimensionData dim;
@@ -169,16 +167,17 @@ go_svg_new_from_file (char const *filename, GError **error)
 
 	if (!input)
 		return NULL;
-	svg->data_length = gsf_input_size (input);
-	data = g_malloc (svg->data_length);
-	if (!data || !gsf_input_read (input, svg->data_length, data)) {
+	svg = g_object_new (GO_TYPE_SVG, NULL);
+	image = GO_IMAGE (svg);
+	image->data_length = gsf_input_size (input);
+	data = g_malloc (image->data_length);
+	if (!data || !gsf_input_read (input, image->data_length, data)) {
 		g_object_unref (svg);
 		g_free (data);
 		return NULL;
 	}
-	image = GO_IMAGE (svg);
 	image->data = data;
-	svg->handle = rsvg_handle_new_from_data (data, svg->data_length, error);
+	svg->handle = rsvg_handle_new_from_data (data, image->data_length, error);
 	if (svg->handle == NULL) {
 		g_object_unref (svg);
 		return NULL;
@@ -201,15 +200,15 @@ go_svg_new_from_data (char const *data, size_t length, GError **error)
 
 	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_length = length;
 	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);
+	svg->handle = rsvg_handle_new_from_data (image->data, image->data_length, error);
 	if (svg->handle == NULL) {
 		g_object_unref (svg);
 		return NULL;



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