[lasem] [SVG] Inlined image support.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: svn-commits-list gnome org
- Subject: [lasem] [SVG] Inlined image support.
- Date: Sun, 17 May 2009 17:16:13 -0400 (EDT)
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]