Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / gfx / geometry / rect.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/gfx/geometry/rect.h"
6
7 #include <algorithm>
8
9 #if defined(OS_WIN)
10 #include <windows.h>
11 #endif
12
13 #include "base/logging.h"
14 #include "base/strings/stringprintf.h"
15 #include "ui/gfx/geometry/insets.h"
16
17 namespace gfx {
18
19 #if defined(OS_WIN)
20 Rect::Rect(const RECT& r)
21     : origin_(r.left, r.top),
22       size_(std::abs(r.right - r.left), std::abs(r.bottom - r.top)) {
23 }
24 #elif defined(OS_MACOSX)
25 Rect::Rect(const CGRect& r)
26     : origin_(r.origin.x, r.origin.y), size_(r.size.width, r.size.height) {
27 }
28 #endif
29
30 #if defined(OS_WIN)
31 RECT Rect::ToRECT() const {
32   RECT r;
33   r.left = x();
34   r.right = right();
35   r.top = y();
36   r.bottom = bottom();
37   return r;
38 }
39 #elif defined(OS_MACOSX)
40 CGRect Rect::ToCGRect() const {
41   return CGRectMake(x(), y(), width(), height());
42 }
43 #endif
44
45 void AdjustAlongAxis(int dst_origin, int dst_size, int* origin, int* size) {
46   *size = std::min(dst_size, *size);
47   if (*origin < dst_origin)
48     *origin = dst_origin;
49   else
50     *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
51 }
52
53 }  // namespace
54
55 namespace gfx {
56
57 void Rect::Inset(const Insets& insets) {
58   Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
59 }
60
61 void Rect::Inset(int left, int top, int right, int bottom) {
62   origin_ += Vector2d(left, top);
63   set_width(std::max(width() - left - right, static_cast<int>(0)));
64   set_height(std::max(height() - top - bottom, static_cast<int>(0)));
65 }
66
67 void Rect::Offset(int horizontal, int vertical) {
68   origin_ += Vector2d(horizontal, vertical);
69 }
70
71 void Rect::operator+=(const Vector2d& offset) {
72   origin_ += offset;
73 }
74
75 void Rect::operator-=(const Vector2d& offset) {
76   origin_ -= offset;
77 }
78
79 Insets Rect::InsetsFrom(const Rect& inner) const {
80   return Insets(inner.y() - y(),
81                 inner.x() - x(),
82                 bottom() - inner.bottom(),
83                 right() - inner.right());
84 }
85
86 bool Rect::operator<(const Rect& other) const {
87   if (origin_ == other.origin_) {
88     if (width() == other.width()) {
89       return height() < other.height();
90     } else {
91       return width() < other.width();
92     }
93   } else {
94     return origin_ < other.origin_;
95   }
96 }
97
98 bool Rect::Contains(int point_x, int point_y) const {
99   return (point_x >= x()) && (point_x < right()) && (point_y >= y()) &&
100          (point_y < bottom());
101 }
102
103 bool Rect::Contains(const Rect& rect) const {
104   return (rect.x() >= x() && rect.right() <= right() && rect.y() >= y() &&
105           rect.bottom() <= bottom());
106 }
107
108 bool Rect::Intersects(const Rect& rect) const {
109   return !(IsEmpty() || rect.IsEmpty() || rect.x() >= right() ||
110            rect.right() <= x() || rect.y() >= bottom() || rect.bottom() <= y());
111 }
112
113 void Rect::Intersect(const Rect& rect) {
114   if (IsEmpty() || rect.IsEmpty()) {
115     SetRect(0, 0, 0, 0);
116     return;
117   }
118
119   int rx = std::max(x(), rect.x());
120   int ry = std::max(y(), rect.y());
121   int rr = std::min(right(), rect.right());
122   int rb = std::min(bottom(), rect.bottom());
123
124   if (rx >= rr || ry >= rb)
125     rx = ry = rr = rb = 0;  // non-intersecting
126
127   SetRect(rx, ry, rr - rx, rb - ry);
128 }
129
130 void Rect::Union(const Rect& rect) {
131   if (IsEmpty()) {
132     *this = rect;
133     return;
134   }
135   if (rect.IsEmpty())
136     return;
137
138   int rx = std::min(x(), rect.x());
139   int ry = std::min(y(), rect.y());
140   int rr = std::max(right(), rect.right());
141   int rb = std::max(bottom(), rect.bottom());
142
143   SetRect(rx, ry, rr - rx, rb - ry);
144 }
145
146 void Rect::Subtract(const Rect& rect) {
147   if (!Intersects(rect))
148     return;
149   if (rect.Contains(*this)) {
150     SetRect(0, 0, 0, 0);
151     return;
152   }
153
154   int rx = x();
155   int ry = y();
156   int rr = right();
157   int rb = bottom();
158
159   if (rect.y() <= y() && rect.bottom() >= bottom()) {
160     // complete intersection in the y-direction
161     if (rect.x() <= x()) {
162       rx = rect.right();
163     } else if (rect.right() >= right()) {
164       rr = rect.x();
165     }
166   } else if (rect.x() <= x() && rect.right() >= right()) {
167     // complete intersection in the x-direction
168     if (rect.y() <= y()) {
169       ry = rect.bottom();
170     } else if (rect.bottom() >= bottom()) {
171       rb = rect.y();
172     }
173   }
174   SetRect(rx, ry, rr - rx, rb - ry);
175 }
176
177 void Rect::AdjustToFit(const Rect& rect) {
178   int new_x = x();
179   int new_y = y();
180   int new_width = width();
181   int new_height = height();
182   AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
183   AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
184   SetRect(new_x, new_y, new_width, new_height);
185 }
186
187 Point Rect::CenterPoint() const {
188   return Point(x() + width() / 2, y() + height() / 2);
189 }
190
191 void Rect::ClampToCenteredSize(const Size& size) {
192   int new_width = std::min(width(), size.width());
193   int new_height = std::min(height(), size.height());
194   int new_x = x() + (width() - new_width) / 2;
195   int new_y = y() + (height() - new_height) / 2;
196   SetRect(new_x, new_y, new_width, new_height);
197 }
198
199 void Rect::SplitVertically(Rect* left_half, Rect* right_half) const {
200   DCHECK(left_half);
201   DCHECK(right_half);
202
203   left_half->SetRect(x(), y(), width() / 2, height());
204   right_half->SetRect(
205       left_half->right(), y(), width() - left_half->width(), height());
206 }
207
208 bool Rect::SharesEdgeWith(const Rect& rect) const {
209   return (y() == rect.y() && height() == rect.height() &&
210           (x() == rect.right() || right() == rect.x())) ||
211          (x() == rect.x() && width() == rect.width() &&
212           (y() == rect.bottom() || bottom() == rect.y()));
213 }
214
215 int Rect::ManhattanDistanceToPoint(const Point& point) const {
216   int x_distance =
217       std::max<int>(0, std::max(x() - point.x(), point.x() - right()));
218   int y_distance =
219       std::max<int>(0, std::max(y() - point.y(), point.y() - bottom()));
220
221   return x_distance + y_distance;
222 }
223
224 int Rect::ManhattanInternalDistance(const Rect& rect) const {
225   Rect c(*this);
226   c.Union(rect);
227
228   static const int kEpsilon = std::numeric_limits<int>::is_integer
229                                   ? 1
230                                   : std::numeric_limits<int>::epsilon();
231
232   int x = std::max<int>(0, c.width() - width() - rect.width() + kEpsilon);
233   int y = std::max<int>(0, c.height() - height() - rect.height() + kEpsilon);
234   return x + y;
235 }
236
237 std::string Rect::ToString() const {
238   return base::StringPrintf("%s %s",
239                             origin().ToString().c_str(),
240                             size().ToString().c_str());
241 }
242
243 Rect operator+(const Rect& lhs, const Vector2d& rhs) {
244   Rect result(lhs);
245   result += rhs;
246   return result;
247 }
248
249 Rect operator-(const Rect& lhs, const Vector2d& rhs) {
250   Rect result(lhs);
251   result -= rhs;
252   return result;
253 }
254
255 Rect IntersectRects(const Rect& a, const Rect& b) {
256   Rect result = a;
257   result.Intersect(b);
258   return result;
259 }
260
261 Rect UnionRects(const Rect& a, const Rect& b) {
262   Rect result = a;
263   result.Union(b);
264   return result;
265 }
266
267 Rect SubtractRects(const Rect& a, const Rect& b) {
268   Rect result = a;
269   result.Subtract(b);
270   return result;
271 }
272
273 Rect BoundingRect(const Point& p1, const Point& p2) {
274   int rx = std::min(p1.x(), p2.x());
275   int ry = std::min(p1.y(), p2.y());
276   int rr = std::max(p1.x(), p2.x());
277   int rb = std::max(p1.y(), p2.y());
278   return Rect(rx, ry, rr - rx, rb - ry);
279 }
280
281 }  // namespace gfx