]> git.mxchange.org Git - simgear.git/blob - simgear/scene/util/parse_color.cxx
Work around apparent OSG 3.2.0 normal binding bug.
[simgear.git] / simgear / scene / util / parse_color.cxx
1 // Parse CSS colors
2 //
3 // Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Library General Public License for more details.
14 //
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
18
19 #include "parse_color.hxx"
20
21 #include <boost/algorithm/string/predicate.hpp>
22 #include <boost/algorithm/string/trim.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <boost/tokenizer.hpp>
25
26 #include <map>
27
28 namespace simgear
29 {
30
31   //----------------------------------------------------------------------------
32   bool parseColor(std::string str, osg::Vec4& result)
33   {
34     boost::trim(str);
35     osg::Vec4 color(0,0,0,1);
36
37     if( str.empty() )
38       return false;
39
40     // #rrggbb
41     if( str[0] == '#' )
42     {
43       const int offsets[] = {2,2,2};
44       const boost::offset_separator hex_separator( boost::begin(offsets),
45                                                    boost::end(offsets) );
46       typedef boost::tokenizer<boost::offset_separator> offset_tokenizer;
47       offset_tokenizer tokens(str.begin() + 1, str.end(), hex_separator);
48
49       int comp = 0;
50       for( offset_tokenizer::const_iterator tok = tokens.begin();
51            tok != tokens.end() && comp < 4;
52            ++tok, ++comp )
53       {
54         color[comp] = strtol(std::string(*tok).c_str(), 0, 16) / 255.f;
55       }
56     }
57     // rgb(r,g,b)
58     // rgba(r,g,b,a)
59     else if( boost::ends_with(str, ")") )
60     {
61       const std::string RGB = "rgb(",
62                         RGBA = "rgba(";
63       size_t pos;
64       if( boost::starts_with(str, RGB) )
65         pos = RGB.length();
66       else if( boost::starts_with(str, RGBA) )
67         pos = RGBA.length();
68       else
69         return false;
70
71       typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
72       const boost::char_separator<char> del(", \t\n");
73
74       tokenizer tokens(str.begin() + pos, str.end() - 1, del);
75       int comp = 0;
76       for( tokenizer::const_iterator tok = tokens.begin();
77            tok != tokens.end() && comp < 4;
78            ++tok, ++comp )
79       {
80         color[comp] = boost::lexical_cast<float>(*tok)
81                     // rgb = [0,255], a = [0,1]
82                     / (comp < 3 ? 255 : 1);
83       }
84     }
85     else
86     {
87       // Basic color keywords
88       // http://www.w3.org/TR/css3-color/#html4
89       typedef std::map<std::string, osg::Vec4> ColorMap;
90       static ColorMap colors;
91       if( colors.empty() )
92       {
93         colors["red"    ] = osg::Vec4(1,    0,      0,      1);
94         colors["black"  ] = osg::Vec4(0,    0,      0,      1);
95         colors["silver" ] = osg::Vec4(0.75, 0.75,   0.75,   1);
96         colors["gray"   ] = osg::Vec4(0.5,  0.5,    0.5,    1);
97         colors["white"  ] = osg::Vec4(1,    1,      1,      1);
98         colors["maroon" ] = osg::Vec4(0.5,  0,      0,      1);
99         colors["red"    ] = osg::Vec4(1,    0,      0,      1);
100         colors["purple" ] = osg::Vec4(0.5,  0,      0.5,    1);
101         colors["fuchsia"] = osg::Vec4(1,    0,      1,      1);
102         colors["green"  ] = osg::Vec4(0,    0.5,    0,      1);
103         colors["lime"   ] = osg::Vec4(0,    1,      0,      1);
104         colors["olive"  ] = osg::Vec4(0.5,  0.5,    0,      1);
105         colors["yellow" ] = osg::Vec4(1,    1,      0,      1);
106         colors["navy"   ] = osg::Vec4(0,    0,      0.5,    1);
107         colors["blue"   ] = osg::Vec4(0,    0,      1,      1);
108         colors["teal"   ] = osg::Vec4(0,    0.5,    0.5,    1);
109         colors["aqua"   ] = osg::Vec4(0,    1,      1,      1);
110       }
111       ColorMap::const_iterator it = colors.find(str);
112       if( it == colors.end() )
113         return false;
114
115       result = it->second;
116       return true;
117     }
118
119     result = color;
120     return true;
121   }
122
123 } // namespace simgear