Created
June 26, 2012 22:27
-
-
Save pierremarc/2999728 to your computer and use it in GitHub Desktop.
SVG polygon symbolizer hack / mapnik
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp | |
index bf81cc5..0643da0 100644 | |
--- a/src/cairo_renderer.cpp | |
+++ b/src/cairo_renderer.cpp | |
@@ -19,7 +19,7 @@ | |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
* | |
*****************************************************************************/ | |
- | |
+#define HAVE_CAIRO | |
#if defined(HAVE_CAIRO) | |
// mapnik | |
@@ -61,8 +61,17 @@ | |
#include "agg_path_storage.h" | |
#include "agg_ellipse.h" | |
+// debug | |
+#include <iostream> | |
+ | |
namespace mapnik | |
{ | |
+ | |
+Cairo::ErrorStatus pseudo_pdf_writer(const unsigned char* /*data*/, unsigned int /*length*/) | |
+{ | |
+ return CAIRO_STATUS_SUCCESS; | |
+} | |
+ | |
class cairo_pattern : private boost::noncopyable | |
{ | |
public: | |
@@ -132,11 +141,31 @@ public: | |
return pattern_; | |
} | |
+ static cairo_pattern* get_pattern(const std::string& key) | |
+ { | |
+ if(pat_pool_.find(key) != pat_pool_.end()) | |
+ return pat_pool_.find(key)->second; | |
+ | |
+ boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance()->find(key,true); | |
+ if (!marker && !(*marker)->is_bitmap()) | |
+ { | |
+ return 0; | |
+ } | |
+ cairo_pattern* pat(new cairo_pattern(**((*marker)->get_bitmap_data()))); | |
+ pat_pool_[key] = pat; | |
+ return pat; | |
+ } | |
+ | |
private: | |
Cairo::RefPtr<Cairo::ImageSurface> surface_; | |
Cairo::RefPtr<Cairo::SurfacePattern> pattern_; | |
+ | |
+ static std::map<std::string, cairo_pattern* > pat_pool_; | |
}; | |
+std::map<std::string, cairo_pattern* > cairo_pattern::pat_pool_ = std::map<std::string, cairo_pattern* >(); | |
+ | |
+ | |
class cairo_gradient : private boost::noncopyable | |
{ | |
public: | |
@@ -496,6 +525,7 @@ public: | |
template <typename T> | |
void add_agg_path(T& path, unsigned start_index = 0) | |
{ | |
+// std::cerr<<"ADD_AGG_PATH ======================="<<std::endl; | |
double x=0; | |
double y=0; | |
@@ -506,6 +536,7 @@ public: | |
if (agg::is_move_to(cm)) | |
{ | |
move_to(x, y); | |
+// std::cerr<<"M " <<x<<"\t "<<y<<std::endl; | |
} | |
else if (agg::is_drawing(cm)) | |
{ | |
@@ -535,6 +566,7 @@ public: | |
else if (agg::is_line_to(cm)) | |
{ | |
line_to(x, y); | |
+// std::cerr<<"L " <<x<<"\t "<<y<<std::endl; | |
} | |
else | |
{ | |
@@ -1275,38 +1307,94 @@ void cairo_renderer_base::start_map_processing(Map const& map) | |
mapnik::feature_ptr const& feature, | |
proj_transform const& prj_trans) | |
{ | |
+ typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type; | |
+ typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type; | |
cairo_context context(context_); | |
context.set_operator(sym.comp_op()); | |
std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature); | |
boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance()->find(filename,true); | |
- if (!marker && !(*marker)->is_bitmap()) return; | |
- | |
- cairo_pattern pattern(**((*marker)->get_bitmap_data())); | |
- | |
- pattern.set_extend(Cairo::EXTEND_REPEAT); | |
- | |
- context.set_pattern(pattern); | |
+ if (!marker) | |
+ return; | |
+ if((*marker)->is_bitmap()) | |
+ { | |
+ | |
+ // cairo_pattern pattern(**((*marker)->get_bitmap_data())); | |
+ cairo_pattern* pattern(cairo_pattern::get_pattern(filename)); | |
+ | |
+ pattern->set_extend(Cairo::EXTEND_REPEAT); | |
+ | |
+ context.set_pattern(*pattern); | |
+ | |
+ typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types; | |
+ vertex_converter<box2d<double>,cairo_context,polygon_pattern_symbolizer, proj_transform, CoordTransform, conv_types> | |
+ converter(query_extent_,context,sym,t_,prj_trans,1.0); | |
+ | |
+ if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true) | |
+ converter.set<transform_tag>(); //always transform | |
+ converter.set<affine_transform_tag>(); | |
+ if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter | |
+ | |
+ BOOST_FOREACH( geometry_type & geom, feature->paths()) | |
+ { | |
+ if (geom.num_points() > 2) | |
+ { | |
+ converter.apply(geom); | |
+ } | |
+ } | |
+ | |
+ // fill polygon | |
+ context.fill(); | |
+ } | |
+ else if((*marker)->is_vector()) | |
+ { | |
+ | |
+ mapnik::path_ptr mk(*(*marker)->get_vector_data()); | |
+ mapnik::svg::path_attributes attrs(mk->attributes()[0]); | |
+ | |
+ double dx,dy; | |
+ attrs.transform.translation(&dx,&dy); | |
+ agg::path_base<agg::vertex_stl_storage<std::vector<agg::vertex_d> > > agg_path; | |
+ BOOST_FOREACH(const agg::vertex_d & v, mk->source()) | |
+ { | |
+ double vx(v.x + dx); | |
+ double vy(v.y + dy); | |
+ agg_path.vertices().add_vertex(vx, vy, v.cmd); | |
+ } | |
+ double patWidth((*marker)->width()); | |
+ double patHeight((*marker)->height()); | |
+ | |
+ Cairo::RefPtr<Cairo::PdfSurface> patSurface(Cairo::PdfSurface::create_for_stream(sigc::ptr_fun(&(mapnik::pseudo_pdf_writer)), patWidth, patHeight)); | |
+ Cairo::RefPtr<Cairo::Context> const& patContext = Cairo::Context::create(patSurface); | |
+ mapnik::cairo_context pctx(patContext); // to easily draw agg_path | |
+ pctx.add_agg_path(agg_path); | |
+ | |
+ pctx.set_color(attrs.fill_color.r,attrs.fill_color.g,attrs.fill_color.b, attrs.fill_color.a); | |
+ pctx.set_line_width(attrs.stroke_width); | |
+ pctx.fill(); | |
+ | |
+ pctx.set_color(attrs.stroke_color.r,attrs.stroke_color.g,attrs.stroke_color.b, attrs.stroke_color.a); | |
+ pctx.set_line_width(attrs.stroke_width); | |
+ pctx.stroke(); | |
+ | |
+ Cairo::RefPtr<Cairo::SurfacePattern> patPattern(Cairo::SurfacePattern::create(patSurface)); | |
+ patPattern->set_extend(Cairo::EXTEND_REPEAT); | |
+ context_->set_source(patPattern); | |
+ | |
+ BOOST_FOREACH( geometry_type & geom, feature->paths()) | |
+ { | |
+ if (geom.num_points() > 2) | |
+ { | |
+ 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); | |
+ context.add_path(path); | |
+ } | |
+ } | |
+ | |
+ context.fill(); | |
+ } | |
- typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types; | |
- vertex_converter<box2d<double>,cairo_context,polygon_pattern_symbolizer, proj_transform, CoordTransform, conv_types> | |
- converter(query_extent_,context,sym,t_,prj_trans,1.0); | |
- | |
- if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true) | |
- converter.set<transform_tag>(); //always transform | |
- converter.set<affine_transform_tag>(); | |
- if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter | |
- | |
- BOOST_FOREACH( geometry_type & geom, feature->paths()) | |
- { | |
- if (geom.num_points() > 2) | |
- { | |
- converter.apply(geom); | |
- } | |
- } | |
- | |
- // fill polygon | |
- context.fill(); | |
} | |
void cairo_renderer_base::process(raster_symbolizer const& sym, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment