| 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
|
|
|