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> |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 if (*origin < dst_origin) | 53 if (*origin < dst_origin) |
54 *origin = dst_origin; | 54 *origin = dst_origin; |
55 else | 55 else |
56 *origin = std::min(dst_origin + dst_size, *origin + *size) - *size; | 56 *origin = std::min(dst_origin + dst_size, *origin + *size) - *size; |
57 } | 57 } |
58 | 58 |
59 } // namespace | 59 } // namespace |
60 | 60 |
61 namespace gfx { | 61 namespace gfx { |
62 | 62 |
| 63 // This is the per-axis heuristic for picking the most useful origin and |
| 64 // width/height to represent the input range. |
| 65 static void SaturatedClampRange(int min, int max, int* origin, int* span) { |
| 66 if (max < min) { |
| 67 *span = 0; |
| 68 *origin = min; |
| 69 return; |
| 70 } |
| 71 |
| 72 int effective_span = base::SaturatedSubtraction(max, min); |
| 73 int span_loss = base::SaturatedSubtraction(max, min + effective_span); |
| 74 |
| 75 // If the desired width is within the limits of ints, we can just |
| 76 // use the simple computations to represent the range precisely. |
| 77 if (span_loss == 0) { |
| 78 *span = effective_span; |
| 79 *origin = min; |
| 80 return; |
| 81 } |
| 82 |
| 83 // Now we have to approximate. If one of min or max is close enough |
| 84 // to zero we choose to represent that one precisely. The other side is |
| 85 // probably practically "infinite", so we move it. |
| 86 if (base::SaturatedAbsolute(max) < std::numeric_limits<int>::max() / 2) { |
| 87 // Maintain origin + span == max. |
| 88 *span = effective_span; |
| 89 *origin = max - effective_span; |
| 90 } else if (base::SaturatedAbsolute(min) < |
| 91 std::numeric_limits<int>::max() / 2) { |
| 92 // Maintain origin == min. |
| 93 *span = effective_span; |
| 94 *origin = min; |
| 95 } else { |
| 96 // Both are big, so keep the center. |
| 97 *span = effective_span; |
| 98 *origin = min + span_loss / 2; |
| 99 } |
| 100 } |
| 101 |
| 102 void Rect::SetByBounds(int left, int top, int right, int bottom) { |
| 103 int x, y; |
| 104 int width, height; |
| 105 SaturatedClampRange(left, right, &x, &width); |
| 106 SaturatedClampRange(top, bottom, &y, &height); |
| 107 origin_.SetPoint(x, y); |
| 108 size_.SetSize(width, height); |
| 109 } |
| 110 |
63 void Rect::Inset(const Insets& insets) { | 111 void Rect::Inset(const Insets& insets) { |
64 Inset(insets.left(), insets.top(), insets.right(), insets.bottom()); | 112 Inset(insets.left(), insets.top(), insets.right(), insets.bottom()); |
65 } | 113 } |
66 | 114 |
67 void Rect::Inset(int left, int top, int right, int bottom) { | 115 void Rect::Inset(int left, int top, int right, int bottom) { |
68 origin_ += Vector2d(left, top); | 116 origin_ += Vector2d(left, top); |
69 // left+right might overflow/underflow, but width() - (left+right) might | 117 // left+right might overflow/underflow, but width() - (left+right) might |
70 // overflow as well. | 118 // overflow as well. |
71 set_width(base::SaturatedSubtraction(width(), | 119 set_width(base::SaturatedSubtraction(width(), |
72 base::SaturatedAddition(left, right))); | 120 base::SaturatedAddition(left, right))); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 rect.bottom() <= bottom()); | 169 rect.bottom() <= bottom()); |
122 } | 170 } |
123 | 171 |
124 bool Rect::Intersects(const Rect& rect) const { | 172 bool Rect::Intersects(const Rect& rect) const { |
125 return !(IsEmpty() || rect.IsEmpty() || rect.x() >= right() || | 173 return !(IsEmpty() || rect.IsEmpty() || rect.x() >= right() || |
126 rect.right() <= x() || rect.y() >= bottom() || rect.bottom() <= y()); | 174 rect.right() <= x() || rect.y() >= bottom() || rect.bottom() <= y()); |
127 } | 175 } |
128 | 176 |
129 void Rect::Intersect(const Rect& rect) { | 177 void Rect::Intersect(const Rect& rect) { |
130 if (IsEmpty() || rect.IsEmpty()) { | 178 if (IsEmpty() || rect.IsEmpty()) { |
131 SetRect(0, 0, 0, 0); | 179 SetRect(0, 0, 0, 0); // Throws away empty position. |
132 return; | 180 return; |
133 } | 181 } |
134 | 182 |
135 int rx = std::max(x(), rect.x()); | 183 int left = std::max(x(), rect.x()); |
136 int ry = std::max(y(), rect.y()); | 184 int top = std::max(y(), rect.y()); |
137 int rr = std::min(right(), rect.right()); | 185 int new_right = std::min(right(), rect.right()); |
138 int rb = std::min(bottom(), rect.bottom()); | 186 int new_bottom = std::min(bottom(), rect.bottom()); |
139 | 187 |
140 if (rx >= rr || ry >= rb) | 188 if (left >= new_right || top >= new_bottom) { |
141 rx = ry = rr = rb = 0; // non-intersecting | 189 SetRect(0, 0, 0, 0); // Throws away empty position. |
| 190 return; |
| 191 } |
142 | 192 |
143 SetRect(rx, ry, rr - rx, rb - ry); | 193 SetByBounds(left, top, new_right, new_bottom); |
144 } | 194 } |
145 | 195 |
146 void Rect::Union(const Rect& rect) { | 196 void Rect::Union(const Rect& rect) { |
147 if (IsEmpty()) { | 197 if (IsEmpty()) { |
148 *this = rect; | 198 *this = rect; |
149 return; | 199 return; |
150 } | 200 } |
151 if (rect.IsEmpty()) | 201 if (rect.IsEmpty()) |
152 return; | 202 return; |
153 | 203 |
154 int rx = std::min(x(), rect.x()); | 204 SetByBounds(std::min(x(), rect.x()), std::min(y(), rect.y()), |
155 int ry = std::min(y(), rect.y()); | 205 std::max(right(), rect.right()), |
156 int rr = std::max(right(), rect.right()); | 206 std::max(bottom(), rect.bottom())); |
157 int rb = std::max(bottom(), rect.bottom()); | |
158 | |
159 // Subtracting to get width/height might overflow integers, so clamp them. | |
160 SetRect(rx, ry, base::SaturatedSubtraction(rr, rx), | |
161 base::SaturatedSubtraction(rb, ry)); | |
162 } | 207 } |
163 | 208 |
164 void Rect::Subtract(const Rect& rect) { | 209 void Rect::Subtract(const Rect& rect) { |
165 if (!Intersects(rect)) | 210 if (!Intersects(rect)) |
166 return; | 211 return; |
167 if (rect.Contains(*this)) { | 212 if (rect.Contains(*this)) { |
168 SetRect(0, 0, 0, 0); | 213 SetRect(0, 0, 0, 0); |
169 return; | 214 return; |
170 } | 215 } |
171 | 216 |
(...skipping 10 matching lines...) Expand all Loading... |
182 rr = rect.x(); | 227 rr = rect.x(); |
183 } | 228 } |
184 } else if (rect.x() <= x() && rect.right() >= right()) { | 229 } else if (rect.x() <= x() && rect.right() >= right()) { |
185 // complete intersection in the x-direction | 230 // complete intersection in the x-direction |
186 if (rect.y() <= y()) { | 231 if (rect.y() <= y()) { |
187 ry = rect.bottom(); | 232 ry = rect.bottom(); |
188 } else if (rect.bottom() >= bottom()) { | 233 } else if (rect.bottom() >= bottom()) { |
189 rb = rect.y(); | 234 rb = rect.y(); |
190 } | 235 } |
191 } | 236 } |
192 SetRect(rx, ry, rr - rx, rb - ry); | 237 SetByBounds(rx, ry, rr, rb); |
193 } | 238 } |
194 | 239 |
195 void Rect::AdjustToFit(const Rect& rect) { | 240 void Rect::AdjustToFit(const Rect& rect) { |
196 int new_x = x(); | 241 int new_x = x(); |
197 int new_y = y(); | 242 int new_y = y(); |
198 int new_width = width(); | 243 int new_width = width(); |
199 int new_height = height(); | 244 int new_height = height(); |
200 AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width); | 245 AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width); |
201 AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height); | 246 AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height); |
202 SetRect(new_x, new_y, new_width, new_height); | 247 SetRect(new_x, new_y, new_width, new_height); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 return result; | 330 return result; |
286 } | 331 } |
287 | 332 |
288 Rect SubtractRects(const Rect& a, const Rect& b) { | 333 Rect SubtractRects(const Rect& a, const Rect& b) { |
289 Rect result = a; | 334 Rect result = a; |
290 result.Subtract(b); | 335 result.Subtract(b); |
291 return result; | 336 return result; |
292 } | 337 } |
293 | 338 |
294 Rect BoundingRect(const Point& p1, const Point& p2) { | 339 Rect BoundingRect(const Point& p1, const Point& p2) { |
295 int rx = std::min(p1.x(), p2.x()); | 340 Rect result; |
296 int ry = std::min(p1.y(), p2.y()); | 341 result.SetByBounds(std::min(p1.x(), p2.x()), std::min(p1.y(), p2.y()), |
297 int rr = std::max(p1.x(), p2.x()); | 342 std::max(p1.x(), p2.x()), std::max(p1.y(), p2.y())); |
298 int rb = std::max(p1.y(), p2.y()); | 343 return result; |
299 return Rect(rx, ry, rr - rx, rb - ry); | |
300 } | 344 } |
301 | 345 |
302 } // namespace gfx | 346 } // namespace gfx |
OLD | NEW |