JSSVGPODTypeWrapper.h [plain text]
#ifndef JSSVGPODTypeWrapper_h
#define JSSVGPODTypeWrapper_h
#if ENABLE(SVG)
#include "JSSVGContextCache.h"
#include "SVGElement.h"
#include <wtf/StdLibExtras.h>
namespace WebCore {
class DOMObject;
template<typename PODType>
class JSSVGPODTypeWrapper : public RefCounted<JSSVGPODTypeWrapper<PODType> > {
public:
virtual ~JSSVGPODTypeWrapper() { }
virtual operator PODType() = 0;
virtual void commitChange(PODType, DOMObject*) = 0;
};
#if COMPILER(MSVC)
#pragma pack(16)
#endif
template<typename PODType, typename PODTypeCreator>
class JSSVGDynamicPODTypeWrapper : public JSSVGPODTypeWrapper<PODType> {
public:
typedef PODType (PODTypeCreator::*GetterMethod)() const;
typedef void (PODTypeCreator::*SetterMethod)(const PODType&);
static PassRefPtr<JSSVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter)
{
return adoptRef(new JSSVGDynamicPODTypeWrapper(creator, getter, setter));
}
virtual operator PODType()
{
return (m_creator.get()->*m_getter)();
}
virtual void commitChange(PODType type, DOMObject* wrapper)
{
(m_creator.get()->*m_setter)(type);
JSSVGContextCache::propagateSVGDOMChange(wrapper, m_creator->associatedAttributeName());
}
private:
JSSVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter)
: m_creator(creator)
, m_getter(getter)
, m_setter(setter)
{
ASSERT(m_creator);
ASSERT(m_getter);
ASSERT(m_setter);
}
virtual ~JSSVGDynamicPODTypeWrapper();
RefPtr<PODTypeCreator> m_creator;
GetterMethod m_getter;
SetterMethod m_setter;
};
template<typename PODType>
class JSSVGStaticPODTypeWrapper : public JSSVGPODTypeWrapper<PODType> {
public:
static PassRefPtr<JSSVGStaticPODTypeWrapper> create(PODType type)
{
return adoptRef(new JSSVGStaticPODTypeWrapper(type));
}
virtual operator PODType()
{
return m_podType;
}
virtual void commitChange(PODType type, DOMObject*)
{
m_podType = type;
}
protected:
JSSVGStaticPODTypeWrapper(PODType type)
: m_podType(type)
{
}
PODType m_podType;
};
template<typename PODType, typename ParentTypeArg>
class JSSVGStaticPODTypeWrapperWithPODTypeParent : public JSSVGStaticPODTypeWrapper<PODType> {
public:
typedef JSSVGPODTypeWrapper<ParentTypeArg> ParentType;
static PassRefPtr<JSSVGStaticPODTypeWrapperWithPODTypeParent> create(PODType type, PassRefPtr<ParentType> parent)
{
return adoptRef(new JSSVGStaticPODTypeWrapperWithPODTypeParent(type, parent));
}
virtual void commitChange(PODType type, DOMObject* wrapper)
{
JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, wrapper);
m_parentType->commitChange(ParentTypeArg(type), wrapper);
}
private:
JSSVGStaticPODTypeWrapperWithPODTypeParent(PODType type, PassRefPtr<ParentType> parent)
: JSSVGStaticPODTypeWrapper<PODType>(type)
, m_parentType(parent)
{
}
RefPtr<ParentType> m_parentType;
};
#if COMPILER(MSVC)
#pragma pack(16)
#endif
template<typename PODType, typename ParentType>
class JSSVGStaticPODTypeWrapperWithParent : public JSSVGPODTypeWrapper<PODType> {
public:
typedef PODType (ParentType::*GetterMethod)() const;
typedef void (ParentType::*SetterMethod)(const PODType&);
static PassRefPtr<JSSVGStaticPODTypeWrapperWithParent> create(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter)
{
return adoptRef(new JSSVGStaticPODTypeWrapperWithParent(parent, getter, setter));
}
virtual operator PODType()
{
return (m_parent.get()->*m_getter)();
}
virtual void commitChange(PODType type, DOMObject*)
{
(m_parent.get()->*m_setter)(type);
}
private:
JSSVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter)
: m_parent(parent)
, m_getter(getter)
, m_setter(setter)
{
ASSERT(m_parent);
ASSERT(m_getter);
ASSERT(m_setter);
}
RefPtr<ParentType> m_parent;
GetterMethod m_getter;
SetterMethod m_setter;
};
template<typename PODType>
class SVGPODListItem;
template<typename PODType>
class JSSVGPODTypeWrapperCreatorForList : public JSSVGPODTypeWrapper<PODType> {
public:
typedef SVGPODListItem<PODType> PODListItemPtrType;
typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const;
typedef void (SVGPODListItem<PODType>::*SetterMethod)(const PODType&);
static PassRefPtr<JSSVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName)
{
return adoptRef(new JSSVGPODTypeWrapperCreatorForList(creator, attributeName));
}
virtual operator PODType()
{
return (m_creator.get()->*m_getter)();
}
virtual void commitChange(PODType type, DOMObject* wrapper)
{
if (!m_setter)
return;
(m_creator.get()->*m_setter)(type);
JSSVGContextCache::propagateSVGDOMChange(wrapper, m_associatedAttributeName);
}
private:
JSSVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName)
: m_creator(creator)
, m_getter(&PODListItemPtrType::value)
, m_setter(&PODListItemPtrType::setValue)
, m_associatedAttributeName(attributeName)
{
ASSERT(m_creator);
ASSERT(m_getter);
ASSERT(m_setter);
}
RefPtr<PODListItemPtrType> m_creator;
GetterMethod m_getter;
SetterMethod m_setter;
const QualifiedName& m_associatedAttributeName;
};
template<typename PODType, typename PODTypeCreator>
struct PODTypeWrapperCacheInfo {
typedef PODType (PODTypeCreator::*GetterMethod)() const;
typedef void (PODTypeCreator::*SetterMethod)(const PODType&);
PODTypeWrapperCacheInfo()
: creator(0)
, getter(0)
, setter(0)
{
}
PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType)
: creator(reinterpret_cast<PODTypeCreator*>(-1))
, getter(0)
, setter(0)
{
}
bool isHashTableDeletedValue() const
{
return creator == reinterpret_cast<PODTypeCreator*>(-1);
}
PODTypeWrapperCacheInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter)
: creator(_creator)
, getter(_getter)
, setter(_setter)
{
ASSERT(creator);
ASSERT(getter);
}
bool operator==(const PODTypeWrapperCacheInfo& other) const
{
return creator == other.creator && getter == other.getter && setter == other.setter;
}
PODTypeCreator* creator;
GetterMethod getter;
SetterMethod setter;
};
template<typename PODType, typename PODTypeCreator>
struct PODTypeWrapperCacheInfoHash {
typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo;
static unsigned hash(const CacheInfo& info)
{
return StringImpl::computeHash(reinterpret_cast<const UChar*>(&info), sizeof(CacheInfo) / sizeof(UChar));
}
static bool equal(const CacheInfo& a, const CacheInfo& b)
{
return a == b;
}
static const bool safeToCompareToEmptyOrDeleted = true;
};
template<typename PODType, typename PODTypeCreator>
struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCacheInfo<PODType, PODTypeCreator> > {
typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo;
static const bool emptyValueIsZero = true;
static const bool needsDestruction = false;
static const CacheInfo& emptyValue()
{
DEFINE_STATIC_LOCAL(CacheInfo, key, ());
return key;
}
static void constructDeletedValue(CacheInfo& slot)
{
new (&slot) CacheInfo(WTF::HashTableDeletedValue);
}
static bool isDeletedValue(const CacheInfo& value)
{
return value.isHashTableDeletedValue();
}
};
template<typename PODType, typename PODTypeCreator>
class JSSVGDynamicPODTypeWrapperCache {
public:
typedef PODType (PODTypeCreator::*GetterMethod)() const;
typedef void (PODTypeCreator::*SetterMethod)(const PODType&);
typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo;
typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash;
typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits;
typedef JSSVGPODTypeWrapper<PODType> WrapperBase;
typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> Wrapper;
typedef HashMap<CacheInfo, Wrapper*, CacheInfoHash, CacheInfoTraits> WrapperMap;
static WrapperMap& wrapperMap()
{
DEFINE_STATIC_LOCAL(WrapperMap, s_wrapperMap, ());
return s_wrapperMap;
}
static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter)
{
CacheInfo info(creator, getter, setter);
pair<typename WrapperMap::iterator, bool> result = wrapperMap().add(info, 0);
if (!result.second) return result.first->second;
RefPtr<Wrapper> wrapper = Wrapper::create(creator, getter, setter);
result.first->second = wrapper.get();
return wrapper.release();
}
static void forgetWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter)
{
CacheInfo info(creator, getter, setter);
wrapperMap().remove(info);
}
};
template<typename PODType, typename PODTypeCreator>
JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::~JSSVGDynamicPODTypeWrapper()
{
JSSVGDynamicPODTypeWrapperCache<PODType, PODTypeCreator>::forgetWrapper(m_creator.get(), m_getter, m_setter);
}
}
#endif // ENABLE(SVG)
#endif // JSSVGPODTypeWrapper_h