OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "core/css/properties/CSSPropertyShapeUtil.h" | |
6 | |
7 #include "core/css/CSSBasicShapeValues.h" | |
8 #include "core/css/parser/CSSParserContext.h" | |
9 #include "core/css/parser/CSSParserMode.h" | |
10 #include "core/css/parser/CSSParserTokenRange.h" | |
11 #include "core/css/parser/CSSPropertyParserHelpers.h" | |
12 | |
13 namespace blink { | |
14 | |
15 using namespace CSSPropertyParserHelpers; | |
16 | |
17 namespace { | |
18 | |
19 static CSSValue* consumeShapeRadius(CSSParserTokenRange& args, | |
aazzam
2017/01/19 01:48:38
put all these static helper functions into an anon
| |
20 CSSParserMode cssParserMode) { | |
21 if (identMatches<CSSValueClosestSide, CSSValueFarthestSide>(args.peek().id())) | |
22 return consumeIdent(args); | |
23 return consumeLengthOrPercent(args, cssParserMode, ValueRangeNonNegative); | |
24 } | |
25 | |
26 static CSSBasicShapeCircleValue* consumeBasicShapeCircle( | |
27 CSSParserTokenRange& args, | |
28 const CSSParserContext* context) { | |
29 // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes | |
30 // circle( [<shape-radius>]? [at <position>]? ) | |
31 CSSBasicShapeCircleValue* shape = CSSBasicShapeCircleValue::create(); | |
32 if (CSSValue* radius = consumeShapeRadius(args, context->mode())) | |
33 shape->setRadius(radius); | |
34 if (consumeIdent<CSSValueAt>(args)) { | |
35 CSSValue* centerX = nullptr; | |
36 CSSValue* centerY = nullptr; | |
37 if (!consumePosition(args, context->mode(), UnitlessQuirk::Forbid, centerX, | |
38 centerY)) | |
39 return nullptr; | |
40 shape->setCenterX(centerX); | |
41 shape->setCenterY(centerY); | |
42 } | |
43 return shape; | |
44 } | |
45 | |
46 static CSSBasicShapeEllipseValue* consumeBasicShapeEllipse( | |
47 CSSParserTokenRange& args, | |
48 const CSSParserContext* context) { | |
49 // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes | |
50 // ellipse( [<shape-radius>{2}]? [at <position>]? ) | |
51 CSSBasicShapeEllipseValue* shape = CSSBasicShapeEllipseValue::create(); | |
52 if (CSSValue* radiusX = consumeShapeRadius(args, context->mode())) { | |
53 shape->setRadiusX(radiusX); | |
54 if (CSSValue* radiusY = consumeShapeRadius(args, context->mode())) | |
55 shape->setRadiusY(radiusY); | |
56 } | |
57 if (consumeIdent<CSSValueAt>(args)) { | |
58 CSSValue* centerX = nullptr; | |
59 CSSValue* centerY = nullptr; | |
60 if (!consumePosition(args, context->mode(), UnitlessQuirk::Forbid, centerX, | |
61 centerY)) | |
62 return nullptr; | |
63 shape->setCenterX(centerX); | |
64 shape->setCenterY(centerY); | |
65 } | |
66 return shape; | |
67 } | |
68 | |
69 static CSSBasicShapePolygonValue* consumeBasicShapePolygon( | |
70 CSSParserTokenRange& args, | |
71 const CSSParserContext* context) { | |
72 CSSBasicShapePolygonValue* shape = CSSBasicShapePolygonValue::create(); | |
73 if (identMatches<CSSValueEvenodd, CSSValueNonzero>(args.peek().id())) { | |
74 shape->setWindRule(args.consumeIncludingWhitespace().id() == CSSValueEvenodd | |
75 ? RULE_EVENODD | |
76 : RULE_NONZERO); | |
77 if (!consumeCommaIncludingWhitespace(args)) | |
78 return nullptr; | |
79 } | |
80 | |
81 do { | |
82 CSSPrimitiveValue* xLength = | |
83 consumeLengthOrPercent(args, context->mode(), ValueRangeAll); | |
84 if (!xLength) | |
85 return nullptr; | |
86 CSSPrimitiveValue* yLength = | |
87 consumeLengthOrPercent(args, context->mode(), ValueRangeAll); | |
88 if (!yLength) | |
89 return nullptr; | |
90 shape->appendPoint(xLength, yLength); | |
91 } while (consumeCommaIncludingWhitespace(args)); | |
92 return shape; | |
93 } | |
94 | |
95 static CSSBasicShapeInsetValue* consumeBasicShapeInset( | |
96 CSSParserTokenRange& args, | |
97 const CSSParserContext* context) { | |
98 CSSBasicShapeInsetValue* shape = CSSBasicShapeInsetValue::create(); | |
99 CSSPrimitiveValue* top = | |
100 consumeLengthOrPercent(args, context->mode(), ValueRangeAll); | |
101 if (!top) | |
102 return nullptr; | |
103 CSSPrimitiveValue* right = | |
104 consumeLengthOrPercent(args, context->mode(), ValueRangeAll); | |
105 CSSPrimitiveValue* bottom = nullptr; | |
106 CSSPrimitiveValue* left = nullptr; | |
107 if (right) { | |
108 bottom = consumeLengthOrPercent(args, context->mode(), ValueRangeAll); | |
109 if (bottom) | |
110 left = consumeLengthOrPercent(args, context->mode(), ValueRangeAll); | |
111 } | |
112 if (left) | |
113 shape->updateShapeSize4Values(top, right, bottom, left); | |
114 else if (bottom) | |
115 shape->updateShapeSize3Values(top, right, bottom); | |
116 else if (right) | |
117 shape->updateShapeSize2Values(top, right); | |
118 else | |
119 shape->updateShapeSize1Value(top); | |
120 | |
121 if (consumeIdent<CSSValueRound>(args)) { | |
122 CSSValue* horizontalRadii[4] = {0}; | |
123 CSSValue* verticalRadii[4] = {0}; | |
124 if (!CSSPropertyShapeUtil::consumeRadii( | |
125 horizontalRadii, verticalRadii, args, context->mode(), false)) | |
126 return nullptr; | |
127 shape->setTopLeftRadius( | |
128 CSSValuePair::create(horizontalRadii[0], verticalRadii[0], | |
129 CSSValuePair::DropIdenticalValues)); | |
130 shape->setTopRightRadius( | |
131 CSSValuePair::create(horizontalRadii[1], verticalRadii[1], | |
132 CSSValuePair::DropIdenticalValues)); | |
133 shape->setBottomRightRadius( | |
134 CSSValuePair::create(horizontalRadii[2], verticalRadii[2], | |
135 CSSValuePair::DropIdenticalValues)); | |
136 shape->setBottomLeftRadius( | |
137 CSSValuePair::create(horizontalRadii[3], verticalRadii[3], | |
138 CSSValuePair::DropIdenticalValues)); | |
139 } | |
140 return shape; | |
141 } | |
142 | |
143 } // namespace | |
144 | |
145 bool CSSPropertyShapeUtil::consumeRadii( | |
146 CSSValue* horizontalRadii[4], | |
147 CSSValue* verticalRadii[4], | |
148 CSSParserTokenRange& range, | |
149 CSSParserMode cssParserMode, | |
150 bool useLegacyParsing) { | |
151 unsigned i = 0; | |
152 for (; i < 4 && !range.atEnd() && range.peek().type() != DelimiterToken; | |
153 ++i) { | |
154 horizontalRadii[i] = | |
155 consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative); | |
156 if (!horizontalRadii[i]) | |
157 return false; | |
158 } | |
159 if (!horizontalRadii[0]) | |
160 return false; | |
161 if (range.atEnd()) { | |
162 // Legacy syntax: -webkit-border-radius: l1 l2; is equivalent to | |
163 // border-radius: l1 / l2; | |
164 if (useLegacyParsing && i == 2) { | |
165 verticalRadii[0] = horizontalRadii[1]; | |
166 horizontalRadii[1] = nullptr; | |
167 } else { | |
168 complete4Sides(horizontalRadii); | |
169 for (unsigned i = 0; i < 4; ++i) | |
170 verticalRadii[i] = horizontalRadii[i]; | |
171 return true; | |
172 } | |
173 } else { | |
174 if (!consumeSlashIncludingWhitespace(range)) | |
175 return false; | |
176 for (i = 0; i < 4 && !range.atEnd(); ++i) { | |
177 verticalRadii[i] = | |
178 consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative); | |
179 if (!verticalRadii[i]) | |
180 return false; | |
181 } | |
182 if (!verticalRadii[0] || !range.atEnd()) | |
183 return false; | |
184 } | |
185 complete4Sides(horizontalRadii); | |
186 complete4Sides(verticalRadii); | |
187 return true; | |
188 } | |
189 | |
190 CSSValue* CSSPropertyShapeUtil::consumeBasicShape( | |
191 CSSParserTokenRange& range, | |
192 const CSSParserContext* context) { | |
193 CSSValue* shape = nullptr; | |
194 if (range.peek().type() != FunctionToken) | |
195 return nullptr; | |
196 CSSValueID id = range.peek().functionId(); | |
197 CSSParserTokenRange rangeCopy = range; | |
198 CSSParserTokenRange args = consumeFunction(rangeCopy); | |
199 if (id == CSSValueCircle) | |
200 shape = consumeBasicShapeCircle(args, context); | |
201 else if (id == CSSValueEllipse) | |
202 shape = consumeBasicShapeEllipse(args, context); | |
203 else if (id == CSSValuePolygon) | |
204 shape = consumeBasicShapePolygon(args, context); | |
205 else if (id == CSSValueInset) | |
206 shape = consumeBasicShapeInset(args, context); | |
207 if (!shape || !args.atEnd()) | |
208 return nullptr; | |
209 range = rangeCopy; | |
210 return shape; | |
211 } | |
212 | |
213 } // namespace blink | |
OLD | NEW |