From b7dda95d843899fe7ba4c443b4589edf7b192ece Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 10 Dec 2013 15:50:03 -0500 Subject: [PATCH 01/10] move symbolizer to json into core symbolizer json grammar (needs more work) --- bindings/python/mapnik_symbolizer.cpp | 26 +-- include/mapnik/json/symbolizer_grammar.hpp | 184 +++++++++++++++++++++ include/mapnik/symbolizer_utils.hpp | 25 +++ 3 files changed, 210 insertions(+), 25 deletions(-) create mode 100644 include/mapnik/json/symbolizer_grammar.hpp diff --git a/bindings/python/mapnik_symbolizer.cpp b/bindings/python/mapnik_symbolizer.cpp index 188cd3e8e..b16930471 100644 --- a/bindings/python/mapnik_symbolizer.cpp +++ b/bindings/python/mapnik_symbolizer.cpp @@ -124,33 +124,9 @@ boost::python::object __getitem__(mapnik::symbolizer_base const& sym, std::strin return boost::python::object(); } -struct symbolizer_to_json : public boost::static_visitor -{ - typedef std::string result_type; - - template - auto operator() (T const& sym) const -> result_type - { - std::stringstream ss; - ss << "{\"type\":\"" << mapnik::symbolizer_traits::name() << "\","; - ss << "\"properties\":{"; - bool first = true; - for (auto const& prop : sym.properties) - { - auto const& meta = mapnik::get_meta(prop.first); - if (first) first = false; - else ss << ","; - ss << "\"" << std::get<0>(meta) << "\":"; - ss << boost::apply_visitor(mapnik::symbolizer_property_value_string(meta),prop.second); - } - ss << "}}"; - return ss.str(); - } -}; - std::string __str__(mapnik::symbolizer const& sym) { - return boost::apply_visitor(symbolizer_to_json(), sym); + return boost::apply_visitor(mapnik::symbolizer_to_json(), sym); } std::string get_symbolizer_type(symbolizer const& sym) diff --git a/include/mapnik/json/symbolizer_grammar.hpp b/include/mapnik/json/symbolizer_grammar.hpp new file mode 100644 index 000000000..a2e36cbf4 --- /dev/null +++ b/include/mapnik/json/symbolizer_grammar.hpp @@ -0,0 +1,184 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_SYMBOLIZER_GRAMMAR_HPP +#define MAPNIK_SYMBOLIZER_GRAMMAR_HPP + +// boost +#define BOOST_SPIRIT_USE_PHOENIX_V3 1 +#include +#include + +// mapnik +#include +#include + +namespace mapnik { namespace json { + +namespace qi = boost::spirit::qi; +namespace phoenix = boost::phoenix; +namespace fusion = boost::fusion; +namespace standard_wide = boost::spirit::standard_wide; +using standard_wide::space_type; + +template +struct put_property_visitor : boost::static_visitor<> +{ + typedef T value_type; + + put_property_visitor(mapnik::keys key, value_type const& val) + : key_(key), val_(val) {} + + template + void operator() (Symbolizer & sym) const + { + std::cerr << std::get<0>(get_meta(key_)) << ":" << val_ << std::endl; + // put(sym, key_, val_); + } + + keys key_; + value_type const& val_; +}; + +struct put_property +{ + typedef void result_type; + //explicit put_property(mapnik::transcoder const& tr) + // : tr_(tr) {} + template + result_type operator() (T0 & sym, T1 const& name, T2 const& val) const + { + try + { + boost::apply_visitor(put_property_visitor(get_key(name),val), sym); + } + catch (std::runtime_error const& err) + { + std::cerr << err.what() << std::endl; + } + } +// mapnik::transcoder const& tr_; +}; + +template +struct symbolizer_grammar : qi::grammar +{ + symbolizer_grammar(generic_json & json) + : symbolizer_grammar::base_type(sym, "symbolizer"), + json_(json) + { + using qi::lit; + using qi::double_; + using qi::int_; + using qi::no_skip; + using qi::omit; + using qi::_val; + using qi::_a; + using qi::_r1; + using qi::_1; + using qi::_2; + using qi::_3; + using qi::_4; + using qi::fail; + using qi::on_error; + using standard_wide::char_; + using phoenix::construct; + + // generic json types + json_.value = json_.object | json_.array | json_.string_ + | json_.number + ; + + json_.pairs = json_.key_value % lit(',') + ; + + json_.key_value = (json_.string_ >> lit(':') >> json_.value) + ; + + json_.object = lit('{') + >> *json_.pairs + >> lit('}') + ; + + json_.array = lit('[') + >> json_.value >> *(lit(',') >> json_.value) + >> lit(']') + ; + + json_.number %= json_.strict_double + | json_.int__ + | lit("true") [_val = true] + | lit ("false") [_val = false] + | lit("null")[_val = construct()] + ; + json_.unesc_char.add + ("\\\"", '\"') // quotation mark + ("\\\\", '\\') // reverse solidus + ("\\/", '/') // solidus + ("\\b", '\b') // backspace + ("\\f", '\f') // formfeed + ("\\n", '\n') // newline + ("\\r", '\r') // carrige return + ("\\t", '\t') // tab + ; + + json_.string_ %= lit('"') >> no_skip[*(json_.unesc_char | "\\u" >> json_.hex4 | (char_ - lit('"')))] >> lit('"') + ; + + sym = lit('{') + >> lit("\"type\"") >> lit(':') + >> (lit("\"PointSymbolizer\"")[_val = construct()] + | + lit("\"LineSymbolizer\"")[_val = construct()] + | + lit("\"PolygonSymbolizer\"")[_val = construct()] + ) + >> lit(',') + >> lit("\"properties\"") >> lit(':') + >> ((lit('{') >> *property(_val) >> lit('}')) | lit("null")) + >> lit('}') + ; + + property = (json_.string_ [_a = _1] >> lit(':') >> property_value [put_property_(_r1,_a,_1)]) % lit(',') + ; + + property_value %= json.number | json.string_ ; + + + } + + // generic JSON + generic_json & json_; + // symbolizer + qi::rule sym; + qi::rule, void(mapnik::symbolizer&),space_type> property; + qi::rule, space_type> property_value; + + phoenix::function put_property_; + // error + //boost::phoenix::function where_message_; +}; + + +}} + +#endif // MAPNIK_FEATURE_GRAMMAR_HPP diff --git a/include/mapnik/symbolizer_utils.hpp b/include/mapnik/symbolizer_utils.hpp index c0108751a..4ec6c69e6 100644 --- a/include/mapnik/symbolizer_utils.hpp +++ b/include/mapnik/symbolizer_utils.hpp @@ -215,6 +215,31 @@ private: Meta const& meta_; }; +struct symbolizer_to_json : public boost::static_visitor +{ + typedef std::string result_type; + + template + auto operator() (T const& sym) const -> result_type + { + std::stringstream ss; + ss << "{\"type\":\"" << mapnik::symbolizer_traits::name() << "\","; + ss << "\"properties\":{"; + bool first = true; + for (auto const& prop : sym.properties) + { + auto const& meta = mapnik::get_meta(prop.first); + if (first) first = false; + else ss << ","; + ss << "\"" << std::get<0>(meta) << "\":"; + ss << boost::apply_visitor(symbolizer_property_value_string(meta),prop.second); + } + ss << "}}"; + return ss.str(); + } }; + +} + #endif // MAPNIK_SYMBOLIZER_UTILS_HPP From d3836bc71a8d9958f858227d3119cbdfbc9c109c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 11 Dec 2013 07:25:23 -0800 Subject: [PATCH 02/10] c++11 --- src/svg/output/process_symbolizers.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/svg/output/process_symbolizers.cpp b/src/svg/output/process_symbolizers.cpp index 10de95982..19338d5f9 100644 --- a/src/svg/output/process_symbolizers.cpp +++ b/src/svg/output/process_symbolizers.cpp @@ -59,7 +59,7 @@ bool svg_renderer::process(rule::symbolizers const& syms, // process each symbolizer to collect its (path) information. // path information (attributes from line_ and polygon_ symbolizers) // is collected with the path_attributes_ data member. - for (symbolizer const& sym : syms) + for (auto const& sym : syms) { if (is_path_based(sym)) { @@ -71,9 +71,8 @@ bool svg_renderer::process(rule::symbolizers const& syms, if (process_path) { // generate path output for each geometry of the current feature. - for(std::size_t i=0; i 0) { path_type path(t_, geom, prj_trans); From 6a0e593d873297f55254260b621117c149a3397a Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 11 Dec 2013 07:26:32 -0800 Subject: [PATCH 03/10] fix svg_renderer --- src/svg/output/process_line_symbolizer.cpp | 8 +- src/svg/output/process_polygon_symbolizer.cpp | 4 +- src/svg/output/svg_renderer.cpp | 1 - .../svg_renderer_tests/path_element_test.cpp | 262 ++++++++++++------ 4 files changed, 180 insertions(+), 95 deletions(-) diff --git a/src/svg/output/process_line_symbolizer.cpp b/src/svg/output/process_line_symbolizer.cpp index 6f2008408..96f5f03ad 100644 --- a/src/svg/output/process_line_symbolizer.cpp +++ b/src/svg/output/process_line_symbolizer.cpp @@ -33,13 +33,15 @@ void svg_renderer::process(line_symbolizer const& sym, mapnik::feature_impl & /*feature*/, proj_transform const& /*prj_trans*/) { - path_attributes_.set_stroke_color(sym.get_stroke().get_color()); - path_attributes_.set_stroke_opacity(sym.get_stroke().get_opacity()); - path_attributes_.set_stroke_width(sym.get_stroke().get_width()); + path_attributes_.set_stroke_color(get(sym, keys::stroke, mapnik::color(0,0,0))); + path_attributes_.set_stroke_opacity(get(sym,keys::stroke_opacity, 1.0)); + path_attributes_.set_stroke_width(get(sym, keys::stroke_width, 1.0)); + /* path_attributes_.set_stroke_linecap(sym.get_stroke().get_line_cap()); path_attributes_.set_stroke_linejoin(sym.get_stroke().get_line_join()); path_attributes_.set_stroke_dasharray(sym.get_stroke().get_dash_array()); path_attributes_.set_stroke_dashoffset(sym.get_stroke().dash_offset()); + */ } template void svg_renderer >::process(line_symbolizer const& sym, diff --git a/src/svg/output/process_polygon_symbolizer.cpp b/src/svg/output/process_polygon_symbolizer.cpp index 43ca9bdf8..63b5b1f47 100644 --- a/src/svg/output/process_polygon_symbolizer.cpp +++ b/src/svg/output/process_polygon_symbolizer.cpp @@ -33,8 +33,8 @@ void svg_renderer::process(polygon_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - path_attributes_.set_fill_color(sym.get_fill()); - path_attributes_.set_fill_opacity(sym.get_opacity()); + path_attributes_.set_fill_color(get(sym, keys::fill, mapnik::color(128,128,128))); + path_attributes_.set_fill_opacity(get(sym,keys::fill_opacity, 1.0)); } template void svg_renderer >::process(polygon_symbolizer const& sym, diff --git a/src/svg/output/svg_renderer.cpp b/src/svg/output/svg_renderer.cpp index b92347c25..3caa65e24 100644 --- a/src/svg/output/svg_renderer.cpp +++ b/src/svg/output/svg_renderer.cpp @@ -97,7 +97,6 @@ void svg_renderer::end_map_processing(Map const& map) { // generate SVG root element closing tag. generator_.generate_closing_root(); - MAPNIK_LOG_DEBUG(svg_renderer) << "svg_renderer: End map processing"; } diff --git a/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp b/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp index 9b99b981a..8ef190bf9 100644 --- a/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp +++ b/tests/cpp_tests/svg_renderer_tests/path_element_test.cpp @@ -14,6 +14,10 @@ #include #include #include +#include +#include +#include + // stl #include @@ -22,119 +26,186 @@ namespace fs = boost::filesystem; using namespace mapnik; -void prepare_map(Map& m) +const std::string srs_lcc="+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 \ + +datum=NAD83 +units=m +no_defs"; +const std::string srs_merc="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 \ + +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"; + +void prepare_map(Map & m) { - const std::string mapnik_dir("/usr/local/lib/mapnik/"); - std::cout << " looking for 'shape.input' plugin in... " << mapnik_dir << "input/" << "\n"; - datasource_cache::instance().register_datasources(mapnik_dir + "input/"); - - // create styles - // Provinces (polygon) feature_type_style provpoly_style; - - rule provpoly_rule_on; - provpoly_rule_on.set_filter(parse_expression("[NAME_EN] = 'Ontario'")); - provpoly_rule_on.append(polygon_symbolizer(color(250, 190, 183))); - provpoly_style.add_rule(provpoly_rule_on); - - rule provpoly_rule_qc; - provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'")); - provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203))); - provpoly_style.add_rule(provpoly_rule_qc); - + { + rule r; + r.set_filter(parse_expression("[NAME_EN] = 'Ontario'")); + { + polygon_symbolizer poly_sym; + put(poly_sym, keys::fill, color(250, 190, 183)); + r.append(std::move(poly_sym)); + } + provpoly_style.add_rule(r); + } + { + rule r; + r.set_filter(parse_expression("[NOM_FR] = 'Québec'")); + { + polygon_symbolizer poly_sym; + put(poly_sym, keys::fill, color(217, 235, 203)); + r.append(std::move(poly_sym)); + } + provpoly_style.add_rule(r); + } m.insert_style("provinces",provpoly_style); // Provinces (polyline) feature_type_style provlines_style; - - stroke provlines_stk (color(0,0,0),1.0); - provlines_stk.add_dash(8, 4); - provlines_stk.add_dash(2, 2); - provlines_stk.add_dash(2, 2); - - rule provlines_rule; - provlines_rule.append(line_symbolizer(provlines_stk)); - provlines_style.add_rule(provlines_rule); - + { + rule r; + { + line_symbolizer line_sym; + put(line_sym,keys::stroke,color(0,0,0)); + put(line_sym,keys::stroke_width,1.0); + dash_array dash; + dash.emplace_back(8,4); + dash.emplace_back(2,2); + dash.emplace_back(2,2); + put(line_sym,keys::stroke_dasharray,dash); + r.append(std::move(line_sym)); + } + provlines_style.add_rule(r); + } m.insert_style("provlines",provlines_style); // Drainage feature_type_style qcdrain_style; - - rule qcdrain_rule; - qcdrain_rule.set_filter(parse_expression("[HYC] = 8")); - qcdrain_rule.append(polygon_symbolizer(color(153, 204, 255))); - qcdrain_style.add_rule(qcdrain_rule); - + { + rule r; + r.set_filter(parse_expression("[HYC] = 8")); + { + polygon_symbolizer poly_sym; + put(poly_sym, keys::fill, color(153, 204, 255)); + r.append(std::move(poly_sym)); + } + qcdrain_style.add_rule(r); + } m.insert_style("drainage",qcdrain_style); // Roads 3 and 4 (The "grey" roads) feature_type_style roads34_style; - rule roads34_rule; - roads34_rule.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4")); - stroke roads34_rule_stk(color(171,158,137),2.0); - roads34_rule_stk.set_line_cap(ROUND_CAP); - roads34_rule_stk.set_line_join(ROUND_JOIN); - roads34_rule.append(line_symbolizer(roads34_rule_stk)); - roads34_style.add_rule(roads34_rule); - + { + rule r; + r.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4")); + { + line_symbolizer line_sym; + put(line_sym,keys::stroke,color(171,158,137)); + put(line_sym,keys::stroke_width,2.0); + put(line_sym,keys::stroke_linecap,ROUND_CAP); + put(line_sym,keys::stroke_linejoin,ROUND_JOIN); + r.append(std::move(line_sym)); + } + roads34_style.add_rule(r); + } m.insert_style("smallroads",roads34_style); // Roads 2 (The thin yellow ones) feature_type_style roads2_style_1; - rule roads2_rule_1; - roads2_rule_1.set_filter(parse_expression("[CLASS] = 2")); - stroke roads2_rule_stk_1(color(171,158,137),4.0); - roads2_rule_stk_1.set_line_cap(ROUND_CAP); - roads2_rule_stk_1.set_line_join(ROUND_JOIN); - roads2_rule_1.append(line_symbolizer(roads2_rule_stk_1)); - roads2_style_1.add_rule(roads2_rule_1); - + { + rule r; + r.set_filter(parse_expression("[CLASS] = 2")); + { + line_symbolizer line_sym; + put(line_sym,keys::stroke,color(171,158,137)); + put(line_sym,keys::stroke_width,4.0); + put(line_sym,keys::stroke_linecap,ROUND_CAP); + put(line_sym,keys::stroke_linejoin,ROUND_JOIN); + r.append(std::move(line_sym)); + } + roads2_style_1.add_rule(r); + } m.insert_style("road-border", roads2_style_1); feature_type_style roads2_style_2; - rule roads2_rule_2; - roads2_rule_2.set_filter(parse_expression("[CLASS] = 2")); - stroke roads2_rule_stk_2(color(255,250,115),2.0); - roads2_rule_stk_2.set_line_cap(ROUND_CAP); - roads2_rule_stk_2.set_line_join(ROUND_JOIN); - roads2_rule_2.append(line_symbolizer(roads2_rule_stk_2)); - roads2_style_2.add_rule(roads2_rule_2); - + { + rule r; + r.set_filter(parse_expression("[CLASS] = 2")); + { + line_symbolizer line_sym; + put(line_sym,keys::stroke,color(255,250,115)); + put(line_sym,keys::stroke_width,2.0); + put(line_sym,keys::stroke_linecap,ROUND_CAP); + put(line_sym,keys::stroke_linejoin,ROUND_JOIN); + r.append(std::move(line_sym)); + } + roads2_style_2.add_rule(r); + } m.insert_style("road-fill", roads2_style_2); // Roads 1 (The big orange ones, the highways) feature_type_style roads1_style_1; - rule roads1_rule_1; - roads1_rule_1.set_filter(parse_expression("[CLASS] = 1")); - stroke roads1_rule_stk_1(color(188,149,28),7.0); - roads1_rule_stk_1.set_line_cap(ROUND_CAP); - roads1_rule_stk_1.set_line_join(ROUND_JOIN); - roads1_rule_1.append(line_symbolizer(roads1_rule_stk_1)); - roads1_style_1.add_rule(roads1_rule_1); + { + rule r; + r.set_filter(parse_expression("[CLASS] = 1")); + { + line_symbolizer line_sym; + put(line_sym,keys::stroke,color(188,149,28)); + put(line_sym,keys::stroke_width,7.0); + put(line_sym,keys::stroke_linecap,ROUND_CAP); + put(line_sym,keys::stroke_linejoin,ROUND_JOIN); + r.append(std::move(line_sym)); + } + roads1_style_1.add_rule(r); + } m.insert_style("highway-border", roads1_style_1); feature_type_style roads1_style_2; - rule roads1_rule_2; - roads1_rule_2.set_filter(parse_expression("[CLASS] = 1")); - stroke roads1_rule_stk_2(color(242,191,36),5.0); - roads1_rule_stk_2.set_line_cap(ROUND_CAP); - roads1_rule_stk_2.set_line_join(ROUND_JOIN); - roads1_rule_2.append(line_symbolizer(roads1_rule_stk_2)); - roads1_style_2.add_rule(roads1_rule_2); + { + rule r; + r.set_filter(parse_expression("[CLASS] = 1")); + { + line_symbolizer line_sym; + put(line_sym,keys::stroke,color(242,191,36)); + put(line_sym,keys::stroke_width,5.0); + put(line_sym,keys::stroke_linecap,ROUND_CAP); + put(line_sym,keys::stroke_linejoin,ROUND_JOIN); + r.append(std::move(line_sym)); + } + roads1_style_2.add_rule(r); + } m.insert_style("highway-fill", roads1_style_2); + // Populated Places + feature_type_style popplaces_style; + { + rule r; + { + text_symbolizer text_sym; + text_placements_ptr placement_finder = std::make_shared(); + placement_finder->defaults.format->face_name = "DejaVu Sans Book"; + placement_finder->defaults.format->text_size = 10; + placement_finder->defaults.format->fill = color(0,0,0); + placement_finder->defaults.format->halo_fill = color(255,255,200); + placement_finder->defaults.format->halo_radius = 1; + placement_finder->defaults.set_old_style_expression(parse_expression("[GEONAME]")); + put(text_sym, keys::text_placements_, placement_finder); + r.append(std::move(text_sym)); + } + popplaces_style.add_rule(r); + } + + m.insert_style("popplaces",popplaces_style ); + // layers // Provincial polygons { parameters p; p["type"]="shape"; - p["file"]="../../../demo/data/boundaries"; + p["file"]="demo/data/boundaries"; + p["encoding"]="latin1"; layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance().create(p)); lyr.add_style("provinces"); + lyr.set_srs(srs_lcc); m.add_layer(lyr); } @@ -142,9 +213,10 @@ void prepare_map(Map& m) { parameters p; p["type"]="shape"; - p["file"]="../../../demo/data/qcdrainage"; + p["file"]="demo/data/qcdrainage"; layer lyr("Quebec Hydrography"); lyr.set_datasource(datasource_cache::instance().create(p)); + lyr.set_srs(srs_lcc); lyr.add_style("drainage"); m.add_layer(lyr); } @@ -152,10 +224,10 @@ void prepare_map(Map& m) { parameters p; p["type"]="shape"; - p["file"]="../../../demo/data/ontdrainage"; - + p["file"]="demo/data/ontdrainage"; layer lyr("Ontario Hydrography"); lyr.set_datasource(datasource_cache::instance().create(p)); + lyr.set_srs(srs_lcc); lyr.add_style("drainage"); m.add_layer(lyr); } @@ -164,8 +236,9 @@ void prepare_map(Map& m) { parameters p; p["type"]="shape"; - p["file"]="../../../demo/data/boundaries_l"; + p["file"]="demo/data/boundaries_l"; layer lyr("Provincial borders"); + lyr.set_srs(srs_lcc); lyr.set_datasource(datasource_cache::instance().create(p)); lyr.add_style("provlines"); m.add_layer(lyr); @@ -175,8 +248,9 @@ void prepare_map(Map& m) { parameters p; p["type"]="shape"; - p["file"]="../../../demo/data/roads"; + p["file"]="demo/data/roads"; layer lyr("Roads"); + lyr.set_srs(srs_lcc); lyr.set_datasource(datasource_cache::instance().create(p)); lyr.add_style("smallroads"); lyr.add_style("road-border"); @@ -186,6 +260,18 @@ void prepare_map(Map& m) m.add_layer(lyr); } + // popplaces + { + parameters p; + p["type"]="shape"; + p["file"]="demo/data/popplaces"; + p["encoding"] = "latin1"; + layer lyr("Populated Places"); + lyr.set_srs(srs_lcc); + lyr.set_datasource(datasource_cache::instance().create(p)); + lyr.add_style("popplaces"); + m.add_layer(lyr); + } } void render_to_file(Map const& m, const std::string output_filename) @@ -195,17 +281,12 @@ void render_to_file(Map const& m, const std::string output_filename) if(output_stream) { typedef svg_renderer > svg_ren; - std::ostream_iterator output_stream_iterator(output_stream); - svg_ren renderer(m, output_stream_iterator); renderer.apply(); - output_stream.close(); - fs::path output_filename_path = fs::system_complete(fs::path(".")) / fs::path(output_filename); - BOOST_CHECK_MESSAGE(fs::exists(output_filename_path), "File '"+output_filename_path.string()+"' was created."); } @@ -217,13 +298,16 @@ void render_to_file(Map const& m, const std::string output_filename) BOOST_AUTO_TEST_CASE(path_element_test_case_1) { + std::cout << " looking for 'shape.input' plugin in ./plugins/input/" << "\n"; + datasource_cache::instance().register_datasources("plugins/input/"); Map m(800,600); - m.set_background(parse_color("steelblue")); - + m.set_background(parse_color("white")); + m.set_srs(srs_merc); prepare_map(m); - - //m.zoom_to_box(box2d(1405120.04127408, -247003.813399447, - //1706357.31328276, -25098.593149577)); - m.zoom_all(); + m.zoom_to_box(box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855)); render_to_file(m, "path_element_test_case_1.svg"); + mapnik::image_32 buf(m.width(),m.height()); + mapnik::agg_renderer ren(m,buf); + ren.apply(); + mapnik::save_to_file(buf,"path_element_test_case_1.png"); } From b492437505b646de91f3d9b78335ceaf28a31060 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 11 Dec 2013 07:27:51 -0800 Subject: [PATCH 04/10] avoid dereferencing pointer more than once --- plugins/input/shape/shapefile.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/input/shape/shapefile.hpp b/plugins/input/shape/shapefile.hpp index 55478b5e5..f27a43a74 100644 --- a/plugins/input/shape/shapefile.hpp +++ b/plugins/input/shape/shapefile.hpp @@ -167,7 +167,7 @@ public: if (memory) { mapped_region_ = *memory; - file_.buffer(static_cast((*memory)->get_address()),(*memory)->get_size()); + file_.buffer(static_cast(mapped_region_->get_address()),mapped_region_->get_size()); } else { From 7cf452da77206e8fdfcb64062d2fd2c0ea84ccc0 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 11 Dec 2013 13:56:11 -0500 Subject: [PATCH 05/10] generic ```to_integral``` helper function (convert strongly typed enumeration values to underlying type) --- include/mapnik/symbolizer.hpp | 7 ++++++- src/symbolizer_keys.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 44ed70f4f..9bc8dba49 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -370,11 +370,16 @@ boost::optional get_optional(symbolizer_base const& sym, keys key) return boost::optional(); } +template +constexpr auto to_integral(Enum e) -> typename std::underlying_type::type +{ + return static_cast::type>(e); +} + typedef std::tuple > property_meta_type; property_meta_type const& get_meta(mapnik::keys key); mapnik::keys get_key(std::string const& name); - // concrete symbolizer types struct MAPNIK_DECL point_symbolizer : public symbolizer_base {}; struct MAPNIK_DECL line_symbolizer : public symbolizer_base {}; diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index f553fb622..ec15d3efd 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -101,13 +101,13 @@ mapnik::keys get_key(std::string const& name) { std::string name_copy(name); boost::algorithm::replace_all(name_copy,"_","-"); - for (unsigned i=0;i(keys::MAX_SYMBOLIZER_KEY);++i) + for (unsigned i=0; i< to_integral(keys::MAX_SYMBOLIZER_KEY) ; ++i) { - property_meta_type const& item = key_meta[i]; - if (name_copy == std::get<0>(item)) - { - return static_cast(i); - } + property_meta_type const& item = key_meta[i]; + if (name_copy == std::get<0>(item)) + { + return static_cast(i); + } } throw std::runtime_error("no key found for '" + name + "'"); return static_cast(0); From d5a0537471dbb1bd97943051134de759fbf9265b Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 11 Dec 2013 13:57:42 -0500 Subject: [PATCH 06/10] convert json value into symbolizer_base::value_type --- include/mapnik/json/symbolizer_grammar.hpp | 47 +++++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/include/mapnik/json/symbolizer_grammar.hpp b/include/mapnik/json/symbolizer_grammar.hpp index a2e36cbf4..040d6e1c3 100644 --- a/include/mapnik/json/symbolizer_grammar.hpp +++ b/include/mapnik/json/symbolizer_grammar.hpp @@ -40,6 +40,44 @@ namespace fusion = boost::fusion; namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; +template +struct json_value_visitor : boost::static_visitor<> +{ + json_value_visitor(Symbolizer & sym, mapnik::keys key) + : sym_(sym), key_(key) {} + + void operator() (value_bool val) const + { + put(sym_, key_, val); + } + + void operator() (value_integer val) const + { + put(sym_, key_, val); + } + + void operator() (value_double val) const + { + put(sym_, key_, val); + } + + void operator() (std::string const& val) const + { + std::cerr << std::get<0>(get_meta(key_)) << ":" << val << std::endl; + put(sym_, key_, val); + } + + template + void operator() (T const& val) const + { + std::cerr << std::get<0>(get_meta(key_)) << ":" << val << std::endl; + //put(sym_, key_, val); + } + + Symbolizer & sym_; + keys key_; +}; + template struct put_property_visitor : boost::static_visitor<> { @@ -51,8 +89,7 @@ struct put_property_visitor : boost::static_visitor<> template void operator() (Symbolizer & sym) const { - std::cerr << std::get<0>(get_meta(key_)) << ":" << val_ << std::endl; - // put(sym, key_, val_); + boost::apply_visitor(json_value_visitor(sym, key_), val_); } keys key_; @@ -62,8 +99,6 @@ struct put_property_visitor : boost::static_visitor<> struct put_property { typedef void result_type; - //explicit put_property(mapnik::transcoder const& tr) - // : tr_(tr) {} template result_type operator() (T0 & sym, T1 const& name, T2 const& val) const { @@ -76,12 +111,12 @@ struct put_property std::cerr << err.what() << std::endl; } } -// mapnik::transcoder const& tr_; }; template struct symbolizer_grammar : qi::grammar { + typedef boost::variant json_value_type; symbolizer_grammar(generic_json & json) : symbolizer_grammar::base_type(sym, "symbolizer"), json_(json) @@ -171,7 +206,7 @@ struct symbolizer_grammar : qi::grammar // symbolizer qi::rule sym; qi::rule, void(mapnik::symbolizer&),space_type> property; - qi::rule, space_type> property_value; + qi::rule property_value; phoenix::function put_property_; // error From f21152a6a96563420da4ba82328f2639c4333252 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 11 Dec 2013 17:08:33 -0500 Subject: [PATCH 07/10] register target type for symbolizer properties --- include/mapnik/symbolizer.hpp | 26 +++++++- src/symbolizer_keys.cpp | 122 +++++++++++++++++----------------- 2 files changed, 86 insertions(+), 62 deletions(-) diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 9bc8dba49..0a00b223a 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -100,6 +100,30 @@ struct MAPNIK_DECL symbolizer_base cont_type properties; }; +// symbolizer properties target types +enum class property_types : std::uint8_t +{ + target_bool = 1, + target_double, + target_integer, + target_color, + target_comp_op, + target_line_cap, + target_line_join, + target_line_rasterizer, + target_halo_rasterizer, + target_point_placement, + target_pattern_alignment, + target_debug_symbolizer_mode, + target_marker_placement, + target_marker_multi_policy, + target_string, + target_transform, + target_placement, + target_dash_array, + target_colorizer +}; + inline bool operator==(symbolizer_base const& lhs, symbolizer_base const& rhs) { return lhs.properties.size() == rhs.properties.size() && @@ -376,7 +400,7 @@ constexpr auto to_integral(Enum e) -> typename std::underlying_type::type return static_cast::type>(e); } -typedef std::tuple > property_meta_type; +typedef std::tuple, property_types> property_meta_type; property_meta_type const& get_meta(mapnik::keys key); mapnik::keys get_key(std::string const& name); diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index ec15d3efd..c7a41cd53 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -30,66 +30,66 @@ namespace mapnik { -// tuple -> name, default value, enumeration to string converter lambda -static const property_meta_type key_meta[static_cast(keys::MAX_SYMBOLIZER_KEY)] = +// tuple -> name, default value, enumeration to string converter lambda, target property type +static const property_meta_type key_meta[to_integral(keys::MAX_SYMBOLIZER_KEY)] = { - property_meta_type{ "gamma", 1.0, nullptr}, - property_meta_type{ "gamma-method", static_cast(GAMMA_POWER), nullptr}, - property_meta_type{ "opacity", 1.0, nullptr}, + property_meta_type{ "gamma", 1.0, nullptr, property_types::target_double}, + property_meta_type{ "gamma-method", static_cast(GAMMA_POWER), nullptr, property_types::target_integer}, + property_meta_type{ "opacity", 1.0, nullptr, property_types::target_double}, property_meta_type{ "alignment", enumeration_wrapper(LOCAL_ALIGNMENT), - [](enumeration_wrapper e) { return enumeration(pattern_alignment_enum(e.value)).as_string();}}, - property_meta_type{ "offset", 0.0, nullptr}, + [](enumeration_wrapper e) { return enumeration(pattern_alignment_enum(e.value)).as_string();}, property_types::target_pattern_alignment}, + property_meta_type{ "offset", 0.0, nullptr, property_types::target_double}, property_meta_type{ "comp-op", enumeration_wrapper(src_over), - [](enumeration_wrapper e) { return *comp_op_to_string(composite_mode_e(e.value)); }}, - property_meta_type{ "clip", false, nullptr}, - property_meta_type{ "fill", mapnik::color("gray"), nullptr}, - property_meta_type{ "fill-opacity", 1.0 , nullptr}, - property_meta_type{ "stroke", mapnik::color("black"), nullptr}, - property_meta_type{ "stroke-width", 1.0 , nullptr}, - property_meta_type{ "stroke-opacity", 1.0, nullptr}, + [](enumeration_wrapper e) { return *comp_op_to_string(composite_mode_e(e.value)); }, property_types::target_comp_op}, + property_meta_type{ "clip", false, nullptr, property_types::target_bool}, + property_meta_type{ "fill", mapnik::color("gray"), nullptr, property_types::target_color}, + property_meta_type{ "fill-opacity", 1.0 , nullptr, property_types::target_double}, + property_meta_type{ "stroke", mapnik::color("black"), nullptr, property_types::target_color}, + property_meta_type{ "stroke-width", 1.0 , nullptr, property_types::target_double}, + property_meta_type{ "stroke-opacity", 1.0, nullptr, property_types::target_double}, property_meta_type{ "stroke-linejoin", enumeration_wrapper(MITER_JOIN), - [](enumeration_wrapper e) { return enumeration(line_join_enum(e.value)).as_string();}}, + [](enumeration_wrapper e) { return enumeration(line_join_enum(e.value)).as_string();}, property_types::target_double }, property_meta_type{ "stroke-linecap", enumeration_wrapper(BUTT_CAP), - [](enumeration_wrapper e) { return enumeration(line_cap_enum(e.value)).as_string();}}, - property_meta_type{ "stroke-gamma", 1.0, nullptr}, - property_meta_type{ "stroke-gamma-method",static_cast(GAMMA_POWER), nullptr}, - property_meta_type{ "stroke-dashoffset", static_cast(0), nullptr}, - property_meta_type{ "stroke-dasharray", false, nullptr}, - property_meta_type{ "stroke-miterlimit", 4.0, nullptr}, - property_meta_type{ "geometry-transform", false, nullptr}, + [](enumeration_wrapper e) { return enumeration(line_cap_enum(e.value)).as_string();}, property_types::target_double }, + property_meta_type{ "stroke-gamma", 1.0, nullptr, property_types::target_double }, + property_meta_type{ "stroke-gamma-method",static_cast(GAMMA_POWER), nullptr, property_types::target_double }, + property_meta_type{ "stroke-dashoffset", static_cast(0), nullptr, property_types::target_double }, + property_meta_type{ "stroke-dasharray", false, nullptr, property_types::target_double }, + property_meta_type{ "stroke-miterlimit", 4.0, nullptr, property_types::target_double }, + property_meta_type{ "geometry-transform", false, nullptr, property_types::target_transform }, property_meta_type{ "line-rasterizer", enumeration_wrapper(RASTERIZER_FULL), - [](enumeration_wrapper e) { return enumeration(line_rasterizer_enum(e.value)).as_string();}}, - property_meta_type{ "transform", false, nullptr}, - property_meta_type{ "spacing", 0.0, nullptr}, - property_meta_type{ "max-error", 0.0, nullptr}, - property_meta_type{ "allow-overlap",false, nullptr}, - property_meta_type{ "ignore-placement", false, nullptr}, - property_meta_type{ "width",static_cast(0), nullptr}, - property_meta_type{ "height",static_cast(0), nullptr}, - property_meta_type{ "file", "", nullptr}, - property_meta_type{ "shield-dx", 0.0, nullptr}, - property_meta_type{ "shield-dy", 0.0, nullptr}, - property_meta_type{ "unlock-image",false, nullptr}, - property_meta_type{ "text-opacity", 1.0, nullptr}, - property_meta_type{ "mode",false, nullptr}, - property_meta_type{ "scaling", 1.0, nullptr}, - property_meta_type{ "filter-factor", 1.0, nullptr}, - property_meta_type{ "mesh-size", static_cast(0), nullptr}, - property_meta_type{ "premultiplied", false, nullptr}, - property_meta_type{ "smooth", false, nullptr}, + [](enumeration_wrapper e) { return enumeration(line_rasterizer_enum(e.value)).as_string();}, property_types::target_double }, + property_meta_type{ "transform", false, nullptr, property_types::target_transform }, + property_meta_type{ "spacing", 0.0, nullptr, property_types::target_double }, + property_meta_type{ "max-error", 0.0, nullptr, property_types::target_double }, + property_meta_type{ "allow-overlap",false, nullptr, property_types::target_bool }, + property_meta_type{ "ignore-placement", false, nullptr, property_types::target_bool }, + property_meta_type{ "width",static_cast(0), nullptr, property_types::target_double }, + property_meta_type{ "height",static_cast(0), nullptr, property_types::target_double }, + property_meta_type{ "file", "", nullptr, property_types::target_string }, + property_meta_type{ "shield-dx", 0.0, nullptr, property_types::target_double }, + property_meta_type{ "shield-dy", 0.0, nullptr, property_types::target_double }, + property_meta_type{ "unlock-image",false, nullptr, property_types::target_bool }, + property_meta_type{ "text-opacity", 1.0, nullptr, property_types::target_double }, + property_meta_type{ "mode",false, nullptr, property_types::target_double }, + property_meta_type{ "scaling", 1.0, nullptr, property_types::target_double }, + property_meta_type{ "filter-factor", 1.0, nullptr, property_types::target_double }, + property_meta_type{ "mesh-size", static_cast(0), nullptr, property_types::target_double }, + property_meta_type{ "premultiplied", false, nullptr, property_types::target_bool }, + property_meta_type{ "smooth", false, nullptr, property_types::target_double }, property_meta_type{ "simplify-algorithm", enumeration_wrapper(radial_distance), - [](enumeration_wrapper e) { return *simplify_algorithm_to_string(simplify_algorithm_e(e.value));}}, - property_meta_type{ "simplify-tolerance", 0.0, nullptr}, + [](enumeration_wrapper e) { return *simplify_algorithm_to_string(simplify_algorithm_e(e.value));}, property_types::target_double }, + property_meta_type{ "simplify-tolerance", 0.0, nullptr, property_types::target_double }, property_meta_type{ "halo-rasterizer", enumeration_wrapper(HALO_RASTERIZER_FULL), - [](enumeration_wrapper e) { return enumeration(halo_rasterizer_enum(e.value)).as_string();}}, - property_meta_type{ "text-placements", false, nullptr}, + [](enumeration_wrapper e) { return enumeration(halo_rasterizer_enum(e.value)).as_string();}, property_types::target_double }, + property_meta_type{ "text-placements", false, nullptr, property_types::target_double }, property_meta_type{ "placement", enumeration_wrapper(MARKER_POINT_PLACEMENT), - [](enumeration_wrapper e) { return enumeration(marker_placement_enum(e.value)).as_string();}}, // FIXME - rename to "markers-placement-type" + [](enumeration_wrapper e) { return enumeration(marker_placement_enum(e.value)).as_string();}, property_types::target_double }, // FIXME - rename to "markers-placement-type" property_meta_type{ "multi-policy", enumeration_wrapper(MARKER_EACH_MULTI), - [](enumeration_wrapper e) { return enumeration(marker_multi_policy_enum(e.value)).as_string();}}, // FIXME - better naming ^^ + [](enumeration_wrapper e) { return enumeration(marker_multi_policy_enum(e.value)).as_string();}, property_types::target_double }, // FIXME - better naming ^^ property_meta_type{ "placement", enumeration_wrapper(CENTROID_POINT_PLACEMENT), - [](enumeration_wrapper e) { return enumeration(point_placement_enum(e.value)).as_string();}}, - property_meta_type{ "raster-colorizer", nullptr, nullptr } + [](enumeration_wrapper e) { return enumeration(point_placement_enum(e.value)).as_string();}, property_types::target_double }, + property_meta_type{ "raster-colorizer", nullptr, nullptr, property_types::target_colorizer} }; property_meta_type const& get_meta(mapnik::keys key) @@ -99,18 +99,18 @@ property_meta_type const& get_meta(mapnik::keys key) mapnik::keys get_key(std::string const& name) { - std::string name_copy(name); - boost::algorithm::replace_all(name_copy,"_","-"); - for (unsigned i=0; i< to_integral(keys::MAX_SYMBOLIZER_KEY) ; ++i) - { - property_meta_type const& item = key_meta[i]; - if (name_copy == std::get<0>(item)) - { - return static_cast(i); - } - } - throw std::runtime_error("no key found for '" + name + "'"); - return static_cast(0); + std::string name_copy(name); + boost::algorithm::replace_all(name_copy,"_","-"); + for (unsigned i=0; i< to_integral(keys::MAX_SYMBOLIZER_KEY) ; ++i) + { + property_meta_type const& item = key_meta[i]; + if (name_copy == std::get<0>(item)) + { + return static_cast(i); + } + } + throw std::runtime_error("no key found for '" + name + "'"); + return static_cast(0); } } From 5dae2999b1808f3e99e60c5e2e968a1080e51996 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 11 Dec 2013 17:26:36 -0500 Subject: [PATCH 08/10] symbolizers: set_property helper --- include/mapnik/json/symbolizer_grammar.hpp | 4 +- include/mapnik/symbolizer_utils.hpp | 68 +++++++++++++++++++++- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/include/mapnik/json/symbolizer_grammar.hpp b/include/mapnik/json/symbolizer_grammar.hpp index 040d6e1c3..89a0cf25f 100644 --- a/include/mapnik/json/symbolizer_grammar.hpp +++ b/include/mapnik/json/symbolizer_grammar.hpp @@ -30,6 +30,7 @@ // mapnik #include +#include #include namespace mapnik { namespace json { @@ -63,8 +64,7 @@ struct json_value_visitor : boost::static_visitor<> void operator() (std::string const& val) const { - std::cerr << std::get<0>(get_meta(key_)) << ":" << val << std::endl; - put(sym_, key_, val); + set_property(sym_, key_, val); } template diff --git a/include/mapnik/symbolizer_utils.hpp b/include/mapnik/symbolizer_utils.hpp index 4ec6c69e6..5d57431cd 100644 --- a/include/mapnik/symbolizer_utils.hpp +++ b/include/mapnik/symbolizer_utils.hpp @@ -24,9 +24,10 @@ #define MAPNIK_SYMBOLIZER_UTILS_HPP // mapnik -#include -#include #include +#include +#include +#include // boost #include @@ -180,7 +181,7 @@ public: std::ostringstream ss; if (expr) { - ss << '\"' << mapnik::to_expression_string(*expr) << '\"'; + ss << '\"' << "FIXME" /*mapnik::to_expression_string(*expr)*/ << '\"'; } return ss.str(); } @@ -239,6 +240,67 @@ struct symbolizer_to_json : public boost::static_visitor } }; +namespace { + +template +struct set_property_impl +{ + static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val) + { + std::cerr << "do nothing" << std::endl; + } +}; + +template +struct set_property_impl > +{ + static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val) + { + put(sym, key, mapnik::parse_color(val)); + } +}; + +template +struct set_property_impl > +{ + static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val) + { + std::cerr << " expects double" << std::endl; + } +}; + +template +struct set_property_impl > +{ + static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val) + { + std::cerr << " expects bool" << std::endl; + } +}; + +} + +template +inline void set_property(Symbolizer & sym, mapnik::keys key, T const& val) +{ + switch (std::get<3>(get_meta(key))) + { + case property_types::target_bool: + set_property_impl >::apply(sym,key,val); + break; + case property_types::target_integer: + set_property_impl >::apply(sym,key,val); + break; + case property_types::target_double: + set_property_impl >::apply(sym,key,val); + break; + case property_types::target_color: + set_property_impl >::apply(sym,key,val); + break; + default: + break; + } +} } From c02a1c5f0409e5675f25af2ed87dfc07ad982bcb Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 13 Dec 2013 06:22:53 -0800 Subject: [PATCH 09/10] avoid signed comparison warning in symbolizer test --- tests/cpp_tests/symbolizer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpp_tests/symbolizer_test.cpp b/tests/cpp_tests/symbolizer_test.cpp index 7f077cc6d..0fb103be3 100644 --- a/tests/cpp_tests/symbolizer_test.cpp +++ b/tests/cpp_tests/symbolizer_test.cpp @@ -23,7 +23,7 @@ int main(int argc, char** argv) BOOST_TEST_EQ(policy_in,MARKER_WHOLE_MULTI); markers_symbolizer sym; put(sym, keys::markers_multipolicy, policy_in); - BOOST_TEST_EQ(sym.properties.count(keys::markers_multipolicy),1); + BOOST_TEST_EQ(sym.properties.count(keys::markers_multipolicy),static_cast(1)); marker_multi_policy_enum policy_out = get(sym, keys::markers_multipolicy); BOOST_TEST_EQ(policy_out,MARKER_WHOLE_MULTI); } catch (...) { From e7e60cb541d6bb03e706dc6718929275247214b0 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 13 Dec 2013 06:23:03 -0800 Subject: [PATCH 10/10] Revert "don't set -stdlib in CXXGLAGS" This reverts commit 62c06eabcc18cfb8a63ee764ccbe4d86bb90eefc. --- SConstruct | 1 + 1 file changed, 1 insertion(+) diff --git a/SConstruct b/SConstruct index 7108350a7..0dd75f130 100644 --- a/SConstruct +++ b/SConstruct @@ -1160,6 +1160,7 @@ if not preconfigured: # set any custom cxxflags and ldflags to come first if sys.platform == 'darwin' and not env['HOST']: + DEFAULT_CXX11_CXXFLAGS += ' -stdlib=libc++' DEFAULT_CXX11_LINKFLAGS = ' -stdlib=libc++' env.Append(CPPDEFINES = env['CUSTOM_DEFINES']) env.Append(CXXFLAGS = DEFAULT_CXX11_CXXFLAGS)