File indexing completed on 2024-04-28 11:37:28
0001 /* 0002 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 0003 2004, 2005, 2007 Rob Buis <buis@kde.org> 0004 Copyright (C) 2005, 2006 Apple Computer, Inc. 0005 0006 This file is part of the KDE project 0007 0008 This library is free software; you can redistribute it and/or 0009 modify it under the terms of the GNU Library General Public 0010 License as published by the Free Software Foundation; either 0011 version 2 of the License, or (at your option) any later version. 0012 0013 This library is distributed in the hope that it will be useful, 0014 but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 Library General Public License for more details. 0017 0018 You should have received a copy of the GNU Library General Public License 0019 along with this library; see the file COPYING.LIB. If not, write to 0020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 Boston, MA 02110-1301, USA. 0022 */ 0023 0024 #include "cssparser.h" 0025 #include "cssproperties.h" 0026 #include "cssvalues.h" 0027 0028 #include "css/css_valueimpl.h" 0029 #include "css/css_svgvalueimpl.h" 0030 0031 using namespace std; 0032 0033 namespace DOM 0034 { 0035 0036 bool CSSParser::parseSVGValue(int propId, bool important) 0037 { 0038 Value *value = valueList->current(); 0039 if (!value) { 0040 return false; 0041 } 0042 0043 int id = value->id; 0044 0045 bool valid_primitive = false; 0046 CSSValueImpl *parsedValue = nullptr; 0047 0048 switch (propId) { 0049 /* The comment to the right defines all valid value of these 0050 * properties as defined in SVG 1.1, Appendix N. Property index */ 0051 case CSS_PROP_ALIGNMENT_BASELINE: 0052 // auto | baseline | before-edge | text-before-edge | middle | 0053 // central | after-edge | text-after-edge | ideographic | alphabetic | 0054 // hanging | mathematical | inherit 0055 if (id == CSS_VAL_AUTO || id == CSS_VAL_BASELINE || id == CSS_VAL_MIDDLE || 0056 (id >= CSS_VAL_BEFORE_EDGE && id <= CSS_VAL_MATHEMATICAL)) { 0057 valid_primitive = true; 0058 } 0059 break; 0060 0061 case CSS_PROP_BASELINE_SHIFT: 0062 // baseline | super | sub | <percentage> | <length> | inherit 0063 if (id == CSS_VAL_BASELINE || id == CSS_VAL_SUB || id >= CSS_VAL_SUPER) { 0064 valid_primitive = true; 0065 } else { 0066 valid_primitive = validUnit(value, FLength | FPercent, false); 0067 } 0068 break; 0069 0070 case CSS_PROP_DOMINANT_BASELINE: 0071 // auto | use-script | no-change | reset-size | ideographic | 0072 // alphabetic | hanging | mathematical | central | middle | 0073 // text-after-edge | text-before-edge | inherit 0074 if (id == CSS_VAL_AUTO || id == CSS_VAL_MIDDLE || 0075 (id >= CSS_VAL_USE_SCRIPT && id <= CSS_VAL_RESET_SIZE) || 0076 (id >= CSS_VAL_CENTRAL && id <= CSS_VAL_MATHEMATICAL)) { 0077 valid_primitive = true; 0078 } 0079 break; 0080 0081 case CSS_PROP_ENABLE_BACKGROUND: 0082 // accumulate | new [x] [y] [width] [height] | inherit 0083 if (id == CSS_VAL_ACCUMULATE) { // ### TODO: new 0084 valid_primitive = true; 0085 } 0086 break; 0087 0088 case CSS_PROP_MARKER_START: 0089 case CSS_PROP_MARKER_MID: 0090 case CSS_PROP_MARKER_END: 0091 case CSS_PROP_MASK: 0092 if (id == CSS_VAL_NONE) { 0093 valid_primitive = true; 0094 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { 0095 parsedValue = new CSSPrimitiveValueImpl(domString(value->string), CSSPrimitiveValue::CSS_URI); 0096 if (parsedValue) { 0097 valueList->next(); 0098 } 0099 } 0100 break; 0101 0102 case CSS_PROP_CLIP_RULE: // nonzero | evenodd | inherit 0103 case CSS_PROP_FILL_RULE: 0104 if (id == CSS_VAL_NONZERO || id == CSS_VAL_EVENODD) { 0105 valid_primitive = true; 0106 } 0107 break; 0108 0109 case CSS_PROP_STROKE_MITERLIMIT: // <miterlimit> | inherit 0110 valid_primitive = validUnit(value, FNumber | FNonNeg, false); 0111 break; 0112 0113 case CSS_PROP_STROKE_LINEJOIN: // miter | round | bevel | inherit 0114 if (id == CSS_VAL_MITER || id == CSS_VAL_ROUND || id == CSS_VAL_BEVEL) { 0115 valid_primitive = true; 0116 } 0117 break; 0118 0119 case CSS_PROP_STROKE_LINECAP: // butt | round | square | inherit 0120 if (id == CSS_VAL_BUTT || id == CSS_VAL_ROUND || id == CSS_VAL_SQUARE) { 0121 valid_primitive = true; 0122 } 0123 break; 0124 0125 case CSS_PROP_STROKE_OPACITY: // <opacity-value> | inherit 0126 case CSS_PROP_FILL_OPACITY: 0127 case CSS_PROP_STOP_OPACITY: 0128 case CSS_PROP_FLOOD_OPACITY: 0129 valid_primitive = (!id && validUnit(value, FNumber | FPercent, false)); 0130 break; 0131 0132 case CSS_PROP_SHAPE_RENDERING: 0133 // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit 0134 if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || 0135 id == CSS_VAL_CRISPEDGES || id == CSS_VAL_GEOMETRICPRECISION) { 0136 valid_primitive = true; 0137 } 0138 break; 0139 0140 case CSS_PROP_TEXT_RENDERING: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit 0141 if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || id == CSS_VAL_OPTIMIZELEGIBILITY || 0142 id == CSS_VAL_GEOMETRICPRECISION) { 0143 valid_primitive = true; 0144 } 0145 break; 0146 0147 case CSS_PROP_IMAGE_RENDERING: // auto | optimizeSpeed | 0148 case CSS_PROP_COLOR_RENDERING: // optimizeQuality | inherit 0149 if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || 0150 id == CSS_VAL_OPTIMIZEQUALITY) { 0151 valid_primitive = true; 0152 } 0153 break; 0154 0155 case CSS_PROP_COLOR_PROFILE: // auto | sRGB | <name> | <uri> inherit 0156 if (id == CSS_VAL_AUTO || id == CSS_VAL_SRGB) { 0157 valid_primitive = true; 0158 } 0159 break; 0160 0161 case CSS_PROP_COLOR_INTERPOLATION: // auto | sRGB | linearRGB | inherit 0162 case CSS_PROP_COLOR_INTERPOLATION_FILTERS: 0163 if (id == CSS_VAL_AUTO || id == CSS_VAL_SRGB || id == CSS_VAL_LINEARRGB) { 0164 valid_primitive = true; 0165 } 0166 break; 0167 0168 case CSS_PROP_POINTER_EVENTS: 0169 // visiblePainted | visibleFill | visibleStroke | visible | 0170 // painted | fill | stroke | all | none | inherit 0171 if (id == CSS_VAL_VISIBLE || id == CSS_VAL_NONE || 0172 (id >= CSS_VAL_VISIBLEPAINTED && id <= CSS_VAL_ALL)) { 0173 valid_primitive = true; 0174 } 0175 break; 0176 0177 case CSS_PROP_TEXT_ANCHOR: // start | middle | end | inherit 0178 if (id == CSS_VAL_START || id == CSS_VAL_MIDDLE || id == CSS_VAL_END) { 0179 valid_primitive = true; 0180 } 0181 break; 0182 0183 case CSS_PROP_GLYPH_ORIENTATION_VERTICAL: // auto | <angle> | inherit 0184 if (id == CSS_VAL_AUTO) { 0185 valid_primitive = true; 0186 break; 0187 } 0188 /* fallthrough intentional */ 0189 case CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit 0190 if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) { 0191 parsedValue = new CSSPrimitiveValueImpl(value->fValue, CSSPrimitiveValue::CSS_DEG); 0192 0193 if (parsedValue) { 0194 valueList->next(); 0195 } 0196 } 0197 break; 0198 0199 case CSS_PROP_FILL: // <paint> | inherit 0200 case CSS_PROP_STROKE: { // <paint> | inherit 0201 if (id == CSS_VAL_NONE) { 0202 parsedValue = new SVGPaintImpl(SVGPaintImpl::SVG_PAINTTYPE_NONE); 0203 } else if (id == CSS_VAL_CURRENTCOLOR) { 0204 parsedValue = new SVGPaintImpl(SVGPaintImpl::SVG_PAINTTYPE_CURRENTCOLOR); 0205 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { 0206 CSSPrimitiveValueImpl *val; 0207 if (valueList->next() && (val = parseColorFromValue(valueList->current()/*, c, true*/))) { 0208 parsedValue = new SVGPaintImpl(domString(value->string), val->getRGBColorValue()); 0209 delete val; 0210 } else { 0211 parsedValue = new SVGPaintImpl(SVGPaintImpl::SVG_PAINTTYPE_URI, domString(value->string)); 0212 } 0213 } else { 0214 parsedValue = parseSVGPaint(); 0215 } 0216 0217 if (parsedValue) { 0218 valueList->next(); 0219 } 0220 } 0221 break; 0222 0223 /*case CSS_PROP_Color: // <color> | inherit 0224 if ((id >= CSS_VAL_Aqua && id <= CSS_VAL_Windowtext) || 0225 (id >= CSS_VAL_Aliceblue && id <= CSS_VAL_Yellowgreen)) 0226 parsedValue = new SVGColor(value->string); 0227 else 0228 parsedValue = parseSVGColor(); 0229 0230 if (parsedValue) 0231 valueList->next(); 0232 break;*/ 0233 0234 case CSS_PROP_STOP_COLOR: // TODO : icccolor 0235 case CSS_PROP_FLOOD_COLOR: 0236 case CSS_PROP_LIGHTING_COLOR: 0237 if ((id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT)/* || 0238 (id >= CSS_VAL_Aliceblue && id <= CSS_VAL_Yellowgreen)*/) { 0239 parsedValue = new SVGColorImpl(domString(value->string)); 0240 } else if (id == CSS_VAL_CURRENTCOLOR) { 0241 parsedValue = new SVGColorImpl(SVGColorImpl::SVG_COLORTYPE_CURRENTCOLOR); 0242 } else { // TODO : svgcolor (iccColor) 0243 parsedValue = parseSVGColor(); 0244 } 0245 0246 if (parsedValue) { 0247 valueList->next(); 0248 } 0249 0250 break; 0251 0252 case CSS_PROP_WRITING_MODE: 0253 // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit 0254 if (id >= CSS_VAL_LR_TB && id <= CSS_VAL_TB) { 0255 valid_primitive = true; 0256 } 0257 break; 0258 0259 case CSS_PROP_STROKE_WIDTH: // <length> | inherit 0260 case CSS_PROP_STROKE_DASHOFFSET: 0261 valid_primitive = validUnit(value, FLength | FPercent, false); 0262 break; 0263 0264 case CSS_PROP_STROKE_DASHARRAY: // none | <dasharray> | inherit 0265 if (id == CSS_VAL_NONE) { 0266 valid_primitive = true; 0267 } else { 0268 parsedValue = parseSVGStrokeDasharray(); 0269 } 0270 0271 break; 0272 0273 case CSS_PROP_KERNING: // auto | normal | <length> | inherit 0274 if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL) { 0275 valid_primitive = true; 0276 } else { 0277 valid_primitive = validUnit(value, FLength, false); 0278 } 0279 break; 0280 0281 case CSS_PROP_CLIP_PATH: // <uri> | none | inherit 0282 case CSS_PROP_FILTER: 0283 if (id == CSS_VAL_NONE) { 0284 valid_primitive = true; 0285 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { 0286 parsedValue = new CSSPrimitiveValueImpl(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit); 0287 if (parsedValue) { 0288 valueList->next(); 0289 } 0290 } 0291 break; 0292 0293 /* shorthand properties */ 0294 case CSS_PROP_MARKER: { 0295 const int properties[3] = { CSS_PROP_MARKER_START, CSS_PROP_MARKER_MID, 0296 CSS_PROP_MARKER_END 0297 }; 0298 return parseShortHand(propId, properties, 3, important); 0299 0300 } 0301 default: 0302 // If you crash here, it's because you added a css property and are not handling it 0303 // in either this switch statement or the one in CSSParser::parseValue 0304 //ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); 0305 //return false; 0306 break; 0307 } 0308 0309 if (valid_primitive) { 0310 if (id != 0) { 0311 parsedValue = new CSSPrimitiveValueImpl(id); 0312 } else if (value->unit == CSSPrimitiveValue::CSS_STRING) { 0313 parsedValue = new CSSPrimitiveValueImpl(domString(value->string), (CSSPrimitiveValue::UnitTypes)value->unit); 0314 } else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) { 0315 parsedValue = new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); 0316 } else if (value->unit >= Value::Q_EMS) { 0317 parsedValue = new CSSQuirkPrimitiveValueImpl(value->fValue, CSSPrimitiveValue::CSS_EMS); 0318 } 0319 valueList->next(); 0320 } 0321 if (!parsedValue || (valueList->current() && !inShorthand())) { 0322 delete parsedValue; 0323 return false; 0324 } 0325 0326 addProperty(propId, parsedValue, important); 0327 return true; 0328 } 0329 0330 CSSValueImpl *CSSParser::parseSVGStrokeDasharray() 0331 { 0332 CSSValueListImpl *ret = new CSSValueListImpl(CSSValueListImpl::Comma); 0333 Value *value = valueList->current(); 0334 bool valid_primitive = true; 0335 while (value) { 0336 valid_primitive = validUnit(value, FLength | FPercent | FNonNeg, false); 0337 if (!valid_primitive) { 0338 break; 0339 } 0340 if (value->id != 0) { 0341 ret->append(new CSSPrimitiveValueImpl(value->id)); 0342 } else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) { 0343 ret->append(new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit)); 0344 } 0345 value = valueList->next(); 0346 if (value && value->unit == Value::Operator && value->iValue == ',') { 0347 value = valueList->next(); 0348 } 0349 } 0350 if (!valid_primitive) { 0351 delete ret; 0352 ret = nullptr; 0353 } 0354 0355 return ret; 0356 } 0357 0358 CSSValueImpl *CSSParser::parseSVGPaint() 0359 { 0360 CSSPrimitiveValueImpl *val; 0361 0362 if (!(val = parseColorFromValue(valueList->current()/*, c, true*/))) { 0363 return new SVGPaintImpl(); 0364 } 0365 0366 SVGPaintImpl *paint = new SVGPaintImpl(QColor(val->getRGBColorValue())); 0367 delete val; 0368 return paint; 0369 } 0370 0371 CSSValueImpl *CSSParser::parseSVGColor() 0372 { 0373 CSSPrimitiveValueImpl *val; 0374 if (!(val = parseColorFromValue(valueList->current()/*, c, true*/))) { 0375 return nullptr; 0376 } 0377 SVGColorImpl *color = new SVGColorImpl(QColor(val->getRGBColorValue())); 0378 delete val; 0379 return color; 0380 } 0381 0382 } 0383