diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2013-10-01 23:13:48 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2013-10-01 23:13:48 +0000 |
| commit | 5dc15e1d0593adc1d5c4ac99aa399642e7e2482d (patch) | |
| tree | 49bc654138644233afef6ecf51faccccc7296cf9 /src/sp-radial-gradient.cpp | |
| parent | Comprehensive fix for the issues with disappearing filtered objects. (diff) | |
| download | inkscape-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.cpp | 36 |
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( |
