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 // Defines a simple integer rectangle class. The containment semantics | 5 // Defines a simple integer rectangle class. The containment semantics |
6 // are array-like; that is, the coordinate (x, y) is considered to be | 6 // are array-like; that is, the coordinate (x, y) is considered to be |
7 // contained by the rectangle, but the coordinate (x + width, y) is not. | 7 // contained by the rectangle, but the coordinate (x + width, y) is not. |
8 // The class will happily let you create malformed rectangles (that is, | 8 // The class will happily let you create malformed rectangles (that is, |
9 // rectangles with negative width and/or height), but there will be assertions | 9 // rectangles with negative width and/or height), but there will be assertions |
10 // in the operations (such as Contains()) to complain in this case. | 10 // in the operations (such as Contains()) to complain in this case. |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 namespace gfx { | 31 namespace gfx { |
32 | 32 |
33 class Insets; | 33 class Insets; |
34 | 34 |
35 class GFX_EXPORT Rect { | 35 class GFX_EXPORT Rect { |
36 public: | 36 public: |
37 constexpr Rect() = default; | 37 constexpr Rect() = default; |
38 constexpr Rect(int width, int height) : size_(width, height) {} | 38 constexpr Rect(int width, int height) : size_(width, height) {} |
39 constexpr Rect(int x, int y, int width, int height) | 39 constexpr Rect(int x, int y, int width, int height) |
40 : origin_(x, y), size_(width, height) {} | 40 : origin_(x, y), |
| 41 size_(GetClampedValue(x, width), GetClampedValue(y, height)) {} |
41 constexpr explicit Rect(const Size& size) : size_(size) {} | 42 constexpr explicit Rect(const Size& size) : size_(size) {} |
42 constexpr Rect(const Point& origin, const Size& size) | 43 constexpr Rect(const Point& origin, const Size& size) |
43 : origin_(origin), size_(size) {} | 44 : origin_(origin), |
| 45 size_(GetClampedValue(origin.x(), size.width()), |
| 46 GetClampedValue(origin.y(), size.height())) {} |
44 | 47 |
45 #if defined(OS_WIN) | 48 #if defined(OS_WIN) |
46 explicit Rect(const RECT& r); | 49 explicit Rect(const RECT& r); |
47 #elif defined(OS_MACOSX) | 50 #elif defined(OS_MACOSX) |
48 explicit Rect(const CGRect& r); | 51 explicit Rect(const CGRect& r); |
49 #endif | 52 #endif |
50 | 53 |
51 #if defined(OS_WIN) | 54 #if defined(OS_WIN) |
52 // Construct an equivalent Win32 RECT object. | 55 // Construct an equivalent Win32 RECT object. |
53 RECT ToRECT() const; | 56 RECT ToRECT() const; |
54 #elif defined(OS_MACOSX) | 57 #elif defined(OS_MACOSX) |
55 // Construct an equivalent CoreGraphics object. | 58 // Construct an equivalent CoreGraphics object. |
56 CGRect ToCGRect() const; | 59 CGRect ToCGRect() const; |
57 #endif | 60 #endif |
58 | 61 |
59 constexpr int x() const { return origin_.x(); } | 62 constexpr int x() const { return origin_.x(); } |
60 void set_x(int x) { origin_.set_x(x); } | 63 void set_x(int x) { |
| 64 origin_.set_x(x); |
| 65 size_.set_width(GetClampedValue(x, width())); |
| 66 } |
61 | 67 |
62 constexpr int y() const { return origin_.y(); } | 68 constexpr int y() const { return origin_.y(); } |
63 void set_y(int y) { origin_.set_y(y); } | 69 void set_y(int y) { |
| 70 origin_.set_y(y); |
| 71 size_.set_height(GetClampedValue(y, height())); |
| 72 } |
64 | 73 |
65 constexpr int width() const { return size_.width(); } | 74 constexpr int width() const { return size_.width(); } |
66 void set_width(int width) { size_.set_width(width); } | 75 void set_width(int width) { size_.set_width(GetClampedValue(x(), width)); } |
67 | 76 |
68 constexpr int height() const { return size_.height(); } | 77 constexpr int height() const { return size_.height(); } |
69 void set_height(int height) { size_.set_height(height); } | 78 void set_height(int height) { |
| 79 size_.set_height(GetClampedValue(y(), height)); |
| 80 } |
70 | 81 |
71 constexpr const Point& origin() const { return origin_; } | 82 constexpr const Point& origin() const { return origin_; } |
72 void set_origin(const Point& origin) { origin_ = origin; } | 83 void set_origin(const Point& origin) { |
| 84 origin_ = origin; |
| 85 // Ensure that width and height remain valid. |
| 86 set_width(width()); |
| 87 set_height(height()); |
| 88 } |
73 | 89 |
74 constexpr const Size& size() const { return size_; } | 90 constexpr const Size& size() const { return size_; } |
75 void set_size(const Size& size) { size_ = size; } | 91 void set_size(const Size& size) { |
| 92 set_width(size.width()); |
| 93 set_height(size.height()); |
| 94 } |
76 | 95 |
77 constexpr int right() const { return x() + width(); } | 96 constexpr int right() const { return x() + width(); } |
78 constexpr int bottom() const { return y() + height(); } | 97 constexpr int bottom() const { return y() + height(); } |
79 | 98 |
80 constexpr Point top_right() const { return Point(right(), y()); } | 99 constexpr Point top_right() const { return Point(right(), y()); } |
81 constexpr Point bottom_left() const { return Point(x(), bottom()); } | 100 constexpr Point bottom_left() const { return Point(x(), bottom()); } |
82 constexpr Point bottom_right() const { return Point(right(), bottom()); } | 101 constexpr Point bottom_right() const { return Point(right(), bottom()); } |
83 | 102 |
84 Vector2d OffsetFromOrigin() const { return Vector2d(x(), y()); } | 103 Vector2d OffsetFromOrigin() const { return Vector2d(x(), y()); } |
85 | 104 |
86 void SetRect(int x, int y, int width, int height) { | 105 void SetRect(int x, int y, int width, int height) { |
87 origin_.SetPoint(x, y); | 106 origin_.SetPoint(x, y); |
88 size_.SetSize(width, height); | 107 // Ensure that width and height remain valid. |
| 108 set_width(width); |
| 109 set_height(height); |
89 } | 110 } |
90 | 111 |
91 // Shrink the rectangle by a horizontal and vertical distance on all sides. | 112 // Shrink the rectangle by a horizontal and vertical distance on all sides. |
92 void Inset(int horizontal, int vertical) { | 113 void Inset(int horizontal, int vertical) { |
93 Inset(horizontal, vertical, horizontal, vertical); | 114 Inset(horizontal, vertical, horizontal, vertical); |
94 } | 115 } |
95 | 116 |
96 // Shrink the rectangle by the given insets. | 117 // Shrink the rectangle by the given insets. |
97 void Inset(const Insets& insets); | 118 void Inset(const Insets& insets); |
98 | 119 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 // returns the smallest non-zero value appropriate for int. | 198 // returns the smallest non-zero value appropriate for int. |
178 int ManhattanInternalDistance(const Rect& rect) const; | 199 int ManhattanInternalDistance(const Rect& rect) const; |
179 | 200 |
180 std::string ToString() const; | 201 std::string ToString() const; |
181 | 202 |
182 bool ApproximatelyEqual(const Rect& rect, int tolerance) const; | 203 bool ApproximatelyEqual(const Rect& rect, int tolerance) const; |
183 | 204 |
184 private: | 205 private: |
185 gfx::Point origin_; | 206 gfx::Point origin_; |
186 gfx::Size size_; | 207 gfx::Size size_; |
| 208 |
| 209 // Clamp the size to avoid integer overflow in bottom() and right(). |
| 210 // There are three conditions to determine whether there is a potential |
| 211 // overflow: |
| 212 // 1) Origin > 0: if the origin is a negative value, origin + size will |
| 213 // definitely be less than int_max. |
| 214 // 2) size > 0: if size <= 0, it will be clamped to 0 making x + 0 valid for |
| 215 // all x. |
| 216 // 3) We cast the values to unsigned int because the compiler can optimize |
| 217 // this check away entirely but it is not smart enough to know that it |
| 218 // won't overflow. It can't overflow since origin is positive ensured by |
| 219 // part 1). If size > int_max - origin it will overflow when added to |
| 220 // origin. |
| 221 static constexpr int GetClampedValue(int origin, int size) { |
| 222 return origin > 0 && size > 0 && |
| 223 static_cast<unsigned>(std::numeric_limits<int>::max() - |
| 224 origin) < static_cast<unsigned>(size) |
| 225 ? std::numeric_limits<int>::max() - origin |
| 226 : size; |
| 227 } |
187 }; | 228 }; |
188 | 229 |
189 inline bool operator==(const Rect& lhs, const Rect& rhs) { | 230 inline bool operator==(const Rect& lhs, const Rect& rhs) { |
190 return lhs.origin() == rhs.origin() && lhs.size() == rhs.size(); | 231 return lhs.origin() == rhs.origin() && lhs.size() == rhs.size(); |
191 } | 232 } |
192 | 233 |
193 inline bool operator!=(const Rect& lhs, const Rect& rhs) { | 234 inline bool operator!=(const Rect& lhs, const Rect& rhs) { |
194 return !(lhs == rhs); | 235 return !(lhs == rhs); |
195 } | 236 } |
196 | 237 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 } | 311 } |
271 | 312 |
272 // This is declared here for use in gtest-based unit tests but is defined in | 313 // This is declared here for use in gtest-based unit tests but is defined in |
273 // the //ui/gfx:test_support target. Depend on that to use this in your unit | 314 // the //ui/gfx:test_support target. Depend on that to use this in your unit |
274 // test. This should not be used in production code - call ToString() instead. | 315 // test. This should not be used in production code - call ToString() instead. |
275 void PrintTo(const Rect& rect, ::std::ostream* os); | 316 void PrintTo(const Rect& rect, ::std::ostream* os); |
276 | 317 |
277 } // namespace gfx | 318 } // namespace gfx |
278 | 319 |
279 #endif // UI_GFX_GEOMETRY_RECT_H_ | 320 #endif // UI_GFX_GEOMETRY_RECT_H_ |
OLD | NEW |