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) svg_height_(0.0)
{} {}
void set_opacity(double opacity) { svg_group_.opacity = opacity; }
void begin_group() void begin_group()
{ {
current_group_->elements.emplace_back(group {cur_attr().opacity, {}, current_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) 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> mapnik::image_rgba8 im(ren.width(), ren.height(), true, true);
(*this, ras, sl, ren, mtx, opacity, symbol_bbox, true), elem); 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, group_renderer(renderer_agg& renderer,
Rasterizer & ras, Scanline& sl, Renderer& ren, Rasterizer & ras, Scanline& sl, Renderer& ren,
agg::trans_affine const& mtx, agg::trans_affine const& mtx,
double opacity, box2d<double> const& symbol_bbox)
box2d<double> const& symbol_bbox,
bool first = false)
: renderer_(renderer), : renderer_(renderer),
ras_(ras), ras_(ras),
sl_(sl), sl_(sl),
ren_(ren), ren_(ren),
mtx_(mtx), mtx_(mtx),
opacity_(opacity), symbol_bbox_(symbol_bbox)
symbol_bbox_(symbol_bbox),
first_(first)
{} {}
void render_gradient(Rasterizer& ras, void render_gradient(Rasterizer& ras,
@ -281,7 +294,6 @@ class renderer_agg : util::noncopyable
void operator() (group const& g) const void operator() (group const& g) const
{ {
double opacity = g.opacity; double opacity = g.opacity;
if (first_) opacity *= opacity_; // adjust top level opacity
if (opacity < 1.0) if (opacity < 1.0)
{ {
mapnik::image_rgba8 im(ren_.width(), ren_.height(), true, true); 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) for (auto const& elem : g.elements)
{ {
mapbox::util::apply_visitor( 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)); 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) for (auto const& elem : g.elements)
{ {
mapbox::util::apply_visitor( 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_; Scanline& sl_;
Renderer& ren_; Renderer& ren_;
agg::trans_affine const& mtx_; agg::trans_affine const& mtx_;
double opacity_;
box2d<double> const& symbol_bbox_; box2d<double> const& symbol_bbox_;
bool first_;
}; };
#if defined(GRID_RENDERER) #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_width = get_optional<double>(sym, keys::stroke_width, feature, vars);
auto stroke_opacity = get_optional<double>(sym, keys::stroke_opacity, feature, vars); auto stroke_opacity = get_optional<double>(sym, keys::stroke_opacity, feature, vars);
bool success = false; bool success = false;
dst.opacity = src.opacity;
if (fill_color || fill_opacity || stroke_color || stroke_width || stroke_opacity) if (fill_color || fill_opacity || stroke_color || stroke_width || stroke_opacity)
{ {
for (auto const& elem : src.elements) 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_) if (parser.css_style_)
process_css(parser, node); process_css(parser, node);
parse_attr(parser, node); parse_attr(parser, node);
if (parser.path_.cur_attr().opacity < 1.0) parser.path_.begin_group();
parse_use(parser, node); parse_use(parser, node);
if (parser.path_.cur_attr().opacity < 1.0) parser.path_.end_group();
parser.path_.pop_attr(); parser.path_.pop_attr();
break; break;
default: default:
@ -622,11 +624,10 @@ void end_element(svg_parser& parser, rapidxml::xml_node<char> const* node)
} }
else if (name == "svg"_case) else if (name == "svg"_case)
{ {
parser.path_.end_group(); //if (node->first_node() != nullptr)
if (node->first_node() != nullptr) //{
{ //parser.path_.pop_attr();
parser.path_.pop_attr(); //}
}
} }
else if (name == "defs"_case) 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); parse_ellipse(parser, node);
break; break;
case "svg"_case: case "svg"_case:
parser.path_.begin_group(); //parser.path_.push_attr();
parser.path_.push_attr();
parse_dimensions(parser, node); parse_dimensions(parser, node);
parse_attr(parser, node); parse_attr(parser, node);
parser.path_.set_opacity(parser.path_.cur_attr().opacity);
break; break;
default: default:
handle_unsupported(parser, unsupported_elements, name, "element"); handle_unsupported(parser, unsupported_elements, name, "element");