File indexing completed on 2024-05-12 15:37:27

0001 /*
0002  * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003  * Copyright (C) 2008 Apple Inc. All rights reserved.
0004  *
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions
0007  * are met:
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
0015  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0016  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0017  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
0018  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0019  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0020  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0021  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
0022  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0024  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025  */
0026 
0027 #ifndef JSSVGPODTypeWrapper_h
0028 #define JSSVGPODTypeWrapper_h
0029 
0030 #if ENABLE(SVG)
0031 
0032 #include "Frame.h"
0033 #include <wtf/RefCounted.h>
0034 #include "SVGElement.h"
0035 
0036 #include <wtf/Assertions.h>
0037 #include <wtf/HashMap.h>
0038 
0039 namespace WebCore
0040 {
0041 template<typename PODType>
0042 class SVGPODListItem;
0043 }
0044 
0045 using namespace WebCore;
0046 
0047 namespace khtml
0048 {
0049 
0050 template<typename PODType>
0051 class JSSVGPODTypeWrapper : public RefCounted<JSSVGPODTypeWrapper<PODType> >
0052 {
0053 public:
0054     JSSVGPODTypeWrapper() : RefCounted<JSSVGPODTypeWrapper<PODType> >(0) { }
0055     virtual ~JSSVGPODTypeWrapper() { }
0056 
0057     // Getter wrapper
0058     virtual operator PODType() = 0;
0059 
0060     // Setter wrapper
0061     virtual void commitChange(PODType, SVGElement *) = 0;
0062 };
0063 
0064 template<typename PODType, typename PODTypeCreator>
0065 class JSSVGPODTypeWrapperCreatorReadWrite : public JSSVGPODTypeWrapper<PODType>
0066 {
0067 public:
0068     typedef PODType(PODTypeCreator::*GetterMethod)() const;
0069     typedef void (PODTypeCreator::*SetterMethod)(PODType);
0070 
0071     JSSVGPODTypeWrapperCreatorReadWrite(PODTypeCreator *creator, GetterMethod getter, SetterMethod setter)
0072         : m_creator(creator)
0073         , m_getter(getter)
0074         , m_setter(setter)
0075     {
0076         ASSERT(creator);
0077         ASSERT(getter);
0078         ASSERT(setter);
0079     }
0080 
0081     virtual ~JSSVGPODTypeWrapperCreatorReadWrite() { }
0082 
0083     // Getter wrapper
0084     virtual operator PODType()
0085     {
0086         return (m_creator.get()->*m_getter)();
0087     }
0088 
0089     // Setter wrapper
0090     virtual void commitChange(PODType type, SVGElement *context)
0091     {
0092         if (!m_setter) {
0093             return;
0094         }
0095 
0096         (m_creator.get()->*m_setter)(type);
0097 
0098         if (context) {
0099             context->svgAttributeChanged(m_creator->associatedAttributeName());
0100         }
0101     }
0102 
0103 private:
0104     // Update callbacks
0105     RefPtr<PODTypeCreator> m_creator;
0106     GetterMethod m_getter;
0107     SetterMethod m_setter;
0108 };
0109 
0110 template<typename PODType>
0111 class JSSVGPODTypeWrapperCreatorReadOnly : public JSSVGPODTypeWrapper<PODType>
0112 {
0113 public:
0114     JSSVGPODTypeWrapperCreatorReadOnly(PODType type)
0115         : m_podType(type)
0116     { }
0117 
0118     virtual ~JSSVGPODTypeWrapperCreatorReadOnly() { }
0119 
0120     // Getter wrapper
0121     virtual operator PODType()
0122     {
0123         return m_podType;
0124     }
0125 
0126     // Setter wrapper
0127     virtual void commitChange(PODType type, SVGElement *)
0128     {
0129         m_podType = type;
0130     }
0131 
0132 private:
0133     PODType m_podType;
0134 };
0135 
0136 template<typename PODType>
0137 class JSSVGPODTypeWrapperCreatorForList : public JSSVGPODTypeWrapper<PODType>
0138 {
0139 public:
0140     typedef PODType(SVGPODListItem<PODType>::*GetterMethod)() const;
0141     typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType);
0142 
0143     JSSVGPODTypeWrapperCreatorForList(SVGPODListItem<PODType> *creator, const QualifiedName &attributeName)
0144         : m_creator(creator)
0145         , m_getter(&SVGPODListItem<PODType>::value)
0146         , m_setter(&SVGPODListItem<PODType>::setValue)
0147         , m_associatedAttributeName(attributeName)
0148     {
0149         ASSERT(m_creator);
0150         ASSERT(m_getter);
0151         ASSERT(m_setter);
0152     }
0153 
0154     virtual ~JSSVGPODTypeWrapperCreatorForList() { }
0155 
0156     // Getter wrapper
0157     virtual operator PODType()
0158     {
0159         return (m_creator.get()->*m_getter)();
0160     }
0161 
0162     // Setter wrapper
0163     virtual void commitChange(PODType type, SVGElement *context)
0164     {
0165         if (!m_setter) {
0166             return;
0167         }
0168 
0169         (m_creator.get()->*m_setter)(type);
0170 
0171         if (context) {
0172             context->svgAttributeChanged(m_associatedAttributeName);
0173         }
0174     }
0175 
0176 private:
0177     // Update callbacks
0178     RefPtr<SVGPODListItem<PODType> > m_creator;
0179     GetterMethod m_getter;
0180     SetterMethod m_setter;
0181     const QualifiedName &m_associatedAttributeName;
0182 };
0183 
0184 // Caching facilities
0185 template<typename PODType, typename PODTypeCreator>
0186 struct PODTypeReadWriteHashInfo {
0187     typedef PODType(PODTypeCreator::*GetterMethod)() const;
0188     typedef void (PODTypeCreator::*SetterMethod)(PODType);
0189 
0190     // Empty value
0191     PODTypeReadWriteHashInfo()
0192         : creator(0)
0193         , getter(0)
0194         , setter(0)
0195     {
0196     }
0197 
0198     // Deleted value
0199     PODTypeReadWriteHashInfo(WTF::HashTableDeletedValueType)
0200         : creator(reinterpret_cast<PODTypeCreator *>(-1))
0201     {
0202     }
0203     bool isHashTableDeletedValue() const
0204     {
0205         return creator == reinterpret_cast<PODTypeCreator *>(-1);
0206     }
0207 
0208     PODTypeReadWriteHashInfo(PODTypeCreator *_creator, GetterMethod _getter, SetterMethod _setter)
0209         : creator(_creator)
0210         , getter(_getter)
0211         , setter(_setter)
0212     {
0213         ASSERT(creator);
0214         ASSERT(getter);
0215     }
0216 
0217     bool operator==(const PODTypeReadWriteHashInfo &other) const
0218     {
0219         return creator == other.creator && getter == other.getter && setter == other.setter;
0220     }
0221 
0222     PODTypeCreator *creator;
0223     GetterMethod getter;
0224     SetterMethod setter;
0225 };
0226 
0227 template<typename PODType, typename PODTypeCreator>
0228 struct PODTypeReadWriteHashInfoHash {
0229     static unsigned hash(const PODTypeReadWriteHashInfo<PODType, PODTypeCreator> &info)
0230     {
0231         return StringImpl::computeHash(reinterpret_cast<const WebCore::UChar *>(&info), sizeof(PODTypeReadWriteHashInfo<PODType, PODTypeCreator>) / sizeof(WebCore::UChar));
0232     }
0233 
0234     static bool equal(const PODTypeReadWriteHashInfo<PODType, PODTypeCreator> &a, const PODTypeReadWriteHashInfo<PODType, PODTypeCreator> &b)
0235     {
0236         return a == b;
0237     }
0238 
0239     static const bool safeToCompareToEmptyOrDeleted = true;
0240 };
0241 
0242 template<typename PODType, typename PODTypeCreator>
0243 struct PODTypeReadWriteHashInfoTraits : WTF::GenericHashTraits<PODTypeReadWriteHashInfo<PODType, PODTypeCreator> > {
0244     static const bool emptyValueIsZero = true;
0245     static const bool needsDestruction = false;
0246 
0247     static const PODTypeReadWriteHashInfo<PODType, PODTypeCreator> &emptyValue()
0248     {
0249         static PODTypeReadWriteHashInfo<PODType, PODTypeCreator> key;
0250         return key;
0251     }
0252 
0253     static void constructDeletedValue(PODTypeReadWriteHashInfo<PODType, PODTypeCreator> *slot)
0254     {
0255         new(slot) PODTypeReadWriteHashInfo<PODType, PODTypeCreator>(WTF::HashTableDeletedValue);
0256     }
0257     static bool isDeletedValue(const PODTypeReadWriteHashInfo<PODType, PODTypeCreator> &value)
0258     {
0259         return value.isHashTableDeletedValue();
0260     }
0261 };
0262 
0263 template<typename PODType, typename PODTypeCreator>
0264 class JSSVGPODTypeWrapperCache
0265 {
0266 public:
0267     typedef PODType(PODTypeCreator::*GetterMethod)() const;
0268     typedef void (PODTypeCreator::*SetterMethod)(PODType);
0269 
0270     typedef HashMap<PODTypeReadWriteHashInfo<PODType, PODTypeCreator>, JSSVGPODTypeWrapperCreatorReadWrite<PODType, PODTypeCreator>*, PODTypeReadWriteHashInfoHash<PODType, PODTypeCreator>, PODTypeReadWriteHashInfoTraits<PODType, PODTypeCreator> > ReadWriteHashMap;
0271     typedef typename ReadWriteHashMap::const_iterator ReadWriteHashMapIterator;
0272 
0273     static ReadWriteHashMap &readWriteHashMap()
0274     {
0275         static ReadWriteHashMap _readWriteHashMap;
0276         return _readWriteHashMap;
0277     }
0278 
0279     // Used for readwrite attributes only
0280     static JSSVGPODTypeWrapper<PODType> *lookupOrCreateWrapper(PODTypeCreator *creator, GetterMethod getter, SetterMethod setter)
0281     {
0282         ReadWriteHashMap &map(readWriteHashMap());
0283         PODTypeReadWriteHashInfo<PODType, PODTypeCreator> info(creator, getter, setter);
0284 
0285         if (map.contains(info)) {
0286             return map.get(info);
0287         }
0288 
0289         JSSVGPODTypeWrapperCreatorReadWrite<PODType, PODTypeCreator> *wrapper = new JSSVGPODTypeWrapperCreatorReadWrite<PODType, PODTypeCreator>(creator, getter, setter);
0290         map.set(info, wrapper);
0291         return wrapper;
0292     }
0293 
0294     static void forgetWrapper(JSSVGPODTypeWrapper<PODType> *wrapper)
0295     {
0296         ReadWriteHashMap &map(readWriteHashMap());
0297 
0298         ReadWriteHashMapIterator it = map.begin();
0299         ReadWriteHashMapIterator end = map.end();
0300 
0301         for (; it != end; ++it) {
0302             if (it->second != wrapper) {
0303                 continue;
0304             }
0305 
0306             // It's guaruanteed that there's just one object we need to take care of.
0307             map.remove(it->first);
0308             break;
0309         }
0310     }
0311 };
0312 
0313 };
0314 
0315 #endif // ENABLE(SVG)
0316 #endif // JSSVGPODTypeWrapper_h