[lasem] svg_filter: start to support primitive subregion.



commit 9121c555814090a329e021dbe3cd63a9c6c77221
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Thu Oct 18 17:39:31 2012 +0200

    svg_filter: start to support primitive subregion.

 docs/reference/lasem/Makefile.am |    3 +-
 src/Makefile.am                  |    7 ++-
 src/lsmcairo.c                   |   69 +++++++++++--------------
 src/lsmcairo.h                   |   15 +++--
 src/lsmsvgdocument.c             |    3 +
 src/lsmsvgfilterblend.c          |    5 +-
 src/lsmsvgfiltercomposite.c      |    5 +-
 src/lsmsvgfilterflood.c          |    5 +-
 src/lsmsvgfiltergaussianblur.c   |    7 +--
 src/lsmsvgfiltermerge.c          |    2 +-
 src/lsmsvgfiltermergenode.c      |    5 +-
 src/lsmsvgfilteroffset.c         |    5 +-
 src/lsmsvgfilterprimitive.c      |   16 +++---
 src/lsmsvgfilterprimitive.h      |    3 +-
 src/lsmsvgfiltertile.c           |  102 ++++++++++++++++++++++++++++++++++++++
 src/lsmsvgfiltertile.h           |   57 +++++++++++++++++++++
 src/lsmsvgtypes.h                |    3 +-
 src/lsmsvgview.c                 |   70 +++++++++++++++++---------
 src/lsmsvgview.h                 |   14 +++---
 19 files changed, 286 insertions(+), 110 deletions(-)
---
diff --git a/docs/reference/lasem/Makefile.am b/docs/reference/lasem/Makefile.am
index 582f8c0..feae0c0 100644
--- a/docs/reference/lasem/Makefile.am
+++ b/docs/reference/lasem/Makefile.am
@@ -153,7 +153,8 @@ IGNORE_HFILES=\
 	lsmsvgfiltergaussianblur.h		\
 	lsmsvgfilteroffset.h			\
 	lsmsvgfiltermerge.h			\
-	lsmsvgfiltermergenode.h
+	lsmsvgfiltermergenode.h			\
+	lsmsvgfiltertile.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 4324367..e7d6510 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -132,7 +132,8 @@ LASEM_SVG_SRCS =				\
 	lsmsvgfiltergaussianblur.c		\
 	lsmsvgfilteroffset.c			\
 	lsmsvgfiltermerge.c			\
-	lsmsvgfiltermergenode.c
+	lsmsvgfiltermergenode.c			\
+	lsmsvgfiltertile.c
 
 LASEM_DOM_HDRS = 				\
 	lsm.h					\
@@ -243,7 +244,9 @@ LASEM_SVG_HDRS =				\
 	lsmsvgfiltergaussianblur.h		\
 	lsmsvgfilteroffset.h			\
 	lsmsvgfiltermerge.h			\
