Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2003, 2006, 2007 Apple Inc.  All rights reserved.
      3  * Copyright (C) 2005 Nokia.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "core/platform/graphics/FloatRect.h"
     29 
     30 #include "core/platform/FloatConversion.h"
     31 #include "core/platform/graphics/IntRect.h"
     32 #include "core/platform/graphics/LayoutRect.h"
     33 #include "third_party/skia/include/core/SkRect.h"
     34 #include "wtf/MathExtras.h"
     35 
     36 #include <algorithm>
     37 #include <math.h>
     38 
     39 using std::max;
     40 using std::min;
     41 
     42 namespace WebCore {
     43 
     44 FloatRect::FloatRect(const IntRect& r) : m_location(r.location()), m_size(r.size())
     45 {
     46 }
     47 
     48 FloatRect::FloatRect(const LayoutRect& r) : m_location(r.location()), m_size(r.size())
     49 {
     50 }
     51 
     52 FloatRect::FloatRect(const SkRect& r) : m_location(r.fLeft, r.fTop), m_size(r.width(), r.height())
     53 {
     54 }
     55 
     56 FloatRect FloatRect::narrowPrecision(double x, double y, double width, double height)
     57 {
     58     return FloatRect(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), narrowPrecisionToFloat(width), narrowPrecisionToFloat(height));
     59 }
     60 
     61 bool FloatRect::isExpressibleAsIntRect() const
     62 {
     63     return isWithinIntRange(x()) && isWithinIntRange(y())
     64         && isWithinIntRange(width()) && isWithinIntRange(height())
     65         && isWithinIntRange(maxX()) && isWithinIntRange(maxY());
     66 }
     67 
     68 bool FloatRect::intersects(const FloatRect& other) const
     69 {
     70     // Checking emptiness handles negative widths as well as zero.
     71     return !isEmpty() && !other.isEmpty()
     72         && x() < other.maxX() && other.x() < maxX()
     73         && y() < other.maxY() && other.y() < maxY();
     74 }
     75 
     76 bool FloatRect::contains(const FloatRect& other) const
     77 {
     78     return x() <= other.x() && maxX() >= other.maxX()
     79         && y() <= other.y() && maxY() >= other.maxY();
     80 }
     81 
     82 bool FloatRect::contains(const FloatPoint& point, ContainsMode containsMode) const
     83 {
     84     if (containsMode == InsideOrOnStroke)
     85         return contains(point.x(), point.y());
     86     return x() < point.x() && maxX() > point.x() && y() < point.y() && maxY() > point.y();
     87 }
     88 
     89 void FloatRect::intersect(const FloatRect& other)
     90 {
     91     float l = max(x(), other.x());
     92     float t = max(y(), other.y());
     93     float r = min(maxX(), other.maxX());
     94     float b = min(maxY(), other.maxY());
     95 
     96     // Return a clean empty rectangle for non-intersecting cases.
     97     if (l >= r || t >= b) {
     98         l = 0;
     99         t = 0;
    100         r = 0;
    101         b = 0;
    102     }
    103 
    104     setLocationAndSizeFromEdges(l, t, r, b);
    105 }
    106 
    107 void FloatRect::unite(const FloatRect& other)
    108 {
    109     // Handle empty special cases first.
    110     if (other.isEmpty())
    111         return;
    112     if (isEmpty()) {
    113         *this = other;
    114         return;
    115     }
    116 
    117     uniteEvenIfEmpty(other);
    118 }
    119 
    120 void FloatRect::uniteEvenIfEmpty(const FloatRect& other)
    121 {
    122     float minX = min(x(), other.x());
    123     float minY = min(y(), other.y());
    124     float maxX = max(this->maxX(), other.maxX());
    125     float maxY = max(this->maxY(), other.maxY());
    126 
    127     setLocationAndSizeFromEdges(minX, minY, maxX, maxY);
    128 }
    129 
    130 void FloatRect::uniteIfNonZero(const FloatRect& other)
    131 {
    132     // Handle empty special cases first.
    133     if (other.isZero())
    134         return;
    135     if (isZero()) {
    136         *this = other;
    137         return;
    138     }
    139 
    140     uniteEvenIfEmpty(other);
    141 }
    142 
    143 void FloatRect::extend(const FloatPoint& p)
    144 {
    145     float minX = min(x(), p.x());
    146     float minY = min(y(), p.y());
    147     float maxX = max(this->maxX(), p.x());
    148     float maxY = max(this->maxY(), p.y());
    149 
    150     setLocationAndSizeFromEdges(minX, minY, maxX, maxY);
    151 }
    152 
    153 void FloatRect::scale(float sx, float sy)
    154 {
    155     m_location.setX(x() * sx);
    156     m_location.setY(y() * sy);
    157     m_size.setWidth(width() * sx);
    158     m_size.setHeight(height() * sy);
    159 }
    160 
    161 FloatRect unionRect(const Vector<FloatRect>& rects)
    162 {
    163     FloatRect result;
    164 
    165     size_t count = rects.size();
    166     for (size_t i = 0; i < count; ++i)
    167         result.unite(rects[i]);
    168 
    169     return result;
    170 }
    171 
    172 void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1)
    173 {
    174     float left = min(p0.x(), p1.x());
    175     float top = min(p0.y(), p1.y());
    176     float right = max(p0.x(), p1.x());
    177     float bottom = max(p0.y(), p1.y());
    178 
    179     setLocationAndSizeFromEdges(left, top, right, bottom);
    180 }
    181 
    182 namespace {
    183 // Helpers for 3- and 4-way max and min.
    184 
    185 template <typename T>
    186 T min3(const T& v1, const T& v2, const T& v3)
    187 {
    188     return min(min(v1, v2), v3);
    189 }
    190 
    191 template <typename T>
    192 T max3(const T& v1, const T& v2, const T& v3)
    193 {
    194     return max(max(v1, v2), v3);
    195 }
    196 
    197 template <typename T>
    198 T min4(const T& v1, const T& v2, const T& v3, const T& v4)
    199 {
    200     return min(min(v1, v2), min(v3, v4));
    201 }
    202 
    203 template <typename T>
    204 T max4(const T& v1, const T& v2, const T& v3, const T& v4)
    205 {
    206     return max(max(v1, v2), max(v3, v4));
    207 }
    208 
    209 } // anonymous namespace
    210 
    211 void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2)
    212 {
    213     float left = min3(p0.x(), p1.x(), p2.x());
    214     float top = min3(p0.y(), p1.y(), p2.y());
    215     float right = max3(p0.x(), p1.x(), p2.x());
    216     float bottom = max3(p0.y(), p1.y(), p2.y());
    217 
    218     setLocationAndSizeFromEdges(left, top, right, bottom);
    219 }
    220 
    221 void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3)
    222 {
    223     float left = min4(p0.x(), p1.x(), p2.x(), p3.x());
    224     float top = min4(p0.y(), p1.y(), p2.y(), p3.y());
    225     float right = max4(p0.x(), p1.x(), p2.x(), p3.x());
    226     float bottom = max4(p0.y(), p1.y(), p2.y(), p3.y());
    227 
    228     setLocationAndSizeFromEdges(left, top, right, bottom);
    229 }
    230 
    231 FloatRect::operator SkRect() const
    232 {
    233     SkRect rect = { x(), y(), maxX(), maxY() };
    234     return rect;
    235 }
    236 
    237 IntRect enclosingIntRect(const FloatRect& rect)
    238 {
    239     IntPoint location = flooredIntPoint(rect.minXMinYCorner());
    240     IntPoint maxPoint = ceiledIntPoint(rect.maxXMaxYCorner());
    241 
    242     return IntRect(location, maxPoint - location);
    243 }
    244 
    245 IntRect enclosedIntRect(const FloatRect& rect)
    246 {
    247     IntPoint location = ceiledIntPoint(rect.minXMinYCorner());
    248     IntPoint maxPoint = flooredIntPoint(rect.maxXMaxYCorner());
    249     IntSize size = maxPoint - location;
    250     size.clampNegativeToZero();
    251 
    252     return IntRect(location, size);
    253 }
    254 
    255 IntRect roundedIntRect(const FloatRect& rect)
    256 {
    257     return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size()));
    258 }
    259 
    260 FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect)
    261 {
    262     if (srcRect.width() == 0 || srcRect.height() == 0)
    263         return FloatRect();
    264 
    265     float widthScale = destRect.width() / srcRect.width();
    266     float heightScale = destRect.height() / srcRect.height();
    267     return FloatRect(destRect.x() + (r.x() - srcRect.x()) * widthScale,
    268                      destRect.y() + (r.y() - srcRect.y()) * heightScale,
    269                      r.width() * widthScale, r.height() * heightScale);
    270 }
    271 
    272 }
    273