1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "config.h"
6#include "core/animation/DeferredLegacyStyleInterpolation.h"
7
8#include "core/animation/LegacyStyleInterpolation.h"
9#include "core/css/CSSImageValue.h"
10#include "core/css/CSSPrimitiveValue.h"
11#include "core/css/CSSSVGDocumentValue.h"
12#include "core/css/CSSShadowValue.h"
13#include "core/css/CSSValueList.h"
14#include "core/css/Pair.h"
15#include "core/css/Rect.h"
16#include "core/css/resolver/StyleResolver.h"
17#include "core/css/resolver/StyleResolverState.h"
18
19namespace blink {
20
21void DeferredLegacyStyleInterpolation::apply(StyleResolverState& state) const
22{
23    RefPtrWillBeRawPtr<LegacyStyleInterpolation> innerInterpolation = LegacyStyleInterpolation::create(
24        StyleResolver::createAnimatableValueSnapshot(state, m_id, *m_startCSSValue),
25        StyleResolver::createAnimatableValueSnapshot(state, m_id, *m_endCSSValue),
26        m_id);
27    innerInterpolation->interpolate(m_cachedIteration, m_cachedFraction);
28    innerInterpolation->apply(state);
29}
30
31bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValue& value)
32{
33    switch (value.cssValueType()) {
34    case CSSValue::CSS_INHERIT:
35        return true;
36    case CSSValue::CSS_PRIMITIVE_VALUE:
37        return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value));
38    case CSSValue::CSS_VALUE_LIST:
39        return interpolationRequiresStyleResolve(toCSSValueList(value));
40    case CSSValue::CSS_CUSTOM:
41        if (value.isImageValue())
42            return interpolationRequiresStyleResolve(toCSSImageValue(value));
43        if (value.isShadowValue())
44            return interpolationRequiresStyleResolve(toCSSShadowValue(value));
45        if (value.isSVGDocumentValue())
46            return interpolationRequiresStyleResolve(toCSSSVGDocumentValue(value));
47        // FIXME: consider other custom types.
48        return true;
49    case CSSValue::CSS_INITIAL:
50        // FIXME: should not require resolving styles for initial.
51        return true;
52    default:
53        ASSERT_NOT_REACHED();
54        return true;
55    }
56}
57
58bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSPrimitiveValue& primitiveValue)
59{
60    // FIXME: consider other types.
61    if (primitiveValue.isNumber() || primitiveValue.isPercentage() || primitiveValue.isAngle() || primitiveValue.isRGBColor() || primitiveValue.isURI())
62        return false;
63
64    if (primitiveValue.isLength())
65        return primitiveValue.isFontRelativeLength() || primitiveValue.isViewportPercentageLength();
66
67    if (primitiveValue.isCalculated()) {
68        CSSLengthArray lengthArray(CSSPrimitiveValue::LengthUnitTypeCount);
69        primitiveValue.accumulateLengthArray(lengthArray);
70        return lengthArray[CSSPrimitiveValue::UnitTypeFontSize] != 0
71            || lengthArray[CSSPrimitiveValue::UnitTypeFontXSize] != 0
72            || lengthArray[CSSPrimitiveValue::UnitTypeRootFontSize] != 0
73            || lengthArray[CSSPrimitiveValue::UnitTypeZeroCharacterWidth] != 0
74            || lengthArray[CSSPrimitiveValue::UnitTypeViewportWidth] != 0
75            || lengthArray[CSSPrimitiveValue::UnitTypeViewportHeight] != 0
76            || lengthArray[CSSPrimitiveValue::UnitTypeViewportMin] != 0
77            || lengthArray[CSSPrimitiveValue::UnitTypeViewportMax] != 0;
78    }
79
80    if (Pair* pair = primitiveValue.getPairValue()) {
81        return interpolationRequiresStyleResolve(*pair->first())
82            || interpolationRequiresStyleResolve(*pair->second());
83    }
84
85    if (Rect* rect = primitiveValue.getRectValue()) {
86        return interpolationRequiresStyleResolve(*rect->top())
87            || interpolationRequiresStyleResolve(*rect->right())
88            || interpolationRequiresStyleResolve(*rect->bottom())
89            || interpolationRequiresStyleResolve(*rect->left());
90    }
91
92    if (Quad* quad = primitiveValue.getQuadValue()) {
93        return interpolationRequiresStyleResolve(*quad->top())
94            || interpolationRequiresStyleResolve(*quad->right())
95            || interpolationRequiresStyleResolve(*quad->bottom())
96            || interpolationRequiresStyleResolve(*quad->left());
97    }
98
99    if (primitiveValue.isShape())
100        return interpolationRequiresStyleResolve(*primitiveValue.getShapeValue());
101
102    CSSValueID id = primitiveValue.getValueID();
103    bool isColor = ((id >= CSSValueAqua && id <= CSSValueTransparent)
104        || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen)
105        || id == CSSValueGrey);
106    return (id != CSSValueNone) && !isColor;
107}
108
109bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSImageValue& imageValue)
110{
111    return false;
112}
113
114bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSShadowValue& shadowValue)
115{
116    return (shadowValue.x && interpolationRequiresStyleResolve(*shadowValue.x))
117        || (shadowValue.y && interpolationRequiresStyleResolve(*shadowValue.y))
118        || (shadowValue.blur && interpolationRequiresStyleResolve(*shadowValue.blur))
119        || (shadowValue.spread && interpolationRequiresStyleResolve(*shadowValue.spread))
120        || (shadowValue.style && interpolationRequiresStyleResolve(*shadowValue.style))
121        || (shadowValue.color && interpolationRequiresStyleResolve(*shadowValue.color));
122}
123
124bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSSVGDocumentValue& documentValue)
125{
126    return true;
127}
128
129bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValueList& valueList)
130{
131    size_t length = valueList.length();
132    for (size_t index = 0; index < length; ++index) {
133        if (interpolationRequiresStyleResolve(*valueList.item(index)))
134            return true;
135    }
136    return false;
137}
138
139bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSBasicShape& shape)
140{
141    // FIXME: Should determine the specific shape, and inspect the members.
142    return false;
143}
144
145void DeferredLegacyStyleInterpolation::trace(Visitor* visitor)
146{
147    visitor->trace(m_startCSSValue);
148    visitor->trace(m_endCSSValue);
149    StyleInterpolation::trace(visitor);
150}
151
152}
153