Home | History | Annotate | Download | only in css
      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 if (isInitial) { \
     59     svgstyle->set##Prop(SVGRenderStyle::initial##Prop()); \
     60     return; \
     61 }
     62 
     63 namespace WebCore {
     64 
     65 static float roundToNearestGlyphOrientationAngle(float angle)
     66 {
     67     angle = fabsf(fmodf(angle, 360.0f));
     68 
     69     if (angle <= 45.0f || angle > 315.0f)
     70         return 0.0f;
     71     else if (angle > 45.0f && angle <= 135.0f)
     72         return 90.0f;
     73     else if (angle > 135.0f && angle <= 225.0f)
     74         return 180.0f;
     75 
     76     return 270.0f;
     77 }
     78 
     79 static int angleToGlyphOrientation(float angle)
     80 {
     81     angle = roundToNearestGlyphOrientationAngle(angle);
     82 
     83     if (angle == 0.0f)
     84         return GO_0DEG;
     85     else if (angle == 90.0f)
     86         return GO_90DEG;
     87     else if (angle == 180.0f)
     88         return GO_180DEG;
     89     else if (angle == 270.0f)
     90         return GO_270DEG;
     91 
     92     return -1;
     93 }
     94 
     95 static Color colorFromSVGColorCSSValue(SVGColor* svgColor, const Color& fgColor)
     96 {
     97     Color color;
     98     if (svgColor->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR)
     99         color = fgColor;
    100     else
    101         color = svgColor->color();
    102     return color;
    103 }
    104 
    105 void CSSStyleSelector::applySVGProperty(int id, CSSValue* value)
    106 {
    107     ASSERT(value);
    108     CSSPrimitiveValue* primitiveValue = 0;
    109     if (value->isPrimitiveValue())
    110         primitiveValue = static_cast<CSSPrimitiveValue*>(value);
    111 
    112     SVGRenderStyle* svgstyle = m_style->accessSVGStyle();
    113     unsigned short valueType = value->cssValueType();
    114 
    115     bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT;
    116     bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT);
    117 
    118     // What follows is a list that maps the CSS properties into their
    119     // corresponding front-end RenderStyle values. Shorthands(e.g. border,
    120     // background) occur in this list as well and are only hit when mapping
    121     // "inherit" or "initial" into front-end values.
    122     switch (id)
    123     {
    124         // ident only properties
    125         case CSSPropertyAlignmentBaseline:
    126         {
    127             HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline)
    128             if (!primitiveValue)
    129                 break;
    130 
    131             svgstyle->setAlignmentBaseline(*primitiveValue);
    132             break;
    133         }
    134         case CSSPropertyBaselineShift:
    135         {
    136             HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift);
    137             if (!primitiveValue)
    138                 break;
    139 
    140             if (primitiveValue->getIdent()) {
    141                 switch (primitiveValue->getIdent()) {
    142                 case CSSValueBaseline:
    143                     svgstyle->setBaselineShift(BS_BASELINE);
    144                     break;
    145                 case CSSValueSub:
    146                     svgstyle->setBaselineShift(BS_SUB);
    147                     break;
    148                 case CSSValueSuper:
    149                     svgstyle->setBaselineShift(BS_SUPER);
    150                     break;
    151                 default:
    152                     break;
    153                 }
    154             } else {
    155                 svgstyle->setBaselineShift(BS_LENGTH);
    156                 svgstyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
    157             }
    158 
    159             break;
    160         }
    161         case CSSPropertyKerning:
    162         {
    163             HANDLE_INHERIT_AND_INITIAL(kerning, Kerning);
    164             if (primitiveValue)
    165                 svgstyle->setKerning(SVGLength::fromCSSPrimitiveValue(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(SVGLength::fromCSSPrimitiveValue(primitiveValue));
    252             break;
    253         }
    254         case CSSPropertyStrokeDasharray:
    255         {
    256             HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
    257             if (!value->isValueList())
    258                 break;
    259 
    260             CSSValueList* dashes = static_cast<CSSValueList*>(value);
    261 
    262             Vector<SVGLength> array;
    263             size_t length = dashes->length();
    264             for (size_t i = 0; i < length; ++i) {
    265                 CSSValue* currValue = dashes->itemWithoutBoundsCheck(i);
    266                 if (!currValue->isPrimitiveValue())
    267                     continue;
    268 
    269                 CSSPrimitiveValue* dash = static_cast<CSSPrimitiveValue*>(dashes->itemWithoutBoundsCheck(i));
    270                 array.append(SVGLength::fromCSSPrimitiveValue(dash));
    271             }
    272 
    273             svgstyle->setStrokeDashArray(array);
    274             break;
    275         }
    276         case CSSPropertyStrokeDashoffset:
    277         {
    278             HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
    279             if (primitiveValue)
    280                 svgstyle->setStrokeDashOffset(SVGLength::fromCSSPrimitiveValue(primitiveValue));
    281             break;
    282         }
    283         case CSSPropertyFillOpacity:
    284         {
    285             HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
    286             if (!primitiveValue)
    287                 return;
    288 
    289             float f = 0.0f;
    290             int type = primitiveValue->primitiveType();
    291             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
    292                 f = primitiveValue->getFloatValue() / 100.0f;
    293             else if (type == CSSPrimitiveValue::CSS_NUMBER)
    294                 f = primitiveValue->getFloatValue();
    295             else
    296                 return;
    297 
    298             svgstyle->setFillOpacity(f);
    299             break;
    300         }
    301         case CSSPropertyStrokeOpacity:
    302         {
    303             HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
    304             if (!primitiveValue)
    305                 return;
    306 
    307             float f = 0.0f;
    308             int type = primitiveValue->primitiveType();
    309             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
    310                 f = primitiveValue->getFloatValue() / 100.0f;
    311             else if (type == CSSPrimitiveValue::CSS_NUMBER)
    312                 f = primitiveValue->getFloatValue();
    313             else
    314                 return;
    315 
    316             svgstyle->setStrokeOpacity(f);
    317             break;
    318         }
    319         case CSSPropertyStopOpacity:
    320         {
    321             HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
    322             if (!primitiveValue)
    323                 return;
    324 
    325             float f = 0.0f;
    326             int type = primitiveValue->primitiveType();
    327             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
    328                 f = primitiveValue->getFloatValue() / 100.0f;
    329             else if (type == CSSPrimitiveValue::CSS_NUMBER)
    330                 f = primitiveValue->getFloatValue();
    331             else
    332                 return;
    333 
    334             svgstyle->setStopOpacity(f);
    335             break;
    336         }
    337         case CSSPropertyMarkerStart:
    338         {
    339             HANDLE_INHERIT_AND_INITIAL(markerStartResource, MarkerStartResource)
    340             if (!primitiveValue)
    341                 return;
    342 
    343             String s;
    344             int type = primitiveValue->primitiveType();
    345             if (type == CSSPrimitiveValue::CSS_URI)
    346                 s = primitiveValue->getStringValue();
    347             else
    348                 return;
    349 
    350             svgstyle->setMarkerStartResource(SVGURIReference::getTarget(s));
    351             break;
    352         }
    353         case CSSPropertyMarkerMid:
    354         {
    355             HANDLE_INHERIT_AND_INITIAL(markerMidResource, MarkerMidResource)
    356             if (!primitiveValue)
    357                 return;
    358 
    359             String s;
    360             int type = primitiveValue->primitiveType();
    361             if (type == CSSPrimitiveValue::CSS_URI)
    362                 s = primitiveValue->getStringValue();
    363             else
    364                 return;
    365 
    366             svgstyle->setMarkerMidResource(SVGURIReference::getTarget(s));
    367             break;
    368         }
    369         case CSSPropertyMarkerEnd:
    370         {
    371             HANDLE_INHERIT_AND_INITIAL(markerEndResource, MarkerEndResource)
    372             if (!primitiveValue)
    373                 return;
    374 
    375             String s;
    376             int type = primitiveValue->primitiveType();
    377             if (type == CSSPrimitiveValue::CSS_URI)
    378                 s = primitiveValue->getStringValue();
    379             else
    380                 return;
    381 
    382             svgstyle->setMarkerEndResource(SVGURIReference::getTarget(s));
    383             break;
    384         }
    385         case CSSPropertyStrokeLinecap:
    386         {
    387             HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
    388             if (primitiveValue)
    389                 svgstyle->setCapStyle(*primitiveValue);
    390             break;
    391         }
    392         case CSSPropertyStrokeMiterlimit:
    393         {
    394             HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
    395             if (!primitiveValue)
    396                 return;
    397 
    398             float f = 0.0f;
    399             int type = primitiveValue->primitiveType();
    400             if (type == CSSPrimitiveValue::CSS_NUMBER)
    401                 f = primitiveValue->getFloatValue();
    402             else
    403                 return;
    404 
    405             svgstyle->setStrokeMiterLimit(f);
    406             break;
    407         }
    408         case CSSPropertyFilter:
    409         {
    410             HANDLE_INHERIT_AND_INITIAL(filterResource, FilterResource)
    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->setFilterResource(SVGURIReference::getTarget(s));
    422             break;
    423         }
    424         case CSSPropertyMask:
    425         {
    426             HANDLE_INHERIT_AND_INITIAL(maskerResource, MaskerResource)
    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->setMaskerResource(SVGURIReference::getTarget(s));
    438             break;
    439         }
    440         case CSSPropertyClipPath:
    441         {
    442             HANDLE_INHERIT_AND_INITIAL(clipperResource, ClipperResource)
    443             if (!primitiveValue)
    444                 return;
    445 
    446             String s;
    447             int type = primitiveValue->primitiveType();
    448             if (type == CSSPrimitiveValue::CSS_URI)
    449                 s = primitiveValue->getStringValue();
    450             else
    451                 return;
    452 
    453             svgstyle->setClipperResource(SVGURIReference::getTarget(s));
    454             break;
    455         }
    456         case CSSPropertyTextAnchor:
    457         {
    458             HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
    459             if (primitiveValue)
    460                 svgstyle->setTextAnchor(*primitiveValue);
    461             break;
    462         }
    463         case CSSPropertyWritingMode:
    464         {
    465             HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
    466             if (primitiveValue)
    467                 svgstyle->setWritingMode(*primitiveValue);
    468             break;
    469         }
    470         case CSSPropertyStopColor:
    471         {
    472             HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
    473             if (value->isSVGColor())
    474                 svgstyle->setStopColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
    475             break;
    476         }
    477        case CSSPropertyLightingColor:
    478         {
    479             HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
    480             if (value->isSVGColor())
    481                 svgstyle->setLightingColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
    482             break;
    483         }
    484         case CSSPropertyFloodOpacity:
    485         {
    486             HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
    487             if (!primitiveValue)
    488                 return;
    489 
    490             float f = 0.0f;
    491             int type = primitiveValue->primitiveType();
    492             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
    493                 f = primitiveValue->getFloatValue() / 100.0f;
    494             else if (type == CSSPrimitiveValue::CSS_NUMBER)
    495                 f = primitiveValue->getFloatValue();
    496             else
    497                 return;
    498 
    499             svgstyle->setFloodOpacity(f);
    500             break;
    501         }
    502         case CSSPropertyFloodColor:
    503         {
    504             HANDLE_INHERIT_AND_INITIAL(floodColor, FloodColor);
    505             if (value->isSVGColor())
    506                 svgstyle->setFloodColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
    507             break;
    508         }
    509         case CSSPropertyGlyphOrientationHorizontal:
    510         {
    511             HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
    512             if (!primitiveValue)
    513                 return;
    514 
    515             if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
    516                 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
    517                 ASSERT(orientation != -1);
    518 
    519                 svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
    520             }
    521 
    522             break;
    523         }
    524         case CSSPropertyGlyphOrientationVertical:
    525         {
    526             HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
    527             if (!primitiveValue)
    528                 return;
    529 
    530             if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
    531                 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
    532                 ASSERT(orientation != -1);
    533 
    534                 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
    535             } else if (primitiveValue->getIdent() == CSSValueAuto)
    536                 svgstyle->setGlyphOrientationVertical(GO_AUTO);
    537 
    538             break;
    539         }
    540         case CSSPropertyEnableBackground:
    541             // Silently ignoring this property for now
    542             // http://bugs.webkit.org/show_bug.cgi?id=6022
    543             break;
    544         case CSSPropertyWebkitSvgShadow: {
    545             if (isInherit)
    546                 return svgstyle->setShadow(m_parentStyle->svgStyle()->shadow() ? new ShadowData(*m_parentStyle->svgStyle()->shadow()) : 0);
    547             if (isInitial || primitiveValue) // initial | none
    548                 return svgstyle->setShadow(0);
    549 
    550             if (!value->isValueList())
    551                 return;
    552 
    553             CSSValueList *list = static_cast<CSSValueList*>(value);
    554             if (!list->length())
    555                 return;
    556 
    557             CSSValue* firstValue = list->itemWithoutBoundsCheck(0);
    558             if (!firstValue->isShadowValue())
    559                 return;
    560             ShadowValue* item = static_cast<ShadowValue*>(firstValue);
    561             int x = item->x->computeLengthInt(style(), m_rootElementStyle);
    562             int y = item->y->computeLengthInt(style(), m_rootElementStyle);
    563             int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle) : 0;
    564             Color color;
    565             if (item->color)
    566                 color = getColorFromPrimitiveValue(item->color.get());
    567 
    568             // -webkit-svg-shadow does should not have a spread or style
    569             ASSERT(!item->spread);
    570             ASSERT(!item->style);
    571 
    572             ShadowData* shadowData = new ShadowData(x, y, blur, 0, Normal, false, color.isValid() ? color : Color::transparent);
    573             svgstyle->setShadow(shadowData);
    574             return;
    575         }
    576         case CSSPropertyVectorEffect: {
    577             HANDLE_INHERIT_AND_INITIAL(vectorEffect, VectorEffect)
    578             if (!primitiveValue)
    579                 break;
    580 
    581             svgstyle->setVectorEffect(*primitiveValue);
    582             break;
    583         }
    584         default:
    585             // If you crash here, it's because you added a css property and are not handling it
    586             // in either this switch statement or the one in CSSStyleSelector::applyProperty
    587             ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);
    588             return;
    589     }
    590 }
    591 
    592 }
    593 
    594 #endif
    595