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 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