2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
12 // under gcc, inline will only take place if optimizations are applied (-O). this will force inline even with optimizations.
13 #define XBMC_FORCE_INLINE __attribute__((always_inline))
15 #define XBMC_FORCE_INLINE
22 template <typename T
> class CPointGen
25 typedef CPointGen
<T
> this_type
;
27 CPointGen() noexcept
= default;
29 constexpr CPointGen(T a
, T b
)
33 template<class U
> explicit constexpr CPointGen(const CPointGen
<U
>& rhs
)
34 : x
{static_cast<T
> (rhs
.x
)}, y
{static_cast<T
> (rhs
.y
)}
37 constexpr this_type
operator+(const this_type
&point
) const
39 return {x
+ point
.x
, y
+ point
.y
};
42 this_type
& operator+=(const this_type
&point
)
49 constexpr this_type
operator-(const this_type
&point
) const
51 return {x
- point
.x
, y
- point
.y
};
54 this_type
& operator-=(const this_type
&point
)
61 constexpr this_type
operator*(T factor
) const
63 return {x
* factor
, y
* factor
};
66 this_type
& operator*=(T factor
)
73 constexpr this_type
operator/(T factor
) const
75 return {x
/ factor
, y
/ factor
};
78 this_type
& operator/=(T factor
)
89 constexpr bool operator==(const CPointGen
<T
> &point1
, const CPointGen
<T
> &point2
) noexcept
91 return (point1
.x
== point2
.x
&& point1
.y
== point2
.y
);
95 constexpr bool operator!=(const CPointGen
<T
> &point1
, const CPointGen
<T
> &point2
) noexcept
97 return !(point1
== point2
);
100 using CPoint
= CPointGen
<float>;
101 using CPointInt
= CPointGen
<int>;
105 * Generic two-dimensional size representation
107 * Class invariant: width and height are both non-negative
108 * Throws std::out_of_range if invariant would be violated. The class
109 * is exception-safe. If modification would violate the invariant, the size
112 template <typename T
> class CSizeGen
116 void CheckSet(T width
, T height
)
120 throw std::out_of_range("Size may not have negative width");
124 throw std::out_of_range("Size may not have negative height");
131 typedef CSizeGen
<T
> this_type
;
133 CSizeGen() noexcept
= default;
135 CSizeGen(T width
, T height
)
137 CheckSet(width
, height
);
150 void SetWidth(T width
)
152 CheckSet(width
, m_h
);
155 void SetHeight(T height
)
157 CheckSet(m_w
, height
);
160 void Set(T width
, T height
)
162 CheckSet(width
, height
);
167 return (m_w
== static_cast<T
> (0) && m_h
== static_cast<T
> (0));
175 CPointGen
<T
> ToPoint() const
180 template<class U
> explicit CSizeGen
<T
>(const CSizeGen
<U
>& rhs
)
182 CheckSet(static_cast<T
> (rhs
.m_w
), static_cast<T
> (rhs
.m_h
));
185 this_type
operator+(const this_type
& size
) const
187 return {m_w
+ size
.m_w
, m_h
+ size
.m_h
};
190 this_type
& operator+=(const this_type
& size
)
192 CheckSet(m_w
+ size
.m_w
, m_h
+ size
.m_h
);
196 this_type
operator-(const this_type
& size
) const
198 return {m_w
- size
.m_w
, m_h
- size
.m_h
};
201 this_type
& operator-=(const this_type
& size
)
203 CheckSet(m_w
- size
.m_w
, m_h
- size
.m_h
);
207 this_type
operator*(T factor
) const
209 return {m_w
* factor
, m_h
* factor
};
212 this_type
& operator*=(T factor
)
214 CheckSet(m_w
* factor
, m_h
* factor
);
218 this_type
operator/(T factor
) const
220 return {m_w
/ factor
, m_h
/ factor
};
223 this_type
& operator/=(T factor
)
225 CheckSet(m_w
/ factor
, m_h
/ factor
);
231 inline bool operator==(const CSizeGen
<T
>& size1
, const CSizeGen
<T
>& size2
) noexcept
233 return (size1
.Width() == size2
.Width() && size1
.Height() == size2
.Height());
237 inline bool operator!=(const CSizeGen
<T
>& size1
, const CSizeGen
<T
>& size2
) noexcept
239 return !(size1
== size2
);
242 using CSize
= CSizeGen
<float>;
243 using CSizeInt
= CSizeGen
<int>;
246 template <typename T
> class CRectGen
249 typedef CRectGen
<T
> this_type
;
250 typedef CPointGen
<T
> point_type
;
251 typedef CSizeGen
<T
> size_type
;
253 CRectGen() noexcept
= default;
255 constexpr CRectGen(T left
, T top
, T right
, T bottom
)
256 : x1
{left
}, y1
{top
}, x2
{right
}, y2
{bottom
}
259 constexpr CRectGen(const point_type
&p1
, const point_type
&p2
)
260 : x1
{p1
.x
}, y1
{p1
.y
}, x2
{p2
.x
}, y2
{p2
.y
}
263 constexpr CRectGen(const point_type
&origin
, const size_type
&size
)
264 : x1
{origin
.x
}, y1
{origin
.y
}, x2
{x1
+ size
.Width()}, y2
{y1
+ size
.Height()}
267 template<class U
> explicit constexpr CRectGen(const CRectGen
<U
>& rhs
)
268 : x1
{static_cast<T
> (rhs
.x1
)}, y1
{static_cast<T
> (rhs
.y1
)}, x2
{static_cast<T
> (rhs
.x2
)}, y2
{static_cast<T
> (rhs
.y2
)}
271 void SetRect(T left
, T top
, T right
, T bottom
)
279 constexpr bool PtInRect(const point_type
&point
) const
281 return (x1
<= point
.x
&& point
.x
<= x2
&& y1
<= point
.y
&& point
.y
<= y2
);
284 this_type
& operator-=(const point_type
&point
) XBMC_FORCE_INLINE
293 constexpr this_type
operator-(const point_type
&point
) const
295 return {x1
- point
.x
, y1
- point
.y
, x2
- point
.x
, y2
- point
.y
};
298 this_type
& operator+=(const point_type
&point
) XBMC_FORCE_INLINE
307 constexpr this_type
operator+(const point_type
&point
) const
309 return {x1
+ point
.x
, y1
+ point
.y
, x2
+ point
.x
, y2
+ point
.y
};
312 this_type
& operator-=(const size_type
&size
)
319 constexpr this_type
operator-(const size_type
&size
) const
321 return {x1
, y1
, x2
- size
.Width(), y2
- size
.Height()};
324 this_type
& operator+=(const size_type
&size
)
331 constexpr this_type
operator+(const size_type
&size
) const
333 return {x1
, y1
, x2
+ size
.Width(), y2
+ size
.Height()};
336 this_type
& Intersect(const this_type
&rect
)
338 x1
= clamp_range(x1
, rect
.x1
, rect
.x2
);
339 x2
= clamp_range(x2
, rect
.x1
, rect
.x2
);
340 y1
= clamp_range(y1
, rect
.y1
, rect
.y2
);
341 y2
= clamp_range(y2
, rect
.y1
, rect
.y2
);
345 this_type
& Union(const this_type
&rect
)
349 else if (!rect
.IsEmpty())
351 x1
= std::min(x1
,rect
.x1
);
352 y1
= std::min(y1
,rect
.y1
);
354 x2
= std::max(x2
,rect
.x2
);
355 y2
= std::max(y2
,rect
.y2
);
361 constexpr bool IsEmpty() const XBMC_FORCE_INLINE
363 return (x2
- x1
) * (y2
- y1
) == 0;
366 constexpr point_type
P1() const XBMC_FORCE_INLINE
371 constexpr point_type
P2() const XBMC_FORCE_INLINE
376 constexpr T
Width() const XBMC_FORCE_INLINE
381 constexpr T
Height() const XBMC_FORCE_INLINE
386 constexpr T
Area() const XBMC_FORCE_INLINE
388 return Width() * Height();
391 size_type
ToSize() const
393 return {Width(), Height()};
396 std::vector
<this_type
> SubtractRect(this_type splitterRect
)
398 std::vector
<this_type
> newRectanglesList
;
399 this_type intersection
= splitterRect
.Intersect(*this);
401 if (!intersection
.IsEmpty())
405 // add rect above intersection if not empty
406 add
= this_type(x1
, y1
, x2
, intersection
.y1
);
408 newRectanglesList
.push_back(add
);
410 // add rect below intersection if not empty
411 add
= this_type(x1
, intersection
.y2
, x2
, y2
);
413 newRectanglesList
.push_back(add
);
415 // add rect left intersection if not empty
416 add
= this_type(x1
, intersection
.y1
, intersection
.x1
, intersection
.y2
);
418 newRectanglesList
.push_back(add
);
420 // add rect right intersection if not empty
421 add
= this_type(intersection
.x2
, intersection
.y1
, x2
, intersection
.y2
);
423 newRectanglesList
.push_back(add
);
427 newRectanglesList
.push_back(*this);
430 return newRectanglesList
;
433 std::vector
<this_type
> SubtractRects(std::vector
<this_type
> intersectionList
)
435 std::vector
<this_type
> fragmentsList
;
436 fragmentsList
.push_back(*this);
438 for (typename
std::vector
<this_type
>::iterator splitter
= intersectionList
.begin(); splitter
!= intersectionList
.end(); ++splitter
)
440 typename
std::vector
<this_type
> toAddList
;
442 for (typename
std::vector
<this_type
>::iterator fragment
= fragmentsList
.begin(); fragment
!= fragmentsList
.end(); ++fragment
)
444 std::vector
<this_type
> newFragmentsList
= fragment
->SubtractRect(*splitter
);
445 toAddList
.insert(toAddList
.end(), newFragmentsList
.begin(), newFragmentsList
.end());
448 fragmentsList
.clear();
449 fragmentsList
.insert(fragmentsList
.end(), toAddList
.begin(), toAddList
.end());
452 return fragmentsList
;
455 void GetQuad(point_type (&points
)[4])
457 points
[0] = { x1
, y1
};
458 points
[1] = { x2
, y1
};
459 points
[2] = { x2
, y2
};
460 points
[3] = { x1
, y2
};
463 T x1
{}, y1
{}, x2
{}, y2
{};
465 static constexpr T
clamp_range(T x
, T l
, T h
) XBMC_FORCE_INLINE
467 return (x
> h
) ? h
: ((x
< l
) ? l
: x
);
472 constexpr bool operator==(const CRectGen
<T
> &rect1
, const CRectGen
<T
> &rect2
) noexcept
474 return (rect1
.x1
== rect2
.x1
&& rect1
.y1
== rect2
.y1
&& rect1
.x2
== rect2
.x2
&& rect1
.y2
== rect2
.y2
);
478 constexpr bool operator!=(const CRectGen
<T
> &rect1
, const CRectGen
<T
> &rect2
) noexcept
480 return !(rect1
== rect2
);
483 using CRect
= CRectGen
<float>;
484 using CRectInt
= CRectGen
<int>;