1 /* 2 Copyright (C) 2005 Apple Computer, Inc. 3 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 4 2004, 2005, 2008 Rob Buis <buis (at) kde.org> 5 Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 6 7 Based on khtml css code by: 8 Copyright(C) 1999-2003 Lars Knoll(knoll (at) kde.org) 9 (C) 2003 Apple Computer, Inc. 10 (C) 2004 Allan Sandfeld Jensen(kde (at) carewolf.com) 11 (C) 2004 Germain Garand(germain (at) ebooksfrance.org) 12 13 This library is free software; you can redistribute it and/or 14 modify it under the terms of the GNU Library General Public 15 License as published by the Free Software Foundation; either 16 version 2 of the License, or (at your option) any later version. 17 18 This library is distributed in the hope that it will be useful, 19 but WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 Library General Public License for more details. 22 23 You should have received a copy of the GNU Library General Public License 24 along with this library; see the file COPYING.LIB. If not, write to 25 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 26 Boston, MA 02110-1301, USA. 27 */ 28 29 #include "config.h" 30 31 #if ENABLE(SVG) 32 #include "CSSStyleSelector.h" 33 34 #include "CSSPrimitiveValueMappings.h" 35 #include "CSSPropertyNames.h" 36 #include "CSSValueList.h" 37 #include "Document.h" 38 #include "ShadowValue.h" 39 #include "SVGColor.h" 40 #include "SVGNames.h" 41 #include "SVGPaint.h" 42 #include "SVGRenderStyle.h" 43 #include "SVGRenderStyleDefs.h" 44 #include "SVGStyledElement.h" 45 #include "SVGURIReference.h" 46 #include <stdlib.h> 47 #include <wtf/MathExtras.h> 48 49 #define HANDLE_INHERIT(prop, Prop) \ 50 if (isInherit) \ 51 {\ 52 svgstyle->set##Prop(m_parentStyle->svgStyle()->prop());\ 53 return;\ 54 } 55 56 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ 57 HANDLE_INHERIT(prop, Prop) \ 58 else if (isInitial) \ 59 svgstyle->set##Prop(SVGRenderStyle::initial##Prop()); 60 61 62 namespace WebCore { 63 64 static float roundToNearestGlyphOrientationAngle(float angle) 65 { 66 angle = fabsf(fmodf(angle, 360.0f)); 67 68 if (angle <= 45.0f || angle > 315.0f) 69 return 0.0f; 70 else if (angle > 45.0f && angle <= 135.0f) 71 return 90.0f; 72 else if (angle > 135.0f && angle <= 225.0f) 73 return 180.0f; 74 75 return 270.0f; 76 } 77 78 static int angleToGlyphOrientation(float angle) 79 { 80 angle = roundToNearestGlyphOrientationAngle(angle); 81 82 if (angle == 0.0f) 83 return GO_0DEG; 84 else if (angle == 90.0f) 85 return GO_90DEG; 86 else if (angle == 180.0f) 87 return GO_180DEG; 88 else if (angle == 270.0f) 89 return GO_270DEG; 90 91 return -1; 92 } 93 94 static Color colorFromSVGColorCSSValue(CSSValue* value, RenderStyle* style) 95 { 96 ASSERT(value->isSVGColor()); 97 SVGColor* c = static_cast<SVGColor*>(value); 98 Color color; 99 if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR) 100 color = style->color(); 101 else 102 color = c->color(); 103 return color; 104 } 105 106 void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) 107 { 108 ASSERT(value); 109 CSSPrimitiveValue* primitiveValue = 0; 110 if (value->isPrimitiveValue()) 111 primitiveValue = static_cast<CSSPrimitiveValue*>(value); 112 113 SVGRenderStyle* svgstyle = m_style->accessSVGStyle(); 114 unsigned short valueType = value->cssValueType(); 115 116 bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT; 117 bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT); 118 119 // What follows is a list that maps the CSS properties into their 120 // corresponding front-end RenderStyle values. Shorthands(e.g. border, 121 // background) occur in this list as well and are only hit when mapping 122 // "inherit" or "initial" into front-end values. 123 switch (id) 124 { 125 // ident only properties 126 case CSSPropertyAlignmentBaseline: 127 { 128 HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline) 129 if (!primitiveValue) 130 break; 131 132 svgstyle->setAlignmentBaseline(*primitiveValue); 133 break; 134 } 135 case CSSPropertyBaselineShift: 136 { 137 HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift); 138 if (!primitiveValue) 139 break; 140 141 if (primitiveValue->getIdent()) { 142 switch (primitiveValue->getIdent()) { 143 case CSSValueBaseline: 144 svgstyle->setBaselineShift(BS_BASELINE); 145 break; 146 case CSSValueSub: 147 svgstyle->setBaselineShift(BS_SUB); 148 break; 149 case CSSValueSuper: 150 svgstyle->setBaselineShift(BS_SUPER); 151 break; 152 default: 153 break; 154 } 155 } else { 156 svgstyle->setBaselineShift(BS_LENGTH); 157 svgstyle->setBaselineShiftValue(primitiveValue); 158 } 159 160 break; 161 } 162 case CSSPropertyKerning: 163 { 164 HANDLE_INHERIT_AND_INITIAL(kerning, Kerning); 165 svgstyle->setKerning(primitiveValue); 166 break; 167 } 168 case CSSPropertyDominantBaseline: 169 { 170 HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline) 171 if (primitiveValue) 172 svgstyle->setDominantBaseline(*primitiveValue); 173 break; 174 } 175 case CSSPropertyColorInterpolation: 176 { 177 HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation) 178 if (primitiveValue) 179 svgstyle->setColorInterpolation(*primitiveValue); 180 break; 181 } 182 case CSSPropertyColorInterpolationFilters: 183 { 184 HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters) 185 if (primitiveValue) 186 svgstyle->setColorInterpolationFilters(*primitiveValue); 187 break; 188 } 189 case CSSPropertyColorRendering: 190 { 191 HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering) 192 if (primitiveValue) 193 svgstyle->setColorRendering(*primitiveValue); 194 break; 195 } 196 case CSSPropertyClipRule: 197 { 198 HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule) 199 if (primitiveValue) 200 svgstyle->setClipRule(*primitiveValue); 201 break; 202 } 203 case CSSPropertyFillRule: 204 { 205 HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule) 206 if (primitiveValue) 207 svgstyle->setFillRule(*primitiveValue); 208 break; 209 } 210 case CSSPropertyStrokeLinejoin: 211 { 212 HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle) 213 if (primitiveValue) 214 svgstyle->setJoinStyle(*primitiveValue); 215 break; 216 } 217 case CSSPropertyImageRendering: 218 { 219 HANDLE_INHERIT_AND_INITIAL(imageRendering, ImageRendering) 220 if (primitiveValue) 221 svgstyle->setImageRendering(*primitiveValue); 222 break; 223 } 224 case CSSPropertyShapeRendering: 225 { 226 HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering) 227 if (primitiveValue) 228 svgstyle->setShapeRendering(*primitiveValue); 229 break; 230 } 231 // end of ident only properties 232 case CSSPropertyFill: 233 { 234 HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint) 235 if (value->isSVGPaint()) 236 svgstyle->setFillPaint(static_cast<SVGPaint*>(value)); 237 break; 238 } 239 case CSSPropertyStroke: 240 { 241 HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint) 242 if (value->isSVGPaint()) 243 svgstyle->setStrokePaint(static_cast<SVGPaint*>(value)); 244 245 break; 246 } 247 case CSSPropertyStrokeWidth: 248 { 249 HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth) 250 if (primitiveValue) 251 svgstyle->setStrokeWidth(primitiveValue); 252 break; 253 } 254 case CSSPropertyStrokeDasharray: 255 { 256 HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray) 257 if (value->isValueList()) 258 svgstyle->setStrokeDashArray(static_cast<CSSValueList*>(value)); 259 break; 260 } 261 case CSSPropertyStrokeDashoffset: 262 { 263 HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset) 264 if (primitiveValue) 265 svgstyle->setStrokeDashOffset(primitiveValue); 266 break; 267 } 268 case CSSPropertyFillOpacity: 269 { 270 HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity) 271 if (!primitiveValue) 272 return; 273 274 float f = 0.0f; 275 int type = primitiveValue->primitiveType(); 276 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 277 f = primitiveValue->getFloatValue() / 100.0f; 278 else if (type == CSSPrimitiveValue::CSS_NUMBER) 279 f = primitiveValue->getFloatValue(); 280 else 281 return; 282 283 svgstyle->setFillOpacity(f); 284 break; 285 } 286 case CSSPropertyStrokeOpacity: 287 { 288 HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity) 289 if (!primitiveValue) 290 return; 291 292 float f = 0.0f; 293 int type = primitiveValue->primitiveType(); 294 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 295 f = primitiveValue->getFloatValue() / 100.0f; 296 else if (type == CSSPrimitiveValue::CSS_NUMBER) 297 f = primitiveValue->getFloatValue(); 298 else 299 return; 300 301 svgstyle->setStrokeOpacity(f); 302 break; 303 } 304 case CSSPropertyStopOpacity: 305 { 306 HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity) 307 if (!primitiveValue) 308 return; 309 310 float f = 0.0f; 311 int type = primitiveValue->primitiveType(); 312 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 313 f = primitiveValue->getFloatValue() / 100.0f; 314 else if (type == CSSPrimitiveValue::CSS_NUMBER) 315 f = primitiveValue->getFloatValue(); 316 else 317 return; 318 319 svgstyle->setStopOpacity(f); 320 break; 321 } 322 case CSSPropertyMarkerStart: 323 { 324 HANDLE_INHERIT_AND_INITIAL(startMarker, StartMarker) 325 if (!primitiveValue) 326 return; 327 328 String s; 329 int type = primitiveValue->primitiveType(); 330 if (type == CSSPrimitiveValue::CSS_URI) 331 s = primitiveValue->getStringValue(); 332 else 333 return; 334 335 svgstyle->setStartMarker(SVGURIReference::getTarget(s)); 336 break; 337 } 338 case CSSPropertyMarkerMid: 339 { 340 HANDLE_INHERIT_AND_INITIAL(midMarker, MidMarker) 341 if (!primitiveValue) 342 return; 343 344 String s; 345 int type = primitiveValue->primitiveType(); 346 if (type == CSSPrimitiveValue::CSS_URI) 347 s = primitiveValue->getStringValue(); 348 else 349 return; 350 351 svgstyle->setMidMarker(SVGURIReference::getTarget(s)); 352 break; 353 } 354 case CSSPropertyMarkerEnd: 355 { 356 HANDLE_INHERIT_AND_INITIAL(endMarker, EndMarker) 357 if (!primitiveValue) 358 return; 359 360 String s; 361 int type = primitiveValue->primitiveType(); 362 if (type == CSSPrimitiveValue::CSS_URI) 363 s = primitiveValue->getStringValue(); 364 else 365 return; 366 367 svgstyle->setEndMarker(SVGURIReference::getTarget(s)); 368 break; 369 } 370 case CSSPropertyStrokeLinecap: 371 { 372 HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle) 373 if (primitiveValue) 374 svgstyle->setCapStyle(*primitiveValue); 375 break; 376 } 377 case CSSPropertyStrokeMiterlimit: 378 { 379 HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit) 380 if (!primitiveValue) 381 return; 382 383 float f = 0.0f; 384 int type = primitiveValue->primitiveType(); 385 if (type == CSSPrimitiveValue::CSS_NUMBER) 386 f = primitiveValue->getFloatValue(); 387 else 388 return; 389 390 svgstyle->setStrokeMiterLimit(f); 391 break; 392 } 393 case CSSPropertyFilter: 394 { 395 HANDLE_INHERIT_AND_INITIAL(filter, Filter) 396 if (!primitiveValue) 397 return; 398 399 String s; 400 int type = primitiveValue->primitiveType(); 401 if (type == CSSPrimitiveValue::CSS_URI) 402 s = primitiveValue->getStringValue(); 403 else 404 return; 405 svgstyle->setFilter(SVGURIReference::getTarget(s)); 406 break; 407 } 408 case CSSPropertyMask: 409 { 410 HANDLE_INHERIT_AND_INITIAL(maskElement, MaskElement) 411 if (!primitiveValue) 412 return; 413 414 String s; 415 int type = primitiveValue->primitiveType(); 416 if (type == CSSPrimitiveValue::CSS_URI) 417 s = primitiveValue->getStringValue(); 418 else 419 return; 420 421 svgstyle->setMaskElement(SVGURIReference::getTarget(s)); 422 break; 423 } 424 case CSSPropertyClipPath: 425 { 426 HANDLE_INHERIT_AND_INITIAL(clipPath, ClipPath) 427 if (!primitiveValue) 428 return; 429 430 String s; 431 int type = primitiveValue->primitiveType(); 432 if (type == CSSPrimitiveValue::CSS_URI) 433 s = primitiveValue->getStringValue(); 434 else 435 return; 436 437 svgstyle->setClipPath(SVGURIReference::getTarget(s)); 438 break; 439 } 440 case CSSPropertyTextAnchor: 441 { 442 HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor) 443 if (primitiveValue) 444 svgstyle->setTextAnchor(*primitiveValue); 445 break; 446 } 447 case CSSPropertyWritingMode: 448 { 449 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode) 450 if (primitiveValue) 451 svgstyle->setWritingMode(*primitiveValue); 452 break; 453 } 454 case CSSPropertyStopColor: 455 { 456 HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor); 457 svgstyle->setStopColor(colorFromSVGColorCSSValue(value, m_style.get())); 458 break; 459 } 460 case CSSPropertyLightingColor: 461 { 462 HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor); 463 svgstyle->setLightingColor(colorFromSVGColorCSSValue(value, m_style.get())); 464 break; 465 } 466 case CSSPropertyFloodOpacity: 467 { 468 HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity) 469 if (!primitiveValue) 470 return; 471 472 float f = 0.0f; 473 int type = primitiveValue->primitiveType(); 474 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 475 f = primitiveValue->getFloatValue() / 100.0f; 476 else if (type == CSSPrimitiveValue::CSS_NUMBER) 477 f = primitiveValue->getFloatValue(); 478 else 479 return; 480 481 svgstyle->setFloodOpacity(f); 482 break; 483 } 484 case CSSPropertyFloodColor: 485 { 486 if (isInitial) { 487 svgstyle->setFloodColor(SVGRenderStyle::initialFloodColor()); 488 return; 489 } 490 svgstyle->setFloodColor(colorFromSVGColorCSSValue(value, m_style.get())); 491 break; 492 } 493 case CSSPropertyGlyphOrientationHorizontal: 494 { 495 HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal) 496 if (!primitiveValue) 497 return; 498 499 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) { 500 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue()); 501 ASSERT(orientation != -1); 502 503 svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation); 504 } 505 506 break; 507 } 508 case CSSPropertyGlyphOrientationVertical: 509 { 510 HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical) 511 if (!primitiveValue) 512 return; 513 514 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) { 515 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue()); 516 ASSERT(orientation != -1); 517 518 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation); 519 } else if (primitiveValue->getIdent() == CSSValueAuto) 520 svgstyle->setGlyphOrientationVertical(GO_AUTO); 521 522 break; 523 } 524 case CSSPropertyEnableBackground: 525 // Silently ignoring this property for now 526 // http://bugs.webkit.org/show_bug.cgi?id=6022 527 break; 528 case CSSPropertyWebkitSvgShadow: { 529 if (isInherit) 530 return svgstyle->setShadow(m_parentStyle->svgStyle()->shadow() ? new ShadowData(*m_parentStyle->svgStyle()->shadow()) : 0); 531 if (isInitial || primitiveValue) // initial | none 532 return svgstyle->setShadow(0); 533 534 if (!value->isValueList()) 535 return; 536 537 float zoomFactor = m_style->effectiveZoom(); 538 539 CSSValueList *list = static_cast<CSSValueList*>(value); 540 ASSERT(list->length() == 1); 541 ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(0)); 542 int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor); 543 int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor); 544 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0; 545 Color color; 546 if (item->color) 547 color = getColorFromPrimitiveValue(item->color.get()); 548 549 // -webkit-svg-shadow does should not have a spread or style 550 ASSERT(!item->spread); 551 ASSERT(!item->style); 552 553 ShadowData* shadowData = new ShadowData(x, y, blur, 0, Normal, color.isValid() ? color : Color::transparent); 554 svgstyle->setShadow(shadowData); 555 return; 556 } 557 default: 558 // If you crash here, it's because you added a css property and are not handling it 559 // in either this switch statement or the one in CSSStyleSelector::applyProperty 560 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id); 561 return; 562 } 563 } 564 565 } 566 567 // vim:ts=4:noet 568 #endif // ENABLE(SVG) 569