| /* |
| * Copyright (c) 2012, Google 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: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * 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. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT |
| * OWNER OR 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. |
| */ |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_RECT_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_RECT_H_ |
| |
| #include <iosfwd> |
| |
| #include "base/compiler_specific.h" |
| #include "third_party/blink/renderer/platform/geometry/float_rect.h" |
| #include "third_party/blink/renderer/platform/geometry/int_rect.h" |
| #include "third_party/blink/renderer/platform/geometry/layout_point.h" |
| #include "third_party/blink/renderer/platform/geometry/layout_rect_outsets.h" |
| #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" |
| #include "third_party/blink/renderer/platform/wtf/forward.h" |
| #include "third_party/blink/renderer/platform/wtf/vector.h" |
| |
| namespace blink { |
| |
| class DoubleRect; |
| |
| class PLATFORM_EXPORT LayoutRect { |
| DISALLOW_NEW(); |
| |
| public: |
| constexpr LayoutRect() = default; |
| constexpr LayoutRect(const LayoutPoint& location, const LayoutSize& size) |
| : location_(location), size_(size) {} |
| constexpr LayoutRect(LayoutUnit x, |
| LayoutUnit y, |
| LayoutUnit width, |
| LayoutUnit height) |
| : location_(LayoutPoint(x, y)), size_(LayoutSize(width, height)) {} |
| constexpr LayoutRect(int x, int y, int width, int height) |
| : location_(LayoutPoint(x, y)), size_(LayoutSize(width, height)) {} |
| constexpr LayoutRect(const FloatPoint& location, const FloatSize& size) |
| : location_(location), size_(size) {} |
| constexpr LayoutRect(const DoublePoint& location, const DoubleSize& size) |
| : location_(location), size_(size) {} |
| constexpr LayoutRect(const IntPoint& location, const IntSize& size) |
| : location_(location), size_(size) {} |
| constexpr explicit LayoutRect(const IntRect& rect) |
| : location_(rect.Location()), size_(rect.Size()) {} |
| |
| // Don't do these implicitly since they are lossy. |
| constexpr explicit LayoutRect(const FloatRect& r) |
| : location_(r.Location()), size_(r.Size()) {} |
| explicit LayoutRect(const DoubleRect&); |
| |
| constexpr explicit operator FloatRect() const { |
| return FloatRect(X(), Y(), Width(), Height()); |
| } |
| |
| constexpr LayoutPoint Location() const { return location_; } |
| constexpr LayoutSize Size() const { return size_; } |
| |
| IntPoint PixelSnappedLocation() const { return RoundedIntPoint(location_); } |
| IntSize PixelSnappedSize() const { |
| return IntSize(SnapSizeToPixel(size_.Width(), location_.X()), |
| SnapSizeToPixel(size_.Height(), location_.Y())); |
| } |
| |
| void SetLocation(const LayoutPoint& location) { location_ = location; } |
| void SetSize(const LayoutSize& size) { size_ = size; } |
| |
| constexpr ALWAYS_INLINE LayoutUnit X() const { return location_.X(); } |
| constexpr ALWAYS_INLINE LayoutUnit Y() const { return location_.Y(); } |
| ALWAYS_INLINE LayoutUnit MaxX() const { return X() + Width(); } |
| ALWAYS_INLINE LayoutUnit MaxY() const { return Y() + Height(); } |
| constexpr LayoutUnit Width() const { return size_.Width(); } |
| constexpr LayoutUnit Height() const { return size_.Height(); } |
| |
| int PixelSnappedWidth() const { return SnapSizeToPixel(Width(), X()); } |
| int PixelSnappedHeight() const { return SnapSizeToPixel(Height(), Y()); } |
| |
| void SetX(LayoutUnit x) { location_.SetX(x); } |
| void SetY(LayoutUnit y) { location_.SetY(y); } |
| void SetWidth(LayoutUnit width) { size_.SetWidth(width); } |
| void SetHeight(LayoutUnit height) { size_.SetHeight(height); } |
| |
| constexpr ALWAYS_INLINE bool IsEmpty() const { return size_.IsEmpty(); } |
| |
| // NOTE: The result is rounded to integer values, and thus may be not the |
| // exact center point. |
| LayoutPoint Center() const { |
| return LayoutPoint(X() + Width() / 2, Y() + Height() / 2); |
| } |
| |
| void Move(const LayoutSize& size) { location_ += size; } |
| void Move(const IntSize& size) { |
| location_.Move(LayoutUnit(size.Width()), LayoutUnit(size.Height())); |
| } |
| void MoveBy(const LayoutPoint& offset) { |
| location_.Move(offset.X(), offset.Y()); |
| } |
| void MoveBy(const IntPoint& offset) { |
| location_.Move(LayoutUnit(offset.X()), LayoutUnit(offset.Y())); |
| } |
| void Move(LayoutUnit dx, LayoutUnit dy) { location_.Move(dx, dy); } |
| void Move(int dx, int dy) { location_.Move(LayoutUnit(dx), LayoutUnit(dy)); } |
| |
| void Expand(const LayoutSize& size) { size_ += size; } |
| void Expand(const LayoutRectOutsets& box) { |
| location_.Move(-box.Left(), -box.Top()); |
| size_.Expand(box.Left() + box.Right(), box.Top() + box.Bottom()); |
| } |
| void Expand(LayoutUnit dw, LayoutUnit dh) { size_.Expand(dw, dh); } |
| void ExpandEdges(LayoutUnit top, |
| LayoutUnit right, |
| LayoutUnit bottom, |
| LayoutUnit left) { |
| location_.Move(-left, -top); |
| size_.Expand(left + right, top + bottom); |
| } |
| void Contract(const LayoutSize& size) { size_ -= size; } |
| void Contract(LayoutUnit dw, LayoutUnit dh) { size_.Expand(-dw, -dh); } |
| void Contract(int dw, int dh) { size_.Expand(-dw, -dh); } |
| void Contract(const LayoutRectOutsets& box) { |
| location_.Move(box.Left(), box.Top()); |
| size_.Shrink(box.Left() + box.Right(), box.Top() + box.Bottom()); |
| } |
| void ContractEdges(LayoutUnit top, |
| LayoutUnit right, |
| LayoutUnit bottom, |
| LayoutUnit left) { |
| location_.Move(left, top); |
| size_.Shrink(left + right, top + bottom); |
| } |
| |
| // Convert to an outsets for {{0, 0}, size} rect. |
| LayoutRectOutsets ToOutsets(const LayoutSize& size) const { |
| return LayoutRectOutsets(-Y(), MaxX() - size.Width(), |
| MaxY() - size.Height(), -X()); |
| } |
| |
| void ShiftXEdgeTo(LayoutUnit edge) { |
| LayoutUnit delta = edge - X(); |
| SetX(edge); |
| SetWidth((Width() - delta).ClampNegativeToZero()); |
| } |
| void ShiftMaxXEdgeTo(LayoutUnit edge) { |
| LayoutUnit delta = edge - MaxX(); |
| SetWidth((Width() + delta).ClampNegativeToZero()); |
| } |
| void ShiftYEdgeTo(LayoutUnit edge) { |
| LayoutUnit delta = edge - Y(); |
| SetY(edge); |
| SetHeight((Height() - delta).ClampNegativeToZero()); |
| } |
| void ShiftMaxYEdgeTo(LayoutUnit edge) { |
| LayoutUnit delta = edge - MaxY(); |
| SetHeight((Height() + delta).ClampNegativeToZero()); |
| } |
| |
| // Typically top left. |
| constexpr LayoutPoint MinXMinYCorner() const { return location_; } |
| |
| // Typically top right. |
| LayoutPoint MaxXMinYCorner() const { |
| return LayoutPoint(location_.X() + size_.Width(), location_.Y()); |
| } |
| |
| // Typically bottom left. |
| LayoutPoint MinXMaxYCorner() const { |
| return LayoutPoint(location_.X(), location_.Y() + size_.Height()); |
| } |
| |
| // Typically bottom right. |
| LayoutPoint MaxXMaxYCorner() const { |
| return LayoutPoint(location_.X() + size_.Width(), |
| location_.Y() + size_.Height()); |
| } |
| |
| WARN_UNUSED_RESULT bool Intersects(const LayoutRect&) const; |
| bool Contains(const LayoutRect&) const; |
| |
| // This checks to see if the rect contains x,y in the traditional sense. |
| // Equivalent to checking if the rect contains a 1x1 rect below and to the |
| // right of (px,py). |
| bool Contains(LayoutUnit px, LayoutUnit py) const { |
| return px >= X() && px < MaxX() && py >= Y() && py < MaxY(); |
| } |
| bool Contains(const LayoutPoint& point) const { |
| return Contains(point.X(), point.Y()); |
| } |
| |
| // Whether all edges of the rect are at full-pixel boundaries. |
| // i.e.: EnclosingIntRect(this)) == this |
| bool EdgesOnPixelBoundaries() const { |
| return !location_.X().HasFraction() && !location_.Y().HasFraction() && |
| !size_.Width().HasFraction() && !size_.Height().HasFraction(); |
| } |
| |
| // Expand each edge outwards to the next full-pixel boundary. |
| // i.e.: this = LayoutRect(EnclosingIntRect(this)) |
| void ExpandEdgesToPixelBoundaries() { |
| int x = X().Floor(); |
| int y = Y().Floor(); |
| int max_x = MaxX().Ceil(); |
| int max_y = MaxY().Ceil(); |
| location_.SetX(LayoutUnit(x)); |
| location_.SetY(LayoutUnit(y)); |
| size_.SetWidth(LayoutUnit(max_x - x)); |
| size_.SetHeight(LayoutUnit(max_y - y)); |
| } |
| |
| void Intersect(const LayoutRect&); |
| void Unite(const LayoutRect&); |
| void UniteIfNonZero(const LayoutRect&); |
| |
| // Set this rect to be the intersection of itself and the argument rect |
| // using edge-inclusive geometry. If the two rectangles overlap but the |
| // overlap region is zero-area (either because one of the two rectangles |
| // is zero-area, or because the rectangles overlap at an edge or a corner), |
| // the result is the zero-area intersection. The return value indicates |
| // whether the two rectangle actually have an intersection, since checking |
| // the result for isEmpty() is not conclusive. |
| bool InclusiveIntersect(const LayoutRect&); |
| |
| // Similar to |Intersects| but inclusive (see also: |InclusiveIntersect|). |
| // For example, (0,0 10x10) would inclusively intersect (10,10 0x0) even |
| // though the intersection has zero area and |Intersects| would be false. |
| bool IntersectsInclusively(const LayoutRect&); |
| |
| // Besides non-empty rects, this method also unites empty rects (as points or |
| // line segments). For example, union of (100, 100, 0x0) and (200, 200, 50x0) |
| // is (100, 100, 150x100). |
| void UniteEvenIfEmpty(const LayoutRect&); |
| |
| void InflateX(LayoutUnit dx) { |
| location_.SetX(location_.X() - dx); |
| size_.SetWidth(size_.Width() + dx + dx); |
| } |
| void InflateY(LayoutUnit dy) { |
| location_.SetY(location_.Y() - dy); |
| size_.SetHeight(size_.Height() + dy + dy); |
| } |
| void Inflate(LayoutUnit d) { |
| InflateX(d); |
| InflateY(d); |
| } |
| void Inflate(int d) { Inflate(LayoutUnit(d)); } |
| void Scale(float s); |
| void Scale(float x_axis_scale, float y_axis_scale); |
| |
| LayoutRect TransposedRect() const { |
| return LayoutRect(location_.TransposedPoint(), size_.TransposedSize()); |
| } |
| |
| static IntRect InfiniteIntRect() { |
| // Due to saturated arithemetic this value is not the same as |
| // LayoutRect(IntRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX)). |
| static IntRect infinite_int_rect(LayoutUnit::NearlyMin().ToInt() / 2, |
| LayoutUnit::NearlyMin().ToInt() / 2, |
| LayoutUnit::NearlyMax().ToInt(), |
| LayoutUnit::NearlyMax().ToInt()); |
| return infinite_int_rect; |
| } |
| |
| String ToString() const; |
| |
| private: |
| LayoutPoint location_; |
| LayoutSize size_; |
| }; |
| |
| inline LayoutRect Intersection(const LayoutRect& a, const LayoutRect& b) { |
| LayoutRect c = a; |
| c.Intersect(b); |
| return c; |
| } |
| |
| inline LayoutRect UnionRect(const LayoutRect& a, const LayoutRect& b) { |
| LayoutRect c = a; |
| c.Unite(b); |
| return c; |
| } |
| |
| PLATFORM_EXPORT LayoutRect UnionRect(const Vector<LayoutRect>&); |
| |
| inline LayoutRect UnionRectEvenIfEmpty(const LayoutRect& a, |
| const LayoutRect& b) { |
| LayoutRect c = a; |
| c.UniteEvenIfEmpty(b); |
| return c; |
| } |
| |
| PLATFORM_EXPORT LayoutRect UnionRectEvenIfEmpty(const Vector<LayoutRect>&); |
| |
| constexpr ALWAYS_INLINE bool operator==(const LayoutRect& a, |
| const LayoutRect& b) { |
| return a.Location() == b.Location() && a.Size() == b.Size(); |
| } |
| |
| constexpr bool operator!=(const LayoutRect& a, const LayoutRect& b) { |
| return !(a == b); |
| } |
| |
| inline IntRect PixelSnappedIntRect(const LayoutRect& rect) { |
| return IntRect(RoundedIntPoint(rect.Location()), |
| IntSize(SnapSizeToPixel(rect.Width(), rect.X()), |
| SnapSizeToPixel(rect.Height(), rect.Y()))); |
| } |
| |
| inline IntRect EnclosingIntRect(const LayoutRect& rect) { |
| IntPoint location = FlooredIntPoint(rect.MinXMinYCorner()); |
| IntPoint max_point = CeiledIntPoint(rect.MaxXMaxYCorner()); |
| return IntRect(location, max_point - location); |
| } |
| |
| inline IntRect EnclosedIntRect(const LayoutRect& rect) { |
| IntPoint location = CeiledIntPoint(rect.MinXMinYCorner()); |
| IntPoint max_point = FlooredIntPoint(rect.MaxXMaxYCorner()); |
| return IntRect(location, max_point - location); |
| } |
| |
| inline LayoutRect EnclosingLayoutRect(const FloatRect& rect) { |
| LayoutUnit x = LayoutUnit::FromFloatFloor(rect.X()); |
| LayoutUnit y = LayoutUnit::FromFloatFloor(rect.Y()); |
| LayoutUnit max_x = LayoutUnit::FromFloatCeil(rect.MaxX()); |
| LayoutUnit max_y = LayoutUnit::FromFloatCeil(rect.MaxY()); |
| return LayoutRect(x, y, max_x - x, max_y - y); |
| } |
| |
| inline IntRect PixelSnappedIntRect(LayoutUnit left, |
| LayoutUnit top, |
| LayoutUnit width, |
| LayoutUnit height) { |
| return IntRect(left.Round(), top.Round(), SnapSizeToPixel(width, left), |
| SnapSizeToPixel(height, top)); |
| } |
| |
| inline IntRect PixelSnappedIntRectFromEdges(LayoutUnit left, |
| LayoutUnit top, |
| LayoutUnit right, |
| LayoutUnit bottom) { |
| return IntRect(left.Round(), top.Round(), SnapSizeToPixel(right - left, left), |
| SnapSizeToPixel(bottom - top, top)); |
| } |
| |
| inline IntRect PixelSnappedIntRect(LayoutPoint location, LayoutSize size) { |
| return IntRect(RoundedIntPoint(location), |
| PixelSnappedIntSize(size, location)); |
| } |
| |
| PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const LayoutRect&); |
| PLATFORM_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, |
| const LayoutRect&); |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_RECT_H_ |