| /* |
| * Copyright (C) 2003, 2006, 2009 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "platform/geometry/IntRect.h" |
| |
| #include "platform/geometry/FloatRect.h" |
| #include "platform/geometry/LayoutRect.h" |
| #include "platform/wtf/CheckedNumeric.h" |
| #include "platform/wtf/Vector.h" |
| #include "platform/wtf/text/WTFString.h" |
| #include "third_party/skia/include/core/SkRect.h" |
| #include "ui/gfx/geometry/rect.h" |
| |
| #include <algorithm> |
| |
| namespace blink { |
| |
| IntRect::IntRect(const FloatRect& r) |
| : location_(clampTo<int>(r.X()), clampTo<int>(r.Y())), |
| size_(clampTo<int>(r.Width()), clampTo<int>(r.Height())) {} |
| |
| IntRect::IntRect(const LayoutRect& r) |
| : location_(r.X().ToInt(), r.Y().ToInt()), |
| size_(r.Width().ToInt(), r.Height().ToInt()) {} |
| |
| void IntRect::ShiftXEdgeTo(int edge) { |
| int delta = edge - X(); |
| SetX(edge); |
| SetWidth(std::max(0, Width() - delta)); |
| } |
| |
| void IntRect::ShiftMaxXEdgeTo(int edge) { |
| int delta = edge - MaxX(); |
| SetWidth(std::max(0, Width() + delta)); |
| } |
| |
| void IntRect::ShiftYEdgeTo(int edge) { |
| int delta = edge - Y(); |
| SetY(edge); |
| SetHeight(std::max(0, Height() - delta)); |
| } |
| |
| void IntRect::ShiftMaxYEdgeTo(int edge) { |
| int delta = edge - MaxY(); |
| SetHeight(std::max(0, Height() + delta)); |
| } |
| |
| bool IntRect::Intersects(const IntRect& other) const { |
| // Checking emptiness handles negative widths as well as zero. |
| return !IsEmpty() && !other.IsEmpty() && X() < other.MaxX() && |
| other.X() < MaxX() && Y() < other.MaxY() && other.Y() < MaxY(); |
| } |
| |
| bool IntRect::Contains(const IntRect& other) const { |
| return X() <= other.X() && MaxX() >= other.MaxX() && Y() <= other.Y() && |
| MaxY() >= other.MaxY(); |
| } |
| |
| void IntRect::Intersect(const IntRect& other) { |
| int left = std::max(X(), other.X()); |
| int top = std::max(Y(), other.Y()); |
| int right = std::min(MaxX(), other.MaxX()); |
| int bottom = std::min(MaxY(), other.MaxY()); |
| |
| // Return a clean empty rectangle for non-intersecting cases. |
| if (left >= right || top >= bottom) { |
| left = 0; |
| top = 0; |
| right = 0; |
| bottom = 0; |
| } |
| |
| location_.SetX(left); |
| location_.SetY(top); |
| size_.SetWidth(right - left); |
| size_.SetHeight(bottom - top); |
| } |
| |
| void IntRect::Unite(const IntRect& other) { |
| // Handle empty special cases first. |
| if (other.IsEmpty()) |
| return; |
| if (IsEmpty()) { |
| *this = other; |
| return; |
| } |
| |
| UniteEvenIfEmpty(other); |
| } |
| |
| void IntRect::UniteIfNonZero(const IntRect& other) { |
| // Handle empty special cases first. |
| if (!other.Width() && !other.Height()) |
| return; |
| if (!Width() && !Height()) { |
| *this = other; |
| return; |
| } |
| |
| UniteEvenIfEmpty(other); |
| } |
| |
| void IntRect::UniteEvenIfEmpty(const IntRect& other) { |
| int left = std::min(X(), other.X()); |
| int top = std::min(Y(), other.Y()); |
| int right = std::max(MaxX(), other.MaxX()); |
| int bottom = std::max(MaxY(), other.MaxY()); |
| |
| location_.SetX(left); |
| location_.SetY(top); |
| size_.SetWidth(right - left); |
| size_.SetHeight(bottom - top); |
| } |
| |
| void IntRect::Scale(float s) { |
| location_.SetX((int)(X() * s)); |
| location_.SetY((int)(Y() * s)); |
| size_.SetWidth((int)(Width() * s)); |
| size_.SetHeight((int)(Height() * s)); |
| } |
| |
| static inline int DistanceToInterval(int pos, int start, int end) { |
| if (pos < start) |
| return start - pos; |
| if (pos > end) |
| return end - pos; |
| return 0; |
| } |
| |
| IntSize IntRect::DifferenceToPoint(const IntPoint& point) const { |
| int xdistance = DistanceToInterval(point.X(), X(), MaxX()); |
| int ydistance = DistanceToInterval(point.Y(), Y(), MaxY()); |
| return IntSize(xdistance, ydistance); |
| } |
| |
| IntRect::operator SkIRect() const { |
| SkIRect rect = {X(), Y(), MaxX(), MaxY()}; |
| return rect; |
| } |
| |
| IntRect::operator SkRect() const { |
| SkRect rect; |
| rect.set(SkIntToScalar(X()), SkIntToScalar(Y()), SkIntToScalar(MaxX()), |
| SkIntToScalar(MaxY())); |
| return rect; |
| } |
| |
| IntRect::operator gfx::Rect() const { |
| return gfx::Rect(X(), Y(), Width(), Height()); |
| } |
| |
| IntRect UnionRect(const Vector<IntRect>& rects) { |
| IntRect result; |
| |
| size_t count = rects.size(); |
| for (size_t i = 0; i < count; ++i) |
| result.Unite(rects[i]); |
| |
| return result; |
| } |
| |
| IntRect UnionRectEvenIfEmpty(const Vector<IntRect>& rects) { |
| size_t count = rects.size(); |
| if (!count) |
| return IntRect(); |
| |
| IntRect result = rects[0]; |
| for (size_t i = 1; i < count; ++i) |
| result.UniteEvenIfEmpty(rects[i]); |
| |
| return result; |
| } |
| |
| std::ostream& operator<<(std::ostream& ostream, const IntRect& rect) { |
| return ostream << rect.ToString(); |
| } |
| |
| String IntRect::ToString() const { |
| return String::Format("%s %s", Location().ToString().Ascii().data(), |
| Size().ToString().Ascii().data()); |
| } |
| |
| bool IntRect::IsValid() const { |
| CheckedNumeric<int> max = location_.X(); |
| max += size_.Width(); |
| if (!max.IsValid()) |
| return false; |
| max = location_.Y(); |
| max += size_.Height(); |
| return max.IsValid(); |
| } |
| |
| } // namespace blink |