1/*
2 * Copyright (C) 2018-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 "SVGAnimatedProperty.h"
29#include "SVGDecoratedProperty.h"
30
31namespace WebCore {
32
33template<template <typename, typename> class DecoratedProperty, typename DecorationType>
34class SVGAnimatedDecoratedProperty : public SVGAnimatedProperty {
35public:
36 template<typename PropertyType, typename AnimatedProperty = SVGAnimatedDecoratedProperty>
37 static Ref<AnimatedProperty> create(SVGElement* contextElement)
38 {
39 return adoptRef(*new AnimatedProperty(contextElement, std::make_unique<DecoratedProperty<DecorationType, PropertyType>>()));
40 }
41
42 template<typename PropertyType, typename AnimatedProperty = SVGAnimatedDecoratedProperty>
43 static Ref<AnimatedProperty> create(SVGElement* contextElement, const PropertyType& value)
44 {
45 return adoptRef(*new AnimatedProperty(contextElement, DecoratedProperty<DecorationType, PropertyType>::create(value)));
46 }
47
48 SVGAnimatedDecoratedProperty(SVGElement* contextElement, std::unique_ptr<SVGDecoratedProperty<DecorationType>>&& baseVal)
49 : SVGAnimatedProperty(contextElement)
50 , m_baseVal(WTFMove(baseVal))
51 {
52 }
53
54 // Used by the DOM.
55 ExceptionOr<void> setBaseVal(const DecorationType& baseVal)
56 {
57 if (!m_baseVal->setValue(baseVal))
58 return Exception { TypeError };
59 commitPropertyChange(nullptr);
60 return { };
61 }
62
63 // Used by SVGElement::parseAttribute().
64 template<typename PropertyType>
65 void setBaseValInternal(const PropertyType& baseVal)
66 {
67 m_baseVal->setValueInternal(static_cast<DecorationType>(baseVal));
68 if (m_animVal)
69 m_animVal->setValueInternal(static_cast<DecorationType>(baseVal));
70 }
71
72 DecorationType baseVal() const { return m_baseVal->value(); }
73
74 // Used by SVGAnimator::progress.
75 template<typename PropertyType>
76 void setAnimVal(const PropertyType& animVal)
77 {
78 ASSERT(isAnimating() && m_animVal);
79 m_animVal->setValueInternal(static_cast<DecorationType>(animVal));
80 }
81
82 template<typename PropertyType = DecorationType>
83 PropertyType animVal() const
84 {
85 ASSERT_IMPLIES(isAnimating(), m_animVal);
86 return static_cast<PropertyType>((isAnimating() ? m_animVal : m_baseVal)->value());
87 }
88
89 // Used when committing a change from the SVGAnimatedProperty to the attribute.
90 String baseValAsString() const override { return m_baseVal->valueAsString(); }
91
92 // Used to apply the SVGAnimator change to the target element.
93 String animValAsString() const override
94 {
95 ASSERT(isAnimating() && !!m_animVal);
96 return m_animVal->valueAsString();
97 }
98
99 // Managing the relationship with the owner.
100 void setDirty() override { m_state = SVGPropertyState::Dirty; }
101 bool isDirty() const override { return m_state == SVGPropertyState::Dirty; }
102 Optional<String> synchronize() override
103 {
104 if (m_state == SVGPropertyState::Clean)
105 return WTF::nullopt;
106 m_state = SVGPropertyState::Clean;
107 return baseValAsString();
108 }
109
110 // Used by RenderSVGElements and DumpRenderTree.
111 template<typename PropertyType>
112 PropertyType currentValue() const
113 {
114 return static_cast<PropertyType>((isAnimating() ? m_animVal : m_baseVal)->valueInternal());
115 }
116
117 // Controlling the animation.
118 void startAnimation() override
119 {
120 if (isAnimating())
121 return;
122 m_animVal = m_baseVal->clone();
123 SVGAnimatedProperty::startAnimation();
124 }
125 void stopAnimation() override
126 {
127 if (!isAnimating())
128 return;
129 m_animVal = nullptr;
130 SVGAnimatedProperty::stopAnimation();
131 }
132
133protected:
134 std::unique_ptr<SVGDecoratedProperty<DecorationType>> m_baseVal;
135 std::unique_ptr<SVGDecoratedProperty<DecorationType>> m_animVal;
136 SVGPropertyState m_state { SVGPropertyState::Clean };
137};
138
139}
140