Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: ui/gfx/geometry/rect.cc

Issue 2744423002: Handle large rects better. (Closed)
Patch Set: Add comment and change constant reference. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/geometry/rect.h ('k') | ui/gfx/geometry/rect_conversions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « ui/gfx/geometry/rect.h ('k') | ui/gfx/geometry/rect_conversions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698