Home | History | Annotate | Download | only in css
      1 /*
      2     Copyright (C) 2007 Eric Seidel <eric (at) webkit.org>
      3     Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public License
     16     along with this library; see the file COPYING.LIB.  If not, write to
     17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18     Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 
     23 #include "core/css/CSSComputedStyleDeclaration.h"
     24 
     25 #include "core/CSSPropertyNames.h"
     26 #include "core/css/CSSPrimitiveValueMappings.h"
     27 #include "core/dom/Document.h"
     28 #include "core/rendering/style/RenderStyle.h"
     29 
     30 namespace blink {
     31 
     32 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation)
     33 {
     34     switch (orientation) {
     35         case GO_0DEG:
     36             return CSSPrimitiveValue::create(0.0f, CSSPrimitiveValue::CSS_DEG);
     37         case GO_90DEG:
     38             return CSSPrimitiveValue::create(90.0f, CSSPrimitiveValue::CSS_DEG);
     39         case GO_180DEG:
     40             return CSSPrimitiveValue::create(180.0f, CSSPrimitiveValue::CSS_DEG);
     41         case GO_270DEG:
     42             return CSSPrimitiveValue::create(270.0f, CSSPrimitiveValue::CSS_DEG);
     43         default:
     44             return nullptr;
     45     }
     46 }
     47 
     48 static PassRefPtrWillBeRawPtr<CSSValue> strokeDashArrayToCSSValueList(PassRefPtr<SVGLengthList> passDashes)
     49 {
     50     RefPtr<SVGLengthList> dashes = passDashes;
     51 
     52     if (dashes->isEmpty())
     53         return CSSPrimitiveValue::createIdentifier(CSSValueNone);
     54 
     55     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
     56     SVGLengthList::ConstIterator it = dashes->begin();
     57     SVGLengthList::ConstIterator itEnd = dashes->end();
     58     for (; it != itEnd; ++it)
     59         list->append(SVGLength::toCSSPrimitiveValue(*it));
     60 
     61     return list.release();
     62 }
     63 
     64 static PassRefPtrWillBeRawPtr<CSSValue> paintOrderToCSSValueList(EPaintOrder paintorder)
     65 {
     66     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
     67     do {
     68         EPaintOrderType paintOrderType = (EPaintOrderType)(paintorder & ((1 << kPaintOrderBitwidth) - 1));
     69         switch (paintOrderType) {
     70         case PT_FILL:
     71         case PT_STROKE:
     72         case PT_MARKERS:
     73             list->append(CSSPrimitiveValue::create(paintOrderType));
     74             break;
     75         case PT_NONE:
     76         default:
     77             ASSERT_NOT_REACHED();
     78             break;
     79         }
     80     } while (paintorder >>= kPaintOrderBitwidth);
     81 
     82     return list.release();
     83 }
     84 
     85 static PassRefPtrWillBeRawPtr<CSSValue> adjustSVGPaintForCurrentColor(SVGPaintType paintType, const String& url, const Color& color, const Color& currentColor)
     86 {
     87     if (paintType >= SVG_PAINTTYPE_URI_NONE) {
     88         RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
     89         values->append(CSSPrimitiveValue::create(url, CSSPrimitiveValue::CSS_URI));
     90         if (paintType == SVG_PAINTTYPE_URI_NONE)
     91             values->append(CSSPrimitiveValue::create(CSSValueNone));
     92         else if (paintType == SVG_PAINTTYPE_URI_CURRENTCOLOR)
     93             values->append(CSSPrimitiveValue::createColor(currentColor.rgb()));
     94         else if (paintType == SVG_PAINTTYPE_URI_RGBCOLOR)
     95             values->append(CSSPrimitiveValue::createColor(color.rgb()));
     96         return values.release();
     97     }
     98     if (paintType == SVG_PAINTTYPE_NONE)
     99         return CSSPrimitiveValue::create(CSSValueNone);
    100     if (paintType == SVG_PAINTTYPE_CURRENTCOLOR)
    101         return CSSPrimitiveValue::createColor(currentColor.rgb());
    102 
    103     return CSSPrimitiveValue::createColor(color.rgb());
    104 }
    105 
    106 static inline String serializeAsFragmentIdentifier(const AtomicString& resource)
    107 {
    108     return "#" + resource;
    109 }
    110 
    111 PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
    112 {
    113     Node* node = m_node.get();
    114     if (!node)
    115         return nullptr;
    116 
    117     // Make sure our layout is up to date before we allow a query on these attributes.
    118     if (updateLayout)
    119         node->document().updateLayout();
    120 
    121     RenderStyle* style = node->computedStyle();
    122     if (!style)
    123         return nullptr;
    124 
    125     const SVGRenderStyle& svgStyle = style->svgStyle();
    126 
    127     switch (propertyID) {
    128         case CSSPropertyClipRule:
    129             return CSSPrimitiveValue::create(svgStyle.clipRule());
    130         case CSSPropertyFloodOpacity:
    131             return CSSPrimitiveValue::create(svgStyle.floodOpacity(), CSSPrimitiveValue::CSS_NUMBER);
    132         case CSSPropertyStopOpacity:
    133             return CSSPrimitiveValue::create(svgStyle.stopOpacity(), CSSPrimitiveValue::CSS_NUMBER);
    134         case CSSPropertyColorInterpolation:
    135             return CSSPrimitiveValue::create(svgStyle.colorInterpolation());
    136         case CSSPropertyColorInterpolationFilters:
    137             return CSSPrimitiveValue::create(svgStyle.colorInterpolationFilters());
    138         case CSSPropertyFillOpacity:
    139             return CSSPrimitiveValue::create(svgStyle.fillOpacity(), CSSPrimitiveValue::CSS_NUMBER);
    140         case CSSPropertyFillRule:
    141             return CSSPrimitiveValue::create(svgStyle.fillRule());
    142         case CSSPropertyColorRendering:
    143             return CSSPrimitiveValue::create(svgStyle.colorRendering());
    144         case CSSPropertyShapeRendering:
    145             return CSSPrimitiveValue::create(svgStyle.shapeRendering());
    146         case CSSPropertyStrokeLinecap:
    147             return CSSPrimitiveValue::create(svgStyle.capStyle());
    148         case CSSPropertyStrokeLinejoin:
    149             return CSSPrimitiveValue::create(svgStyle.joinStyle());
    150         case CSSPropertyStrokeMiterlimit:
    151             return CSSPrimitiveValue::create(svgStyle.strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER);
    152         case CSSPropertyStrokeOpacity:
    153             return CSSPrimitiveValue::create(svgStyle.strokeOpacity(), CSSPrimitiveValue::CSS_NUMBER);
    154         case CSSPropertyAlignmentBaseline:
    155             return CSSPrimitiveValue::create(svgStyle.alignmentBaseline());
    156         case CSSPropertyDominantBaseline:
    157             return CSSPrimitiveValue::create(svgStyle.dominantBaseline());
    158         case CSSPropertyTextAnchor:
    159             return CSSPrimitiveValue::create(svgStyle.textAnchor());
    160         case CSSPropertyWritingMode:
    161             return CSSPrimitiveValue::create(svgStyle.writingMode());
    162         case CSSPropertyClipPath:
    163             if (!svgStyle.clipperResource().isEmpty())
    164                 return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle.clipperResource()), CSSPrimitiveValue::CSS_URI);
    165             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
    166         case CSSPropertyMask:
    167             if (!svgStyle.maskerResource().isEmpty())
    168                 return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle.maskerResource()), CSSPrimitiveValue::CSS_URI);
    169             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
    170         case CSSPropertyFilter:
    171             if (!svgStyle.filterResource().isEmpty())
    172                 return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle.filterResource()), CSSPrimitiveValue::CSS_URI);
    173             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
    174         case CSSPropertyFloodColor:
    175             return currentColorOrValidColor(*style, svgStyle.floodColor());
    176         case CSSPropertyLightingColor:
    177             return currentColorOrValidColor(*style, svgStyle.lightingColor());
    178         case CSSPropertyStopColor:
    179             return currentColorOrValidColor(*style, svgStyle.stopColor());
    180         case CSSPropertyFill:
    181             return adjustSVGPaintForCurrentColor(svgStyle.fillPaintType(), svgStyle.fillPaintUri(), svgStyle.fillPaintColor(), style->color());
    182         case CSSPropertyMarkerEnd:
    183             if (!svgStyle.markerEndResource().isEmpty())
    184                 return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle.markerEndResource()), CSSPrimitiveValue::CSS_URI);
    185             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
    186         case CSSPropertyMarkerMid:
    187             if (!svgStyle.markerMidResource().isEmpty())
    188                 return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle.markerMidResource()), CSSPrimitiveValue::CSS_URI);
    189             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
    190         case CSSPropertyMarkerStart:
    191             if (!svgStyle.markerStartResource().isEmpty())
    192                 return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle.markerStartResource()), CSSPrimitiveValue::CSS_URI);
    193             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
    194         case CSSPropertyStroke:
    195             return adjustSVGPaintForCurrentColor(svgStyle.strokePaintType(), svgStyle.strokePaintUri(), svgStyle.strokePaintColor(), style->color());
    196         case CSSPropertyStrokeDasharray:
    197             return strokeDashArrayToCSSValueList(svgStyle.strokeDashArray());
    198         case CSSPropertyStrokeDashoffset:
    199             return SVGLength::toCSSPrimitiveValue(svgStyle.strokeDashOffset());
    200         case CSSPropertyStrokeWidth:
    201             return SVGLength::toCSSPrimitiveValue(svgStyle.strokeWidth());
    202         case CSSPropertyBaselineShift: {
    203             switch (svgStyle.baselineShift()) {
    204                 case BS_BASELINE:
    205                     return CSSPrimitiveValue::createIdentifier(CSSValueBaseline);
    206                 case BS_SUPER:
    207                     return CSSPrimitiveValue::createIdentifier(CSSValueSuper);
    208                 case BS_SUB:
    209                     return CSSPrimitiveValue::createIdentifier(CSSValueSub);
    210                 case BS_LENGTH:
    211                     return SVGLength::toCSSPrimitiveValue(svgStyle.baselineShiftValue());
    212             }
    213             ASSERT_NOT_REACHED();
    214             return nullptr;
    215         }
    216         case CSSPropertyBufferedRendering:
    217             return CSSPrimitiveValue::create(svgStyle.bufferedRendering());
    218         case CSSPropertyGlyphOrientationHorizontal:
    219             return glyphOrientationToCSSPrimitiveValue(svgStyle.glyphOrientationHorizontal());
    220         case CSSPropertyGlyphOrientationVertical: {
    221             if (RefPtrWillBeRawPtr<CSSPrimitiveValue> value = glyphOrientationToCSSPrimitiveValue(svgStyle.glyphOrientationVertical()))
    222                 return value.release();
    223 
    224             if (svgStyle.glyphOrientationVertical() == GO_AUTO)
    225                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
    226 
    227             return nullptr;
    228         }
    229         case CSSPropertyPaintOrder:
    230             return paintOrderToCSSValueList(svgStyle.paintOrder());
    231         case CSSPropertyVectorEffect:
    232             return CSSPrimitiveValue::create(svgStyle.vectorEffect());
    233         case CSSPropertyMaskType:
    234             return CSSPrimitiveValue::create(svgStyle.maskType());
    235         case CSSPropertyMarker:
    236         case CSSPropertyEnableBackground:
    237             // the above properties are not yet implemented in the engine
    238             break;
    239     default:
    240         // If you crash here, it's because you added a css property and are not handling it
    241         // in either this switch statement or the one in CSSComputedStyleDelcaration::getPropertyCSSValue
    242         ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propertyID);
    243     }
    244     WTF_LOG_ERROR("unimplemented propertyID: %d", propertyID);
    245     return nullptr;
    246 }
    247 
    248 }
    249