[lasem] svg: add beginning of feBlend support. Fix feFlood.



commit 31be1ce5e8f9cf3faa4005df76e205558ea44c5c
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Sun Oct 14 17:04:27 2012 +0200

    svg: add beginning of feBlend support. Fix feFlood.

 docs/reference/lasem/Makefile.am |    1 +
 src/Makefile.am                  |    2 +
 src/lsmcairo.c                   |   78 +++++++++++++++++++---------
 src/lsmcairo.h                   |    7 ++-
 src/lsmsvgattributes.h           |    5 ++
 src/lsmsvgdocument.c             |    9 ++-
 src/lsmsvgenums.c                |   24 +++++++++
 src/lsmsvgenums.h                |   13 +++++
 src/lsmsvgfilterblend.c          |  106 ++++++++++++++++++++++++++++++++++++++
 src/lsmsvgfilterblend.h          |   58 +++++++++++++++++++++
 src/lsmsvgtraits.c               |   24 +++++++++
 src/lsmsvgtraits.h               |    1 +
 src/lsmsvgtypes.h                |    3 +-
 src/lsmsvgview.c                 |   91 ++++++++++++++++++--------------
 src/lsmsvgview.h                 |    2 +
 15 files changed, 355 insertions(+), 69 deletions(-)
---
diff --git a/docs/reference/lasem/Makefile.am b/docs/reference/lasem/Makefile.am
index cb8b57a..d505435 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			\
+	lsmsvgfilterblend.h			\
 	lsmsvgfilterflood.h			\
 	lsmsvgfiltergaussianblur.h
 
diff --git a/src/Makefile.am b/src/Makefile.am
index cfb9577..cd1b0d8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -126,6 +126,7 @@ LASEM_SVG_SRCS =				\
 	lsmsvgmaskelement.c			\
 	lsmsvgfilterelement.c			\
 	lsmsvgfilterprimitive.c			\
+	lsmsvgfilterblend.c			\
 	lsmsvgfilterflood.c			\
 	lsmsvgfiltergaussianblur.c
 
@@ -232,6 +233,7 @@ LASEM_SVG_HDRS =				\
 	lsmsvgmaskelement.h			\
 	lsmsvgfilterelement.h			\
 	lsmsvgfilterprimitive.h			\
+	lsmsvgfilterblend.h			\
 	lsmsvgfilterflood.h			\
 	lsmsvgfiltergaussianblur.h
 
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index 34e1007..4b31cd1 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -1,7 +1,7 @@
 /* Lasem
  *
  * Copyright  2004 Caleb Moore
- * Copyright  2010 Emmanuel Pacaud
+ * 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
@@ -24,6 +24,7 @@
  */
 
 #include <lsmcairo.h>
+#include <lsmsvgenums.h>
 #include <math.h>
 #include <string.h>
 
@@ -84,26 +85,6 @@ lsm_filter_surface_new_similar (const char *name, LsmFilterSurface *model)
 	return lsm_filter_surface_new (name, model->x0, model->y0, model->x1, model->y1);
 }
 
