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