[release] version bump to 13.0 beta1
[vuplus_xbmc] / xbmc / guilib / Geometry.h
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program 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
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #pragma once
22
23 #ifdef __GNUC__
24 // under gcc, inline will only take place if optimizations are applied (-O). this will force inline even whith optimizations.
25 #define XBMC_FORCE_INLINE __attribute__((always_inline))
26 #else
27 #define XBMC_FORCE_INLINE
28 #endif
29
30 #include <vector>
31 #include <algorithm>
32
33 template <typename T> class CPointGen
34 {
35 public:
36   typedef CPointGen<T> this_type;
37
38   CPointGen<T>()
39   {
40     x = 0; y = 0;
41   };
42
43   CPointGen<T>(T a, T b)
44   {
45     x = a;
46     y = b;
47   };
48
49   template <class U> CPointGen<T>(const CPointGen<U>& rhs)
50   {
51     x = rhs.x;
52     y = rhs.y;
53   }
54
55   this_type operator+(const this_type &point) const
56   {
57     this_type ans;
58     ans.x = x + point.x;
59     ans.y = y + point.y;
60     return ans;
61   };
62
63   const this_type &operator+=(const this_type &point)
64   {
65     x += point.x;
66     y += point.y;
67     return *this;
68   };
69
70   this_type operator-(const this_type &point) const
71   {
72     CPointGen<T> ans;
73     ans.x = x - point.x;
74     ans.y = y - point.y;
75     return ans;
76   };
77
78   const this_type &operator-=(const this_type &point)
79   {
80     x -= point.x;
81     y -= point.y;
82     return *this;
83   };
84
85   T x, y;
86 };
87
88 template <typename T> class CRectGen
89 {
90 public:
91   typedef CRectGen<T> this_type;
92
93   CRectGen<T>() { x1 = y1 = x2 = y2 = 0;};
94   CRectGen<T>(T left, T top, T right, T bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; };
95   CRectGen<T>(const CPointGen<T> &p1, const CPointGen<T> &p2)
96   {
97     x1 = p1.x;
98     y1 = p1.y;
99     x2 = p2.x;
100     y2 = p2.y;
101   }
102
103   template <class U> CRectGen<T>(const CRectGen<U>& rhs)
104   {
105     x1 = rhs.x1;
106     y1 = rhs.y1;
107     x2 = rhs.x2;
108     y2 = rhs.y2;
109   }
110
111   void SetRect(T left, T top, T right, T bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; };
112
113   bool PtInRect(const CPointGen<T> &point) const
114   {
115     if (x1 <= point.x && point.x <= x2 && y1 <= point.y && point.y <= y2)
116       return true;
117     return false;
118   };
119
120   inline const this_type &operator -=(const CPointGen<T> &point) XBMC_FORCE_INLINE
121   {
122     x1 -= point.x;
123     y1 -= point.y;
124     x2 -= point.x;
125     y2 -= point.y;
126     return *this;
127   };
128
129   inline const this_type &operator +=(const CPointGen<T> &point) XBMC_FORCE_INLINE
130   {
131     x1 += point.x;
132     y1 += point.y;
133     x2 += point.x;
134     y2 += point.y;
135     return *this;
136   };
137
138   const this_type &Intersect(const this_type &rect)
139   {
140     x1 = clamp_range(x1, rect.x1, rect.x2);
141     x2 = clamp_range(x2, rect.x1, rect.x2);
142     y1 = clamp_range(y1, rect.y1, rect.y2);
143     y2 = clamp_range(y2, rect.y1, rect.y2);
144     return *this;
145   };
146
147   const this_type &Union(const this_type &rect)
148   {
149     if (IsEmpty())
150       *this = rect;
151     else if (!rect.IsEmpty())
152     {
153       x1 = std::min(x1,rect.x1);
154       y1 = std::min(y1,rect.y1);
155
156       x2 = std::max(x2,rect.x2);
157       y2 = std::max(y2,rect.y2);
158     }
159
160     return *this;
161   };
162
163   inline bool IsEmpty() const XBMC_FORCE_INLINE
164   {
165     return (x2 - x1) * (y2 - y1) == 0;
166   };
167
168   inline CPointGen<T> P1() const XBMC_FORCE_INLINE
169   {
170     return CPointGen<T>(x1, y1);
171   }
172
173   inline CPointGen<T> P2() const XBMC_FORCE_INLINE
174   {
175     return CPointGen<T>(x2, y2);
176   }
177
178   inline T Width() const XBMC_FORCE_INLINE
179   {
180     return x2 - x1;
181   };
182
183   inline T Height() const XBMC_FORCE_INLINE
184   {
185     return y2 - y1;
186   };
187
188   inline T Area() const XBMC_FORCE_INLINE
189   {
190     return Width() * Height();
191   };
192
193   std::vector<this_type> SubtractRect(this_type splitterRect)
194   {
195     std::vector<this_type> newRectaglesList;
196     this_type intersection = splitterRect.Intersect(*this);
197
198     if (!intersection.IsEmpty())
199     {
200       this_type add;
201
202       // add rect above intersection if not empty
203       add = this_type(x1, y1, x2, intersection.y1);
204       if (!add.IsEmpty())
205         newRectaglesList.push_back(add);
206
207       // add rect below intersection if not empty
208       add = this_type(x1, intersection.y2, x2, y2);
209       if (!add.IsEmpty())
210         newRectaglesList.push_back(add);
211
212       // add rect left intersection if not empty
213       add = this_type(x1, intersection.y1, intersection.x1, intersection.y2);
214       if (!add.IsEmpty())
215         newRectaglesList.push_back(add);
216
217       // add rect right intersection if not empty
218       add = this_type(intersection.x2, intersection.y1, x2, intersection.y2);
219       if (!add.IsEmpty())
220         newRectaglesList.push_back(add);
221     }
222     else
223     {
224       newRectaglesList.push_back(*this);
225     }
226
227     return newRectaglesList;
228   }
229
230   std::vector<this_type> SubtractRects(std::vector<this_type > intersectionList)
231   {
232     std::vector<this_type> fragmentsList;
233     fragmentsList.push_back(*this);
234
235     for (typename std::vector<this_type>::iterator splitter = intersectionList.begin(); splitter != intersectionList.end(); ++splitter)
236     {
237       typename std::vector<this_type> toAddList;
238
239       for (typename std::vector<this_type>::iterator fragment = fragmentsList.begin(); fragment != fragmentsList.end(); ++fragment)
240       {
241         std::vector<this_type> newFragmentsList = fragment->SubtractRect(*splitter);
242         toAddList.insert(toAddList.end(), newFragmentsList.begin(), newFragmentsList.end());
243       }
244
245       fragmentsList.clear();
246       fragmentsList.insert(fragmentsList.end(), toAddList.begin(), toAddList.end());
247     }
248
249     return fragmentsList;
250   }
251
252   bool operator !=(const this_type &rect) const
253   {
254     if (x1 != rect.x1) return true;
255     if (x2 != rect.x2) return true;
256     if (y1 != rect.y1) return true;
257     if (y2 != rect.y2) return true;
258     return false;
259   };
260
261   T x1, y1, x2, y2;
262 private:
263   inline static float clamp_range(T x, T l, T h) XBMC_FORCE_INLINE
264   {
265     return (x > h) ? h : ((x < l) ? l : x);
266   }
267 };
268
269 typedef CPointGen<float> CPoint;
270 typedef CPointGen<int>   CPointInt;
271
272 typedef CRectGen<float>  CRect;
273 typedef CRectGen<int>    CRectInt;