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.
5 #include "ui/gfx/geometry/rect.h"
12 #include <CoreGraphics/CoreGraphics.h>
13 #elif defined(OS_MACOSX)
14 #include <ApplicationServices/ApplicationServices.h>
17 #include "base/logging.h"
18 #include "base/strings/stringprintf.h"
19 #include "ui/gfx/geometry/insets.h"
24 Rect::Rect(const RECT
& r
)
25 : origin_(r
.left
, r
.top
),
26 size_(std::abs(r
.right
- r
.left
), std::abs(r
.bottom
- r
.top
)) {
28 #elif defined(OS_MACOSX)
29 Rect::Rect(const CGRect
& r
)
30 : origin_(r
.origin
.x
, r
.origin
.y
), size_(r
.size
.width
, r
.size
.height
) {
35 RECT
Rect::ToRECT() const {
43 #elif defined(OS_MACOSX)
44 CGRect
Rect::ToCGRect() const {
45 return CGRectMake(x(), y(), width(), height());
49 void AdjustAlongAxis(int dst_origin
, int dst_size
, int* origin
, int* size
) {
50 *size
= std::min(dst_size
, *size
);
51 if (*origin
< dst_origin
)
54 *origin
= std::min(dst_origin
+ dst_size
, *origin
+ *size
) - *size
;
61 void Rect::Inset(const Insets
& insets
) {
62 Inset(insets
.left(), insets
.top(), insets
.right(), insets
.bottom());
65 void Rect::Inset(int left
, int top
, int right
, int bottom
) {
66 origin_
+= Vector2d(left
, top
);
67 set_width(std::max(width() - left
- right
, static_cast<int>(0)));
68 set_height(std::max(height() - top
- bottom
, static_cast<int>(0)));
71 void Rect::Offset(int horizontal
, int vertical
) {
72 origin_
+= Vector2d(horizontal
, vertical
);
75 void Rect::operator+=(const Vector2d
& offset
) {
79 void Rect::operator-=(const Vector2d
& offset
) {
83 Insets
Rect::InsetsFrom(const Rect
& inner
) const {
84 return Insets(inner
.y() - y(),
86 bottom() - inner
.bottom(),
87 right() - inner
.right());
90 bool Rect::operator<(const Rect
& other
) const {
91 if (origin_
== other
.origin_
) {
92 if (width() == other
.width()) {
93 return height() < other
.height();
95 return width() < other
.width();
98 return origin_
< other
.origin_
;
102 bool Rect::Contains(int point_x
, int point_y
) const {
103 return (point_x
>= x()) && (point_x
< right()) && (point_y
>= y()) &&
104 (point_y
< bottom());
107 bool Rect::Contains(const Rect
& rect
) const {
108 return (rect
.x() >= x() && rect
.right() <= right() && rect
.y() >= y() &&
109 rect
.bottom() <= bottom());
112 bool Rect::Intersects(const Rect
& rect
) const {
113 return !(IsEmpty() || rect
.IsEmpty() || rect
.x() >= right() ||
114 rect
.right() <= x() || rect
.y() >= bottom() || rect
.bottom() <= y());
117 void Rect::Intersect(const Rect
& rect
) {
118 if (IsEmpty() || rect
.IsEmpty()) {
123 int rx
= std::max(x(), rect
.x());
124 int ry
= std::max(y(), rect
.y());
125 int rr
= std::min(right(), rect
.right());
126 int rb
= std::min(bottom(), rect
.bottom());
128 if (rx
>= rr
|| ry
>= rb
)
129 rx
= ry
= rr
= rb
= 0; // non-intersecting
131 SetRect(rx
, ry
, rr
- rx
, rb
- ry
);
134 void Rect::Union(const Rect
& rect
) {
142 int rx
= std::min(x(), rect
.x());
143 int ry
= std::min(y(), rect
.y());
144 int rr
= std::max(right(), rect
.right());
145 int rb
= std::max(bottom(), rect
.bottom());
147 SetRect(rx
, ry
, rr
- rx
, rb
- ry
);
150 void Rect::Subtract(const Rect
& rect
) {
151 if (!Intersects(rect
))
153 if (rect
.Contains(*this)) {
163 if (rect
.y() <= y() && rect
.bottom() >= bottom()) {
164 // complete intersection in the y-direction
165 if (rect
.x() <= x()) {
167 } else if (rect
.right() >= right()) {
170 } else if (rect
.x() <= x() && rect
.right() >= right()) {
171 // complete intersection in the x-direction
172 if (rect
.y() <= y()) {
174 } else if (rect
.bottom() >= bottom()) {
178 SetRect(rx
, ry
, rr
- rx
, rb
- ry
);
181 void Rect::AdjustToFit(const Rect
& rect
) {
184 int new_width
= width();
185 int new_height
= height();
186 AdjustAlongAxis(rect
.x(), rect
.width(), &new_x
, &new_width
);
187 AdjustAlongAxis(rect
.y(), rect
.height(), &new_y
, &new_height
);
188 SetRect(new_x
, new_y
, new_width
, new_height
);
191 Point
Rect::CenterPoint() const {
192 return Point(x() + width() / 2, y() + height() / 2);
195 void Rect::ClampToCenteredSize(const Size
& size
) {
196 int new_width
= std::min(width(), size
.width());
197 int new_height
= std::min(height(), size
.height());
198 int new_x
= x() + (width() - new_width
) / 2;
199 int new_y
= y() + (height() - new_height
) / 2;
200 SetRect(new_x
, new_y
, new_width
, new_height
);
203 void Rect::SplitVertically(Rect
* left_half
, Rect
* right_half
) const {
207 left_half
->SetRect(x(), y(), width() / 2, height());
209 left_half
->right(), y(), width() - left_half
->width(), height());
212 bool Rect::SharesEdgeWith(const Rect
& rect
) const {
213 return (y() == rect
.y() && height() == rect
.height() &&
214 (x() == rect
.right() || right() == rect
.x())) ||
215 (x() == rect
.x() && width() == rect
.width() &&
216 (y() == rect
.bottom() || bottom() == rect
.y()));
219 int Rect::ManhattanDistanceToPoint(const Point
& point
) const {
221 std::max
<int>(0, std::max(x() - point
.x(), point
.x() - right()));
223 std::max
<int>(0, std::max(y() - point
.y(), point
.y() - bottom()));
225 return x_distance
+ y_distance
;
228 int Rect::ManhattanInternalDistance(const Rect
& rect
) const {
232 static const int kEpsilon
= std::numeric_limits
<int>::is_integer
234 : std::numeric_limits
<int>::epsilon();
236 int x
= std::max
<int>(0, c
.width() - width() - rect
.width() + kEpsilon
);
237 int y
= std::max
<int>(0, c
.height() - height() - rect
.height() + kEpsilon
);
241 std::string
Rect::ToString() const {
242 return base::StringPrintf("%s %s",
243 origin().ToString().c_str(),
244 size().ToString().c_str());
247 Rect
operator+(const Rect
& lhs
, const Vector2d
& rhs
) {
253 Rect
operator-(const Rect
& lhs
, const Vector2d
& rhs
) {
259 Rect
IntersectRects(const Rect
& a
, const Rect
& b
) {
265 Rect
UnionRects(const Rect
& a
, const Rect
& b
) {
271 Rect
SubtractRects(const Rect
& a
, const Rect
& b
) {
277 Rect
BoundingRect(const Point
& p1
, const Point
& p2
) {
278 int rx
= std::min(p1
.x(), p2
.x());
279 int ry
= std::min(p1
.y(), p2
.y());
280 int rr
= std::max(p1
.x(), p2
.x());
281 int rb
= std::max(p1
.y(), p2
.y());
282 return Rect(rx
, ry
, rr
- rx
, rb
- ry
);