summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2012-10-15 10:50:00 +0000
committertavmjong-free <tavmjong@free.fr>2012-10-15 10:50:00 +0000
commitbd2871a7036bb8f907ad9921f18560d1460f7af9 (patch)
treea829660880210e7fbecfb42a3cacde688cd8059c /src
parentextensions. apply inkex.localize() for consistency (diff)
downloadinkscape-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.cpp132
-rw-r--r--src/display/nr-filter-image.h1
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;