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

Unified Diff: ui/gfx/geometry/rect.cc

Issue 2744423002: Handle large rects better. (Closed)
Patch Set: Add comment and change constant reference. Created 3 years, 9 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/geometry/rect.cc
diff --git a/ui/gfx/geometry/rect.cc b/ui/gfx/geometry/rect.cc
index f3c47b2b378e9b0bd8087330560a4b7541e6384d..b5ceda58291679a36ded337c80733a37fc52a67e 100644
--- a/ui/gfx/geometry/rect.cc
+++ b/ui/gfx/geometry/rect.cc
@@ -60,6 +60,54 @@ void AdjustAlongAxis(int dst_origin, int dst_size, int* origin, int* size) {
namespace gfx {
+// This is the per-axis heuristic for picking the most useful origin and
+// width/height to represent the input range.
+static void SaturatedClampRange(int min, int max, int* origin, int* span) {
+ if (max < min) {
+ *span = 0;
+ *origin = min;
+ return;
+ }
+
+ int effective_span = base::SaturatedSubtraction(max, min);
+ int span_loss = base::SaturatedSubtraction(max, min + effective_span);
+
+ // If the desired width is within the limits of ints, we can just
+ // use the simple computations to represent the range precisely.
+ if (span_loss == 0) {
+ *span = effective_span;
+ *origin = min;
+ return;
+ }
+
+ // Now we have to approximate. If one of min or max is close enough
+ // to zero we choose to represent that one precisely. The other side is
+ // probably practically "infinite", so we move it.
+ if (base::SaturatedAbsolute(max) < std::numeric_limits<int>::max() / 2) {
+ // Maintain origin + span == max.
+ *span = effective_span;
+ *origin = max - effective_span;
+ } else if (base::SaturatedAbsolute(min) <
+ std::numeric_limits<int>::max() / 2) {
+ // Maintain origin == min.
+ *span = effective_span;
+ *origin = min;
+ } else {
+ // Both are big, so keep the center.
+ *span = effective_span;
+ *origin = min + span_loss / 2;
+ }
+}
+
+void Rect::SetByBounds(int left, int top, int right, int bottom) {
+ int x, y;
+ int width, height;
+ SaturatedClampRange(left, right, &x, &width);
+ SaturatedClampRange(top, bottom, &y, &height);
+ origin_.SetPoint(x, y);
+ size_.SetSize(width, height);
+}
+
void Rect::Inset(const Insets& insets) {
Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
}
@@ -128,19 +176,21 @@ bool Rect::Intersects(const Rect& rect) const {
void Rect::Intersect(const Rect& rect) {
if (IsEmpty() || rect.IsEmpty()) {
- SetRect(0, 0, 0, 0);
+ SetRect(0, 0, 0, 0); // Throws away empty position.
return;
}
- int rx = std::max(x(), rect.x());
- int ry = std::max(y(), rect.y());
- int rr = std::min(right(), rect.right());
- int rb = std::min(bottom(), rect.bottom());
+ int left = std::max(x(), rect.x());
+ int top = std::max(y(), rect.y());
+ int new_right = std::min(right(), rect.right());
+ int new_bottom = std::min(bottom(), rect.bottom());
- if (rx >= rr || ry >= rb)
- rx = ry = rr = rb = 0; // non-intersecting
+ if (left >= new_right || top >= new_bottom) {
+ SetRect(0, 0, 0, 0); // Throws away empty position.
+ return;
+ }
- SetRect(rx, ry, rr - rx, rb - ry);
+ SetByBounds(left, top, new_right, new_bottom);
}
void Rect::Union(const Rect& rect) {
@@ -151,14 +201,9 @@ void Rect::Union(const Rect& rect) {
if (rect.IsEmpty())
return;
- int rx = std::min(x(), rect.x());
- int ry = std::min(y(), rect.y());
- int rr = std::max(right(), rect.right());
- int rb = std::max(bottom(), rect.bottom());
-
- // Subtracting to get width/height might overflow integers, so clamp them.
- SetRect(rx, ry, base::SaturatedSubtraction(rr, rx),
- base::SaturatedSubtraction(rb, ry));
+ SetByBounds(std::min(x(), rect.x()), std::min(y(), rect.y()),
+ std::max(right(), rect.right()),
+ std::max(bottom(), rect.bottom()));
}
void Rect::Subtract(const Rect& rect) {
@@ -189,7 +234,7 @@ void Rect::Subtract(const Rect& rect) {
rb = rect.y();
}
}
- SetRect(rx, ry, rr - rx, rb - ry);
+ SetByBounds(rx, ry, rr, rb);
}
void Rect::AdjustToFit(const Rect& rect) {
@@ -292,11 +337,10 @@ Rect SubtractRects(const Rect& a, const Rect& b) {
}
Rect BoundingRect(const Point& p1, const Point& p2) {
- int rx = std::min(p1.x(), p2.x());
- int ry = std::min(p1.y(), p2.y());
- int rr = std::max(p1.x(), p2.x());
- int rb = std::max(p1.y(), p2.y());
- return Rect(rx, ry, rr - rx, rb - ry);
+ Rect result;
+ result.SetByBounds(std::min(p1.x(), p2.x()), std::min(p1.y(), p2.y()),
+ std::max(p1.x(), p2.x()), std::max(p1.y(), p2.y()));
+ return result;
}
} // namespace gfx
« 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