-void
-lsm_filter_surface_copy_data (LsmFilterSurface *to, LsmFilterSurface *from)
-{
-	size_t to_size;
-	size_t from_size;
-	void *to_data;
-	void *from_data;
-
-	g_return_if_fail (to != NULL);
-	g_return_if_fail (from != NULL);
-
-	to_size = cairo_image_surface_get_height (to->surface) * cairo_image_surface_get_stride (to->surface);
-	from_size = cairo_image_surface_get_height (from->surface) * cairo_image_surface_get_stride (from->surface);
-	to_data = cairo_image_surface_get_data (to->surface);
-	from_data = cairo_image_surface_get_data (from->surface);
-	
-	if (to_size == from_size)
-		memcpy (to_data, from_data, to_size);
-}
-
 const char *
 lsm_filter_surface_get_name (LsmFilterSurface *surface)
 {
@@ -285,6 +266,8 @@ lsm_filter_surface_fast_blur (LsmFilterSurface *input,
 	box_blur (output, output, intermediate, kx, ky);
 
 	g_free (intermediate);
+
+	cairo_surface_mark_dirty (output->surface);
 }
 
 void
@@ -295,6 +278,7 @@ lsm_filter_surface_flood (LsmFilterSurface *surface, guint32 color, double opaci
 	int i, x, y;
 	int stride;
 	unsigned char *pixels;
+	int channelmap[4] = {0, 1, 2, 3};
 
 	g_return_if_fail (surface != NULL);
 
@@ -306,12 +290,58 @@ lsm_filter_surface_flood (LsmFilterSurface *surface, guint32 color, double opaci
 	for (i = 0; i < 3; i++)
 		pixcolour[i] = (int) (((unsigned char *)
 				       (&color))[2 - i]) * int_opacity / 255;
-	pixcolour[3] = opacity;
+	pixcolour[3] = int_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];
+			for (i = 0; i < 4; i++) {
+				pixels[4 * x + y * stride + channelmap[i]] = pixcolour[i];
+			}
+
+	cairo_surface_mark_dirty (surface->surface);
+}
+
+void
+lsm_filter_surface_blend (LsmFilterSurface *input_1,
+			  LsmFilterSurface *input_2,
+			  LsmFilterSurface *output,
+			  int blending_mode)
+{
+	cairo_t *cairo;
+	cairo_operator_t op;
+
+	g_return_if_fail (input_1 != NULL);
+	g_return_if_fail (input_2 != NULL);
+	g_return_if_fail (output != NULL);
+
+	switch (blending_mode) {
+		case LSM_SVG_BLENDING_MODE_MULTIPLY:
+			op = CAIRO_OPERATOR_MULTIPLY;
+			break;
+		case LSM_SVG_BLENDING_MODE_SCREEN:
+			op = CAIRO_OPERATOR_SCREEN;
+			break;
+		case LSM_SVG_BLENDING_MODE_DARKEN:
+			op = CAIRO_OPERATOR_DARKEN;
+			break;
+		case LSM_SVG_BLENDING_MODE_LIGHTEN:
+			op = CAIRO_OPERATOR_LIGHTEN;
+			break;
+		default:
+			op = CAIRO_OPERATOR_OVER;
+			break;
+	}
+
+	cairo = cairo_create (output->surface);
+
+	cairo_set_source_surface (cairo, input_1->surface, 0, 0);
+	cairo_paint (cairo);
+
+	cairo_set_source_surface (cairo, input_2->surface, 0, 0);
+	cairo_set_operator (cairo, op);
+	cairo_paint (cairo);
+
+	cairo_destroy (cairo);
 }
 
 /**
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index d71b176..102081f 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -1,6 +1,6 @@
 /* Lasem
  *
- * Copyright  2010 Emmanuel Pacaud
+ * 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
@@ -25,6 +25,7 @@
 #define LSM_CAIRO_H
 
 #include <lsmtypes.h>
+#include <lsmsvgenums.h>
 #include <cairo.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
@@ -49,6 +50,10 @@ cairo_surface_t *	lsm_filter_surface_get_cairo_surface	(LsmFilterSurface *surfac
 void 			lsm_filter_surface_unref 		(LsmFilterSurface *filter_surface);
 LsmFilterSurface *	lsm_filter_surface_ref 			(LsmFilterSurface *filter_surface);
 
+void 			lsm_filter_surface_blend 		(LsmFilterSurface *input_1,
+								 LsmFilterSurface *input_2,
+								 LsmFilterSurface *output,
+								 int blending_mode);
 void 			lsm_filter_surface_fast_blur 		(LsmFilterSurface *input,
 								 LsmFilterSurface *output,
 								 double sx, double sy);
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index 1d50919..3e5c8e4 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -35,6 +35,11 @@ G_BEGIN_DECLS
 
 typedef struct {
 	LsmAttribute base;
+	LsmSvgBlendingMode value;
+} LsmSvgBlendingModeAttribute;
+
+typedef struct {
+	LsmAttribute base;
 	double value;
 } LsmSvgDoubleAttribute;
 
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index ed1e745..7fc90b6 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -46,8 +46,9 @@
 #include <lsmsvgpatternelement.h>
 #include <lsmsvgmaskelement.h>
 #include <lsmsvgfilterelement.h>
-#include <lsmsvgfiltergaussianblur.h>
+#include <lsmsvgfilterblend.h>
 #include <lsmsvgfilterflood.h>
+#include <lsmsvgfiltergaussianblur.h>
 #include <lsmsvgview.h>
 #include <string.h>
 
@@ -135,10 +136,12 @@ _create_element (LsmDomDocument *document, const char *tag_name)
 		node = lsm_svg_clip_path_element_new ();
 	else if (strcmp (tag_name, "filter") == 0)
 		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, "feBlend") == 0)
+		node = lsm_svg_filter_blend_new ();
 	else if (strcmp (tag_name, "feFlood") == 0)
 		node = lsm_svg_filter_flood_new ();
+	else if (strcmp (tag_name, "feGaussianBlur") == 0)
+		node = lsm_svg_filter_gaussian_blur_new ();
 
 	if (node != NULL)
 		lsm_debug_dom ("[LsmSvgDocument::create_element] Create a %s element", tag_name);
diff --git a/src/lsmsvgenums.c b/src/lsmsvgenums.c
index 8a31c3d..95c8b69 100644
--- a/src/lsmsvgenums.c
+++ b/src/lsmsvgenums.c
@@ -25,6 +25,30 @@
 #include <lsmtraits.h>
 #include <string.h>
 
+static const char *lsm_svg_blending_mode_strings[] = {
+	"normal",
+	"multiply",
+	"screen",
+	"darken",
+	"lighten"
+};
+
+const char *
+lsm_svg_blending_mode_to_string (LsmSvgBlendingMode blending_mode)
+{
+	if (blending_mode < 0 || blending_mode > LSM_SVG_BLENDING_MODE_LIGHTEN)
+		return NULL;
+
+	return lsm_svg_blending_mode_strings[blending_mode];
+}
+
+LsmSvgBlendingMode
+lsm_svg_blending_mode_from_string (const char *string)
+{
+	return lsm_enum_value_from_string (string, lsm_svg_blending_mode_strings,
+					   G_N_ELEMENTS (lsm_svg_blending_mode_strings));
+}
+
 static const char *lsm_svg_length_type_strings[] = {
 	"",
 	"%",
diff --git a/src/lsmsvgenums.h b/src/lsmsvgenums.h
index 942cbed..003c0e5 100644
--- a/src/lsmsvgenums.h
+++ b/src/lsmsvgenums.h
@@ -25,6 +25,7 @@
 #define LSM_SVG_ENUMS_H
 
 #include <glib-object.h>
+#include <lsmtypes.h>
 
 G_BEGIN_DECLS
 
@@ -35,6 +36,18 @@ typedef enum {
 } LsmSvgAngleType;
 
 typedef enum {
+	LSM_SVG_BLENDING_MODE_ERROR = -1,
+	LSM_SVG_BLENDING_MODE_NORMAL,
+	LSM_SVG_BLENDING_MODE_MULTIPLY,
+	LSM_SVG_BLENDING_MODE_SCREEN,
+	LSM_SVG_BLENDING_MODE_DARKEN,
+	LSM_SVG_BLENDING_MODE_LIGHTEN
+} LsmSvgBlendingMode;
+
+const char * 		lsm_svg_blending_mode_to_string 	(LsmSvgBlendingMode blending_mode);
+LsmSvgBlendingMode	lsm_svg_blending_mode_from_string 	(const char *string);
+
+typedef enum {
 	LSM_SVG_PAINT_TYPE_ERROR = -1,
 	LSM_SVG_PAINT_TYPE_UNKNOWN = 0,
 	LSM_SVG_PAINT_TYPE_RGB_COLOR,
diff --git a/src/lsmsvgfilterblend.c b/src/lsmsvgfilterblend.c
new file mode 100644
index 0000000..a72257e
--- /dev/null
+++ b/src/lsmsvgfilterblend.c
@@ -0,0 +1,106 @@
+/* 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 <lsmsvgfilterblend.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_blend_get_node_name (LsmDomNode *node)
+{
+	return "feBlend";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_blend_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+			     const char *input, const char *output,
+			     double x, double y, double w, double h)
+{
+	LsmSvgFilterBlend *blend = LSM_SVG_FILTER_BLEND (self);
+
+	lsm_svg_view_apply_blend (view, input, blend->in2.value, output, blend->mode.value);
+}
+
+/* LsmSvgFilterBlend implementation */
+
+LsmDomNode *
+lsm_svg_filter_blend_new (void)
+{
+	return g_object_new (LSM_TYPE_SVG_FILTER_BLEND, NULL);
+}
+
+static void
+lsm_svg_filter_blend_init (LsmSvgFilterBlend *self)
+{
+}
+
+static void
+lsm_svg_filter_blend_finalize (GObject *object)
+{
+	parent_class->finalize (object);
+}
+
+/* LsmSvgFilterBlend class */
+
+static const LsmAttributeInfos lsm_svg_filter_blend_attribute_infos[] = {
+	{
+		.name = "in2",
+		.attribute_offset = offsetof (LsmSvgFilterBlend, in2),
+		.trait_class = &lsm_null_trait_class
+	},
+	{
+		.name = "mode",
+		.attribute_offset = offsetof (LsmSvgFilterBlend, mode),
+		.trait_class = &lsm_svg_blending_mode_trait_class
+	}
+};
+
+static void
+lsm_svg_filter_blend_class_init (LsmSvgFilterBlendClass *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_blend_finalize;
+
+	d_node_class->get_node_name = lsm_svg_filter_blend_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_blend_attribute_infos),
+					      lsm_svg_filter_blend_attribute_infos);
+
+	f_primitive_class->apply = lsm_svg_filter_blend_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterBlend, lsm_svg_filter_blend, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfilterblend.h b/src/lsmsvgfilterblend.h
new file mode 100644
index 0000000..69e05ed
--- /dev/null
+++ b/src/lsmsvgfilterblend.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_BLEND_H
+#define LSM_SVG_FILTER_BLEND_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_BLEND             (lsm_svg_filter_blend_get_type ())
+#define LSM_SVG_FILTER_BLEND(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_FILTER_BLEND, LsmSvgFilterBlend))
+#define LSM_SVG_FILTER_BLEND_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_FILTER_BLEND, LsmSvgFilterBlendClass))
+#define LSM_IS_SVG_FILTER_BLEND(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_FILTER_BLEND))
+#define LSM_IS_SVG_FILTER_BLEND_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_FILTER_BLEND))
+#define LSM_SVG_FILTER_BLEND_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_FILTER_BLEND, LsmSvgFilterBlendClass))
+
+typedef struct _LsmSvgFilterBlendClass LsmSvgFilterBlendClass;
+
+struct _LsmSvgFilterBlend {
+	LsmSvgFilterPrimitive base;
+
+	LsmAttribute in2;
+	LsmSvgBlendingModeAttribute mode;
+};
+
+struct _LsmSvgFilterBlendClass {
+	LsmSvgFilterPrimitiveClass  element_class;
+};
+
+GType lsm_svg_filter_blend_get_type (void);
+
+LsmDomNode * 	lsm_svg_filter_blend_new 		(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
index 5b4299b..d79a57c 100644
--- a/src/lsmsvgtraits.c
+++ b/src/lsmsvgtraits.c
@@ -32,6 +32,30 @@ const LsmSvgColor lsm_svg_color_null = {0.0, 0.0, 0.0};
 const LsmSvgDashArray lsm_svg_dash_array_null = {0, NULL};
 
 static gboolean
+lsm_svg_blending_mode_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmSvgBlendingMode *trait = (LsmSvgBlendingMode *) abstract_trait;
+
+	*trait = lsm_svg_blending_mode_from_string (string);
+
+	return *trait >= 0;
+}
+
+char *
+lsm_svg_blending_mode_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmSvgBlendingMode *trait = (LsmSvgBlendingMode *) abstract_trait;
+
+	return g_strdup (lsm_svg_blending_mode_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_blending_mode_trait_class = {
+	.size = sizeof (LsmSvgBlendingMode),
+	.from_string = lsm_svg_blending_mode_trait_from_string,
+	.to_string = lsm_svg_blending_mode_trait_to_string
+};
+
+static gboolean
 lsm_svg_length_trait_from_string (LsmTrait *abstract_trait, char *string)
 {
 	LsmSvgLength *svg_length = (LsmSvgLength *) abstract_trait;
diff --git a/src/lsmsvgtraits.h b/src/lsmsvgtraits.h
index 716da41..8cd0a91 100644
--- a/src/lsmsvgtraits.h
+++ b/src/lsmsvgtraits.h
@@ -73,6 +73,7 @@ typedef struct {
 } LsmSvgOneOrTwoDouble;
 
 extern const LsmTraitClass lsm_svg_angle_trait_class;
+extern const LsmTraitClass lsm_svg_blending_mode_trait_class;
 extern const LsmTraitClass lsm_svg_color_trait_class;
 extern const LsmTraitClass lsm_svg_dash_array_trait_class;
 extern const LsmTraitClass lsm_svg_display_trait_class;
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index aeefcf0..fa8b0b1 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -57,8 +57,9 @@ typedef struct _LsmSvgPatternElement LsmSvgPatternElement;
 typedef struct _LsmSvgMaskElement LsmSvgMaskElement;
 typedef struct _LsmSvgFilterElement LsmSvgFilterElement;
 typedef struct _LsmSvgFilterPrimitive LsmSvgFilterPrimitive;
-typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
+typedef struct _LsmSvgFilterBlend LsmSvgFilterBlend;
 typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
+typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
 
 typedef struct _LsmSvgView LsmSvgView;
 typedef struct _LsmSvgStyle LsmSvgStyle;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index e01836f..da2fba5 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -2007,29 +2007,15 @@ 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_t *pattern;
+			cairo_surface_t *surface;
 
-			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
+			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_set_source (view->pattern_data->old_cairo, pattern);
+			cairo_paint (view->pattern_data->old_cairo);
 		}
 
 		for (iter = view->filter_surfaces; iter != NULL; iter = iter->next)
@@ -2072,35 +2058,28 @@ _create_filter_surface (LsmSvgView *view, const char *output, LsmFilterSurface *
 }
 
 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)
