summaryrefslogtreecommitdiffstats
path: root/src/sp-radial-gradient.cpp
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2013-10-01 23:13:48 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2013-10-01 23:13:48 +0000
commit5dc15e1d0593adc1d5c4ac99aa399642e7e2482d (patch)
tree49bc654138644233afef6ecf51faccccc7296cf9 /src/sp-radial-gradient.cpp
parentComprehensive fix for the issues with disappearing filtered objects. (diff)
downloadinkscape-5dc15e1d0593adc1d5c4ac99aa399642e7e2482d.tar.gz
inkscape-5dc15e1d0593adc1d5c4ac99aa399642e7e2482d.zip
Fix outfocus gradients. Fixes a regression from 0.48 in the SVG test suite
(test case pserver-grad-13-b.svg). (bzr r12649)
Diffstat (limited to 'src/sp-radial-gradient.cpp')
-rw-r--r--src/sp-radial-gradient.cpp36
1 files changed, 22 insertions, 14 deletions
diff --git a/src/sp-radial-gradient.cpp b/src/sp-radial-gradient.cpp
index c8bf5db81..7c481fead 100644
--- a/src/sp-radial-gradient.cpp
+++ b/src/sp-radial-gradient.cpp
@@ -156,28 +156,36 @@ cairo_pattern_t* SPRadialGradient::pattern_new(cairo_t *ct, Geom::OptRect const
// https://bugs.launchpad.net/inkscape/+bug/970355
Geom::Affine gs2user = this->gradientTransform;
- Geom::Scale gs2user_scale;
if (this->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX && bbox) {
Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top());
gs2user *= bbox2user;
- gs2user_scale = Geom::Scale( gs2user[0], gs2user[3] );
}
- Geom::Point d = focus - center;
- Geom::Point d_user = d * gs2user_scale;
- Geom::Point r_user( radius, 0 );
- r_user *= gs2user_scale;
-
- if (d_user.length() + tolerance > r_user.length()) {
+ // we need to use vectors with the same direction to represent the transformed
+ // radius and the focus-center delta, because gs2user might contain non-uniform scaling
+ Geom::Point d(focus - center);
+ Geom::Point d_user(d.length(), 0);
+ Geom::Point r_user(radius, 0);
+ d_user *= gs2user.withoutTranslation();
+ r_user *= gs2user.withoutTranslation();
+
+ double dx = d_user.x(), dy = d_user.y();
+ cairo_user_to_device_distance(ct, &dx, &dy);
+
+ // compute the tolerance distance in user space
+ // create a vector with the same direction as the transformed d,
+ // with the length equal to tolerance
+ double dl = hypot(dx, dy);
+ double tx = tolerance * dx / dl, ty = tolerance * dy / dl;
+ cairo_device_to_user_distance(ct, &tx, &ty);
+ double tolerance_user = hypot(tx, ty);
+
+ if (d_user.length() + tolerance_user > r_user.length()) {
scale = r_user.length() / d_user.length();
- double dx = d_user.x(), dy = d_user.y();
- cairo_user_to_device_distance(ct, &dx, &dy);
- if (!Geom::are_near(dx, 0, tolerance) || !Geom::are_near(dy, 0, tolerance))
- {
- scale *= 1.0 - 2.0 * tolerance / hypot(dx, dy);
- }
+ // nudge the focus slightly inside
+ scale *= 1.0 - 2.0 * tolerance / dl;
}
cairo_pattern_t *cp = cairo_pattern_create_radial(