OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/geometry/rect.h" | 5 #include "ui/gfx/geometry/rect.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #if defined(OS_WIN) | 9 #if defined(OS_WIN) |
10 #include <windows.h> | 10 #include <windows.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "ui/gfx/geometry/insets.h" | 15 #include "ui/gfx/geometry/insets.h" |
16 #include "ui/gfx/geometry/rect_base_impl.h" | |
17 | 16 |
18 namespace gfx { | 17 namespace gfx { |
19 | 18 |
20 template class RectBase<Rect, Point, Size, Insets, Vector2d, int>; | |
21 | |
22 typedef class RectBase<Rect, Point, Size, Insets, Vector2d, int> RectBaseT; | |
23 | |
24 #if defined(OS_WIN) | 19 #if defined(OS_WIN) |
25 Rect::Rect(const RECT& r) | 20 Rect::Rect(const RECT& r) |
26 : RectBaseT(gfx::Point(r.left, r.top)) { | 21 : origin_(r.left, r.top), |
27 set_width(std::abs(r.right - r.left)); | 22 size_(std::abs(r.right - r.left), std::abs(r.bottom - r.top)) { |
28 set_height(std::abs(r.bottom - r.top)); | |
29 } | 23 } |
30 #elif defined(OS_MACOSX) | 24 #elif defined(OS_MACOSX) |
31 Rect::Rect(const CGRect& r) | 25 Rect::Rect(const CGRect& r) |
32 : RectBaseT(gfx::Point(r.origin.x, r.origin.y)) { | 26 : origin_(r.origin.x, r.origin.y), size_(r.size.width, r.size.height) { |
33 set_width(r.size.width); | |
34 set_height(r.size.height); | |
35 } | 27 } |
36 #endif | 28 #endif |
37 | 29 |
38 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
39 RECT Rect::ToRECT() const { | 31 RECT Rect::ToRECT() const { |
40 RECT r; | 32 RECT r; |
41 r.left = x(); | 33 r.left = x(); |
42 r.right = right(); | 34 r.right = right(); |
43 r.top = y(); | 35 r.top = y(); |
44 r.bottom = bottom(); | 36 r.bottom = bottom(); |
45 return r; | 37 return r; |
46 } | 38 } |
47 #elif defined(OS_MACOSX) | 39 #elif defined(OS_MACOSX) |
48 CGRect Rect::ToCGRect() const { | 40 CGRect Rect::ToCGRect() const { |
49 return CGRectMake(x(), y(), width(), height()); | 41 return CGRectMake(x(), y(), width(), height()); |
50 } | 42 } |
51 #endif | 43 #endif |
52 | 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 |
53 std::string Rect::ToString() const { | 237 std::string Rect::ToString() const { |
54 return base::StringPrintf("%s %s", | 238 return base::StringPrintf("%s %s", |
55 origin().ToString().c_str(), | 239 origin().ToString().c_str(), |
56 size().ToString().c_str()); | 240 size().ToString().c_str()); |
57 } | 241 } |
58 | 242 |
59 Rect operator+(const Rect& lhs, const Vector2d& rhs) { | 243 Rect operator+(const Rect& lhs, const Vector2d& rhs) { |
60 Rect result(lhs); | 244 Rect result(lhs); |
61 result += rhs; | 245 result += rhs; |
62 return result; | 246 return result; |
(...skipping 25 matching lines...) Expand all Loading... |
88 | 272 |
89 Rect BoundingRect(const Point& p1, const Point& p2) { | 273 Rect BoundingRect(const Point& p1, const Point& p2) { |
90 int rx = std::min(p1.x(), p2.x()); | 274 int rx = std::min(p1.x(), p2.x()); |
91 int ry = std::min(p1.y(), p2.y()); | 275 int ry = std::min(p1.y(), p2.y()); |
92 int rr = std::max(p1.x(), p2.x()); | 276 int rr = std::max(p1.x(), p2.x()); |
93 int rb = std::max(p1.y(), p2.y()); | 277 int rb = std::max(p1.y(), p2.y()); |
94 return Rect(rx, ry, rr - rx, rb - ry); | 278 return Rect(rx, ry, rr - rx, rb - ry); |
95 } | 279 } |
96 | 280 |
97 } // namespace gfx | 281 } // namespace gfx |
OLD | NEW |