OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | 2 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above | 8 * 1. Redistributions of source code must retain the above |
9 * copyright notice, this list of conditions and the following | 9 * copyright notice, this list of conditions and the following |
10 * disclaimer. | 10 * disclaimer. |
(...skipping 10 matching lines...) Expand all Loading... |
21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF | 25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 * SUCH DAMAGE. | 27 * SUCH DAMAGE. |
28 */ | 28 */ |
29 | 29 |
30 #include "config.h" | 30 #include "config.h" |
| 31 #include "core/rendering/style/BasicShapes.h" |
31 | 32 |
32 #include "core/rendering/style/BasicShapes.h" | 33 #include "core/css/BasicShapeFunctions.h" |
33 #include "platform/LengthFunctions.h" | 34 #include "platform/LengthFunctions.h" |
34 #include "platform/geometry/FloatRect.h" | 35 #include "platform/geometry/FloatRect.h" |
35 #include "platform/graphics/Path.h" | 36 #include "platform/graphics/Path.h" |
36 | 37 |
37 namespace WebCore { | 38 namespace WebCore { |
38 | 39 |
39 bool BasicShape::canBlend(const BasicShape* other) const | 40 bool BasicShape::canBlend(const BasicShape* other) const |
40 { | 41 { |
41 // FIXME: Support animations between different shapes in the future. | 42 // FIXME: Support animations between different shapes in the future. |
42 if (!other || !isSameType(*other)) | 43 if (!other || !isSameType(*other)) |
43 return false; | 44 return false; |
44 | 45 |
45 // Just polygons with same number of vertices can be animated. | 46 // Just polygons with same number of vertices can be animated. |
46 if (type() == BasicShape::BasicShapePolygonType | 47 if (type() == BasicShape::BasicShapePolygonType |
47 && static_cast<const BasicShapePolygon*>(this)->values().size() != stati
c_cast<const BasicShapePolygon*>(other)->values().size()) | 48 && static_cast<const BasicShapePolygon*>(this)->values().size() != stati
c_cast<const BasicShapePolygon*>(other)->values().size()) |
48 return false; | 49 return false; |
49 | 50 |
| 51 // Circles with keywords for radii or center coordinates cannot be animated. |
| 52 if (type() == BasicShape::BasicShapeCircleType) { |
| 53 const BasicShapeCircle* thisCircle = static_cast<const BasicShapeCircle*
>(this); |
| 54 const BasicShapeCircle* otherCircle = static_cast<const BasicShapeCircle
*>(other); |
| 55 if (!thisCircle->radius().canBlend(otherCircle->radius()) |
| 56 || !thisCircle->centerX().canBlend(otherCircle->centerX()) |
| 57 || !thisCircle->centerY().canBlend(otherCircle->centerY())) |
| 58 return false; |
| 59 } |
| 60 |
50 return true; | 61 return true; |
51 } | 62 } |
52 | 63 |
53 void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox) | 64 void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox) |
54 { | 65 { |
55 ASSERT(path.isEmpty()); | 66 ASSERT(path.isEmpty()); |
56 path.addRoundedRect( | 67 path.addRoundedRect( |
57 FloatRect( | 68 FloatRect( |
58 floatValueForLength(m_x, boundingBox.width()) + boundingBox.x(), | 69 floatValueForLength(m_x, boundingBox.width()) + boundingBox.x(), |
59 floatValueForLength(m_y, boundingBox.height()) + boundingBox.y(), | 70 floatValueForLength(m_y, boundingBox.height()) + boundingBox.y(), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 { | 105 { |
95 if (!isSameType(o)) | 106 if (!isSameType(o)) |
96 return false; | 107 return false; |
97 const DeprecatedBasicShapeCircle& other = toDeprecatedBasicShapeCircle(o); | 108 const DeprecatedBasicShapeCircle& other = toDeprecatedBasicShapeCircle(o); |
98 return m_centerX == other.m_centerX && m_centerY == other.m_centerY && m_rad
ius == other.m_radius; | 109 return m_centerX == other.m_centerX && m_centerY == other.m_centerY && m_rad
ius == other.m_radius; |
99 } | 110 } |
100 | 111 |
101 void DeprecatedBasicShapeCircle::path(Path& path, const FloatRect& boundingBox) | 112 void DeprecatedBasicShapeCircle::path(Path& path, const FloatRect& boundingBox) |
102 { | 113 { |
103 ASSERT(path.isEmpty()); | 114 ASSERT(path.isEmpty()); |
104 float diagonal = sqrtf((boundingBox.width() * boundingBox.width() + bounding
Box.height() * boundingBox.height()) / 2); | 115 float diagonal = hypotf(boundingBox.width(), boundingBox.height()) / sqrtf(2
); |
105 float centerX = floatValueForLength(m_centerX, boundingBox.width()); | 116 float centerX = floatValueForLength(m_centerX, boundingBox.width()); |
106 float centerY = floatValueForLength(m_centerY, boundingBox.height()); | 117 float centerY = floatValueForLength(m_centerY, boundingBox.height()); |
107 float radius = floatValueForLength(m_radius, diagonal); | 118 float radius = floatValueForLength(m_radius, diagonal); |
108 path.addEllipse(FloatRect( | 119 path.addEllipse(FloatRect( |
109 centerX - radius + boundingBox.x(), | 120 centerX - radius + boundingBox.x(), |
110 centerY - radius + boundingBox.y(), | 121 centerY - radius + boundingBox.y(), |
111 radius * 2, | 122 radius * 2, |
112 radius * 2 | 123 radius * 2 |
113 )); | 124 )); |
114 } | 125 } |
(...skipping 11 matching lines...) Expand all Loading... |
126 } | 137 } |
127 | 138 |
128 bool BasicShapeCircle::operator==(const BasicShape& o) const | 139 bool BasicShapeCircle::operator==(const BasicShape& o) const |
129 { | 140 { |
130 if (!isSameType(o)) | 141 if (!isSameType(o)) |
131 return false; | 142 return false; |
132 const BasicShapeCircle& other = toBasicShapeCircle(o); | 143 const BasicShapeCircle& other = toBasicShapeCircle(o); |
133 return m_centerX == other.m_centerX && m_centerY == other.m_centerY && m_rad
ius == other.m_radius; | 144 return m_centerX == other.m_centerX && m_centerY == other.m_centerY && m_rad
ius == other.m_radius; |
134 } | 145 } |
135 | 146 |
| 147 float BasicShapeCircle::floatValueForRadiusInBox(FloatSize boxSize) const |
| 148 { |
| 149 if (m_radius.type() == BasicShapeRadius::Value) |
| 150 return floatValueForLength(m_radius.value(), hypotf(boxSize.width(), box
Size.height()) / sqrtf(2)); |
| 151 |
| 152 FloatPoint center = floatPointForCenterCoordinate(m_centerX, m_centerY, boxS
ize); |
| 153 |
| 154 if (m_radius.type() == BasicShapeRadius::ClosestSide) |
| 155 return std::min(std::min(center.x(), boxSize.width() - center.x()), std:
:min(center.y(), boxSize.height() - center.y())); |
| 156 |
| 157 // If radius.type() == BasicShapeRadius::FarthestSide. |
| 158 return std::max(std::max(center.x(), boxSize.width() - center.x()), std::max
(center.y(), boxSize.height() - center.y())); |
| 159 } |
| 160 |
136 void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox) | 161 void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox) |
137 { | 162 { |
138 ASSERT(path.isEmpty()); | 163 ASSERT(path.isEmpty()); |
139 // FIXME Complete implementation of path. | 164 FloatPoint center = floatPointForCenterCoordinate(m_centerX, m_centerY, boun
dingBox.size()); |
140 // Compute closest-side and farthest-side from boundingBox. | 165 float radius = floatValueForRadiusInBox(boundingBox.size()); |
141 // Compute top, left, bottom, right from boundingBox. | |
142 if (m_radius.type() != BasicShapeRadius::Value) | |
143 return; | |
144 if (m_centerX.keyword() != BasicShapeCenterCoordinate::None || m_centerY.key
word() != BasicShapeCenterCoordinate::None) | |
145 return; | |
146 | |
147 float diagonal = sqrtf((boundingBox.width() * boundingBox.width() + bounding
Box.height() * boundingBox.height()) / 2); | |
148 float centerX = floatValueForLength(m_centerX.length(), boundingBox.width())
; | |
149 float centerY = floatValueForLength(m_centerY.length(), boundingBox.height()
); | |
150 float radius = floatValueForLength(m_radius.value(), diagonal); | |
151 path.addEllipse(FloatRect( | 166 path.addEllipse(FloatRect( |
152 centerX - radius + boundingBox.x(), | 167 center.x() - radius + boundingBox.x(), |
153 centerY - radius + boundingBox.y(), | 168 center.y() - radius + boundingBox.y(), |
154 radius * 2, | 169 radius * 2, |
155 radius * 2 | 170 radius * 2 |
156 )); | 171 )); |
157 } | 172 } |
158 | 173 |
159 PassRefPtr<BasicShape> BasicShapeCircle::blend(const BasicShape* other, double p
rogress) const | 174 PassRefPtr<BasicShape> BasicShapeCircle::blend(const BasicShape* other, double p
rogress) const |
160 { | 175 { |
161 ASSERT(type() == other->type()); | 176 ASSERT(type() == other->type()); |
162 const BasicShapeCircle* o = static_cast<const BasicShapeCircle*>(other); | 177 const BasicShapeCircle* o = static_cast<const BasicShapeCircle*>(other); |
163 RefPtr<BasicShapeCircle> result = BasicShapeCircle::create(); | 178 RefPtr<BasicShapeCircle> result = BasicShapeCircle::create(); |
164 | 179 |
165 if (m_radius.type() != BasicShapeRadius::Value || o->radius().type() != Basi
cShapeRadius::Value) { | |
166 result->setCenterX(o->centerX()); | |
167 result->setCenterY(o->centerY()); | |
168 result->setRadius(o->radius()); | |
169 return result; | |
170 } | |
171 | |
172 result->setCenterX(m_centerX.blend(o->centerX(), progress)); | 180 result->setCenterX(m_centerX.blend(o->centerX(), progress)); |
173 result->setCenterY(m_centerY.blend(o->centerY(), progress)); | 181 result->setCenterY(m_centerY.blend(o->centerY(), progress)); |
174 result->setRadius(m_radius.blend(o->radius(), progress)); | 182 result->setRadius(m_radius.blend(o->radius(), progress)); |
175 return result.release(); | 183 return result.release(); |
176 } | 184 } |
177 | 185 |
178 void DeprecatedBasicShapeEllipse::path(Path& path, const FloatRect& boundingBox) | 186 void DeprecatedBasicShapeEllipse::path(Path& path, const FloatRect& boundingBox) |
179 { | 187 { |
180 ASSERT(path.isEmpty()); | 188 ASSERT(path.isEmpty()); |
181 float centerX = floatValueForLength(m_centerX, boundingBox.width()); | 189 float centerX = floatValueForLength(m_centerX, boundingBox.width()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 { | 231 { |
224 ASSERT(path.isEmpty()); | 232 ASSERT(path.isEmpty()); |
225 // FIXME Complete implementation of path. Bug 124619. | 233 // FIXME Complete implementation of path. Bug 124619. |
226 // Compute closest-side and farthest-side from boundingBox. | 234 // Compute closest-side and farthest-side from boundingBox. |
227 // Compute top, left, bottom, right from boundingBox. | 235 // Compute top, left, bottom, right from boundingBox. |
228 if (m_radiusX.type() != BasicShapeRadius::Value || m_radiusY.type() != Basic
ShapeRadius::Value) | 236 if (m_radiusX.type() != BasicShapeRadius::Value || m_radiusY.type() != Basic
ShapeRadius::Value) |
229 return; | 237 return; |
230 if (m_centerX.keyword() != BasicShapeCenterCoordinate::None || m_centerY.key
word() != BasicShapeCenterCoordinate::None) | 238 if (m_centerX.keyword() != BasicShapeCenterCoordinate::None || m_centerY.key
word() != BasicShapeCenterCoordinate::None) |
231 return; | 239 return; |
232 | 240 |
233 float diagonal = sqrtf((boundingBox.width() * boundingBox.width() + bounding
Box.height() * boundingBox.height()) / 2); | 241 float diagonal = hypotf(boundingBox.width(), boundingBox.height()) / sqrtf(2
); |
234 float centerX = floatValueForLength(m_centerX.length(), boundingBox.width())
; | 242 float centerX = floatValueForLength(m_centerX.length(), boundingBox.width())
; |
235 float centerY = floatValueForLength(m_centerY.length(), boundingBox.height()
); | 243 float centerY = floatValueForLength(m_centerY.length(), boundingBox.height()
); |
236 float radiusX = floatValueForLength(m_radiusX.value(), diagonal); | 244 float radiusX = floatValueForLength(m_radiusX.value(), diagonal); |
237 float radiusY = floatValueForLength(m_radiusY.value(), diagonal); | 245 float radiusY = floatValueForLength(m_radiusY.value(), diagonal); |
238 path.addEllipse(FloatRect( | 246 path.addEllipse(FloatRect( |
239 centerX - radiusX + boundingBox.x(), | 247 centerX - radiusX + boundingBox.x(), |
240 centerY - radiusY + boundingBox.y(), | 248 centerY - radiusY + boundingBox.y(), |
241 radiusX * 2, | 249 radiusX * 2, |
242 radiusY * 2 | 250 radiusY * 2 |
243 )); | 251 )); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 } | 357 } |
350 | 358 |
351 bool BasicShapeInsetRectangle::operator==(const BasicShape& o) const | 359 bool BasicShapeInsetRectangle::operator==(const BasicShape& o) const |
352 { | 360 { |
353 if (!isSameType(o)) | 361 if (!isSameType(o)) |
354 return false; | 362 return false; |
355 const BasicShapeInsetRectangle& other = toBasicShapeInsetRectangle(o); | 363 const BasicShapeInsetRectangle& other = toBasicShapeInsetRectangle(o); |
356 return m_right == other.m_right && m_top == other.m_top && m_bottom == other
.m_bottom && m_left == other.m_left && m_cornerRadiusX == other.m_cornerRadiusX
&& m_cornerRadiusY == other.m_cornerRadiusY; | 364 return m_right == other.m_right && m_top == other.m_top && m_bottom == other
.m_bottom && m_left == other.m_left && m_cornerRadiusX == other.m_cornerRadiusX
&& m_cornerRadiusY == other.m_cornerRadiusY; |
357 } | 365 } |
358 } | 366 } |
OLD | NEW |