[lasem] svg: add feFlood support (not working yet).



commit dba92601694710de3591ecd1eb98e24f2a7384b6
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Sun Oct 14 12:19:43 2012 +0200

    svg: add feFlood support (not working yet).

 docs/reference/lasem/Makefile.am |    1 +
 src/Makefile.am                  |    2 +
 src/lsmcairo.c                   |   31 +++++++++++-
 src/lsmcairo.h                   |    2 +
 src/lsmsvgdocument.c             |    3 +
 src/lsmsvgfilterflood.c          |  103 ++++++++++++++++++++++++++++++++++++++
 src/lsmsvgfilterflood.h          |   57 +++++++++++++++++++++
 src/lsmsvgfilterprimitive.c      |    7 +++
 src/lsmsvgstyle.c                |    6 +-
 src/lsmsvgstyle.h                |    6 +-
 src/lsmsvgtypes.h                |    1 +
 src/lsmsvgview.c                 |   76 ++++++++++++++++++++--------
 12 files changed, 265 insertions(+), 30 deletions(-)
---
diff --git a/docs/reference/lasem/Makefile.am b/docs/reference/lasem/Makefile.am
index 4ac9476..cb8b57a 100644
--- a/docs/reference/lasem/Makefile.am
+++ b/docs/reference/lasem/Makefile.am
@@ -147,6 +147,7 @@ IGNORE_HFILES=\
 	lsmsvgmaskelement.h			\
 	lsmsvgfilterelement.h			\
 	lsmsvgfilterprimitive.h			\
+	lsmsvgfilterflood.h			\
 	lsmsvgfiltergaussianblur.h
 
 # Images to copy into HTML directory.
diff --git a/src/Makefile.am b/src/Makefile.am
index ebabeb2..cfb9577 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -126,6 +126,7 @@ LASEM_SVG_SRCS =				\
 	lsmsvgmaskelement.c			\
 	lsmsvgfilterelement.c			\
 	lsmsvgfilterprimitive.c			\
+	lsmsvgfilterflood.c			\
 	lsmsvgfiltergaussianblur.c
 
 LASEM_DOM_HDRS = 				\
@@ -231,6 +232,7 @@ LASEM_SVG_HDRS =				\
 	lsmsvgmaskelement.h			\
 	lsmsvgfilterelement.h			\
 	lsmsvgfilterprimitive.h			\
