]> git.mxchange.org Git - simgear.git/blob - simgear/misc/SVGpreserveAspectRatio.cxx
Fix VS2010 lack of fminf
[simgear.git] / simgear / misc / SVGpreserveAspectRatio.cxx
1 // Parse and represent SVG preserveAspectRatio attribute
2 //
3 // Copyright (C) 2014  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 "SVGpreserveAspectRatio.hxx"
20
21 #include <simgear/debug/logstream.hxx>
22 #include <simgear/misc/strutils.hxx>
23
24 #include <boost/tokenizer.hpp>
25
26 namespace simgear
27 {
28
29   //----------------------------------------------------------------------------
30   SVGpreserveAspectRatio::SVGpreserveAspectRatio():
31     _align_x(ALIGN_NONE),
32     _align_y(ALIGN_NONE),
33     _meet(true)
34   {
35
36   }
37
38   //----------------------------------------------------------------------------
39   SVGpreserveAspectRatio::Align SVGpreserveAspectRatio::alignX() const
40   {
41     return _align_x;
42   }
43
44   //----------------------------------------------------------------------------
45   SVGpreserveAspectRatio::Align SVGpreserveAspectRatio::alignY() const
46   {
47     return _align_y;
48   }
49
50   //----------------------------------------------------------------------------
51   bool SVGpreserveAspectRatio::scaleToFill() const
52   {
53     return (_align_x == ALIGN_NONE) && (_align_y == ALIGN_NONE);
54   }
55
56   //----------------------------------------------------------------------------
57   bool SVGpreserveAspectRatio::scaleToFit() const
58   {
59     return !scaleToFill() && _meet;
60   }
61
62   //----------------------------------------------------------------------------
63   bool SVGpreserveAspectRatio::scaleToCrop() const
64   {
65     return !scaleToFill() && !_meet;
66   }
67
68   //----------------------------------------------------------------------------
69   bool SVGpreserveAspectRatio::meet() const
70   {
71     return _meet;
72   }
73
74   //----------------------------------------------------------------------------
75   bool
76   SVGpreserveAspectRatio::operator==(const SVGpreserveAspectRatio& rhs) const
77   {
78     return (_align_x == rhs._align_x)
79         && (_align_y == rhs._align_y)
80         && (_meet == rhs._meet || scaleToFill());
81   }
82
83   //----------------------------------------------------------------------------
84   SVGpreserveAspectRatio SVGpreserveAspectRatio::parse(const std::string& str)
85   {
86     SVGpreserveAspectRatio ret;
87     enum
88     {
89       PARSE_defer,
90       PARSE_align,
91       PARSE_meetOrSlice,
92       PARSE_done,
93       PARSE_error
94     } parse_state = PARSE_defer;
95
96     typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
97     const boost::char_separator<char> del(" \t\n");
98
99     tokenizer tokens(str.begin(), str.end(), del);
100     for( tokenizer::const_iterator tok = tokens.begin();
101                                    tok != tokens.end()
102                                 && parse_state != PARSE_error;
103                                  ++tok )
104     {
105       const std::string& cur_tok = tok.current_token();
106
107       switch( parse_state )
108       {
109         case PARSE_defer:
110           if( cur_tok == "defer" )
111           {
112             SG_LOG( SG_GENERAL,
113                     SG_INFO,
114                     "SVGpreserveAspectRatio: 'defer' is ignored." );
115             parse_state = PARSE_align;
116             break;
117           }
118           // fall through
119         case PARSE_align:
120           if( cur_tok == "none" )
121           {
122             ret._align_x = ALIGN_NONE;
123             ret._align_y = ALIGN_NONE;
124           }
125           else if( cur_tok.length() == 8 )
126           {
127             if(      strutils::starts_with(cur_tok, "xMin") )
128               ret._align_x = ALIGN_MIN;
129             else if( strutils::starts_with(cur_tok, "xMid") )
130               ret._align_x = ALIGN_MID;
131             else if( strutils::starts_with(cur_tok, "xMax") )
132               ret._align_x = ALIGN_MAX;
133             else
134             {
135               parse_state = PARSE_error;
136               break;
137             }
138
139             if(      strutils::ends_with(cur_tok, "YMin") )
140               ret._align_y = ALIGN_MIN;
141             else if( strutils::ends_with(cur_tok, "YMid") )
142               ret._align_y = ALIGN_MID;
143             else if( strutils::ends_with(cur_tok, "YMax") )
144               ret._align_y = ALIGN_MAX;
145             else
146             {
147               parse_state = PARSE_error;
148               break;
149             }
150           }
151           else
152           {
153             parse_state = PARSE_error;
154             break;
155           }
156           parse_state = PARSE_meetOrSlice;
157           break;
158         case PARSE_meetOrSlice:
159           if( cur_tok == "meet" )
160             ret._meet = true;
161           else if( cur_tok == "slice" )
162             ret._meet = false;
163           else
164           {
165             parse_state = PARSE_error;
166             break;
167           }
168           parse_state = PARSE_done;
169           break;
170         case PARSE_done:
171           SG_LOG( SG_GENERAL,
172                   SG_WARN,
173                   "SVGpreserveAspectRatio: Ignoring superfluous token"
174                   " '" << cur_tok << "'" );
175           break;
176         default:
177           break;
178       }
179     }
180
181     if( parse_state == PARSE_error )
182     {
183       SG_LOG( SG_GENERAL,
184               SG_WARN,
185               "SVGpreserveAspectRatio: Failed to parse: '" << str << "'" );
186       return SVGpreserveAspectRatio();
187     }
188
189     return ret;
190   }
191
192 } // namespace simgear