diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp index 2bf7e78cb..90a9d1512 100644 --- a/bindings/python/mapnik_feature.cpp +++ b/bindings/python/mapnik_feature.cpp @@ -47,6 +47,11 @@ namespace boost { namespace python { { return ::PyUnicode_FromWideChar((wchar_t*)s.getBuffer(),implicit_cast(s.length())); } + + PyObject * operator() (mapnik::value_null const& s) const + { + return NULL; + } }; struct mapnik_value_to_python diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index a750cd1ad..518b6f90a 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -120,11 +120,6 @@ namespace mapnik { return props_.end(); } - bool exists(const std::string &k) const - { - return props_.find(k) != props_.end(); - } - std::string to_string() const { std::stringstream ss; diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 344645b84..e2858ab3d 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -39,14 +39,18 @@ namespace mapnik { - typedef boost::variant value_base; + struct value_null + { + }; + + typedef boost::variant value_base; namespace impl { struct equals : public boost::static_visitor { template - bool operator() (const T &, const U & ) const + bool operator() (const T &, const U &) const { return false; } @@ -72,19 +76,73 @@ namespace mapnik { { return lhs == rhs; } + + bool operator() (value_null, value_null) const + { + return false; + } }; + struct not_equals + : public boost::static_visitor + { + template + bool operator() (const T &, const U &) const + { + return true; + } + + template + bool operator() (T lhs, T rhs) const + { + return lhs != rhs; + } + + bool operator() (int lhs, double rhs) const + { + return lhs != rhs; + } + + bool operator() (double lhs, int rhs) const + { + return lhs != rhs; + } + + bool operator() (UnicodeString const& lhs, + UnicodeString const& rhs) const + { + return lhs != rhs; + } + + bool operator() (value_null, value_null) const + { + return false; + } + + template + bool operator() (value_null, const T &) const + { + return false; + } + + template + bool operator() (const T &, value_null) const + { + return false; + } + }; + struct greater_than : public boost::static_visitor { template - bool operator()( const T &, const U & ) const + bool operator()(const T &, const U &) const { return false; } template - bool operator()( T lhs, T rhs ) const + bool operator()(T lhs, T rhs) const { return lhs > rhs; } @@ -103,13 +161,18 @@ namespace mapnik { { return lhs > rhs; } + + bool operator() (value_null, value_null) const + { + return false; + } }; struct greater_or_equal : public boost::static_visitor { template - bool operator()( const T &, const U & ) const + bool operator()(const T &, const U &) const { return false; } @@ -130,23 +193,28 @@ namespace mapnik { return lhs >= rhs; } - bool operator() (UnicodeString const& lhs, UnicodeString const& rhs ) const + bool operator() (UnicodeString const& lhs, UnicodeString const& rhs) const { return lhs >= rhs; } + + bool operator() (value_null, value_null) const + { + return false; + } }; struct less_than : public boost::static_visitor { template - bool operator()( const T &, const U & ) const + bool operator()(const T &, const U &) const { return false; } template - bool operator()( T lhs,T rhs) const + bool operator()(T lhs, T rhs) const { return lhs < rhs; } @@ -161,24 +229,29 @@ namespace mapnik { return lhs < rhs; } - bool operator()( UnicodeString const& lhs, - UnicodeString const& rhs ) const + bool operator()(UnicodeString const& lhs, + UnicodeString const& rhs ) const { return lhs < rhs; } + + bool operator() (value_null, value_null) const + { + return false; + } }; struct less_or_equal : public boost::static_visitor { template - bool operator()( const T &, const U & ) const + bool operator()(const T &, const U &) const { return false; } template - bool operator()(T lhs, T rhs ) const + bool operator()(T lhs, T rhs) const { return lhs <= rhs; } @@ -194,11 +267,16 @@ namespace mapnik { } template - bool operator()( UnicodeString const& lhs, - UnicodeString const& rhs ) const + bool operator()(UnicodeString const& lhs, + UnicodeString const& rhs ) const { return lhs <= rhs; } + + bool operator() (value_null, value_null) const + { + return false; + } }; template @@ -386,7 +464,12 @@ namespace mapnik { ss << std::setprecision(16) << val; return ss.str(); } - }; + + std::string operator() (value_null const& val) const + { + return ""; + } + }; struct to_unicode : public boost::static_visitor { @@ -411,6 +494,11 @@ namespace mapnik { out << std::setprecision(16) << val; return UnicodeString(out.str().c_str()); } + + UnicodeString operator() (value_null const& val) const + { + return UnicodeString(""); + } }; struct to_expression_string : public boost::static_visitor @@ -455,9 +543,14 @@ namespace mapnik { ss << std::setprecision(16) << val; return ss.str(); } + + std::string operator() (value_null const& val) const + { + return "null"; + } }; } - + class value { value_base base_; @@ -468,7 +561,7 @@ namespace mapnik { public: value () - : base_(0) {} + : base_(value_null()) {} template value(T _val_) : base_(_val_) {} @@ -480,7 +573,7 @@ namespace mapnik { bool operator!=(value const& other) const { - return !(boost::apply_visitor(impl::equals(),base_,other.base_)); + return boost::apply_visitor(impl::not_equals(),base_,other.base_); } bool operator>(value const& other) const diff --git a/src/agg_renderer.cpp b/src/agg_renderer.cpp index 98546fbfe..6f29716a0 100644 --- a/src/agg_renderer.cpp +++ b/src/agg_renderer.cpp @@ -456,52 +456,49 @@ namespace mapnik proj_transform const& prj_trans) { typedef coord_transform2 path_type; - if (feature.exists(sym.get_name())) + UnicodeString text = feature[sym.get_name()].to_unicode(); + boost::shared_ptr const& data = sym.get_image(); + if (text.length() > 0 && data) { - UnicodeString text = feature[sym.get_name()].to_unicode(); - boost::shared_ptr const& data = sym.get_image(); - if (text.length() > 0 && data) + face_ptr face = font_manager_.get_face(sym.get_face_name()); + if (face) { - face_ptr face = font_manager_.get_face(sym.get_face_name()); - if (face) + text_renderer ren(pixmap_,face); + ren.set_pixel_size(sym.get_text_size()); + ren.set_fill(sym.get_fill()); + + string_info info(text); + face->get_string_info(info); + + placement_finder finder(detector_); + + unsigned num_geom = feature.num_geometries(); + for (unsigned i=0;i ren(pixmap_,face); - ren.set_pixel_size(sym.get_text_size()); - ren.set_fill(sym.get_fill()); - - string_info info(text); - face->get_string_info(info); - - placement_finder finder(detector_); - - unsigned num_geom = feature.num_geometries(); - for (unsigned i=0;i 0) // don't bother with empty geometries - { - path_type path(t_,geom,prj_trans); - placement text_placement(info, sym); - text_placement.avoid_edges = sym.get_avoid_edges(); - finder.find_point_placements(text_placement,path); + geometry2d const& geom = feature.get_geometry(i); + if (geom.num_points() > 0) // don't bother with empty geometries + { + path_type path(t_,geom,prj_trans); + placement text_placement(info, sym); + text_placement.avoid_edges = sym.get_avoid_edges(); + finder.find_point_placements(text_placement,path); - for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) - { - int w = data->width(); - int h = data->height(); + for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) + { + int w = data->width(); + int h = data->height(); - double x = text_placement.placements[ii].starting_x; - double y = text_placement.placements[ii].starting_y; + double x = text_placement.placements[ii].starting_x; + double y = text_placement.placements[ii].starting_y; - int px=int(x - (w/2)); - int py=int(y - (h/2)); + int px=int(x - (w/2)); + int py=int(y - (h/2)); - pixmap_.set_rectangle_alpha(px,py,*data); + pixmap_.set_rectangle_alpha(px,py,*data); - Envelope dim = ren.prepare_glyphs(&text_placement.placements[ii]); + Envelope dim = ren.prepare_glyphs(&text_placement.placements[ii]); - ren.render(x,y); - } + ren.render(x,y); } } } @@ -668,61 +665,58 @@ namespace mapnik proj_transform const& prj_trans) { typedef coord_transform2 path_type; - - if (feature.exists(sym.get_name())) + + UnicodeString text = feature[sym.get_name()].to_unicode(); + if ( text.length() > 0 ) { - UnicodeString text = feature[sym.get_name()].to_unicode(); - if ( text.length() > 0 ) + Color const& fill = sym.get_fill(); + face_ptr face = font_manager_.get_face(sym.get_face_name()); + if (face) { - Color const& fill = sym.get_fill(); - face_ptr face = font_manager_.get_face(sym.get_face_name()); - if (face) + text_renderer ren(pixmap_,face); + ren.set_pixel_size(sym.get_text_size()); + ren.set_fill(fill); + ren.set_halo_fill(sym.get_halo_fill()); + ren.set_halo_radius(sym.get_halo_radius()); + + placement_finder finder(detector_); + + string_info info(text); + face->get_string_info(info); + unsigned num_geom = feature.num_geometries(); + for (unsigned i=0;i ren(pixmap_,face); - ren.set_pixel_size(sym.get_text_size()); - ren.set_fill(fill); - ren.set_halo_fill(sym.get_halo_fill()); - ren.set_halo_radius(sym.get_halo_radius()); - - placement_finder finder(detector_); - - string_info info(text); - face->get_string_info(info); - unsigned num_geom = feature.num_geometries(); - for (unsigned i=0;i 0) // don't bother with empty geometries { - geometry2d const& geom = feature.get_geometry(i); - if (geom.num_points() > 0) // don't bother with empty geometries + path_type path(t_,geom,prj_trans); + placement text_placement(info,sym); + if (sym.get_label_placement() == POINT_PLACEMENT) { - path_type path(t_,geom,prj_trans); - placement text_placement(info,sym); - if (sym.get_label_placement() == POINT_PLACEMENT) - { - double label_x, label_y, z=0.0; - geom.label_position(&label_x, &label_y); - prj_trans.backward(label_x,label_y, z); - t_.forward(&label_x,&label_y); - finder.find_point_placement(text_placement,label_x,label_y); - } - else //LINE_PLACEMENT - { - finder.find_line_placements(text_placement,path); - } + double label_x, label_y, z=0.0; + geom.label_position(&label_x, &label_y); + prj_trans.backward(label_x,label_y, z); + t_.forward(&label_x,&label_y); + finder.find_point_placement(text_placement,label_x,label_y); + } + else //LINE_PLACEMENT + { + finder.find_line_placements(text_placement,path); + } - for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii) - { - double x = text_placement.placements[ii].starting_x; - double y = text_placement.placements[ii].starting_y; - Envelope dim = ren.prepare_glyphs(&text_placement.placements[ii]); - ren.render(x,y); - } + for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii) + { + double x = text_placement.placements[ii].starting_x; + double y = text_placement.placements[ii].starting_y; + Envelope dim = ren.prepare_glyphs(&text_placement.placements[ii]); + ren.render(x,y); } } - } - else - { - throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); - } + } + } + else + { + throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); } } } diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index d1cda8da1..caa0da6a8 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -750,47 +750,44 @@ namespace mapnik { typedef coord_transform2 path_type; - if (feature.exists(sym.get_name())) + UnicodeString text = feature[sym.get_name()].to_unicode(); + boost::shared_ptr const& data = sym.get_image(); + + if (text.length() > 0 && data) { - UnicodeString text = feature[sym.get_name()].to_unicode(); - boost::shared_ptr const& data = sym.get_image(); + cairo_face_ptr face = face_manager_.get_face(sym.get_face_name()); - if (text.length() > 0 && data) + if (face) { - cairo_face_ptr face = face_manager_.get_face(sym.get_face_name()); + cairo_context context(context_); - if (face) + context.set_font_face(face); + + string_info info(text); + + face->get_string_info(sym.get_text_size(), info); + + placement_finder finder(detector_); + + for (unsigned i = 0; i < feature.num_geometries(); ++i) { - cairo_context context(context_); + geometry2d const& geom = feature.get_geometry(i); - context.set_font_face(face); - - string_info info(text); - - face->get_string_info(sym.get_text_size(), info); - - placement_finder finder(detector_); - - for (unsigned i = 0; i < feature.num_geometries(); ++i) + if (geom.num_points() > 0) // don't bother with empty geometries { - geometry2d const& geom = feature.get_geometry(i); + path_type path(t_, geom, prj_trans); + placement text_placement(info, sym); - if (geom.num_points() > 0) // don't bother with empty geometries + text_placement.avoid_edges = sym.get_avoid_edges(); + finder.find_point_placements(text_placement, path); + + for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) { - path_type path(t_, geom, prj_trans); - placement text_placement(info, sym); + double shield_x = text_placement.placements[ii].starting_x - data->width() / 2; + double shield_y = text_placement.placements[ii].starting_y - data->height() / 2; - text_placement.avoid_edges = sym.get_avoid_edges(); - finder.find_point_placements(text_placement, path); - - for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) - { - double shield_x = text_placement.placements[ii].starting_x - data->width() / 2; - double shield_y = text_placement.placements[ii].starting_y - data->height() / 2; - - context.add_image(shield_x, shield_y, *data); - context.add_text(sym, text_placement.placements[ii], face); - } + context.add_image(shield_x, shield_y, *data); + context.add_text(sym, text_placement.placements[ii], face); } } } @@ -927,60 +924,57 @@ namespace mapnik { typedef coord_transform2 path_type; - if (feature.exists(sym.get_name())) + UnicodeString text = feature[sym.get_name()].to_unicode(); + + if (text.length() > 0) { - UnicodeString text = feature[sym.get_name()].to_unicode(); + cairo_face_ptr face = face_manager_.get_face(sym.get_face_name()); - if (text.length() > 0) + if (face) { - cairo_face_ptr face = face_manager_.get_face(sym.get_face_name()); + cairo_context context(context_); - if (face) + context.set_font_face(face); + + string_info info(text); + + face->get_string_info(sym.get_text_size(), info); + + placement_finder finder(detector_); + + for (unsigned i = 0; i < feature.num_geometries(); ++i) { - cairo_context context(context_); + geometry2d const& geom = feature.get_geometry(i); - context.set_font_face(face); - - string_info info(text); - - face->get_string_info(sym.get_text_size(), info); - - placement_finder finder(detector_); - - for (unsigned i = 0; i < feature.num_geometries(); ++i) + if (geom.num_points() > 0) // don't bother with empty geometries { - geometry2d const& geom = feature.get_geometry(i); + path_type path(t_, geom, prj_trans); + placement text_placement(info, sym); - if (geom.num_points() > 0) // don't bother with empty geometries + if (sym.get_label_placement() == POINT_PLACEMENT) { - path_type path(t_, geom, prj_trans); - placement text_placement(info, sym); + double label_x, label_y, z = 0.0; - if (sym.get_label_placement() == POINT_PLACEMENT) - { - double label_x, label_y, z = 0.0; + geom.label_position(&label_x, &label_y); + prj_trans.backward(label_x, label_y, z); + t_.forward(&label_x, &label_y); + finder.find_point_placement(text_placement, label_x, label_y); + } + else //LINE_PLACEMENT + { + finder.find_line_placements(text_placement, path); + } - geom.label_position(&label_x, &label_y); - prj_trans.backward(label_x, label_y, z); - t_.forward(&label_x, &label_y); - finder.find_point_placement(text_placement, label_x, label_y); - } - else //LINE_PLACEMENT - { - finder.find_line_placements(text_placement, path); - } - - for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii) - { - context.add_text(sym, text_placement.placements[ii], face); - } + for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii) + { + context.add_text(sym, text_placement.placements[ii], face); } } } - else - { - throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); - } + } + else + { + throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); } } }