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 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 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#ifndef FloatRect_h 28#define FloatRect_h 29 30#include "FloatPoint.h" 31 32#if USE(CG) 33typedef struct CGRect CGRect; 34#endif 35 36#if PLATFORM(MAC) 37#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES 38typedef struct CGRect NSRect; 39#else 40typedef struct _NSRect NSRect; 41#endif 42#endif // PLATFORM(MAC) 43 44#if USE(CAIRO) 45typedef struct _cairo_rectangle cairo_rectangle_t; 46#endif 47 48namespace WebCore { 49 50class IntRect; 51class IntPoint; 52 53class FloatRect { 54public: 55 enum ContainsMode { 56 InsideOrOnStroke, 57 InsideButNotOnStroke 58 }; 59 60 FloatRect() { } 61 FloatRect(const FloatPoint& location, const FloatSize& size) 62 : m_location(location), m_size(size) { } 63 FloatRect(float x, float y, float width, float height) 64 : m_location(FloatPoint(x, y)), m_size(FloatSize(width, height)) { } 65 FloatRect(const IntRect&); 66 67 static FloatRect narrowPrecision(double x, double y, double width, double height); 68 69 FloatPoint location() const { return m_location; } 70 FloatSize size() const { return m_size; } 71 72 void setLocation(const FloatPoint& location) { m_location = location; } 73 void setSize(const FloatSize& size) { m_size = size; } 74 75 float x() const { return m_location.x(); } 76 float y() const { return m_location.y(); } 77 float maxX() const { return x() + width(); } 78 float maxY() const { return y() + height(); } 79 float width() const { return m_size.width(); } 80 float height() const { return m_size.height(); } 81 82 void setX(float x) { m_location.setX(x); } 83 void setY(float y) { m_location.setY(y); } 84 void setWidth(float width) { m_size.setWidth(width); } 85 void setHeight(float height) { m_size.setHeight(height); } 86 87 bool isEmpty() const { return m_size.isEmpty(); } 88 bool isZero() const { return m_size.isZero(); } 89 bool isExpressibleAsIntRect() const; 90 91 FloatPoint center() const { return FloatPoint(x() + width() / 2, y() + height() / 2); } 92 93 void move(const FloatSize& delta) { m_location += delta; } 94 void moveBy(const FloatPoint& delta) { m_location.move(delta.x(), delta.y()); } 95 void move(float dx, float dy) { m_location.move(dx, dy); } 96 97 void expand(const FloatSize& size) { m_size += size; } 98 void expand(float dw, float dh) { m_size.expand(dw, dh); } 99 void contract(const FloatSize& size) { m_size -= size; } 100 void contract(float dw, float dh) { m_size.expand(-dw, -dh); } 101 102 void shiftXEdgeTo(float edge) 103 { 104 float delta = edge - x(); 105 setX(edge); 106 setWidth(std::max(0.0f, width() - delta)); 107 } 108 void shiftMaxXEdgeTo(float edge) 109 { 110 float delta = edge - maxX(); 111 setWidth(std::max(0.0f, width() + delta)); 112 } 113 void shiftYEdgeTo(float edge) 114 { 115 float delta = edge - y(); 116 setY(edge); 117 setHeight(std::max(0.0f, height() - delta)); 118 } 119 void shiftMaxYEdgeTo(float edge) 120 { 121 float delta = edge - maxY(); 122 setHeight(std::max(0.0f, height() + delta)); 123 } 124 125 FloatPoint minXMinYCorner() const { return m_location; } // typically topLeft 126 FloatPoint maxXMinYCorner() const { return FloatPoint(m_location.x() + m_size.width(), m_location.y()); } // typically topRight 127 FloatPoint minXMaxYCorner() const { return FloatPoint(m_location.x(), m_location.y() + m_size.height()); } // typically bottomLeft 128 FloatPoint maxXMaxYCorner() const { return FloatPoint(m_location.x() + m_size.width(), m_location.y() + m_size.height()); } // typically bottomRight 129 130 bool intersects(const FloatRect&) const; 131 bool contains(const FloatRect&) const; 132 bool contains(const FloatPoint&, ContainsMode = InsideOrOnStroke) const; 133 134 void intersect(const FloatRect&); 135 void unite(const FloatRect&); 136 void uniteEvenIfEmpty(const FloatRect&); 137 void uniteIfNonZero(const FloatRect&); 138 void extend(const FloatPoint&); 139 140 // Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version 141 // is really checking for containment of 1x1 rect, but that doesn't make sense with floats. 142 bool contains(float px, float py) const 143 { return px >= x() && px <= maxX() && py >= y() && py <= maxY(); } 144 145 bool overlapsYRange(float y1, float y2) const { return !isEmpty() && y2 >= y1 && y2 >= y() && y1 <= maxY(); } 146 bool overlapsXRange(float x1, float x2) const { return !isEmpty() && x2 >= x1 && x2 >= x() && x1 <= maxX(); } 147 148 void inflateX(float dx) { 149 m_location.setX(m_location.x() - dx); 150 m_size.setWidth(m_size.width() + dx + dx); 151 } 152 void inflateY(float dy) { 153 m_location.setY(m_location.y() - dy); 154 m_size.setHeight(m_size.height() + dy + dy); 155 } 156 void inflate(float d) { inflateX(d); inflateY(d); } 157 void scale(float s) { scale(s, s); } 158 void scale(float sx, float sy); 159 160 FloatRect transposedRect() const { return FloatRect(m_location.transposedPoint(), m_size.transposedSize()); } 161 162 // Re-initializes this rectangle to fit the sets of passed points. 163 void fitToPoints(const FloatPoint& p0, const FloatPoint& p1); 164 void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2); 165 void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3); 166 167#if USE(CG) 168 FloatRect(const CGRect&); 169 operator CGRect() const; 170#endif 171 172#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES) 173 FloatRect(const NSRect&); 174 operator NSRect() const; 175#endif 176 177#if USE(CAIRO) 178 FloatRect(const cairo_rectangle_t&); 179 operator cairo_rectangle_t() const; 180#endif 181 182 void dump(WTF::PrintStream& out) const; 183 184 static FloatRect infiniteRect(); 185 bool isInfinite() const; 186 187private: 188 FloatPoint m_location; 189 FloatSize m_size; 190 191 void setLocationAndSizeFromEdges(float left, float top, float right, float bottom) 192 { 193 m_location.set(left, top); 194 m_size.setWidth(right - left); 195 m_size.setHeight(bottom - top); 196 } 197}; 198 199inline FloatRect intersection(const FloatRect& a, const FloatRect& b) 200{ 201 FloatRect c = a; 202 c.intersect(b); 203 return c; 204} 205 206inline FloatRect unionRect(const FloatRect& a, const FloatRect& b) 207{ 208 FloatRect c = a; 209 c.unite(b); 210 return c; 211} 212 213inline FloatRect& operator+=(FloatRect& a, const FloatRect& b) 214{ 215 a.move(b.x(), b.y()); 216 a.setWidth(a.width() + b.width()); 217 a.setHeight(a.height() + b.height()); 218 return a; 219} 220 221inline FloatRect operator+(const FloatRect& a, const FloatRect& b) 222{ 223 FloatRect c = a; 224 c += b; 225 return c; 226} 227 228inline bool operator==(const FloatRect& a, const FloatRect& b) 229{ 230 return a.location() == b.location() && a.size() == b.size(); 231} 232 233inline bool operator!=(const FloatRect& a, const FloatRect& b) 234{ 235 return a.location() != b.location() || a.size() != b.size(); 236} 237 238inline FloatRect FloatRect::infiniteRect() 239{ 240 static FloatRect infiniteRect(-std::numeric_limits<float>::max() / 2, -std::numeric_limits<float>::max() / 2, std::numeric_limits<float>::max(), std::numeric_limits<float>::max()); 241 return infiniteRect; 242} 243 244inline bool FloatRect::isInfinite() const 245{ 246 return *this == infiniteRect(); 247} 248 249FloatRect enclosingRectExtendedToDevicePixels(const FloatRect&, float deviceScaleFactor); 250IntRect enclosingIntRect(const FloatRect&); 251 252// Returns a valid IntRect contained within the given FloatRect. 253IntRect enclosedIntRect(const FloatRect&); 254 255IntRect roundedIntRect(const FloatRect&); 256 257} 258 259#endif 260