+	lsmsvgfilterflood.h			\
 	lsmsvgfiltergaussianblur.h
 
 liblasem_ LASEM_API_VERSION@_ladir = $(includedir)/lasem- LASEM_API_VERSION@
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index deeb227..34e1007 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -263,8 +263,8 @@ box_blur (LsmFilterSurface *input,
 
 void
 lsm_filter_surface_fast_blur (LsmFilterSurface *input,
-		      LsmFilterSurface *output,
-		      double sx, double sy)
+			      LsmFilterSurface *output,
+			      double sx, double sy)
 {
 	gint kx, ky;
 	guchar *intermediate;
@@ -287,6 +287,33 @@ lsm_filter_surface_fast_blur (LsmFilterSurface *input,
 	g_free (intermediate);
 }
 
+void
+lsm_filter_surface_flood (LsmFilterSurface *surface, guint32 color, double opacity)
+{
+	guint8 int_opacity;
+	char pixcolour[4];
+	int i, x, y;
+	int stride;
+	unsigned char *pixels;
+
+	g_return_if_fail (surface != NULL);
+
+	stride = cairo_image_surface_get_stride (surface->surface);
+	pixels = cairo_image_surface_get_data (surface->surface);
+
+	int_opacity = (double) (0.5 + opacity * 255.0); 
+
+	for (i = 0; i < 3; i++)
+		pixcolour[i] = (int) (((unsigned char *)
+				       (&color))[2 - i]) * int_opacity / 255;
+	pixcolour[3] = opacity;
+
+	for (y = surface->y0; y < surface->y1; y++)
+		for (x = surface->x0; x < surface->x1; x++)
+			for (i = 0; i < 4; i++)
+				pixels[4 * x + y * stride + /*ctx->channelmap[i]*/ i] = pixcolour[i];
+}
+
 /**
  * lsm_cairo_set_source_pixbuf:
  * @cr: a cairo context
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index 8955f4f..d71b176 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -52,6 +52,8 @@ LsmFilterSurface *	lsm_filter_surface_ref 			(LsmFilterSurface *filter_surface);
 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_cairo_set_source_pixbuf 		(cairo_t         *cr,
 								 const GdkPixbuf *pixbuf,
 								 gdouble          pixbuf_x,
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index 082b8ad..ed1e745 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -47,6 +47,7 @@
 #include <lsmsvgmaskelement.h>
 #include <lsmsvgfilterelement.h>
 #include <lsmsvgfiltergaussianblur.h>
+#include <lsmsvgfilterflood.h>
 #include <lsmsvgview.h>
 #include <string.h>
 
@@ -136,6 +137,8 @@ _create_element (LsmDomDocument *document, const char *tag_name)
 		node = lsm_svg_filter_element_new ();
 	else if (strcmp (tag_name, "feGaussianBlur") == 0)
 		node = lsm_svg_filter_gaussian_blur_new ();
+	else if (strcmp (tag_name, "feFlood") == 0)
+		node = lsm_svg_filter_flood_new ();
 
 	if (node != NULL)
 		lsm_debug_dom ("[LsmSvgDocument::create_element] Create a %s element", tag_name);
diff --git a/src/lsmsvgfilterflood.c b/src/lsmsvgfilterflood.c
new file mode 100644
index 0000000..11a4600
--- /dev/null
+++ b/src/lsmsvgfilterflood.c
@@ -0,0 +1,103 @@
+/* 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 <lsmsvgfilterflood.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_flood_get_node_name (LsmDomNode *node)
+{
+	return "feFlood";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_flood_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+				     const char *input, const char *output,
+				     double x, double y, double w, double h)
+{
+	lsm_svg_view_apply_flood (view, output, x, y, w, h);
+}
+
+/* LsmSvgFilterFlood implementation */
+
+static const LsmSvgOneOrTwoDouble std_deviation_default =  {.a = 0.0, .b = 0.0};
+
+LsmDomNode *
+lsm_svg_filter_flood_new (void)
+{
+	return g_object_new (LSM_TYPE_SVG_FILTER_FLOOD, NULL);
+}
+
+static void
+lsm_svg_filter_flood_init (LsmSvgFilterFlood *self)
+{
+	self->std_deviation.value = std_deviation_default;
+}
+
+static void
+lsm_svg_filter_flood_finalize (GObject *object)
+{
+	parent_class->finalize (object);
+}
+
+/* LsmSvgFilterFlood class */
+
+static const LsmAttributeInfos lsm_svg_filter_flood_attribute_infos[] = {
+	{
+		.name = "stdDeviation",
+		.attribute_offset = offsetof (LsmSvgFilterFlood, std_deviation),
+		.trait_class = &lsm_svg_one_or_two_double_trait_class,
+		.trait_default = &std_deviation_default
+	}
+};
+
+static void
+lsm_svg_filter_flood_class_init (LsmSvgFilterFloodClass *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_flood_finalize;
+
+	d_node_class->get_node_name = lsm_svg_filter_flood_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_flood_attribute_infos),
+					      lsm_svg_filter_flood_attribute_infos);
+
+	f_primitive_class->apply = lsm_svg_filter_flood_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterFlood, lsm_svg_filter_flood, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfilterflood.h b/src/lsmsvgfilterflood.h
new file mode 100644
index 0000000..5da9242
--- /dev/null
+++ b/src/lsmsvgfilterflood.h
@@ -0,0 +1,57 @@
+/* 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_FLOOD_H
+#define LSM_SVG_FILTER_FLOOD_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_FLOOD             (lsm_svg_filter_flood_get_type ())
+#define LSM_SVG_FILTER_FLOOD(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_FILTER_FLOOD, LsmSvgFilterFlood))
+#define LSM_SVG_FILTER_FLOOD_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_FILTER_FLOOD, LsmSvgFilterFloodClass))
+#define LSM_IS_SVG_FILTER_FLOOD(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_FILTER_FLOOD))
+#define LSM_IS_SVG_FILTER_FLOOD_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_FILTER_FLOOD))
+#define LSM_SVG_FILTER_FLOOD_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_FILTER_FLOOD, LsmSvgFilterFloodClass))
+
+typedef struct _LsmSvgFilterFloodClass LsmSvgFilterFloodClass;
+
+struct _LsmSvgFilterFlood {
+	LsmSvgFilterPrimitive base;
+
+	LsmSvgOneOrTwoDoubleAttribute std_deviation;
+};
+
+struct _LsmSvgFilterFloodClass {
+	LsmSvgFilterPrimitiveClass  element_class;
+};
+
+GType lsm_svg_filter_flood_get_type (void);
+
+LsmDomNode * 	lsm_svg_filter_flood_new 		(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgfilterprimitive.c b/src/lsmsvgfilterprimitive.c
index 2d9cf44..536bc6e 100644
--- a/src/lsmsvgfilterprimitive.c
+++ b/src/lsmsvgfilterprimitive.c
@@ -42,6 +42,8 @@ void
 lsm_svg_filter_primitive_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view)
 {
 	LsmSvgFilterPrimitiveClass *primitive_class;
+	const LsmSvgStyle *parent_style;
+	LsmSvgStyle *style;
 	double x, y, w, h;
 
 	g_return_if_fail (LSM_IS_SVG_FILTER_PRIMITIVE (self));
@@ -55,8 +57,13 @@ lsm_svg_filter_primitive_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view)
 
 	lsm_log_render ("[Svg::FilterPrimitive::apply] Apply %s", lsm_dom_node_get_node_name (LSM_DOM_NODE (self)));
 
+	parent_style = lsm_svg_view_get_current_style (view);
+	style = lsm_svg_style_new_inherited (parent_style, &(LSM_SVG_ELEMENT (self))->property_bag);
+
 	if (primitive_class->apply != NULL)
 		primitive_class->apply (self, view, self->in.value, self->result.value, x, y, w, h);
+
+	lsm_svg_style_unref (style);
 }
 
 static const LsmSvgLength x_y_default = 	 { .value_unit =   0.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
diff --git a/src/lsmsvgstyle.c b/src/lsmsvgstyle.c
index b2790d5..85b8b1f 100644
--- a/src/lsmsvgstyle.c
+++ b/src/lsmsvgstyle.c
@@ -74,19 +74,19 @@ static const LsmPropertyInfos lsm_svg_property_infos[] = {
 	{
 		.name = "flood-color",
 		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, flood_color),
-		.trait_class = &lsm_null_trait_class,
+		.trait_class = &lsm_svg_color_trait_class,
 		.trait_default = "black"
 	},
 	{
 		.name = "flood-opacity",
 		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, flood_opacity),
-		.trait_class = &lsm_null_trait_class,
+		.trait_class = &lsm_double_trait_class,
 		.trait_default = "1"
 	},
 	{
 		.name = "lighting-color",
 		.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, lighting_color),
-		.trait_class = &lsm_null_trait_class,
+		.trait_class = &lsm_svg_color_trait_class,
 		.trait_default = "white"
 	},
 	{
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index 56a8ebe..fca298d 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -124,9 +124,9 @@ struct _LsmSvgStyle {
 	LsmProperty *	 		dominant_baseline;
 	LsmProperty *	 		enable_background;
 	LsmProperty *	 		filter;
-	LsmProperty *	 		flood_color;
-	LsmProperty *	 		flood_opacity;
-	LsmProperty *			lighting_color;
+	LsmSvgColorProperty *		flood_color;
+	LsmSvgDoubleProperty *		flood_opacity;
+	LsmSvgColorProperty *		lighting_color;
 	LsmProperty *			mask;
 	LsmSvgDoubleProperty *		opacity;
 	LsmSvgOverflowProperty *	overflow;
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index 8ef45d8..aeefcf0 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -58,6 +58,7 @@ typedef struct _LsmSvgMaskElement LsmSvgMaskElement;
 typedef struct _LsmSvgFilterElement LsmSvgFilterElement;
 typedef struct _LsmSvgFilterPrimitive LsmSvgFilterPrimitive;
 typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
+typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
 
 typedef struct _LsmSvgView LsmSvgView;
 typedef struct _LsmSvgStyle LsmSvgStyle;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 2465e41..8457a95 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -1990,28 +1990,6 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
 
 		lsm_svg_element_force_render (filter_element, view);
 
-#if 1
-		lsm_filter_surface_copy_data (filter_surface, view->filter_surfaces->data);
-
-		cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_NONE);
-		cairo_set_source (view->pattern_data->old_cairo, view->pattern_data->pattern);
-		cairo_paint_with_alpha (view->pattern_data->old_cairo, view->pattern_data->opacity);
-#else
-		/* This is the code that should be used. But unfortunately it doesn't work.
-		 * For some reason, cairo_paint paints nothing. I fail to see why it doesn't, while
-		 * the above code does. */
-		{
-			cairo_pattern_t *pattern;
-
-			pattern = cairo_pattern_create_for_surface (lsm_filter_surface_get_cairo_surface (view->filter_surfaces->data));
-			cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
-			cairo_pattern_set_matrix (pattern, &matrix);
-			cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
-			cairo_set_source (view->pattern_data->old_cairo, pattern);
-			cairo_paint_with_alpha (view->pattern_data->old_cairo, view->pattern_data->opacity);
-		}
-#endif
-
 		if (view->debug_filter) {
 			GSList *iter;
 			char *filename;
@@ -2028,6 +2006,32 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
 			}
 		}
 
