diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2012-10-15 10:50:00 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2012-10-15 10:50:00 +0000 |
| commit | bd2871a7036bb8f907ad9921f18560d1460f7af9 (patch) | |
| tree | a829660880210e7fbecfb42a3cacde688cd8059c /src | |
| parent | extensions. apply inkex.localize() for consistency (diff) | |
| download | inkscape-bd2871a7036bb8f907ad9921f18560d1460f7af9.tar.gz inkscape-bd2871a7036bb8f907ad9921f18560d1460f7af9.zip | |
Use filter primitive region and aspect ratio in image filter primitive, fixes regression.
(bzr r11803)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/nr-filter-image.cpp | 132 | ||||
| -rw-r--r-- | src/display/nr-filter-image.h | 1 |
2 files changed, 110 insertions, 23 deletions
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp index a9a5ec3e0..722a4ed7f 100644 --- a/src/display/nr-filter-image.cpp +++ b/src/display/nr-filter-image.cpp @@ -20,6 +20,7 @@ #include "display/nr-filter-image.h" #include "display/nr-filter-slot.h" #include "display/nr-filter-units.h" +#include "enums.h" #include <glibmm/fileutils.h> namespace Inkscape { @@ -50,22 +51,31 @@ void FilterImage::render_cairo(FilterSlot &slot) //cairo_surface_t *input = slot.getcairo(_input); + // Viewport is filter primitive area (in user coordinates). + // Note: viewport calculation in non-trivial. Do not use + // rely on get_matrix_primitiveunits2pb(). + Geom::Rect vp = filter_primitive_area( slot.get_units() ); + double feImageX = vp.min()[Geom::X]; + double feImageY = vp.min()[Geom::Y]; + double feImageWidth = vp.width(); + double feImageHeight = vp.height(); + + // feImage is suppose to use the same parameters as a normal SVG image. + // If a width or height is set to zero, the image is not suppose to be displayed. + // This does not seem to be what Firefox or Opera does, nor does the W3C displacement + // filter test expect this behavior. If the width and/or height are zero, we use + // the width and height of the object bounding box. Geom::Affine m = slot.get_units().get_matrix_user2filterunits().inverse(); Geom::Point bbox_00 = Geom::Point(0,0) * m; Geom::Point bbox_w0 = Geom::Point(1,0) * m; Geom::Point bbox_0h = Geom::Point(0,1) * m; double bbox_width = Geom::distance(bbox_00, bbox_w0); double bbox_height = Geom::distance(bbox_00, bbox_0h); - - // feImage is suppose to use the same parameters as a normal SVG image. - // If a width or height is set to zero, the image is not suppose to be displayed. - // This does not seem to be what Firefox or Opera does, nor does the W3C displacement - // filter test expect this behavior. If the width and/or height are zero, we use - // the width and height of the object bounding box. if( feImageWidth == 0 ) feImageWidth = bbox_width; if( feImageHeight == 0 ) feImageHeight = bbox_height; + // Internal image, like <use> if (from_element) { if (!SVGElem) return; @@ -87,7 +97,7 @@ void FilterImage::render_cairo(FilterSlot &slot) drawing.setRoot(ai); Geom::Rect area = *optarea; - Geom::Affine pu2pb = slot.get_units().get_matrix_primitiveunits2pb(); + Geom::Affine user2pb = slot.get_units().get_matrix_user2pb(); double scaleX = feImageWidth / area.width(); double scaleY = feImageHeight / area.height(); @@ -96,9 +106,9 @@ void FilterImage::render_cairo(FilterSlot &slot) cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, sa.width(), sa.height()); Inkscape::DrawingContext ct(out, sa.min()); - ct.transform(pu2pb); // we are now in primitive units + ct.transform(user2pb); // we are now in primitive units ct.translate(feImageX, feImageY); - ct.scale(scaleX, scaleY); +// ct.scale(scaleX, scaleY); No scaling should be done Geom::IntRect render_rect = area.roundOutwards(); ct.translate(render_rect.min()); @@ -113,6 +123,7 @@ void FilterImage::render_cairo(FilterSlot &slot) return; } + // External image, like <image> if (!image && !broken_ref) { broken_ref = true; try { @@ -158,9 +169,9 @@ void FilterImage::render_cairo(FilterSlot &slot) } // Native size of image - //width = image->get_width(); - //height = image->get_height(); - //rowstride = image->get_rowstride(); + // width = image->get_width(); + // height = image->get_height(); + // rowstride = image->get_rowstride(); convert_pixbuf_normal_to_argb32(image->gobj()); @@ -174,11 +185,94 @@ void FilterImage::render_cairo(FilterSlot &slot) cairo_t *ct = cairo_create(out); cairo_translate(ct, -sa.min()[Geom::X], -sa.min()[Geom::Y]); - // now ct is in pb coordinates - ink_cairo_transform(ct, slot.get_units().get_matrix_primitiveunits2pb()); + + // now ct is in pb coordinates, note the feWidth etc. are in user units + ink_cairo_transform(ct, slot.get_units().get_matrix_user2pb()); + // now ct is in the coordinates of feImageX etc. - // TODO: add preserveAspectRatio support here + // Now that we have the viewport, we must map image inside. + // Partially copied from sp-image.cpp. + + // Do nothing if preserveAspectRatio is "none". + if( aspect_align != SP_ASPECT_NONE ) { + + // Check aspect ratio of image vs. viewport + double feAspect = feImageHeight/feImageWidth; + double aspect = (double)image->get_height()/(double)image->get_width(); + bool ratio = (feAspect < aspect); + + double ax, ay; // Align side + switch( aspect_align ) { + case SP_ASPECT_XMIN_YMIN: + ax = 0.0; + ay = 0.0; + break; + case SP_ASPECT_XMID_YMIN: + ax = 0.5; + ay = 0.0; + break; + case SP_ASPECT_XMAX_YMIN: + ax = 1.0; + ay = 0.0; + break; + case SP_ASPECT_XMIN_YMID: + ax = 0.0; + ay = 0.5; + break; + case SP_ASPECT_XMID_YMID: + ax = 0.5; + ay = 0.5; + break; + case SP_ASPECT_XMAX_YMID: + ax = 1.0; + ay = 0.5; + break; + case SP_ASPECT_XMIN_YMAX: + ax = 0.0; + ay = 1.0; + break; + case SP_ASPECT_XMID_YMAX: + ax = 0.5; + ay = 1.0; + break; + case SP_ASPECT_XMAX_YMAX: + ax = 1.0; + ay = 1.0; + break; + default: + ax = 0.0; + ay = 0.0; + break; + } + + if( aspect_clip == SP_ASPECT_SLICE ) { + // image clipped by viewbox + + if( ratio ) { + // clip top/bottom + feImageY -= ay * (feImageWidth * aspect - feImageHeight); + feImageHeight = feImageWidth * aspect; + } else { + // clip sides + feImageX -= ax * (feImageHeight / aspect - feImageWidth); + feImageWidth = feImageHeight / aspect; + } + + } else { + // image fits into viewbox + + if( ratio ) { + // fit to height + feImageX += ax * (feImageWidth - feImageHeight / aspect ); + feImageWidth = feImageHeight / aspect; + } else { + // fit to width + feImageY += ay * (feImageHeight - feImageWidth * aspect); + feImageHeight = feImageWidth * aspect; + } + } + } double scaleX = feImageWidth / image->get_width(); double scaleY = feImageHeight / image->get_height(); @@ -204,6 +298,7 @@ double FilterImage::complexity(Geom::Affine const &) } void FilterImage::set_href(const gchar *href){ + if (feImageHref) g_free (feImageHref); feImageHref = (href) ? g_strdup (href) : NULL; @@ -218,13 +313,6 @@ void FilterImage::set_document(SPDocument *doc){ document = doc; } -void FilterImage::set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height) { - feImageX=x.computed; - feImageY=y.computed; - feImageWidth=width.computed; - feImageHeight=height.computed; -} - void FilterImage::set_align( unsigned int align ) { aspect_align = align; } diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h index c0b9d6e81..05b7d65a8 100644 --- a/src/display/nr-filter-image.h +++ b/src/display/nr-filter-image.h @@ -35,7 +35,6 @@ public: void set_document( SPDocument *document ); void set_href(const gchar *href); - void set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height); void set_align( unsigned int align ); void set_clip( unsigned int clip ); bool from_element; |
