1 /* Copyright (C) 2015 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. 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 General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19 Shapes.cpp
20 */
21 
22 #include "precompiled.h"
23 
24 #include <string>
25 
26 #include "Shapes.h"
27 #include "CLogger.h"
28 #include "CStr.h"
29 
30 /**
31  * Try to parse @p Value as a color. Returns true on success, false otherwise.
32  * @param Value Should be "r g b" or "r g b a" where each value is an integer in [0,255].
33  * @param DefaultAlpha The alpha value that is used if the format of @p Value is "r g b".
34  */
ParseString(const CStr8 & Value,int DefaultAlpha)35 bool CColor::ParseString(const CStr8& Value, int DefaultAlpha)
36 {
37 	const unsigned int NUM_VALS = 4;
38 	int values[NUM_VALS] = { 0, 0, 0, DefaultAlpha };
39 	std::stringstream stream;
40 	stream.str(Value);
41 	// Parse each value
42 	size_t i;
43 	for (i = 0; i < NUM_VALS; ++i)
44 	{
45 		if (stream.eof())
46 			break;
47 
48 		stream >> values[i];
49 		if ((stream.rdstate() & std::stringstream::failbit) != 0)
50 		{
51 			LOGWARNING("Unable to parse CColor parameters. Your input: '%s'", Value.c_str());
52 			return false;
53 		}
54 		if (values[i] < 0 || values[i] > 255)
55 		{
56 			LOGWARNING("Invalid value (<0 or >255) when parsing CColor parameters. Your input: '%s'", Value.c_str());
57 			return false;
58 		}
59 	}
60 
61 	if (i < 3)
62 	{
63 		LOGWARNING("Not enough parameters when parsing as CColor. Your input: '%s'", Value.c_str());
64 		return false;
65 	}
66 	if (!stream.eof())
67 	{
68 		LOGWARNING("Too many parameters when parsing as CColor. Your input: '%s'", Value.c_str());
69 		return false;
70 	}
71 
72 	r = values[0]/255.f;
73 	g = values[1]/255.f;
74 	b = values[2]/255.f;
75 	a = values[3]/255.f;
76 
77 	return true;
78 }
79 
80 
81 /*************************************************************************/
82 
operator ==(const CColor & color) const83 bool CColor::operator == (const CColor &color) const
84 {
85 	return r==color.r &&
86 		   g==color.g &&
87 		   b==color.b &&
88 		   a==color.a;
89 }
90 
91 /*************************************************************************/
92 
CRect()93 CRect::CRect() :
94 	left(0.f), top(0.f), right(0.f), bottom(0.f)
95 {
96 }
97 
CRect(const CPos & pos)98 CRect::CRect(const CPos &pos) :
99 	left(pos.x), top(pos.y), right(pos.x), bottom(pos.y)
100 {
101 }
102 
CRect(const CSize & size)103 CRect::CRect(const CSize &size) :
104 	left(0.f), top(0.f), right(size.cx), bottom(size.cy)
105 {
106 }
107 
CRect(const CPos & upperleft,const CPos & bottomright)108 CRect::CRect(const CPos &upperleft, const CPos &bottomright) :
109 	left(upperleft.x), top(upperleft.y), right(bottomright.x), bottom(bottomright.y)
110 {
111 }
112 
CRect(const CPos & pos,const CSize & size)113 CRect::CRect(const CPos &pos, const CSize &size) :
114 	left(pos.x), top(pos.y), right((pos.x+size.cx)), bottom((pos.y+size.cy))
115 {
116 }
117 
CRect(const float l,const float t,const float r,const float b)118 CRect::CRect(const float l, const float t, const float r, const float b) :
119 	left(l), top(t), right(r), bottom(b)
120 {
121 }
122 
123 // =
operator =(const CRect & a)124 CRect& CRect::operator = (const CRect& a)
125 {
126 	left = a.left;
127 	top = a.top;
128 	right = a.right;
129 	bottom = a.bottom;
130 	return *this;
131 }
132 
133 // ==
operator ==(const CRect & a) const134 bool CRect::operator ==(const CRect &a) const
135 {
136 	return	(left==a.left &&
137 			 top==a.top &&
138 			 right==a.right &&
139 			 bottom==a.bottom);
140 }
141 
142 // !=
operator !=(const CRect & a) const143 bool CRect::operator != (const CRect& a) const
144 {
145 	return !(*this==a);
146 }
147 
148 // - (the unary operator)
operator -(void) const149 CRect CRect::operator - (void) const
150 {
151 	return CRect(-left, -top, -right, -bottom);
152 }
153 
154 // + (the unary operator)
operator +(void) const155 CRect CRect::operator + (void) const
156 {
157 	return *this;
158 }
159 
160 // +
operator +(const CRect & a) const161 CRect CRect::operator + (const CRect& a) const
162 {
163 	return CRect(left+a.left, top+a.top, right+a.right, bottom+a.bottom);
164 }
165 
166 // +
operator +(const CPos & a) const167 CRect CRect::operator + (const CPos& a) const
168 {
169 	return CRect(left+a.x, top+a.y, right+a.x, bottom+a.y);
170 }
171 
172 // +
operator +(const CSize & a) const173 CRect CRect::operator + (const CSize& a) const
174 {
175 	return CRect(left+a.cx, top+a.cy, right+a.cx, bottom+a.cy);
176 }
177 
178 // -
operator -(const CRect & a) const179 CRect CRect::operator - (const CRect& a) const
180 {
181 	return CRect(left-a.left, top-a.top, right-a.right, bottom-a.bottom);
182 }
183 
184 // -
operator -(const CPos & a) const185 CRect CRect::operator - (const CPos& a) const
186 {
187 	return CRect(left-a.x, top-a.y, right-a.x, bottom-a.y);
188 }
189 
190 // -
operator -(const CSize & a) const191 CRect CRect::operator - (const CSize& a) const
192 {
193 	return CRect(left-a.cx, top-a.cy, right-a.cx, bottom-a.cy);
194 }
195 
196 // +=
operator +=(const CRect & a)197 void CRect::operator +=(const CRect& a)
198 {
199 	left += a.left;
200 	top += a.top;
201 	right += a.right;
202 	bottom += a.bottom;
203 }
204 
205 // +=
operator +=(const CPos & a)206 void CRect::operator +=(const CPos& a)
207 {
208 	left += a.x;
209 	top += a.y;
210 	right += a.x;
211 	bottom += a.y;
212 }
213 
214 // +=
operator +=(const CSize & a)215 void CRect::operator +=(const CSize& a)
216 {
217 	left += a.cx;
218 	top += a.cy;
219 	right += a.cx;
220 	bottom += a.cy;
221 }
222 
223 // -=
operator -=(const CRect & a)224 void CRect::operator -=(const CRect& a)
225 {
226 	left -= a.left;
227 	top -= a.top;
228 	right -= a.right;
229 	bottom -= a.bottom;
230 }
231 
232 // -=
operator -=(const CPos & a)233 void CRect::operator -=(const CPos& a)
234 {
235 	left -= a.x;
236 	top -= a.y;
237 	right -= a.x;
238 	bottom -= a.y;
239 }
240 
241 // -=
operator -=(const CSize & a)242 void CRect::operator -=(const CSize& a)
243 {
244 	left -= a.cx;
245 	top -= a.cy;
246 	right -= a.cx;
247 	bottom -= a.cy;
248 }
249 
GetWidth() const250 float CRect::GetWidth() const
251 {
252 	return right-left;
253 }
254 
GetHeight() const255 float CRect::GetHeight() const
256 {
257 	return bottom-top;
258 }
259 
GetSize() const260 CSize CRect::GetSize() const
261 {
262 	return CSize(right-left, bottom-top);
263 }
264 
TopLeft() const265 CPos CRect::TopLeft() const
266 {
267 	return CPos(left, top);
268 }
269 
TopRight() const270 CPos CRect::TopRight() const
271 {
272 	return CPos(right, top);
273 }
274 
BottomLeft() const275 CPos CRect::BottomLeft() const
276 {
277 	return CPos(left, bottom);
278 }
279 
BottomRight() const280 CPos CRect::BottomRight() const
281 {
282 	return CPos(right, bottom);
283 }
284 
CenterPoint() const285 CPos CRect::CenterPoint() const
286 {
287 	return CPos((left+right)/2.f, (top+bottom)/2.f);
288 }
289 
PointInside(const CPos & point) const290 bool CRect::PointInside(const CPos &point) const
291 {
292 	return (point.x >= left &&
293 			point.x <= right &&
294 			point.y >= top &&
295 			point.y <= bottom);
296 }
297 
Scale(float x,float y) const298 CRect CRect::Scale(float x, float y) const
299 {
300 	return CRect(left*x, top*y, right*x, bottom*y);
301 }
302 
303 /*************************************************************************/
304 
CPos()305 CPos::CPos() : x(0.f), y(0.f)
306 {
307 }
308 
CPos(const CSize & s)309 CPos::CPos(const CSize& s) : x(s.cx), y(s.cy)
310 {
311 }
312 
CPos(const float & _x,const float & _y)313 CPos::CPos(const float &_x, const float &_y) : x(_x), y(_y)
314 {
315 }
316 
317 // =
operator =(const CPos & a)318 CPos& CPos::operator = (const CPos& a)
319 {
320 	x = a.x;
321 	y = a.y;
322 	return *this;
323 }
324 
325 // ==
operator ==(const CPos & a) const326 bool CPos::operator ==(const CPos &a) const
327 {
328 	return	(x==a.x && y==a.y);
329 }
330 
331 // !=
operator !=(const CPos & a) const332 bool CPos::operator != (const CPos& a) const
333 {
334 	return !(*this==a);
335 }
336 
337 // - (the unary operator)
operator -(void) const338 CPos CPos::operator - (void) const
339 {
340 	return CPos(-x, -y);
341 }
342 
343 // + (the unary operator)
operator +(void) const344 CPos CPos::operator + (void) const
345 {
346 	return *this;
347 }
348 
349 // +
operator +(const CPos & a) const350 CPos CPos::operator + (const CPos& a) const
351 {
352 	return CPos(x+a.x, y+a.y);
353 }
354 
355 // +
operator +(const CSize & a) const356 CPos CPos::operator + (const CSize& a) const
357 {
358 	return CPos(x+a.cx, y+a.cy);
359 }
360 
361 // -
operator -(const CPos & a) const362 CPos CPos::operator - (const CPos& a) const
363 {
364 	return CPos(x-a.x, y-a.y);
365 }
366 
367 // -
operator -(const CSize & a) const368 CPos CPos::operator - (const CSize& a) const
369 {
370 	return CPos(x-a.cx, y-a.cy);
371 }
372 
373 // +=
operator +=(const CPos & a)374 void CPos::operator +=(const CPos& a)
375 {
376 	x += a.x;
377 	y += a.y;
378 }
379 
380 // +=
operator +=(const CSize & a)381 void CPos::operator +=(const CSize& a)
382 {
383 	x += a.cx;
384 	y += a.cy;
385 }
386 
387 // -=
operator -=(const CPos & a)388 void CPos::operator -=(const CPos& a)
389 {
390 	x -= a.x;
391 	y -= a.y;
392 }
393 
394 // -=
operator -=(const CSize & a)395 void CPos::operator -=(const CSize& a)
396 {
397 	x -= a.cx;
398 	y -= a.cy;
399 }
400 
401 /*************************************************************************/
402 
CSize()403 CSize::CSize() : cx(0.f), cy(0.f)
404 {
405 }
406 
CSize(const CRect & rect)407 CSize::CSize(const CRect &rect) : cx(rect.GetWidth()), cy(rect.GetHeight())
408 {
409 }
410 
CSize(const CPos & pos)411 CSize::CSize(const CPos &pos) : cx(pos.x), cy(pos.y)
412 {
413 }
414 
CSize(const float & _cx,const float & _cy)415 CSize::CSize(const float &_cx, const float &_cy) : cx(_cx), cy(_cy)
416 {
417 }
418 
419 // =
operator =(const CSize & a)420 CSize& CSize::operator = (const CSize& a)
421 {
422 	cx = a.cx;
423 	cy = a.cy;
424 	return *this;
425 }
426 
427 // ==
operator ==(const CSize & a) const428 bool CSize::operator ==(const CSize &a) const
429 {
430 	return	(cx==a.cx && cy==a.cy);
431 }
432 
433 // !=
operator !=(const CSize & a) const434 bool CSize::operator != (const CSize& a) const
435 {
436 	return !(*this==a);
437 }
438 
439 // - (the unary operator)
operator -(void) const440 CSize CSize::operator - (void) const
441 {
442 	return CSize(-cx, -cy);
443 }
444 
445 // + (the unary operator)
operator +(void) const446 CSize CSize::operator + (void) const
447 {
448 	return *this;
449 }
450 
451 // +
operator +(const CSize & a) const452 CSize CSize::operator + (const CSize& a) const
453 {
454 	return CSize(cx+a.cx, cy+a.cy);
455 }
456 
457 // -
operator -(const CSize & a) const458 CSize CSize::operator - (const CSize& a) const
459 {
460 	return CSize(cx-a.cx, cy-a.cy);
461 }
462 
463 // /
operator /(const float & a) const464 CSize CSize::operator / (const float& a) const
465 {
466 	return CSize(cx/a, cy/a);
467 }
468 
469 // *
operator *(const float & a) const470 CSize CSize::operator * (const float& a) const
471 {
472 	return CSize(cx*a, cy*a);
473 }
474 
475 // +=
operator +=(const CSize & a)476 void CSize::operator +=(const CSize& a)
477 {
478 	cx += a.cx;
479 	cy += a.cy;
480 }
481 
482 // -=
operator -=(const CSize & a)483 void CSize::operator -=(const CSize& a)
484 {
485 	cx -= a.cx;
486 	cy -= a.cy;
487 }
488 
489 // /=
operator /=(const float & a)490 void CSize::operator /=(const float& a)
491 {
492 	cx /= a;
493 	cy /= a;
494 }
495 
496 // *=
operator *=(const float & a)497 void CSize::operator *=(const float& a)
498 {
499 	cx *= a;
500 	cy *= a;
501 }
502