[lasem] svg_fe_image: simple implementation
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [lasem] svg_fe_image: simple implementation
- Date: Sat, 1 Aug 2015 21:38:28 +0000 (UTC)
commit 9df4a24116232e029986e9197c5c25e8c5c0d830
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Sat Aug 1 23:36:48 2015 +0200
svg_fe_image: simple implementation
No preserve_aspect_ratio support nor antyhing else than an external
bitmap image.
src/Makefile.am | 1 +
src/lsmsvgdocument.c | 3 +
src/lsmsvgfilterimage.c | 167 +++++++++++++++++++++++++++++++++++++++++++++
src/lsmsvgfilterimage.h | 61 ++++++++++++++++
src/lsmsvgfiltersurface.c | 36 ++++++++++
src/lsmsvgfiltersurface.h | 5 +-
src/lsmsvgtypes.h | 1 +
src/lsmsvgview.c | 28 +++++++-
src/lsmsvgview.h | 2 +
9 files changed, 299 insertions(+), 5 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b2f9e7..4d78c57 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -138,6 +138,7 @@ LASEM_SVG_SRCS = \
lsmsvgfiltercomposite.c \
lsmsvgfilterflood.c \
lsmsvgfiltergaussianblur.c \
+ lsmsvgfilterimage.c \
lsmsvgfilteroffset.c \
lsmsvgfiltermerge.c \
lsmsvgfiltermergenode.c \
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index f9e4879..99ade04 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -33,6 +33,7 @@
#include <lsmsvgfiltercomposite.h>
#include <lsmsvgfilterflood.h>
#include <lsmsvgfiltergaussianblur.h>
+#include <lsmsvgfilterimage.h>
#include <lsmsvgfilteroffset.h>
#include <lsmsvgfiltermerge.h>
#include <lsmsvgfiltermergenode.h>
@@ -169,6 +170,8 @@ _create_element (LsmDomDocument *document, const char *tag_name)
node = lsm_svg_filter_specular_lighting_new ();
else if (strcmp (tag_name, "feColorMatrix") == 0)
node = lsm_svg_filter_color_matrix_new ();
+ else if (strcmp (tag_name, "feImage") == 0)
+ node = lsm_svg_filter_image_new ();
else if (strcmp (tag_name, "feTile") == 0)
node = lsm_svg_filter_tile_new ();
diff --git a/src/lsmsvgfilterimage.c b/src/lsmsvgfilterimage.c
new file mode 100644
index 0000000..5ded3e4
--- /dev/null
+++ b/src/lsmsvgfilterimage.c
@@ -0,0 +1,167 @@
+/* Lasem
+ *
+ * Copyright © 2015 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmsvgfilterimage.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_image_get_node_name (LsmDomNode *node)
+{
+ return "feImage";
+}
+
+static void
+lsm_svg_filter_image_set_attribute (LsmDomElement *self, const char *name, const char *value)
+{
+ LsmSvgFilterImage *filter = LSM_SVG_FILTER_IMAGE (self);
+
+ LSM_DOM_ELEMENT_CLASS (parent_class)->set_attribute (self, name, value);
+
+ if (g_strcmp0 (name, "xlink:href") == 0)
+ g_clear_object (&filter->pixbuf);
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_image_apply (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+ const char *input, const char *output, const LsmBox *subregion)
+{
+ LsmSvgFilterImage *filter = LSM_SVG_FILTER_IMAGE (self);
+
+ /* TODO href can also be a reference to an element */
+ /* TODO this code can be factorized with the one of <image> */
+
+ if (filter->pixbuf == NULL) {
+ LsmDomDocument *document;
+ char *data;
+ gsize size;
+
+ document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
+
+ if (filter->href.value != NULL) {
+ data = lsm_dom_document_get_href_data (document, filter->href.value, &size);
+ if (data != NULL) {
+ GdkPixbufLoader *loader;
+
+ loader = gdk_pixbuf_loader_new ();
+
+ gdk_pixbuf_loader_write (loader, (guchar *) data, size, NULL);
+
+ g_free (data);
+
+ gdk_pixbuf_loader_close (loader, NULL);
+
+ filter->pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ g_object_ref (filter->pixbuf);
+
+ g_object_unref (loader);
+ } else
+ lsm_debug_render ("[SvgFilterImage::apply] Failed to load image '%s'",
+ filter->href.value);
+ } else
+ lsm_debug_render ("[SvgFilterImage::apply] Missing xlink:href attribute");
+ }
+
+ if (GDK_IS_PIXBUF (filter->pixbuf))
+ lsm_svg_view_apply_image (view, output, subregion, filter->pixbuf,
filter->preserve_aspect_ratio.value);
+}
+
+/* LsmSvgFilterImage implementation */
+
+LsmDomNode *
+lsm_svg_filter_image_new (void)
+{
+ return g_object_new (LSM_TYPE_SVG_FILTER_IMAGE, NULL);
+}
+
+static const LsmSvgPreserveAspectRatio preserve_aspect_ratio_default = {
+ .defer = FALSE,
+ .align = LSM_SVG_ALIGN_X_MID_Y_MID,
+ .meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET
+};
+
+static void
+lsm_svg_filter_image_init (LsmSvgFilterImage *self)
+{
+ self->pixbuf = NULL;
+ self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
+}
+
+static void
+lsm_svg_filter_image_finalize (GObject *object)
+{
+ LsmSvgFilterImage *filter = LSM_SVG_FILTER_IMAGE (object);
+
+ g_clear_object (&filter->pixbuf);
+
+ parent_class->finalize (object);
+}
+
+/* LsmSvgFilterImage class */
+
+static const LsmAttributeInfos lsm_svg_filter_image_attribute_infos[] = {
+ {
+ .name = "xlink:href",
+ .attribute_offset = offsetof (LsmSvgFilterImage, href),
+ .trait_class = &lsm_null_trait_class
+ },
+ {
+ .name = "preserveAspectRatio",
+ .attribute_offset = offsetof (LsmSvgFilterImage, preserve_aspect_ratio),
+ .trait_class = &lsm_svg_preserve_aspect_ratio_trait_class,
+ .trait_default = &preserve_aspect_ratio_default
+ }
+};
+
+static void
+lsm_svg_filter_image_class_init (LsmSvgFilterImageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
+ LsmDomElementClass *d_element_class = LSM_DOM_ELEMENT_CLASS (klass);
+ LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
+ LsmSvgFilterPrimitiveClass *f_primitive_class = LSM_SVG_FILTER_PRIMITIVE_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = lsm_svg_filter_image_finalize;
+
+ d_node_class->get_node_name = lsm_svg_filter_image_get_node_name;
+
+ d_element_class->set_attribute = lsm_svg_filter_image_set_attribute;
+
+ s_element_class->attribute_manager = lsm_attribute_manager_duplicate
(s_element_class->attribute_manager);
+
+ lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+ G_N_ELEMENTS (lsm_svg_filter_image_attribute_infos),
+ lsm_svg_filter_image_attribute_infos);
+
+ f_primitive_class->apply = lsm_svg_filter_image_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterImage, lsm_svg_filter_image, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfilterimage.h b/src/lsmsvgfilterimage.h
new file mode 100644
index 0000000..8568bd3
--- /dev/null
+++ b/src/lsmsvgfilterimage.h
@@ -0,0 +1,61 @@
+/* Lasem
+ *
+ * Copyright © 2015 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_SVG_FILTER_IMAGE_H
+#define LSM_SVG_FILTER_IMAGE_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_IMAGE (lsm_svg_filter_image_get_type ())
+#define LSM_SVG_FILTER_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_FILTER_IMAGE,
LsmSvgFilterImage))
+#define LSM_SVG_FILTER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_FILTER_IMAGE,
LsmSvgFilterImageClass))
+#define LSM_IS_SVG_FILTER_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_FILTER_IMAGE))
+#define LSM_IS_SVG_FILTER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_FILTER_IMAGE))
+#define LSM_SVG_FILTER_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_FILTER_IMAGE,
LsmSvgFilterImageClass))
+
+typedef struct _LsmSvgFilterImageClass LsmSvgFilterImageClass;
+
+struct _LsmSvgFilterImage {
+ LsmSvgFilterPrimitive base;
+
+ LsmAttribute href;
+
+ LsmSvgPreserveAspectRatioAttribute preserve_aspect_ratio;
+
+ GdkPixbuf *pixbuf;
+};
+
+struct _LsmSvgFilterImageClass {
+ LsmSvgFilterPrimitiveClass element_class;
+};
+
+GType lsm_svg_filter_image_get_type (void);
+
+LsmDomNode * lsm_svg_filter_image_new (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgfiltersurface.c b/src/lsmsvgfiltersurface.c
index 42a53d5..5a8f171 100644
--- a/src/lsmsvgfiltersurface.c
+++ b/src/lsmsvgfiltersurface.c
@@ -610,3 +610,39 @@ lsm_svg_filter_surface_color_matrix (LsmSvgFilterSurface *input, LsmSvgFilterSur
cairo_destroy (cairo);
}
+
+void
+lsm_svg_filter_surface_image (LsmSvgFilterSurface *output, GdkPixbuf *pixbuf,
+ LsmSvgPreserveAspectRatio preserve_aspect_ratio)
+{
+ cairo_t *cairo;
+ int width, height;
+ double zoom_x, zoom_y;
+
+ g_return_if_fail (output != NULL);
+ g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
+
+ if (output->subregion.width < 1 ||
+ output->subregion.height < 1)
+ return;
+
+ /* TODO Implement preserve_aspect_ratio support */
+
+ width = gdk_pixbuf_get_height (pixbuf);
+ height = gdk_pixbuf_get_width (pixbuf);
+
+ if (height < 1 || width < 1)
+ return;
+
+ zoom_x = (double) output->subregion.width / (double) width;
+ zoom_y = (double) output->subregion.height / (double) height;
+
+ cairo = cairo_create (output->surface);
+
+ cairo_translate (cairo, output->subregion.x, output->subregion.y);
+ cairo_scale (cairo, zoom_x, zoom_y);
+ lsm_cairo_set_source_pixbuf (cairo, pixbuf, 0, 0);
+ cairo_paint (cairo);
+
+ cairo_destroy (cairo);
+}
diff --git a/src/lsmsvgfiltersurface.h b/src/lsmsvgfiltersurface.h
index eb2be25..48c9bfd 100644
--- a/src/lsmsvgfiltersurface.h
+++ b/src/lsmsvgfiltersurface.h
@@ -25,8 +25,9 @@
#define LSM_SVG_FILTER_SURFACE_H
#include <lsmtypes.h>
-#include <lsmsvgenums.h>
+#include <lsmsvgtraits.h>
#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
G_BEGIN_DECLS
@@ -63,6 +64,8 @@ void lsm_svg_filter_surface_merge (LsmSvgFilterSurface *input,
LsmSvgFilter
void lsm_svg_filter_surface_tile (LsmSvgFilterSurface *input,
LsmSvgFilterSurface *output);
void lsm_svg_filter_surface_color_matrix (LsmSvgFilterSurface *input,
LsmSvgFilterSurface *output,
LsmSvgColorFilterType type, unsigned
n_values, const double *values);
+void lsm_svg_filter_surface_image (LsmSvgFilterSurface *output, GdkPixbuf
*pixbuf,
+ LsmSvgPreserveAspectRatio
preserve_aspect_ratio);
G_END_DECLS
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index 62ef995..d3931da 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -51,6 +51,7 @@ typedef struct _LsmSvgFilterColorMatrix LsmSvgFilterColorMatrix;
typedef struct _LsmSvgFilterComposite LsmSvgFilterComposite;
typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
+typedef struct _LsmSvgFilterImage LsmSvgFilterImage;
typedef struct _LsmSvgFilterMerge LsmSvgFilterMerge;
typedef struct _LsmSvgFilterMergeNode LsmSvgFilterMergeNode;
typedef struct _LsmSvgFilterOffset LsmSvgFilterOffset;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index b34351a..61647db 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -2110,10 +2110,30 @@ lsm_svg_view_apply_flood (LsmSvgView *view, const char *output, const LsmBox *su
subregion_px.x, subregion_px.y);
lsm_svg_filter_surface_flood (output_surface,
- view->style->flood_color->value.red,
- view->style->flood_color->value.green,
- view->style->flood_color->value.blue,
- view->style->flood_opacity->value);
+ view->style->flood_color->value.red,
+ view->style->flood_color->value.green,
+ view->style->flood_color->value.blue,
+ view->style->flood_opacity->value);
+}
+
+void
+lsm_svg_view_apply_image (LsmSvgView *view, const char *output, const LsmBox *subregion,
+ GdkPixbuf *pixbuf, LsmSvgPreserveAspectRatio preserve_aspect_ratio)
+{
+ LsmSvgFilterSurface *output_surface;
+ LsmSvgFilterSurface *input_surface;
+ LsmBox subregion_px;
+
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+
+ input_surface = _get_filter_surface (view, NULL);
+
+ lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+ output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
+
+ lsm_log_render ("[SvgView::apply_image]");
+
+ lsm_svg_filter_surface_image (output_surface, pixbuf, preserve_aspect_ratio);
}
void
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 575c166..128fc62 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -177,6 +177,8 @@ void lsm_svg_view_apply_color_matrix (LsmSvgView *view, const char
*input, co
unsigned int n_values, const double *values);
void lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char
*output, const LsmBox *subregion);
void lsm_svg_view_apply_tile (LsmSvgView *view, const char *input, const char
*output, const LsmBox *subregion);
+void lsm_svg_view_apply_image (LsmSvgView *view, const char *output, const LsmBox
*subregion,
+ GdkPixbuf *pixbuf, LsmSvgPreserveAspectRatio
preserve_aspect_ratio);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]