REGRESSION(r244635): [GTK] Wrong background color used in non-dark mode
[WebKit-https.git] / Source / WebCore / css / CSSToStyleMap.cpp
index 5ca22e8..e93de99 100644 (file)
@@ -30,6 +30,9 @@
 
 #include "Animation.h"
 #include "CSSBorderImageSliceValue.h"
+#include "CSSImageGeneratorValue.h"
+#include "CSSImageSetValue.h"
+#include "CSSImageValue.h"
 #include "CSSPrimitiveValue.h"
 #include "CSSPrimitiveValueMappings.h"
 #include "CSSTimingFunctionValue.h"
 #include "FillLayer.h"
 #include "Pair.h"
 #include "Rect.h"
+#include "StyleBuilderConverter.h"
 #include "StyleResolver.h"
 
 namespace WebCore {
 
+CSSToStyleMap::CSSToStyleMap(StyleResolver* resolver)
+    : m_resolver(resolver)
+{
+}
+
 RenderStyle* CSSToStyleMap::style() const
 {
     return m_resolver->style();
 }
-    
-RenderStyle* CSSToStyleMap::rootElementStyle() const
+
+const RenderStyle* CSSToStyleMap::rootElementStyle() const
 {
     return m_resolver->rootElementStyle();
 }
@@ -55,487 +64,476 @@ bool CSSToStyleMap::useSVGZoomRules() const
 {
     return m_resolver->useSVGZoomRules();
 }
-    
-PassRefPtr<StyleImage> CSSToStyleMap::styleImage(CSSPropertyID propertyId, CSSValue* value)
+
+RefPtr<StyleImage> CSSToStyleMap::styleImage(CSSValue& value)
 {
-    return m_resolver->styleImage(propertyId, value);
+    return m_resolver->styleImage(value);
 }
 
-void CSSToStyleMap::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillAttachment(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setAttachment(FillLayer::initialFillAttachment(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    switch (primitiveValue->getIdent()) {
+    switch (downcast<CSSPrimitiveValue>(value).valueID()) {
     case CSSValueFixed:
-        layer->setAttachment(FixedBackgroundAttachment);
+        layer.setAttachment(FillAttachment::FixedBackground);
         break;
     case CSSValueScroll:
-        layer->setAttachment(ScrollBackgroundAttachment);
+        layer.setAttachment(FillAttachment::ScrollBackground);
         break;
     case CSSValueLocal:
-        layer->setAttachment(LocalBackgroundAttachment);
+        layer.setAttachment(FillAttachment::LocalBackground);
         break;
     default:
         return;
     }
 }
 
-void CSSToStyleMap::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillClip(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setClip(FillLayer::initialFillClip(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setClip(FillLayer::initialFillClip(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    layer->setClip(*primitiveValue);
+    layer.setClip(downcast<CSSPrimitiveValue>(value));
 }
 
-void CSSToStyleMap::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillComposite(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setComposite(FillLayer::initialFillComposite(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setComposite(FillLayer::initialFillComposite(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    layer->setComposite(*primitiveValue);
+    layer.setComposite(downcast<CSSPrimitiveValue>(value));
 }
 
-void CSSToStyleMap::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillBlendMode(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setBlendMode(FillLayer::initialFillBlendMode(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    layer->setOrigin(*primitiveValue);
+    layer.setBlendMode(downcast<CSSPrimitiveValue>(value));
 }
 
-
-void CSSToStyleMap::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillOrigin(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setImage(FillLayer::initialFillImage(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setOrigin(FillLayer::initialFillOrigin(layer.type()));
         return;
     }
 
-    layer->setImage(styleImage(property, value));
+    if (!is<CSSPrimitiveValue>(value))
+        return;
+
+    layer.setOrigin(downcast<CSSPrimitiveValue>(value));
 }
 
-void CSSToStyleMap::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillImage(CSSPropertyID propertyID, FillLayer& layer, CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setImage(FillLayer::initialFillImage(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
-        return;
-
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    layer->setRepeatX(*primitiveValue);
+    layer.setImage(styleImage(value));
 }
 
-void CSSToStyleMap::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillRepeatX(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setRepeatX(FillLayer::initialFillRepeatX(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    layer->setRepeatY(*primitiveValue);
+    layer.setRepeatX(downcast<CSSPrimitiveValue>(value));
 }
 
-void CSSToStyleMap::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillRepeatY(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (!value->isPrimitiveValue()) {
-        layer->setSizeType(SizeNone);
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setRepeatY(FillLayer::initialFillRepeatY(layer.type()));
         return;
     }
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    if (primitiveValue->getIdent() == CSSValueContain)
-        layer->setSizeType(Contain);
-    else if (primitiveValue->getIdent() == CSSValueCover)
-        layer->setSizeType(Cover);
-    else
-        layer->setSizeType(SizeLength);
-
-    LengthSize b = FillLayer::initialFillSizeLength(layer->type());
-
-    if (value->isInitialValue() || primitiveValue->getIdent() == CSSValueContain || primitiveValue->getIdent() == CSSValueCover) {
-        layer->setSizeLength(b);
+    if (!is<CSSPrimitiveValue>(value))
         return;
-    }
 
-    float zoomFactor = style()->effectiveZoom();
+    layer.setRepeatY(downcast<CSSPrimitiveValue>(value));
+}
 
-    Length firstLength;
-    Length secondLength;
+static inline bool convertToLengthSize(const CSSPrimitiveValue& primitiveValue, CSSToLengthConversionData conversionData, LengthSize& size)
+{
+    if (auto* pair = primitiveValue.pairValue()) {
+        size.width = pair->first()->convertToLength<AnyConversion>(conversionData);
+        size.height = pair->second()->convertToLength<AnyConversion>(conversionData);
+    } else
+        size.width = primitiveValue.convertToLength<AnyConversion>(conversionData);
+    return !size.width.isUndefined() && !size.height.isUndefined();
+}
 
-    if (Pair* pair = primitiveValue->getPairValue()) {
-        CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first());
-        CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second());
-        firstLength = first->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor);
-        secondLength = second->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor);
-    } else {
-        firstLength = primitiveValue->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor);
-        secondLength = Length();
+void CSSToStyleMap::mapFillSize(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
+{
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setSize(FillLayer::initialFillSize(layer.type()));
+        return;
     }
 
-    if (firstLength.isUndefined() || secondLength.isUndefined())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    b.setWidth(firstLength);
-    b.setHeight(secondLength);
-    layer->setSizeLength(b);
+    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    FillSize fillSize;
+    switch (primitiveValue.valueID()) {
+    case CSSValueContain:
+        fillSize.type = FillSizeType::Contain;
+        break;
+    case CSSValueCover:
+        fillSize.type = FillSizeType::Cover;
+        break;
+    default:
+        ASSERT(fillSize.type == FillSizeType::Size);
+        if (!convertToLengthSize(primitiveValue, m_resolver->state().cssToLengthConversionData(), fillSize.size))
+            return;
+        break;
+    }
+    layer.setSize(fillSize);
 }
 
-void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setXPosition(FillLayer::initialFillXPosition(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    float zoomFactor = style()->effectiveZoom();
-
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-#if ENABLE(CSS3_BACKGROUND)
-    Pair* pair = primitiveValue->getPairValue();
+    auto* primitiveValue = &downcast<CSSPrimitiveValue>(value);
+    Pair* pair = primitiveValue->pairValue();
+    Length length;
     if (pair) {
         ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionX || propertyID == CSSPropertyWebkitMaskPositionX);
-        primitiveValue = pair->second();
-    }
-#else
-    UNUSED_PARAM(propertyID);
-#endif
-    Length length;
-    if (primitiveValue->isLength())
-        length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor);
-    else if (primitiveValue->isPercentage())
-        length = Length(primitiveValue->getDoubleValue(), Percent);
-    else if (primitiveValue->isCalculatedPercentageWithLength())
-        length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor));
-    else if (primitiveValue->isViewportPercentageLength())
-        length = primitiveValue->viewportPercentageLength();
-    else
-        return;
-    layer->setXPosition(length);
-#if ENABLE(CSS3_BACKGROUND)
+        length = StyleBuilderConverter::convertLength(*m_resolver, *pair->second());
+    } else
+        length = StyleBuilderConverter::convertPositionComponentX(*m_resolver, value);
+
+    layer.setXPosition(length);
     if (pair)
-        layer->setBackgroundXOrigin(*(pair->first()));
-#endif
+        layer.setBackgroundXOrigin(*pair->first());
 }
 
-void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value)
+void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setYPosition(FillLayer::initialFillYPosition(layer.type()));
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    float zoomFactor = style()->effectiveZoom();
-
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-#if ENABLE(CSS3_BACKGROUND)
-    Pair* pair = primitiveValue->getPairValue();
+    auto* primitiveValue = &downcast<CSSPrimitiveValue>(value);
+    Pair* pair = primitiveValue->pairValue();
+    Length length;
     if (pair) {
         ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY);
-        primitiveValue = pair->second();
+        length = StyleBuilderConverter::convertLength(*m_resolver, *pair->second());
+    } else
+        length = StyleBuilderConverter::convertPositionComponentY(*m_resolver, value);
+    
+    layer.setYPosition(length);
+    if (pair)
+        layer.setBackgroundYOrigin(*pair->first());
+}
+
+void CSSToStyleMap::mapFillMaskSourceType(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
+{
+    MaskSourceType type = FillLayer::initialFillMaskSourceType(layer.type());
+    if (value.treatAsInitialValue(propertyID)) {
+        layer.setMaskSourceType(type);
+        return;
     }
-#else
-    UNUSED_PARAM(propertyID);
-#endif
-    Length length;
-    if (primitiveValue->isLength())
-        length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor);
-    else if (primitiveValue->isPercentage())
-        length = Length(primitiveValue->getDoubleValue(), Percent);
-    else if (primitiveValue->isCalculatedPercentageWithLength())
-        length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor));
-    else if (primitiveValue->isViewportPercentageLength())
-        length = primitiveValue->viewportPercentageLength();
-    else
+
+    if (!is<CSSPrimitiveValue>(value))
         return;
-    layer->setYPosition(length);
-#if ENABLE(CSS3_BACKGROUND)
-    if (pair)
-        layer->setBackgroundYOrigin(*(pair->first()));
-#endif
+
+    switch (downcast<CSSPrimitiveValue>(value).valueID()) {
+    case CSSValueAlpha:
+        type = MaskSourceType::Alpha;
+        break;
+    case CSSValueLuminance:
+        type = MaskSourceType::Luminance;
+        break;
+    case CSSValueAuto:
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    layer.setMaskSourceType(type);
 }
 
-void CSSToStyleMap::mapAnimationDelay(Animation* animation, CSSValue* value)
+void CSSToStyleMap::mapAnimationDelay(Animation& animation, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        animation->setDelay(Animation::initialAnimationDelay());
+    if (value.treatAsInitialValue(CSSPropertyAnimationDelay)) {
+        animation.setDelay(Animation::initialDelay());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    animation->setDelay(primitiveValue->computeTime<float, CSSPrimitiveValue::Seconds>());
+    animation.setDelay(downcast<CSSPrimitiveValue>(value).computeTime<double, CSSPrimitiveValue::Seconds>());
 }
 
-void CSSToStyleMap::mapAnimationDirection(Animation* layer, CSSValue* value)
+void CSSToStyleMap::mapAnimationDirection(Animation& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setDirection(Animation::initialAnimationDirection());
+    if (value.treatAsInitialValue(CSSPropertyAnimationDirection)) {
+        layer.setDirection(Animation::initialDirection());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    switch (primitiveValue->getIdent()) {
+    switch (downcast<CSSPrimitiveValue>(value).valueID()) {
     case CSSValueNormal:
-        layer->setDirection(Animation::AnimationDirectionNormal);
+        layer.setDirection(Animation::AnimationDirectionNormal);
         break;
     case CSSValueAlternate:
-        layer->setDirection(Animation::AnimationDirectionAlternate);
+        layer.setDirection(Animation::AnimationDirectionAlternate);
         break;
     case CSSValueReverse:
-        layer->setDirection(Animation::AnimationDirectionReverse);
+        layer.setDirection(Animation::AnimationDirectionReverse);
         break;
     case CSSValueAlternateReverse:
-        layer->setDirection(Animation::AnimationDirectionAlternateReverse);
+        layer.setDirection(Animation::AnimationDirectionAlternateReverse);
+        break;
+    default:
         break;
     }
 }
 
-void CSSToStyleMap::mapAnimationDuration(Animation* animation, CSSValue* value)
+void CSSToStyleMap::mapAnimationDuration(Animation& animation, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        animation->setDuration(Animation::initialAnimationDuration());
+    if (value.treatAsInitialValue(CSSPropertyAnimationDuration)) {
+        animation.setDuration(Animation::initialDuration());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    animation->setDuration(primitiveValue->computeTime<float, CSSPrimitiveValue::Seconds>());
+    animation.setDuration(downcast<CSSPrimitiveValue>(value).computeTime<double, CSSPrimitiveValue::Seconds>());
 }
 
-void CSSToStyleMap::mapAnimationFillMode(Animation* layer, CSSValue* value)
+void CSSToStyleMap::mapAnimationFillMode(Animation& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setFillMode(Animation::initialAnimationFillMode());
+    if (value.treatAsInitialValue(CSSPropertyAnimationFillMode)) {
+        layer.setFillMode(Animation::initialFillMode());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    switch (primitiveValue->getIdent()) {
+    switch (downcast<CSSPrimitiveValue>(value).valueID()) {
     case CSSValueNone:
-        layer->setFillMode(AnimationFillModeNone);
+        layer.setFillMode(AnimationFillMode::None);
         break;
     case CSSValueForwards:
-        layer->setFillMode(AnimationFillModeForwards);
+        layer.setFillMode(AnimationFillMode::Forwards);
         break;
     case CSSValueBackwards:
-        layer->setFillMode(AnimationFillModeBackwards);
+        layer.setFillMode(AnimationFillMode::Backwards);
         break;
     case CSSValueBoth:
-        layer->setFillMode(AnimationFillModeBoth);
+        layer.setFillMode(AnimationFillMode::Both);
+        break;
+    default:
         break;
     }
 }
 
-void CSSToStyleMap::mapAnimationIterationCount(Animation* animation, CSSValue* value)
+void CSSToStyleMap::mapAnimationIterationCount(Animation& animation, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        animation->setIterationCount(Animation::initialAnimationIterationCount());
+    if (value.treatAsInitialValue(CSSPropertyAnimationIterationCount)) {
+        animation.setIterationCount(Animation::initialIterationCount());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    if (primitiveValue->getIdent() == CSSValueInfinite)
-        animation->setIterationCount(Animation::IterationCountInfinite);
+    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    if (primitiveValue.valueID() == CSSValueInfinite)
+        animation.setIterationCount(Animation::IterationCountInfinite);
     else
-        animation->setIterationCount(primitiveValue->getFloatValue());
+        animation.setIterationCount(primitiveValue.floatValue());
 }
 
-void CSSToStyleMap::mapAnimationName(Animation* layer, CSSValue* value)
+void CSSToStyleMap::mapAnimationName(Animation& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setName(Animation::initialAnimationName());
+    if (value.treatAsInitialValue(CSSPropertyAnimationName)) {
+        layer.setName(Animation::initialName());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    if (primitiveValue->getIdent() == CSSValueNone)
-        layer->setIsNoneAnimation(true);
+    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    if (primitiveValue.valueID() == CSSValueNone)
+        layer.setIsNoneAnimation(true);
     else
-        layer->setName(primitiveValue->getStringValue());
+        layer.setName(primitiveValue.stringValue(), m_resolver->state().styleScopeOrdinal());
 }
 
-void CSSToStyleMap::mapAnimationPlayState(Animation* layer, CSSValue* value)
+void CSSToStyleMap::mapAnimationPlayState(Animation& layer, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        layer->setPlayState(Animation::initialAnimationPlayState());
+    if (value.treatAsInitialValue(CSSPropertyAnimationPlayState)) {
+        layer.setPlayState(Animation::initialPlayState());
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying;
-    layer->setPlayState(playState);
+    AnimationPlayState playState = (downcast<CSSPrimitiveValue>(value).valueID() == CSSValuePaused) ? AnimationPlayState::Paused : AnimationPlayState::Playing;
+    layer.setPlayState(playState);
 }
 
-void CSSToStyleMap::mapAnimationProperty(Animation* animation, CSSValue* value)
+void CSSToStyleMap::mapAnimationProperty(Animation& animation, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        animation->setAnimationMode(Animation::AnimateAll);
-        animation->setProperty(CSSPropertyInvalid);
+    if (value.treatAsInitialValue(CSSPropertyAnimation)) {
+        animation.setAnimationMode(Animation::AnimateAll);
+        animation.setProperty(CSSPropertyInvalid);
         return;
     }
 
-    if (!value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    if (primitiveValue->getIdent() == CSSValueAll) {
-        animation->setAnimationMode(Animation::AnimateAll);
-        animation->setProperty(CSSPropertyInvalid);
-    } else if (primitiveValue->getIdent() == CSSValueNone) {
-        animation->setAnimationMode(Animation::AnimateNone);
-        animation->setProperty(CSSPropertyInvalid);
-    } else {
-        animation->setAnimationMode(Animation::AnimateSingleProperty);
-        animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
+    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    if (primitiveValue.valueID() == CSSValueAll) {
+        animation.setAnimationMode(Animation::AnimateAll);
+        animation.setProperty(CSSPropertyInvalid);
+        return;
     }
+    if (primitiveValue.valueID() == CSSValueNone) {
+        animation.setAnimationMode(Animation::AnimateNone);
+        animation.setProperty(CSSPropertyInvalid);
+        return;
+    }
+    if (primitiveValue.propertyID() == CSSPropertyInvalid) {
+        animation.setAnimationMode(Animation::AnimateUnknownProperty);
+        animation.setProperty(CSSPropertyInvalid);
+        animation.setUnknownProperty(primitiveValue.stringValue());
+        return;
+    }
+    animation.setAnimationMode(Animation::AnimateSingleProperty);
+    animation.setProperty(primitiveValue.propertyID());
 }
 
-void CSSToStyleMap::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
+void CSSToStyleMap::mapAnimationTimingFunction(Animation& animation, const CSSValue& value)
 {
-    if (value->isInitialValue()) {
-        animation->setTimingFunction(Animation::initialAnimationTimingFunction());
+    if (value.treatAsInitialValue(CSSPropertyAnimationTimingFunction)) {
+        animation.setTimingFunction(Animation::initialTimingFunction());
         return;
     }
 
-    if (value->isPrimitiveValue()) {
-        CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-        switch (primitiveValue->getIdent()) {
+    if (is<CSSPrimitiveValue>(value)) {
+        switch (downcast<CSSPrimitiveValue>(value).valueID()) {
         case CSSValueLinear:
-            animation->setTimingFunction(LinearTimingFunction::create());
+            animation.setTimingFunction(LinearTimingFunction::create());
             break;
         case CSSValueEase:
-            animation->setTimingFunction(CubicBezierTimingFunction::create());
+            animation.setTimingFunction(CubicBezierTimingFunction::create());
             break;
         case CSSValueEaseIn:
-            animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 1.0, 1.0));
+            animation.setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseIn));
             break;
         case CSSValueEaseOut:
-            animation->setTimingFunction(CubicBezierTimingFunction::create(0.0, 0.0, 0.58, 1.0));
+            animation.setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseOut));
             break;
         case CSSValueEaseInOut:
-            animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 0.58, 1.0));
+            animation.setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseInOut));
             break;
         case CSSValueStepStart:
-            animation->setTimingFunction(StepsTimingFunction::create(1, true));
+            animation.setTimingFunction(StepsTimingFunction::create(1, true));
             break;
         case CSSValueStepEnd:
-            animation->setTimingFunction(StepsTimingFunction::create(1, false));
+            animation.setTimingFunction(StepsTimingFunction::create(1, false));
+            break;
+        default:
             break;
         }
         return;
     }
 
-    if (value->isCubicBezierTimingFunctionValue()) {
-        CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value);
-        animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2()));
-    } else if (value->isStepsTimingFunctionValue()) {
-        CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value);
-        animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart()));
-    } else if (value->isLinearTimingFunctionValue())
-        animation->setTimingFunction(LinearTimingFunction::create());
+    if (is<CSSCubicBezierTimingFunctionValue>(value)) {
+        auto& cubicTimingFunction = downcast<CSSCubicBezierTimingFunctionValue>(value);
+        animation.setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction.x1(), cubicTimingFunction.y1(), cubicTimingFunction.x2(), cubicTimingFunction.y2()));
+    } else if (is<CSSStepsTimingFunctionValue>(value)) {
+        auto& stepsTimingFunction = downcast<CSSStepsTimingFunctionValue>(value);
+        animation.setTimingFunction(StepsTimingFunction::create(stepsTimingFunction.numberOfSteps(), stepsTimingFunction.stepAtStart()));
+    } else if (is<CSSSpringTimingFunctionValue>(value)) {
+        auto& springTimingFunction = downcast<CSSSpringTimingFunctionValue>(value);
+        animation.setTimingFunction(SpringTimingFunction::create(springTimingFunction.mass(), springTimingFunction.stiffness(), springTimingFunction.damping(), springTimingFunction.initialVelocity()));
+    }
 }
 
 void CSSToStyleMap::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image)
 {
     // If we're not a value list, then we are "none" and don't need to alter the empty image at all.
-    if (!value || !value->isValueList())
+    if (!is<CSSValueList>(value))
         return;
 
     // Retrieve the border image value.
-    CSSValueList* borderImage = static_cast<CSSValueList*>(value);
-
-    // Set the image (this kicks off the load).
-    CSSPropertyID imageProperty;
-    if (property == CSSPropertyWebkitBorderImage)
-        imageProperty = CSSPropertyBorderImageSource;
-    else if (property == CSSPropertyWebkitMaskBoxImage)
-        imageProperty = CSSPropertyWebkitMaskBoxImageSource;
-    else
-        imageProperty = property;
-
-    for (unsigned i = 0 ; i < borderImage->length() ; ++i) {
-        CSSValue* current = borderImage->item(i);
-
-        if (current->isImageValue() || current->isImageGeneratorValue()
-#if ENABLE(CSS_IMAGE_SET)
-            || current->isImageSetValue()
-#endif
-            )
-            image.setImage(styleImage(imageProperty, current));
-        else if (current->isBorderImageSliceValue())
+    CSSValueList& borderImage = downcast<CSSValueList>(*value);
+
+    for (auto& current : borderImage) {
+        if (is<CSSImageValue>(current) || is<CSSImageGeneratorValue>(current) || is<CSSImageSetValue>(current))
+            image.setImage(styleImage(current.get()));
+        else if (is<CSSBorderImageSliceValue>(current))
             mapNinePieceImageSlice(current, image);
-        else if (current->isValueList()) {
-            CSSValueList* slashList = static_cast<CSSValueList*>(current);
+        else if (is<CSSValueList>(current)) {
+            CSSValueList& slashList = downcast<CSSValueList>(current.get());
             // Map in the image slices.
-            if (slashList->item(0) && slashList->item(0)->isBorderImageSliceValue())
-                mapNinePieceImageSlice(slashList->item(0), image);
+            if (is<CSSBorderImageSliceValue>(slashList.item(0)))
+                mapNinePieceImageSlice(*slashList.item(0), image);
 
             // Map in the border slices.
-            if (slashList->item(1))
-                image.setBorderSlices(mapNinePieceImageQuad(slashList->item(1)));
+            if (slashList.item(1))
+                image.setBorderSlices(mapNinePieceImageQuad(*slashList.item(1)));
 
             // Map in the outset.
-            if (slashList->item(2))
-                image.setOutset(mapNinePieceImageQuad(slashList->item(2)));
-        } else if (current->isPrimitiveValue()) {
+            if (slashList.item(2))
+                image.setOutset(mapNinePieceImageQuad(*slashList.item(2)));
+        } else if (is<CSSPrimitiveValue>(current)) {
             // Set the appropriate rules for stretch/round/repeat of the slices.
             mapNinePieceImageRepeat(current, image);
         }
@@ -556,96 +554,96 @@ void CSSToStyleMap::mapNinePieceImage(CSSPropertyID property, CSSValue* value, N
     }
 }
 
-void CSSToStyleMap::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& image)
+void CSSToStyleMap::mapNinePieceImageSlice(CSSValue& value, NinePieceImage& image)
 {
-    if (!value || !value->isBorderImageSliceValue())
+    if (!is<CSSBorderImageSliceValue>(value))
         return;
 
     // Retrieve the border image value.
-    CSSBorderImageSliceValue* borderImageSlice = static_cast<CSSBorderImageSliceValue*>(value);
+    auto& borderImageSlice = downcast<CSSBorderImageSliceValue>(value);
 
     // Set up a length box to represent our image slices.
     LengthBox box;
-    Quad* slices = borderImageSlice->slices();
+    Quad* slices = borderImageSlice.slices();
     if (slices->top()->isPercentage())
-        box.m_top = Length(slices->top()->getDoubleValue(), Percent);
+        box.top() = Length(slices->top()->doubleValue(), Percent);
     else
-        box.m_top = Length(slices->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
+        box.top() = Length(slices->top()->intValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
     if (slices->bottom()->isPercentage())
-        box.m_bottom = Length(slices->bottom()->getDoubleValue(), Percent);
+        box.bottom() = Length(slices->bottom()->doubleValue(), Percent);
     else
-        box.m_bottom = Length((int)slices->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
+        box.bottom() = Length((int)slices->bottom()->floatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
     if (slices->left()->isPercentage())
-        box.m_left = Length(slices->left()->getDoubleValue(), Percent);
+        box.left() = Length(slices->left()->doubleValue(), Percent);
     else
-        box.m_left = Length(slices->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
+        box.left() = Length(slices->left()->intValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
     if (slices->right()->isPercentage())
-        box.m_right = Length(slices->right()->getDoubleValue(), Percent);
+        box.right() = Length(slices->right()->doubleValue(), Percent);
     else
-        box.m_right = Length(slices->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
+        box.right() = Length(slices->right()->intValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
     image.setImageSlices(box);
 
     // Set our fill mode.
-    image.setFill(borderImageSlice->m_fill);
+    image.setFill(borderImageSlice.m_fill);
 }
 
-LengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue* value)
+LengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue& value)
 {
-    if (!value || !value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return LengthBox();
 
     // Get our zoom value.
-    float zoom = useSVGZoomRules() ? 1.0f : style()->effectiveZoom();
+    CSSToLengthConversionData conversionData = useSVGZoomRules() ? m_resolver->state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f) : m_resolver->state().cssToLengthConversionData();
 
     // Retrieve the primitive value.
-    CSSPrimitiveValue* borderWidths = static_cast<CSSPrimitiveValue*>(value);
+    auto& borderWidths = downcast<CSSPrimitiveValue>(value);
 
     // Set up a length box to represent our image slices.
     LengthBox box; // Defaults to 'auto' so we don't have to handle that explicitly below.
-    Quad* slices = borderWidths->getQuadValue();
+    Quad* slices = borderWidths.quadValue();
     if (slices->top()->isNumber())
-        box.m_top = Length(slices->top()->getIntValue(), Relative);
+        box.top() = Length(slices->top()->intValue(), Relative);
     else if (slices->top()->isPercentage())
-        box.m_top = Length(slices->top()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
-    else if (slices->top()->getIdent() != CSSValueAuto)
-        box.m_top = slices->top()->computeLength<Length>(style(), rootElementStyle(), zoom);
+        box.top() = Length(slices->top()->doubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+    else if (slices->top()->valueID() != CSSValueAuto)
+        box.top() = slices->top()->computeLength<Length>(conversionData);
 
     if (slices->right()->isNumber())
-        box.m_right = Length(slices->right()->getIntValue(), Relative);
+        box.right() = Length(slices->right()->intValue(), Relative);
     else if (slices->right()->isPercentage())
-        box.m_right = Length(slices->right()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
-    else if (slices->right()->getIdent() != CSSValueAuto)
-        box.m_right = slices->right()->computeLength<Length>(style(), rootElementStyle(), zoom);
+        box.right() = Length(slices->right()->doubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+    else if (slices->right()->valueID() != CSSValueAuto)
+        box.right() = slices->right()->computeLength<Length>(conversionData);
 
     if (slices->bottom()->isNumber())
-        box.m_bottom = Length(slices->bottom()->getIntValue(), Relative);
+        box.bottom() = Length(slices->bottom()->intValue(), Relative);
     else if (slices->bottom()->isPercentage())
-        box.m_bottom = Length(slices->bottom()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
-    else if (slices->bottom()->getIdent() != CSSValueAuto)
-        box.m_bottom = slices->bottom()->computeLength<Length>(style(), rootElementStyle(), zoom);
+        box.bottom() = Length(slices->bottom()->doubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+    else if (slices->bottom()->valueID() != CSSValueAuto)
+        box.bottom() = slices->bottom()->computeLength<Length>(conversionData);
 
     if (slices->left()->isNumber())
-        box.m_left = Length(slices->left()->getIntValue(), Relative);
+        box.left() = Length(slices->left()->intValue(), Relative);
     else if (slices->left()->isPercentage())
-        box.m_left = Length(slices->left()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
-    else if (slices->left()->getIdent() != CSSValueAuto)
-        box.m_left = slices->left()->computeLength<Length>(style(), rootElementStyle(), zoom);
+        box.left() = Length(slices->left()->doubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+    else if (slices->left()->valueID() != CSSValueAuto)
+        box.left() = slices->left()->computeLength<Length>(conversionData);
 
     return box;
 }
 
-void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image)
+void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue& value, NinePieceImage& image)
 {
-    if (!value || !value->isPrimitiveValue())
+    if (!is<CSSPrimitiveValue>(value))
         return;
 
-    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-    Pair* pair = primitiveValue->getPairValue();
+    CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(value);
+    Pair* pair = primitiveValue.pairValue();
     if (!pair || !pair->first() || !pair->second())
         return;
 
-    int firstIdentifier = pair->first()->getIdent();
-    int secondIdentifier = pair->second()->getIdent();
+    CSSValueID firstIdentifier = pair->first()->valueID();
+    CSSValueID secondIdentifier = pair->second()->valueID();
 
     ENinePieceImageRule horizontalRule;
     switch (firstIdentifier) {