1/*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#ifndef SVGAnimatedPropertyMacros_h
23#define SVGAnimatedPropertyMacros_h
24
25#if ENABLE(SVG)
26#include "SVGAnimatedProperty.h"
27#include "SVGAttributeToPropertyMap.h"
28#include "SVGPropertyTraits.h"
29#include <wtf/StdLibExtras.h>
30
31namespace WebCore {
32
33// SVGSynchronizableAnimatedProperty implementation
34template<typename PropertyType>
35struct SVGSynchronizableAnimatedProperty {
36    SVGSynchronizableAnimatedProperty()
37        : value(SVGPropertyTraits<PropertyType>::initialValue())
38        , shouldSynchronize(false)
39        , isValid(false)
40    {
41    }
42
43    template<typename ConstructorParameter1>
44    SVGSynchronizableAnimatedProperty(const ConstructorParameter1& value1)
45        : value(value1)
46        , shouldSynchronize(false)
47        , isValid(false)
48    {
49    }
50
51    template<typename ConstructorParameter1, typename ConstructorParameter2>
52    SVGSynchronizableAnimatedProperty(const ConstructorParameter1& value1, const ConstructorParameter2& value2)
53        : value(value1, value2)
54        , shouldSynchronize(false)
55        , isValid(false)
56    {
57    }
58
59    void synchronize(SVGElement* ownerElement, const QualifiedName& attrName, const AtomicString& value)
60    {
61        ownerElement->setSynchronizedLazyAttribute(attrName, value);
62    }
63
64    PropertyType value;
65    bool shouldSynchronize : 1;
66    bool isValid : 1;
67};
68
69// Property registration helpers
70#define BEGIN_REGISTER_ANIMATED_PROPERTIES(OwnerType) \
71SVGAttributeToPropertyMap& OwnerType::attributeToPropertyMap() \
72{ \
73    DEFINE_STATIC_LOCAL(SVGAttributeToPropertyMap, s_attributeToPropertyMap, ()); \
74    return s_attributeToPropertyMap; \
75} \
76\
77static void registerAnimatedPropertiesFor##OwnerType() \
78{ \
79    SVGAttributeToPropertyMap& map = OwnerType::attributeToPropertyMap(); \
80    if (!map.isEmpty()) \
81        return; \
82    typedef OwnerType UseOwnerType;
83
84#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) \
85     map.addProperty(UseOwnerType::LowerProperty##PropertyInfo());
86
87#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) \
88     map.addProperties(ClassName::attributeToPropertyMap()); \
89
90#define END_REGISTER_ANIMATED_PROPERTIES }
91
92// Property definition helpers (used in SVG*.cpp files)
93#define DEFINE_ANIMATED_PROPERTY(AnimatedPropertyTypeEnum, OwnerType, DOMAttribute, SVGDOMAttributeIdentifier, UpperProperty, LowerProperty) \
94const SVGPropertyInfo* OwnerType::LowerProperty##PropertyInfo() { \
95    DEFINE_STATIC_LOCAL(const SVGPropertyInfo, s_propertyInfo, \
96                        (AnimatedPropertyTypeEnum, \
97                         PropertyIsReadWrite, \
98                         DOMAttribute, \
99                         SVGDOMAttributeIdentifier, \
100                         &OwnerType::synchronize##UpperProperty, \
101                         &OwnerType::lookupOrCreate##UpperProperty##Wrapper)); \
102    return &s_propertyInfo; \
103}
104
105// Property declaration helpers (used in SVG*.h files)
106#define BEGIN_DECLARE_ANIMATED_PROPERTIES(OwnerType) \
107public: \
108    static SVGAttributeToPropertyMap& attributeToPropertyMap(); \
109    virtual SVGAttributeToPropertyMap& localAttributeToPropertyMap() \
110    { \
111        return attributeToPropertyMap(); \
112    } \
113    typedef OwnerType UseOwnerType;
114
115#define DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \
116public: \
117    static const SVGPropertyInfo* LowerProperty##PropertyInfo(); \
118    PropertyType& LowerProperty() const \
119    { \
120        if (TearOffType* wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) { \
121            if (wrapper->isAnimating()) \
122                return wrapper->currentAnimatedValue(); \
123        } \
124        return m_##LowerProperty.value; \
125    } \
126\
127    PropertyType& LowerProperty##BaseValue() const \
128    { \
129        return m_##LowerProperty.value; \
130    } \
131\
132    void set##UpperProperty##BaseValue(const PropertyType& type, const bool validValue = true) \
133    { \
134        m_##LowerProperty.value = type; \
135        m_##LowerProperty.isValid = validValue; \
136    } \
137\
138    PassRefPtr<TearOffType> LowerProperty##Animated() \
139    { \
140        m_##LowerProperty.shouldSynchronize = true; \
141        return static_pointer_cast<TearOffType>(lookupOrCreate##UpperProperty##Wrapper(this)); \
142    } \
143\
144    bool LowerProperty##IsValid() const \
145    { \
146        return m_##LowerProperty.isValid; \
147    } \
148\
149private: \
150    void synchronize##UpperProperty() \
151    { \
152        if (!m_##LowerProperty.shouldSynchronize) \
153            return; \
154        AtomicString value(SVGPropertyTraits<PropertyType>::toString(m_##LowerProperty.value)); \
155        m_##LowerProperty.synchronize(this, LowerProperty##PropertyInfo()->attributeName, value); \
156    } \
157\
158    static PassRefPtr<SVGAnimatedProperty> lookupOrCreate##UpperProperty##Wrapper(SVGElement* maskedOwnerType) \
159    { \
160        ASSERT(maskedOwnerType); \
161        UseOwnerType* ownerType = static_cast<UseOwnerType*>(maskedOwnerType); \
162        return SVGAnimatedProperty::lookupOrCreateWrapper<UseOwnerType, TearOffType, PropertyType>(ownerType, LowerProperty##PropertyInfo(), ownerType->m_##LowerProperty.value); \
163    } \
164\
165    static void synchronize##UpperProperty(SVGElement* maskedOwnerType) \
166    { \
167        ASSERT(maskedOwnerType); \
168        UseOwnerType* ownerType = static_cast<UseOwnerType*>(maskedOwnerType); \
169        ownerType->synchronize##UpperProperty(); \
170    } \
171\
172    mutable SVGSynchronizableAnimatedProperty<PropertyType> m_##LowerProperty;
173
174#define END_DECLARE_ANIMATED_PROPERTIES
175
176// List specific definition/declaration helpers
177#define DECLARE_ANIMATED_LIST_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \
178DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \
179void detachAnimated##UpperProperty##ListWrappers(unsigned newListSize) \
180{ \
181    if (TearOffType* wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) \
182        wrapper->detachListWrappers(newListSize); \
183}
184
185}
186
187#endif // ENABLE(SVG)
188#endif // SVGAnimatedPropertyMacros_h
189