diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index e120f1552..61710d476 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -23,9 +23,11 @@ // mapnik #include #include +#include #include #include #include +#include #include #include #include @@ -49,6 +51,97 @@ namespace mapnik { +template +struct markers_rasterizer_dispatch +{ + typedef agg::rgba8 color_type; + typedef agg::order_rgba order_type; + typedef agg::pixel32_type pixel_type; + typedef agg::comp_op_adaptor_rgba_pre blender_type; // comp blender + typedef agg::pixfmt_custom_blend_rgba pixfmt_comp_type; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_type; + + markers_rasterizer_dispatch(BufferType & image_buffer, + SvgRenderer & svg_renderer, + Rasterizer & ras, + box2d const& bbox, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor) + : buf_(image_buffer.raw_data(), image_buffer.width(), image_buffer.height(), image_buffer.width() * 4), + pixf_(buf_), + renb_(pixf_), + svg_renderer_(svg_renderer), + ras_(ras), + bbox_(bbox), + marker_trans_(marker_trans), + sym_(sym), + detector_(detector), + scale_factor_(scale_factor) + { + pixf_.comp_op(static_cast(sym_.comp_op())); + } + + template + void add_path(T & path) + { + marker_placement_e placement_method = sym_.get_marker_placement(); +// std::cout << "add_path called -> " << placement_method << std::endl; +// std::cout << typeid(path).name() << std::endl; + if (placement_method == MARKER_POINT_PLACEMENT) + { + + double x,y; + path.rewind(0); + label_interior_position(path, x, y); +// std::cout << "pos -> " << x << "," << y << std::endl; + agg::trans_affine matrix = marker_trans_; + matrix.translate(x,y); + box2d transformed_bbox = bbox_ * matrix; + + if (sym_.get_allow_overlap() || + detector_.has_placement(transformed_bbox)) + { + svg_renderer_.render(ras_, sl_, renb_, matrix, sym_.get_opacity(), bbox_); + + if (!sym_.get_ignore_placement()) + detector_.insert(transformed_bbox); + } + } + else + { + markers_placement placement(path, bbox_, marker_trans_, detector_, + sym_.get_spacing() * scale_factor_, + sym_.get_max_error(), + sym_.get_allow_overlap()); + double x, y, angle; + while (placement.get_point(x, y, angle)) + { + agg::trans_affine matrix = marker_trans_; + matrix.rotate(angle); + matrix.translate(x, y); + svg_renderer_.render(ras_, sl_, renb_, matrix, sym_.get_opacity(), bbox_); + } + } + } + +private: + agg::scanline_u8 sl_; + agg::rendering_buffer buf_; + pixfmt_comp_type pixf_; + renderer_base renb_; + SvgRenderer & svg_renderer_; + Rasterizer & ras_; + box2d const& bbox_; + agg::trans_affine const& marker_trans_; + markers_symbolizer const& sym_; + Detector & detector_; + double scale_factor_; +}; + + template void agg_renderer::process(markers_symbolizer const& sym, mapnik::feature_impl & feature, @@ -77,12 +170,6 @@ void agg_renderer::process(markers_symbolizer const& sym, ras_ptr->reset(); ras_ptr->gamma(agg::gamma_power()); - agg::scanline_u8 sl; - agg::rendering_buffer buf(current_buffer_->raw_data(), width_, height_, width_ * 4); - pixfmt_comp_type pixf(buf); - pixf.comp_op(static_cast(sym.comp_op())); - renderer_base renb(pixf); - renderer_type ren(renb); agg::trans_affine geom_tr; evaluate_transform(geom_tr, feature, sym.get_transform()); @@ -105,100 +192,36 @@ void agg_renderer::process(markers_symbolizer const& sym, agg::pod_bvector attributes; bool result = push_explicit_style( (*marker)->attributes(), attributes, sym); - svg_renderer, - renderer_type, - agg::pixfmt_rgba32 > svg_renderer(svg_path, result ? attributes : (*marker)->attributes()); + typedef label_collision_detector4 detector_type; + typedef svg_renderer, + renderer_type, + agg::pixfmt_rgba32 > svg_renderer_type; + typedef markers_rasterizer_dispatch markers_rasterizer_dispatch_type; + typedef boost::mpl::vector conv_types; - marker_placement_e placement_method = sym.get_marker_placement(); + svg_renderer_type svg_renderer(svg_path, result ? attributes : (*marker)->attributes()); - BOOST_FOREACH( geometry_type & geom, feature.paths()) + markers_rasterizer_dispatch_type rasterizer_dispatch(*current_buffer_,svg_renderer,*ras_ptr, + bbox, marker_trans, sym, *detector_, scale_factor_); + + + vertex_converter, markers_rasterizer_dispatch_type, markers_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(query_extent_* 1.1,rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + + if (sym.clip()) converter.template set(); //optional clip (default: true) + converter.template set(); //always transform + if (sym.smooth() > 0.0) converter.template set(); // optional smooth converter + + BOOST_FOREACH(geometry_type & geom, feature.paths()) { - // TODO - merge this code with point_symbolizer rendering - if (placement_method == MARKER_POINT_PLACEMENT || geom.num_points() <= 1) - { - double x; - double y; - double z=0; - geom.label_interior_position(&x, &y); - prj_trans.backward(x,y,z); - t_.forward(&x,&y); - geom_tr.transform(&x,&y); - agg::trans_affine matrix = marker_trans; - matrix.translate(x,y); - box2d transformed_bbox = bbox * matrix; - - if (sym.get_allow_overlap() || - detector_->has_placement(transformed_bbox)) - { - svg_renderer.render(*ras_ptr, sl, renb, matrix, sym.get_opacity(), bbox); - if (/* DEBUG */ 0) - { - debug_draw_box(buf, transformed_bbox, 0, 0, 0.0); - } - - if (!sym.get_ignore_placement()) - detector_->insert(transformed_bbox); - } - } - else if (sym.clip()) - { - typedef agg::conv_clip_polyline clipped_geometry_type; - typedef coord_transform path_type; - typedef agg::conv_transform transformed_path_type; - - clipped_geometry_type clipped(geom); - clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); - path_type path(t_,clipped,prj_trans); - transformed_path_type path_transformed(path,geom_tr); - markers_placement placement(path_transformed, bbox, marker_trans, *detector_, - sym.get_spacing() * scale_factor_, - sym.get_max_error(), - sym.get_allow_overlap()); - double x, y, angle; - while (placement.get_point(x, y, angle)) - { - agg::trans_affine matrix = marker_trans; - matrix.rotate(angle); - matrix.translate(x, y); - svg_renderer.render(*ras_ptr, sl, renb, matrix, sym.get_opacity(), bbox); - - if (/* DEBUG */ 0) - { - debug_draw_box(buf, bbox*matrix, 0, 0, 0.0); - } - } - } - else - { - typedef coord_transform path_type; - typedef agg::conv_transform transformed_path_type; - path_type path(t_,geom,prj_trans); - transformed_path_type path_transformed(path,geom_tr); - markers_placement placement(path_transformed, bbox, marker_trans, *detector_, - sym.get_spacing() * scale_factor_, - sym.get_max_error(), - sym.get_allow_overlap()); - double x, y, angle; - while (placement.get_point(x, y, angle)) - { - agg::trans_affine matrix = marker_trans; - matrix.rotate(angle); - matrix.translate(x, y); - svg_renderer.render(*ras_ptr, sl, renb, matrix, sym.get_opacity(), bbox); - - if (/* DEBUG */ 0) - { - debug_draw_box(buf, bbox*matrix, 0, 0, 0.0); - } - } - } + converter.apply(geom); } } } } - template void agg_renderer::process(markers_symbolizer const&, mapnik::feature_impl &, proj_transform const&);