-	lsmsvgfiltermergenode.h
+	lsmsvgfiltermergenode.h			\
+	lsmsvgfiltertile.h
+
 
 liblasem_ LASEM_API_VERSION@_ladir = $(includedir)/lasem- LASEM_API_VERSION@
 
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index c1c408c..6c29a5c 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -246,6 +246,7 @@ box_blur (LsmFilterSurface *input,
 void
 lsm_filter_surface_fast_blur (LsmFilterSurface *input,
 			      LsmFilterSurface *output,
+			      const LsmBox *subregion,
 			      double sx, double sy)
 {
 	gint kx, ky;
@@ -286,42 +287,31 @@ lsm_filter_surface_fast_blur (LsmFilterSurface *input,
 }
 
 void
-lsm_filter_surface_flood (LsmFilterSurface *surface, guint32 color, double opacity)
+lsm_filter_surface_flood (LsmFilterSurface *surface,
+			  const LsmBox *subregion,
+			  double red,
+			  double green,
+			  double blue,
+			  double opacity)
 {
-	guint8 int_opacity;
-	char pixcolour[4];
-	int i, x, y;
-	int stride;
-	unsigned char *pixels;
-	int channelmap[4] = {2, 1, 0, 3};
+	cairo_t *cairo;
 
 	g_return_if_fail (surface != NULL);
 
-	cairo_surface_flush (surface->surface);
-
-	stride = cairo_image_surface_get_stride (surface->surface);
-	pixels = cairo_image_surface_get_data (surface->surface);
-
-	int_opacity = (double) (0.5 + (double) opacity * 255.0); 
-
-	for (i = 0; i < 3; i++)
-		pixcolour[i] = (int) (((unsigned char *)
-				       (&color))[2 - i]) * int_opacity / 255;
-	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 + channelmap[i]] = pixcolour[i];
-			}
-
-	cairo_surface_mark_dirty (surface->surface);
+	cairo = cairo_create (surface->surface);
+	if (subregion != NULL) {
+		cairo_rectangle (cairo, subregion->x, subregion->y, subregion->width, subregion->height);
+		cairo_clip (cairo);
+	}
+	cairo_set_source_rgba (cairo, red, green, blue, opacity);
+	cairo_paint (cairo);
 }
 
 void
 lsm_filter_surface_blend (LsmFilterSurface *input_1,
 			  LsmFilterSurface *input_2,
 			  LsmFilterSurface *output,
+			  const LsmBox *subregion,
 			  int blending_mode)
 {
 	cairo_t *cairo;
@@ -331,9 +321,6 @@ lsm_filter_surface_blend (LsmFilterSurface *input_1,
 	g_return_if_fail (input_2 != NULL);
 	g_return_if_fail (output != NULL);
 
-	cairo_surface_flush (input_1->surface);
-	cairo_surface_flush (input_2->surface);
-
 	switch (blending_mode) {
 		case LSM_SVG_BLENDING_MODE_MULTIPLY:
 			op = CAIRO_OPERATOR_MULTIPLY;
@@ -365,20 +352,22 @@ lsm_filter_surface_blend (LsmFilterSurface *input_1,
 	}
 
 	cairo = cairo_create (output->surface);
-
+	if (subregion != NULL) {
+		cairo_rectangle (cairo, subregion->x, subregion->y, subregion->width, subregion->height);
+		cairo_clip (cairo);
+	}
 	cairo_set_source_surface (cairo, input_2->surface, 0, 0);
 	cairo_paint (cairo);
-
 	cairo_set_source_surface (cairo, input_1->surface, 0, 0);
 	cairo_set_operator (cairo, op);
 	cairo_paint (cairo);
-
 	cairo_destroy (cairo);
 }
 
 void
 lsm_filter_surface_offset (LsmFilterSurface *input,
 			   LsmFilterSurface *output,
+			   const LsmBox *subregion,
 			   int dx, int dy)
 {
 	cairo_t *cairo;
@@ -386,9 +375,11 @@ lsm_filter_surface_offset (LsmFilterSurface *input,
 	g_return_if_fail (input != NULL);
 	g_return_if_fail (output != NULL);
 
-	cairo_surface_flush (input->surface);
-
 	cairo = cairo_create (output->surface);
+	if (subregion != NULL) {
+		cairo_rectangle (cairo, subregion->x, subregion->y, subregion->width, subregion->height);
+		cairo_clip (cairo);
+	}
 	cairo_set_source_surface (cairo, input->surface, dx, dy);
 	cairo_paint (cairo);
 	cairo_destroy (cairo);
@@ -396,19 +387,21 @@ lsm_filter_surface_offset (LsmFilterSurface *input,
 
 void
 lsm_filter_surface_merge (LsmFilterSurface *input,
-			  LsmFilterSurface *output)
+			  LsmFilterSurface *output,
+			  const LsmBox *subregion)
 {
 	cairo_t *cairo;
 
 	g_return_if_fail (input != NULL);
 	g_return_if_fail (output != NULL);
 
-	cairo_surface_flush (input->surface);
-
 	cairo = cairo_create (output->surface);
+	if (subregion != NULL) {
+		cairo_rectangle (cairo, subregion->x, subregion->y, subregion->width, subregion->height);
+		cairo_clip (cairo);
+	}
 	cairo_set_source_surface (cairo, input->surface, 0, 0);
 	cairo_paint (cairo);
-
 	cairo_destroy (cairo);
 }
 
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index 2b93ffd..c15b6c9 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -53,13 +53,16 @@ void 			lsm_filter_surface_alpha 		(LsmFilterSurface *input, LsmFilterSurface *o
 void 			lsm_filter_surface_blend 		(LsmFilterSurface *input_1,
 								 LsmFilterSurface *input_2,
 								 LsmFilterSurface *output,
+								 const LsmBox *subregion,
 								 int blending_mode);
-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_filter_surface_merge 		(LsmFilterSurface *input, LsmFilterSurface *output);
+void 			lsm_filter_surface_fast_blur 		(LsmFilterSurface *input, LsmFilterSurface *output,
+								 const LsmBox *subregion, double sx, double sy);
+void 			lsm_filter_surface_flood 		(LsmFilterSurface *surface, const LsmBox *subregion,
+								 double red, double green, double blue, double opacity);
+void 			lsm_filter_surface_offset 		(LsmFilterSurface *input, LsmFilterSurface *output,
+								const LsmBox *subregion, int dx, int dy);
+void 			lsm_filter_surface_merge 		(LsmFilterSurface *input, LsmFilterSurface *output,
+								 const LsmBox *subregion);
 
 void 			lsm_cairo_set_source_pixbuf 		(cairo_t         *cr,
 								 const GdkPixbuf *pixbuf,
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index 64fdff8..4a57700 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -53,6 +53,7 @@
 #include <lsmsvgfilteroffset.h>
 #include <lsmsvgfiltermerge.h>
 #include <lsmsvgfiltermergenode.h>
+#include <lsmsvgfiltertile.h>
 #include <lsmsvgview.h>
 #include <string.h>
 
@@ -154,6 +155,8 @@ _create_element (LsmDomDocument *document, const char *tag_name)
 		node = lsm_svg_filter_merge_node_new ();
 	else if (strcmp (tag_name, "feOffset") == 0)
 		node = lsm_svg_filter_offset_new ();
+	else if (strcmp (tag_name, "feTile") == 0)
+		node = lsm_svg_filter_tile_new ();
 
 	if (node != NULL)
 		lsm_debug_dom ("[LsmSvgDocument::create_element] Create a %s element", tag_name);
diff --git a/src/lsmsvgfilterblend.c b/src/lsmsvgfilterblend.c
index a72257e..ede028e 100644
--- a/src/lsmsvgfilterblend.c
+++ b/src/lsmsvgfilterblend.c
@@ -38,12 +38,11 @@ lsm_svg_filter_blend_get_node_name (LsmDomNode *node)
 
 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)
+			     const char *input, const char *output, const LsmBox *subregion)
 {
 	LsmSvgFilterBlend *blend = LSM_SVG_FILTER_BLEND (self);
 
-	lsm_svg_view_apply_blend (view, input, blend->in2.value, output, blend->mode.value);
+	lsm_svg_view_apply_blend (view, input, blend->in2.value, output, subregion, blend->mode.value);
 }
 
 /* LsmSvgFilterBlend implementation */
diff --git a/src/lsmsvgfiltercomposite.c b/src/lsmsvgfiltercomposite.c
index 1730ae8..7dce135 100644
--- a/src/lsmsvgfiltercomposite.c
+++ b/src/lsmsvgfiltercomposite.c
@@ -38,12 +38,11 @@ lsm_svg_filter_composite_get_node_name (LsmDomNode *node)
 
 static void
 lsm_svg_filter_composite_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
-				     const char *input, const char *output,
-				     double x, double y, double w, double h)
+				     const char *input, const char *output, const LsmBox *subregion)
 {
 	LsmSvgFilterComposite *composite = LSM_SVG_FILTER_COMPOSITE (self);
 
-	lsm_svg_view_apply_blend (view, input, composite->in2.value, output, composite->op.value);
+	lsm_svg_view_apply_blend (view, input, composite->in2.value, output, subregion, composite->op.value);
 }
 
 /* LsmSvgFilterComposite implementation */
diff --git a/src/lsmsvgfilterflood.c b/src/lsmsvgfilterflood.c
index 11a4600..eda740c 100644
--- a/src/lsmsvgfilterflood.c
+++ b/src/lsmsvgfilterflood.c
@@ -38,10 +38,9 @@ lsm_svg_filter_flood_get_node_name (LsmDomNode *node)
 
 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)
+				     const char *input, const char *output, const LsmBox *subregion)
 {
-	lsm_svg_view_apply_flood (view, output, x, y, w, h);
+	lsm_svg_view_apply_flood (view, output, subregion);
 }
 
 /* LsmSvgFilterFlood implementation */
