summaryrefslogtreecommitdiffstats
path: root/src/sp-gradient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp-gradient.cpp')
-rw-r--r--src/sp-gradient.cpp27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index b42768f30..0acdac76e 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -1531,7 +1531,7 @@ sp_gradient_pattern_common_setup(cairo_pattern_t *cp,
static cairo_pattern_t *
sp_radialgradient_create_pattern(SPPaintServer *ps,
- cairo_t */* ct */,
+ cairo_t *ct,
Geom::OptRect const &bbox,
double opacity)
{
@@ -1540,9 +1540,30 @@ sp_radialgradient_create_pattern(SPPaintServer *ps,
gr->ensureVector();
+ Geom::Point focus(rg->fx.computed, rg->fy.computed);
+ Geom::Point center(rg->cx.computed, rg->cy.computed);
+ double radius = rg->r.computed;
+ double scale = 1.0;
+ double tolerance = cairo_get_tolerance(ct);
+
+ // code below suggested by Cairo devs to overcome tolerance problems
+ // more: https://bugs.freedesktop.org/show_bug.cgi?id=40918
+ Geom::Point d = focus - center;
+ if (d.length() + tolerance > radius) {
+ scale = radius / d.length();
+
+ double dx = d.x(), dy = d.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);
+ }
+ }
+
cairo_pattern_t *cp = cairo_pattern_create_radial(
- rg->fx.computed, rg->fy.computed, 0,
- rg->cx.computed, rg->cy.computed, rg->r.computed);
+ scale * d.x() + center.x(), scale * d.y() + center.y(), 0,
+ center.x(), center.y(), radius);
sp_gradient_pattern_common_setup(cp, gr, bbox, opacity);