From d27b45553a2aa1f0dd6e2d7472e708f79a5a85a7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 15:19:37 -0700 Subject: [PATCH 01/25] use emplace/emplace_back over insert/push_back - refs #2336 --- include/mapnik/attribute_collector.hpp | 6 +++--- include/mapnik/feature.hpp | 4 ++-- .../renderer_common/process_group_symbolizer.hpp | 2 +- include/mapnik/symbolizer.hpp | 7 ++----- include/mapnik/util/geometry_to_wkb.hpp | 4 ++-- include/mapnik/xml_attribute_cast.hpp | 2 +- plugins/input/postgis/postgis_datasource.cpp | 2 +- plugins/input/python/python_datasource.cpp | 2 +- src/cairo/cairo_context.cpp | 3 +-- src/datasource_cache.cpp | 2 +- src/font_engine_freetype.cpp | 6 +++--- src/grid/grid.cpp | 4 ++-- src/load_map.cpp | 2 +- src/map.cpp | 4 ++-- src/mapped_memory_cache.cpp | 6 ++---- src/marker_cache.cpp | 12 ++++++------ src/text/face.cpp | 2 +- src/text/formatting/registry.cpp | 2 +- src/text/placements/registry.cpp | 2 +- src/xml_tree.cpp | 2 +- 20 files changed, 35 insertions(+), 41 deletions(-) diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp index 16d397ca4..2e0eec6cf 100644 --- a/include/mapnik/attribute_collector.hpp +++ b/include/mapnik/attribute_collector.hpp @@ -56,7 +56,7 @@ struct expression_attributes : boost::static_visitor void operator() (attribute const& attr) const { - names_.insert(attr.name()); + names_.emplace(attr.name()); } template @@ -289,7 +289,7 @@ inline void group_attribute_collector::operator() (group_symbolizer const& sym) { std::string col_idx_name = col_name; boost::replace_all(col_idx_name, "%", col_idx_str); - names_.insert(col_idx_name); + names_.emplace(col_idx_name); } } } @@ -298,7 +298,7 @@ inline void group_attribute_collector::operator() (group_symbolizer const& sym) { // This is not an indexed column, or we are ignoring indexes. // Insert the name as is. - names_.insert(col_name); + names_.emplace(col_name); } } } diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 10be7d64f..9547ba86b 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -67,13 +67,13 @@ public: inline size_type push(key_type const& name) { size_type index = mapping_.size(); - mapping_.insert(std::make_pair(name, index)); + mapping_.emplace(name, index); return index; } inline void add(key_type const& name, size_type index) { - mapping_.insert(std::make_pair(name, index)); + mapping_.emplace(name, index); } inline size_type size() const { return mapping_.size(); } diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index c4cc390d3..abf13dbfc 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -268,7 +268,7 @@ void render_group_symbolizer(group_symbolizer const& sym, *(rule->get_filter())).to_bool()) { // add matched rule and feature to the list of things to draw - matches.push_back(std::make_pair(rule, sub_feature)); + matches.emplace_back(rule, sub_feature); // construct a bounding box around all symbolizers for the matched rule bound_box bounds; diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 56a55e852..a84d7c7be 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -311,10 +311,7 @@ struct put_impl } else { - // NOTE: we use insert here instead of emplace - // because of lacking std::map emplace support in libstdc++ - // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44436 - sym.properties.insert(std::make_pair(key, enumeration_wrapper(val))); + sym.properties.emplace(key, enumeration_wrapper(val)); } } }; @@ -331,7 +328,7 @@ struct put_impl } else { - sym.properties.insert(std::make_pair(key, val)); + sym.properties.emplace(key, val); } } }; diff --git a/include/mapnik/util/geometry_to_wkb.hpp b/include/mapnik/util/geometry_to_wkb.hpp index ff89bd721..53245aecb 100644 --- a/include/mapnik/util/geometry_to_wkb.hpp +++ b/include/mapnik/util/geometry_to_wkb.hpp @@ -196,13 +196,13 @@ wkb_buffer_ptr to_polygon_wkb( GeometryType const& g, wkbByteOrder byte_order) if (command == SEG_MOVETO) { rings.push_back(new linear_ring); // start new loop - rings.back().push_back(std::make_pair(x,y)); + rings.back().emplace_back(x,y); size += 4; // num_points size += 2 * 8; // point } else if (command == SEG_LINETO) { - rings.back().push_back(std::make_pair(x,y)); + rings.back().emplace_back(x,y); size += 2 * 8; // point } } diff --git a/include/mapnik/xml_attribute_cast.hpp b/include/mapnik/xml_attribute_cast.hpp index 9398b4ff8..2e4c666b1 100644 --- a/include/mapnik/xml_attribute_cast.hpp +++ b/include/mapnik/xml_attribute_cast.hpp @@ -194,7 +194,7 @@ struct do_xml_attribute_cast else { mapnik::expression_ptr expr = parse_expression(source); - tree.expr_cache_.insert(std::make_pair(source,expr)); + tree.expr_cache_.emplace(source,expr); return expr; } } diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 9ca1756f0..5ce128af3 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -684,7 +684,7 @@ processor_context_ptr postgis_datasource::get_context(feature_style_context_map } else { - return ctx.insert(std::make_pair(ds_name,std::make_shared())).first->second; + return ctx.emplace(ds_name,std::make_shared()).first->second; } } diff --git a/plugins/input/python/python_datasource.cpp b/plugins/input/python/python_datasource.cpp index 4cd7813bd..dbc964e80 100644 --- a/plugins/input/python/python_datasource.cpp +++ b/plugins/input/python/python_datasource.cpp @@ -29,7 +29,7 @@ python_datasource::python_datasource(parameters const& params) { if((kv.first != "type") && (kv.first != "factory")) { - kwargs_.insert(std::make_pair(kv.first, *params.get(kv.first))); + kwargs_.emplace(kv.first, *params.get(kv.first)); } } diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index c0f5978f0..3a908ef8f 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -525,9 +525,8 @@ cairo_face_ptr cairo_face_manager::get_face(face_ptr face) else { entry = std::make_shared(font_engine_, face); - cache_.insert(std::make_pair(face, entry)); + cache_.emplace(face, entry); } - return entry; } diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index 3c6b0c4e4..08af17caa 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -224,7 +224,7 @@ bool datasource_cache::register_datasource(std::string const& filename) } else { - if (plugins_.insert(std::make_pair(plugin->name(),plugin)).second) + if (plugins_.emplace(plugin->name(),plugin).second) { MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Registered=" diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index da78888f0..87209f569 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -177,7 +177,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar // skip fonts with leading . in the name if (!boost::algorithm::starts_with(name,".")) { - name2file_.insert(std::make_pair(name, std::make_pair(i,file_name))); + name2file_.emplace(name,std::make_pair(i,file_name)); success = true; } } @@ -332,7 +332,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name) std::fseek(file.get(), 0, SEEK_SET); std::unique_ptr buffer(new char[file_size]); std::fread(buffer.get(), file_size, 1, file.get()); - auto result = memory_fonts_.insert(std::make_pair(itr->second.second, std::make_pair(std::move(buffer),file_size))); + auto result = memory_fonts_.emplace(itr->second.second, std::make_pair(std::move(buffer),file_size)); FT_Error error = FT_New_Memory_Face (library_, reinterpret_cast(result.first->second.first.get()), static_cast(result.first->second.second), @@ -377,7 +377,7 @@ face_ptr face_manager::get_face(std::string const& name) face_ptr face = engine_.create_face(name); if (face) { - face_ptr_cache_.insert(make_pair(name,face)); + face_ptr_cache_.emplace(name,face); } return face; } diff --git a/src/grid/grid.cpp b/src/grid/grid.cpp index 96ead5719..208fe663e 100644 --- a/src/grid/grid.cpp +++ b/src/grid/grid.cpp @@ -127,7 +127,7 @@ void hit_grid::add_feature(mapnik::feature_impl const& feature) { // TODO - consider shortcutting f_keys if feature_id == lookup_value // create a mapping between the pixel id and the feature key - f_keys_.insert(std::make_pair(feature_id,lookup_value)); + f_keys_.emplace(feature_id,lookup_value); // if extra fields have been supplied, push them into grid memory if (!names_.empty()) { @@ -136,7 +136,7 @@ void hit_grid::add_feature(mapnik::feature_impl const& feature) // https://github.com/mapnik/mapnik/issues/1198 mapnik::feature_ptr feature2(mapnik::feature_factory::create(ctx_,feature_id)); feature2->set_data(feature.get_data()); - features_.insert(std::make_pair(lookup_value,feature2)); + features_.emplace(lookup_value,feature2); } } else diff --git a/src/load_map.cpp b/src/load_map.cpp index aa03500b8..5ae2c2349 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -501,7 +501,7 @@ void map_parser::parse_fontset(Map & map, xml_node const& node) // XXX Hack because map object isn't accessible by text_symbolizer // when it's parsed - fontsets_.insert(std::make_pair(name, fontset)); + fontsets_.emplace(name, fontset); map.insert_fontset(name, std::move(fontset)); } catch (config_error const& ex) diff --git a/src/map.cpp b/src/map.cpp index d3163f49f..227544c76 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -201,7 +201,7 @@ Map::const_style_iterator Map::end_styles() const bool Map::insert_style(std::string const& name,feature_type_style style) { - return styles_.insert(make_pair(name, std::move(style))).second; + return styles_.emplace(name, std::move(style)).second; } void Map::remove_style(std::string const& name) @@ -224,7 +224,7 @@ bool Map::insert_fontset(std::string const& name, font_set fontset) { throw mapnik::config_error("Fontset name must match the name used to reference it on the map"); } - return fontsets_.insert(make_pair(name, std::move(fontset))).second; + return fontsets_.emplace(name, std::move(fontset)).second; } boost::optional Map::find_fontset(std::string const& name) const diff --git a/src/mapped_memory_cache.cpp b/src/mapped_memory_cache.cpp index 96bce78ad..36b2aa8d0 100644 --- a/src/mapped_memory_cache.cpp +++ b/src/mapped_memory_cache.cpp @@ -48,7 +48,7 @@ bool mapped_memory_cache::insert(std::string const& uri, mapped_region_ptr mem) #ifdef MAPNIK_THREADSAFE mapnik::scoped_lock lock(mutex_); #endif - return cache_.insert(std::make_pair(uri,mem)).second; + return cache_.emplace(uri,mem).second; } boost::optional mapped_memory_cache::find(std::string const& uri, bool update_cache) @@ -71,12 +71,10 @@ boost::optional mapped_memory_cache::find(std::string const& { boost::interprocess::file_mapping mapping(uri.c_str(),boost::interprocess::read_only); mapped_region_ptr region(std::make_shared(mapping,boost::interprocess::read_only)); - result.reset(region); - if (update_cache) { - cache_.insert(std::make_pair(uri,*result)); + cache_.emplace(uri,*result); } return result; } diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 6620efcc8..f64ae152e 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -61,7 +61,7 @@ marker_cache::marker_cache() boost::optional bitmap_data = boost::optional(std::make_shared(4,4)); (*bitmap_data)->set(0xff000000); marker_ptr mark = std::make_shared(bitmap_data); - marker_cache_.insert(std::make_pair("image://square",mark)); + marker_cache_.emplace("image://square",mark); } marker_cache::~marker_cache() {} @@ -103,7 +103,7 @@ bool marker_cache::insert_svg(std::string const& name, std::string const& svg_st iterator_type itr = svg_cache_.find(key); if (itr == svg_cache_.end()) { - return svg_cache_.insert(std::make_pair(key,svg_string)).second; + return svg_cache_.emplace(key,svg_string).second; } return false; } @@ -113,7 +113,7 @@ bool marker_cache::insert_marker(std::string const& uri, marker_ptr path) #ifdef MAPNIK_THREADSAFE mapnik::scoped_lock lock(mutex_); #endif - return marker_cache_.insert(std::make_pair(uri,path)).second; + return marker_cache_.emplace(uri,path).second; } boost::optional marker_cache::find(std::string const& uri, @@ -165,7 +165,7 @@ boost::optional marker_cache::find(std::string const& uri, result.reset(mark); if (update_cache) { - marker_cache_.insert(std::make_pair(uri,*result)); + marker_cache_.emplace(uri,*result); } } // otherwise assume file-based @@ -194,7 +194,7 @@ boost::optional marker_cache::find(std::string const& uri, result.reset(mark); if (update_cache) { - marker_cache_.insert(std::make_pair(uri,*result)); + marker_cache_.emplace(uri,*result); } } else @@ -218,7 +218,7 @@ boost::optional marker_cache::find(std::string const& uri, result.reset(mark); if (update_cache) { - marker_cache_.insert(std::make_pair(uri,*result)); + marker_cache_.emplace(uri,*result); } } else diff --git a/src/text/face.cpp b/src/text/face.cpp index 3f57bc89a..20d487317 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -94,7 +94,7 @@ bool font_face::glyph_dimensions(glyph_info & glyph) const glyph.unscaled_ymax = glyph_bbox.yMax; glyph.unscaled_advance = face_->glyph->advance.x; glyph.unscaled_line_height = face_->size->metrics.height; - glyph_info_cache_.insert(std::make_pair(glyph.glyph_index, glyph)); + glyph_info_cache_.emplace(glyph.glyph_index, glyph); return true; } diff --git a/src/text/formatting/registry.cpp b/src/text/formatting/registry.cpp index fe653e265..86ffb25fd 100644 --- a/src/text/formatting/registry.cpp +++ b/src/text/formatting/registry.cpp @@ -44,7 +44,7 @@ void registry::register_name(std::string const& name, from_xml_function_ptr ptr, if (overwrite) { map_[name] = ptr; } else { - map_.insert(make_pair(name, ptr)); + map_.emplace(name, ptr); } } diff --git a/src/text/placements/registry.cpp b/src/text/placements/registry.cpp index adbd662d7..95ebd1e88 100644 --- a/src/text/placements/registry.cpp +++ b/src/text/placements/registry.cpp @@ -42,7 +42,7 @@ void registry::register_name(std::string name, from_xml_function_ptr ptr, bool o if (overwrite) { map_[name] = ptr; } else { - map_.insert(make_pair(name, ptr)); + map_.emplace(name, ptr); } } diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 1c7ee10b9..f2f79bb85 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -226,7 +226,7 @@ xml_node &xml_node::add_child(std::string && name, unsigned line, bool is_text) void xml_node::add_attribute(const char * name, const char * value) { - attributes_.insert(std::make_pair(name,xml_attribute(value))); + attributes_.emplace(name,xml_attribute(value)); } xml_node::attribute_map const& xml_node::get_attributes() const From 471eaed9df7c10875dab71bbc9a8b746dfc04697 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 7 Aug 2014 17:42:24 -0700 Subject: [PATCH 02/25] initialize is_geographic --- src/projection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/projection.cpp b/src/projection.cpp index 9c6e338cf..06dc5e4c8 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -49,6 +49,7 @@ namespace mapnik { projection::projection(std::string const& params, bool defer_proj_init) : params_(params), defer_proj_init_(defer_proj_init), + is_geographic_(false), proj_(nullptr), proj_ctx_(nullptr) { From 5a35422ee56aa8c01e2920cd0a5ea62057645cd3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 08:17:41 -0700 Subject: [PATCH 03/25] build: remove -finline-functions which is no longer supported by clang-3.5 --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 42015153c..6e594967b 100644 --- a/SConstruct +++ b/SConstruct @@ -1785,7 +1785,7 @@ if not preconfigured: else: # TODO - add back -fvisibility-inlines-hidden # https://github.com/mapnik/mapnik/issues/1863 - env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION'])) + env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION'])) if env['DEBUG_UNDEFINED']: env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv') From e33e0150ad863d3e104a51b5d00846efb11ab209 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 12:34:41 -0700 Subject: [PATCH 04/25] 2x faster compile of value_types.hpp - start working on #2346 --- include/mapnik/value_types.hpp | 44 ++++++++++++---------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index 0d08d1567..8e810199e 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -26,11 +26,8 @@ // icu #include // for UnicodeString -// boost -#include - // stl -#include // for ostream +#include namespace mapnik { @@ -47,82 +44,71 @@ using value_bool = bool; struct value_null { - bool operator==(value_null const& other) const + bool operator==(value_null const&) const { - boost::ignore_unused_variable_warning(other); return true; } template - bool operator==(T const& other) const + bool operator==(T const&) const { - boost::ignore_unused_variable_warning(other); return false; } - bool operator!=(value_null const& other) const + bool operator!=(value_null const&) const { - boost::ignore_unused_variable_warning(other); return false; } template - bool operator!=(T const& other) const + bool operator!=(T const&) const { - boost::ignore_unused_variable_warning(other); return true; } template - value_null operator+ (T const& other) const + value_null operator+ (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator- (T const& other) const + value_null operator- (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator* (T const& other) const + value_null operator* (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator/ (T const& other) const + value_null operator/ (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator% (T const& other) const + value_null operator% (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } }; -inline std::size_t hash_value(const value_null& val) +inline std::size_t hash_value(value_null const&) { - boost::ignore_unused_variable_warning(val); return 0; } -inline std::ostream& operator<< (std::ostream & out,value_null const& v) -{ - boost::ignore_unused_variable_warning(v); +template +inline std::basic_ostream& operator<<(std::basic_ostream& out, value_null const& v) { return out; } -inline std::istream& operator>> ( std::istream & s, value_null & null ) + +inline std::istream& operator>> ( std::istream & s, value_null & ) { - boost::ignore_unused_variable_warning(null); return s; } From 1727fae6e7d3bba491d4b71e7fa37adddaeb15b8 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 13:15:57 -0700 Subject: [PATCH 05/25] remove boost concept_check usage - refs #2346 --- include/mapnik/image_filter.hpp | 7 +-- include/mapnik/symbolizer.hpp | 11 +--- include/mapnik/symbolizer_utils.hpp | 3 +- include/mapnik/text/placements/dummy.hpp | 2 - include/mapnik/transform_processor.hpp | 6 +- include/mapnik/value.hpp | 75 ++++++++---------------- src/parse_path.cpp | 3 +- src/save_map.cpp | 14 ++--- src/transform_expression.cpp | 3 +- 9 files changed, 38 insertions(+), 86 deletions(-) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 35fa4d257..50ccb0772 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -31,8 +31,6 @@ // boost #include #include -#include - // agg #include "agg_basics.h" @@ -176,11 +174,8 @@ void process_channel_impl (Src const& src, Dst & dst, Conv const& k) } template -void process_channel (Src const& src, Dst & dst, Conv const& k) +void process_channel (Src const&, Dst &, Conv const&) { - boost::ignore_unused_variable_warning(src); - boost::ignore_unused_variable_warning(dst); - boost::ignore_unused_variable_warning(k); } template diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index a84d7c7be..ad3a0c9bb 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -51,7 +51,6 @@ #include // boost #include -#include namespace agg { struct trans_affine; } @@ -163,10 +162,8 @@ struct evaluate_path_wrapper { using result_type = T; template - result_type operator() (T1 const& expr, T2 const& feature) const + result_type operator() (T1 const&, T2 const&) const { - boost::ignore_unused_variable_warning(expr); - boost::ignore_unused_variable_warning(feature); return result_type(); } @@ -291,9 +288,8 @@ template struct enumeration_result { using result_type = T; - static result_type convert(enumeration_wrapper const& e) + static result_type convert(enumeration_wrapper const&) { - boost::ignore_unused_variable_warning(e); return result_type();// FAIL } }; @@ -425,9 +421,8 @@ struct extract_value : public boost::static_visitor } template - auto operator() (T1 const& val) const -> result_type + auto operator() (T1 const&) const -> result_type { - boost::ignore_unused_variable_warning(val); return result_type(); } diff --git a/include/mapnik/symbolizer_utils.hpp b/include/mapnik/symbolizer_utils.hpp index d92375da2..ee788a85e 100644 --- a/include/mapnik/symbolizer_utils.hpp +++ b/include/mapnik/symbolizer_utils.hpp @@ -127,9 +127,8 @@ struct symbolizer_name_impl : public boost::static_visitor { public: template - std::string operator () (Symbolizer const& sym) const + std::string operator () (Symbolizer const&) const { - boost::ignore_unused_variable_warning(sym); return symbolizer_traits::name(); } }; diff --git a/include/mapnik/text/placements/dummy.hpp b/include/mapnik/text/placements/dummy.hpp index 6d54f3f29..d3ed4aac3 100644 --- a/include/mapnik/text/placements/dummy.hpp +++ b/include/mapnik/text/placements/dummy.hpp @@ -25,8 +25,6 @@ // mapnik #include #include -// boost -#include namespace mapnik { diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index 343531cd9..063ac1f6e 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -57,9 +57,8 @@ struct transform_processor attribute_collector(Container& names) : collect_(names) {} - void operator() (identity_node const& node) const + void operator() (identity_node const&) const { - boost::ignore_unused_variable_warning(node); } void operator() (matrix_node const& node) const @@ -113,9 +112,8 @@ struct transform_processor vars_(v), scale_factor_(scale_factor) {} - void operator() (identity_node const& node) + void operator() (identity_node const&) { - boost::ignore_unused_variable_warning(node); } void operator() (matrix_node const& node) diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 31cfca2a6..5c96e257f 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -31,7 +31,6 @@ // boost #include -#include #include #include "hash_variant.hpp" @@ -179,9 +178,8 @@ struct not_equals // back compatibility shim to equate empty string with null for != test // https://github.com/mapnik/mapnik/issues/1859 // TODO - consider removing entire specialization at Mapnik 3.x - bool operator() (value_null lhs, value_unicode_string const& rhs) const + bool operator() (value_null, value_unicode_string const& rhs) const { - boost::ignore_unused_variable_warning(lhs); if (rhs.isEmpty()) return false; return true; } @@ -354,15 +352,13 @@ struct add : public boost::static_visitor return lhs + rhs; } - value_type operator() (value_unicode_string const& lhs, value_null rhs) const + value_type operator() (value_unicode_string const& lhs, value_null) const { - boost::ignore_unused_variable_warning(rhs); return lhs; } - value_type operator() (value_null lhs, value_unicode_string const& rhs) const + value_type operator() (value_null, value_unicode_string const& rhs) const { - boost::ignore_unused_variable_warning(lhs); return rhs; } @@ -418,11 +414,9 @@ struct sub : public boost::static_visitor return lhs - rhs ; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } @@ -457,11 +451,9 @@ struct mult : public boost::static_visitor return lhs * rhs; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } @@ -475,10 +467,8 @@ struct mult : public boost::static_visitor return lhs * rhs; } - value_type operator() (value_bool lhs, value_bool rhs) const + value_type operator() (value_bool, value_bool) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_integer(0); } }; @@ -500,18 +490,14 @@ struct div: public boost::static_visitor return lhs / rhs; } - value_type operator() (value_bool lhs, value_bool rhs) const + value_type operator() (value_bool, value_bool) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return false; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } @@ -544,19 +530,15 @@ struct mod: public boost::static_visitor return lhs % rhs; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } - value_type operator() (value_bool lhs, - value_bool rhs) const + value_type operator() (value_bool, + value_bool) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return false; } @@ -597,9 +579,8 @@ struct negate : public boost::static_visitor return val ? value_integer(-1) : value_integer(0); } - value_type operator() (value_unicode_string const& ustr) const + value_type operator() (value_unicode_string const&) const { - boost::ignore_unused_variable_warning(ustr); return value_type(); } }; @@ -621,9 +602,8 @@ struct convert : public boost::static_visitor return !ustr.isEmpty(); } - value_bool operator() (value_null const& val) const + value_bool operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return false; } @@ -667,9 +647,8 @@ struct convert : public boost::static_visitor return operator()(utf8); } - value_double operator() (value_null const& val) const + value_double operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return 0.0; } }; @@ -707,9 +686,8 @@ struct convert : public boost::static_visitor return operator()(utf8); } - value_integer operator() (value_null const& val) const + value_integer operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return value_integer(0); } }; @@ -740,9 +718,8 @@ struct convert : public boost::static_visitor return str; } - std::string operator() (value_null const& val) const + std::string operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return ""; } }; @@ -771,9 +748,8 @@ struct to_unicode : public boost::static_visitor return value_unicode_string(str.c_str()); } - value_unicode_string operator() (value_null const& val) const + value_unicode_string operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return value_unicode_string(""); } }; @@ -806,9 +782,8 @@ struct to_expression_string : public boost::static_visitor return val ? "true":"false"; } - std::string operator() (value_null const& val) const + std::string operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return "null"; } }; @@ -996,16 +971,14 @@ struct is_null : public boost::static_visitor return val.is_null(); } - bool operator() (value_null const& val) const + bool operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return true; } template - bool operator() (T const& val) const + bool operator() (T const&) const { - boost::ignore_unused_variable_warning(val); return false; } diff --git a/src/parse_path.cpp b/src/parse_path.cpp index f12889bb5..d5f25da4e 100644 --- a/src/parse_path.cpp +++ b/src/parse_path.cpp @@ -102,9 +102,8 @@ namespace path_processor_detail { collect_ (std::set & cont) : cont_(cont) {} - void operator() (std::string const& token) const + void operator() (std::string const&) const { - boost::ignore_unused_variable_warning(token); } void operator() (attribute const& attr) const diff --git a/src/save_map.cpp b/src/save_map.cpp index 356b09275..fa2df5a2e 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -51,7 +51,7 @@ #include #include #include -#include + // stl #include @@ -488,27 +488,23 @@ public: serialize_type( boost::property_tree::ptree & node): node_(node) {} - void operator () ( mapnik::value_integer val ) const + void operator () ( mapnik::value_integer ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "int" ); } - void operator () ( mapnik::value_double val ) const + void operator () ( mapnik::value_double ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "float" ); } - void operator () ( std::string const& val ) const + void operator () ( std::string const& ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "string" ); } - void operator () ( mapnik::value_null val ) const + void operator () ( mapnik::value_null ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "string" ); } diff --git a/src/transform_expression.cpp b/src/transform_expression.cpp index f235255d4..69f831296 100644 --- a/src/transform_expression.cpp +++ b/src/transform_expression.cpp @@ -38,9 +38,8 @@ struct transform_node_to_expression_string transform_node_to_expression_string(std::ostringstream& os) : os_(os) {} - void operator() (identity_node const& node) const + void operator() (identity_node const&) const { - boost::ignore_unused_variable_warning(node); } void operator() (matrix_node const& node) From 578da317020e267021776568f19e850cdd111ce3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 14:16:49 -0700 Subject: [PATCH 06/25] use extern template to fix osx -flto bug - closes #2339 --- include/mapnik/datasource_cache.hpp | 3 +++ src/datasource_cache.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/include/mapnik/datasource_cache.hpp b/include/mapnik/datasource_cache.hpp index 556097a16..6646888bd 100644 --- a/include/mapnik/datasource_cache.hpp +++ b/include/mapnik/datasource_cache.hpp @@ -58,6 +58,9 @@ private: bool registered_; std::set plugin_directories_; }; + +extern template class singleton; + } #endif // MAPNIK_DATASOURCE_CACHE_HPP diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index 08af17caa..152107ba1 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -42,6 +42,8 @@ namespace mapnik { +template class singleton; + extern datasource_ptr create_static_datasource(parameters const& params); extern std::vector get_static_datasource_names(); From fc70ab6c0a5d367cce21f811c35e908f31635e7d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 15:01:35 -0700 Subject: [PATCH 07/25] test a crazy matrix --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6bb81ad0e..440b25f43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,11 @@ compiler: - clang # - gcc +env: + matrix: + - DEBUG=True ENABLE_LOG=True DEFAULT_LOG_SEVERITY=debug XMLPARSER="libxml2" DEMO=False BENCHMARK=False CUSTOM_CXXFLAGS="" CUSTOM_LDFLAGS="" + - DEBUG=False ENABLE_LOG=False DEFAULT_LOG_SEVERITY=none XMLPARSER="ptree" DEMO=False BENCHMARK=False CUSTOM_CXXFLAGS="-flto" CUSTOM_LDFLAGS="-flto" + addons: postgresql: "9.3" @@ -37,7 +42,7 @@ before_install: install: - export RANLIB=/bin/true - - ./configure CXX="${CXX}" CC="${CC}" CUSTOM_CXXFLAGS="-flto" CUSTOM_LDFLAGS="-flto" DEMO=True BENCHMARK=True CPP_TESTS=True CAIRO=True FAST=True || cat config.log + - ./configure CXX="${CXX}" CC="${CC}" CUSTOM_CXXFLAGS="${CUSTOM_CXXFLAGS}" CUSTOM_LDFLAGS="${CUSTOM_LDFLAGS}" XML_PARSER=${XML_PARSER} ENABLE_LOG=${ENABLE_LOG} DEBUG=${DEBUG} DEMO=${DEMO} BENCHMARK=${BENCHMARK} CPP_TESTS=True CAIRO=True FAST=True || cat config.log # workaround ar bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13256 - echo 'ar "$@" --plugin /usr/lib/LLVMgold.so' > ar-lto && chmod +x ./ar-lto && export AR=$(pwd)/ar-lto - if [[ "${CXX}" == 'g++-4.8' ]]; then JOBS=2 make; else JOBS=6 make; fi; From 4cb7b56f6676669a2951ffa6f03bd4a345a1b647 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 15:01:48 -0700 Subject: [PATCH 08/25] remove uneeded logging --- src/symbolizer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/symbolizer.cpp b/src/symbolizer.cpp index fdceb66f7..7107fe706 100644 --- a/src/symbolizer.cpp +++ b/src/symbolizer.cpp @@ -36,10 +36,6 @@ void evaluate_transform(agg::trans_affine& tr, { if (trans_expr) { -#ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(transform) << "transform: evaluate " - << transform_processor_type::to_string(*trans_expr); -#endif transform_processor_type::evaluate(tr, feature, vars, *trans_expr, scale_factor); } } From 95430a3bebf6d61d8697b9025878cde9c4af4684 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 15:41:18 -0700 Subject: [PATCH 09/25] remove uneeded debug statement --- include/mapnik/offset_converter.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/mapnik/offset_converter.hpp b/include/mapnik/offset_converter.hpp index 685c25d80..e7316d0f9 100644 --- a/include/mapnik/offset_converter.hpp +++ b/include/mapnik/offset_converter.hpp @@ -387,10 +387,6 @@ private: void push_vertex(vertex2d const& v) { - #ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(ctrans) << "offset_converter: " << v; - #endif - vertices_.push_back(v); } From 1c9afc9a866b8dc1939a95f927ba3b70ba1859e0 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:37:25 -0700 Subject: [PATCH 10/25] boolean_type cleanup/code re-use --- include/mapnik/boolean.hpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/include/mapnik/boolean.hpp b/include/mapnik/boolean.hpp index ea267d3cb..bbee2b513 100644 --- a/include/mapnik/boolean.hpp +++ b/include/mapnik/boolean.hpp @@ -22,17 +22,22 @@ #ifndef MAPNIK_BOOLEAN_HPP #define MAPNIK_BOOLEAN_HPP +// mapnik +#include +#include + // std -#include +#include #include #include -#include +//#include +//#include namespace mapnik { -// Helper for class bool -class boolean_type { +class MAPNIK_DECL boolean_type +{ public: boolean_type() : b_(false) {} @@ -63,25 +68,12 @@ template std::basic_istream & operator >> ( std::basic_istream & s, boolean_type & b ) { - std::string word; - s >> word; - std::transform(word.begin(), word.end(), word.begin(), ::tolower); if ( s ) { - if ( word == "true" || word == "yes" || word == "on" || - word == "1") - { - b = true; - } - else if ( word == "false" || word == "no" || word == "off" || - word == "0") - { - b = false; - } - else - { - s.setstate( std::ios::failbit ); - } + std::string word; + s >> word; + bool result; + if (util::string2bool(word,result)) b = result; } return s; } From d61efc0b5a5f9824d58cb580f1adb967b17f514e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:40:05 -0700 Subject: [PATCH 11/25] -fvisibility=hidden fixes on osx with -flto --- include/mapnik/enumeration.hpp | 6 +++--- include/mapnik/group/group_rule.hpp | 2 +- include/mapnik/image_data.hpp | 3 ++- include/mapnik/symbolizer.hpp | 18 +++++++++--------- include/mapnik/value_types.hpp | 5 ++++- plugins/input/gdal/gdal_datasource.cpp | 1 + 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index f60a16f45..c0ca1c79e 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -333,8 +333,8 @@ operator>>(std::istream & is, mapnik::enumeration & e) */ #define IMPLEMENT_ENUM( name, strings ) \ - template <> const char ** name ::our_strings_ = strings; \ - template <> std::string name ::our_name_ = #name; \ - template <> bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__)); + template <> MAPNIK_DECL const char ** name ::our_strings_ = strings; \ + template <> MAPNIK_DECL std::string name ::our_name_ = #name; \ + template <> MAPNIK_DECL bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__)); #endif // MAPNIK_ENUMERATION_HPP diff --git a/include/mapnik/group/group_rule.hpp b/include/mapnik/group/group_rule.hpp index da83a6707..267093b78 100644 --- a/include/mapnik/group/group_rule.hpp +++ b/include/mapnik/group/group_rule.hpp @@ -36,7 +36,7 @@ namespace mapnik * be rendered atomically when the filter attached to * this rule is matched. */ -struct group_rule +struct MAPNIK_DECL group_rule { using symbolizers = std::vector; diff --git a/include/mapnik/image_data.hpp b/include/mapnik/image_data.hpp index f576e09d0..599387e04 100644 --- a/include/mapnik/image_data.hpp +++ b/include/mapnik/image_data.hpp @@ -25,6 +25,7 @@ // mapnik #include +#include // stl #include @@ -34,7 +35,7 @@ namespace mapnik { template -class ImageData +class MAPNIK_DECL ImageData { public: using pixel_type = T; diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index ad3a0c9bb..92df57b47 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -90,7 +90,7 @@ using dash_array = std::vector >; class text_placements; using text_placements_ptr = std::shared_ptr; -struct MAPNIK_DECL symbolizer_base +struct MAPNIK_DECL symbolizer_base { using value_type = boost::variant }; template -void put(symbolizer_base & sym, keys key, T const& val) +MAPNIK_DECL void put(symbolizer_base & sym, keys key, T const& val) { constexpr bool enum_ = std::is_enum::value; detail::put_impl::apply(sym, key, val); } template -bool has_key(symbolizer_base const& sym, keys key) +MAPNIK_DECL bool has_key(symbolizer_base const& sym, keys key) { return (sym.properties.count(key) == 1); } template -T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars, T const& _default_value = T()) +MAPNIK_DECL T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars, T const& _default_value = T()) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -478,7 +478,7 @@ T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, } template -boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars) +MAPNIK_DECL boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -490,7 +490,7 @@ boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::fe } template -T get(symbolizer_base const& sym, keys key, T const& _default_value = T()) +MAPNIK_DECL T get(symbolizer_base const& sym, keys key, T const& _default_value = T()) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -502,7 +502,7 @@ T get(symbolizer_base const& sym, keys key, T const& _default_value = T()) } template -boost::optional get_optional(symbolizer_base const& sym, keys key) +MAPNIK_DECL boost::optional get_optional(symbolizer_base const& sym, keys key) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -520,8 +520,8 @@ constexpr auto to_integral(Enum e) -> typename std::underlying_type::type } using property_meta_type = std::tuple, property_types>; -property_meta_type const& get_meta(mapnik::keys key); -mapnik::keys get_key(std::string const& name); +MAPNIK_DECL property_meta_type const& get_meta(mapnik::keys key); +MAPNIK_DECL mapnik::keys get_key(std::string const& name); // concrete symbolizer types struct MAPNIK_DECL point_symbolizer : public symbolizer_base {}; diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index 8e810199e..fb6e2d8c7 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -23,6 +23,9 @@ #ifndef MAPNIK_VALUE_TYPES_HPP #define MAPNIK_VALUE_TYPES_HPP +// mapnik +#include + // icu #include // for UnicodeString @@ -42,7 +45,7 @@ using value_double = double; using value_unicode_string = U_NAMESPACE_QUALIFIER UnicodeString; using value_bool = bool; -struct value_null +struct MAPNIK_DECL value_null { bool operator==(value_null const&) const { diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index 6da44d0cd..ed714019c 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include From 52b1da225b0a0edc816bcdad6d844129321f2ef5 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:41:34 -0700 Subject: [PATCH 12/25] less verbose ifdefs --- src/image_util.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/image_util.cpp b/src/image_util.cpp index 6f3536e81..79f74b2bf 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -58,17 +58,16 @@ extern "C" #include #ifdef CAIRO_HAS_PDF_SURFACE #include -#endif // CAIRO_HAS_PDF_SURFACE +#endif #ifdef CAIRO_HAS_PS_SURFACE #include -#endif // CAIRO_HAS_PS_SURFACE +#endif #ifdef CAIRO_HAS_SVG_SURFACE #include -#endif // CAIRO_HAS_SVG_SURFACE +#endif #endif // boost - #include // stl From 1c0b1884c3fcf72efbb3d565a2a4a66f30fdb26b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:44:08 -0700 Subject: [PATCH 13/25] use extern template to solve -fvisibility=hidden issues on osx --- include/mapnik/image_util.hpp | 57 ++++++++++++++--------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index c9bfe1fa7..fcd7dbdf3 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -25,10 +25,8 @@ // mapnik #include - -#ifdef _MSC_VER -#include -#endif +#include +#include // boost #include @@ -37,6 +35,7 @@ // stl #include #include +#include namespace mapnik { @@ -132,44 +131,43 @@ void save_as_jpeg(std::string const& filename, T const& image); #endif -inline bool is_png (std::string const& filename) +inline bool is_png(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".png")); } -inline bool is_jpeg (std::string const& filename) +inline bool is_jpeg(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".jpg")) || boost::algorithm::iends_with(filename,std::string(".jpeg")); } -inline bool is_tiff (std::string const& filename) +inline bool is_tiff(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".tif")) || boost::algorithm::iends_with(filename,std::string(".tiff")); } -inline bool is_pdf (std::string const& filename) +inline bool is_pdf(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".pdf")); } -inline bool is_svg (std::string const& filename) +inline bool is_svg(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".svg")); } -inline bool is_ps (std::string const& filename) +inline bool is_ps(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".ps")); } -inline bool is_webp (std::string const& filename) +inline bool is_webp(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".webp")); } - inline boost::optional type_from_filename(std::string const& filename) { @@ -193,15 +191,6 @@ inline std::string guess_type( std::string const& filename ) return ""; } -template -double distance(T x0,T y0,T x1,T y1) -{ - double dx = x1-x0; - double dy = y1-y0; - return std::sqrt(dx * dx + dy * dy); -} - - // add 1-px border around image - useful for debugging alignment issues template void add_border(T & image) @@ -257,53 +246,53 @@ MAPNIK_DECL void save_to_stream(image_32 const& image, /////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&, std::string const&); -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&); -template MAPNIK_DECL std::string save_to_string(image_data_32 const&, +extern template MAPNIK_DECL std::string save_to_string(image_data_32 const&, std::string const&); -template MAPNIK_DECL std::string save_to_string(image_data_32 const&, +extern template MAPNIK_DECL std::string save_to_string(image_data_32 const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL std::string save_to_string > (image_view const&, +extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&); -template MAPNIK_DECL std::string save_to_string > (image_view const&, +extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&, rgba_palette const&); +#ifdef _MSC_VER template MAPNIK_DECL void save_to_stream( image_data_32 const& image, From bcc92c96935d2d82a060bbe52bbf2ec225b3a3c4 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 16:06:04 -0700 Subject: [PATCH 14/25] Travis: disable notifications + only run bench when built --- .travis.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 440b25f43..e60523602 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,10 +51,4 @@ before_script: - make test script: - - make bench - -notifications: - irc: - channels: - - "irc.freenode.org#mapnik" - use_notice: true + - if [[ ${BENCHMARK} ]]; then make bench; fi; From 8ff987af6de5e7f6d8023f8af3df83d3b8287252 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 21:58:08 -0700 Subject: [PATCH 15/25] iwyu --- bindings/python/python_to_value.hpp | 1 + include/mapnik/evaluate_global_attributes.hpp | 1 + include/mapnik/label_collision_detector.hpp | 3 +++ include/mapnik/util/conversions.hpp | 1 - include/mapnik/value.hpp | 5 ++++- include/mapnik/value_types.hpp | 7 ++++++- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/bindings/python/python_to_value.hpp b/bindings/python/python_to_value.hpp index fd2eb4da2..6d220b61f 100644 --- a/bindings/python/python_to_value.hpp +++ b/bindings/python/python_to_value.hpp @@ -27,6 +27,7 @@ // mapnik #include +#include #include diff --git a/include/mapnik/evaluate_global_attributes.hpp b/include/mapnik/evaluate_global_attributes.hpp index c2f6a75f2..9dedee2c4 100644 --- a/include/mapnik/evaluate_global_attributes.hpp +++ b/include/mapnik/evaluate_global_attributes.hpp @@ -30,6 +30,7 @@ #include #include #include +#include // boost #include diff --git a/include/mapnik/label_collision_detector.hpp b/include/mapnik/label_collision_detector.hpp index af5eef979..254704205 100644 --- a/include/mapnik/label_collision_detector.hpp +++ b/include/mapnik/label_collision_detector.hpp @@ -28,6 +28,9 @@ #include #include +// icu +#include + // stl #include diff --git a/include/mapnik/util/conversions.hpp b/include/mapnik/util/conversions.hpp index e9bd716a8..22cafea52 100644 --- a/include/mapnik/util/conversions.hpp +++ b/include/mapnik/util/conversions.hpp @@ -30,7 +30,6 @@ // stl #include #include -#include namespace mapnik { namespace util { diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 5c96e257f..5869e35eb 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include // icu #include @@ -118,7 +121,7 @@ struct equals } template - bool operator() (T const& /*lhs*/, U const& /*rhs*/) const + bool operator() (T const&, U const&) const { return false; } diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index fb6e2d8c7..01709781a 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -27,10 +27,15 @@ #include // icu -#include // for UnicodeString +#include // for U_NAMESPACE_QUALIFIER // stl #include +#include + +namespace U_ICU_NAMESPACE { + class UnicodeString; +} namespace mapnik { From 678907e027e34b2a35127d130c130f383e8ff0b4 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:57:01 -0700 Subject: [PATCH 16/25] silence webp -Wunused-function warning --- include/mapnik/webp_io.hpp | 3 +++ src/webp_reader.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/include/mapnik/webp_io.hpp b/include/mapnik/webp_io.hpp index f6e80767f..851bd53d6 100644 --- a/include/mapnik/webp_io.hpp +++ b/include/mapnik/webp_io.hpp @@ -30,7 +30,10 @@ // webp #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" +extern "C" +{ #include +} #pragma clang diagnostic pop // stl diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp index c4327c66c..bd618f222 100644 --- a/src/webp_reader.cpp +++ b/src/webp_reader.cpp @@ -25,11 +25,14 @@ #include #include +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" extern "C" { #include #include } +#pragma clang diagnostic pop // boost #include From b0392ff002ad9e43ad6b7939545ad36ad5292319 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 14:01:28 -0700 Subject: [PATCH 17/25] travis: fix benchmark run logic [skip ci] --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e60523602..96d7b2173 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,4 +51,4 @@ before_script: - make test script: - - if [[ ${BENCHMARK} ]]; then make bench; fi; + - if [[ ${BENCHMARK} != False ]]; then make bench; fi; From 378ab71a51293b8f754eea48d64d2407498fb140 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 14:23:23 -0700 Subject: [PATCH 18/25] more -fvisibility=hidden fixes for osx --- include/mapnik/agg_renderer.hpp | 3 +++ include/mapnik/datasource_cache.hpp | 2 +- include/mapnik/text/vertex_cache.hpp | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 4a8dd89e2..bade3b4c1 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -53,6 +53,7 @@ namespace mapnik { class marker; class proj_transform; struct rasterizer; + class image_32; } namespace mapnik { @@ -165,6 +166,8 @@ private: void setup(Map const& m); }; +extern template class MAPNIK_DECL agg_renderer; + } // namespace mapnik #endif // MAPNIK_AGG_RENDERER_HPP diff --git a/include/mapnik/datasource_cache.hpp b/include/mapnik/datasource_cache.hpp index 6646888bd..bd646abb8 100644 --- a/include/mapnik/datasource_cache.hpp +++ b/include/mapnik/datasource_cache.hpp @@ -59,7 +59,7 @@ private: std::set plugin_directories_; }; -extern template class singleton; +extern template class MAPNIK_DECL singleton; } diff --git a/include/mapnik/text/vertex_cache.hpp b/include/mapnik/text/vertex_cache.hpp index 552b6845d..6069d03e7 100644 --- a/include/mapnik/text/vertex_cache.hpp +++ b/include/mapnik/text/vertex_cache.hpp @@ -25,6 +25,7 @@ // mapnik #include #include +#include // agg #include "agg_basics.h" @@ -41,7 +42,7 @@ class vertex_cache; using vertex_cache_ptr = std::shared_ptr; // Caches all path points and their lengths. Allows easy moving in both directions. -class vertex_cache +class MAPNIK_DECL vertex_cache { struct segment { From 4c10d901457e66f65eeee88f73f484a6b58a8f1c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:02:34 -0700 Subject: [PATCH 19/25] declare segment y_order inline --- include/mapnik/segment.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/segment.hpp b/include/mapnik/segment.hpp index f5ea1605f..ef0582118 100644 --- a/include/mapnik/segment.hpp +++ b/include/mapnik/segment.hpp @@ -31,7 +31,7 @@ namespace mapnik using segment_t = std::tuple; -static bool y_order(segment_t const& first,segment_t const& second) +static inline bool y_order(segment_t const& first,segment_t const& second) { double miny0 = std::min(std::get<1>(first), std::get<3>(first)); double miny1 = std::min(std::get<1>(second), std::get<3>(second)); From 9a1423e66937588fed49b3170da609c297f03668 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:03:07 -0700 Subject: [PATCH 20/25] create cairo context raster than passing surface --- bindings/python/mapnik_python.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index 11abd698f..dffecb821 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -241,7 +241,7 @@ void render3(mapnik::Map const& map, { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map,surface,scale_factor,offset_x,offset_y); + mapnik::cairo_renderer ren(map,mapnik::create_context(surface),scale_factor,offset_x,offset_y); ren.apply(); } @@ -249,7 +249,7 @@ void render4(mapnik::Map const& map, PycairoSurface* py_surface) { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map,surface); + mapnik::cairo_renderer ren(map,mapnik::create_context(surface)); ren.apply(); } @@ -304,7 +304,7 @@ void render_with_detector4( { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map, surface, detector); + mapnik::cairo_renderer ren(map, mapnik::create_context(surface), detector); ren.apply(); } @@ -318,7 +318,7 @@ void render_with_detector5( { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map, surface, detector, scale_factor, offset_x, offset_y); + mapnik::cairo_renderer ren(map, mapnik::create_context(surface), detector, scale_factor, offset_x, offset_y); ren.apply(); } From 7cae3c34cad073d90e558ab72aee88e2fd86faa3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:04:20 -0700 Subject: [PATCH 21/25] iwyu in renderer_common --- .../renderer_common/process_building_symbolizer.hpp | 8 +++++++- .../renderer_common/process_group_symbolizer.hpp | 11 ++++++----- .../renderer_common/process_markers_symbolizer.hpp | 3 +++ .../renderer_common/process_point_symbolizer.hpp | 1 + .../renderer_common/process_raster_symbolizer.hpp | 6 +++++- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/mapnik/renderer_common/process_building_symbolizer.hpp b/include/mapnik/renderer_common/process_building_symbolizer.hpp index aeea04cb2..5785e7bda 100644 --- a/include/mapnik/renderer_common/process_building_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_building_symbolizer.hpp @@ -23,6 +23,12 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP +#include +#include +#include + +#include + namespace mapnik { template @@ -106,4 +112,4 @@ void render_building_symbolizer(mapnik::feature_impl &feature, } // namespace mapnik -#endif /* MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP */ +#endif // MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index abf13dbfc..db8c3de4a 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -23,28 +23,29 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP +// mapnik #include #include #include #include #include -#include #include #include -#include #include -#include #include #include -#include #include #include +#include +// agg #include namespace mapnik { class proj_transform; +struct glyph_info; +class text_symbolizer_helper; // General: @@ -345,4 +346,4 @@ void render_group_symbolizer(group_symbolizer const& sym, } // namespace mapnik -#endif /* MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP */ +#endif // MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp index 7500db447..68ffb07b5 100644 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_markers_symbolizer.hpp @@ -27,6 +27,9 @@ #include #include #include +#include + +// boost #include namespace mapnik { diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index e7cc3b5a7..6694bada8 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace mapnik { diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp index f575d2931..deddb74bc 100644 --- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp @@ -25,6 +25,10 @@ // mapnik #include +#include +#include +#include +#include // agg #include "agg_rendering_buffer.h" @@ -136,4 +140,4 @@ void render_raster_symbolizer(raster_symbolizer const &sym, } // namespace mapnik -#endif /* MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP */ +#endif // MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP From 9c7f8284bd78bdbb6194276bd56ce008255a5b4a Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:52:45 -0700 Subject: [PATCH 22/25] iwyu --- src/renderer_common/process_group_symbolizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index 14ac14899..8041507b7 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include +#include namespace mapnik { From c285cfa188a9f2231de48e5ff8637eafef1a9437 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:53:45 -0700 Subject: [PATCH 23/25] refactor cairo_renderer - splits process functions into new cpp files to reduce peak compile memory usage - drops cairo_renderer_base to match agg_renderer design - only cairo_ptr is accepted so cairo_surface_ptr must be converted into a context first - fixes -fvisibility=hidden --- include/mapnik/cairo/cairo_render_vector.hpp | 49 + include/mapnik/cairo/cairo_renderer.hpp | 112 +- .../process_point_symbolizer.hpp | 4 +- .../process_polygon_symbolizer.hpp | 2 + src/build.py | 14 +- src/cairo/cairo_context.cpp | 2 +- src/cairo/cairo_render_vector.cpp | 131 +++ src/cairo/cairo_renderer.cpp | 1045 +---------------- src/cairo/process_building_symbolizer.cpp | 84 ++ src/cairo/process_debug_symbolizer.cpp | 110 ++ src/cairo/process_group_symbolizer.cpp | 126 ++ src/cairo/process_line_pattern_symbolizer.cpp | 141 +++ src/cairo/process_line_symbolizer.cpp | 116 ++ src/cairo/process_markers_symbolizer.cpp | 224 ++++ src/cairo/process_point_symbolizer.cpp | 66 ++ .../process_polygon_pattern_symbolizer.cpp | 135 +++ src/cairo/process_polygon_symbolizer.cpp | 66 ++ src/cairo/process_raster_symbolizer.cpp | 59 + src/cairo/process_text_symbolizer.cpp | 107 ++ src/feature_style_processor.cpp | 1 - 20 files changed, 1549 insertions(+), 1045 deletions(-) create mode 100644 include/mapnik/cairo/cairo_render_vector.hpp create mode 100644 src/cairo/cairo_render_vector.cpp create mode 100644 src/cairo/process_building_symbolizer.cpp create mode 100644 src/cairo/process_debug_symbolizer.cpp create mode 100644 src/cairo/process_group_symbolizer.cpp create mode 100644 src/cairo/process_line_pattern_symbolizer.cpp create mode 100644 src/cairo/process_line_symbolizer.cpp create mode 100644 src/cairo/process_markers_symbolizer.cpp create mode 100644 src/cairo/process_point_symbolizer.cpp create mode 100644 src/cairo/process_polygon_pattern_symbolizer.cpp create mode 100644 src/cairo/process_polygon_symbolizer.cpp create mode 100644 src/cairo/process_raster_symbolizer.cpp create mode 100644 src/cairo/process_text_symbolizer.cpp diff --git a/include/mapnik/cairo/cairo_render_vector.hpp b/include/mapnik/cairo/cairo_render_vector.hpp new file mode 100644 index 000000000..3016fad35 --- /dev/null +++ b/include/mapnik/cairo/cairo_render_vector.hpp @@ -0,0 +1,49 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +#ifndef MAPNIK_CAIRO_RENDER_VECTOR_HPP +#define MAPNIK_CAIRO_RENDER_VECTOR_HPP + +// mapnik +#include + +namespace agg { struct trans_affine; } + +namespace mapnik { + +class cairo_context; +struct pixel_position; +template class box2d; +namespace svg { struct path_attributes; } + +void render_vector_marker(cairo_context & context, pixel_position const& pos, + svg::svg_path_adapter & svg_path, box2d const& bbox, + agg::pod_bvector const & attributes, + agg::trans_affine const& tr, double opacity, bool recenter); + +} + +#endif // MAPNIK_CAIRO_RENDER_VECTOR_HPP + +#endif \ No newline at end of file diff --git a/include/mapnik/cairo/cairo_renderer.hpp b/include/mapnik/cairo/cairo_renderer.hpp index 2b70b089d..0abfc7294 100644 --- a/include/mapnik/cairo/cairo_renderer.hpp +++ b/include/mapnik/cairo/cairo_renderer.hpp @@ -28,19 +28,13 @@ // mapnik #include #include -#include -#include -#include -#include -#include // for all symbolizers #include +#include // for all symbolizers #include -#include -#include // for CoordTransform #include -// cairo -#include +// stl +#include namespace agg { struct trans_affine; @@ -48,34 +42,57 @@ struct trans_affine; namespace mapnik { +class Map; +class feature_impl; +class feature_type_style; +class label_collision_detector4; +class layer; class marker; - -class MAPNIK_DECL cairo_renderer_base : private mapnik::noncopyable +class proj_transform; +class request; +struct pixel_position; +struct cairo_save_restore +{ + cairo_save_restore(cairo_context & context) + : context_(context) + { + context_.save(); + } + ~cairo_save_restore() + { + context_.restore(); + } + cairo_context & context_; +}; + +template +class MAPNIK_DECL cairo_renderer : public feature_style_processor >, + private mapnik::noncopyable { -protected: - cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer_base(Map const& m, - request const& req, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - std::shared_ptr detector, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); public: - ~cairo_renderer_base(); + using processor_impl_type = cairo_renderer; + cairo_renderer(Map const& m, + T const& obj, + double scale_factor=1.0, + unsigned offset_x=0, + unsigned offset_y=0); + cairo_renderer(Map const& m, + request const& req, + attributes const& vars, + T const& obj, + double scale_factor=1.0, + unsigned offset_x=0, + unsigned offset_y=0); + cairo_renderer(Map const& m, + T const& obj, + std::shared_ptr detector, + double scale_factor=1.0, + unsigned offset_x=0, + unsigned offset_y=0); + + ~cairo_renderer(); void start_map_processing(Map const& map); + void end_map_processing(Map const& map); void start_layer_processing(layer const& lay, box2d const& query_extent); void end_layer_processing(layer const& lay); void start_style_processing(feature_type_style const& st); @@ -155,34 +172,11 @@ protected: renderer_common common_; cairo_face_manager face_manager_; void setup(Map const& m); + }; -template -class MAPNIK_DECL cairo_renderer : public feature_style_processor >, - public cairo_renderer_base -{ -public: - using processor_impl_type = cairo_renderer_base; - cairo_renderer(Map const& m, - T const& obj, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer(Map const& m, - request const& req, - attributes const& vars, - T const& obj, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer(Map const& m, - T const& obj, - std::shared_ptr detector, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - void end_map_processing(Map const& map); -}; +extern template class MAPNIK_DECL cairo_renderer; + } #endif // MAPNIK_CAIRO_RENDERER_HPP diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index 6694bada8..a58a6a714 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,8 @@ #define MAPNIK_RENDERER_COMMON_PROCESS_POINT_SYMBOLIZER_HPP #include +#include +#include #include #include #include diff --git a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp index 42bbf12d6..901158d5b 100644 --- a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP +#include + namespace mapnik { template diff --git a/src/build.py b/src/build.py index aa273f8aa..cd360f997 100644 --- a/src/build.py +++ b/src/build.py @@ -272,8 +272,20 @@ if env['HAS_CAIRO']: lib_env.Append(CPPDEFINES = '-DHAVE_CAIRO') libmapnik_defines.append('-DHAVE_CAIRO') lib_env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS'])) - source.append('cairo/cairo_renderer.cpp') source.append('cairo/cairo_context.cpp') + source.append('cairo/cairo_renderer.cpp') + source.append('cairo/cairo_render_vector.cpp') + source.append('cairo/process_markers_symbolizer.cpp') + source.append('cairo/process_text_symbolizer.cpp') + source.append('cairo/process_group_symbolizer.cpp') + source.append('cairo/process_line_symbolizer.cpp') + source.append('cairo/process_line_pattern_symbolizer.cpp') + source.append('cairo/process_polygon_symbolizer.cpp') + source.append('cairo/process_polygon_pattern_symbolizer.cpp') + source.append('cairo/process_debug_symbolizer.cpp') + source.append('cairo/process_point_symbolizer.cpp') + source.append('cairo/process_raster_symbolizer.cpp') + source.append('cairo/process_building_symbolizer.cpp') for cpp in enabled_imaging_libraries: source.append(cpp) diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index 3a908ef8f..1c59a8303 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/cairo/cairo_render_vector.cpp b/src/cairo/cairo_render_vector.cpp new file mode 100644 index 000000000..31a24f33d --- /dev/null +++ b/src/cairo/cairo_render_vector.cpp @@ -0,0 +1,131 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include + +namespace mapnik +{ + +void render_vector_marker(cairo_context & context, pixel_position const& pos, + svg::svg_path_adapter & svg_path, box2d const& bbox, + agg::pod_bvector const & attributes, + agg::trans_affine const& tr, double opacity, bool recenter) +{ + using namespace mapnik::svg; + agg::trans_affine mtx = tr; + if (recenter) + { + coord c = bbox.center(); + mtx = agg::trans_affine_translation(-c.x,-c.y); + mtx *= tr; + mtx.translate(pos.x, pos.y); + } + + agg::trans_affine transform; + + for(unsigned i = 0; i < attributes.size(); ++i) + { + mapnik::svg::path_attributes const& attr = attributes[i]; + if (!attr.visibility_flag) + continue; + cairo_save_restore guard(context); + transform = attr.transform; + transform *= mtx; + + // TODO - this 'is_valid' check is not used in the AGG renderer and also + // appears to lead to bogus results with + // tests/data/good_maps/markers_symbolizer_lines_file.xml + //if (transform.is_valid() && !transform.is_identity()) + if (!transform.is_identity()) + { + double m[6]; + transform.store_to(m); + cairo_matrix_t matrix; + cairo_matrix_init(&matrix,m[0],m[1],m[2],m[3],m[4],m[5]); + context.transform(matrix); + } + + if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT) + { + context.add_agg_path(svg_path,attr.index); + if (attr.even_odd_flag) + { + context.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); + } + else + { + context.set_fill_rule(CAIRO_FILL_RULE_WINDING); + } + if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT) + { + cairo_gradient g(attr.fill_gradient,attr.fill_opacity * attr.opacity * opacity); + + context.set_gradient(g,bbox); + context.fill(); + } + else if(attr.fill_flag) + { + double fill_opacity = attr.fill_opacity * attr.opacity * opacity * attr.fill_color.opacity(); + context.set_color(attr.fill_color.r/255.0,attr.fill_color.g/255.0, + attr.fill_color.b/255.0, fill_opacity); + context.fill(); + } + } + + if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) + { + context.add_agg_path(svg_path,attr.index); + if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) + { + context.set_line_width(attr.stroke_width); + context.set_line_cap(line_cap_enum(attr.line_cap)); + context.set_line_join(line_join_enum(attr.line_join)); + context.set_miter_limit(attr.miter_limit); + cairo_gradient g(attr.stroke_gradient,attr.fill_opacity * attr.opacity * opacity); + context.set_gradient(g,bbox); + context.stroke(); + } + else if (attr.stroke_flag) + { + double stroke_opacity = attr.stroke_opacity * attr.opacity * opacity * attr.stroke_color.opacity(); + context.set_color(attr.stroke_color.r/255.0,attr.stroke_color.g/255.0, + attr.stroke_color.b/255.0, stroke_opacity); + context.set_line_width(attr.stroke_width); + context.set_line_cap(line_cap_enum(attr.line_cap)); + context.set_line_join(line_join_enum(attr.line_join)); + context.set_miter_limit(attr.miter_limit); + context.stroke(); + } + } + } +} + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index a357f11fc..62d6c959a 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,113 +23,56 @@ #if defined(HAVE_CAIRO) // mapnik -#include -#include #include #include -#include -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include // todo - only need some of this expensive header -#include #include -#include -#include -#include -#include #include -#include -#include -#include - -// mapnik symbolizer generics -#include -#include -#include -#include -#include -#include -// cairo -#include -#include -#include - -// boost -#include +#include +#include +#include +#include // agg -#include "agg_conv_clip_polyline.h" -#include "agg_conv_clip_polygon.h" -#include "agg_conv_smooth_poly1.h" -#include "agg_rendering_buffer.h" -#include "agg_pixfmt_rgba.h" -// markers -#include "agg_path_storage.h" -#include "agg_ellipse.h" +#include "agg/include/agg_trans_affine.h" // for trans_affine, etc // stl -#include #include namespace mapnik { -struct cairo_save_restore -{ - cairo_save_restore(cairo_context & context) - : context_(context) - { - context_.save(); - } - ~cairo_save_restore() - { - context_.restore(); - } - cairo_context & context_; -}; +class feature_type_style; -cairo_renderer_base::cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor, - unsigned offset_x, - unsigned offset_y) - : m_(m), +template +cairo_renderer::cairo_renderer(Map const& m, + T const& cairo, + double scale_factor, + unsigned offset_x, + unsigned offset_y) + : feature_style_processor(m, scale_factor), + m_(m), context_(cairo), - common_(m, vars, offset_x, offset_y, m.width(), m.height(), scale_factor), + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor), face_manager_(common_.shared_font_engine_) { setup(m); } -cairo_renderer_base::cairo_renderer_base(Map const& m, - request const& req, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor, - unsigned offset_x, - unsigned offset_y) - : m_(m), +template +cairo_renderer::cairo_renderer(Map const& m, + request const& req, + attributes const& vars, + T const& cairo, + double scale_factor, + unsigned offset_x, + unsigned offset_y) + : feature_style_processor(m, scale_factor), + m_(m), context_(cairo), common_(req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor), face_manager_(common_.shared_font_engine_) @@ -137,54 +80,27 @@ cairo_renderer_base::cairo_renderer_base(Map const& m, setup(m); } -cairo_renderer_base::cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - std::shared_ptr detector, - double scale_factor, - unsigned offset_x, - unsigned offset_y) - : m_(m), +template +cairo_renderer::cairo_renderer(Map const& m, + T const& cairo, + std::shared_ptr detector, + double scale_factor, + unsigned offset_x, + unsigned offset_y) + : feature_style_processor(m, scale_factor), + m_(m), context_(cairo), - common_(m, vars, offset_x, offset_y, m.width(), m.height(), scale_factor, detector), + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor, detector), face_manager_(common_.shared_font_engine_) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << m.scale(); + setup(m); } -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,cairo,attributes(),scale_factor,offset_x,offset_y) {} +template +cairo_renderer::~cairo_renderer() {} -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,create_context(surface),attributes(),scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, request const& req, attributes const& vars, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,req,cairo,vars,scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, request const& req, attributes const& vars, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,req,create_context(surface),attributes(),scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_ptr const& cairo, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,cairo,attributes(),detector,scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_surface_ptr const& surface, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,create_context(surface),attributes(),detector,scale_factor,offset_x,offset_y) {} - -cairo_renderer_base::~cairo_renderer_base() {} - -void cairo_renderer_base::setup(Map const& map) +template +void cairo_renderer::setup(Map const& map) { boost::optional bg = m_.background(); if (bg) @@ -221,36 +137,30 @@ void cairo_renderer_base::setup(Map const& map) } } } - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << map.scale(); + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Scale=" << map.scale(); } -void cairo_renderer_base::start_map_processing(Map const& map) +template +void cairo_renderer::start_map_processing(Map const& map) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Start map processing bbox=" << map.get_current_extent(); + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Start map processing bbox=" << map.get_current_extent(); box2d bounds = common_.t_.forward(common_.t_.extent()); context_.rectangle(bounds.minx(), bounds.miny(), bounds.maxx(), bounds.maxy()); context_.clip(); } -template <> -void cairo_renderer::end_map_processing(Map const& ) +template +void cairo_renderer::end_map_processing(Map const&) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: End map processing"; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: End map processing"; } -template <> -void cairo_renderer::end_map_processing(Map const& ) +template +void cairo_renderer::start_layer_processing(layer const& lay, box2d const& query_extent) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: End map processing"; - - context_.show_page(); -} - -void cairo_renderer_base::start_layer_processing(layer const& lay, box2d const& query_extent) -{ - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Start processing layer=" << lay.name() ; - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: -- datasource=" << lay.datasource().get(); - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: -- query_extent=" << query_extent; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Start processing layer=" << lay.name() ; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: -- datasource=" << lay.datasource().get(); + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: -- query_extent=" << query_extent; if (lay.clear_label_cache()) { @@ -259,263 +169,26 @@ void cairo_renderer_base::start_layer_processing(layer const& lay, box2d common_.query_extent_ = query_extent; } -void cairo_renderer_base::end_layer_processing(layer const&) +template +void cairo_renderer::end_layer_processing(layer const&) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: End layer processing"; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: End layer processing"; } -void cairo_renderer_base::start_style_processing(feature_type_style const& st) +template +void cairo_renderer::start_style_processing(feature_type_style const& st) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:start style processing"; } -void cairo_renderer_base::end_style_processing(feature_type_style const& st) +template +void cairo_renderer::end_style_processing(feature_type_style const& st) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:end style processing"; } -void cairo_renderer_base::process(polygon_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using conv_types = boost::mpl::vector; - using vertex_converter_type = vertex_converter, cairo_context, polygon_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, - conv_types, feature_impl>; - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - context_.set_operator(comp_op); - - render_polygon_symbolizer( - sym, feature, prj_trans, common_, common_.query_extent_, context_, - [&](color const &fill, double opacity) { - context_.set_color(fill, opacity); - // fill polygon - context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); - context_.fill(); - }); -} - -void cairo_renderer_base::process(building_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using path_type = coord_transform; - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - mapnik::color fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); - double opacity = get(sym, keys::fill_opacity, feature, common_.vars_, 1.0); - double height = get(sym, keys::height, feature, common_.vars_, 0.0); - - context_.set_operator(comp_op); - - render_building_symbolizer( - feature, height, - [&](geometry_type &faces) { - path_type faces_path(common_.t_, faces, prj_trans); - context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8 / 255.0, - fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); - context_.add_path(faces_path); - context_.fill(); - }, - [&](geometry_type &frame) { - path_type path(common_.t_, frame, prj_trans); - context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8/255.0, - fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); - context_.set_line_width(common_.scale_factor_); - context_.add_path(path); - context_.stroke(); - }, - [&](geometry_type &roof) { - path_type roof_path(common_.t_, roof, prj_trans); - context_.set_color(fill, opacity); - context_.add_path(roof_path); - context_.fill(); - }); -} - -void cairo_renderer_base::process(line_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using conv_types = boost::mpl::vector; - - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - bool clip = get(sym, keys::clip, feature, common_.vars_, false); - double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); - double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - - mapnik::color stroke = get(sym, keys::stroke, feature, common_.vars_, mapnik::color(0,0,0)); - double stroke_opacity = get(sym, keys::stroke_opacity, feature, common_.vars_, 1.0); - line_join_enum stroke_join = get(sym, keys::stroke_linejoin, feature, common_.vars_, MITER_JOIN); - line_cap_enum stroke_cap = get(sym, keys::stroke_linecap, feature, common_.vars_, BUTT_CAP); - auto dash = get_optional(sym, keys::stroke_dasharray, feature, common_.vars_); - double miterlimit = get(sym, keys::stroke_miterlimit, feature, common_.vars_, 4.0); - double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - context_.set_color(stroke, stroke_opacity); - context_.set_line_join(stroke_join); - context_.set_line_cap(stroke_cap); - context_.set_miter_limit(miterlimit); - context_.set_line_width(width * common_.scale_factor_); - if (dash) - { - context_.set_dash(*dash, common_.scale_factor_); - } - - agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - - box2d clipping_extent = common_.query_extent_; - if (clip) - { - double padding = (double)(common_.query_extent_.width()/common_.width_); - double half_stroke = width/2.0; - if (half_stroke > 1) - padding *= half_stroke; - if (std::fabs(offset) > 0) - padding *= std::fabs(offset) * 1.2; - padding *= common_.scale_factor_; - clipping_extent.pad(padding); - } - vertex_converter, cairo_context, line_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); - - if (clip) converter.set(); // optional clip (default: true) - converter.set(); // always transform - if (std::fabs(offset) > 0.0) converter.set(); // parallel offset - converter.set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - for (geometry_type & geom : feature.paths()) - { - if (geom.size() > 1) - { - converter.apply(geom); - } - } - // stroke - context_.set_fill_rule(CAIRO_FILL_RULE_WINDING); - context_.stroke(); -} - -void cairo_renderer_base::render_box(box2d const& b) -{ - cairo_save_restore guard(context_); - context_.move_to(b.minx(), b.miny()); - context_.line_to(b.minx(), b.maxy()); - context_.line_to(b.maxx(), b.maxy()); - context_.line_to(b.maxx(), b.miny()); - context_.close_path(); - context_.stroke(); -} - -void render_vector_marker(cairo_context & context, pixel_position const& pos, - svg::svg_path_adapter & svg_path, box2d const& bbox, - agg::pod_bvector const & attributes, - agg::trans_affine const& tr, double opacity, bool recenter) -{ - using namespace mapnik::svg; - agg::trans_affine mtx = tr; - if (recenter) - { - coord c = bbox.center(); - mtx = agg::trans_affine_translation(-c.x,-c.y); - mtx *= tr; - mtx.translate(pos.x, pos.y); - } - - agg::trans_affine transform; - - for(unsigned i = 0; i < attributes.size(); ++i) - { - mapnik::svg::path_attributes const& attr = attributes[i]; - if (!attr.visibility_flag) - continue; - cairo_save_restore guard(context); - transform = attr.transform; - transform *= mtx; - - // TODO - this 'is_valid' check is not used in the AGG renderer and also - // appears to lead to bogus results with - // tests/data/good_maps/markers_symbolizer_lines_file.xml - if (/*transform.is_valid() && */ !transform.is_identity()) - { - double m[6]; - transform.store_to(m); - cairo_matrix_t matrix; - cairo_matrix_init(&matrix,m[0],m[1],m[2],m[3],m[4],m[5]); - context.transform(matrix); - } - - if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT) - { - context.add_agg_path(svg_path,attr.index); - if (attr.even_odd_flag) - { - context.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); - } - else - { - context.set_fill_rule(CAIRO_FILL_RULE_WINDING); - } - if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT) - { - cairo_gradient g(attr.fill_gradient,attr.fill_opacity * attr.opacity * opacity); - - context.set_gradient(g,bbox); - context.fill(); - } - else if(attr.fill_flag) - { - double fill_opacity = attr.fill_opacity * attr.opacity * opacity * attr.fill_color.opacity(); - context.set_color(attr.fill_color.r/255.0,attr.fill_color.g/255.0, - attr.fill_color.b/255.0, fill_opacity); - context.fill(); - } - } - - if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) - { - context.add_agg_path(svg_path,attr.index); - if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) - { - context.set_line_width(attr.stroke_width); - context.set_line_cap(line_cap_enum(attr.line_cap)); - context.set_line_join(line_join_enum(attr.line_join)); - context.set_miter_limit(attr.miter_limit); - cairo_gradient g(attr.stroke_gradient,attr.fill_opacity * attr.opacity * opacity); - context.set_gradient(g,bbox); - context.stroke(); - } - else if (attr.stroke_flag) - { - double stroke_opacity = attr.stroke_opacity * attr.opacity * opacity * attr.stroke_color.opacity(); - context.set_color(attr.stroke_color.r/255.0,attr.stroke_color.g/255.0, - attr.stroke_color.b/255.0, stroke_opacity); - context.set_line_width(attr.stroke_width); - context.set_line_cap(line_cap_enum(attr.line_cap)); - context.set_line_join(line_join_enum(attr.line_join)); - context.set_miter_limit(attr.miter_limit); - context.stroke(); - } - } - } -} - - -void cairo_renderer_base::render_marker(pixel_position const& pos, +template +void cairo_renderer::render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity, @@ -552,598 +225,6 @@ void cairo_renderer_base::render_marker(pixel_position const& pos, } } -void cairo_renderer_base::process(point_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - - render_point_symbolizer( - sym, feature, prj_trans, common_, - [this](pixel_position const& pos, marker const& marker, - agg::trans_affine const& tr, double opacity) { - render_marker(pos, marker, tr, opacity); - }); -} - -void cairo_renderer_base::process(shield_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - agg::trans_affine tr; - auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); - text_symbolizer_helper helper( - sym, feature, common_.vars_, prj_trans, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_, tr); - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); - double opacity = get(sym,keys::opacity,feature, common_.vars_, 1.0); - - placements_list const &placements = helper.get(); - for (glyph_positions_ptr glyphs : placements) - { - if (glyphs->marker()) { - pixel_position pos = glyphs->marker_pos(); - render_marker(pos, - *(glyphs->marker()->marker), - glyphs->marker()->transform, - opacity); - } - context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); - } -} - -void cairo_renderer_base::process(line_pattern_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - - using conv_types = boost::mpl::vector; - - std::string filename = get(sym, keys::file, feature, common_.vars_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - bool clip = get(sym, keys::clip, feature, common_.vars_, false); - double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); - double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - - boost::optional marker; - if ( !filename.empty() ) - { - marker = marker_cache::instance().find(filename, true); - } - if (!marker || !(*marker)) return; - - unsigned width = (*marker)->width(); - unsigned height = (*marker)->height(); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - std::shared_ptr pattern; - image_ptr image = nullptr; - // TODO - re-implement at renderer level like polygon_pattern symbolizer - double opacity = get(sym, keys::opacity, feature, common_.vars_,1.0); - if ((*marker)->is_bitmap()) - { - pattern = std::make_unique(**((*marker)->get_bitmap_data())); - context_.set_line_width(height); - } - else - { - mapnik::rasterizer ras; - agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); - auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - image = render_pattern(ras, **marker, image_tr, opacity); - pattern = std::make_unique(*image); - width = image->width(); - height = image->height(); - context_.set_line_width(height); - } - - pattern->set_extend(CAIRO_EXTEND_REPEAT); - pattern->set_filter(CAIRO_FILTER_BILINEAR); - - agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - - box2d clipping_extent = common_.query_extent_; - if (clip) - { - double padding = (double)(common_.query_extent_.width()/common_.width_); - double half_stroke = width/2.0; - if (half_stroke > 1) - padding *= half_stroke; - if (std::fabs(offset) > 0) - padding *= std::fabs(offset) * 1.2; - padding *= common_.scale_factor_; - clipping_extent.pad(padding); - } - - using rasterizer_type = line_pattern_rasterizer; - rasterizer_type ras(context_, *pattern, width, height); - vertex_converter, rasterizer_type, line_pattern_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent, ras, sym, common_.t_, prj_trans, tr, feature, common_.vars_, common_.scale_factor_); - - if (clip) converter.set(); // optional clip (default: true) - converter.set(); // always transform - if (std::fabs(offset) > 0.0) converter.set(); // parallel offset - converter.set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - - for (auto & geom : feature.paths()) - { - if (geom.size() > 1) - { - converter.apply(geom); - } - } -} - -void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - std::string filename = get(sym, keys::file, feature, common_.vars_); - bool clip = get(sym, keys::clip, feature, common_.vars_, false); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); - double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - - agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); - auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - - boost::optional marker = mapnik::marker_cache::instance().find(filename,true); - if (!marker || !(*marker)) return; - - unsigned offset_x=0; - unsigned offset_y=0; - box2d const& clip_box = clipping_extent(common_); - pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); - if (alignment == LOCAL_ALIGNMENT) - { - double x0 = 0.0; - double y0 = 0.0; - - if (feature.num_geometries() > 0) - { - using clipped_geometry_type = agg::conv_clip_polygon; - using path_type = coord_transform; - clipped_geometry_type clipped(feature.get_geometry(0)); - clipped.clip_box(clip_box.minx(), clip_box.miny(), - clip_box.maxx(), clip_box.maxy()); - path_type path(common_.t_, clipped, prj_trans); - path.vertex(&x0, &y0); - } - offset_x = std::abs(clip_box.width() - x0); - offset_y = std::abs(clip_box.height() - y0); - } - - if ((*marker)->is_bitmap()) - { - cairo_pattern pattern(**((*marker)->get_bitmap_data())); - pattern.set_extend(CAIRO_EXTEND_REPEAT); - pattern.set_origin(offset_x, offset_y); - context_.set_pattern(pattern); - } - else - { - mapnik::rasterizer ras; - double opacity = get(sym,keys::opacity, feature, common_.vars_, 1.0); - image_ptr image = render_pattern(ras, **marker, image_tr, opacity); - cairo_pattern pattern(*image); - pattern.set_extend(CAIRO_EXTEND_REPEAT); - pattern.set_origin(offset_x, offset_y); - context_.set_pattern(pattern); - } - - agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - - using conv_types = boost::mpl::vector; - vertex_converter, cairo_context, polygon_pattern_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); - - if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) - converter.set(); //always transform - converter.set(); - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - for ( geometry_type & geom : feature.paths()) - { - if (geom.size() > 2) - { - converter.apply(geom); - } - } - // fill polygon - context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); - context_.fill(); -} - -void cairo_renderer_base::process(raster_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - cairo_save_restore guard(context_); - render_raster_symbolizer( - sym, feature, prj_trans, common_, - [&](image_data_32 &target, composite_mode_e comp_op, double opacity, - int start_x, int start_y) { - context_.set_operator(comp_op); - context_.add_image(start_x, start_y, target, opacity); - } - ); -} - -namespace detail { - -template -struct markers_dispatch : mapnik::noncopyable -{ - markers_dispatch(SvgPath & marker, - Attributes const& attributes, - box2d const& bbox, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl const& feature, - mapnik::attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - :marker_(marker), - attributes_(attributes), - bbox_(bbox), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), - ctx_(std::get<0>(renderer_context)) - {} - - - template - void add_path(T & path) - { - marker_placement_enum placement_method = get( - sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - coord2d center = bbox_.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine tr = recenter * marker_trans_; - markers_placement_finder placement_finder( - placement_method, - path, - bbox_, - tr, - detector_, - spacing * scale_factor_, - max_error, - allow_overlap); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = tr; - matrix.rotate(angle); - matrix.translate(x, y); - render_vector_marker( - ctx_, - pixel_position(x, y), - marker_, - bbox_, - attributes_, - matrix, - opacity, - false); - } - } - - SvgPath & marker_; - Attributes const& attributes_; - box2d const& bbox_; - agg::trans_affine const& marker_trans_; - markers_symbolizer const& sym_; - Detector & detector_; - double scale_factor_; - feature_impl const& feature_; - attributes const& vars_; - cairo_context & ctx_; -}; - -template -struct raster_markers_dispatch : mapnik::noncopyable -{ - raster_markers_dispatch(mapnik::image_data_32 & src, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl const& feature, - mapnik::attributes const& vars, - RendererContext const& renderer_context) - : src_(src), - detector_(detector), - sym_(sym), - marker_trans_(marker_trans), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), - ctx_(std::get<0>(renderer_context)) {} - - template - void add_path(T & path) - { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - box2d bbox_(0,0, src_.width(),src_.height()); - markers_placement_finder placement_finder( - placement_method, - path, - bbox_, - marker_trans_, - detector_, - spacing * scale_factor_, - max_error, - allow_overlap); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = marker_trans_; - matrix.rotate(angle); - matrix.translate(x, y); - ctx_.add_image(matrix, src_, opacity); - } - } - - image_data_32 & src_; - Detector & detector_; - markers_symbolizer const& sym_; - agg::trans_affine const& marker_trans_; - double scale_factor_; - feature_impl const& feature_; - attributes const& vars_; - cairo_context & ctx_; -}; - -} -void cairo_renderer_base::process(markers_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using svg_attribute_type = agg::pod_bvector; - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - context_.set_operator(comp_op); - box2d clip_box = common_.query_extent_; - - auto renderer_context = std::tie(context_); - - using RendererContextType = decltype(renderer_context); - using vector_dispatch_type = detail::markers_dispatch >, - svg_attribute_type,label_collision_detector4>; - - using raster_dispatch_type = detail::raster_markers_dispatch; - - - render_markers_symbolizer( - sym, feature, prj_trans, common_, clip_box, - renderer_context); -} - -void cairo_renderer_base::process(text_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - agg::trans_affine tr; - auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); - text_symbolizer_helper helper( - sym, feature, common_.vars_, prj_trans, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_, tr); - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); - - placements_list const& placements = helper.get(); - for (glyph_positions_ptr glyphs : placements) - { - context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); - } -} - -namespace { - -/** - * Render a thunk which was frozen from a previous call to - * extract_bboxes. We should now have a new offset at which - * to render it, and the boxes themselves should already be - * in the detector from the placement_finder. - */ -struct thunk_renderer : public boost::static_visitor<> -{ - using renderer_type = cairo_renderer_base; - - thunk_renderer(renderer_type &ren, - cairo_context &context, - cairo_face_manager &face_manager, - renderer_common &common, - pixel_position const &offset) - : ren_(ren), context_(context), face_manager_(face_manager), - common_(common), offset_(offset) - {} - - void operator()(point_render_thunk const &thunk) const - { - pixel_position new_pos(thunk.pos_.x + offset_.x, thunk.pos_.y + offset_.y); - ren_.render_marker(new_pos, *thunk.marker_, thunk.tr_, thunk.opacity_, - thunk.comp_op_); - } - - void operator()(text_render_thunk const &thunk) const - { - cairo_save_restore guard(context_); - context_.set_operator(thunk.comp_op_); - - render_offset_placements( - thunk.placements_, - offset_, - [&] (glyph_positions_ptr glyphs) - { - if (glyphs->marker()) - { - ren_.render_marker(glyphs->marker_pos(), - *(glyphs->marker()->marker), - glyphs->marker()->transform, - thunk.opacity_, thunk.comp_op_); - } - context_.add_text(glyphs, face_manager_, common_.font_manager_, src_over, src_over, common_.scale_factor_); - }); - } - - template - void operator()(T const &) const - { - // TODO: warning if unimplemented? - } - -private: - renderer_type &ren_; - cairo_context &context_; - cairo_face_manager &face_manager_; - renderer_common &common_; - pixel_position offset_; -}; - -} // anonymous namespace - -void cairo_renderer_base::process(group_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - render_group_symbolizer( - sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, - [&](render_thunk_list const& thunks, pixel_position const& render_offset) - { - thunk_renderer ren(*this, context_, face_manager_, common_, render_offset); - for (render_thunk_ptr const& thunk : thunks) - { - boost::apply_visitor(ren, *thunk); - } - }); -} - -namespace { - -// special implementation of the box drawing so that it's pixel-aligned -void render_debug_box(cairo_context &context, box2d const& b) -{ - cairo_save_restore guard(context); - double minx = std::floor(b.minx()) + 0.5; - double miny = std::floor(b.miny()) + 0.5; - double maxx = std::floor(b.maxx()) + 0.5; - double maxy = std::floor(b.maxy()) + 0.5; - context.move_to(minx, miny); - context.line_to(minx, maxy); - context.line_to(maxx, maxy); - context.line_to(maxx, miny); - context.close_path(); - context.stroke(); -} - -} // anonymous namespace - -void cairo_renderer_base::process(debug_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using detector_type = label_collision_detector4; - cairo_save_restore guard(context_); - - debug_symbolizer_mode_enum mode = get(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); - - context_.set_operator(src_over); - context_.set_color(mapnik::color(255, 0, 0), 1.0); - context_.set_line_join(MITER_JOIN); - context_.set_line_cap(BUTT_CAP); - context_.set_miter_limit(4.0); - context_.set_line_width(1.0); - - if (mode == DEBUG_SYM_MODE_COLLISION) - { - typename detector_type::query_iterator itr = common_.detector_->begin(); - typename detector_type::query_iterator end = common_.detector_->end(); - for ( ;itr!=end; ++itr) - { - render_debug_box(context_, itr->box); - } - } - else if (mode == DEBUG_SYM_MODE_VERTEX) - { - for (auto const& geom : feature.paths()) - { - double x; - double y; - double z = 0; - geom.rewind(0); - unsigned cmd = 1; - while ((cmd = geom.vertex(&x, &y)) != mapnik::SEG_END) - { - if (cmd == SEG_CLOSE) continue; - prj_trans.backward(x,y,z); - common_.t_.forward(&x,&y); - context_.move_to(std::floor(x) - 0.5, std::floor(y) + 0.5); - context_.line_to(std::floor(x) + 1.5, std::floor(y) + 0.5); - context_.move_to(std::floor(x) + 0.5, std::floor(y) - 0.5); - context_.line_to(std::floor(x) + 0.5, std::floor(y) + 1.5); - context_.stroke(); - } - } - } -} - -template class cairo_renderer; template class cairo_renderer; } diff --git a/src/cairo/process_building_symbolizer.cpp b/src/cairo/process_building_symbolizer.cpp new file mode 100644 index 000000000..47f54b406 --- /dev/null +++ b/src/cairo/process_building_symbolizer.cpp @@ -0,0 +1,84 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +// mapnik symbolizer generics +#include + +// stl +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(building_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using path_type = coord_transform; + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + mapnik::color fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); + double opacity = get(sym, keys::fill_opacity, feature, common_.vars_, 1.0); + double height = get(sym, keys::height, feature, common_.vars_, 0.0); + + context_.set_operator(comp_op); + + render_building_symbolizer( + feature, height, + [&](geometry_type &faces) { + path_type faces_path(common_.t_, faces, prj_trans); + context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8 / 255.0, + fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); + context_.add_path(faces_path); + context_.fill(); + }, + [&](geometry_type &frame) { + path_type path(common_.t_, frame, prj_trans); + context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8/255.0, + fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); + context_.set_line_width(common_.scale_factor_); + context_.add_path(path); + context_.stroke(); + }, + [&](geometry_type &roof) { + path_type roof_path(common_.t_, roof, prj_trans); + context_.set_color(fill, opacity); + context_.add_path(roof_path); + context_.fill(); + }); +} + +template void cairo_renderer::process(building_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_debug_symbolizer.cpp b/src/cairo/process_debug_symbolizer.cpp new file mode 100644 index 000000000..bab726bec --- /dev/null +++ b/src/cairo/process_debug_symbolizer.cpp @@ -0,0 +1,110 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include + +namespace mapnik +{ + +namespace { + +// special implementation of the box drawing so that it's pixel-aligned +inline void render_debug_box(cairo_context &context, box2d const& b) +{ + cairo_save_restore guard(context); + double minx = std::floor(b.minx()) + 0.5; + double miny = std::floor(b.miny()) + 0.5; + double maxx = std::floor(b.maxx()) + 0.5; + double maxy = std::floor(b.maxy()) + 0.5; + context.move_to(minx, miny); + context.line_to(minx, maxy); + context.line_to(maxx, maxy); + context.line_to(maxx, miny); + context.close_path(); + context.stroke(); +} + +} // anonymous namespace + +template +void cairo_renderer::process(debug_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using detector_type = label_collision_detector4; + cairo_save_restore guard(context_); + + debug_symbolizer_mode_enum mode = get(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); + + context_.set_operator(src_over); + context_.set_color(mapnik::color(255, 0, 0), 1.0); + context_.set_line_join(MITER_JOIN); + context_.set_line_cap(BUTT_CAP); + context_.set_miter_limit(4.0); + context_.set_line_width(1.0); + + if (mode == DEBUG_SYM_MODE_COLLISION) + { + typename detector_type::query_iterator itr = common_.detector_->begin(); + typename detector_type::query_iterator end = common_.detector_->end(); + for ( ;itr!=end; ++itr) + { + render_debug_box(context_, itr->box); + } + } + else if (mode == DEBUG_SYM_MODE_VERTEX) + { + for (auto const& geom : feature.paths()) + { + double x; + double y; + double z = 0; + geom.rewind(0); + unsigned cmd = 1; + while ((cmd = geom.vertex(&x, &y)) != mapnik::SEG_END) + { + if (cmd == SEG_CLOSE) continue; + prj_trans.backward(x,y,z); + common_.t_.forward(&x,&y); + context_.move_to(std::floor(x) - 0.5, std::floor(y) + 0.5); + context_.line_to(std::floor(x) + 1.5, std::floor(y) + 0.5); + context_.move_to(std::floor(x) + 0.5, std::floor(y) - 0.5); + context_.line_to(std::floor(x) + 0.5, std::floor(y) + 1.5); + context_.stroke(); + } + } + } +} + +template void cairo_renderer::process(debug_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_group_symbolizer.cpp b/src/cairo/process_group_symbolizer.cpp new file mode 100644 index 000000000..967fce270 --- /dev/null +++ b/src/cairo/process_group_symbolizer.cpp @@ -0,0 +1,126 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include + +// mapnik symbolizer generics +#include + +namespace mapnik +{ + +class feature_impl; +class proj_transform; +struct group_symbolizer; + +namespace { + +// Render a thunk which was frozen from a previous call to +// extract_bboxes. We should now have a new offset at which +// to render it, and the boxes themselves should already be +// in the detector from the placement_finder. +template +struct thunk_renderer : public boost::static_visitor<> +{ + using renderer_type = cairo_renderer; + + thunk_renderer(renderer_type & ren, + cairo_context & context, + cairo_face_manager & face_manager, + renderer_common & common, + pixel_position const& offset) + : ren_(ren), context_(context), face_manager_(face_manager), + common_(common), offset_(offset) + {} + + void operator()(point_render_thunk const &thunk) const + { + pixel_position new_pos(thunk.pos_.x + offset_.x, thunk.pos_.y + offset_.y); + ren_.render_marker(new_pos, *thunk.marker_, thunk.tr_, thunk.opacity_, + thunk.comp_op_); + } + + void operator()(text_render_thunk const &thunk) const + { + cairo_save_restore guard(context_); + context_.set_operator(thunk.comp_op_); + + render_offset_placements( + thunk.placements_, + offset_, + [&] (glyph_positions_ptr glyphs) + { + if (glyphs->marker()) + { + ren_.render_marker(glyphs->marker_pos(), + *(glyphs->marker()->marker), + glyphs->marker()->transform, + thunk.opacity_, thunk.comp_op_); + } + context_.add_text(glyphs, face_manager_, common_.font_manager_, src_over, src_over, common_.scale_factor_); + }); + } + + template + void operator()(T0 const &) const + { + // TODO: warning if unimplemented? + } + +private: + renderer_type & ren_; + cairo_context & context_; + cairo_face_manager & face_manager_; + renderer_common & common_; + pixel_position offset_; +}; + +} // anonymous namespace + +template +void cairo_renderer::process(group_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + render_group_symbolizer( + sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, + [&](render_thunk_list const& thunks, pixel_position const& render_offset) + { + thunk_renderer ren(*this, context_, face_manager_, common_, render_offset); + for (render_thunk_ptr const& thunk : thunks) + { + boost::apply_visitor(ren, *thunk); + } + }); +} + +template void cairo_renderer::process(group_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_line_pattern_symbolizer.cpp b/src/cairo/process_line_pattern_symbolizer.cpp new file mode 100644 index 000000000..4f1e1af60 --- /dev/null +++ b/src/cairo/process_line_pattern_symbolizer.cpp @@ -0,0 +1,141 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(line_pattern_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + + using conv_types = boost::mpl::vector; + + std::string filename = get(sym, keys::file, feature, common_.vars_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); + + boost::optional marker; + if ( !filename.empty() ) + { + marker = marker_cache::instance().find(filename, true); + } + if (!marker || !(*marker)) return; + + unsigned width = (*marker)->width(); + unsigned height = (*marker)->height(); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + std::shared_ptr pattern; + image_ptr image = nullptr; + // TODO - re-implement at renderer level like polygon_pattern symbolizer + double opacity = get(sym, keys::opacity, feature, common_.vars_,1.0); + if ((*marker)->is_bitmap()) + { + pattern = std::make_unique(**((*marker)->get_bitmap_data())); + context_.set_line_width(height); + } + else + { + mapnik::rasterizer ras; + agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); + auto image_transform = get_optional(sym, keys::image_transform); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + image = render_pattern(ras, **marker, image_tr, opacity); + pattern = std::make_unique(*image); + width = image->width(); + height = image->height(); + context_.set_line_width(height); + } + + pattern->set_extend(CAIRO_EXTEND_REPEAT); + pattern->set_filter(CAIRO_FILTER_BILINEAR); + + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } + + box2d clipping_extent = common_.query_extent_; + if (clip) + { + double padding = (double)(common_.query_extent_.width()/common_.width_); + double half_stroke = width/2.0; + if (half_stroke > 1) + padding *= half_stroke; + if (std::fabs(offset) > 0) + padding *= std::fabs(offset) * 1.2; + padding *= common_.scale_factor_; + clipping_extent.pad(padding); + } + + using rasterizer_type = line_pattern_rasterizer; + rasterizer_type ras(context_, *pattern, width, height); + vertex_converter, rasterizer_type, line_pattern_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clipping_extent, ras, sym, common_.t_, prj_trans, tr, feature, common_.vars_, common_.scale_factor_); + + if (clip) converter.set(); // optional clip (default: true) + converter.set(); // always transform + if (std::fabs(offset) > 0.0) converter.set(); // parallel offset + converter.set(); // optional affine transform + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + + for (auto & geom : feature.paths()) + { + if (geom.size() > 1) + { + converter.apply(geom); + } + } +} + +template void cairo_renderer::process(line_pattern_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_line_symbolizer.cpp b/src/cairo/process_line_symbolizer.cpp new file mode 100644 index 000000000..0b008cf57 --- /dev/null +++ b/src/cairo/process_line_symbolizer.cpp @@ -0,0 +1,116 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(line_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using conv_types = boost::mpl::vector; + + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); + + mapnik::color stroke = get(sym, keys::stroke, feature, common_.vars_, mapnik::color(0,0,0)); + double stroke_opacity = get(sym, keys::stroke_opacity, feature, common_.vars_, 1.0); + line_join_enum stroke_join = get(sym, keys::stroke_linejoin, feature, common_.vars_, MITER_JOIN); + line_cap_enum stroke_cap = get(sym, keys::stroke_linecap, feature, common_.vars_, BUTT_CAP); + auto dash = get_optional(sym, keys::stroke_dasharray, feature, common_.vars_); + double miterlimit = get(sym, keys::stroke_miterlimit, feature, common_.vars_, 4.0); + double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + context_.set_color(stroke, stroke_opacity); + context_.set_line_join(stroke_join); + context_.set_line_cap(stroke_cap); + context_.set_miter_limit(miterlimit); + context_.set_line_width(width * common_.scale_factor_); + if (dash) + { + context_.set_dash(*dash, common_.scale_factor_); + } + + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } + + box2d clipping_extent = common_.query_extent_; + if (clip) + { + double padding = (double)(common_.query_extent_.width()/common_.width_); + double half_stroke = width/2.0; + if (half_stroke > 1) + padding *= half_stroke; + if (std::fabs(offset) > 0) + padding *= std::fabs(offset) * 1.2; + padding *= common_.scale_factor_; + clipping_extent.pad(padding); + } + vertex_converter, cairo_context, line_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clipping_extent,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); + + if (clip) converter.set(); // optional clip (default: true) + converter.set(); // always transform + if (std::fabs(offset) > 0.0) converter.set(); // parallel offset + converter.set(); // optional affine transform + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + for (geometry_type & geom : feature.paths()) + { + if (geom.size() > 1) + { + converter.apply(geom); + } + } + // stroke + context_.set_fill_rule(CAIRO_FILL_RULE_WINDING); + context_.stroke(); +} + +template void cairo_renderer::process(line_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_markers_symbolizer.cpp b/src/cairo/process_markers_symbolizer.cpp new file mode 100644 index 000000000..07bd142ee --- /dev/null +++ b/src/cairo/process_markers_symbolizer.cpp @@ -0,0 +1,224 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// agg +#include "agg/include/agg_array.h" // for pod_bvector +#include "agg/include/agg_trans_affine.h" // for trans_affine, etc + +namespace mapnik +{ + +class feature_impl; +class proj_transform; +namespace svg { struct path_attributes; } + +namespace detail { + +template +struct markers_dispatch : mapnik::noncopyable +{ + markers_dispatch(SvgPath & marker, + Attributes const& attributes, + box2d const& bbox, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + feature_impl const& feature, + mapnik::attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) + :marker_(marker), + attributes_(attributes), + bbox_(bbox), + marker_trans_(marker_trans), + sym_(sym), + detector_(detector), + scale_factor_(scale_factor), + feature_(feature), + vars_(vars), + ctx_(std::get<0>(renderer_context)) + {} + + + template + void add_path(T & path) + { + marker_placement_enum placement_method = get( + sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + coord2d center = bbox_.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine tr = recenter * marker_trans_; + markers_placement_finder placement_finder( + placement_method, + path, + bbox_, + tr, + detector_, + spacing * scale_factor_, + max_error, + allow_overlap); + double x, y, angle = .0; + while (placement_finder.get_point(x, y, angle, ignore_placement)) + { + agg::trans_affine matrix = tr; + matrix.rotate(angle); + matrix.translate(x, y); + render_vector_marker( + ctx_, + pixel_position(x, y), + marker_, + bbox_, + attributes_, + matrix, + opacity, + false); + } + } + + SvgPath & marker_; + Attributes const& attributes_; + box2d const& bbox_; + agg::trans_affine const& marker_trans_; + markers_symbolizer const& sym_; + Detector & detector_; + double scale_factor_; + feature_impl const& feature_; + attributes const& vars_; + cairo_context & ctx_; +}; + +template +struct raster_markers_dispatch : mapnik::noncopyable +{ + raster_markers_dispatch(mapnik::image_data_32 & src, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + feature_impl const& feature, + mapnik::attributes const& vars, + RendererContext const& renderer_context) + : src_(src), + detector_(detector), + sym_(sym), + marker_trans_(marker_trans), + scale_factor_(scale_factor), + feature_(feature), + vars_(vars), + ctx_(std::get<0>(renderer_context)) {} + + template + void add_path(T & path) + { + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + box2d bbox_(0,0, src_.width(),src_.height()); + markers_placement_finder placement_finder( + placement_method, + path, + bbox_, + marker_trans_, + detector_, + spacing * scale_factor_, + max_error, + allow_overlap); + double x, y, angle = .0; + while (placement_finder.get_point(x, y, angle, ignore_placement)) + { + agg::trans_affine matrix = marker_trans_; + matrix.rotate(angle); + matrix.translate(x, y); + ctx_.add_image(matrix, src_, opacity); + } + } + + image_data_32 & src_; + Detector & detector_; + markers_symbolizer const& sym_; + agg::trans_affine const& marker_trans_; + double scale_factor_; + feature_impl const& feature_; + attributes const& vars_; + cairo_context & ctx_; +}; + +} + +template +void cairo_renderer::process(markers_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using svg_attribute_type = agg::pod_bvector; + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + context_.set_operator(comp_op); + box2d clip_box = common_.query_extent_; + + auto renderer_context = std::tie(context_); + + using RendererContextType = decltype(renderer_context); + using vector_dispatch_type = detail::markers_dispatch >, + svg_attribute_type,label_collision_detector4>; + + using raster_dispatch_type = detail::raster_markers_dispatch; + + + render_markers_symbolizer( + sym, feature, prj_trans, common_, clip_box, + renderer_context); +} + +template void cairo_renderer::process(markers_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_point_symbolizer.cpp b/src/cairo/process_point_symbolizer.cpp new file mode 100644 index 000000000..349a198f2 --- /dev/null +++ b/src/cairo/process_point_symbolizer.cpp @@ -0,0 +1,66 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include + +namespace agg { struct trans_affine; } + +namespace mapnik +{ + +class feature_impl; +class proj_transform; + +template +void cairo_renderer::process(point_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + + render_point_symbolizer( + sym, feature, prj_trans, common_, + [this](pixel_position const& pos, marker const& marker, + agg::trans_affine const& tr, double opacity) { + render_marker(pos, marker, tr, opacity); + }); +} + +template void cairo_renderer::process(point_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_polygon_pattern_symbolizer.cpp b/src/cairo/process_polygon_pattern_symbolizer.cpp new file mode 100644 index 000000000..3bea8c6b7 --- /dev/null +++ b/src/cairo/process_polygon_pattern_symbolizer.cpp @@ -0,0 +1,135 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(polygon_pattern_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + std::string filename = get(sym, keys::file, feature, common_.vars_); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); + + agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); + auto image_transform = get_optional(sym, keys::image_transform); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + + boost::optional marker = mapnik::marker_cache::instance().find(filename,true); + if (!marker || !(*marker)) return; + + unsigned offset_x=0; + unsigned offset_y=0; + box2d const& clip_box = clipping_extent(common_); + pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); + if (alignment == LOCAL_ALIGNMENT) + { + double x0 = 0.0; + double y0 = 0.0; + + if (feature.num_geometries() > 0) + { + using clipped_geometry_type = agg::conv_clip_polygon; + using path_type = coord_transform; + clipped_geometry_type clipped(feature.get_geometry(0)); + clipped.clip_box(clip_box.minx(), clip_box.miny(), + clip_box.maxx(), clip_box.maxy()); + path_type path(common_.t_, clipped, prj_trans); + path.vertex(&x0, &y0); + } + offset_x = std::abs(clip_box.width() - x0); + offset_y = std::abs(clip_box.height() - y0); + } + + if ((*marker)->is_bitmap()) + { + cairo_pattern pattern(**((*marker)->get_bitmap_data())); + pattern.set_extend(CAIRO_EXTEND_REPEAT); + pattern.set_origin(offset_x, offset_y); + context_.set_pattern(pattern); + } + else + { + mapnik::rasterizer ras; + double opacity = get(sym,keys::opacity, feature, common_.vars_, 1.0); + image_ptr image = render_pattern(ras, **marker, image_tr, opacity); + cairo_pattern pattern(*image); + pattern.set_extend(CAIRO_EXTEND_REPEAT); + pattern.set_origin(offset_x, offset_y); + context_.set_pattern(pattern); + } + + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } + + using conv_types = boost::mpl::vector; + vertex_converter, cairo_context, polygon_pattern_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); + + if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) + converter.set(); //always transform + converter.set(); + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + for ( geometry_type & geom : feature.paths()) + { + if (geom.size() > 2) + { + converter.apply(geom); + } + } + // fill polygon + context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); + context_.fill(); +} + +template void cairo_renderer::process(polygon_pattern_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_polygon_symbolizer.cpp b/src/cairo/process_polygon_symbolizer.cpp new file mode 100644 index 000000000..2680dafce --- /dev/null +++ b/src/cairo/process_polygon_symbolizer.cpp @@ -0,0 +1,66 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include + +namespace mapnik +{ + + +template +void cairo_renderer::process(polygon_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using conv_types = boost::mpl::vector; + using vertex_converter_type = vertex_converter, cairo_context, polygon_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, + conv_types, feature_impl>; + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + context_.set_operator(comp_op); + + render_polygon_symbolizer( + sym, feature, prj_trans, common_, common_.query_extent_, context_, + [&](color const &fill, double opacity) { + context_.set_color(fill, opacity); + // fill polygon + context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); + context_.fill(); + }); +} + +template void cairo_renderer::process(polygon_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_raster_symbolizer.cpp b/src/cairo/process_raster_symbolizer.cpp new file mode 100644 index 000000000..62f45353a --- /dev/null +++ b/src/cairo/process_raster_symbolizer.cpp @@ -0,0 +1,59 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include + +// mapnik symbolizer generics +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(raster_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + cairo_save_restore guard(context_); + render_raster_symbolizer( + sym, feature, prj_trans, common_, + [&](image_data_32 &target, composite_mode_e comp_op, double opacity, + int start_x, int start_y) { + context_.set_operator(comp_op); + context_.add_image(start_x, start_y, target, opacity); + } + ); +} + +template void cairo_renderer::process(raster_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_text_symbolizer.cpp b/src/cairo/process_text_symbolizer.cpp new file mode 100644 index 000000000..0948b4cce --- /dev/null +++ b/src/cairo/process_text_symbolizer.cpp @@ -0,0 +1,107 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include + + +namespace mapnik +{ + +class feature_impl; +class proj_transform; + +template +void cairo_renderer::process(shield_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + text_symbolizer_helper helper( + sym, feature, common_.vars_, prj_trans, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + common_.query_extent_, tr); + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); + double opacity = get(sym,keys::opacity,feature, common_.vars_, 1.0); + + placements_list const &placements = helper.get(); + for (glyph_positions_ptr glyphs : placements) + { + if (glyphs->marker()) { + pixel_position pos = glyphs->marker_pos(); + render_marker(pos, + *(glyphs->marker()->marker), + glyphs->marker()->transform, + opacity); + } + context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); + } +} + +template void cairo_renderer::process(shield_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +template +void cairo_renderer::process(text_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + text_symbolizer_helper helper( + sym, feature, common_.vars_, prj_trans, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + common_.query_extent_, tr); + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); + + placements_list const& placements = helper.get(); + for (glyph_positions_ptr glyphs : placements) + { + context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); + } +} + +template void cairo_renderer::process(text_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 0d30c7682..a9af0dc5a 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -45,7 +45,6 @@ namespace mapnik #if defined(HAVE_CAIRO) template class feature_style_processor >; -template class feature_style_processor >; #endif #if defined(SVG_RENDERER) From 48078da22dd952801c520bb4b669962728bca2b7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 20:35:23 -0700 Subject: [PATCH 24/25] debug font crash - refs #2341 --- .travis.yml | 3 +++ src/font_engine_freetype.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 96d7b2173..317dbe64e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,3 +52,6 @@ before_script: script: - if [[ ${BENCHMARK} != False ]]; then make bench; fi; + # install some exotic fonts to ensure we don't crash registering them + - sudo apt-get install ttf-* + - python -c "import mapnik;mapnik.logger.set_severity(mapnik.severity_type.Debug);mapnik.register_fonts('/usr/share/fonts/');mapnik.register_fonts('/usr/share/fonts/');print '\n'.join(list(mapnik.FontEngine.instance().face_names()))" diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index 87209f569..722b22959 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -132,6 +132,7 @@ bool freetype_engine::register_font(std::string const& file_name) bool freetype_engine::register_font_impl(std::string const& file_name, FT_LibraryRec_ * library) { + MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name; #ifdef _WINDOWS FILE * file = _wfopen(mapnik::utf8_to_utf16(file_name).c_str(), L"rb"); #else From 4054b97984966e1b8e7374c4391424db8681db39 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 20:56:13 -0700 Subject: [PATCH 25/25] fix font testing --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 317dbe64e..e12580b01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,5 +53,6 @@ before_script: script: - if [[ ${BENCHMARK} != False ]]; then make bench; fi; # install some exotic fonts to ensure we don't crash registering them - - sudo apt-get install ttf-* + - sudo apt-get install ttf-wqy-microhei + - source localize.sh - python -c "import mapnik;mapnik.logger.set_severity(mapnik.severity_type.Debug);mapnik.register_fonts('/usr/share/fonts/');mapnik.register_fonts('/usr/share/fonts/');print '\n'.join(list(mapnik.FontEngine.instance().face_names()))"