[lasem] svg_fe_image: simple implementation



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]