From c1504f874ef66f4f20e9c12b55f10f96958dc648 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 27 Oct 2011 13:24:50 +0100 Subject: [PATCH 1/6] add support for fractional text size ( use FT_Set_Char_Size ) NOTE: ensure it works as expected, currently I see different results from different fonts. --- include/mapnik/font_engine_freetype.hpp | 24 ++++++++++++++++++++++-- include/mapnik/shield_symbolizer.hpp | 4 ++-- include/mapnik/text_placements.hpp | 10 +++++----- include/mapnik/text_symbolizer.hpp | 8 ++++---- src/agg/process_glyph_symbolizer.cpp | 6 +++--- src/agg/process_shield_symbolizer.cpp | 2 +- src/agg/process_text_symbolizer.cpp | 5 +++-- src/cairo_renderer.cpp | 6 +++--- src/glyph_symbolizer.cpp | 2 +- src/grid/process_shield_symbolizer.cpp | 2 +- src/grid/process_text_symbolizer.cpp | 2 +- src/load_map.cpp | 8 ++++---- src/shield_symbolizer.cpp | 4 ++-- src/text_symbolizer.cpp | 8 ++++---- 14 files changed, 56 insertions(+), 35 deletions(-) diff --git a/include/mapnik/font_engine_freetype.hpp b/include/mapnik/font_engine_freetype.hpp index 5754e6471..fcdbb9740 100644 --- a/include/mapnik/font_engine_freetype.hpp +++ b/include/mapnik/font_engine_freetype.hpp @@ -119,7 +119,13 @@ public: { if (! FT_Set_Pixel_Sizes( face_, 0, size )) return true; + return false; + } + bool set_character_sizes(float size) + { + if ( !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0)) + return true; return false; } @@ -184,6 +190,14 @@ public: (*face)->set_pixel_sizes(size); } } + + void set_character_sizes(float size) + { + for (std::vector::iterator face = faces_.begin(); face != faces_.end(); ++face) + { + (*face)->set_character_sizes(size); + } + } private: std::vector faces_; std::map dimension_cache_; @@ -198,7 +212,7 @@ public: void init(double radius) { - FT_Stroker_Set(s_, (FT_Fixed) radius * (1<<6), + FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); @@ -332,11 +346,17 @@ struct text_renderer : private boost::noncopyable halo_radius_(0.0), opacity_(1.0) {} + void set_pixel_size(unsigned size) { faces_->set_pixel_sizes(size); } - + + void set_character_size(float size) + { + faces_->set_character_sizes(size); + } + void set_fill(mapnik::color const& fill) { fill_=fill; diff --git a/include/mapnik/shield_symbolizer.hpp b/include/mapnik/shield_symbolizer.hpp index b8b3bfe47..847bff663 100644 --- a/include/mapnik/shield_symbolizer.hpp +++ b/include/mapnik/shield_symbolizer.hpp @@ -38,11 +38,11 @@ struct MAPNIK_DECL shield_symbolizer : public text_symbolizer, { shield_symbolizer(expression_ptr name, std::string const& face_name, - unsigned size, + float size, color const& fill, path_expression_ptr file); shield_symbolizer(expression_ptr name, - unsigned size, + float size, color const& fill, path_expression_ptr file); diff --git a/include/mapnik/text_placements.hpp b/include/mapnik/text_placements.hpp index 47c088636..383bbcb33 100644 --- a/include/mapnik/text_placements.hpp +++ b/include/mapnik/text_placements.hpp @@ -112,7 +112,7 @@ public: /* NOTE: Values are public and non-virtual to avoid any performance problems. */ position displacement; - unsigned text_size; + float text_size; horizontal_alignment_e halign; justify_alignment_e jalign; vertical_alignment_e valign; @@ -127,9 +127,9 @@ public: text_size_(10), halign_(H_MIDDLE), jalign_(J_MIDDLE), valign_(V_MIDDLE) {} virtual text_placement_info_ptr get_placement_info() const =0; - virtual void set_default_text_size(unsigned size) { text_size_ = size; } - unsigned get_default_text_size() const { return text_size_; } - + virtual void set_default_text_size(float size) { text_size_ = size; } + float get_default_text_size() const { return text_size_; } + virtual void set_default_displacement(position const& displacement) { displacement_ = displacement;} position const& get_default_displacement() { return displacement_; } @@ -144,7 +144,7 @@ public: virtual ~text_placements() {} protected: - unsigned text_size_; + float text_size_; position displacement_; horizontal_alignment_e halign_; justify_alignment_e jalign_; diff --git a/include/mapnik/text_symbolizer.hpp b/include/mapnik/text_symbolizer.hpp index e4d57d8ed..5ad9f7f44 100644 --- a/include/mapnik/text_symbolizer.hpp +++ b/include/mapnik/text_symbolizer.hpp @@ -44,10 +44,10 @@ namespace mapnik struct MAPNIK_DECL text_symbolizer : public symbolizer_base { text_symbolizer(expression_ptr name, std::string const& face_name, - unsigned size, color const& fill, + float size, color const& fill, text_placements_ptr placements = boost::make_shared() ); - text_symbolizer(expression_ptr name, unsigned size, color const& fill, + text_symbolizer(expression_ptr name, float size, color const& fill, text_placements_ptr placements = boost::make_shared() ); text_symbolizer(text_symbolizer const& rhs); @@ -80,8 +80,8 @@ struct MAPNIK_DECL text_symbolizer : public symbolizer_base void set_force_odd_labels(bool force); double get_max_char_angle_delta() const; // maximum change in angle between adjacent characters void set_max_char_angle_delta(double angle); - unsigned get_text_size() const; - void set_text_size(unsigned size); + float get_text_size() const; + void set_text_size(float size); std::string const& get_face_name() const; void set_face_name(std::string face_name); font_set const& get_fontset() const; diff --git a/src/agg/process_glyph_symbolizer.cpp b/src/agg/process_glyph_symbolizer.cpp index 276db2668..4a82cdb4b 100644 --- a/src/agg/process_glyph_symbolizer.cpp +++ b/src/agg/process_glyph_symbolizer.cpp @@ -59,9 +59,9 @@ void agg_renderer::process(glyph_symbolizer const& sym, } // set font size - unsigned size = sym.eval_size(feature); - ren.set_pixel_size(size * scale_factor_); - faces->set_pixel_sizes(size * scale_factor_); + float size = sym.eval_size(feature); + ren.set_character_size(size * scale_factor_); + faces->set_character_sizes(size * scale_factor_); // Get and render text path // diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index 94a9caeec..7d2c02741 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -129,7 +129,7 @@ void agg_renderer::process(shield_symbolizer const& sym, { text_renderer ren(pixmap_, faces, *strk); - ren.set_pixel_size(sym.get_text_size() * scale_factor_); + ren.set_character_size(sym.get_text_size() * scale_factor_); ren.set_fill(sym.get_fill()); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index c45e05c46..f58d73289 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -103,12 +103,13 @@ void agg_renderer::process(text_symbolizer const& sym, throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); } text_renderer ren(pixmap_, faces, *strk); - ren.set_pixel_size(placement_options->text_size * scale_factor_); + + ren.set_character_size(placement_options->text_size * scale_factor_); ren.set_fill(fill); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); ren.set_opacity(sym.get_text_opacity()); - + box2d dims(0,0,width_,height_); placement_finder finder(*detector_,dims); diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 3939d49a6..668c8ebbd 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -1138,7 +1138,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym, placement_finder finder(detector_); - faces->set_pixel_sizes(placement_options->text_size); + faces->set_character_sizes(placement_options->text_size); faces->get_string_info(info); int w = (*marker)->width(); @@ -1466,7 +1466,7 @@ void cairo_renderer_base::process(glyph_symbolizer const& sym, // set font size unsigned size = sym.eval_size(feature); - faces->set_pixel_sizes(size); + faces->set_character_sizes(size); // Get and render text path // @@ -1563,7 +1563,7 @@ void cairo_renderer_base::process(text_symbolizer const& sym, cairo_context context(context_); string_info info(text); - faces->set_pixel_sizes(placement_options->text_size); + faces->set_character_sizes(placement_options->text_size); faces->get_string_info(info); placement_finder finder(detector_); diff --git a/src/glyph_symbolizer.cpp b/src/glyph_symbolizer.cpp index b94bb7766..8ef41c638 100644 --- a/src/glyph_symbolizer.cpp +++ b/src/glyph_symbolizer.cpp @@ -97,7 +97,7 @@ unsigned glyph_symbolizer::eval_size(Feature const& feature) const #ifdef MAPNIK_DEBUG std::clog << "size_result=" << result.to_string() << "\n"; #endif - unsigned size = static_cast(result.to_int()); + float size = static_cast(result.to_double()); #ifdef MAPNIK_DEBUG std::clog << "size=" << size << "\n"; #endif diff --git a/src/grid/process_shield_symbolizer.cpp b/src/grid/process_shield_symbolizer.cpp index 182412f22..d0f61cd67 100644 --- a/src/grid/process_shield_symbolizer.cpp +++ b/src/grid/process_shield_symbolizer.cpp @@ -110,7 +110,7 @@ void grid_renderer::process(shield_symbolizer const& sym, { text_renderer ren(pixmap_, faces, *strk); - ren.set_pixel_size(sym.get_text_size() * scale_factor_ * (1.0/pixmap_.get_resolution())); + ren.set_character_size(sym.get_text_size() * scale_factor_ * (1.0/pixmap_.get_resolution())); ren.set_fill(sym.get_fill()); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 6e3c1b5dc..e88aed6c5 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -77,7 +77,7 @@ void grid_renderer::process(text_symbolizer const& sym, throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); } text_renderer ren(pixmap_, faces, *strk); - ren.set_pixel_size(placement_options->text_size * (scale_factor_ * (1.0/pixmap_.get_resolution()))); + ren.set_character_size(placement_options->text_size * (scale_factor_ * (1.0/pixmap_.get_resolution()))); ren.set_fill(fill); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); diff --git a/src/load_map.cpp b/src/load_map.cpp index 381ac4bdb..9b25dec5f 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -1244,10 +1244,10 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym ) optional fontset_name = get_opt_attr(sym, "fontset-name"); - unsigned size = get_attr(sym, "size", 10U); - + float size = get_attr(sym, "size", 10.0f); + color c = get_attr(sym, "fill", color(0,0,0)); - + text_symbolizer text_symbol = text_symbolizer(parse_expression(name, "utf8"), size, c, placement_finder); optional orientation = get_opt_attr(sym, "orientation"); @@ -1486,7 +1486,7 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym ) optional fontset_name = get_opt_attr(sym, "fontset-name"); - unsigned size = get_attr(sym, "size", 10U); + float size = get_attr(sym, "size", 10.0f); color fill = get_attr(sym, "fill", color(0,0,0)); std::string image_file = get_attr(sym, "file"); diff --git a/src/shield_symbolizer.cpp b/src/shield_symbolizer.cpp index 6ef85788e..fcf54a73e 100644 --- a/src/shield_symbolizer.cpp +++ b/src/shield_symbolizer.cpp @@ -37,7 +37,7 @@ namespace mapnik shield_symbolizer::shield_symbolizer( expression_ptr name, std::string const& face_name, - unsigned size, + float size, color const& fill, path_expression_ptr file) : text_symbolizer(name, face_name, size, fill), @@ -50,7 +50,7 @@ shield_symbolizer::shield_symbolizer( shield_symbolizer::shield_symbolizer( expression_ptr name, - unsigned size, + float size, color const& fill, path_expression_ptr file) : text_symbolizer(name, size, fill), diff --git a/src/text_symbolizer.cpp b/src/text_symbolizer.cpp index 8b2fcf21c..a328c8f58 100644 --- a/src/text_symbolizer.cpp +++ b/src/text_symbolizer.cpp @@ -87,7 +87,7 @@ IMPLEMENT_ENUM( text_transform_e, text_transform_strings ) text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_name, - unsigned size, color const& fill, + float size, color const& fill, text_placements_ptr placements) : symbolizer_base(), name_(name), @@ -120,7 +120,7 @@ text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_na set_text_size(size); } -text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const& fill, +text_symbolizer::text_symbolizer(expression_ptr name, float size, color const& fill, text_placements_ptr placements) : symbolizer_base(), name_(name), @@ -378,12 +378,12 @@ void text_symbolizer::set_max_char_angle_delta(double angle) max_char_angle_delta_ = angle; } -void text_symbolizer::set_text_size(unsigned size) +void text_symbolizer::set_text_size(float size) { placement_options_->set_default_text_size(size); } -unsigned text_symbolizer::get_text_size() const +float text_symbolizer::get_text_size() const { return placement_options_->get_default_text_size(); } From 8ecde650df7f453e7f9dd3f1207ad02bf7149d52 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 27 Oct 2011 09:00:16 -0700 Subject: [PATCH 2/6] add tests for feature expression bugs - refs #933 and #934 --- tests/python_tests/feature_test.py | 48 ++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/tests/python_tests/feature_test.py b/tests/python_tests/feature_test.py index 828995d3c..982e44c77 100644 --- a/tests/python_tests/feature_test.py +++ b/tests/python_tests/feature_test.py @@ -1,23 +1,24 @@ #encoding: utf8 import itertools import unittest +from nose.tools import * +import mapnik2 +from binascii import unhexlify from utilities import Todo class FeatureTest(unittest.TestCase): def makeOne(self, *args, **kw): - from mapnik2 import Feature - return Feature(*args, **kw) + return mapnik2.Feature(*args, **kw) def test_default_constructor(self): f = self.makeOne(1) self.failUnless(f is not None) def test_python_extended_constructor(self): - from mapnik2 import Box2d f = self.makeOne(1, 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))', foo="bar") self.failUnlessEqual(f['foo'], 'bar') - self.failUnlessEqual(f.envelope(),Box2d(10.0,10.0,45.0,45.0)) + self.failUnlessEqual(f.envelope(),mapnik2.Box2d(10.0,10.0,45.0,45.0)) def test_set_get_properties(self): f = self.makeOne(1) @@ -33,13 +34,12 @@ class FeatureTest(unittest.TestCase): test_val(v) def test_add_wkt_geometry(self): - from mapnik2 import Box2d def add_geom_wkt(wkt): f = self.makeOne(1) self.failUnlessEqual(len(f.geometries()), 0) f.add_geometries_from_wkt(wkt) self.failUnlessEqual(len(f.geometries()), 3) - e = Box2d() + e = mapnik2.Box2d() self.failUnlessEqual(e.valid(), False) for g in f.geometries(): if not e.valid(): @@ -48,13 +48,13 @@ class FeatureTest(unittest.TestCase): e +=g.envelope() self.failUnlessEqual(e, f.envelope()) - from binascii import unhexlify + def add_geom_wkb(wkb): f = self.makeOne(1) self.failUnlessEqual(len(f.geometries()), 0) f.add_geometries_from_wkb(unhexlify(wkb)) self.failUnlessEqual(len(f.geometries()), 1) - e = Box2d() + e = mapnik2.Box2d() self.failUnlessEqual(e.valid(), False) for g in f.geometries(): if not e.valid(): @@ -63,10 +63,40 @@ class FeatureTest(unittest.TestCase): e +=g.envelope() self.failUnlessEqual(e, f.envelope()) + def run() : add_geom_wkt('GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10),POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10)))') add_geom_wkb('010300000001000000050000000000000000003e4000000000000024400000000000002440000000000000344000000000000034400000000000004440000000000000444000000000000044400000000000003e400000000000002440') # POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10)) run() - + + +def test_feature_expression_evaluation(): + f = mapnik2.Feature(1) + f['name'] = 'a' + expr = mapnik2.Expression("[name]='a'") + evaluated = expr.evaluate(f) + eq_(evaluated,True) + num_attributes = len(f) + eq_(num_attributes,1) + eq_(f.id(),1) + +# https://github.com/mapnik/mapnik/issues/933 +def test_feature_expression_evaluation_missing_attr(): + f = mapnik2.Feature(1) + f['name'] = 'a' + expr = mapnik2.Expression("[fielddoesnotexist]='a'") + evaluated = expr.evaluate(f) + eq_(evaluated,True) + num_attributes = len(f) + eq_(num_attributes,1) + eq_(f.id(),1) + +# https://github.com/mapnik/mapnik/issues/934 +def test_feature_expression_evaluation_attr_with_spaces(): + f = mapnik2.Feature(1) + f['name with space'] = 'a' + expr = mapnik2.Expression("[name with space]='a'") + eq_(expr.evaluate(f),True) + if __name__ == "__main__": [eval(run)() for run in dir() if 'test_' in run] From 4b65b7259e8161e93a6db769011e0d168d1eda13 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 27 Oct 2011 18:02:55 +0100 Subject: [PATCH 3/6] avoid creating default initialised values if key doesn't exist --- include/mapnik/attribute.hpp | 15 +++++++++++++-- include/mapnik/feature.hpp | 18 +++++++++++++++++- include/mapnik/metawriter.hpp | 13 ++++++++++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/include/mapnik/attribute.hpp b/include/mapnik/attribute.hpp index 196874392..62b7a2a75 100644 --- a/include/mapnik/attribute.hpp +++ b/include/mapnik/attribute.hpp @@ -23,10 +23,15 @@ #ifndef MAPNIK_ATTRIBUTE_HPP #define MAPNIK_ATTRIBUTE_HPP +// mapnik +#include +// stl #include namespace mapnik { +static mapnik::value _null_value; + struct attribute { std::string name_; @@ -34,9 +39,15 @@ struct attribute : name_(name) {} template - V value(F const& f) const + V const& value(F const& f) const { - return f[name_]; + typedef typename F::const_iterator const_iterator; + const_iterator itr = f.find(name_); + if (itr != f.end()) + { + return itr->second; + } + return _null_value; } std::string const& name() const { return name_;} }; diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 087776799..fd8347a3e 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -65,6 +65,7 @@ private: std::map props_; public: typedef std::map::iterator iterator; + typedef std::map::const_iterator const_iterator; explicit feature(int id) : properties(props_), id_(id), @@ -145,7 +146,7 @@ public: { return props_; } - + iterator begin() { return props_.begin(); @@ -155,7 +156,22 @@ public: { return props_.end(); } + + const_iterator begin() const + { + return props_.begin(); + } + const_iterator end() const + { + return props_.end(); + } + + const_iterator find(std::string const& key) const + { + return props_.find(key); + } + std::string to_string() const { std::stringstream ss; diff --git a/include/mapnik/metawriter.hpp b/include/mapnik/metawriter.hpp index 3b2838b5d..fa324cecf 100644 --- a/include/mapnik/metawriter.hpp +++ b/include/mapnik/metawriter.hpp @@ -47,11 +47,22 @@ struct placement; class metawriter_property_map { public: + typedef std::map property_map; + typedef property_map::const_iterator const_iterator; + metawriter_property_map() {} UnicodeString const& operator[](std::string const& key) const; UnicodeString& operator[](std::string const& key) {return m_[key];} + std::map::const_iterator find(std::string const& key) const + { + return m_.find(key); + } + std::map::const_iterator end() const + { + return m_.end(); + } private: - std::map m_; + property_map m_; UnicodeString not_found_; }; From 1819034484432e7973a2b8394c0d0421b65cb374 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 27 Oct 2011 12:01:58 -0700 Subject: [PATCH 4/6] more robust tests for feature expressions - refs #933 and #944 --- tests/python_tests/feature_test.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/python_tests/feature_test.py b/tests/python_tests/feature_test.py index 982e44c77..669c1d3ec 100644 --- a/tests/python_tests/feature_test.py +++ b/tests/python_tests/feature_test.py @@ -73,6 +73,7 @@ class FeatureTest(unittest.TestCase): def test_feature_expression_evaluation(): f = mapnik2.Feature(1) f['name'] = 'a' + eq_(f['name'],u'a') expr = mapnik2.Expression("[name]='a'") evaluated = expr.evaluate(f) eq_(evaluated,True) @@ -83,10 +84,11 @@ def test_feature_expression_evaluation(): # https://github.com/mapnik/mapnik/issues/933 def test_feature_expression_evaluation_missing_attr(): f = mapnik2.Feature(1) - f['name'] = 'a' + f['name'] = u'a' + eq_(f['name'],u'a') expr = mapnik2.Expression("[fielddoesnotexist]='a'") evaluated = expr.evaluate(f) - eq_(evaluated,True) + eq_(evaluated,False) num_attributes = len(f) eq_(num_attributes,1) eq_(f.id(),1) @@ -94,8 +96,10 @@ def test_feature_expression_evaluation_missing_attr(): # https://github.com/mapnik/mapnik/issues/934 def test_feature_expression_evaluation_attr_with_spaces(): f = mapnik2.Feature(1) - f['name with space'] = 'a' + f['name with space'] = u'a' + eq_(f['name with space'],u'a') expr = mapnik2.Expression("[name with space]='a'") + eq_(str(expr),"[name with space]='a'") eq_(expr.evaluate(f),True) if __name__ == "__main__": From 5ad3ec92e63c0d77c55a885393cd7f1e9d716fd1 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 27 Oct 2011 20:58:33 +0100 Subject: [PATCH 5/6] return by value --- include/mapnik/attribute.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/attribute.hpp b/include/mapnik/attribute.hpp index 62b7a2a75..d4172ab9c 100644 --- a/include/mapnik/attribute.hpp +++ b/include/mapnik/attribute.hpp @@ -39,7 +39,7 @@ struct attribute : name_(name) {} template - V const& value(F const& f) const + V value(F const& f) const { typedef typename F::const_iterator const_iterator; const_iterator itr = f.find(name_); From b2c9a3605a5f9c5daa7180d42c1e3c45823d4674 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 27 Oct 2011 22:01:01 +0100 Subject: [PATCH 6/6] don't skip white space in attributes names --- include/mapnik/expression_grammar.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index 8f91aaf52..469a24a09 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -223,11 +223,13 @@ struct expression_grammar : qi::grammar | '(' >> expr [_val = _1 ] >> ')' ; - attr %= '[' >> +(char_ - ']') >> ']'; + #if BOOST_VERSION > 104200 ustring %= '\'' >> no_skip[*~char_('\'')] >> '\''; + attr %= '[' >> no_skip[+~char_(']')] >> ']'; #else ustring %= '\'' >> lexeme[*(char_-'\'')] >> '\''; + attr %= '[' >> lexeme[+(char_ - ']')] >> ']'; #endif }