OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. |
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> | 5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) | 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) |
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | 8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
9 * Copyright (C) 2012 Intel Corporation. All rights reserved. | 9 * Copyright (C) 2012 Intel Corporation. All rights reserved. |
10 * | 10 * |
11 * This library is free software; you can redistribute it and/or | 11 * This library is free software; you can redistribute it and/or |
12 * modify it under the terms of the GNU Library General Public | 12 * modify it under the terms of the GNU Library General Public |
13 * License as published by the Free Software Foundation; either | 13 * License as published by the Free Software Foundation; either |
14 * version 2 of the License, or (at your option) any later version. | 14 * version 2 of the License, or (at your option) any later version. |
15 * | 15 * |
16 * This library is distributed in the hope that it will be useful, | 16 * This library is distributed in the hope that it will be useful, |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 * Library General Public License for more details. | 19 * Library General Public License for more details. |
20 * | 20 * |
21 * You should have received a copy of the GNU Library General Public License | 21 * You should have received a copy of the GNU Library General Public License |
22 * along with this library; see the file COPYING.LIB. If not, write to | 22 * along with this library; see the file COPYING.LIB. If not, write to |
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
24 * Boston, MA 02110-1301, USA. | 24 * Boston, MA 02110-1301, USA. |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 #include "core/css/parser/CSSPropertyParser.h" | 28 #include "core/css/parser/CSSPropertyParser.h" |
29 #include "RuntimeEnabledFeatures.h" | |
30 #include "core/rendering/RenderTheme.h" | |
31 #include "core/svg/SVGPaint.h" | |
32 | |
33 using namespace std; | |
29 | 34 |
30 namespace WebCore { | 35 namespace WebCore { |
31 | 36 |
32 CSSPropertyParser::CSSPropertyParser(OwnPtr<CSSParserValueList>& valueList, | 37 CSSPropertyParser::CSSPropertyParser(OwnPtr<CSSParserValueList>& valueList, |
33 const CSSParserContext& context, bool inViewport, bool savedImportant, | 38 const CSSParserContext& context, bool inViewport, bool savedImportant, |
34 ParsedPropertyVector& parsedProperties, bool& hasFontFaceOnlyValues) | 39 ParsedPropertyVector& parsedProperties, bool& hasFontFaceOnlyValues) |
35 : m_valueList(valueList) | 40 : m_valueList(valueList) |
36 , m_context(context) | 41 , m_context(context) |
37 , m_inViewport(inViewport) | 42 , m_inViewport(inViewport) |
38 , m_important(savedImportant) // See comment in header, should be removed. | 43 , m_important(savedImportant) // See comment in header, should be removed. |
39 , m_parsedProperties(parsedProperties) | 44 , m_parsedProperties(parsedProperties) |
40 , m_hasFontFaceOnlyValues(hasFontFaceOnlyValues) | 45 , m_hasFontFaceOnlyValues(hasFontFaceOnlyValues) |
41 , m_inParseShorthand(0) | 46 , m_inParseShorthand(0) |
42 , m_currentShorthand(CSSPropertyInvalid) | 47 , m_currentShorthand(CSSPropertyInvalid) |
43 , m_implicitShorthand(false) | 48 , m_implicitShorthand(false) |
44 { | 49 { |
45 } | 50 } |
46 | 51 |
47 CSSPropertyParser::~CSSPropertyParser() | 52 CSSPropertyParser::~CSSPropertyParser() |
48 { | 53 { |
49 } | 54 } |
50 | 55 |
56 static bool isSystemColor(int id) | |
pdr.
2014/02/28 22:47:17
Can we now remove the version of this from BisonCS
| |
57 { | |
58 return (id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSS ValueMenu; | |
59 } | |
60 | |
61 bool CSSPropertyParser::parseSVGValue(CSSPropertyID propId, bool important) | |
62 { | |
63 CSSParserValue* value = m_valueList->current(); | |
64 if (!value) | |
65 return false; | |
66 | |
67 CSSValueID id = value->id; | |
68 | |
69 bool validPrimitive = false; | |
70 RefPtrWillBeRawPtr<CSSValue> parsedValue; | |
71 | |
72 switch (propId) { | |
73 /* The comment to the right defines all valid value of these | |
74 * properties as defined in SVG 1.1, Appendix N. Property index */ | |
75 case CSSPropertyAlignmentBaseline: | |
76 // auto | baseline | before-edge | text-before-edge | middle | | |
77 // central | after-edge | text-after-edge | ideographic | alphabetic | | |
78 // hanging | mathematical | inherit | |
79 if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle | |
80 || (id >= CSSValueBeforeEdge && id <= CSSValueMathematical)) | |
81 validPrimitive = true; | |
82 break; | |
83 | |
84 case CSSPropertyBaselineShift: | |
85 // baseline | super | sub | <percentage> | <length> | inherit | |
86 if (id == CSSValueBaseline || id == CSSValueSub | |
87 || id >= CSSValueSuper) | |
88 validPrimitive = true; | |
89 else | |
90 validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMo de); | |
91 break; | |
92 | |
93 case CSSPropertyDominantBaseline: | |
94 // auto | use-script | no-change | reset-size | ideographic | | |
95 // alphabetic | hanging | mathematical | central | middle | | |
96 // text-after-edge | text-before-edge | inherit | |
97 if (id == CSSValueAuto || id == CSSValueMiddle | |
98 || (id >= CSSValueUseScript && id <= CSSValueResetSize) | |
99 || (id >= CSSValueCentral && id <= CSSValueMathematical)) | |
100 validPrimitive = true; | |
101 break; | |
102 | |
103 case CSSPropertyEnableBackground: | |
104 // accumulate | new [x] [y] [width] [height] | inherit | |
105 if (id == CSSValueAccumulate) // TODO : new | |
106 validPrimitive = true; | |
107 break; | |
108 | |
109 case CSSPropertyMarkerStart: | |
110 case CSSPropertyMarkerMid: | |
111 case CSSPropertyMarkerEnd: | |
112 case CSSPropertyMask: | |
113 if (id == CSSValueNone) { | |
114 validPrimitive = true; | |
115 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { | |
116 parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveV alue::CSS_URI); | |
117 if (parsedValue) | |
118 m_valueList->next(); | |
119 } | |
120 break; | |
121 | |
122 case CSSPropertyClipRule: // nonzero | evenodd | inherit | |
123 case CSSPropertyFillRule: | |
124 if (id == CSSValueNonzero || id == CSSValueEvenodd) | |
125 validPrimitive = true; | |
126 break; | |
127 | |
128 case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit | |
129 validPrimitive = validUnit(value, FNumber | FNonNeg, SVGAttributeMode); | |
130 break; | |
131 | |
132 case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit | |
133 if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel) | |
134 validPrimitive = true; | |
135 break; | |
136 | |
137 case CSSPropertyStrokeLinecap: // butt | round | square | inherit | |
138 if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare) | |
139 validPrimitive = true; | |
140 break; | |
141 | |
142 case CSSPropertyStrokeOpacity: // <opacity-value> | inherit | |
143 case CSSPropertyFillOpacity: | |
144 case CSSPropertyStopOpacity: | |
145 case CSSPropertyFloodOpacity: | |
146 validPrimitive = (!id && validUnit(value, FNumber | FPercent, SVGAttribu teMode)); | |
147 break; | |
148 | |
149 case CSSPropertyShapeRendering: | |
150 // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit | |
151 if (id == CSSValueAuto || id == CSSValueOptimizespeed | |
152 || id == CSSValueCrispedges || id == CSSValueGeometricprecision) | |
153 validPrimitive = true; | |
154 break; | |
155 | |
156 case CSSPropertyImageRendering: // auto | optimizeSpeed | | |
157 case CSSPropertyColorRendering: // optimizeQuality | inherit | |
158 if (id == CSSValueAuto || id == CSSValueOptimizespeed | |
159 || id == CSSValueOptimizequality) | |
160 validPrimitive = true; | |
161 break; | |
162 | |
163 case CSSPropertyBufferedRendering: // auto | dynamic | static | |
164 if (id == CSSValueAuto || id == CSSValueDynamic || id == CSSValueStatic) | |
165 validPrimitive = true; | |
166 break; | |
167 | |
168 case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit | |
169 if (id == CSSValueAuto || id == CSSValueSrgb) | |
170 validPrimitive = true; | |
171 break; | |
172 | |
173 case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit | |
174 case CSSPropertyColorInterpolationFilters: | |
175 if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb) | |
176 validPrimitive = true; | |
177 break; | |
178 | |
179 /* Start of supported CSS properties with validation. This is needed for par seShortHand to work | |
180 * correctly and allows optimization in applyRule(..) | |
181 */ | |
182 | |
183 case CSSPropertyTextAnchor: // start | middle | end | inherit | |
184 if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd) | |
185 validPrimitive = true; | |
186 break; | |
187 | |
188 case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit | |
189 if (id == CSSValueAuto) { | |
190 validPrimitive = true; | |
191 break; | |
192 } | |
193 /* fallthrough intentional */ | |
194 case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit | |
195 if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimi tiveValue::CSS_NUMBER) { | |
196 parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveV alue::CSS_DEG); | |
197 | |
198 if (parsedValue) | |
199 m_valueList->next(); | |
200 } | |
201 break; | |
202 | |
203 case CSSPropertyFill: // <paint> | inherit | |
204 case CSSPropertyStroke: // <paint> | inherit | |
205 { | |
206 if (id == CSSValueNone) { | |
207 parsedValue = SVGPaint::createNone(); | |
208 } else if (id == CSSValueCurrentcolor) { | |
209 parsedValue = SVGPaint::createCurrentColor(); | |
210 } else if (isSystemColor(id)) { | |
211 parsedValue = SVGPaint::createColor(RenderTheme::theme().systemC olor(id)); | |
212 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { | |
213 RGBA32 c = Color::transparent; | |
214 if (m_valueList->next()) { | |
215 if (parseColorFromValue(m_valueList->current(), c)) | |
216 parsedValue = SVGPaint::createURIAndColor(value->string, c); | |
217 else if (m_valueList->current()->id == CSSValueNone) | |
218 parsedValue = SVGPaint::createURIAndNone(value->string); | |
219 else if (m_valueList->current()->id == CSSValueCurrentcolor) | |
220 parsedValue = SVGPaint::createURIAndCurrentColor(value-> string); | |
221 } | |
222 if (!parsedValue) | |
223 parsedValue = SVGPaint::createURI(value->string); | |
224 } else { | |
225 parsedValue = parseSVGPaint(); | |
226 } | |
227 | |
228 if (parsedValue) | |
229 m_valueList->next(); | |
230 } | |
231 break; | |
232 | |
233 case CSSPropertyStopColor: // TODO : icccolor | |
234 case CSSPropertyFloodColor: | |
235 case CSSPropertyLightingColor: | |
236 if (isSystemColor(id)) | |
237 parsedValue = SVGColor::createFromColor(RenderTheme::theme().systemC olor(id)); | |
238 else if ((id >= CSSValueAqua && id <= CSSValueTransparent) | |
239 || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen) || id == C SSValueGrey) | |
240 parsedValue = SVGColor::createFromString(value->string); | |
241 else if (id == CSSValueCurrentcolor) | |
242 parsedValue = SVGColor::createCurrentColor(); | |
243 else // TODO : svgcolor (iccColor) | |
244 parsedValue = parseSVGColor(); | |
245 | |
246 if (parsedValue) | |
247 m_valueList->next(); | |
248 | |
249 break; | |
250 | |
251 case CSSPropertyPaintOrder: | |
252 if (!RuntimeEnabledFeatures::svgPaintOrderEnabled()) | |
253 return false; | |
254 | |
255 if (m_valueList->size() == 1 && id == CSSValueNormal) | |
256 validPrimitive = true; | |
257 else if ((parsedValue = parsePaintOrder())) | |
258 m_valueList->next(); | |
259 break; | |
260 | |
261 case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit | |
262 if (id == CSSValueNone || id == CSSValueNonScalingStroke) | |
263 validPrimitive = true; | |
264 break; | |
265 | |
266 case CSSPropertyWritingMode: | |
267 // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit | |
268 if (id == CSSValueLrTb || id == CSSValueRlTb || id == CSSValueTbRl || id == CSSValueLr || id == CSSValueRl || id == CSSValueTb) | |
269 validPrimitive = true; | |
270 break; | |
271 | |
272 case CSSPropertyStrokeWidth: // <length> | inherit | |
273 case CSSPropertyStrokeDashoffset: | |
274 validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMode); | |
275 break; | |
276 case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit | |
277 if (id == CSSValueNone) | |
278 validPrimitive = true; | |
279 else | |
280 parsedValue = parseSVGStrokeDasharray(); | |
281 | |
282 break; | |
283 | |
284 case CSSPropertyKerning: // auto | normal | <length> | inherit | |
285 if (id == CSSValueAuto || id == CSSValueNormal) | |
286 validPrimitive = true; | |
287 else | |
288 validPrimitive = validUnit(value, FLength, SVGAttributeMode); | |
289 break; | |
290 | |
291 case CSSPropertyClipPath: // <uri> | none | inherit | |
292 case CSSPropertyFilter: | |
293 if (id == CSSValueNone) { | |
294 validPrimitive = true; | |
295 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { | |
296 parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitive Value::UnitTypes) value->unit); | |
297 if (parsedValue) | |
298 m_valueList->next(); | |
299 } | |
300 break; | |
301 case CSSPropertyMaskType: // luminance | alpha | inherit | |
302 if (id == CSSValueLuminance || id == CSSValueAlpha) | |
303 validPrimitive = true; | |
304 break; | |
305 | |
306 /* shorthand properties */ | |
307 case CSSPropertyMarker: { | |
308 ShorthandScope scope(this, propId); | |
309 CSSPropertyParser::ImplicitScope implicitScope(this, PropertyImplicit); | |
310 if (!parseValue(CSSPropertyMarkerStart, important)) | |
311 return false; | |
312 if (m_valueList->current()) { | |
313 rollbackLastProperties(1); | |
314 return false; | |
315 } | |
316 CSSValue* value = m_parsedProperties.last().value(); | |
317 addProperty(CSSPropertyMarkerMid, value, important); | |
318 addProperty(CSSPropertyMarkerEnd, value, important); | |
319 return true; | |
320 } | |
321 default: | |
322 // If you crash here, it's because you added a css property and are not handling it | |
323 // in either this switch statement or the one in CSSPropertyParser::pars eValue | |
324 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); | |
325 return false; | |
326 } | |
327 | |
328 if (validPrimitive) { | |
329 if (id) | |
330 parsedValue = CSSPrimitiveValue::createIdentifier(id); | |
331 else if (value->unit == CSSPrimitiveValue::CSS_STRING) | |
332 parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitive Value::UnitTypes) value->unit); | |
333 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) | |
334 parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitive Value::UnitTypes) value->unit); | |
335 else if (value->unit >= CSSParserValue::Q_EMS) | |
336 parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fV alue, CSSPrimitiveValue::CSS_EMS); | |
337 if (isCalculation(value)) { | |
338 // FIXME calc() http://webkit.org/b/16662 : actually create a CSSPri mitiveValue here, ie | |
339 // parsedValue = CSSPrimitiveValue::create(m_parsedCalculation.relea se()); | |
340 m_parsedCalculation.release(); | |
341 parsedValue = nullptr; | |
342 } | |
343 m_valueList->next(); | |
344 } | |
345 if (!parsedValue || (m_valueList->current() && !inShorthand())) | |
346 return false; | |
347 | |
348 addProperty(propId, parsedValue.release(), important); | |
349 return true; | |
350 } | |
351 | |
352 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGStrokeDasharray() | |
353 { | |
354 RefPtrWillBeRawPtr<CSSValueList> ret = CSSValueList::createCommaSeparated(); | |
355 CSSParserValue* value = m_valueList->current(); | |
356 bool validPrimitive = true; | |
357 while (value) { | |
358 validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, SVGAttri buteMode); | |
359 if (!validPrimitive) | |
360 break; | |
361 if (value->id) | |
362 ret->append(CSSPrimitiveValue::createIdentifier(value->id)); | |
363 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) | |
364 ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveVa lue::UnitTypes) value->unit)); | |
365 value = m_valueList->next(); | |
366 if (value && value->unit == CSSParserValue::Operator && value->iValue == ',') | |
367 value = m_valueList->next(); | |
368 } | |
369 if (!validPrimitive) | |
370 return nullptr; | |
371 return ret.release(); | |
372 } | |
373 | |
374 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGPaint() | |
375 { | |
376 RGBA32 c = Color::transparent; | |
377 if (!parseColorFromValue(m_valueList->current(), c)) | |
378 return SVGPaint::createUnknown(); | |
379 return SVGPaint::createColor(Color(c)); | |
380 } | |
381 | |
382 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGColor() | |
383 { | |
384 RGBA32 c = Color::transparent; | |
385 if (!parseColorFromValue(m_valueList->current(), c)) | |
386 return nullptr; | |
387 return SVGColor::createFromColor(Color(c)); | |
388 } | |
389 | |
390 // normal | [ fill || stroke || markers ] | |
391 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parsePaintOrder() const | |
392 { | |
393 if (m_valueList->size() > 3) | |
394 return nullptr; | |
395 | |
396 CSSParserValue* value = m_valueList->current(); | |
397 if (!value) | |
398 return nullptr; | |
399 | |
400 RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSep arated(); | |
401 | |
402 // The default paint-order is: Fill, Stroke, Markers. | |
403 bool seenFill = false, seenStroke = false, seenMarkers = false; | |
404 | |
405 do { | |
406 switch (value->id) { | |
407 case CSSValueNormal: | |
408 // normal inside [fill || stroke || markers] not valid | |
409 return nullptr; | |
410 case CSSValueFill: | |
411 if (seenFill) | |
412 return nullptr; | |
413 | |
414 seenFill = true; | |
415 break; | |
416 case CSSValueStroke: | |
417 if (seenStroke) | |
418 return nullptr; | |
419 | |
420 seenStroke = true; | |
421 break; | |
422 case CSSValueMarkers: | |
423 if (seenMarkers) | |
424 return nullptr; | |
425 | |
426 seenMarkers = true; | |
427 break; | |
428 default: | |
429 return nullptr; | |
430 } | |
431 | |
432 parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); | |
433 } while ((value = m_valueList->next())); | |
434 | |
435 // fill out the rest of the paint order | |
436 if (!seenFill) | |
437 parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueFill)); | |
438 if (!seenStroke) | |
439 parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke) ); | |
440 if (!seenMarkers) | |
441 parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers )); | |
442 | |
443 return parsedValues.release(); | |
444 } | |
445 | |
51 } // namespace WebCore | 446 } // namespace WebCore |
OLD | NEW |