• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/css/BasicShapeFunctions.h"
32 
33 #include "core/css/CSSBasicShapes.h"
34 #include "core/css/CSSPrimitiveValueMappings.h"
35 #include "core/css/CSSValuePool.h"
36 #include "core/css/Pair.h"
37 #include "core/css/resolver/StyleResolverState.h"
38 #include "core/rendering/style/BasicShapes.h"
39 #include "core/rendering/style/RenderStyle.h"
40 
41 namespace blink {
42 
valueForCenterCoordinate(CSSValuePool & pool,const RenderStyle & style,const BasicShapeCenterCoordinate & center,EBoxOrient orientation)43 static PassRefPtrWillBeRawPtr<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), Pair::DropIdenticalValues));
51 }
52 
basicShapeRadiusToCSSValue(CSSValuePool & pool,const RenderStyle & style,const BasicShapeRadius & radius)53 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> basicShapeRadiusToCSSValue(CSSValuePool& pool, const RenderStyle& style, 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 nullptr;
66 }
67 
valueForBasicShape(const RenderStyle & style,const BasicShape * basicShape)68 PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape)
69 {
70     CSSValuePool& pool = cssValuePool();
71 
72     RefPtrWillBeRawPtr<CSSBasicShape> basicShapeValue = nullptr;
73     switch (basicShape->type()) {
74     case BasicShape::BasicShapeCircleType: {
75         const BasicShapeCircle* circle = toBasicShapeCircle(basicShape);
76         RefPtrWillBeRawPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create();
77 
78         circleValue->setCenterX(valueForCenterCoordinate(pool, style, circle->centerX(), HORIZONTAL));
79         circleValue->setCenterY(valueForCenterCoordinate(pool, style, circle->centerY(), VERTICAL));
80         circleValue->setRadius(basicShapeRadiusToCSSValue(pool, style, circle->radius()));
81         basicShapeValue = circleValue.release();
82         break;
83     }
84     case BasicShape::BasicShapeEllipseType: {
85         const BasicShapeEllipse* ellipse = toBasicShapeEllipse(basicShape);
86         RefPtrWillBeRawPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create();
87 
88         ellipseValue->setCenterX(valueForCenterCoordinate(pool, style, ellipse->centerX(), HORIZONTAL));
89         ellipseValue->setCenterY(valueForCenterCoordinate(pool, style, ellipse->centerY(), VERTICAL));
90         ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusX()));
91         ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusY()));
92         basicShapeValue = ellipseValue.release();
93         break;
94     }
95     case BasicShape::BasicShapePolygonType: {
96         const BasicShapePolygon* polygon = toBasicShapePolygon(basicShape);
97         RefPtrWillBeRawPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create();
98 
99         polygonValue->setWindRule(polygon->windRule());
100         const Vector<Length>& values = polygon->values();
101         for (unsigned i = 0; i < values.size(); i += 2)
102             polygonValue->appendPoint(pool.createValue(values.at(i), style), pool.createValue(values.at(i + 1), style));
103 
104         basicShapeValue = polygonValue.release();
105         break;
106     }
107     case BasicShape::BasicShapeInsetType: {
108         const BasicShapeInset* inset = toBasicShapeInset(basicShape);
109         RefPtrWillBeRawPtr<CSSBasicShapeInset> insetValue = CSSBasicShapeInset::create();
110 
111         insetValue->setTop(pool.createValue(inset->top(), style));
112         insetValue->setRight(pool.createValue(inset->right(), style));
113         insetValue->setBottom(pool.createValue(inset->bottom(), style));
114         insetValue->setLeft(pool.createValue(inset->left(), style));
115 
116         insetValue->setTopLeftRadius(CSSPrimitiveValue::create(inset->topLeftRadius(), style));
117         insetValue->setTopRightRadius(CSSPrimitiveValue::create(inset->topRightRadius(), style));
118         insetValue->setBottomRightRadius(CSSPrimitiveValue::create(inset->bottomRightRadius(), style));
119         insetValue->setBottomLeftRadius(CSSPrimitiveValue::create(inset->bottomLeftRadius(), style));
120 
121         basicShapeValue = insetValue.release();
122         break;
123     }
124     default:
125         break;
126     }
127 
128     return pool.createValue(basicShapeValue.release());
129 }
130 
convertToLength(const StyleResolverState & state,CSSPrimitiveValue * value)131 static Length convertToLength(const StyleResolverState& state, CSSPrimitiveValue* value)
132 {
133     if (!value)
134         return Length(0, Fixed);
135     return value->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
136 }
137 
convertToLengthSize(const StyleResolverState & state,CSSPrimitiveValue * value)138 static LengthSize convertToLengthSize(const StyleResolverState& state, CSSPrimitiveValue* value)
139 {
140     if (!value)
141         return LengthSize(Length(0, Fixed), Length(0, Fixed));
142 
143     Pair* pair = value->getPairValue();
144     return LengthSize(convertToLength(state, pair->first()), convertToLength(state, pair->second()));
145 }
146 
convertToCenterCoordinate(const StyleResolverState & state,CSSPrimitiveValue * value)147 static BasicShapeCenterCoordinate convertToCenterCoordinate(const StyleResolverState& state, CSSPrimitiveValue* value)
148 {
149     BasicShapeCenterCoordinate::Direction direction;
150     Length offset = Length(0, Fixed);
151 
152     CSSValueID keyword = CSSValueTop;
153     if (!value) {
154         keyword = CSSValueCenter;
155     } else if (value->isValueID()) {
156         keyword = value->getValueID();
157     } else if (Pair* pair = value->getPairValue()) {
158         keyword = pair->first()->getValueID();
159         offset = convertToLength(state, pair->second());
160     } else {
161         offset = convertToLength(state, value);
162     }
163 
164     switch (keyword) {
165     case CSSValueTop:
166     case CSSValueLeft:
167         direction = BasicShapeCenterCoordinate::TopLeft;
168         break;
169     case CSSValueRight:
170     case CSSValueBottom:
171         direction = BasicShapeCenterCoordinate::BottomRight;
172         break;
173     case CSSValueCenter:
174         direction = BasicShapeCenterCoordinate::TopLeft;
175         offset = Length(50, Percent);
176         break;
177     default:
178         ASSERT_NOT_REACHED();
179         direction = BasicShapeCenterCoordinate::TopLeft;
180         break;
181     }
182 
183     return BasicShapeCenterCoordinate(direction, offset);
184 }
185 
cssValueToBasicShapeRadius(const StyleResolverState & state,PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius)186 static BasicShapeRadius cssValueToBasicShapeRadius(const StyleResolverState& state, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius)
187 {
188     if (!radius)
189         return BasicShapeRadius(BasicShapeRadius::ClosestSide);
190 
191     if (radius->isValueID()) {
192         switch (radius->getValueID()) {
193         case CSSValueClosestSide:
194             return BasicShapeRadius(BasicShapeRadius::ClosestSide);
195         case CSSValueFarthestSide:
196             return BasicShapeRadius(BasicShapeRadius::FarthestSide);
197         default:
198             ASSERT_NOT_REACHED();
199             break;
200         }
201     }
202 
203     return BasicShapeRadius(convertToLength(state, radius.get()));
204 }
205 
basicShapeForValue(const StyleResolverState & state,const CSSBasicShape * basicShapeValue)206 PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const CSSBasicShape* basicShapeValue)
207 {
208     RefPtr<BasicShape> basicShape;
209 
210     switch (basicShapeValue->type()) {
211     case CSSBasicShape::CSSBasicShapeCircleType: {
212         const CSSBasicShapeCircle* circleValue = static_cast<const CSSBasicShapeCircle *>(basicShapeValue);
213         RefPtr<BasicShapeCircle> circle = BasicShapeCircle::create();
214 
215         circle->setCenterX(convertToCenterCoordinate(state, circleValue->centerX()));
216         circle->setCenterY(convertToCenterCoordinate(state, circleValue->centerY()));
217         circle->setRadius(cssValueToBasicShapeRadius(state, circleValue->radius()));
218 
219         basicShape = circle.release();
220         break;
221     }
222     case CSSBasicShape::CSSBasicShapeEllipseType: {
223         const CSSBasicShapeEllipse* ellipseValue = static_cast<const CSSBasicShapeEllipse *>(basicShapeValue);
224         RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create();
225 
226         ellipse->setCenterX(convertToCenterCoordinate(state, ellipseValue->centerX()));
227         ellipse->setCenterY(convertToCenterCoordinate(state, ellipseValue->centerY()));
228         ellipse->setRadiusX(cssValueToBasicShapeRadius(state, ellipseValue->radiusX()));
229         ellipse->setRadiusY(cssValueToBasicShapeRadius(state, ellipseValue->radiusY()));
230 
231         basicShape = ellipse.release();
232         break;
233     }
234     case CSSBasicShape::CSSBasicShapePolygonType: {
235         const CSSBasicShapePolygon* polygonValue = static_cast<const CSSBasicShapePolygon *>(basicShapeValue);
236         RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create();
237 
238         polygon->setWindRule(polygonValue->windRule());
239         const WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> >& values = polygonValue->values();
240         for (unsigned i = 0; i < values.size(); i += 2)
241             polygon->appendPoint(convertToLength(state, values.at(i).get()), convertToLength(state, values.at(i + 1).get()));
242 
243         basicShape = polygon.release();
244         break;
245     }
246     case CSSBasicShape::CSSBasicShapeInsetType: {
247         const CSSBasicShapeInset* rectValue = static_cast<const CSSBasicShapeInset* >(basicShapeValue);
248         RefPtr<BasicShapeInset> rect = BasicShapeInset::create();
249 
250         rect->setTop(convertToLength(state, rectValue->top()));
251         rect->setRight(convertToLength(state, rectValue->right()));
252         rect->setBottom(convertToLength(state, rectValue->bottom()));
253         rect->setLeft(convertToLength(state, rectValue->left()));
254 
255         rect->setTopLeftRadius(convertToLengthSize(state, rectValue->topLeftRadius()));
256         rect->setTopRightRadius(convertToLengthSize(state, rectValue->topRightRadius()));
257         rect->setBottomRightRadius(convertToLengthSize(state, rectValue->bottomRightRadius()));
258         rect->setBottomLeftRadius(convertToLengthSize(state, rectValue->bottomLeftRadius()));
259 
260         basicShape = rect.release();
261         break;
262     }
263     default:
264         break;
265     }
266 
267     return basicShape.release();
268 }
269 
floatPointForCenterCoordinate(const BasicShapeCenterCoordinate & centerX,const BasicShapeCenterCoordinate & centerY,FloatSize boxSize)270 FloatPoint floatPointForCenterCoordinate(const BasicShapeCenterCoordinate& centerX, const BasicShapeCenterCoordinate& centerY, FloatSize boxSize)
271 {
272     float x = floatValueForLength(centerX.computedLength(), boxSize.width());
273     float y = floatValueForLength(centerY.computedLength(), boxSize.height());
274     return FloatPoint(x, y);
275 }
276 
277 }
278