| /* |
| * 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 LayoutRect_h |
| #define LayoutRect_h |
| |
| #include <iosfwd> |
| #include "platform/geometry/IntRect.h" |
| #include "platform/geometry/LayoutPoint.h" |
| #include "platform/geometry/LayoutRectOutsets.h" |
| #include "platform/wtf/Allocator.h" |
| #include "platform/wtf/Forward.h" |
| #include "platform/wtf/Vector.h" |
| |
| namespace blink { |
| |
| class FloatRect; |
| class DoubleRect; |
| |
| class PLATFORM_EXPORT LayoutRect { |
| DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
| |
| public: |
| LayoutRect() = default; |
| LayoutRect(const LayoutPoint& location, const LayoutSize& size) |
| : location_(location), size_(size) {} |
| LayoutRect(LayoutUnit x, LayoutUnit y, LayoutUnit width, LayoutUnit height) |
| : location_(LayoutPoint(x, y)), size_(LayoutSize(width, height)) {} |
| LayoutRect(int x, int y, int width, int height) |
| : location_(LayoutPoint(x, y)), size_(LayoutSize(width, height)) {} |
| LayoutRect(const FloatPoint& location, const FloatSize& size) |
| : location_(location), size_(size) {} |
| LayoutRect(const DoublePoint& location, const DoubleSize& size) |
| : location_(location), size_(size) {} |
| LayoutRect(const IntPoint& location, const IntSize& size) |
| : location_(location), size_(size) {} |
| explicit LayoutRect(const IntRect& rect) |
| : location_(rect.Location()), size_(rect.Size()) {} |
| |
| explicit LayoutRect( |
| const FloatRect&); // don't do this implicitly since it's lossy |
| explicit LayoutRect( |
| const DoubleRect&); // don't do this implicitly since it's lossy |
| |
| LayoutPoint Location() const { return location_; } |
| 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; } |
| |
| ALWAYS_INLINE LayoutUnit X() const { return location_.X(); } |
| ALWAYS_INLINE LayoutUnit Y() const { return location_.Y(); } |
| ALWAYS_INLINE LayoutUnit MaxX() const { return X() + Width(); } |
| ALWAYS_INLINE LayoutUnit MaxY() const { return Y() + Height(); } |
| LayoutUnit Width() const { return size_.Width(); } |
| 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); } |
| |
| 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()); |
| } |
| |
| LayoutPoint MinXMinYCorner() const { return location_; } // typically topLeft |
| LayoutPoint MaxXMinYCorner() const { |
| return LayoutPoint(location_.X() + size_.Width(), location_.Y()); |
| } // typically topRight |
| LayoutPoint MinXMaxYCorner() const { |
| return LayoutPoint(location_.X(), location_.Y() + size_.Height()); |
| } // typically bottomLeft |
| LayoutPoint MaxXMaxYCorner() const { |
| return LayoutPoint(location_.X() + size_.Width(), |
| location_.Y() + size_.Height()); |
| } // typically bottomRight |
| |
| 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()); |
| } |
| |
| 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&); |
| |
| // 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( |
| LayoutRect(LayoutUnit::NearlyMin() / 2, LayoutUnit::NearlyMin() / 2, |
| LayoutUnit::NearlyMax(), LayoutUnit::NearlyMax())); |
| 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>&); |
| |
| ALWAYS_INLINE bool operator==(const LayoutRect& a, const LayoutRect& b) { |
| return a.Location() == b.Location() && a.Size() == b.Size(); |
| } |
| |
| inline bool operator!=(const LayoutRect& a, const LayoutRect& b) { |
| return a.Location() != b.Location() || a.Size() != b.Size(); |
| } |
| |
| 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); |
| } |
| |
| PLATFORM_EXPORT LayoutRect EnclosingLayoutRect(const FloatRect&); |
| |
| 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&); |
| |
| // Redeclared here to avoid ODR issues. |
| // See platform/testing/GeometryPrinters.h. |
| void PrintTo(const LayoutRect&, std::ostream*); |
| |
| } // namespace blink |
| |
| #endif // LayoutRect_h |