diff --git a/src/lsmsvgfiltergaussianblur.c b/src/lsmsvgfiltergaussianblur.c
index b96a4b3..755a9f8 100644
--- a/src/lsmsvgfiltergaussianblur.c
+++ b/src/lsmsvgfiltergaussianblur.c
@@ -38,8 +38,7 @@ lsm_svg_filter_gaussian_blur_get_node_name (LsmDomNode *node)
 
 static void
 lsm_svg_filter_gaussian_blur_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
-				     const char *input, const char *output,
-				     double x, double y, double w, double h)
+				     const char *input, const char *output, const LsmBox *subregion)
 {
 	LsmSvgFilterGaussianBlur *blur = LSM_SVG_FILTER_GAUSSIAN_BLUR (self);
 	LsmSvgLength length;
@@ -53,9 +52,7 @@ lsm_svg_filter_gaussian_blur_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *vi
 	length.value_unit = blur->std_deviation.value.b;
 	std_b = lsm_svg_view_normalize_length (view, &length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 
-	lsm_svg_view_apply_gaussian_blur (view, input, output,
-					  x, y, w, h,
-					  std_a, std_b);
+	lsm_svg_view_apply_gaussian_blur (view, input, output, subregion, std_a, std_b);
 }
 
 /* LsmSvgFilterGaussianBlur implementation */
diff --git a/src/lsmsvgfiltermerge.c b/src/lsmsvgfiltermerge.c
index 76c39a9..ae859e3 100644
--- a/src/lsmsvgfiltermerge.c
+++ b/src/lsmsvgfiltermerge.c
@@ -46,7 +46,7 @@ lsm_svg_filter_merge_can_append_child (LsmDomNode *self, LsmDomNode *child)
 static void
 lsm_svg_filter_merge_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
 			     const char *input, const char *output,
-			     double x, double y, double w, double h)
+			     const LsmBox *subregion)
 {
 	LsmDomNode *iter;
 
diff --git a/src/lsmsvgfiltermergenode.c b/src/lsmsvgfiltermergenode.c
index da11e51..4c49e5a 100644
--- a/src/lsmsvgfiltermergenode.c
+++ b/src/lsmsvgfiltermergenode.c
@@ -38,11 +38,10 @@ lsm_svg_filter_merge_node_get_node_name (LsmDomNode *node)
 
 static void
 lsm_svg_filter_merge_node_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
-				  const char *input, const char *output,
-				  double x, double y, double w, double h)
+				  const char *input, const char *output, const LsmBox *subregion)
 {
 	/* FIXME We probably want to retrieve output name from parent feMerge element */
-	lsm_svg_view_apply_merge (view, input, "MergeSurface");
+	lsm_svg_view_apply_merge (view, input, "MergeSurface", subregion);
 }
 
 /* LsmSvgFilterMergeNode implementation */
