diff --git a/CHANGELOG.md b/CHANGELOG.md index 36b739b98..6bd53aa0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Released: YYYY XX, 2015 - Visual tests: new command line arguments `--agg`, `--cairo`, `--svg`, `--grid` for selecting renderers (https://github.com/mapnik/mapnik/pull/3074) - Visual tests: new command line argument `--scale-factor` or abbreviated `-s` for setting scale factor (https://github.com/mapnik/mapnik/pull/3074) +- Fixed parsing colors in hexadecimal notation (https://github.com/mapnik/mapnik/pull/3075) ## 3.0.5 diff --git a/include/mapnik/css_color_grammar.hpp b/include/mapnik/css_color_grammar.hpp index 4403d34c9..04ff02d55 100644 --- a/include/mapnik/css_color_grammar.hpp +++ b/include/mapnik/css_color_grammar.hpp @@ -37,6 +37,7 @@ #pragma GCC diagnostic ignored "-Wconversion" #include #include +#include #include #include #include diff --git a/include/mapnik/css_color_grammar_impl.hpp b/include/mapnik/css_color_grammar_impl.hpp index 4ce313435..c978194a4 100644 --- a/include/mapnik/css_color_grammar_impl.hpp +++ b/include/mapnik/css_color_grammar_impl.hpp @@ -39,6 +39,7 @@ css_color_grammar::css_color_grammar() qi::_a_type _a; qi::_b_type _b; qi::_c_type _c; + qi::lexeme_type lexeme; ascii::no_case_type no_case; using phoenix::at_c; @@ -49,18 +50,18 @@ css_color_grammar::css_color_grammar() | hex_color_small | no_case[named]; - hex_color = lit('#') + hex_color = lexeme[ lit('#') >> hex2 [ at_c<0>(_val) = _1 ] >> hex2 [ at_c<1>(_val) = _1 ] >> hex2 [ at_c<2>(_val) = _1 ] - >>-hex2 [ at_c<3>(_val) = _1 ] + >>-hex2 [ at_c<3>(_val) = _1 ] ] ; - hex_color_small = lit('#') + hex_color_small = lexeme[ lit('#') >> hex1 [ at_c<0>(_val) = _1 | _1 << 4 ] >> hex1 [ at_c<1>(_val) = _1 | _1 << 4 ] >> hex1 [ at_c<2>(_val) = _1 | _1 << 4 ] - >>-hex1 [ at_c<3>(_val) = _1 | _1 << 4 ] + >>-hex1 [ at_c<3>(_val) = _1 | _1 << 4 ] ] ; rgba_color = lit("rgb") >> -lit('a') diff --git a/test/unit/color/css_color.cpp b/test/unit/color/css_color.cpp index 38e151890..7ff6e3fa5 100644 --- a/test/unit/color/css_color.cpp +++ b/test/unit/color/css_color.cpp @@ -1,5 +1,6 @@ #include "catch.hpp" #include +#include #include TEST_CASE("css color") { @@ -35,4 +36,132 @@ TEST_CASE("css color") { CHECK( c.green() == 0 ); CHECK( c.blue() == 0 ); } -} \ No newline at end of file + + SECTION("hex colors") + { + mapnik::css_color_grammar color_grammar; + boost::spirit::qi::ascii::space_type space; + + { + std::string s("#abcdef"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0xff ); + CHECK( c.red() == 0xab ); + CHECK( c.green() == 0xcd ); + CHECK( c.blue() == 0xef ); + } + + { + std::string s("#abcdef12"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0x12 ); + CHECK( c.red() == 0xab ); + CHECK( c.green() == 0xcd ); + CHECK( c.blue() == 0xef ); + } + + { + std::string s(" #abcdef"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0xff ); + CHECK( c.red() == 0xab ); + CHECK( c.green() == 0xcd ); + CHECK( c.blue() == 0xef ); + } + + { + std::string s(" #abcdef12"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0x12 ); + CHECK( c.red() == 0xab ); + CHECK( c.green() == 0xcd ); + CHECK( c.blue() == 0xef ); + } + + { + std::string s("# abcdef"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + { + std::string s("# abcdef12"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + { + std::string s("#ab cdef"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + { + std::string s("#ab cdef12"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + // hex_color_small + + { + std::string s("#abc"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0xff ); + CHECK( c.red() == 0xaa ); + CHECK( c.green() == 0xbb ); + CHECK( c.blue() == 0xcc ); + } + + { + std::string s("#abcd"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0xdd ); + CHECK( c.red() == 0xaa ); + CHECK( c.green() == 0xbb ); + CHECK( c.blue() == 0xcc ); + } + + { + std::string s(" #abc"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0xff ); + CHECK( c.red() == 0xaa ); + CHECK( c.green() == 0xbb ); + CHECK( c.blue() == 0xcc ); + } + + { + std::string s(" #abcd"); + mapnik::color c; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) ); + CHECK( c.alpha() == 0xdd ); + CHECK( c.red() == 0xaa ); + CHECK( c.green() == 0xbb ); + CHECK( c.blue() == 0xcc ); + } + + { + std::string s("# abc"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + { + std::string s("# abcd"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + { + std::string s("#a bc"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + + { + std::string s("#a bcd"); + CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); + } + } +} diff --git a/test/unit/imaging/image_filter.cpp b/test/unit/imaging/image_filter.cpp index 03864093a..79576a4b0 100644 --- a/test/unit/imaging/image_filter.cpp +++ b/test/unit/imaging/image_filter.cpp @@ -6,6 +6,9 @@ #include #include #include +#include +#include +#include TEST_CASE("image filter") { @@ -388,6 +391,49 @@ SECTION("test colorize-alpha - two color with transparency") { } // END SECTION +SECTION("test colorize-alpha - parsing correct input") { + + mapnik::image_filter_grammar> filter_grammar; + boost::spirit::qi::ascii::space_type space; + std::vector f; + std::string s("colorize-alpha(#0000ff 0%, #00ff00 100%)"); + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), filter_grammar, space, f) ); + mapnik::filter::colorize_alpha const & ca = mapnik::util::get(f.front()); + + { + mapnik::filter::color_stop const & s = ca[0]; + CHECK( s.color.alpha() == 0xff ); + CHECK( s.color.red() == 0x00 ); + CHECK( s.color.green() == 0x00 ); + CHECK( s.color.blue() == 0xff ); + CHECK( s.offset == 0.0 ); + } + + { + mapnik::filter::color_stop const & s = ca[1]; + CHECK( s.color.alpha() == 0xff ); + CHECK( s.color.red() == 0x00 ); + CHECK( s.color.green() == 0xff ); + CHECK( s.color.blue() == 0x00 ); + CHECK( s.offset == 1.0 ); + } + +} // END SECTION + +SECTION("test colorize-alpha - parsing incorrect input") { + + mapnik::image_filter_grammar> filter_grammar; + boost::spirit::qi::ascii::space_type space; + std::string s("colorize-alpha(#0000ff 0%, #00ff00 00 100%)"); + std::string::const_iterator itr = s.cbegin(); + std::string::const_iterator end = s.cend(); + std::vector f; + CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), filter_grammar, space, f) ); + CHECK( f.empty() ); + CHECK( itr != end ); + +} // END SECTION + SECTION("test color-blind-protanope") { mapnik::image_rgba8 im(2,2);