Browse files

restore the fast line rasterizer (rasterizer_outline_aa) and improve …

…its rendering quality and consistency with standard method - refs #873
  • Loading branch information...
1 parent ac2d935 commit c1495c0c74f6ac574f926fa63aa1491e07d45265 @springmeyer springmeyer committed May 11, 2012
View
9 bindings/python/mapnik_line_symbolizer.cpp
@@ -42,12 +42,19 @@ struct line_symbolizer_pickle_suite : boost::python::pickle_suite
void export_line_symbolizer()
{
using namespace boost::python;
-
+ enumeration_<line_rasterizer_e>("line_rasterizer")
+ .value("FULL",RASTERIZER_FULL)
+ .value("FAST",RASTERIZER_FAST)
+ ;
class_<line_symbolizer>("LineSymbolizer",
init<>("Default LineSymbolizer - 1px solid black"))
.def(init<stroke const&>("TODO"))
.def(init<color const& ,float>())
.def_pickle(line_symbolizer_pickle_suite())
+ .add_property("rasterizer",
+ &line_symbolizer::get_rasterizer,
+ &line_symbolizer::set_rasterizer,
+ "Set/get the rasterization method of the line of the point")
.add_property("stroke",make_function
(&line_symbolizer::get_stroke,
return_value_policy<copy_const_reference>()),
View
35 include/mapnik/agg_helpers.hpp
@@ -32,6 +32,7 @@
#include "agg_scanline_p.h"
#include "agg_renderer_outline_aa.h"
#include "agg_renderer_scanline.h"
+#include "agg_rasterizer_outline_aa.h"
namespace mapnik {
@@ -94,6 +95,40 @@ void set_join_caps(Stroke const& stroke_, PathType & stroke)
}
+template <typename Stroke,typename Rasterizer>
+void set_join_caps_aa(Stroke const& stroke_, Rasterizer & ras)
+{
+
+ line_join_e join=stroke_.get_line_join();
+ switch (join)
+ {
+ case MITER_JOIN:
+ ras.line_join(agg::outline_miter_accurate_join);
+ break;
+ case MITER_REVERT_JOIN:
+ ras.line_join(agg::outline_no_join);
+ break;
+ case ROUND_JOIN:
+ ras.line_join(agg::outline_round_join);
+ break;
+ default:
+ ras.line_join(agg::outline_no_join);
+ }
+
+ line_cap_e cap=stroke_.get_line_cap();
+ switch (cap)
+ {
+ case BUTT_CAP:
+ ras.round_cap(false);
+ break;
+ case SQUARE_CAP:
+ ras.round_cap(false);
+ break;
+ default:
+ ras.round_cap(true);
+ }
+}
+
template <typename PixelFormat>
struct renderer_scanline_solid : private boost::noncopyable
{
View
31 include/mapnik/line_symbolizer.hpp
@@ -31,24 +31,36 @@
namespace mapnik
{
+enum line_rasterizer_enum {
+ RASTERIZER_FULL, // agg::renderer_scanline_aa_solid
+ RASTERIZER_FAST, // agg::rasterizer_outline_aa, twice as fast but only good for thin lines
+ line_rasterizer_enum_MAX
+};
+
+DEFINE_ENUM( line_rasterizer_e, line_rasterizer_enum );
+
+
struct MAPNIK_DECL line_symbolizer : public symbolizer_base
{
explicit line_symbolizer()
: symbolizer_base(),
stroke_(),
- offset_(0.0)
+ offset_(0.0),
+ rasterizer_p_(RASTERIZER_FULL)
{}
line_symbolizer(stroke const& stroke)
: symbolizer_base(),
stroke_(stroke),
- offset_(0.0)
+ offset_(0.0),
+ rasterizer_p_(RASTERIZER_FULL)
{}
line_symbolizer(color const& pen,float width=1.0)
: symbolizer_base(),
stroke_(pen,width),
- offset_(0.0)
+ offset_(0.0),
+ rasterizer_p_(RASTERIZER_FULL)
{}
stroke const& get_stroke() const
@@ -70,10 +82,21 @@ struct MAPNIK_DECL line_symbolizer : public symbolizer_base
{
return offset_;
}
-
+
+ void set_rasterizer(line_rasterizer_e rasterizer_p)
+ {
+ rasterizer_p_ = rasterizer_p;
+ }
+
+ line_rasterizer_e get_rasterizer() const
+ {
+ return rasterizer_p_;
+ }
+
private:
stroke stroke_;
double offset_;
+ line_rasterizer_e rasterizer_p_;
};
}
View
92 src/agg/process_line_symbolizer.cpp
@@ -63,45 +63,81 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
ras_ptr->reset();
set_gamma_method(stroke_, ras_ptr);
-
- typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
- vertex_converter<box2d<double>,rasterizer,line_symbolizer, proj_transform, CoordTransform,conv_types>
- converter(query_extent_,*ras_ptr,sym,t_,prj_trans,scale_factor_);
-
- if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
- converter.set<transform_tag>(); // always transform
-
- if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
- converter.set<affine_transform_tag>(); // optional affine transform
- if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
- if (stroke_.has_dash()) converter.set<dash_tag>();
- converter.set<stroke_tag>(); //always stroke
-
- BOOST_FOREACH( geometry_type & geom, feature->paths())
- {
- if (geom.num_points() > 1)
- {
- converter.apply(geom);
- }
- }
agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4);
-
typedef agg::rgba8 color_type;
typedef agg::order_rgba order_type;
typedef agg::pixel32_type pixel_type;
typedef agg::comp_op_adaptor_rgba<color_type, order_type> blender_type; // comp blender
typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_comp_type;
typedef agg::renderer_base<pixfmt_comp_type> renderer_base;
- typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
+
pixfmt_comp_type pixf(buf);
- pixf.comp_op(static_cast<agg::comp_op_e>(sym.comp_op()));
renderer_base renb(pixf);
- renderer_type ren(renb);
- ren.color(agg::rgba8(r, g, b, int(a * stroke_.get_opacity())));
- agg::scanline_u8 sl;
- agg::render_scanlines(*ras_ptr, sl, ren);
+
+ if (sym.get_rasterizer() == RASTERIZER_FAST)
+ {
+ typedef agg::renderer_outline_aa<renderer_base> renderer_type;
+ typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
+ // need to reduce width by half to match standard rasterizer look
+ double scaled = scale_factor_ * .5;
+ agg::line_profile_aa profile(stroke_.get_width() * scaled, agg::gamma_power(stroke_.get_gamma()));
+ renderer_type ren(renb, profile);
+ ren.color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity())));
+ rasterizer_type ras(ren);
+ set_join_caps_aa(stroke_,ras);
+
+ typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
+ vertex_converter<box2d<double>,rasterizer_type,line_symbolizer, proj_transform, CoordTransform,conv_types>
+ converter(query_extent_,ras,sym,t_,prj_trans,scaled);
+
+ if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
+ converter.set<transform_tag>(); // always transform
+ if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
+ converter.set<affine_transform_tag>(); // optional affine transform
+ if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
+ if (stroke_.has_dash()) converter.set<dash_tag>();
+ converter.set<stroke_tag>(); //always stroke
+
+ BOOST_FOREACH( geometry_type & geom, feature->paths())
+ {
+ if (geom.num_points() > 1)
+ {
+ converter.apply(geom);
+ }
+ }
+ }
+ else
+ {
+ typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
+ vertex_converter<box2d<double>,rasterizer,line_symbolizer, proj_transform, CoordTransform,conv_types>
+ converter(query_extent_,*ras_ptr,sym,t_,prj_trans,scale_factor_);
+
+ if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
+ converter.set<transform_tag>(); // always transform
+ if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
+ converter.set<affine_transform_tag>(); // optional affine transform
+ if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
+ if (stroke_.has_dash()) converter.set<dash_tag>();
+ converter.set<stroke_tag>(); //always stroke
+
+ BOOST_FOREACH( geometry_type & geom, feature->paths())
+ {
+ if (geom.num_points() > 1)
+ {
+ converter.apply(geom);
+ }
+ }
+
+ typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
+ pixf.comp_op(static_cast<agg::comp_op_e>(sym.comp_op()));
+ renderer_base renb(pixf);
+ renderer_type ren(renb);
+ ren.color(agg::rgba8(r, g, b, int(a * stroke_.get_opacity())));
+ agg::scanline_u8 sl;
+ agg::render_scanlines(*ras_ptr, sl, ren);
+ }
}
View
9 src/line_symbolizer.cpp
@@ -26,6 +26,13 @@
namespace mapnik
{
-//
+
+static const char * line_rasterizer_strings[] = {
+ "full",
+ "fast",
+ ""
+};
+IMPLEMENT_ENUM( line_rasterizer_e, line_rasterizer_strings )
+
}
View
5 src/load_map.cpp
@@ -1430,7 +1430,10 @@ void map_parser::parse_line_symbolizer(rule & rule, xml_node const & sym)
// offset value
optional<double> offset = sym.get_opt_attr<double>("offset");
if (offset) symbol.set_offset(*offset);
-
+
+ line_rasterizer_e rasterizer = sym.get_attr<line_rasterizer_e>("rasterizer", RASTERIZER_FULL);
+ symbol.set_rasterizer(rasterizer);
+
// meta-writer
parse_symbolizer_base(symbol, sym);
rule.append(symbol);
View
6 src/save_map.cpp
@@ -84,6 +84,12 @@ class serialize_symbolizer : public boost::static_visitor<>
const stroke & strk = sym.get_stroke();
add_stroke_attributes(sym_node, strk);
add_metawriter_attributes(sym_node, sym);
+
+ line_symbolizer dfl;
+ if ( sym.get_rasterizer() != dfl.get_rasterizer() || explicit_defaults_ )
+ {
+ set_attr( sym_node, "rasterizer", sym.get_rasterizer() );
+ }
}
void operator () ( line_pattern_symbolizer const& sym )
View
1 src/xml_tree.cpp
@@ -475,6 +475,7 @@ compile_get_attr(point_placement_e);
compile_get_attr(marker_placement_e);
compile_get_attr(marker_type_e);
compile_get_attr(pattern_alignment_e);
+compile_get_attr(line_rasterizer_e);
compile_get_attr(colorizer_mode);
compile_get_attr(double);
compile_get_value(int);

0 comments on commit c1495c0

Please sign in to comment.