diff --git a/src/lsmsvgfilteroffset.c b/src/lsmsvgfilteroffset.c
index 2abe1a9..91866d4 100644
--- a/src/lsmsvgfilteroffset.c
+++ b/src/lsmsvgfilteroffset.c
@@ -38,12 +38,11 @@ lsm_svg_filter_offset_get_node_name (LsmDomNode *node)
 
 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)
+			      const char *input, const char *output, const LsmBox *subregion)
 {
 	LsmSvgFilterOffset *offset = LSM_SVG_FILTER_OFFSET (self);
 
-	lsm_svg_view_apply_offset (view, input, output, offset->dx.value, offset->dy.value);
+	lsm_svg_view_apply_offset (view, input, output, subregion, offset->dx.value, offset->dy.value);
 }
 
 /* LsmSvgFilterOffset implementation */
diff --git a/src/lsmsvgfilterprimitive.c b/src/lsmsvgfilterprimitive.c
index 44a9ce3..1b7a5c0 100644
--- a/src/lsmsvgfilterprimitive.c
+++ b/src/lsmsvgfilterprimitive.c
@@ -44,18 +44,20 @@ lsm_svg_filter_primitive_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view)
 	LsmSvgFilterPrimitiveClass *primitive_class;
 	const LsmSvgStyle *parent_style;
 	LsmSvgStyle *style;
