1 | /* |
2 | * Copyright (C) 2013 Adobe Systems Incorporated. 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 | * |
8 | * 1. Redistributions of source code must retain the above |
9 | * copyright notice, this list of conditions and the following |
10 | * disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above |
12 | * copyright notice, this list of conditions and the following |
13 | * disclaimer in the documentation and/or other materials |
14 | * provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
20 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
21 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
25 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
27 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ |
29 | |
30 | #ifndef FloatRoundedRect_h |
31 | #define FloatRoundedRect_h |
32 | |
33 | #include "FloatRect.h" |
34 | #include "FloatSize.h" |
35 | #include "RoundedRect.h" |
36 | |
37 | namespace WebCore { |
38 | |
39 | class FloatRoundedRect { |
40 | WTF_MAKE_FAST_ALLOCATED; |
41 | public: |
42 | class Radii { |
43 | public: |
44 | Radii() { } |
45 | Radii(const FloatSize& topLeft, const FloatSize& topRight, const FloatSize& bottomLeft, const FloatSize& bottomRight) |
46 | : m_topLeft(topLeft) |
47 | , m_topRight(topRight) |
48 | , m_bottomLeft(bottomLeft) |
49 | , m_bottomRight(bottomRight) |
50 | { |
51 | } |
52 | |
53 | Radii(const RoundedRect::Radii& intRadii) |
54 | : m_topLeft(intRadii.topLeft()) |
55 | , m_topRight(intRadii.topRight()) |
56 | , m_bottomLeft(intRadii.bottomLeft()) |
57 | , m_bottomRight(intRadii.bottomRight()) |
58 | { |
59 | } |
60 | |
61 | explicit Radii(float uniformRadius) |
62 | : m_topLeft(uniformRadius, uniformRadius) |
63 | , m_topRight(uniformRadius, uniformRadius) |
64 | , m_bottomLeft(uniformRadius, uniformRadius) |
65 | , m_bottomRight(uniformRadius, uniformRadius) |
66 | { |
67 | } |
68 | |
69 | void setTopLeft(const FloatSize& size) { m_topLeft = size; } |
70 | void setTopRight(const FloatSize& size) { m_topRight = size; } |
71 | void setBottomLeft(const FloatSize& size) { m_bottomLeft = size; } |
72 | void setBottomRight(const FloatSize& size) { m_bottomRight = size; } |
73 | const FloatSize& topLeft() const { return m_topLeft; } |
74 | const FloatSize& topRight() const { return m_topRight; } |
75 | const FloatSize& bottomLeft() const { return m_bottomLeft; } |
76 | const FloatSize& bottomRight() const { return m_bottomRight; } |
77 | |
78 | bool isZero() const; |
79 | bool isUniformCornerRadius() const; // Including no radius. |
80 | |
81 | void scale(float factor); |
82 | void scale(float horizontalFactor, float verticalFactor); |
83 | void expand(float topWidth, float bottomWidth, float leftWidth, float rightWidth); |
84 | void expand(float size) { expand(size, size, size, size); } |
85 | void shrink(float topWidth, float bottomWidth, float leftWidth, float rightWidth) { expand(-topWidth, -bottomWidth, -leftWidth, -rightWidth); } |
86 | void shrink(float size) { shrink(size, size, size, size); } |
87 | |
88 | private: |
89 | FloatSize m_topLeft; |
90 | FloatSize m_topRight; |
91 | FloatSize m_bottomLeft; |
92 | FloatSize m_bottomRight; |
93 | }; |
94 | |
95 | WEBCORE_EXPORT explicit FloatRoundedRect(const FloatRect& = FloatRect(), const Radii& = Radii()); |
96 | explicit FloatRoundedRect(const RoundedRect&); |
97 | FloatRoundedRect(float x, float y, float width, float height); |
98 | FloatRoundedRect(const FloatRect&, const FloatSize& topLeft, const FloatSize& topRight, const FloatSize& bottomLeft, const FloatSize& bottomRight); |
99 | |
100 | const FloatRect& rect() const { return m_rect; } |
101 | const Radii& radii() const { return m_radii; } |
102 | bool isRounded() const { return !m_radii.isZero(); } |
103 | bool isEmpty() const { return m_rect.isEmpty(); } |
104 | |
105 | void setRect(const FloatRect& rect) { m_rect = rect; } |
106 | void setRadii(const Radii& radii) { m_radii = radii; } |
107 | |
108 | void move(const FloatSize& size) { m_rect.move(size); } |
109 | void inflate(float size) { m_rect.inflate(size); } |
110 | void expandRadii(float size) { m_radii.expand(size); } |
111 | void shrinkRadii(float size) { m_radii.shrink(size); } |
112 | void inflateWithRadii(float size); |
113 | void adjustRadii(); |
114 | |
115 | FloatRect topLeftCorner() const |
116 | { |
117 | return FloatRect(m_rect.x(), m_rect.y(), m_radii.topLeft().width(), m_radii.topLeft().height()); |
118 | } |
119 | FloatRect topRightCorner() const |
120 | { |
121 | return FloatRect(m_rect.maxX() - m_radii.topRight().width(), m_rect.y(), m_radii.topRight().width(), m_radii.topRight().height()); |
122 | } |
123 | FloatRect bottomLeftCorner() const |
124 | { |
125 | return FloatRect(m_rect.x(), m_rect.maxY() - m_radii.bottomLeft().height(), m_radii.bottomLeft().width(), m_radii.bottomLeft().height()); |
126 | } |
127 | FloatRect bottomRightCorner() const |
128 | { |
129 | return FloatRect(m_rect.maxX() - m_radii.bottomRight().width(), m_rect.maxY() - m_radii.bottomRight().height(), m_radii.bottomRight().width(), m_radii.bottomRight().height()); |
130 | } |
131 | |
132 | bool isRenderable() const; |
133 | bool xInterceptsAtY(float y, float& minXIntercept, float& maxXIntercept) const; |
134 | |
135 | bool intersectionIsRectangular(const FloatRect&) const; |
136 | |
137 | private: |
138 | FloatRect m_rect; |
139 | Radii m_radii; |
140 | }; |
141 | |
142 | inline bool operator==(const FloatRoundedRect::Radii& a, const FloatRoundedRect::Radii& b) |
143 | { |
144 | return a.topLeft() == b.topLeft() && a.topRight() == b.topRight() && a.bottomLeft() == b.bottomLeft() && a.bottomRight() == b.bottomRight(); |
145 | } |
146 | |
147 | inline bool operator!=(const FloatRoundedRect::Radii& a, const FloatRoundedRect::Radii& b) |
148 | { |
149 | return !(a == b); |
150 | } |
151 | |
152 | inline bool operator==(const FloatRoundedRect& a, const FloatRoundedRect& b) |
153 | { |
154 | return a.rect() == b.rect() && a.radii() == b.radii(); |
155 | } |
156 | |
157 | inline bool operator!=(const FloatRoundedRect& a, const FloatRoundedRect& b) |
158 | { |
159 | return !(a == b); |
160 | } |
161 | |
162 | inline float calcBorderRadiiConstraintScaleFor(const FloatRect& rect, const FloatRoundedRect::Radii& radii) |
163 | { |
164 | // Constrain corner radii using CSS3 rules: |
165 | // http://www.w3.org/TR/css3-background/#the-border-radius |
166 | |
167 | float factor = 1; |
168 | float radiiSum; |
169 | |
170 | // top |
171 | radiiSum = radii.topLeft().width() + radii.topRight().width(); // Casts to avoid integer overflow. |
172 | if (radiiSum > rect.width()) |
173 | factor = std::min(rect.width() / radiiSum, factor); |
174 | |
175 | // bottom |
176 | radiiSum = radii.bottomLeft().width() + radii.bottomRight().width(); |
177 | if (radiiSum > rect.width()) |
178 | factor = std::min(rect.width() / radiiSum, factor); |
179 | |
180 | // left |
181 | radiiSum = radii.topLeft().height() + radii.bottomLeft().height(); |
182 | if (radiiSum > rect.height()) |
183 | factor = std::min(rect.height() / radiiSum, factor); |
184 | |
185 | // right |
186 | radiiSum = radii.topRight().height() + radii.bottomRight().height(); |
187 | if (radiiSum > rect.height()) |
188 | factor = std::min(rect.height() / radiiSum, factor); |
189 | |
190 | ASSERT(factor <= 1); |
191 | return factor; |
192 | } |
193 | |
194 | WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const FloatRoundedRect&); |
195 | |
196 | } // namespace WebCore |
197 | |
198 | #endif // FloatRoundedRect_h |
199 | |