SVG - improve handling of gradientUnits and gradientTransform attributes (radial gradient) + correct default values [skip ci]
This commit is contained in:
parent
1c6d14eb85
commit
dcfb2d692c
4 changed files with 33 additions and 25 deletions
|
@ -64,6 +64,8 @@ MAPNIK_DISABLE_WARNING_PUSH
|
|||
#include "agg_span_interpolator_linear.h"
|
||||
MAPNIK_DISABLE_WARNING_POP
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace mapnik {
|
||||
namespace svg {
|
||||
|
||||
|
@ -222,16 +224,14 @@ class renderer_agg : util::noncopyable
|
|||
}
|
||||
if (m_gradient_lut.build_lut())
|
||||
{
|
||||
agg::trans_affine transform = mtx;
|
||||
double scale = mtx.scale();
|
||||
transform.invert();
|
||||
agg::trans_affine tr;
|
||||
tr = grad.get_transform();
|
||||
tr.invert();
|
||||
agg::trans_affine tr = mtx;
|
||||
agg::trans_affine transform = grad.get_transform();
|
||||
transform *= tr;
|
||||
transform.invert();
|
||||
|
||||
if (grad.get_units() != USER_SPACE_ON_USE)
|
||||
{
|
||||
double scale = mtx.scale();
|
||||
double bx1 = symbol_bbox.minx();
|
||||
double by1 = symbol_bbox.miny();
|
||||
double bx2 = symbol_bbox.maxx();
|
||||
|
@ -244,7 +244,17 @@ class renderer_agg : util::noncopyable
|
|||
transform.translate(-bx1 / scale, -by1 / scale);
|
||||
transform.scale(scale / (bx2 - bx1), scale / (by2 - by1));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
double scaledown = 255;
|
||||
x1 /= scaledown; // fx
|
||||
y1 /= scaledown; // fy
|
||||
x2 /= scaledown; // cx
|
||||
y2 /= scaledown; // cy
|
||||
radius /= scaledown;
|
||||
transform.translate(-symbol_bbox.minx(), -symbol_bbox.miny());
|
||||
transform.scale(1 / scaledown, 1 / scaledown);
|
||||
}
|
||||
if (grad.get_gradient_type() == RADIAL)
|
||||
{
|
||||
using gradient_adaptor_type = agg::gradient_radial_focus;
|
||||
|
@ -253,7 +263,6 @@ class renderer_agg : util::noncopyable
|
|||
|
||||
// the agg radial gradient assumes it is centred on 0
|
||||
transform.translate(-x2, -y2);
|
||||
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup = 255;
|
||||
radius *= scaleup;
|
||||
|
@ -261,7 +270,6 @@ class renderer_agg : util::noncopyable
|
|||
y1 *= scaleup;
|
||||
x2 *= scaleup;
|
||||
y2 *= scaleup;
|
||||
|
||||
transform.scale(scaleup, scaleup);
|
||||
|
||||
interpolator_type span_interpolator(transform);
|
||||
|
|
|
@ -70,8 +70,8 @@ gradient& gradient::operator=(gradient rhs)
|
|||
bool gradient::operator==(gradient const& other) const
|
||||
{
|
||||
return transform_ == other.transform_ && x1_ == other.x1_ && y1_ == other.y1_ && x2_ == other.x2_ &&
|
||||
y2_ == other.y2_ && r_ == other.r_ && std::equal(stops_.begin(), stops_.end(), other.stops_.begin()) &&
|
||||
units_ == other.units_ && gradient_type_ == other.gradient_type_;
|
||||
y2_ == other.y2_ && r_ == other.r_ && std::equal(stops_.begin(), stops_.end(), other.stops_.begin()) &&
|
||||
units_ == other.units_ && gradient_type_ == other.gradient_type_;
|
||||
}
|
||||
|
||||
void gradient::set_gradient_type(gradient_e grad)
|
||||
|
|
|
@ -1533,8 +1533,8 @@ void parse_radial_gradient(svg_parser& parser, rapidxml::xml_node<char> const* n
|
|||
return;
|
||||
double cx = 0.5;
|
||||
double cy = 0.5;
|
||||
double fx = 0.0;
|
||||
double fy = 0.0;
|
||||
double fx = 0.5;
|
||||
double fy = 0.5;
|
||||
double r = 0.5;
|
||||
bool has_percent = false;
|
||||
|
||||
|
@ -1543,12 +1543,20 @@ void parse_radial_gradient(svg_parser& parser, rapidxml::xml_node<char> const* n
|
|||
{
|
||||
cx = parse_svg_value(parser, attr->value(), has_percent);
|
||||
}
|
||||
else if (gr.get_units() == USER_SPACE_ON_USE)
|
||||
{
|
||||
cx = 0.5 * (parser.vbox_ ? parser.vbox_->width : parser.path_.width()); // 50%
|
||||
}
|
||||
|
||||
attr = node->first_attribute("cy");
|
||||
if (attr != nullptr)
|
||||
{
|
||||
cy = parse_svg_value(parser, attr->value(), has_percent);
|
||||
}
|
||||
else if (gr.get_units() == USER_SPACE_ON_USE)
|
||||
{
|
||||
cy = 0.5 * (parser.vbox_ ? parser.vbox_->height : parser.path_.height()); // 50%
|
||||
}
|
||||
|
||||
attr = node->first_attribute("fx");
|
||||
if (attr != nullptr)
|
||||
|
@ -1573,19 +1581,11 @@ void parse_radial_gradient(svg_parser& parser, rapidxml::xml_node<char> const* n
|
|||
{
|
||||
r = parse_svg_value(parser, attr->value(), has_percent);
|
||||
}
|
||||
// this logic for detecting %'s will not support mixed coordinates.
|
||||
if (gr.get_units() == USER_SPACE_ON_USE)
|
||||
else if (gr.get_units() == USER_SPACE_ON_USE)
|
||||
{
|
||||
if (!has_percent && parser.path_.width() > 0 && parser.path_.height() > 0)
|
||||
{
|
||||
fx /= parser.path_.width();
|
||||
fy /= parser.path_.height();
|
||||
cx /= parser.path_.width();
|
||||
cy /= parser.path_.height();
|
||||
r /= parser.path_.width();
|
||||
}
|
||||
gr.set_units(USER_SPACE_ON_USE_BOUNDING_BOX);
|
||||
r = 0.5 * parser.normalized_diagonal_; // 50%
|
||||
}
|
||||
|
||||
gr.set_gradient_type(RADIAL);
|
||||
gr.set_control_points(fx, fy, cx, cy, r);
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ac363ee887d2a55039fd19390c186663d8f0f206
|
||||
Subproject commit 540561debb38280deb1b9598de1724e0ebd8df49
|
Loading…
Reference in a new issue