PageRenderTime 30ms CodeModel.GetById 10ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/guilib/Geometry.h

http://github.com/xbmc/xbmc
C++ Header | 280 lines | 210 code | 46 blank | 24 comment | 29 complexity | 128b0255ac2ea0bb540b96ffc0954ca6 MD5 | raw file
  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
 33template <typename T> class CPointGen
 34{
 35public:
 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  bool operator !=(const this_type &point) const
 86  {
 87    if (x != point.x) return true;
 88    if (y != point.y) return true;
 89    return false;
 90  };
 91
 92  T x, y;
 93};
 94
 95template <typename T> class CRectGen
 96{
 97public:
 98  typedef CRectGen<T> this_type;
 99
100  CRectGen<T>() { x1 = y1 = x2 = y2 = 0;};
101  CRectGen<T>(T left, T top, T right, T bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; };
102  CRectGen<T>(const CPointGen<T> &p1, const CPointGen<T> &p2)
103  {
104    x1 = p1.x;
105    y1 = p1.y;
106    x2 = p2.x;
107    y2 = p2.y;
108  }
109
110  template <class U> CRectGen<T>(const CRectGen<U>& rhs)
111  {
112    x1 = rhs.x1;
113    y1 = rhs.y1;
114    x2 = rhs.x2;
115    y2 = rhs.y2;
116  }
117
118  void SetRect(T left, T top, T right, T bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; };
119
120  bool PtInRect(const CPointGen<T> &point) const
121  {
122    if (x1 <= point.x && point.x <= x2 && y1 <= point.y && point.y <= y2)
123      return true;
124    return false;
125  };
126
127  inline const this_type &operator -=(const CPointGen<T> &point) XBMC_FORCE_INLINE
128  {
129    x1 -= point.x;
130    y1 -= point.y;
131    x2 -= point.x;
132    y2 -= point.y;
133    return *this;
134  };
135
136  inline const this_type &operator +=(const CPointGen<T> &point) XBMC_FORCE_INLINE
137  {
138    x1 += point.x;
139    y1 += point.y;
140    x2 += point.x;
141    y2 += point.y;
142    return *this;
143  };
144
145  const this_type &Intersect(const this_type &rect)
146  {
147    x1 = clamp_range(x1, rect.x1, rect.x2);
148    x2 = clamp_range(x2, rect.x1, rect.x2);
149    y1 = clamp_range(y1, rect.y1, rect.y2);
150    y2 = clamp_range(y2, rect.y1, rect.y2);
151    return *this;
152  };
153
154  const this_type &Union(const this_type &rect)
155  {
156    if (IsEmpty())
157      *this = rect;
158    else if (!rect.IsEmpty())
159    {
160      x1 = std::min(x1,rect.x1);
161      y1 = std::min(y1,rect.y1);
162
163      x2 = std::max(x2,rect.x2);
164      y2 = std::max(y2,rect.y2);
165    }
166
167    return *this;
168  };
169
170  inline bool IsEmpty() const XBMC_FORCE_INLINE
171  {
172    return (x2 - x1) * (y2 - y1) == 0;
173  };
174
175  inline CPointGen<T> P1() const XBMC_FORCE_INLINE
176  {
177    return CPointGen<T>(x1, y1);
178  }
179
180  inline CPointGen<T> P2() const XBMC_FORCE_INLINE
181  {
182    return CPointGen<T>(x2, y2);
183  }
184
185  inline T Width() const XBMC_FORCE_INLINE
186  {
187    return x2 - x1;
188  };
189
190  inline T Height() const XBMC_FORCE_INLINE
191  {
192    return y2 - y1;
193  };
194
195  inline T Area() const XBMC_FORCE_INLINE
196  {
197    return Width() * Height();
198  };
199
200  std::vector<this_type> SubtractRect(this_type splitterRect)
201  {
202    std::vector<this_type> newRectaglesList;
203    this_type intersection = splitterRect.Intersect(*this);
204
205    if (!intersection.IsEmpty())
206    {
207      this_type add;
208
209      // add rect above intersection if not empty
210      add = this_type(x1, y1, x2, intersection.y1);
211      if (!add.IsEmpty())
212        newRectaglesList.push_back(add);
213
214      // add rect below intersection if not empty
215      add = this_type(x1, intersection.y2, x2, y2);
216      if (!add.IsEmpty())
217        newRectaglesList.push_back(add);
218
219      // add rect left intersection if not empty
220      add = this_type(x1, intersection.y1, intersection.x1, intersection.y2);
221      if (!add.IsEmpty())
222        newRectaglesList.push_back(add);
223
224      // add rect right intersection if not empty
225      add = this_type(intersection.x2, intersection.y1, x2, intersection.y2);
226      if (!add.IsEmpty())
227        newRectaglesList.push_back(add);
228    }
229    else
230    {
231      newRectaglesList.push_back(*this);
232    }
233
234    return newRectaglesList;
235  }
236
237  std::vector<this_type> SubtractRects(std::vector<this_type > intersectionList)
238  {
239    std::vector<this_type> fragmentsList;
240    fragmentsList.push_back(*this);
241
242    for (typename std::vector<this_type>::iterator splitter = intersectionList.begin(); splitter != intersectionList.end(); ++splitter)
243    {
244      typename std::vector<this_type> toAddList;
245
246      for (typename std::vector<this_type>::iterator fragment = fragmentsList.begin(); fragment != fragmentsList.end(); ++fragment)
247      {
248        std::vector<this_type> newFragmentsList = fragment->SubtractRect(*splitter);
249        toAddList.insert(toAddList.end(), newFragmentsList.begin(), newFragmentsList.end());
250      }
251
252      fragmentsList.clear();
253      fragmentsList.insert(fragmentsList.end(), toAddList.begin(), toAddList.end());
254    }
255
256    return fragmentsList;
257  }
258
259  bool operator !=(const this_type &rect) const
260  {
261    if (x1 != rect.x1) return true;
262    if (x2 != rect.x2) return true;
263    if (y1 != rect.y1) return true;
264    if (y2 != rect.y2) return true;
265    return false;
266  };
267
268  T x1, y1, x2, y2;
269private:
270  inline static T clamp_range(T x, T l, T h) XBMC_FORCE_INLINE
271  {
272    return (x > h) ? h : ((x < l) ? l : x);
273  }
274};
275
276typedef CPointGen<float> CPoint;
277typedef CPointGen<int>   CPointInt;
278
279typedef CRectGen<float>  CRect;
280typedef CRectGen<int>    CRectInt;