Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / css / BasicShapeFunctions.cpp
1 /*
2  * Copyright (C) 2012 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 HOLDER “AS IS” AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
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
27  * SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "BasicShapeFunctions.h"
32
33 #include "BasicShapes.h"
34 #include "CSSBasicShapes.h"
35 #include "CSSPrimitiveValueMappings.h"
36 #include "CSSValuePool.h"
37 #include "Pair.h"
38 #include "RenderStyle.h"
39 #include "SVGPathByteStream.h"
40
41 namespace WebCore {
42
43 static Ref<CSSPrimitiveValue> valueForCenterCoordinate(CSSValuePool& pool, const RenderStyle& style, const BasicShapeCenterCoordinate& center, EBoxOrient orientation)
44 {
45     if (center.direction() == BasicShapeCenterCoordinate::TopLeft)
46         return pool.createValue(center.length(), style);
47
48     CSSValueID keyword = orientation == HORIZONTAL ? CSSValueRight : CSSValueBottom;
49
50     return pool.createValue(Pair::create(pool.createIdentifierValue(keyword), pool.createValue(center.length(), style)));
51 }
52
53 static Ref<CSSPrimitiveValue> basicShapeRadiusToCSSValue(const RenderStyle& style, CSSValuePool& pool, const BasicShapeRadius& radius)
54 {
55     switch (radius.type()) {
56     case BasicShapeRadius::Value:
57         return pool.createValue(radius.value(), style);
58     case BasicShapeRadius::ClosestSide:
59         return pool.createIdentifierValue(CSSValueClosestSide);
60     case BasicShapeRadius::FarthestSide:
61         return pool.createIdentifierValue(CSSValueFarthestSide);
62     }
63
64     ASSERT_NOT_REACHED();
65     return pool.createIdentifierValue(CSSValueClosestSide);
66 }
67
68 Ref<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape& basicShape)
69 {
70     auto& cssValuePool = CSSValuePool::singleton();
71
72     RefPtr<CSSBasicShape> basicShapeValue;
73     switch (basicShape.type()) {
74     case BasicShape::BasicShapeCircleType: {
75         auto& circle = downcast<BasicShapeCircle>(basicShape);
76         auto circleValue = CSSBasicShapeCircle::create();
77
78         circleValue->setCenterX(valueForCenterCoordinate(cssValuePool, style, circle.centerX(), HORIZONTAL));
79         circleValue->setCenterY(valueForCenterCoordinate(cssValuePool, style, circle.centerY(), VERTICAL));
80         circleValue->setRadius(basicShapeRadiusToCSSValue(style, cssValuePool, circle.radius()));
81
82         basicShapeValue = WTFMove(circleValue);
83         break;
84     }
85     case BasicShape::BasicShapeEllipseType: {
86         auto& ellipse = downcast<BasicShapeEllipse>(basicShape);
87         auto ellipseValue = CSSBasicShapeEllipse::create();
88
89         ellipseValue->setCenterX(valueForCenterCoordinate(cssValuePool, style, ellipse.centerX(), HORIZONTAL));
90         ellipseValue->setCenterY(valueForCenterCoordinate(cssValuePool, style, ellipse.centerY(), VERTICAL));
91         ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(style, cssValuePool, ellipse.radiusX()));
92         ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(style, cssValuePool, ellipse.radiusY()));
93
94         basicShapeValue = WTFMove(ellipseValue);
95         break;
96     }
97     case BasicShape::BasicShapePolygonType: {
98         auto& polygon = downcast<BasicShapePolygon>(basicShape);
99         auto polygonValue = CSSBasicShapePolygon::create();
100
101         polygonValue->setWindRule(polygon.windRule());
102         const Vector<Length>& values = polygon.values();
103         for (unsigned i = 0; i < values.size(); i += 2)
104             polygonValue->appendPoint(cssValuePool.createValue(values.at(i), style), cssValuePool.createValue(values.at(i + 1), style));
105
106         basicShapeValue = WTFMove(polygonValue);
107         break;
108     }
109     case BasicShape::BasicShapePathType: {
110         auto& pathShape = downcast<BasicShapePath>(basicShape);
111         auto pathShapeValue = CSSBasicShapePath::create(pathShape.pathData()->copy());
112         pathShapeValue->setWindRule(pathShape.windRule());
113
114         basicShapeValue = WTFMove(pathShapeValue);
115         break;
116     }
117     case BasicShape::BasicShapeInsetType: {
118         auto& inset = downcast<BasicShapeInset>(basicShape);
119         auto insetValue = CSSBasicShapeInset::create();
120
121         insetValue->setTop(cssValuePool.createValue(inset.top(), style));
122         insetValue->setRight(cssValuePool.createValue(inset.right(), style));
123         insetValue->setBottom(cssValuePool.createValue(inset.bottom(), style));
124         insetValue->setLeft(cssValuePool.createValue(inset.left(), style));
125
126         insetValue->setTopLeftRadius(cssValuePool.createValue(inset.topLeftRadius(), style));
127         insetValue->setTopRightRadius(cssValuePool.createValue(inset.topRightRadius(), style));
128         insetValue->setBottomRightRadius(cssValuePool.createValue(inset.bottomRightRadius(), style));
129         insetValue->setBottomLeftRadius(cssValuePool.createValue(inset.bottomLeftRadius(), style));
130
131         basicShapeValue = WTFMove(insetValue);
132         break;
133     }
134     }
135
136     return cssValuePool.createValue(basicShapeValue.releaseNonNull());
137 }
138
139 static Length convertToLength(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
140 {
141     return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion | CalculatedConversion>(conversionData);
142 }
143
144 static LengthSize convertToLengthSize(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
145 {
146     if (!value)
147         return LengthSize(Length(0, Fixed), Length(0, Fixed));
148
149     Pair* pair = value->getPairValue();
150     return LengthSize(convertToLength(conversionData, pair->first()), convertToLength(conversionData, pair->second()));
151 }
152
153 static BasicShapeCenterCoordinate convertToCenterCoordinate(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
154 {
155     BasicShapeCenterCoordinate::Direction direction;
156     Length offset = Length(0, Fixed);
157
158     CSSValueID keyword = CSSValueTop;
159     if (!value)
160         keyword = CSSValueCenter;
161     else if (value->isValueID())
162         keyword = value->getValueID();
163     else if (Pair* pair = value->getPairValue()) {
164         keyword = pair->first()->getValueID();
165         offset = convertToLength(conversionData, pair->second());
166     } else
167         offset = convertToLength(conversionData, value);
168
169     switch (keyword) {
170     case CSSValueTop:
171     case CSSValueLeft:
172         direction = BasicShapeCenterCoordinate::TopLeft;
173         break;
174     case CSSValueRight:
175     case CSSValueBottom:
176         direction = BasicShapeCenterCoordinate::BottomRight;
177         break;
178     case CSSValueCenter:
179         direction = BasicShapeCenterCoordinate::TopLeft;
180         offset = Length(50, Percent);
181         break;
182     default:
183         ASSERT_NOT_REACHED();
184         direction = BasicShapeCenterCoordinate::TopLeft;
185         break;
186     }
187
188     return BasicShapeCenterCoordinate(direction, offset);
189 }
190
191 static BasicShapeRadius cssValueToBasicShapeRadius(const CSSToLengthConversionData& conversionData, PassRefPtr<CSSPrimitiveValue> radius)
192 {
193     if (!radius)
194         return BasicShapeRadius(BasicShapeRadius::ClosestSide);
195
196     if (radius->isValueID()) {
197         switch (radius->getValueID()) {
198         case CSSValueClosestSide:
199             return BasicShapeRadius(BasicShapeRadius::ClosestSide);
200         case CSSValueFarthestSide:
201             return BasicShapeRadius(BasicShapeRadius::FarthestSide);
202         default:
203             ASSERT_NOT_REACHED();
204             break;
205         }
206     }
207
208     return BasicShapeRadius(convertToLength(conversionData, radius.get()));
209 }
210
211 Ref<BasicShape> basicShapeForValue(const CSSToLengthConversionData& conversionData, const CSSBasicShape* basicShapeValue)
212 {
213     RefPtr<BasicShape> basicShape;
214
215     switch (basicShapeValue->type()) {
216     case CSSBasicShape::CSSBasicShapeCircleType: {
217         auto& circleValue = downcast<CSSBasicShapeCircle>(*basicShapeValue);
218         auto circle = BasicShapeCircle::create();
219
220         circle->setCenterX(convertToCenterCoordinate(conversionData, circleValue.centerX()));
221         circle->setCenterY(convertToCenterCoordinate(conversionData, circleValue.centerY()));
222         circle->setRadius(cssValueToBasicShapeRadius(conversionData, circleValue.radius()));
223
224         basicShape = WTFMove(circle);
225         break;
226     }
227     case CSSBasicShape::CSSBasicShapeEllipseType: {
228         auto& ellipseValue = downcast<CSSBasicShapeEllipse>(*basicShapeValue);
229         auto ellipse = BasicShapeEllipse::create();
230
231         ellipse->setCenterX(convertToCenterCoordinate(conversionData, ellipseValue.centerX()));
232         ellipse->setCenterY(convertToCenterCoordinate(conversionData, ellipseValue.centerY()));
233
234         ellipse->setRadiusX(cssValueToBasicShapeRadius(conversionData, ellipseValue.radiusX()));
235         ellipse->setRadiusY(cssValueToBasicShapeRadius(conversionData, ellipseValue.radiusY()));
236
237         basicShape = WTFMove(ellipse);
238         break;
239     }
240     case CSSBasicShape::CSSBasicShapePolygonType: {
241         auto& polygonValue = downcast<CSSBasicShapePolygon>(*basicShapeValue);
242         auto polygon = BasicShapePolygon::create();
243
244         polygon->setWindRule(polygonValue.windRule());
245         const Vector<RefPtr<CSSPrimitiveValue>>& values = polygonValue.values();
246         for (unsigned i = 0; i < values.size(); i += 2)
247             polygon->appendPoint(convertToLength(conversionData, values.at(i).get()), convertToLength(conversionData, values.at(i + 1).get()));
248
249         basicShape = WTFMove(polygon);
250         break;
251     }
252     case CSSBasicShape::CSSBasicShapeInsetType: {
253         auto& rectValue = downcast<CSSBasicShapeInset>(*basicShapeValue);
254         auto rect = BasicShapeInset::create();
255
256         rect->setTop(convertToLength(conversionData, rectValue.top()));
257         rect->setRight(convertToLength(conversionData, rectValue.right()));
258         rect->setBottom(convertToLength(conversionData, rectValue.bottom()));
259         rect->setLeft(convertToLength(conversionData, rectValue.left()));
260
261         rect->setTopLeftRadius(convertToLengthSize(conversionData, rectValue.topLeftRadius()));
262         rect->setTopRightRadius(convertToLengthSize(conversionData, rectValue.topRightRadius()));
263         rect->setBottomRightRadius(convertToLengthSize(conversionData, rectValue.bottomRightRadius()));
264         rect->setBottomLeftRadius(convertToLengthSize(conversionData, rectValue.bottomLeftRadius()));
265
266         basicShape = WTFMove(rect);
267         break;
268     }
269     case CSSBasicShape::CSSBasicShapePathType: {
270         auto& pathValue = downcast<CSSBasicShapePath>(*basicShapeValue);
271         auto path = BasicShapePath::create(pathValue.pathData().copy());
272         path->setWindRule(pathValue.windRule());
273
274         basicShape = WTFMove(path);
275         break;
276     }
277     }
278
279     return basicShape.releaseNonNull();
280 }
281
282 float floatValueForCenterCoordinate(const BasicShapeCenterCoordinate& center, float boxDimension)
283 {
284     float offset = floatValueForLength(center.length(), boxDimension);
285     if (center.direction() == BasicShapeCenterCoordinate::TopLeft)
286         return offset;
287     return boxDimension - offset;
288 }
289
290 }