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 "FloatRect.h"
     29 
     30 #include "FloatConversion.h"
     31 #include "IntRect.h"
     32 #include <algorithm>
     33 #include <math.h>
     34 #include <wtf/MathExtras.h>
     35 
     36 using std::max;
     37 using std::min;
     38 
     39 namespace WebCore {
     40 
     41 FloatRect::FloatRect(const IntRect& r) : m_location(r.location()), m_size(r.size())
     42 {
     43 }
     44 
     45 FloatRect FloatRect::narrowPrecision(double x, double y, double width, double height)
     46 {
     47     return FloatRect(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), narrowPrecisionToFloat(width), narrowPrecisionToFloat(height));
     48 }
     49 
     50 bool FloatRect::intersects(const FloatRect& other) const
     51 {
     52     // Checking emptiness handles negative widths as well as zero.
     53     return !isEmpty() && !other.isEmpty()
     54         && x() < other.maxX() && other.x() < maxX()
     55         && y() < other.maxY() && other.y() < maxY();
     56 }
     57 
     58 bool FloatRect::contains(const FloatRect& other) const
     59 {
     60     return x() <= other.x() && maxX() >= other.maxX()
     61         && y() <= other.y() && maxY() >= other.maxY();
     62 }
     63 
     64 void FloatRect::intersect(const FloatRect& other)
     65 {
     66     float l = max(x(), other.x());
     67     float t = max(y(), other.y());
     68     float r = min(maxX(), other.maxX());
     69     float b = min(maxY(), other.maxY());
     70 
     71     // Return a clean empty rectangle for non-intersecting cases.
     72     if (l >= r || t >= b) {
     73         l = 0;
     74         t = 0;
     75         r = 0;
     76         b = 0;
     77     }
     78 
     79     setLocationAndSizeFromEdges(l, t, r, b);
     80 }
     81 
     82 void FloatRect::unite(const FloatRect& other)
     83 {
     84     // Handle empty special cases first.
     85     if (other.isEmpty())
     86         return;
     87     if (isEmpty()) {
     88         *this = other;
     89         return;
     90     }
     91 
     92     float l = min(x(), other.x());
     93     float t = min(y(), other.y());
     94     float r = max(maxX(), other.maxX());
     95     float b = max(maxY(), other.maxY());
     96 
     97     setLocationAndSizeFromEdges(l, t, r, b);
     98 }
     99 
    100 void FloatRect::uniteIfNonZero(const FloatRect& other)
    101 {
    102     // Handle empty special cases first.
    103     if (!other.width() && !other.height())
    104         return;
    105     if (!width() && !height()) {
    106         *this = other;
    107         return;
    108     }
    109 
    110     float left = min(x(), other.x());
    111     float top = min(y(), other.y());
    112     float right = max(maxX(), other.maxX());
    113     float bottom = max(maxY(), other.maxY());
    114 
    115     setLocationAndSizeFromEdges(left, top, right, bottom);
    116 }
    117 
    118 void FloatRect::scale(float sx, float sy)
    119 {
    120     m_location.setX(x() * sx);
    121     m_location.setY(y() * sy);
    122     m_size.setWidth(width() * sx);
    123     m_size.setHeight(height() * sy);
    124 }
    125 
    126 void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1)
    127 {
    128     float left = min(p0.x(), p1.x());
    129     float top = min(p0.y(), p1.y());
    130     float right = max(p0.x(), p1.x());
    131     float bottom = max(p0.y(), p1.y());
    132 
    133     setLocationAndSizeFromEdges(left, top, right, bottom);
    134 }
    135 
    136 namespace {
    137 // Helpers for 3- and 4-way max and min.
    138 
    139 template <typename T>
    140 T min3(const T& v1, const T& v2, const T& v3)
    141 {
    142     return min(min(v1, v2), v3);
    143 }
    144 
    145 template <typename T>
    146 T max3(const T& v1, const T& v2, const T& v3)
    147 {
    148     return max(max(v1, v2), v3);
    149 }
    150 
    151 template <typename T>
    152 T min4(const T& v1, const T& v2, const T& v3, const T& v4)
    153 {
    154     return min(min(v1, v2), min(v3, v4));
    155 }
    156 
    157 template <typename T>
    158 T max4(const T& v1, const T& v2, const T& v3, const T& v4)
    159 {
    160     return max(max(v1, v2), max(v3, v4));
    161 }
    162 
    163 } // anonymous namespace
    164 
    165 void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2)
    166 {
    167     float left = min3(p0.x(), p1.x(), p2.x());
    168     float top = min3(p0.y(), p1.y(), p2.y());
    169     float right = max3(p0.x(), p1.x(), p2.x());
    170     float bottom = max3(p0.y(), p1.y(), p2.y());
    171 
    172     setLocationAndSizeFromEdges(left, top, right, bottom);
    173 }
    174 
    175 void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3)
    176 {
    177     float left = min4(p0.x(), p1.x(), p2.x(), p3.x());
    178     float top = min4(p0.y(), p1.y(), p2.y(), p3.y());
    179     float right = max4(p0.x(), p1.x(), p2.x(), p3.x());
    180     float bottom = max4(p0.y(), p1.y(), p2.y(), p3.y());
    181 
    182     setLocationAndSizeFromEdges(left, top, right, bottom);
    183 }
    184 
    185 IntRect enclosingIntRect(const FloatRect& rect)
    186 {
    187     float left = floorf(rect.x());
    188     float top = floorf(rect.y());
    189     float width = ceilf(rect.maxX()) - left;
    190     float height = ceilf(rect.maxY()) - top;
    191 
    192     return IntRect(clampToInteger(left), clampToInteger(top),
    193                    clampToInteger(width), clampToInteger(height));
    194 }
    195 
    196 FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect)
    197 {
    198     if (srcRect.width() == 0 || srcRect.height() == 0)
    199         return FloatRect();
    200 
    201     float widthScale = destRect.width() / srcRect.width();
    202     float heightScale = destRect.height() / srcRect.height();
    203     return FloatRect(destRect.x() + (r.x() - srcRect.x()) * widthScale,
    204                      destRect.y() + (r.y() - srcRect.y()) * heightScale,
    205                      r.width() * widthScale, r.height() * heightScale);
    206 }
    207 
    208 }
    209