[lasem] [SVG] Inlined image support.



commit 829248eab4d03ac18fac48d9d2704d4f3e6f974c
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Sun May 17 23:12:21 2009 +0200

    [SVG] Inlined image support.
    
    This pulls a gdkpixbuf dependency, but that's not something I want
    to avoid !
    
    The support is very rough for now. There's room for improvements:
    
      - try to avoid unecessary memory duplication.
      - don't decode the base64 data on every update if the data have
      not changed (may be by overloading the set_attribute function).
---
 configure.ac             |    2 +-
 src/lsmdomparser.c       |    4 +-
 src/lsmsvgelement.c      |    2 +-
 src/lsmsvgimageelement.c |  106 +++++++++++++++++++++++++++++++++++++++-------
 src/lsmsvgimageelement.h |    5 ++
 src/lsmsvgview.c         |   11 +++++
 src/lsmsvgview.h         |    2 +
 7 files changed, 112 insertions(+), 20 deletions(-)

diff --git a/configure.ac b/configure.ac
index 1cf582c..75d718a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,7 +28,7 @@ IT_PROG_INTLTOOL([0.35.0])
 
 AM_PROG_LIBTOOL
 
-PKG_CHECK_MODULES(LASEM, [gobject-2.0 glib-2.0 gio-2.0 cairo >= 1.2 pangocairo >= 1.16.0 libxml-2.0])
+PKG_CHECK_MODULES(LASEM, [gobject-2.0 glib-2.0 gio-2.0 gdk-pixbuf-2.0 >= 2.16 gdk-2.0 >= 2.16 cairo >= 1.2 pangocairo >= 1.16.0 libxml-2.0])
 AC_SUBST(LASEM_CFLAGS)
 AC_SUBST(LASEM_LIBS)
 
diff --git a/src/lsmdomparser.c b/src/lsmdomparser.c
index 1a5e60f..8d3bbef 100644
--- a/src/lsmdomparser.c
+++ b/src/lsmdomparser.c
@@ -107,8 +107,8 @@ lsm_dom_parser_start_element(void *user_data,
 		if (attrs != NULL)
 			for (i = 0; attrs[i] != NULL && attrs[i+1] != NULL; i += 2)
 				lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (node),
-							    (char *) attrs[i],
-							    (char *) attrs[i+1]);
+							       (char *) attrs[i],
+							       (char *) attrs[i+1]);
 
 		state->current_node = node;
 		state->is_error = FALSE;
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index 134333d..9bd5e9a 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -59,7 +59,7 @@ lsm_svg_element_set_attribute (LsmDomElement *self, const char* name, const char
 		    lsm_dom_node_get_node_name (LSM_DOM_NODE (self)), name, value);
 
 	lsm_dom_attribute_map_set_attribute (s_element_class->attributes, self,
-					  name, value);
+					     name, value);
 }
 
 const char *
diff --git a/src/lsmsvgimageelement.c b/src/lsmsvgimageelement.c
index 650f490..f679be1 100644
--- a/src/lsmsvgimageelement.c
+++ b/src/lsmsvgimageelement.c
@@ -24,6 +24,7 @@
 #include <lsmdebug.h>
 #include <lsmdomdocument.h>
 #include <stdio.h>
+#include <string.h>
 
 static GObjectClass *parent_class;
 
@@ -48,6 +49,7 @@ lsm_svg_image_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 {
 	LsmSvgImageElement *image_element = LSM_SVG_IMAGE_ELEMENT (self);
 	LsmSvgLength length;
+	const char *href;
 
 	length.value_unit = 0.0;
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
@@ -65,7 +67,49 @@ lsm_svg_image_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 	length.type = LSM_SVG_LENGTH_TYPE_PX;
 	lsm_svg_animated_length_attribute_parse (&image_element->height, &length);
 
+	lsm_svg_preserve_aspect_ratio_attribute_parse (&image_element->preserve_aspect_ratio);
+
 	LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
+
+	if (image_element->pixbuf != NULL) {
+		g_object_unref (image_element->pixbuf);
+		image_element->pixbuf = NULL;
+	}
+
+	href = image_element->href.value;
+
+	if (href != NULL) {
+		GdkPixbufLoader *loader;
+		void *image_data;
+		gsize data_size;
+		int result;
+
+		if (strncmp (href, "data:", 5) == 0) {
+
+			lsm_debug ("[LsmSvgImageElement::update] Found inlined image");
+
+			while (*href != '\0' && *href != ',')
+				href++;
+
+			image_data = g_base64_decode (href, &data_size);
+		} else {
+			image_data = NULL;
+			data_size = 0;
+		}
+
+		loader = gdk_pixbuf_loader_new ();
+
+		result = gdk_pixbuf_loader_write (loader, image_data, data_size, NULL);
+
+		g_free (image_data);
+
+		gdk_pixbuf_loader_close (loader, NULL);
+
+		image_element->pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+		g_object_ref (image_element->pixbuf);
+
+		g_object_unref (loader);
+	}
 }
 
 /* LsmSvgGraphic implementation */