+		if (view->filter_surfaces->next != NULL) {
+#if 1
+			lsm_filter_surface_copy_data (filter_surface, view->filter_surfaces->data);
+
+			cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_NONE);
+			cairo_set_source (view->pattern_data->old_cairo, view->pattern_data->pattern);
+			cairo_paint_with_alpha (view->pattern_data->old_cairo, view->pattern_data->opacity);
+#else
+			/* This is the code that should be used. But unfortunately it doesn't work.
+			 * For some reason, cairo_paint paints nothing. I fail to see why it doesn't, while
+			 * the above code does. */
+			{
+				cairo_pattern_t *pattern;
+				cairo_surface_t *surface;
+
+				surface = lsm_filter_surface_get_cairo_surface (view->filter_surfaces->data);
+				pattern = cairo_pattern_create_for_surface (surface);
+				cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
+				cairo_pattern_set_matrix (pattern, &matrix);
+				cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
+				cairo_set_source (view->pattern_data->old_cairo, pattern);
+				cairo_paint_with_alpha (view->pattern_data->old_cairo, view->pattern_data->opacity);
+			}
+#endif
+		}
+
 		for (iter = view->filter_surfaces; iter != NULL; iter = iter->next)
 			lsm_filter_surface_unref (iter->data);
 		g_slist_free (view->filter_surfaces);
@@ -2100,6 +2104,34 @@ lsm_svg_view_apply_gaussian_blur (LsmSvgView *view, const char *input, const cha
 }
 
 void
+lsm_svg_view_apply_flood (LsmSvgView *view, const char *output,
+			  double x, double y, double w, double h)
+{
+	LsmFilterSurface *output_surface;
+	LsmFilterSurface *input_surface;
+	guint8 red, green, blue;
+	guint32 color;
+	double opacity;
+
+	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+
+	input_surface = _get_filter_surface (view, NULL);
+
+	output_surface = _create_filter_surface (view, output, input_surface);
+
+	red = (double) (0.5 + view->style->flood_color->value.red * 255.0);
+	green = (double) (0.5 + view->style->flood_color->value.green * 255.0);
+	blue = (double) (0.5 + view->style->flood_color->value.blue * 255.0);
+	color = red << 16 | green << 8 | blue << 0;
+	opacity = view->style->fill_opacity->value;
+
+	lsm_log_render ("[SvgView::apply_flood] color = 0x%06x - opacity = %g",
+			color, opacity);
+
+	lsm_filter_surface_flood (output_surface, color, opacity);
+}
+
+void
 lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));



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