2 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005, 2007 Rob Buis <buis@kde.org>
4 Copyright (C) 2005, 2006 Apple Computer, Inc.
6 This file is part of the KDE project
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
24 #include "cssparser.h"
25 #include "cssproperties.h"
26 #include "cssvalues.h"
29 /*#include "CSSInheritedValue.h"
30 #include "CSSInitialValue.h"
31 #include "CSSParser.h"
32 #include "CSSProperty.h"
33 #include "CSSPropertyNames.h"
34 #include "CSSQuirkPrimitiveValue.h"
35 #include "CSSValueKeywords.h"
36 #include "CSSValueList.h"*/
37 #include "wtf/Platform.h"
41 using WebCore::SVGPaint
;
42 using WebCore::SVGColor
;
48 bool CSSParser::parseSVGValue(int propId
, bool important
)
50 Value
* value
= valueList
->current();
56 bool valid_primitive
= false;
57 CSSValueImpl
*parsedValue
= 0;
60 /* The comment to the right defines all valid value of these
61 * properties as defined in SVG 1.1, Appendix N. Property index */
62 /*case CSSPropertyAlignmentBaseline:
63 // auto | baseline | before-edge | text-before-edge | middle |
64 // central | after-edge | text-after-edge | ideographic | alphabetic |
65 // hanging | mathematical | inherit
66 if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle ||
67 (id >= CSSValueBeforeEdge && id <= CSSValueMathematical))
68 valid_primitive = true;
71 case CSSPropertyBaselineShift:
72 // baseline | super | sub | <percentage> | <length> | inherit
73 if (id == CSSValueBaseline || id == CSSValueSub ||
75 valid_primitive = true;
77 valid_primitive = validUnit(value, FLength|FPercent, false);
80 case CSSPropertyDominantBaseline:
81 // auto | use-script | no-change | reset-size | ideographic |
82 // alphabetic | hanging | mathematical | central | middle |
83 // text-after-edge | text-before-edge | inherit
84 if (id == CSSValueAuto || id == CSSValueMiddle ||
85 (id >= CSSValueUseScript && id <= CSSValueResetSize) ||
86 (id >= CSSValueCentral && id <= CSSValueMathematical))
87 valid_primitive = true;
90 case CSSPropertyEnableBackground:
91 // accumulate | new [x] [y] [width] [height] | inherit
92 if (id == CSSValueAccumulate) // TODO : new
93 valid_primitive = true;
96 case CSSPropertyMarkerStart:
97 case CSSPropertyMarkerMid:
98 case CSSPropertyMarkerEnd:
100 if (id == CSSValueNone)
101 valid_primitive = true;
102 else if (value->unit == CSSPrimitiveValue::CSS_URI) {
103 parsedValue = new CSSPrimitiveValue(value->string, CSSPrimitiveValue::CSS_URI);
109 case CSS_PROP_CLIP_RULE
: // nonzero | evenodd | inherit
110 case CSS_PROP_FILL_RULE
:
111 if (id
== CSS_VAL_NONZERO
|| id
== CSS_VAL_EVENODD
)
112 valid_primitive
= true;
115 /*case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit
116 valid_primitive = validUnit(value, FNumber|FNonNeg, false);
119 case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit
120 if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel)
121 valid_primitive = true;
124 case CSSPropertyStrokeLinecap: // butt | round | square | inherit
125 if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare)
126 valid_primitive = true;
129 case CSS_PROP_STROKE_OPACITY
: // <opacity-value> | inherit
130 case CSS_PROP_FILL_OPACITY
:
131 case CSS_PROP_STOP_OPACITY
:
132 //case CSSPropertyFloodOpacity:
133 valid_primitive
= (!id
&& validUnit(value
, FNumber
|FPercent
, false));
136 /*case CSSPropertyShapeRendering:
137 // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit
138 if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
139 id == CSSValueCrispedges || id == CSSValueGeometricprecision)
140 valid_primitive = true;
143 case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit
144 if (id == CSSValueAuto || id == CSSValueOptimizespeed || id == CSSValueOptimizelegibility ||
145 id == CSSValueGeometricprecision)
146 valid_primitive = true;
149 case CSSPropertyImageRendering: // auto | optimizeSpeed |
150 case CSSPropertyColorRendering: // optimizeQuality | inherit
151 if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
152 id == CSSValueOptimizequality)
153 valid_primitive = true;
156 case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit
157 if (id == CSSValueAuto || id == CSSValueSrgb)
158 valid_primitive = true;
161 case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit
162 case CSSPropertyColorInterpolationFilters:
163 if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb)
164 valid_primitive = true;
167 /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
168 * correctly and allows optimization in applyRule(..)
171 /*case CSSPropertyPointerEvents:
172 // none | visiblePainted | visibleFill | visibleStroke | visible |
173 // painted | fill | stroke | none | all | inherit
174 if (id == CSSValueVisible || id == CSSValueNone ||
175 (id >= CSSValueVisiblepainted && id <= CSSValueAll))
176 valid_primitive = true;
179 case CSSPropertyTextAnchor: // start | middle | end | inherit
180 if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd)
181 valid_primitive = true;
184 case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit
185 if (id == CSSValueAuto) {
186 valid_primitive = true;
189 /* fallthrough intentional */
190 /*case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit
191 if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) {
192 parsedValue = new CSSPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_DEG);
199 case CSS_PROP_FILL
: // <paint> | inherit
200 case CSS_PROP_STROKE
: // <paint> | inherit
202 if (id
== CSS_VAL_NONE
)
203 parsedValue
= new SVGPaint(SVGPaint::SVG_PAINTTYPE_NONE
);
204 else /*if (id == CSSValueCurrentcolor)
205 parsedValue = new SVGPaint(SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR);
206 else */if (value
->unit
== CSSPrimitiveValue::CSS_URI
) {
207 CSSPrimitiveValueImpl
* val
;
208 // khtml FIXME memory leak here
209 if (valueList
->next() && (val
= parseColorFromValue(valueList
->current()/*, c, true*/))) {
210 parsedValue
= new SVGPaint(domString(value
->string
), val
->getRGBColorValue());
212 parsedValue
= new SVGPaint(SVGPaint::SVG_PAINTTYPE_URI
, domString(value
->string
));
214 parsedValue
= parseSVGPaint();
221 /*case CSSPropertyColor: // <color> | inherit
222 if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
223 (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
224 parsedValue = new SVGColor(value->string);
226 parsedValue = parseSVGColor();
232 case CSS_PROP_STOP_COLOR
: // TODO : icccolor
233 //case CSSPropertyFloodColor:
234 //case CSSPropertyLightingColor:
235 if ((id
>= CSS_VAL_AQUA
&& id
<= CSS_VAL_WINDOWTEXT
)/* ||
236 (id >= CSSValueAliceblue && id <= CSSValueYellowgreen)*/)
237 parsedValue
= new SVGColor(domString(value
->string
));
238 else /*if (id == CSSValueCurrentcolor)
239 parsedValue = new SVGColor(SVGColor::SVG_COLORTYPE_CURRENTCOLOR);
240 else*/ // TODO : svgcolor (iccColor)
241 parsedValue
= parseSVGColor();
248 /*case CSSPropertyWritingMode:
249 // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
250 if (id >= CSSValueLrTb && id <= CSSValueTb)
251 valid_primitive = true;
254 case CSS_PROP_STROKE_WIDTH
: // <length> | inherit
255 //case CSSPropertyStrokeDashoffset:
256 valid_primitive
= validUnit(value
, FLength
| FPercent
, false);
258 /*case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit
259 if (id == CSSValueNone)
260 valid_primitive = true;
262 parsedValue = parseSVGStrokeDasharray();
266 case CSSPropertyKerning: // auto | normal | <length> | inherit
267 if (id == CSSValueAuto || id == CSSValueNormal)
268 valid_primitive = true;
270 valid_primitive = validUnit(value, FLength, false);
273 case CSS_PROP_CLIP_PATH
: // <uri> | none | inherit
274 //case CSSPropertyFilter:
275 if (id
== CSS_VAL_NONE
)
276 valid_primitive
= true;
277 else if (value
->unit
== CSSPrimitiveValue::CSS_URI
) {
278 parsedValue
= new CSSPrimitiveValueImpl(domString(value
->string
), (CSSPrimitiveValue::UnitTypes
) value
->unit
);
284 /* shorthand properties */
285 /*case CSSPropertyMarker:
287 ShorthandScope scope(this, propId);
288 m_implicitShorthand = true;
289 if (!parseValue(CSSPropertyMarkerStart, important))
291 if (valueList->current()) {
292 rollbackLastProperties(1);
295 CSSValue *value = parsedProperties[numParsedProperties - 1]->value();
296 addProperty(CSSPropertyMarkerMid, value, important);
297 addProperty(CSSPropertyMarkerEnd, value, important);
298 m_implicitShorthand = false;
302 // If you crash here, it's because you added a css property and are not handling it
303 // in either this switch statement or the one in CSSParser::parseValue
304 //ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId);
309 if (valid_primitive
) {
311 parsedValue
= new CSSPrimitiveValueImpl(id
);
312 else if (value
->unit
== CSSPrimitiveValue::CSS_STRING
)
313 parsedValue
= new CSSPrimitiveValueImpl(domString(value
->string
), (CSSPrimitiveValue::UnitTypes
)value
->unit
);
314 else if (value
->unit
>= CSSPrimitiveValue::CSS_NUMBER
&& value
->unit
<= CSSPrimitiveValue::CSS_KHZ
)
315 parsedValue
= new CSSPrimitiveValueImpl(value
->fValue
, (CSSPrimitiveValue::UnitTypes
)value
->unit
);
316 else if (value
->unit
>= Value::Q_EMS
)
317 parsedValue
= new CSSQuirkPrimitiveValueImpl(value
->fValue
, CSSPrimitiveValue::CSS_EMS
);
320 if (!parsedValue
|| (valueList
->current() && !inShorthand())) {
322 delete parsedValue
; // khtml: we should delete here, right?
326 addProperty(propId
, parsedValue
, important
);
330 PassRefPtr
<CSSValue
> CSSParser::parseSVGStrokeDasharray()
332 CSSValueList
* ret
= new CSSValueList
;
333 Value
* value
= valueList
->current();
334 bool valid_primitive
= true;
336 valid_primitive
= validUnit(value
, FLength
| FPercent
|FNonNeg
, false);
337 if (!valid_primitive
)
340 ret
->append(new CSSPrimitiveValue(value
->id
));
341 else if (value
->unit
>= CSSPrimitiveValue::CSS_NUMBER
&& value
->unit
<= CSSPrimitiveValue::CSS_KHZ
)
342 ret
->append(new CSSPrimitiveValue(value
->fValue
, (CSSPrimitiveValue::UnitTypes
) value
->unit
));
343 value
= valueList
->next();
344 if (value
&& value
->unit
== Value::Operator
&& value
->iValue
== ',')
345 value
= valueList
->next();
347 if (!valid_primitive
) {
355 CSSValueImpl
* CSSParser::parseSVGPaint()
357 CSSPrimitiveValueImpl
* val
;
358 if (!(val
= parseColorFromValue(valueList
->current()/*, c, true*/)))
359 return new SVGPaint();
360 // khtml FIXME memory leak
361 return new SVGPaint(QColor(val
->getRGBColorValue()));
364 CSSValueImpl
* CSSParser::parseSVGColor()
366 CSSPrimitiveValueImpl
* val
;
367 if (!(val
= parseColorFromValue(valueList
->current()/*, c, true*/)))
369 // khtml FIXME memory leak
370 return new SVGColor(Color(val
->getRGBColorValue()));