[lasem] svg_filter: filter primitive subregion support.



commit 3466c2ddafa72e9c793f83c8e63a65ac30283bfa
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Thu Oct 18 22:32:24 2012 +0200

    svg_filter: filter primitive subregion support.

 src/lsmcairo.c              |  107 +++++++++++++++++++++++++++++++-----------
 src/lsmcairo.h              |   21 ++++----
 src/lsmsvgfilterelement.c   |   39 +--------------
 src/lsmsvgfilterprimitive.c |   27 ++++++++--
 src/lsmsvgview.c            |   67 ++++++++++++++++----------
 src/lsmsvgview.h            |    5 +-
 6 files changed, 157 insertions(+), 109 deletions(-)
---
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index 6c29a5c..c2f1313 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -32,23 +32,20 @@
 struct _LsmFilterSurface {
 	char *name;
 	cairo_surface_t *surface;
-	unsigned int x0;
-	unsigned int y0;
-	unsigned int x1;
-	unsigned int y1;
+	LsmBox subregion;
 
 	gint ref_count;
 };
 
 LsmFilterSurface *
-lsm_filter_surface_new (const char *name, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
+lsm_filter_surface_new (const char *name, unsigned int width, unsigned int height, const LsmBox *subregion)
 {
 	LsmFilterSurface *filter_surface;
 	cairo_surface_t *surface;
 
-	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, x1 - x0, y1 - y0);
+	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
 
-	filter_surface = lsm_filter_surface_new_with_content (name, x0, y0, surface);
+	filter_surface = lsm_filter_surface_new_with_content (name, surface, subregion);
 
 	cairo_surface_destroy (surface);
 
@@ -56,22 +53,24 @@ lsm_filter_surface_new (const char *name, unsigned int x0, unsigned int y0, unsi
 }
 
 LsmFilterSurface *
-lsm_filter_surface_new_with_content (const char *name, unsigned int x0, unsigned int y0, cairo_surface_t *surface)
+lsm_filter_surface_new_with_content (const char *name, cairo_surface_t *surface, const LsmBox *subregion)
 {
 	LsmFilterSurface *filter_surface;
+	LsmBox null_subregion = {0, 0, 0, 0};
 
-	g_return_val_if_fail (surface != NULL, NULL);
-	g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
-	g_return_val_if_fail (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32, NULL);
+	if (surface == NULL ||
+	    cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE ||
+	    cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
+		surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
+		subregion = &null_subregion;
+	} else if (subregion == NULL)
+		subregion = &null_subregion;
 
 	cairo_surface_reference (surface);
 
 	filter_surface = g_new (LsmFilterSurface, 1);
 	filter_surface->name = g_strdup (name);
-	filter_surface->x0 = x0;
-	filter_surface->y0 = y0;
-	filter_surface->x1 = x0 + cairo_image_surface_get_width (surface);
-	filter_surface->y1 = y0 + cairo_image_surface_get_height (surface);
+	filter_surface->subregion = *subregion;
 	filter_surface->surface  = surface;
 	filter_surface->ref_count = 1;
 
@@ -79,11 +78,15 @@ lsm_filter_surface_new_with_content (const char *name, unsigned int x0, unsigned
 }
 
 LsmFilterSurface *
-lsm_filter_surface_new_similar (const char *name, LsmFilterSurface *model)
+lsm_filter_surface_new_similar (const char *name, LsmFilterSurface *model, const LsmBox *subregion)
 {
-	g_return_val_if_fail (model != NULL, NULL);
+	if (model == NULL)
+		return lsm_filter_surface_new (name, 0, 0, subregion);
 
-	return lsm_filter_surface_new (name, model->x0, model->y0, model->x1, model->y1);
+	return lsm_filter_surface_new (name,
+				       cairo_image_surface_get_width (model->surface),
+				       cairo_image_surface_get_height (model->surface),
+				       subregion != NULL ? subregion : &model->subregion);
 }
 
 const char *
@@ -102,6 +105,17 @@ lsm_filter_surface_get_cairo_surface (LsmFilterSurface *surface)
 	return surface->surface;
 }
 
+const LsmBox *
+lsm_filter_surface_get_subregion (LsmFilterSurface *surface)
+{
+	static const LsmBox null_subregion = {0, 0, 0, 0};
+
+	if (surface == NULL)
+		return &null_subregion;
+
+	return &surface->subregion;
+}
+
 LsmFilterSurface *
 lsm_filter_surface_ref (LsmFilterSurface *filter_surface)
 {
@@ -146,10 +160,9 @@ box_blur (LsmFilterSurface *input,
 
 	rowstride = cairo_image_surface_get_stride (input->surface);
 
-	x1 = input->x0;
-	y1 = input->y0;
-	x2 = input->x1;
-	y2 = input->y1;
+	x1 = 0; y1 = 0;
+	x2 = cairo_image_surface_get_width (input->surface);
+	y2 = cairo_image_surface_get_height (input->surface);
 
 	if (kw > x2 - x1)
 		kw = x2 - x1;
@@ -420,14 +433,52 @@ lsm_filter_surface_alpha (LsmFilterSurface *input, LsmFilterSurface *output)
 	cairo_destroy (cairo);
 }
 
+void
+lsm_cairo_box_user_to_device (cairo_t *cairo, LsmBox *to, const LsmBox *from)
+{
+	if (to == NULL)
+		return;
+
+	if (from == NULL || cairo == NULL) {
+		to->x = 0;
+		to->y = 0;
+		to->width = 0;
+		to->height = 0;
+	}
+
+	*to = *from;
+
+	cairo_user_to_device (cairo, &to->x, &to->y);
+	cairo_user_to_device_distance (cairo, &to->width, &to->height);
+}
+
+void
+lsm_cairo_box_device_to_user (cairo_t *cairo, LsmBox *to, const LsmBox *from)
+{
+	if (to == NULL)
+		return;
+
+	if (from == NULL || cairo == NULL) {
+		to->x = 0;
+		to->y = 0;
+		to->width = 0;
+		to->height = 0;
+	}
+
+	*to = *from;
+
+	cairo_device_to_user (cairo, &to->x, &to->y);
+	cairo_device_to_user_distance (cairo, &to->width, &to->height);
+}
+
 /**
  * lsm_cairo_set_source_pixbuf:
- * @cr: a cairo context
+ * @cairo: a cairo context
  * @pixbuf: a #GdkPixbuf
  * @pixbuf_x: X coordinate of location to place upper left corner of @pixbuf
  * @pixbuf_y: Y coordinate of location to place upper left corner of @pixbuf
  *
- * Sets the given pixbuf as the source pattern for @cr.
+ * Sets the given pixbuf as the source pattern for @cairo.
  *
  * The pattern has an extend mode of %CAIRO_EXTEND_NONE and is aligned
  * so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y.
@@ -436,10 +487,10 @@ lsm_filter_surface_alpha (LsmFilterSurface *input, LsmFilterSurface *output)
  */
 
 void
-lsm_cairo_set_source_pixbuf (cairo_t         *cr,
+lsm_cairo_set_source_pixbuf (cairo_t *cairo,
                              const GdkPixbuf *pixbuf,
-                             gdouble          pixbuf_x,
-                             gdouble          pixbuf_y)
+                             double pixbuf_x,
+                             double pixbuf_y)
 {
 	gint width = gdk_pixbuf_get_width (pixbuf);
 	gint height = gdk_pixbuf_get_height (pixbuf);
@@ -523,7 +574,7 @@ lsm_cairo_set_source_pixbuf (cairo_t         *cr,
 		cairo_pixels += cairo_stride;
 	}
 
-	cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y);
+	cairo_set_source_surface (cairo, surface, pixbuf_x, pixbuf_y);
 	cairo_surface_destroy (surface);
 }
 
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index c15b6c9..782c038 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -36,16 +36,15 @@ typedef struct _LsmFilterSurface LsmFilterSurface;
 
 GType lsm_filter_surface_get_type (void);
 
-LsmFilterSurface * 	lsm_filter_surface_new 			(const char *name,
-								 unsigned int x0, unsigned int y0,
-								 unsigned int x1, unsigned int y1);
-LsmFilterSurface * 	lsm_filter_surface_new_with_content 	(const char *name,
-								 unsigned int x0, unsigned int y0,
-								 cairo_surface_t *surface);
-LsmFilterSurface *	lsm_filter_surface_new_similar		(const char *name, LsmFilterSurface *model);
+LsmFilterSurface * 	lsm_filter_surface_new 			(const char *name, unsigned int width, unsigned int height,
+								 const LsmBox *subregion);
+LsmFilterSurface * 	lsm_filter_surface_new_with_content 	(const char *name, cairo_surface_t *surface, const LsmBox *subregion);
+LsmFilterSurface *	lsm_filter_surface_new_similar		(const char *name, LsmFilterSurface *model, const LsmBox *subregion);
+
 void 			lsm_filter_surface_copy_data 		(LsmFilterSurface *to, LsmFilterSurface *from);
 const char * 		lsm_filter_surface_get_name 		(LsmFilterSurface *surface);
 cairo_surface_t *	lsm_filter_surface_get_cairo_surface	(LsmFilterSurface *surface);
+const LsmBox *		lsm_filter_surface_get_subregion 	(LsmFilterSurface *surface);
 void 			lsm_filter_surface_unref 		(LsmFilterSurface *filter_surface);
 LsmFilterSurface *	lsm_filter_surface_ref 			(LsmFilterSurface *filter_surface);
 
@@ -64,10 +63,10 @@ void 			lsm_filter_surface_offset 		(LsmFilterSurface *input, LsmFilterSurface *
 void 			lsm_filter_surface_merge 		(LsmFilterSurface *input, LsmFilterSurface *output,
 								 const LsmBox *subregion);
 
-void 			lsm_cairo_set_source_pixbuf 		(cairo_t         *cr,
-								 const GdkPixbuf *pixbuf,
-								 gdouble          pixbuf_x,
-								 gdouble          pixbuf_y);
+void 			lsm_cairo_box_user_to_device 		(cairo_t *cairo, LsmBox *to, const LsmBox *from);
+void 			lsm_cairo_box_device_to_user 		(cairo_t *cairo, LsmBox *to, const LsmBox *from);
+void 			lsm_cairo_set_source_pixbuf 		(cairo_t *cairo, const GdkPixbuf *pixbuf,
+								 double pixbuf_x, double pixbuf_y);
 
 G_END_DECLS
 
diff --git a/src/lsmsvgfilterelement.c b/src/lsmsvgfilterelement.c
index 0a337f5..4515dca 100644
--- a/src/lsmsvgfilterelement.c
+++ b/src/lsmsvgfilterelement.c
@@ -90,9 +90,8 @@ lsm_svg_filter_element_render (LsmSvgElement *self, LsmSvgView *view)
 {
 	LsmSvgFilterElement *filter = LSM_SVG_FILTER_ELEMENT (self);
 	LsmDomNode *node;
-	LsmBox viewport;
 	LsmBox viewbox = {.x = 0.0, .y = .0, .width = 1.0, .height = 1.0};
-	const LsmBox *filter_extents;
+	const LsmBox *object_extents;
 	gboolean is_object_bounding_box;
 
 	if (!filter->enable_rendering) {
@@ -102,43 +101,11 @@ lsm_svg_filter_element_render (LsmSvgElement *self, LsmSvgView *view)
 		filter->enable_rendering = FALSE;
 	}
 
-	filter_extents = lsm_svg_view_get_object_extents (view);
-
-	is_object_bounding_box = (filter->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
-
-	if (is_object_bounding_box)
-		lsm_svg_view_push_viewbox (view, &viewbox);
-
-	viewport.x      = lsm_svg_view_normalize_length (view, &filter->x.length,
-							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.y      = lsm_svg_view_normalize_length (view, &filter->y.length,
-							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-	viewport.width  = lsm_svg_view_normalize_length (view, &filter->width.length,
-							 LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
-	viewport.height = lsm_svg_view_normalize_length (view, &filter->height.length,
-							 LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-
-	if (is_object_bounding_box) {
-		lsm_svg_view_pop_viewbox (view);
-
-		viewport.x = viewport.x * filter_extents->width + filter_extents->x;
-		viewport.y = viewport.y * filter_extents->height + filter_extents->y;
-		viewport.width *= filter_extents->width;
-		viewport.height *= filter_extents->height;
-	}
-
-	if (viewport.width <= 0.0 || viewport.height <= 0.0) {
-		lsm_debug_render ("[LsmSvgFilterElement::render] Invalid filter area w = %g, h = %g",
-			   viewport.width, viewport.height);
-		return;
-	}
-
-	lsm_debug_render ("[LsmFilterElement::render] Render filter x = %g, y = %g, w = %g, h = %g",
-		   viewport.x, viewport.y, viewport.width, viewport.height);
+	object_extents = lsm_svg_view_get_object_extents (view);
 
 	is_object_bounding_box = (filter->primitive_units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
 
-	lsm_svg_view_push_viewport (view, &viewport,
+	lsm_svg_view_push_viewport (view, object_extents,
 				    is_object_bounding_box ? &viewbox : NULL, NULL, LSM_SVG_OVERFLOW_VISIBLE); 
 
 	for (node = LSM_DOM_NODE (filter)->first_child; node != NULL; node = node->next_sibling)
diff --git a/src/lsmsvgfilterprimitive.c b/src/lsmsvgfilterprimitive.c
index 1b7a5c0..5d2ec14 100644
--- a/src/lsmsvgfilterprimitive.c
+++ b/src/lsmsvgfilterprimitive.c
@@ -45,17 +45,32 @@ lsm_svg_filter_primitive_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view)
 	const LsmSvgStyle *parent_style;
 	LsmSvgStyle *style;
 	LsmBox subregion;
-
+	gboolean is_x_defined;
+	gboolean is_y_defined;
+	gboolean is_width_defined;
+	gboolean is_height_defined;
+	
 	g_return_if_fail (LSM_IS_SVG_FILTER_PRIMITIVE (self));
 
 	primitive_class = LSM_SVG_FILTER_PRIMITIVE_GET_CLASS (self);
 
-	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);
+	is_x_defined = lsm_attribute_is_defined (&self->x.base);
+	is_y_defined = lsm_attribute_is_defined (&self->y.base);
+	is_width_defined = lsm_attribute_is_defined (&self->width.base);
+	is_height_defined = lsm_attribute_is_defined (&self->height.base);
+
+	subregion = lsm_svg_view_get_filter_surface_extents (view, self->in.value);
+
+	if (is_x_defined)
+		subregion.x = lsm_svg_view_normalize_length (view, &self->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	if (is_y_defined)
+		subregion.y = lsm_svg_view_normalize_length (view, &self->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+	if (is_width_defined)
+		subregion.width = lsm_svg_view_normalize_length (view, &self->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+	if (is_height_defined)
+		subregion.height = lsm_svg_view_normalize_length (view, &self->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	lsm_log_render ("[Svg::FilterPrimitive::apply] Apply %s at %g,%g over %g%g",
+	lsm_log_render ("[Svg::FilterPrimitive::apply] Apply %s at %g,%g over a %gx%g region",
 		       	lsm_dom_node_get_node_name (LSM_DOM_NODE (self)),
 			subregion.x, subregion.y, subregion.width, subregion.height);
 
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 0916532..d6aa406 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -1975,11 +1975,18 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
 	if (LSM_IS_SVG_FILTER_ELEMENT (filter_element) &&
 	    view->pattern_data->pattern != NULL) {
 		cairo_matrix_t matrix;
+		LsmBox subregion;
 
 		view->filter_surfaces = NULL;
 
 		cairo_pattern_get_surface (view->pattern_data->pattern, &surface);
-		filter_surface = lsm_filter_surface_new_with_content ("SourceGraphic", 0, 0, surface);
+
+		subregion.x = 0;
+		subregion.y = 0;
+		subregion.width = cairo_image_surface_get_width (surface);
+		subregion.height = cairo_image_surface_get_height (surface);
+
+		filter_surface = lsm_filter_surface_new_with_content ("SourceGraphic", surface, &subregion);
 		cairo_pattern_get_matrix (view->pattern_data->pattern, &matrix);
 
 		view->filter_surfaces = g_slist_prepend (view->filter_surfaces, filter_surface);
@@ -2044,7 +2051,7 @@ _get_filter_surface (LsmSvgView *view, const char *input)
 	if (g_strcmp0 (input, "SourceAlpha") == 0 && source_surface != NULL) {
 		LsmFilterSurface *surface;
 
-		surface = lsm_filter_surface_new_similar ("SourceAlpha", source_surface);
+		surface = lsm_filter_surface_new_similar ("SourceAlpha", source_surface, NULL);
 		lsm_filter_surface_alpha (source_surface, surface);
 		view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);	
 
@@ -2053,13 +2060,13 @@ _get_filter_surface (LsmSvgView *view, const char *input)
 		/* TODO */
 		LsmFilterSurface *surface;
 
-		surface = lsm_filter_surface_new_similar ("BackgroundImage", source_surface);
+		surface = lsm_filter_surface_new_similar ("BackgroundImage", source_surface, NULL);
 		view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);	
 	} else if (g_strcmp0 (input, "BackgroundAlpha") == 0) {
 		/* TODO */
 		LsmFilterSurface *surface;
 
-		surface = lsm_filter_surface_new_similar ("BackgroundAlpha", source_surface);
+		surface = lsm_filter_surface_new_similar ("BackgroundAlpha", source_surface, NULL);
 		view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);	
 	}
 
@@ -2067,24 +2074,33 @@ _get_filter_surface (LsmSvgView *view, const char *input)
 }
 
 static LsmFilterSurface *
-_create_filter_surface (LsmSvgView *view, const char *output, LsmFilterSurface *input_surface)
+_create_filter_surface (LsmSvgView *view, const char *output, LsmFilterSurface *input_surface, const LsmBox *subregion)
 {
 	LsmFilterSurface *surface;
 
-	surface = lsm_filter_surface_new_similar (output, input_surface);
+	surface = lsm_filter_surface_new_similar (output, input_surface, subregion);
 
 	view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface); 
 
 	return surface;
 }
 
-static void
-_cairo_box_user_to_device (cairo_t *cairo, LsmBox *to, const LsmBox *from)
+LsmBox
+lsm_svg_view_get_filter_surface_extents (LsmSvgView *view, const char *name)
 {
-	*to = *from;
+	static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
+	LsmFilterSurface *surface;
+	LsmBox extents;
+
+	g_return_val_if_fail (LSM_IS_SVG_VIEW (view), null_extents);
 
-	cairo_user_to_device (cairo, &to->x, &to->y);
-	cairo_user_to_device_distance (cairo, &to->width, &to->height);
+	surface = _get_filter_surface (view, name);
+	if (surface == NULL)
+		return null_extents;
+
+	lsm_cairo_box_device_to_user (view->dom_view.cairo, &extents, lsm_filter_surface_get_subregion (surface));
+
+	return extents;
 }
 
 void
@@ -2102,16 +2118,15 @@ lsm_svg_view_apply_blend (LsmSvgView *view, const char *input_1, const char*inpu
 	input_2_surface = _get_filter_surface (view, input_2);
 
 	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);
+		lsm_warning_render ("[SvgView::apply_blend] Inputs '%s' or '%s' not found", input_1, input_2);
 		return;
 	}
 
-	output_surface = _create_filter_surface (view, output, input_1_surface);
+	lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+	output_surface = _create_filter_surface (view, output, input_1_surface, &subregion_px);
 
 	lsm_log_render ("[SvgView::blend] mode = %s", lsm_svg_blending_mode_to_string (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);
 }
 
@@ -2126,9 +2141,12 @@ lsm_svg_view_apply_flood (LsmSvgView *view, const char *output, const LsmBox *su
 
 	input_surface = _get_filter_surface (view, NULL);
 
-	output_surface = _create_filter_surface (view, output, input_surface);
+	lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+	output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
 
-	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+	lsm_log_render ("[SvgView::apply_flood] subregion %gx%g px at %g,%g px",
+		        subregion_px.width, subregion_px.height,
+		        subregion_px.x, subregion_px.y);
 
 	lsm_filter_surface_flood (output_surface, &subregion_px,
 				  view->style->flood_color->value.red,
@@ -2154,7 +2172,8 @@ lsm_svg_view_apply_gaussian_blur (LsmSvgView *view, const char *input, const cha
 		return;
 	}
 
-	output_surface = _create_filter_surface (view, output, input_surface);
+	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_gaussian_blur] %s -> %s (%g,%g)",
 			input != NULL ? input : "previous",
@@ -2166,8 +2185,6 @@ lsm_svg_view_apply_gaussian_blur (LsmSvgView *view, const char *input, const cha
 	lsm_log_render ("[SvgView::apply_gaussian_blur] %g px,%g px",
 			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);
 }
 
@@ -2188,7 +2205,8 @@ lsm_svg_view_apply_offset (LsmSvgView *view, const char *input, const char *outp
 		return;
 	}
 
-	output_surface = _create_filter_surface (view, output, input_surface);
+	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_offset] %s -> %s (dx:%g,dy:%g)", input, output, dx, dy); 
 
@@ -2196,8 +2214,6 @@ 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);
 
-	_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
-
 	lsm_filter_surface_offset (input_surface, output_surface, &subregion_px, dx, dy);
 }
 
@@ -2218,10 +2234,9 @@ lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *outpu
 	}
 
 	output_surface = _get_filter_surface (view, output);
+	lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
 	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);
+		output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
 
 	if (output_surface != NULL)
 		lsm_filter_surface_merge (input_surface, output_surface, &subregion_px);
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 244c8a1..c553776 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -146,11 +146,12 @@ void		lsm_svg_view_pop_element		(LsmSvgView *view);
 
 void		lsm_svg_view_push_style			(LsmSvgView *view, LsmSvgStyle *style);
 void		lsm_svg_view_pop_style			(LsmSvgView *view);
+LsmSvgStyle *	lsm_svg_view_get_current_style		(LsmSvgView *view);
+
 void		lsm_svg_view_push_composition		(LsmSvgView *view, LsmSvgStyle *style);
 void		lsm_svg_view_pop_composition		(LsmSvgView *view);
 
-LsmSvgStyle *	lsm_svg_view_get_current_style	(LsmSvgView *view);
-
+LsmBox 		lsm_svg_view_get_filter_surface_extents (LsmSvgView *view, const char *name);
 void 		lsm_svg_view_apply_blend 		(LsmSvgView *view, const char *input_1, const char*input_2, const char *output,
 							 const LsmBox *subregion, LsmSvgBlendingMode mode);
 void 		lsm_svg_view_apply_flood 		(LsmSvgView *view, const char *output, const LsmBox *subregion);



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