Home | History | Annotate | Download | only in geometry
      1 /*
      2  * Copyright (C) 2003, 2006, 2009 Apple 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
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "platform/geometry/IntRect.h"
     28 
     29 #include "platform/geometry/FloatRect.h"
     30 #include "platform/geometry/LayoutRect.h"
     31 #include "third_party/skia/include/core/SkRect.h"
     32 
     33 #include <algorithm>
     34 
     35 namespace WebCore {
     36 
     37 IntRect::IntRect(const FloatRect& r)
     38     : m_location(clampToInteger(r.x()), clampToInteger(r.y()))
     39     , m_size(clampToInteger(r.width()), clampToInteger(r.height()))
     40 {
     41 }
     42 
     43 IntRect::IntRect(const LayoutRect& r)
     44     : m_location(r.x(), r.y())
     45     , m_size(r.width(), r.height())
     46 {
     47 }
     48 
     49 bool IntRect::intersects(const IntRect& other) const
     50 {
     51     // Checking emptiness handles negative widths as well as zero.
     52     return !isEmpty() && !other.isEmpty()
     53         && x() < other.maxX() && other.x() < maxX()
     54         && y() < other.maxY() && other.y() < maxY();
     55 }
     56 
     57 bool IntRect::contains(const IntRect& other) const
     58 {
     59     return x() <= other.x() && maxX() >= other.maxX()
     60         && y() <= other.y() && maxY() >= other.maxY();
     61 }
     62 
     63 void IntRect::intersect(const IntRect& other)
     64 {
     65     int left = std::max(x(), other.x());
     66     int top = std::max(y(), other.y());
     67     int right = std::min(maxX(), other.maxX());
     68     int bottom = std::min(maxY(), other.maxY());
     69 
     70     // Return a clean empty rectangle for non-intersecting cases.
     71     if (left >= right || top >= bottom) {
     72         left = 0;
     73         top = 0;
     74         right = 0;
     75         bottom = 0;
     76     }
     77 
     78     m_location.setX(left);
     79     m_location.setY(top);
     80     m_size.setWidth(right - left);
     81     m_size.setHeight(bottom - top);
     82 }
     83 
     84 void IntRect::unite(const IntRect& other)
     85 {
     86     // Handle empty special cases first.
     87     if (other.isEmpty())
     88         return;
     89     if (isEmpty()) {
     90         *this = other;
     91         return;
     92     }
     93 
     94     int left = std::min(x(), other.x());
     95     int top = std::min(y(), other.y());
     96     int right = std::max(maxX(), other.maxX());
     97     int bottom = std::max(maxY(), other.maxY());
     98 
     99     m_location.setX(left);
    100     m_location.setY(top);
    101     m_size.setWidth(right - left);
    102     m_size.setHeight(bottom - top);
    103 }
    104 
    105 void IntRect::uniteIfNonZero(const IntRect& other)
    106 {
    107     // Handle empty special cases first.
    108     if (!other.width() && !other.height())
    109         return;
    110     if (!width() && !height()) {
    111         *this = other;
    112         return;
    113     }
    114 
    115     int left = std::min(x(), other.x());
    116     int top = std::min(y(), other.y());
    117     int right = std::max(maxX(), other.maxX());
    118     int bottom = std::max(maxY(), other.maxY());
    119 
    120     m_location.setX(left);
    121     m_location.setY(top);
    122     m_size.setWidth(right - left);
    123     m_size.setHeight(bottom - top);
    124 }
    125 
    126 void IntRect::scale(float s)
    127 {
    128     m_location.setX((int)(x() * s));
    129     m_location.setY((int)(y() * s));
    130     m_size.setWidth((int)(width() * s));
    131     m_size.setHeight((int)(height() * s));
    132 }
    133 
    134 static inline int distanceToInterval(int pos, int start, int end)
    135 {
    136     if (pos < start)
    137         return start - pos;
    138     if (pos > end)
    139         return end - pos;
    140     return 0;
    141 }
    142 
    143 IntSize IntRect::differenceToPoint(const IntPoint& point) const
    144 {
    145     int xdistance = distanceToInterval(point.x(), x(), maxX());
    146     int ydistance = distanceToInterval(point.y(), y(), maxY());
    147     return IntSize(xdistance, ydistance);
    148 }
    149 
    150 IntRect::operator SkIRect() const
    151 {
    152     SkIRect rect = { x(), y(), maxX(), maxY() };
    153     return rect;
    154 }
    155 
    156 IntRect::operator SkRect() const
    157 {
    158     SkRect rect;
    159     rect.set(SkIntToScalar(x()), SkIntToScalar(y()), SkIntToScalar(maxX()), SkIntToScalar(maxY()));
    160     return rect;
    161 }
    162 
    163 IntRect unionRect(const Vector<IntRect>& rects)
    164 {
    165     IntRect result;
    166 
    167     size_t count = rects.size();
    168     for (size_t i = 0; i < count; ++i)
    169         result.unite(rects[i]);
    170 
    171     return result;
    172 }
    173 
    174 #ifndef NDEBUG
    175     // Prints the rect to the screen.
    176 void IntRect::show() const
    177 {
    178     LayoutRect(*this).show();
    179 }
    180 #endif
    181 
    182 } // namespace WebCore
    183