1/*
2 * Copyright (C) Research In Motion Limited 2012. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "SVGAnimatedEnumeration.h"
22
23#include "SVGAnimationElement.h"
24#include "SVGComponentTransferFunctionElement.h"
25#include "SVGFEBlendElement.h"
26#include "SVGFEColorMatrixElement.h"
27#include "SVGFECompositeElement.h"
28#include "SVGFEConvolveMatrixElement.h"
29#include "SVGFEDisplacementMapElement.h"
30#include "SVGFEMorphologyElement.h"
31#include "SVGFETurbulenceElement.h"
32#include "SVGGradientElement.h"
33#include "SVGMarkerElement.h"
34#include "SVGNames.h"
35#include "SVGTextContentElement.h"
36#include "SVGTextPathElement.h"
37#include "SVGUnitTypes.h"
38
39namespace WebCore {
40
41static inline unsigned enumerationValueForTargetAttribute(SVGElement* targetElement, const QualifiedName& attrName, const String& value)
42{
43    ASSERT(targetElement);
44    if (attrName == SVGNames::clipPathUnitsAttr
45        || attrName == SVGNames::filterUnitsAttr
46        || attrName == SVGNames::gradientUnitsAttr
47        || attrName == SVGNames::maskContentUnitsAttr
48        || attrName == SVGNames::maskUnitsAttr
49        || attrName == SVGNames::patternContentUnitsAttr
50        || attrName == SVGNames::patternUnitsAttr
51        || attrName == SVGNames::primitiveUnitsAttr)
52        return SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
53
54    if (attrName == SVGNames::lengthAdjustAttr)
55        return SVGPropertyTraits<SVGLengthAdjustType>::fromString(value);
56    if (attrName == SVGNames::markerUnitsAttr)
57        return SVGPropertyTraits<SVGMarkerUnitsType>::fromString(value);
58    if (attrName == SVGNames::methodAttr)
59        return SVGPropertyTraits<SVGTextPathMethodType>::fromString(value);
60    if (attrName == SVGNames::spacingAttr)
61        return SVGPropertyTraits<SVGTextPathSpacingType>::fromString(value);
62    if (attrName == SVGNames::spreadMethodAttr)
63        return SVGPropertyTraits<SVGSpreadMethodType>::fromString(value);
64
65#if ENABLE(FILTERS)
66    if (attrName == SVGNames::edgeModeAttr)
67        return SVGPropertyTraits<EdgeModeType>::fromString(value);
68
69    if (attrName == SVGNames::operatorAttr) {
70        if (targetElement->hasTagName(SVGNames::feCompositeTag))
71            return SVGPropertyTraits<CompositeOperationType>::fromString(value);
72        ASSERT(targetElement->hasTagName(SVGNames::feMorphologyTag));
73        return SVGPropertyTraits<MorphologyOperatorType>::fromString(value);
74    }
75
76    if (attrName == SVGNames::typeAttr) {
77        if (targetElement->hasTagName(SVGNames::feColorMatrixTag))
78            return SVGPropertyTraits<ColorMatrixType>::fromString(value);
79        if (targetElement->hasTagName(SVGNames::feTurbulenceTag))
80            return SVGPropertyTraits<TurbulenceType>::fromString(value);
81
82        ASSERT(targetElement->hasTagName(SVGNames::feFuncATag)
83               || targetElement->hasTagName(SVGNames::feFuncBTag)
84               || targetElement->hasTagName(SVGNames::feFuncGTag)
85               || targetElement->hasTagName(SVGNames::feFuncRTag));
86        return SVGPropertyTraits<ComponentTransferType>::fromString(value);
87    }
88
89    if (attrName == SVGNames::modeAttr) {
90        BlendMode mode = BlendModeNormal;
91        parseBlendMode(value, mode);
92        return mode;
93    }
94    if (attrName == SVGNames::stitchTilesAttr)
95        return SVGPropertyTraits<SVGStitchOptions>::fromString(value);
96    if (attrName == SVGNames::xChannelSelectorAttr)
97        return SVGPropertyTraits<ChannelSelectorType>::fromString(value);
98    if (attrName == SVGNames::yChannelSelectorAttr)
99        return SVGPropertyTraits<ChannelSelectorType>::fromString(value);
100#endif
101
102    ASSERT_NOT_REACHED();
103    return 0;
104}
105
106SVGAnimatedEnumerationAnimator::SVGAnimatedEnumerationAnimator(SVGAnimationElement* animationElement, SVGElement* contextElement)
107    : SVGAnimatedTypeAnimator(AnimatedEnumeration, animationElement, contextElement)
108{
109}
110
111std::unique_ptr<SVGAnimatedType> SVGAnimatedEnumerationAnimator::constructFromString(const String& string)
112{
113    ASSERT(m_animationElement);
114    auto animatedType = SVGAnimatedType::createEnumeration(std::make_unique<unsigned>());
115    animatedType->enumeration() = enumerationValueForTargetAttribute(m_animationElement->targetElement(), m_animationElement->attributeName(), string);
116    return animatedType;
117}
118
119std::unique_ptr<SVGAnimatedType> SVGAnimatedEnumerationAnimator::startAnimValAnimation(const SVGElementAnimatedPropertyList& animatedTypes)
120{
121    return SVGAnimatedType::createEnumeration(constructFromBaseValue<SVGAnimatedEnumeration>(animatedTypes));
122}
123
124void SVGAnimatedEnumerationAnimator::stopAnimValAnimation(const SVGElementAnimatedPropertyList& animatedTypes)
125{
126    stopAnimValAnimationForType<SVGAnimatedEnumeration>(animatedTypes);
127}
128
129void SVGAnimatedEnumerationAnimator::resetAnimValToBaseVal(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type)
130{
131    resetFromBaseValue<SVGAnimatedEnumeration>(animatedTypes, type, &SVGAnimatedType::enumeration);
132}
133
134void SVGAnimatedEnumerationAnimator::animValWillChange(const SVGElementAnimatedPropertyList& animatedTypes)
135{
136    animValWillChangeForType<SVGAnimatedEnumeration>(animatedTypes);
137}
138
139void SVGAnimatedEnumerationAnimator::animValDidChange(const SVGElementAnimatedPropertyList& animatedTypes)
140{
141    animValDidChangeForType<SVGAnimatedEnumeration>(animatedTypes);
142}
143
144void SVGAnimatedEnumerationAnimator::addAnimatedTypes(SVGAnimatedType*, SVGAnimatedType*)
145{
146    ASSERT_NOT_REACHED();
147}
148
149void SVGAnimatedEnumerationAnimator::calculateAnimatedValue(float percentage, unsigned, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType*, SVGAnimatedType* animated)
150{
151    ASSERT(m_animationElement);
152    ASSERT(m_contextElement);
153
154    unsigned fromEnumeration = m_animationElement->animationMode() == ToAnimation ? animated->enumeration() : from->enumeration();
155    unsigned toEnumeration = to->enumeration();
156    unsigned& animatedEnumeration = animated->enumeration();
157
158    m_animationElement->animateDiscreteType<unsigned>(percentage, fromEnumeration, toEnumeration, animatedEnumeration);
159}
160
161float SVGAnimatedEnumerationAnimator::calculateDistance(const String&, const String&)
162{
163    // No paced animations for enumerations.
164    return -1;
165}
166
167}
168