[lasem] svg_filter: add support for feOffset.



commit 9673d803ddd05c070af4151a926cb97c72b51e4a
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Sun Oct 14 18:54:34 2012 +0200

    svg_filter: add support for feOffset.

 docs/reference/lasem/Makefile.am |    3 +-
 src/Makefile.am                  |    6 +-
 src/lsmcairo.c                   |   45 +++++++++++++++
 src/lsmcairo.h                   |    1 +
 src/lsmsvgdocument.c             |    3 +
 src/lsmsvgfilteroffset.c         |  113 ++++++++++++++++++++++++++++++++++++++
 src/lsmsvgfilteroffset.h         |   58 +++++++++++++++++++
 src/lsmsvgtypes.h                |    1 +
 src/lsmsvgview.c                 |   29 ++++++++++
 src/lsmsvgview.h                 |    2 +
 10 files changed, 258 insertions(+), 3 deletions(-)
---
diff --git a/docs/reference/lasem/Makefile.am b/docs/reference/lasem/Makefile.am
index d505435..5acc841 100644
--- a/docs/reference/lasem/Makefile.am
+++ b/docs/reference/lasem/Makefile.am
@@ -149,7 +149,8 @@ IGNORE_HFILES=\
 	lsmsvgfilterprimitive.h			\
 	lsmsvgfilterblend.h			\
 	lsmsvgfilterflood.h			\
-	lsmsvgfiltergaussianblur.h
+	lsmsvgfiltergaussianblur.h		\
+	lsmsvgfilteroffset.h
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/src/Makefile.am b/src/Makefile.am
index cd1b0d8..1ab507f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -128,7 +128,8 @@ LASEM_SVG_SRCS =				\
 	lsmsvgfilterprimitive.c			\
 	lsmsvgfilterblend.c			\
 	lsmsvgfilterflood.c			\
-	lsmsvgfiltergaussianblur.c
+	lsmsvgfiltergaussianblur.c		\
+	lsmsvgfilteroffset.c
 
 LASEM_DOM_HDRS = 				\
 	lsm.h					\
@@ -235,7 +236,8 @@ LASEM_SVG_HDRS =				\
 	lsmsvgfilterprimitive.h			\
 	lsmsvgfilterblend.h			\
 	lsmsvgfilterflood.h			\
-	lsmsvgfiltergaussianblur.h
+	lsmsvgfiltergaussianblur.h		\
+	lsmsvgfilteroffset.h
 
 liblasem_ LASEM_API_VERSION@_ladir = $(includedir)/lasem- LASEM_API_VERSION@
 
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index 23576a5..921acdf 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -25,6 +25,7 @@
 
 #include <lsmcairo.h>
 #include <lsmsvgenums.h>
+#include <lsmutils.h>
 #include <math.h>
 #include <string.h>
 
@@ -351,6 +352,50 @@ lsm_filter_surface_blend (LsmFilterSurface *input_1,
 	cairo_destroy (cairo);
 }
 
