SVG - refactor and minimise internal group usage [WIP] [skip ci]

This commit is contained in:
Artem Pavlenko 2022-11-23 15:53:08 +00:00
parent 8c04fb1262
commit 5f4711a019
4 changed files with 35 additions and 21 deletions

View file

@ -65,6 +65,8 @@ class svg_converter : util::noncopyable
svg_height_(0.0)
{}
void set_opacity(double opacity) { svg_group_.opacity = opacity; }
void begin_group()
{
current_group_->elements.emplace_back(group {cur_attr().opacity, {}, current_group_});

View file

@ -145,10 +145,27 @@ class renderer_agg : util::noncopyable
box2d<double> const& symbol_bbox)
{
for (auto const& elem : svg_group_.elements)
double adjusted_opacity = opacity * svg_group_.opacity; // adjust top level opacity
if (adjusted_opacity < 1.0)
{
mapbox::util::apply_visitor(group_renderer<Rasterizer, Scanline, Renderer>
(*this, ras, sl, ren, mtx, opacity, symbol_bbox, true), elem);
mapnik::image_rgba8 im(ren.width(), ren.height(), true, true);
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
PixelFormat pixf(buf);
Renderer ren_g(pixf);
for (auto const& elem : svg_group_.elements)
{
mapbox::util::apply_visitor(group_renderer<Rasterizer, Scanline, Renderer>
(*this, ras, sl, ren_g, mtx, symbol_bbox), elem);
}
ren.blend_from(ren_g.ren(), 0, 0, 0, unsigned(adjusted_opacity * 255));
}
else
{
for (auto const& elem : svg_group_.elements)
{
mapbox::util::apply_visitor(group_renderer<Rasterizer, Scanline, Renderer>
(*this, ras, sl, ren, mtx, symbol_bbox), elem);
}
}
}
@ -158,17 +175,13 @@ class renderer_agg : util::noncopyable
group_renderer(renderer_agg& renderer,
Rasterizer & ras, Scanline& sl, Renderer& ren,
agg::trans_affine const& mtx,
double opacity,
box2d<double> const& symbol_bbox,
bool first = false)
box2d<double> const& symbol_bbox)
: renderer_(renderer),
ras_(ras),
sl_(sl),
ren_(ren),
mtx_(mtx),
opacity_(opacity),
symbol_bbox_(symbol_bbox),
first_(first)
symbol_bbox_(symbol_bbox)
{}
void render_gradient(Rasterizer& ras,
@ -281,7 +294,6 @@ class renderer_agg : util::noncopyable
void operator() (group const& g) const
{
double opacity = g.opacity;
if (first_) opacity *= opacity_; // adjust top level opacity
if (opacity < 1.0)
{
mapnik::image_rgba8 im(ren_.width(), ren_.height(), true, true);
@ -291,7 +303,7 @@ class renderer_agg : util::noncopyable
for (auto const& elem : g.elements)
{
mapbox::util::apply_visitor(
group_renderer(renderer_, ras_, sl_, ren, mtx_, opacity_, symbol_bbox_), elem);
group_renderer(renderer_, ras_, sl_, ren, mtx_, symbol_bbox_), elem);
}
ren_.blend_from(ren.ren(), 0, 0, 0, unsigned(opacity * 255));
}
@ -300,7 +312,7 @@ class renderer_agg : util::noncopyable
for (auto const& elem : g.elements)
{
mapbox::util::apply_visitor(
group_renderer(renderer_, ras_, sl_, ren_, mtx_, opacity_, symbol_bbox_), elem);
group_renderer(renderer_, ras_, sl_, ren_, mtx_, symbol_bbox_), elem);
}
}
}
@ -463,9 +475,7 @@ class renderer_agg : util::noncopyable
Scanline& sl_;
Renderer& ren_;
agg::trans_affine const& mtx_;
double opacity_;
box2d<double> const& symbol_bbox_;
bool first_;
};
#if defined(GRID_RENDERER)

View file

@ -189,6 +189,7 @@ bool push_explicit_style(svg::group const& src,
auto stroke_width = get_optional<double>(sym, keys::stroke_width, feature, vars);
auto stroke_opacity = get_optional<double>(sym, keys::stroke_opacity, feature, vars);
bool success = false;
dst.opacity = src.opacity;
if (fill_color || fill_opacity || stroke_color || stroke_width || stroke_opacity)
{
for (auto const& elem : src.elements)

View file

@ -548,7 +548,9 @@ void traverse_tree(svg_parser& parser, rapidxml::xml_node<char> const* node)
if (parser.css_style_)
process_css(parser, node);
parse_attr(parser, node);
if (parser.path_.cur_attr().opacity < 1.0) parser.path_.begin_group();
parse_use(parser, node);
if (parser.path_.cur_attr().opacity < 1.0) parser.path_.end_group();
parser.path_.pop_attr();
break;
default:
@ -622,11 +624,10 @@ void end_element(svg_parser& parser, rapidxml::xml_node<char> const* node)
}
else if (name == "svg"_case)
{
parser.path_.end_group();
if (node->first_node() != nullptr)
{
parser.path_.pop_attr();
}
//if (node->first_node() != nullptr)
//{
//parser.path_.pop_attr();
//}
}
else if (name == "defs"_case)
{
@ -675,10 +676,10 @@ void parse_element(svg_parser& parser, char const* name, rapidxml::xml_node<char
parse_ellipse(parser, node);
break;
case "svg"_case:
parser.path_.begin_group();
parser.path_.push_attr();
//parser.path_.push_attr();
parse_dimensions(parser, node);
parse_attr(parser, node);
parser.path_.set_opacity(parser.path_.cur_attr().opacity);
break;
default:
handle_unsupported(parser, unsupported_elements, name, "element");