Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / gui / css_length.cpp
blob79465c27d4f038757b2d9bf9ca55fa29596c9a06
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2021 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
19 #include <string>
20 #include "nel/gui/css_length.h"
22 using namespace NLMISC;
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 namespace NLGUI
31 bool CSSLength::parseValue(const std::string &value, bool allowPercent, bool allowNegative)
33 static const std::set<std::string> knownUnits = {
34 "%", "rem", "em", "px", "pt", "vw", "vh", "vi", "vb", "vmin", "vmax"
37 std::string::size_type pos = 0;
38 std::string::size_type len = value.size();
39 if (len == 0)
40 return false;
42 if (len == 1 && value[0] == '0')
44 m_Value = 0;
45 m_Kind = Auto;
46 return true;
49 // +100px; -100px
50 if (value[0] == '+')
51 pos++;
52 else if (allowNegative && value[0] == '-')
53 pos++;
55 while(pos < len)
57 bool isNumeric = (value[pos] >= '0' && value[pos] <= '9')
58 || (pos == 0 && value[pos] == '.')
59 || (pos > 0 && value[pos] == '.' && value[pos-1] >= '0' && value[pos-1] <= '9');
61 if (!isNumeric)
62 break;
64 pos++;
67 std::string unit = toLowerAscii(value.substr(pos));
68 if (knownUnits.count(unit))
70 std::string tmpstr = value.substr(0, pos);
71 return fromString(tmpstr, m_Value);
74 return false;
77 float CSSLength::getValue() const
79 if (m_Unit == CSS_UNIT_PERCENT)
80 return m_Value / 100.f;
82 return m_Value;
84 void CSSLength::setFloatValue(float f, const std::string &unit)
86 m_Value = f;
87 setUnit(unit);
90 void CSSLength::setUnit(const std::string &unit)
92 if (unit.empty())
94 m_Unit = CSS_UNIT_NONE;
95 m_Kind = Fixed;
97 else if (unit == "px")
99 m_Unit = CSS_UNIT_PX;
100 m_Kind = Fixed;
101 } else if (unit == "pt")
103 m_Unit = CSS_UNIT_PT;
104 m_Kind = Fixed;
105 } else if (unit == "%")
107 m_Unit = CSS_UNIT_PERCENT;
108 m_Kind = Relative;
109 } else if (unit == "em")
111 m_Unit = CSS_UNIT_EM;
112 m_Kind = Relative;
113 } else if (unit == "rem")
115 m_Unit = CSS_UNIT_REM;
116 m_Kind = Relative;
117 } else if (unit == "vw")
119 m_Unit = CSS_UNIT_VW;
120 m_Kind = Relative;
121 } else if (unit == "vh")
123 m_Unit = CSS_UNIT_VH;
124 m_Kind = Relative;
125 } else if (unit == "vi")
127 m_Unit = CSS_UNIT_VI;
128 m_Kind = Relative;
129 } else if (unit == "vb")
131 m_Unit = CSS_UNIT_VB;
132 m_Kind = Relative;
133 } else if (unit == "vmin")
135 m_Unit = CSS_UNIT_VMIN;
136 m_Kind = Relative;
137 } else if (unit == "vmax")
139 m_Unit = CSS_UNIT_VMAX;
140 m_Kind = Relative;
141 } else if (unit == "auto")
143 m_Unit = CSS_UNIT_NONE;
144 m_Kind = Auto;
145 } else
147 // fallback to auto
148 m_Unit = CSS_UNIT_NONE;
149 m_Kind = Auto;
153 float CSSLength::calculate(uint32 relValue, uint32 emSize, uint32 remSize, uint32 vwSize, uint32 vhSize = 0) const
155 if (m_Kind == Auto)
156 return 0;
158 float value = getValue();
159 switch(m_Unit)
161 case CSS_UNIT_EM:
162 return emSize * value;
163 case CSS_UNIT_REM:
164 return remSize * value;
165 case CSS_UNIT_PERCENT:
166 return relValue * value;
167 case CSS_UNIT_PX:
168 case CSS_UNIT_PT:
169 return value;
170 case CSS_UNIT_VW:
171 case CSS_UNIT_VI:
172 // Vi for horizontal writing mode only
173 return (float)vwSize*0.01f;
174 case CSS_UNIT_VH:
175 case CSS_UNIT_VB:
176 // Vb for horizontal writing mode only
177 return (float)vhSize*0.01f;
178 case CSS_UNIT_VMIN:
179 return (float)std::min(vwSize, vhSize)*0.01f;
180 case CSS_UNIT_VMAX:
181 return (float)std::max(vwSize, vhSize)*0.01f;
184 nldebug("Unknown CSS unit '%s'", toString().c_str());
185 return value;
188 std::string CSSLength::toString() const
190 if (m_Kind == Auto)
191 return "auto";
193 std::string ret;
194 ret += NLMISC::toString("%f", m_Value);
196 size_t pos = ret.find(".");
197 for( ; pos < ret.size(); ++pos)
199 if (ret[pos] != '0')
200 break;
202 if (pos == ret.size())
203 ret = ret.substr(0, ret.find("."));
205 switch(m_Unit)
207 case CSS_UNIT_NONE: break;
208 case CSS_UNIT_EM: ret += "em"; break;
209 case CSS_UNIT_REM: ret += "rem"; break;
210 case CSS_UNIT_PERCENT: ret += "%"; break;
211 case CSS_UNIT_PX: ret += "px"; break;
212 case CSS_UNIT_PT: ret += "pt"; break;
213 case CSS_UNIT_VW: ret += "vw"; break;
214 case CSS_UNIT_VH: ret += "vh"; break;
215 case CSS_UNIT_VI: ret += "vi"; break;
216 case CSS_UNIT_VB: ret += "vb"; break;
217 case CSS_UNIT_VMIN: ret += "vmin"; break;
218 case CSS_UNIT_VMAX: ret += "vmax"; break;
221 return ret;
224 } // namespace