+void
+lsm_filter_surface_offset (LsmFilterSurface *input,
+			   LsmFilterSurface *output,
+			   int dx, int dy)
+{
+	int x, y;
+	int rowstride, height, width, ch;
+	unsigned char *input_pixels;
+	unsigned char *output_pixels;
+	LsmExtents boundarys;
+
+	g_return_if_fail (input != NULL);
+	g_return_if_fail (output != NULL);
+
+	cairo_surface_flush (input->surface);
+
+	height = cairo_image_surface_get_height (input->surface);
+	width = cairo_image_surface_get_width (input->surface);
+	rowstride = cairo_image_surface_get_stride (input->surface);
+
+	input_pixels = cairo_image_surface_get_data (input->surface);
+	output_pixels = cairo_image_surface_get_data (output->surface);
+
+	boundarys.x1 = 0;
+	boundarys.y1 = 0;
+	boundarys.x2 = width;
+	boundarys.y2 = height;
+
+	for (y = boundarys.y1; y < boundarys.y2; y++)
+		for (x = boundarys.x1; x < boundarys.x2; x++) {
+			if (x - dx < boundarys.x1 || x - dx >= boundarys.x2)
+				continue;
+			if (y - dy < boundarys.y1 || y - dy >= boundarys.y2)
+				continue;
+
+			for (ch = 0; ch < 4; ch++) {
+				output_pixels[y * rowstride + x * 4 + ch] =
+					input_pixels[(y - dy) * rowstride + (x - dx) * 4 + ch];
+			}
+		}
+
+	cairo_surface_mark_dirty (output->surface);
+}
+
 /**
  * lsm_cairo_set_source_pixbuf:
  * @cr: a cairo context
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index 102081f..2f0bdf7 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -58,6 +58,7 @@ void 			lsm_filter_surface_fast_blur 		(LsmFilterSurface *input,
 								 LsmFilterSurface *output,
 								 double sx, double sy);
 void 			lsm_filter_surface_flood 		(LsmFilterSurface *surface, guint32 color, double opacity);
+void 			lsm_filter_surface_offset 		(LsmFilterSurface *input, LsmFilterSurface *output, int dx, int dy);
 
 void 			lsm_cairo_set_source_pixbuf 		(cairo_t         *cr,
 								 const GdkPixbuf *pixbuf,
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index 7fc90b6..979476f 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -49,6 +49,7 @@
 #include <lsmsvgfilterblend.h>
 #include <lsmsvgfilterflood.h>
 #include <lsmsvgfiltergaussianblur.h>
+#include <lsmsvgfilteroffset.h>
 #include <lsmsvgview.h>
 #include <string.h>
 
@@ -142,6 +143,8 @@ _create_element (LsmDomDocument *document, const char *tag_name)
 		node = lsm_svg_filter_flood_new ();
 	else if (strcmp (tag_name, "feGaussianBlur") == 0)
 		node = lsm_svg_filter_gaussian_blur_new ();
+	else if (strcmp (tag_name, "feOffset") == 0)
+		node = lsm_svg_filter_offset_new ();
 
 	if (node != NULL)
 		lsm_debug_dom ("[LsmSvgDocument::create_element] Create a %s element", tag_name);
diff --git a/src/lsmsvgfilteroffset.c b/src/lsmsvgfilteroffset.c
new file mode 100644
index 0000000..2abe1a9
--- /dev/null
+++ b/src/lsmsvgfilteroffset.c
@@ -0,0 +1,113 @@
+/* Lasem
+ * 
+ * Copyright  2012 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 <lsmsvgfilteroffset.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_offset_get_node_name (LsmDomNode *node)
+{
+	return "feOffset";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_offset_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+				     const char *input, const char *output,
+				     double x, double y, double w, double h)
+{
+	LsmSvgFilterOffset *offset = LSM_SVG_FILTER_OFFSET (self);
+
+	lsm_svg_view_apply_offset (view, input, output, offset->dx.value, offset->dy.value);
+}
+
+/* LsmSvgFilterOffset implementation */
+
+static const double dy_default =  0.0;
+static const double dx_default =  0.0;
+
+LsmDomNode *
+lsm_svg_filter_offset_new (void)
+{
+	return g_object_new (LSM_TYPE_SVG_FILTER_OFFSET, NULL);
+}
+
+static void
+lsm_svg_filter_offset_init (LsmSvgFilterOffset *self)
+{
+	self->dx.value = dx_default;
+	self->dy.value = dy_default;
+}
+
+static void
+lsm_svg_filter_offset_finalize (GObject *object)
+{
+	parent_class->finalize (object);
+}
+
+/* LsmSvgFilterOffset class */
+
+static const LsmAttributeInfos lsm_svg_filter_offset_attribute_infos[] = {
+	{
+		.name = "dx",
+		.attribute_offset = offsetof (LsmSvgFilterOffset, dx),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = &dx_default
+	},
+	{
+		.name = "dy",
+		.attribute_offset = offsetof (LsmSvgFilterOffset, dy),
+		.trait_class = &lsm_double_trait_class,
+		.trait_default = &dy_default
+	}
+};
+
+static void
+lsm_svg_filter_offset_class_init (LsmSvgFilterOffsetClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	LsmDomNodeClass *d_node_class = LSM_DOM_NODE_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_offset_finalize;
+
+	d_node_class->get_node_name = lsm_svg_filter_offset_get_node_name;
+
+	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_offset_attribute_infos),
+					      lsm_svg_filter_offset_attribute_infos);
+
+	f_primitive_class->apply = lsm_svg_filter_offset_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterOffset, lsm_svg_filter_offset, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfilteroffset.h b/src/lsmsvgfilteroffset.h
new file mode 100644
index 0000000..42edcad
--- /dev/null
+++ b/src/lsmsvgfilteroffset.h
@@ -0,0 +1,58 @@
+/* Lasem
+ *
+ * Copyright  2012 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_OFFSET_H
+#define LSM_SVG_FILTER_OFFSET_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_OFFSET             (lsm_svg_filter_offset_get_type ())
+#define LSM_SVG_FILTER_OFFSET(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_FILTER_OFFSET, LsmSvgFilterOffset))
+#define LSM_SVG_FILTER_OFFSET_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_FILTER_OFFSET, LsmSvgFilterOffsetClass))
+#define LSM_IS_SVG_FILTER_OFFSET(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_FILTER_OFFSET))
+#define LSM_IS_SVG_FILTER_OFFSET_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_FILTER_OFFSET))
+#define LSM_SVG_FILTER_OFFSET_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_FILTER_OFFSET, LsmSvgFilterOffsetClass))
+
+typedef struct _LsmSvgFilterOffsetClass LsmSvgFilterOffsetClass;
+
+struct _LsmSvgFilterOffset {
+	LsmSvgFilterPrimitive base;
+
+	LsmSvgDoubleAttribute dx;
+	LsmSvgDoubleAttribute dy;
+};
+
+struct _LsmSvgFilterOffsetClass {
+	LsmSvgFilterPrimitiveClass  element_class;
+};
+
+GType lsm_svg_filter_offset_get_type (void);
+
+LsmDomNode * 	lsm_svg_filter_offset_new 		(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index fa8b0b1..d1432bc 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -60,6 +60,7 @@ typedef struct _LsmSvgFilterPrimitive LsmSvgFilterPrimitive;
 typedef struct _LsmSvgFilterBlend LsmSvgFilterBlend;
 typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
 typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
+typedef struct _LsmSvgFilterOffset LsmSvgFilterOffset;
 
 typedef struct _LsmSvgView LsmSvgView;
 typedef struct _LsmSvgStyle LsmSvgStyle;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 60c0f6a..3111da0 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -1988,6 +1988,9 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
 
 		view->filter_surfaces = g_slist_prepend (view->filter_surfaces, filter_surface);
 
+		filter_surface = lsm_filter_surface_new_with_content ("SourceAlpha", 0, 0, surface);
+		view->filter_surfaces = g_slist_prepend (view->filter_surfaces, filter_surface);
+
 		lsm_svg_element_force_render (filter_element, view);
 
 		if (view->debug_filter) {
@@ -2143,6 +2146,32 @@ lsm_svg_view_apply_gaussian_blur (LsmSvgView *view, const char *input, const cha
 }
 
 void
+lsm_svg_view_apply_offset (LsmSvgView *view, const char *input, const char *output, double dx, double dy)
+{
+	LsmFilterSurface *input_surface;
+	LsmFilterSurface *output_surface;
+
+	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+
+	input_surface = _get_filter_surface (view, input);
+
+	if (input_surface == NULL) {
+		lsm_debug_render ("[SvgView::apply_offset] Input '%s' not found", input);
+		return;
+	}
+
+	output_surface = _create_filter_surface (view, output, input_surface);
+
+	lsm_log_render ("[SvgView::apply_offset] %s -> %s (dx:%g,dy:%g)", input, output, dx, dy); 
+
+	cairo_user_to_device_distance (view->dom_view.cairo, &dx, &dy);
+
+	lsm_log_render ("[SvgView::apply_offset] %g px,%g px", dx, dy);
+
+	lsm_filter_surface_offset (input_surface, output_surface, dx, dy);
+}
+
+void
 lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 002ef54..00d150f 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -161,6 +161,8 @@ void 		lsm_svg_view_apply_flood 		(LsmSvgView *view, const char *output,
 void		lsm_svg_view_apply_gaussian_blur 	(LsmSvgView *view, const char *input, const char *output,
 							 double x, double y, double w, double h,
 							 double std_x, double std_y);
+void 		lsm_svg_view_apply_offset 		(LsmSvgView *view, const char *input, const char *output, double dx, double dy);
+
 G_END_DECLS
 
 #endif



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