@@ -73,21 +117,36 @@ lsm_svg_image_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
 static void
 lsm_svg_image_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
 {
-	LsmSvgImageElement *image_element;
-	LsmDomDocument *document;
-	const char *id;
+	LsmSvgImageElement *image;
+	LsmBox viewport;
+	LsmBox viewbox;
 
-	document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
-	if (document == NULL) {
-		lsm_debug ("[LsmSvgImageElement::graphic_render] Owner document not found");
+	image = LSM_SVG_IMAGE_ELEMENT (self);
+	if (image->pixbuf == NULL)
 		return;
-	}
 
-	image_element = LSM_SVG_IMAGE_ELEMENT (self);
+	viewport.x      = lsm_svg_view_normalize_length (view, &image->x.length.base,
+							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	viewport.y      = lsm_svg_view_normalize_length (view, &image->y.length.base,
+							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	viewport.width  = lsm_svg_view_normalize_length (view, &image->width.length.base,
+							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	viewport.height = lsm_svg_view_normalize_length (view, &image->height.length.base,
+							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	id = image_element->href.value;
-	if (id == NULL)
-		return;
+	lsm_debug ("[LsmSvgImageElement::graphic_render] viewport %g, %g, %g, %g",
+		   viewport.x, viewport.y, viewport.width, viewport.height);
+
+	viewbox.x = 0;
+	viewbox.y = 0;
+	viewbox.width = gdk_pixbuf_get_width (image->pixbuf);
+	viewbox.height = gdk_pixbuf_get_height (image->pixbuf);
+
+	lsm_svg_view_push_viewport (view, &viewport, &viewbox, &image->preserve_aspect_ratio.value);
+
+	lsm_svg_view_show_pixbuf (view, image->pixbuf);
+
+	lsm_svg_view_pop_viewport (view);
 }
 
 /* LsmSvgImageElement implementation */
@@ -101,6 +160,16 @@ lsm_svg_image_element_new (void)
 static void
 lsm_svg_image_element_init (LsmSvgImageElement *self)
 {
+	self->pixbuf = NULL;
+}
+
+static void
+lsm_svg_image_element_finalize (GObject *gobject)
+{
+	LsmSvgImageElement *image = LSM_SVG_IMAGE_ELEMENT (gobject);
+
+	if (image->pixbuf != NULL)
+		g_object_unref (image->pixbuf);
 }
 
 /* LsmSvgImageElement class */
@@ -108,12 +177,15 @@ lsm_svg_image_element_init (LsmSvgImageElement *self)
 static void
 lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
 {
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
 	LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
 	LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (klass);
 
+	gobject_class->finalize = lsm_svg_image_element_finalize;
+
 	d_node_class->get_node_name = lsm_svg_image_element_get_node_name;
 	d_node_class->can_append_child = lsm_svg_use_can_append_child;
 
@@ -124,15 +196,17 @@ lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
 	s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
 
 	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
-					  offsetof (LsmSvgImageElement, x));
+					     offsetof (LsmSvgImageElement, x));
 	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
-					  offsetof (LsmSvgImageElement, y));
+					     offsetof (LsmSvgImageElement, y));
 	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
-					  offsetof (LsmSvgImageElement, width));
+					     offsetof (LsmSvgImageElement, width));
 	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
-					  offsetof (LsmSvgImageElement, height));
+					     offsetof (LsmSvgImageElement, height));
 	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "xlink:href",
-					  offsetof (LsmSvgImageElement, href));
+					     offsetof (LsmSvgImageElement, href));
+	lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",
+					     offsetof (LsmSvgImageElement, preserve_aspect_ratio));
 }
 
 G_DEFINE_TYPE (LsmSvgImageElement, lsm_svg_image_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgimageelement.h b/src/lsmsvgimageelement.h
index 0bb8ac8..d2d63d2 100644
--- a/src/lsmsvgimageelement.h
+++ b/src/lsmsvgimageelement.h
@@ -24,6 +24,7 @@
 
 #include <lsmsvg.h>
 #include <lsmsvggraphic.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
 
 G_BEGIN_DECLS
 
@@ -45,6 +46,10 @@ struct _LsmSvgImageElement {
 	LsmSvgAnimatedLengthAttribute	height;
 
 	LsmDomAttribute		href;
+
+	LsmSvgPreserveAspectRatioAttribute	preserve_aspect_ratio;
+
+	GdkPixbuf *pixbuf;
 };
 
 struct _LsmSvgImageElementClass {
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 1c30206..96834e0 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -27,6 +27,7 @@
 #include <lsmsvggradientelement.h>
 #include <lsmsvgpatternelement.h>
 #include <lsmsvgutils.h>
+#include <gdk/gdk.h>
 #include <glib/gprintf.h>
 
 #include <math.h>
@@ -1228,6 +1229,16 @@ lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y
 }
 
 void
+lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf)
+{
+	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+	g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
+
+	gdk_cairo_set_source_pixbuf (view->dom_view.cairo, pixbuf, 0, 0);
+	cairo_paint (view->dom_view.cairo);
+}
+
+void
 lsm_svg_view_push_group (LsmSvgView *view)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 6aeb5d3..35a437b 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -25,6 +25,7 @@
 #include <lsmdomview.h>
 #include <lsmsvgelement.h>
 #include <lsmsvg.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
 
 G_BEGIN_DECLS
 
@@ -108,6 +109,7 @@ void 		lsm_svg_view_show_line 		(LsmSvgView *view, double x1, double y1, double
 void 		lsm_svg_view_show_polyline	(LsmSvgView *view, const char *points);
 void 		lsm_svg_view_show_polygon	(LsmSvgView *view, const char *points);
 void 		lsm_svg_view_show_text 		(LsmSvgView *view, char const *text, double x, double y);
+void		lsm_svg_view_show_pixbuf	(LsmSvgView *view, GdkPixbuf *pixbuf);
 
 void 		lsm_svg_view_push_group 	(LsmSvgView *view);
 void 		lsm_svg_view_paint_group 	(LsmSvgView *view, double opacity);



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