Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / gui / css_background.cpp
blob4665a0c42e5578a4eb3eaf7539bcb4dbd2ab8b98
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/libwww.h"
21 #include "nel/gui/css_length.h"
22 #include "nel/gui/css_background.h"
24 using namespace NLMISC;
26 #ifdef DEBUG_NEW
27 #define new DEBUG_NEW
28 #endif
30 namespace NLGUI
33 void CSSBackground::setImage(const std::string &value)
35 image = value;
38 void CSSBackground::setPosition(const std::string &value)
40 std::vector<std::string> parts;
41 splitString(toLowerAscii(value), " ", parts);
43 if (parts.empty() || parts.size() > 4)
44 return;
46 switch(parts.size())
48 case 1:
49 positionFromOne(parts);
50 break;
51 case 2:
52 positionFromTwo(parts);
53 break;
54 case 3:
55 positionFromThree(parts);
56 break;
57 case 4:
58 positionFromFour(parts);
59 break;
60 default:
61 return;
65 void CSSBackground::setSize(const std::string &value)
67 std::vector<std::string> parts;
68 splitString(toLowerAscii(value), " ", parts);
69 if (parts.size() > 2)
70 return;
72 if (parts.size() == 1 && (parts[0] == "cover" || parts[0] == "contain"))
74 if (parts[0] == "cover")
75 size = CSS_VALUE_COVER;
76 else
77 size = CSS_VALUE_CONTAIN;
79 width.setAuto();
80 height.setAuto();
81 return;
84 // height will default to 'auto' if not set
85 if (parts.size() == 1)
86 parts.push_back("auto");
88 if (parts[0] == "auto" && parts[1] == "auto")
90 size = CSS_VALUE_AUTO;
91 width.setAuto();
92 height.setAuto();
93 return;
96 CSSLength newW, newH;
97 bool success = true;
98 if (parts[0] == "auto")
100 newW.setAuto();
102 else
104 float fval;
105 std::string unit;
106 if (!getCssLength(fval, unit, parts[0]))
108 nlwarning("Failed to parse background-size[0] '%s'", parts[0].c_str());
109 return;
111 newW.setFloatValue(fval, unit);
114 if (parts[1] == "auto")
116 newH.setAuto();
118 else
120 float fval;
121 std::string unit;
122 if (!getCssLength(fval, unit, parts[1]))
124 nlwarning("Failed to parse background-size[1] '%s'", parts[1].c_str());
125 return;
127 newH.setFloatValue(fval, unit);
130 size = CSS_VALUE_LENGTH;
131 width = newW;
132 height = newH;
135 void CSSBackground::setRepeat(const std::string &value)
137 std::vector<std::string> parts;
138 splitString(toLowerAscii(value), " ", parts);
139 if (parts.size() == 0 || parts.size() > 2)
140 return;
142 if (parts.size() == 1)
144 if (parts[0] == "repeat-x")
145 parts.push_back("no-repeat");
146 else if (parts[0] == "repeat-y")
147 parts.insert(parts.begin(), "no-repeat");
148 else //repeat, space, round, no-repeat
149 parts.push_back(parts[0]);
153 if (parts[0] == "repeat") repeatX = CSS_VALUE_REPEAT;
154 else if (parts[0] == "no-repeat") repeatX = CSS_VALUE_NOREPEAT;
155 else if (parts[0] == "space") repeatX = CSS_VALUE_SPACE;
156 else if (parts[0] == "round") repeatX = CSS_VALUE_ROUND;
157 else repeatX = CSS_VALUE_REPEAT;
159 if (parts[1] == "repeat") repeatY = CSS_VALUE_REPEAT;
160 else if (parts[1] == "no-repeat") repeatY = CSS_VALUE_NOREPEAT;
161 else if (parts[1] == "space") repeatY = CSS_VALUE_SPACE;
162 else if (parts[1] == "round") repeatY = CSS_VALUE_ROUND;
163 else repeatY = CSS_VALUE_REPEAT;
166 void CSSBackground::setOrigin(const std::string &value)
168 if (value == "border-box") origin = CSS_VALUE_BORDER_BOX;
169 else if (value == "padding-box") origin = CSS_VALUE_PADDING_BOX;
170 else if (value == "content-box") origin = CSS_VALUE_CONTENT_BOX;
171 else origin = CSS_VALUE_PADDING_BOX;
174 void CSSBackground::setClip(const std::string &value)
176 if (value == "border-box") clip = CSS_VALUE_BORDER_BOX;
177 else if (value == "padding-box") clip = CSS_VALUE_PADDING_BOX;
178 else if (value == "content-box") clip = CSS_VALUE_CONTENT_BOX;
179 //else if (value == "text") clip = CSSValueType::Text;
180 else clip = CSS_VALUE_PADDING_BOX;
183 void CSSBackground::setAttachment(const std::string &value)
185 if (value == "fixed") attachment = CSS_VALUE_FIXED;
186 else if (value == "local") attachment = CSS_VALUE_LOCAL;
187 else if (value == "scroll") attachment = CSS_VALUE_SCROLL;
188 else attachment = CSS_VALUE_SCROLL;
191 void CSSBackground::setColor(const std::string &value)
193 NLMISC::CRGBA tmp;
194 if (scanHTMLColor(value.c_str(), tmp))
195 color = tmp;
198 static bool isHorizontalKeyword(const std::string &val)
200 return val == "left" || val == "right";
203 static bool isVerticalKeyword(const std::string &val)
205 return val == "top" || val == "bottom";
208 void CSSBackground::positionFromOne(const std::vector<std::string> &parts)
210 CSSValueType newH = CSS_VALUE_LEFT;
211 CSSValueType newV = CSS_VALUE_TOP;
212 CSSLength newX, newY;
213 newX.setFloatValue(0, "%");
214 newY.setFloatValue(0, "%");
216 uint index = 0;
217 float fval;
218 std::string unit;
219 if (isHorizontalKeyword(parts[index]))
221 newH = parts[index] == "left" ? CSS_VALUE_LEFT : CSS_VALUE_RIGHT;
222 newV = CSS_VALUE_CENTER;
224 else if (isVerticalKeyword(parts[index]))
226 newH = CSS_VALUE_CENTER;
227 newV = parts[index] == "top" ? CSS_VALUE_TOP : CSS_VALUE_BOTTOM;
229 else if (parts[index] == "center")
231 newH = CSS_VALUE_CENTER;
232 newV = CSS_VALUE_CENTER;
234 else if (getCssLength(fval, unit, parts[index], true))
236 newX.setFloatValue(fval, unit);
237 newV = CSS_VALUE_CENTER;
239 else
241 return;
244 xAnchor = newH;
245 yAnchor = newV;
246 xPosition = newX;
247 yPosition = newY;
250 void CSSBackground::positionFromTwo(const std::vector<std::string> &parts)
252 CSSValueType newH = CSS_VALUE_LEFT;
253 CSSValueType newV = CSS_VALUE_TOP;
254 CSSLength newX, newY;
255 newX.setFloatValue(0, "%");
256 newY.setFloatValue(0, "%");
258 float fval;
259 std::string unit;
260 uint index = 0;
261 bool hasCenter = false;
262 bool hasX = false;
263 bool hasY = false;
264 for (uint index = 0; index < parts.size(); index++)
266 if (parts[index] == "center")
268 hasCenter = true;
270 else if (isHorizontalKeyword(parts[index]))
272 if (hasX) return;
273 hasX = true;
274 newH = parts[index] == "left" ? CSS_VALUE_LEFT : CSS_VALUE_RIGHT;
276 else if (isVerticalKeyword(parts[index]))
278 if (hasY) return;
279 hasY = true;
280 newV = parts[index] == "top" ? CSS_VALUE_TOP : CSS_VALUE_BOTTOM;
282 else if (getCssLength(fval, unit, parts[index], true))
284 // invalid: 'top 50%';
285 if (hasY) return;
286 if (!hasX)
288 hasX = true;
289 newX.setFloatValue(fval, unit);
291 else
293 hasY = true;
294 newY.setFloatValue(fval, unit);
297 else
299 return;
303 if (hasCenter)
305 if (!hasX)
306 newH = CSS_VALUE_CENTER;
307 if (!hasY)
308 newV = CSS_VALUE_CENTER;
311 xAnchor = newH;
312 yAnchor = newV;
313 xPosition = newX;
314 yPosition = newY;
317 void CSSBackground::positionFromThree(const std::vector<std::string> &parts)
319 CSSValueType newH = CSS_VALUE_LEFT;
320 CSSValueType newV = CSS_VALUE_TOP;
321 CSSLength newX, newY;
322 newX.setFloatValue(0, "%");
323 newY.setFloatValue(0, "%");
325 float fval;
326 std::string unit;
327 bool hasCenter = false;
328 bool hasX = false;
329 bool hasY = false;
330 for(uint index = 0; index < 3; index++)
332 if (parts[index] == "center")
334 if (hasCenter) return;
335 hasCenter = true;
337 else if (isHorizontalKeyword(parts[index]))
339 if (hasX) return;
340 hasX = true;
341 newH = parts[index] == "left" ? CSS_VALUE_LEFT : CSS_VALUE_RIGHT;
342 if ((index+1) < parts.size() && getCssLength(fval, unit, parts[index+1], true))
344 newX.setFloatValue(fval, unit);
345 index++;
348 else if (isVerticalKeyword(parts[index]))
350 if (hasY) return;
351 hasY = true;
352 newV = parts[index] == "top" ? CSS_VALUE_TOP : CSS_VALUE_BOTTOM;
353 if ((index+1) < parts.size() && getCssLength(fval, unit, parts[index+1], true))
355 newY.setFloatValue(fval, unit);
356 index++;
359 else
361 return;
364 if (hasCenter)
366 if (hasX && hasY)
367 return;
369 if (!hasX)
370 newH = CSS_VALUE_CENTER;
371 else
372 newV = CSS_VALUE_CENTER;
375 xAnchor = newH;
376 yAnchor = newV;
377 xPosition = newX;
378 yPosition = newY;
381 void CSSBackground::positionFromFour(const std::vector<std::string> &parts)
383 CSSValueType newH = CSS_VALUE_LEFT;
384 CSSValueType newV = CSS_VALUE_TOP;
385 CSSLength newX, newY;
386 newX.setFloatValue(0, "%");
387 newY.setFloatValue(0, "%");
389 float fval;
390 std::string unit;
391 bool hasX = false;
392 bool hasY = false;
393 for(uint index = 0; index<4; index+=2)
395 if (parts[index] == "center")
396 return;
398 if (isHorizontalKeyword(parts[index]))
400 if (hasX) return;
401 hasX = true;
402 if (!getCssLength(fval, unit, parts[index+1], true)) return;
403 newH = parts[index] == "left" ? CSS_VALUE_LEFT : CSS_VALUE_RIGHT;
404 newX.setFloatValue(fval, unit);
406 else if (isVerticalKeyword(parts[index]))
408 if (hasY) return;
409 hasY = true;
410 if (!getCssLength(fval, unit, parts[index+1], true)) return;
411 newV = parts[index] == "top" ? CSS_VALUE_TOP : CSS_VALUE_BOTTOM;
412 newY.setFloatValue(fval, unit);
414 else
416 return;
420 xAnchor = newH;
421 yAnchor = newV;
422 xPosition = newX;
423 yPosition = newY;
426 } // namespace