-	double x, y, w, h;
+	LsmBox subregion;
 
 	g_return_if_fail (LSM_IS_SVG_FILTER_PRIMITIVE (self));
 
 	primitive_class = LSM_SVG_FILTER_PRIMITIVE_GET_CLASS (self);
 
-	x = lsm_svg_view_normalize_length (view, &self->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	y = lsm_svg_view_normalize_length (view, &self->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	w = lsm_svg_view_normalize_length (view, &self->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	h = lsm_svg_view_normalize_length (view, &self->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	subregion.x = lsm_svg_view_normalize_length (view, &self->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	subregion.y = lsm_svg_view_normalize_length (view, &self->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	subregion.width = lsm_svg_view_normalize_length (view, &self->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	subregion.height = lsm_svg_view_normalize_length (view, &self->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	lsm_log_render ("[Svg::FilterPrimitive::apply] Apply %s", lsm_dom_node_get_node_name (LSM_DOM_NODE (self)));
+	lsm_log_render ("[Svg::FilterPrimitive::apply] Apply %s at %g,%g over %g%g",
+		       	lsm_dom_node_get_node_name (LSM_DOM_NODE (self)),
+			subregion.x, subregion.y, subregion.width, subregion.height);
 
 	parent_style = lsm_svg_view_get_current_style (view);
 	style = lsm_svg_style_new_inherited (parent_style, &(LSM_SVG_ELEMENT (self))->property_bag);
@@ -63,7 +65,7 @@ lsm_svg_filter_primitive_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view)
 	lsm_svg_view_push_style (view, style);
 
 	if (primitive_class->apply != NULL)
-		primitive_class->apply (self, view, self->in.value, self->result.value, x, y, w, h);
+		primitive_class->apply (self, view, self->in.value, self->result.value, &subregion);
 
 	lsm_svg_view_pop_style (view);
 
diff --git a/src/lsmsvgfilterprimitive.h b/src/lsmsvgfilterprimitive.h
index e3fc05f..5aa16f2 100644
--- a/src/lsmsvgfilterprimitive.h
+++ b/src/lsmsvgfilterprimitive.h
@@ -54,8 +54,7 @@ struct _LsmSvgFilterPrimitiveClass {
 	LsmSvgElementClass  element_class;
 
 	void (*apply)		(LsmSvgFilterPrimitive *self, LsmSvgView *view,
-				 const char *input, const char *output,
-				 double x, double y, double w, double h);
+				 const char *input, const char *output, const LsmBox *subregion);
 };
 
 GType 	lsm_svg_filter_primitive_get_type 	(void);
diff --git a/src/lsmsvgfiltertile.c b/src/lsmsvgfiltertile.c
new file mode 100644
index 0000000..93ec40b
--- /dev/null
+++ b/src/lsmsvgfiltertile.c
@@ -0,0 +1,102 @@
+/* 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 <lsmsvgfiltertile.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_tile_get_node_name (LsmDomNode *node)
+{
+	return "feTile";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_tile_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+				     const char *input, const char *output, const LsmBox *subregion)
+{
+	lsm_svg_view_apply_tile (view, input, output, subregion);
+}
+
+/* LsmSvgFilterTile implementation */
+
+static const LsmSvgOneOrTwoDouble std_deviation_default =  {.a = 0.0, .b = 0.0};
+
+LsmDomNode *
+lsm_svg_filter_tile_new (void)
+{
+	return g_object_new (LSM_TYPE_SVG_FILTER_TILE, NULL);
+}
+
+static void
+lsm_svg_filter_tile_init (LsmSvgFilterTile *self)
+{
+	self->std_deviation.value = std_deviation_default;
+}
+
+static void
+lsm_svg_filter_tile_finalize (GObject *object)
+{
+	parent_class->finalize (object);
+}
+
+/* LsmSvgFilterTile class */
+
+static const LsmAttributeInfos lsm_svg_filter_tile_attribute_infos[] = {
+	{
+		.name = "stdDeviation",
+		.attribute_offset = offsetof (LsmSvgFilterTile, std_deviation),
+		.trait_class = &lsm_svg_one_or_two_double_trait_class,
+		.trait_default = &std_deviation_default
+	}
+};
+
+static void
+lsm_svg_filter_tile_class_init (LsmSvgFilterTileClass *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_tile_finalize;
+
+	d_node_class->get_node_name = lsm_svg_filter_tile_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_tile_attribute_infos),
+					      lsm_svg_filter_tile_attribute_infos);
+
+	f_primitive_class->apply = lsm_svg_filter_tile_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterTile, lsm_svg_filter_tile, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfiltertile.h b/src/lsmsvgfiltertile.h
new file mode 100644
index 0000000..84f4a26
--- /dev/null
+++ b/src/lsmsvgfiltertile.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_TILE_H
+#define LSM_SVG_FILTER_TILE_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_TILE             (lsm_svg_filter_tile_get_type ())
+#define LSM_SVG_FILTER_TILE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_FILTER_TILE, LsmSvgFilterTile))
+#define LSM_SVG_FILTER_TILE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_FILTER_TILE, LsmSvgFilterTileClass))
+#define LSM_IS_SVG_FILTER_TILE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_FILTER_TILE))
+#define LSM_IS_SVG_FILTER_TILE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_FILTER_TILE))
+#define LSM_SVG_FILTER_TILE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_FILTER_TILE, LsmSvgFilterTileClass))
+
+typedef struct _LsmSvgFilterTileClass LsmSvgFilterTileClass;
+
+struct _LsmSvgFilterTile {
+	LsmSvgFilterPrimitive base;
+
+	LsmSvgOneOrTwoDoubleAttribute std_deviation;
+};
+
+struct _LsmSvgFilterTileClass {
+	LsmSvgFilterPrimitiveClass  element_class;
+};
+
+GType lsm_svg_filter_tile_get_type (void);
+
+LsmDomNode * 	lsm_svg_filter_tile_new 		(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index c8a7e63..01aed01 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -61,9 +61,10 @@ typedef struct _LsmSvgFilterBlend LsmSvgFilterBlend;
 typedef struct _LsmSvgFilterComposite LsmSvgFilterComposite;
 typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
 typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
-typedef struct _LsmSvgFilterOffset LsmSvgFilterOffset;
 typedef struct _LsmSvgFilterMerge LsmSvgFilterMerge;
 typedef struct _LsmSvgFilterMergeNode LsmSvgFilterMergeNode;
+typedef struct _LsmSvgFilterOffset LsmSvgFilterOffset;
+typedef struct _LsmSvgFilterTile LsmSvgFilterTile;
 
 typedef struct _LsmSvgView LsmSvgView;
 typedef struct _LsmSvgStyle LsmSvgStyle;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index dc4d9a7..0916532 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -2078,13 +2078,23 @@ _create_filter_surface (LsmSvgView *view, const char *output, LsmFilterSurface *
 	return surface;
 }
 
+static void
+_cairo_box_user_to_device (cairo_t *cairo, LsmBox *to, const LsmBox *from)
+{
+	*to = *from;
+
+	cairo_user_to_device (cairo, &to->x, &to->y);
+	cairo_user_to_device_distance (cairo, &to->width, &to->height);
+}
+
 void
 lsm_svg_view_apply_blend (LsmSvgView *view, const char *input_1, const char*input_2, const char *output,
-			  LsmSvgBlendingMode mode)
+			  const LsmBox *subregion, LsmSvgBlendingMode mode)
 {
 	LsmFilterSurface *output_surface;
 	LsmFilterSurface *input_1_surface;
 	LsmFilterSurface *input_2_surface;
+	LsmBox subregion_px;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
@@ -2100,18 +2110,17 @@ lsm_svg_view_apply_blend (LsmSvgView *view, const char *input_1, const char*inpu
 
 	lsm_log_render ("[SvgView::blend] mode = %s", lsm_svg_blending_mode_to_string (mode));
 
-	lsm_filter_surface_blend (input_1_surface, input_2_surface, output_surface, mode);
+	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+
+	lsm_filter_surface_blend (input_1_surface, input_2_surface, output_surface, &subregion_px, mode);
 }
 
 void
-lsm_svg_view_apply_flood (LsmSvgView *view, const char *output,
-			  double x, double y, double w, double h)
+lsm_svg_view_apply_flood (LsmSvgView *view, const char *output, const LsmBox *subregion)
 {
 	LsmFilterSurface *output_surface;
 	LsmFilterSurface *input_surface;
-	guint8 red, green, blue;
-	guint32 color;
-	double opacity;
+	LsmBox subregion_px;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
@@ -2119,25 +2128,22 @@ lsm_svg_view_apply_flood (LsmSvgView *view, const char *output,
 
 	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->flood_opacity->value;
-
-	lsm_log_render ("[SvgView::apply_flood] color = 0x%06x - opacity = %g",
-			color, opacity);
+	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
 
-	lsm_filter_surface_flood (output_surface, color, opacity);
+	lsm_filter_surface_flood (output_surface, &subregion_px,
+				  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_gaussian_blur (LsmSvgView *view, const char *input, const char *output,
-				  double x, double y, double w, double h,
-				  double std_x, double std_y)
+				  const LsmBox *subregion, double std_x, double std_y)
 {
 	LsmFilterSurface *input_surface;
 	LsmFilterSurface *output_surface;
+	LsmBox subregion_px;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
@@ -2150,24 +2156,28 @@ lsm_svg_view_apply_gaussian_blur (LsmSvgView *view, const char *input, const cha
 
 	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)",
+	lsm_log_render ("[SvgView::apply_gaussian_blur] %s -> %s (%g,%g)",
 			input != NULL ? input : "previous",
 			output != NULL ? output : "next",
-			x, y, w, h, std_x, std_y); 
+			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);
+	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+
+	lsm_filter_surface_fast_blur (input_surface, output_surface, &subregion_px, std_x, std_y);
 }
 
 void
-lsm_svg_view_apply_offset (LsmSvgView *view, const char *input, const char *output, double dx, double dy)
+lsm_svg_view_apply_offset (LsmSvgView *view, const char *input, const char *output,
+			   const LsmBox *subregion, double dx, double dy)
 {
 	LsmFilterSurface *input_surface;
 	LsmFilterSurface *output_surface;
+	LsmBox subregion_px;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
@@ -2186,14 +2196,17 @@ lsm_svg_view_apply_offset (LsmSvgView *view, const char *input, const char *outp
 
 	lsm_log_render ("[SvgView::apply_offset] %g px,%g px", dx, dy);
 
-	lsm_filter_surface_offset (input_surface, output_surface, dx, dy);
+	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+
+	lsm_filter_surface_offset (input_surface, output_surface, &subregion_px, dx, dy);
 }
 
 void
-lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *output)
+lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion)
 {
 	LsmFilterSurface *input_surface;
 	LsmFilterSurface *output_surface;
+	LsmBox subregion_px;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
@@ -2208,8 +2221,15 @@ lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *outpu
 	if (output_surface == NULL)
 		output_surface = _create_filter_surface (view, output, input_surface);
 
+	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+
 	if (output_surface != NULL)
-		lsm_filter_surface_merge (input_surface, output_surface);
+		lsm_filter_surface_merge (input_surface, output_surface, &subregion_px);
+}
+
+void
+lsm_svg_view_apply_tile (LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion)
+{
 }
 
 void
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 7b7124a..244c8a1 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -152,14 +152,14 @@ void		lsm_svg_view_pop_composition		(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,
-							 double x, double y, double w, double h,
+							 const LsmBox *subregion, LsmSvgBlendingMode mode);
+void 		lsm_svg_view_apply_flood 		(LsmSvgView *view, const char *output, const LsmBox *subregion);
+void		lsm_svg_view_apply_gaussian_blur 	(LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion,
 							 double std_x, double std_y);
-void 		lsm_svg_view_apply_offset 		(LsmSvgView *view, const char *input, const char *output, double dx, double dy);
-void 		lsm_svg_view_apply_merge 		(LsmSvgView *view, const char *input, const char *output);
+void 		lsm_svg_view_apply_offset 		(LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion,
+							 double dx, double dy);
+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);
 
 G_END_DECLS
 



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