+lsm_svg_view_apply_blend (LsmSvgView *view, const char *input_1, const char*input_2, const char *output,
+			  LsmSvgBlendingMode mode)
 {
-	LsmFilterSurface *input_surface;
 	LsmFilterSurface *output_surface;
+	LsmFilterSurface *input_1_surface;
+	LsmFilterSurface *input_2_surface;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
-	input_surface = _get_filter_surface (view, input);
+	input_1_surface = _get_filter_surface (view, input_1);
+	input_2_surface = _get_filter_surface (view, input_2);
 
-	if (input_surface == NULL) {
-		lsm_debug_render ("[SvgView::apply_gaussian_blur] Input '%s' not found", input);
+	if (input_1_surface == NULL || input_2_surface == NULL) {
+		lsm_debug_render ("[SvgView::apply_blend] Inputs '%s' or '%s' not found", input_1, input_2);
 		return;
 	}
 
-	output_surface = _create_filter_surface (view, output, input_surface);
+	output_surface = _create_filter_surface (view, output, input_1_surface);
 
-	lsm_log_render ("[SvgView::apply_gaussian_blur] %s -> %s (x:%g,y:%g,w:%g,h:%g) (%g,%g)",
-			input != NULL ? input : "previous",
-			output != NULL ? output : "next",
-			x, y, w, h, std_x, std_y); 
-
-	cairo_user_to_device_distance (view->dom_view.cairo, &std_x, &std_y);
+	lsm_log_render ("[SvgView::blend] mode = %s", lsm_svg_blending_mode_to_string (mode));
 
-	lsm_log_render ("[SvgView::apply_gaussian_blur] %g px,%g px",
-			std_x, std_y);
-
-	lsm_filter_surface_fast_blur (input_surface, output_surface, std_x, std_y);
+	lsm_filter_surface_blend (input_1_surface, input_2_surface, output_surface, mode);
 }
 
 void
@@ -2132,6 +2111,38 @@ 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)
+{
+	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_gaussian_blur] Input '%s' not found", input);
+		return;
+	}
+
+	output_surface = _create_filter_surface (view, output, input_surface);
+
+	lsm_log_render ("[SvgView::apply_gaussian_blur] %s -> %s (x:%g,y:%g,w:%g,h:%g) (%g,%g)",
+			input != NULL ? input : "previous",
+			output != NULL ? output : "next",
+			x, y, w, h, std_x, std_y); 
+
+	cairo_user_to_device_distance (view->dom_view.cairo, &std_x, &std_y);
+
+	lsm_log_render ("[SvgView::apply_gaussian_blur] %g px,%g px",
+			std_x, std_y);
+
+	lsm_filter_surface_fast_blur (input_surface, output_surface, std_x, std_y);
+}
+
+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 cde1146..002ef54 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -154,6 +154,8 @@ void		lsm_svg_view_pop_style			(LsmSvgView *view);
 
 LsmSvgStyle *	lsm_svg_view_get_current_style	(LsmSvgView *view);
 
+void 		lsm_svg_view_apply_blend 		(LsmSvgView *view, const char *input_1, const char*input_2, const char *output,
+							 LsmSvgBlendingMode mode);
 void 		lsm_svg_view_apply_flood 		(LsmSvgView *view, const char *output,
 							 double x, double y, double w, double h);
 void		lsm_svg_view_apply_gaussian_blur 	(LsmSvgView *view, const char *input, const char *output,



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