Home | History | Annotate | Download | only in geometry
      1 /*
      2  * Copyright (c) 2012, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef LayoutRect_h
     32 #define LayoutRect_h
     33 
     34 #include "platform/geometry/IntRect.h"
     35 #include "platform/geometry/LayoutBoxExtent.h"
     36 #include "platform/geometry/LayoutPoint.h"
     37 #include "wtf/Vector.h"
     38 
     39 namespace WebCore {
     40 
     41 class FloatRect;
     42 
     43 class PLATFORM_EXPORT LayoutRect {
     44 public:
     45     LayoutRect() { }
     46     LayoutRect(const LayoutPoint& location, const LayoutSize& size)
     47         : m_location(location), m_size(size) { }
     48     LayoutRect(LayoutUnit x, LayoutUnit y, LayoutUnit width, LayoutUnit height)
     49         : m_location(LayoutPoint(x, y)), m_size(LayoutSize(width, height)) { }
     50     LayoutRect(const FloatPoint& location, const FloatSize& size)
     51         : m_location(location), m_size(size) { }
     52     LayoutRect(const IntRect& rect) : m_location(rect.location()), m_size(rect.size()) { }
     53 
     54     explicit LayoutRect(const FloatRect&); // don't do this implicitly since it's lossy
     55 
     56     LayoutPoint location() const { return m_location; }
     57     LayoutSize size() const { return m_size; }
     58 
     59     IntPoint pixelSnappedLocation() const { return roundedIntPoint(m_location); }
     60     IntSize pixelSnappedSize() const { return IntSize(snapSizeToPixel(m_size.width(), m_location.x()), snapSizeToPixel(m_size.height(), m_location.y())); }
     61 
     62     void setLocation(const LayoutPoint& location) { m_location = location; }
     63     void setSize(const LayoutSize& size) { m_size = size; }
     64 
     65     ALWAYS_INLINE LayoutUnit x() const { return m_location.x(); }
     66     ALWAYS_INLINE LayoutUnit y() const { return m_location.y(); }
     67     ALWAYS_INLINE LayoutUnit maxX() const { return x() + width(); }
     68     ALWAYS_INLINE LayoutUnit maxY() const { return y() + height(); }
     69     LayoutUnit width() const { return m_size.width(); }
     70     LayoutUnit height() const { return m_size.height(); }
     71 
     72     int pixelSnappedX() const { return x().round(); }
     73     int pixelSnappedY() const { return y().round(); }
     74     int pixelSnappedWidth() const { return snapSizeToPixel(width(), x()); }
     75     int pixelSnappedHeight() const { return snapSizeToPixel(height(), y()); }
     76     int pixelSnappedMaxX() const { return (m_location.x() + m_size.width()).round(); }
     77     int pixelSnappedMaxY() const { return (m_location.y() + m_size.height()).round(); }
     78 
     79     void setX(LayoutUnit x) { m_location.setX(x); }
     80     void setY(LayoutUnit y) { m_location.setY(y); }
     81     void setWidth(LayoutUnit width) { m_size.setWidth(width); }
     82     void setHeight(LayoutUnit height) { m_size.setHeight(height); }
     83 
     84     ALWAYS_INLINE bool isEmpty() const { return m_size.isEmpty(); }
     85 
     86     // NOTE: The result is rounded to integer values, and thus may be not the exact
     87     // center point.
     88     LayoutPoint center() const { return LayoutPoint(x() + width() / 2, y() + height() / 2); }
     89 
     90     void move(const LayoutSize& size) { m_location += size; }
     91     void moveBy(const LayoutPoint& offset) { m_location.move(offset.x(), offset.y()); }
     92     void move(LayoutUnit dx, LayoutUnit dy) { m_location.move(dx, dy); }
     93 
     94     void expand(const LayoutSize& size) { m_size += size; }
     95     void expand(const LayoutBoxExtent& box)
     96     {
     97         m_location.move(-box.left(), -box.top());
     98         m_size.expand(box.left() + box.right(), box.top() + box.bottom());
     99     }
    100     void expand(LayoutUnit dw, LayoutUnit dh) { m_size.expand(dw, dh); }
    101     void contract(const LayoutSize& size) { m_size -= size; }
    102     void contract(const LayoutBoxExtent& box)
    103     {
    104         m_location.move(box.left(), box.top());
    105         m_size.shrink(box.left() + box.right(), box.top() + box.bottom());
    106     }
    107     void contract(LayoutUnit dw, LayoutUnit dh) { m_size.expand(-dw, -dh); }
    108 
    109     void shiftXEdgeTo(LayoutUnit edge)
    110     {
    111         LayoutUnit delta = edge - x();
    112         setX(edge);
    113         setWidth(std::max<LayoutUnit>(0, width() - delta));
    114     }
    115     void shiftMaxXEdgeTo(LayoutUnit edge)
    116     {
    117         LayoutUnit delta = edge - maxX();
    118         setWidth(std::max<LayoutUnit>(0, width() + delta));
    119     }
    120     void shiftYEdgeTo(LayoutUnit edge)
    121     {
    122         LayoutUnit delta = edge - y();
    123         setY(edge);
    124         setHeight(std::max<LayoutUnit>(0, height() - delta));
    125     }
    126     void shiftMaxYEdgeTo(LayoutUnit edge)
    127     {
    128         LayoutUnit delta = edge - maxY();
    129         setHeight(std::max<LayoutUnit>(0, height() + delta));
    130     }
    131 
    132     LayoutPoint minXMinYCorner() const { return m_location; } // typically topLeft
    133     LayoutPoint maxXMinYCorner() const { return LayoutPoint(m_location.x() + m_size.width(), m_location.y()); } // typically topRight
    134     LayoutPoint minXMaxYCorner() const { return LayoutPoint(m_location.x(), m_location.y() + m_size.height()); } // typically bottomLeft
    135     LayoutPoint maxXMaxYCorner() const { return LayoutPoint(m_location.x() + m_size.width(), m_location.y() + m_size.height()); } // typically bottomRight
    136 
    137     bool intersects(const LayoutRect&) const;
    138     bool contains(const LayoutRect&) const;
    139 
    140     // This checks to see if the rect contains x,y in the traditional sense.
    141     // Equivalent to checking if the rect contains a 1x1 rect below and to the right of (px,py).
    142     bool contains(LayoutUnit px, LayoutUnit py) const
    143         { return px >= x() && px < maxX() && py >= y() && py < maxY(); }
    144     bool contains(const LayoutPoint& point) const { return contains(point.x(), point.y()); }
    145 
    146     void intersect(const LayoutRect&);
    147     void unite(const LayoutRect&);
    148     void uniteIfNonZero(const LayoutRect&);
    149 
    150     void inflateX(LayoutUnit dx)
    151     {
    152         m_location.setX(m_location.x() - dx);
    153         m_size.setWidth(m_size.width() + dx + dx);
    154     }
    155     void inflateY(LayoutUnit dy)
    156     {
    157         m_location.setY(m_location.y() - dy);
    158         m_size.setHeight(m_size.height() + dy + dy);
    159     }
    160     void inflate(LayoutUnit d) { inflateX(d); inflateY(d); }
    161     void scale(float s);
    162     void scale(float xAxisScale, float yAxisScale);
    163 
    164     LayoutRect transposedRect() const { return LayoutRect(m_location.transposedPoint(), m_size.transposedSize()); }
    165 
    166     static LayoutRect infiniteRect()
    167     {
    168         // Return a rect that is slightly smaller than the true max rect to allow pixelSnapping to round up to the nearest IntRect without overflowing.
    169         return LayoutRect(LayoutUnit::nearlyMin() / 2, LayoutUnit::nearlyMin() / 2, LayoutUnit::nearlyMax(), LayoutUnit::nearlyMax());
    170     }
    171 
    172 #ifndef NDEBUG
    173     // Prints the rect to the screen.
    174     void show(bool showRawValue = false) const;
    175 #endif
    176 
    177 private:
    178     LayoutPoint m_location;
    179     LayoutSize m_size;
    180 };
    181 
    182 inline LayoutRect intersection(const LayoutRect& a, const LayoutRect& b)
    183 {
    184     LayoutRect c = a;
    185     c.intersect(b);
    186     return c;
    187 }
    188 
    189 inline LayoutRect unionRect(const LayoutRect& a, const LayoutRect& b)
    190 {
    191     LayoutRect c = a;
    192     c.unite(b);
    193     return c;
    194 }
    195 
    196 PLATFORM_EXPORT LayoutRect unionRect(const Vector<LayoutRect>&);
    197 
    198 ALWAYS_INLINE bool operator==(const LayoutRect& a, const LayoutRect& b)
    199 {
    200     return a.location() == b.location() && a.size() == b.size();
    201 }
    202 
    203 inline bool operator!=(const LayoutRect& a, const LayoutRect& b)
    204 {
    205     return a.location() != b.location() || a.size() != b.size();
    206 }
    207 
    208 inline IntRect pixelSnappedIntRect(const LayoutRect& rect)
    209 {
    210     return IntRect(roundedIntPoint(rect.location()), IntSize(
    211         snapSizeToPixel(rect.width(), rect.x()),
    212         snapSizeToPixel(rect.height(), rect.y())));
    213 }
    214 
    215 PLATFORM_EXPORT IntRect enclosingIntRect(const LayoutRect&);
    216 PLATFORM_EXPORT LayoutRect enclosingLayoutRect(const FloatRect&);
    217 
    218 inline IntRect pixelSnappedIntRect(LayoutUnit left, LayoutUnit top, LayoutUnit width, LayoutUnit height)
    219 {
    220     return IntRect(left.round(), top.round(), snapSizeToPixel(width, left), snapSizeToPixel(height, top));
    221 }
    222 
    223 inline IntRect pixelSnappedIntRectFromEdges(LayoutUnit left, LayoutUnit top, LayoutUnit right, LayoutUnit bottom)
    224 {
    225     return IntRect(left.round(), top.round(), snapSizeToPixel(right - left, left), snapSizeToPixel(bottom - top, top));
    226 }
    227 
    228 inline IntRect pixelSnappedIntRect(LayoutPoint location, LayoutSize size)
    229 {
    230     return IntRect(roundedIntPoint(location), pixelSnappedIntSize(size, location));
    231 }
    232 
    233 } // namespace WebCore
    234 
    235 #endif // LayoutRect_h
    236