1/*
2 * Copyright (C) 2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "SVGLength.h"
29#include "SVGNames.h"
30#include "SVGPrimitivePropertyAnimatorImpl.h"
31#include "SVGValuePropertyAnimatorImpl.h"
32#include "SVGValuePropertyListAnimatorImpl.h"
33
34namespace WebCore {
35
36class SVGPropertyAnimatorFactory {
37public:
38 SVGPropertyAnimatorFactory() = default;
39
40 static bool isKnownAttribute(const QualifiedName& attributeName)
41 {
42 return attributeAnimatorCreator().contains(attributeName.impl());
43 }
44
45 std::unique_ptr<SVGAttributeAnimator> createAnimator(const QualifiedName& attributeName, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
46 {
47 auto iterator = attributeAnimatorCreator().find(attributeName.impl());
48 if (iterator == attributeAnimatorCreator().end())
49 return nullptr;
50
51 auto addResult = m_attributeProperty.ensure(attributeName, [&iterator]() {
52 return iterator->value.first();
53 });
54
55 return iterator->value.second(attributeName, addResult.iterator->value.copyRef(), animationMode, calcMode, isAccumulated, isAdditive);
56 }
57
58 void animatorWillBeDeleted(const QualifiedName& attributeName)
59 {
60 auto iterator = m_attributeProperty.find(attributeName);
61 if (iterator == m_attributeProperty.end())
62 return;
63
64 // If refCount = 1 (in the animator) + 1 (in m_attributeProperty) = 2, the entry can be deleted.
65 if (iterator->value->refCount() == 2)
66 m_attributeProperty.remove(iterator);
67 }
68
69private:
70 // This HashMap maps an attribute name to a pair of static methods. The first one creates a shared
71 // Ref<SVGProperty> for the value type of this attribute. The second creates the animator given the
72 // attribute name and the shared Ref<SVGProperty>.
73 using AttributeAnimatorCreator = HashMap<
74 QualifiedName::QualifiedNameImpl*,
75 std::pair<
76 std::function<Ref<SVGProperty>()>,
77 std::function<std::unique_ptr<SVGAttributeAnimator>(const QualifiedName&, Ref<SVGProperty>&&, AnimationMode, CalcMode, bool, bool)>
78 >
79 >;
80
81 static auto createColorAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
82 {
83 return SVGColorAnimator::create(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
84 }
85
86 static auto createLengthAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
87 {
88 return SVGLengthAnimator::create(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
89 }
90
91 static auto createLengthListAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
92 {
93 return SVGLengthListAnimator::create(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
94 }
95
96 static auto createNumberAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
97 {
98 return SVGNumberAnimator::create(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
99 }
100
101 static auto createStringAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
102 {
103 return SVGStringAnimator::create(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
104 }
105
106 static const AttributeAnimatorCreator& attributeAnimatorCreator()
107 {
108 static NeverDestroyed<AttributeAnimatorCreator> map = AttributeAnimatorCreator({
109 { SVGNames::colorAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
110 { SVGNames::fillAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
111 { SVGNames::flood_colorAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
112 { SVGNames::lighting_colorAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
113 { SVGNames::stop_colorAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
114 { SVGNames::strokeAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
115
116 { SVGNames::font_sizeAttr->impl(), std::make_pair([]() { return SVGLength::create(); }, SVGPropertyAnimatorFactory::createLengthAnimator) },
117 { SVGNames::kerningAttr->impl(), std::make_pair([]() { return SVGLength::create(); }, SVGPropertyAnimatorFactory::createLengthAnimator) },
118 { SVGNames::letter_spacingAttr->impl(), std::make_pair([]() { return SVGLength::create(); }, SVGPropertyAnimatorFactory::createLengthAnimator) },
119 { SVGNames::stroke_dashoffsetAttr->impl(), std::make_pair([]() { return SVGLength::create(); }, SVGPropertyAnimatorFactory::createLengthAnimator) },
120 { SVGNames::stroke_widthAttr->impl(), std::make_pair([]() { return SVGLength::create(); }, SVGPropertyAnimatorFactory::createLengthAnimator) },
121 { SVGNames::word_spacingAttr->impl(), std::make_pair([]() { return SVGLength::create(); }, SVGPropertyAnimatorFactory::createLengthAnimator) },
122
123 { SVGNames::stroke_dasharrayAttr->impl(), std::make_pair([]() { return SVGLengthList::create(); }, SVGPropertyAnimatorFactory::createLengthListAnimator) },
124
125 { SVGNames::fill_opacityAttr->impl(), std::make_pair(SVGValueProperty<float>::create, SVGPropertyAnimatorFactory::createNumberAnimator) },
126 { SVGNames::flood_opacityAttr->impl(), std::make_pair(SVGValueProperty<float>::create, SVGPropertyAnimatorFactory::createNumberAnimator) },
127 { SVGNames::opacityAttr->impl(), std::make_pair(SVGValueProperty<float>::create, SVGPropertyAnimatorFactory::createNumberAnimator) },
128 { SVGNames::stop_opacityAttr->impl(), std::make_pair(SVGValueProperty<float>::create, SVGPropertyAnimatorFactory::createNumberAnimator) },
129 { SVGNames::stroke_miterlimitAttr->impl(), std::make_pair(SVGValueProperty<float>::create, SVGPropertyAnimatorFactory::createNumberAnimator) },
130 { SVGNames::stroke_opacityAttr->impl(), std::make_pair(SVGValueProperty<float>::create, SVGPropertyAnimatorFactory::createNumberAnimator) },
131
132 { SVGNames::alignment_baselineAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
133 { SVGNames::baseline_shiftAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
134 { SVGNames::buffered_renderingAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
135 { SVGNames::clip_pathAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
136 { SVGNames::clip_ruleAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
137 { SVGNames::color_interpolationAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
138 { SVGNames::color_interpolation_filtersAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
139 { SVGNames::color_profileAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
140 { SVGNames::color_renderingAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
141 { SVGNames::cursorAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
142 { SVGNames::displayAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
143 { SVGNames::dominant_baselineAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
144 { SVGNames::fill_ruleAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
145 { SVGNames::filterAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
146 { SVGNames::font_familyAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
147 { SVGNames::font_stretchAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
148 { SVGNames::font_styleAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
149 { SVGNames::font_variantAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
150 { SVGNames::font_weightAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
151 { SVGNames::image_renderingAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
152 { SVGNames::marker_endAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
153 { SVGNames::marker_midAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
154 { SVGNames::marker_startAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
155 { SVGNames::maskAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
156 { SVGNames::mask_typeAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
157 { SVGNames::overflowAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
158 { SVGNames::paint_orderAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
159 { SVGNames::pointer_eventsAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
160 { SVGNames::shape_renderingAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
161 { SVGNames::stroke_linecapAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
162 { SVGNames::stroke_linejoinAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
163 { SVGNames::text_anchorAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
164 { SVGNames::text_decorationAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
165 { SVGNames::text_renderingAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
166 { SVGNames::vector_effectAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) },
167 { SVGNames::visibilityAttr->impl(), std::make_pair(SVGValueProperty<String>::create, SVGPropertyAnimatorFactory::createStringAnimator) }
168 });
169 return map;
170 }
171
172 using AttributeProperty = HashMap<QualifiedName, Ref<SVGProperty>>;
173 AttributeProperty m_attributeProperty;
174};
175
176}
177