• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2008 Apple Inc. All rights reserved.
4  * Copyright (C) 2008, 2009 Google. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef V8SVGPODTypeWrapper_h
29 #define V8SVGPODTypeWrapper_h
30 
31 #if ENABLE(SVG)
32 
33 #include <utility>
34 
35 #include "SVGElement.h"
36 #include "SVGList.h"
37 #include "V8Proxy.h"
38 
39 #include <wtf/Assertions.h>
40 #include <wtf/HashFunctions.h>
41 #include <wtf/HashMap.h>
42 #include <wtf/RefCounted.h>
43 #include <wtf/StdLibExtras.h>
44 
45 namespace WebCore {
46 
47 template<typename PODType>
48 class V8SVGPODTypeWrapper : public RefCounted<V8SVGPODTypeWrapper<PODType> > {
49 public:
V8SVGPODTypeWrapper()50     V8SVGPODTypeWrapper() { }
~V8SVGPODTypeWrapper()51     virtual ~V8SVGPODTypeWrapper() { }
52     virtual operator PODType() = 0;
53     virtual void commitChange(PODType, SVGElement*) = 0;
54 };
55 
56 template<typename PODType>
57 class V8SVGPODTypeWrapperCreatorForList : public V8SVGPODTypeWrapper<PODType> {
58 public:
59     typedef SVGPODListItem<PODType> PODListItemPtrType;
60 
61     typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const;
62     typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType);
63 
create(PassRefPtr<PODListItemPtrType> creator,const QualifiedName & attributeName)64     static PassRefPtr<V8SVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName)
65     {
66         return adoptRef(new V8SVGPODTypeWrapperCreatorForList(creator, attributeName));
67     }
68 
~V8SVGPODTypeWrapperCreatorForList()69     virtual ~V8SVGPODTypeWrapperCreatorForList() { }
70 
71     // Getter wrapper
PODType()72     virtual operator PODType() { return (m_creator.get()->*m_getter)(); }
73 
74     // Setter wrapper
commitChange(PODType type,SVGElement * context)75     virtual void commitChange(PODType type, SVGElement* context)
76     {
77         if (!m_setter)
78             return;
79 
80         (m_creator.get()->*m_setter)(type);
81 
82         if (context)
83             context->svgAttributeChanged(m_associatedAttributeName);
84     }
85 
86 private:
V8SVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator,const QualifiedName & attributeName)87     V8SVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName)
88         : m_creator(creator)
89         , m_getter(&SVGPODListItem<PODType>::value)
90         , m_setter(&SVGPODListItem<PODType>::setValue)
91         , m_associatedAttributeName(attributeName)
92     {
93         ASSERT(m_creator);
94         ASSERT(m_getter);
95         ASSERT(m_setter);
96     }
97 
98     // Update callbacks
99     RefPtr<SVGPODListItem<PODType> > m_creator;
100     GetterMethod m_getter;
101     SetterMethod m_setter;
102     const QualifiedName& m_associatedAttributeName;
103 };
104 
105 template<typename PODType>
106 class V8SVGStaticPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> {
107 public:
create(PODType type)108     static PassRefPtr<V8SVGStaticPODTypeWrapper> create(PODType type)
109     {
110         return adoptRef(new V8SVGStaticPODTypeWrapper(type));
111     }
112 
~V8SVGStaticPODTypeWrapper()113     virtual ~V8SVGStaticPODTypeWrapper() { }
114 
115     // Getter wrapper
PODType()116     virtual operator PODType() { return m_podType; }
117 
118     // Setter wrapper
commitChange(PODType type,SVGElement *)119     virtual void commitChange(PODType type, SVGElement*)
120     {
121         m_podType = type;
122     }
123 
124 protected:
V8SVGStaticPODTypeWrapper(PODType type)125     V8SVGStaticPODTypeWrapper(PODType type)
126         : m_podType(type)
127     {
128     }
129 
130     PODType m_podType;
131 };
132 
133 template<typename PODType, typename ParentTypeArg>
134 class V8SVGStaticPODTypeWrapperWithPODTypeParent : public V8SVGStaticPODTypeWrapper<PODType> {
135 public:
136     typedef V8SVGPODTypeWrapper<ParentTypeArg> ParentType;
137 
create(PODType type,PassRefPtr<ParentType> parent)138     static PassRefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent> create(PODType type, PassRefPtr<ParentType> parent)
139     {
140         return adoptRef(new V8SVGStaticPODTypeWrapperWithPODTypeParent(type, parent));
141     }
142 
commitChange(PODType type,SVGElement * context)143     virtual void commitChange(PODType type, SVGElement* context)
144     {
145         V8SVGStaticPODTypeWrapper<PODType>::commitChange(type, context);
146         m_parentType->commitChange(ParentTypeArg(type), context);
147     }
148 
149 private:
V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type,PassRefPtr<ParentType> parent)150     V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type, PassRefPtr<ParentType> parent)
151         : V8SVGStaticPODTypeWrapper<PODType>(type)
152         , m_parentType(parent)
153     {
154     }
155 
156     RefPtr<ParentType> m_parentType;
157 };
158 
159 template<typename PODType, typename ParentType>
160 class V8SVGStaticPODTypeWrapperWithParent : public V8SVGPODTypeWrapper<PODType> {
161 public:
162     typedef PODType (ParentType::*GetterMethod)() const;
163     typedef void (ParentType::*SetterMethod)(const PODType&);
164 
create(PassRefPtr<ParentType> parent,GetterMethod getter,SetterMethod setter)165     static PassRefPtr<V8SVGStaticPODTypeWrapperWithParent> create(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter)
166     {
167         return adoptRef(new V8SVGStaticPODTypeWrapperWithParent(parent, getter, setter));
168     }
169 
PODType()170     virtual operator PODType()
171     {
172         return (m_parent.get()->*m_getter)();
173     }
174 
commitChange(PODType type,SVGElement * context)175     virtual void commitChange(PODType type, SVGElement* context)
176     {
177         (m_parent.get()->*m_setter)(type);
178     }
179 
180 private:
V8SVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent,GetterMethod getter,SetterMethod setter)181     V8SVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter)
182         : m_parent(parent)
183         , m_getter(getter)
184         , m_setter(setter)
185     {
186         ASSERT(m_parent);
187         ASSERT(m_getter);
188         ASSERT(m_setter);
189     }
190 
191     RefPtr<ParentType> m_parent;
192     GetterMethod m_getter;
193     SetterMethod m_setter;
194 };
195 
196 template<typename PODType, typename PODTypeCreator>
197 class V8SVGDynamicPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> {
198 public:
199     typedef PODType (PODTypeCreator::*GetterMethod)() const;
200     typedef void (PODTypeCreator::*SetterMethod)(PODType);
201     typedef void (*CacheRemovalCallback)(V8SVGPODTypeWrapper<PODType>*);
202 
create(PassRefPtr<PODTypeCreator> creator,GetterMethod getter,SetterMethod setter,CacheRemovalCallback cacheRemovalCallback)203     static PassRefPtr<V8SVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback)
204     {
205         return adoptRef(new V8SVGDynamicPODTypeWrapper(creator, getter, setter, cacheRemovalCallback));
206     }
207 
~V8SVGDynamicPODTypeWrapper()208     virtual ~V8SVGDynamicPODTypeWrapper() {
209         ASSERT(m_cacheRemovalCallback);
210 
211         (*m_cacheRemovalCallback)(this);
212     }
213 
214     // Getter wrapper
PODType()215     virtual operator PODType() { return (m_creator.get()->*m_getter)(); }
216 
217     // Setter wrapper
commitChange(PODType type,SVGElement * context)218     virtual void commitChange(PODType type, SVGElement* context)
219     {
220         (m_creator.get()->*m_setter)(type);
221 
222         if (context)
223             context->svgAttributeChanged(m_creator->associatedAttributeName());
224     }
225 
226 private:
V8SVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator,GetterMethod getter,SetterMethod setter,CacheRemovalCallback cacheRemovalCallback)227     V8SVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback)
228         : m_creator(creator)
229         , m_getter(getter)
230         , m_setter(setter)
231         , m_cacheRemovalCallback(cacheRemovalCallback)
232     {
233         ASSERT(m_creator);  // |creator|'s pointer was taken by m_creator.
234         ASSERT(getter);
235         ASSERT(setter);
236         ASSERT(cacheRemovalCallback);
237     }
238 
239     // Update callbacks
240     RefPtr<PODTypeCreator> m_creator;
241     GetterMethod m_getter;
242     SetterMethod m_setter;
243     CacheRemovalCallback m_cacheRemovalCallback;
244 };
245 
246 // Caching facilities
247 template<typename PODType, typename PODTypeCreator>
248 struct PODTypeWrapperCacheInfo {
249     typedef PODType (PODTypeCreator::*GetterMethod)() const;
250     typedef void (PODTypeCreator::*SetterMethod)(PODType);
251 
252     // Empty value
PODTypeWrapperCacheInfoPODTypeWrapperCacheInfo253     PODTypeWrapperCacheInfo()
254         : creator(0)
255         , getter(0)
256         , setter(0)
257         , fieldHash(0)
258     { }
259 
260     // Deleted value
PODTypeWrapperCacheInfoPODTypeWrapperCacheInfo261     explicit PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType)
262         : creator(reinterpret_cast<PODTypeCreator*>(-1))
263         , getter(0)
264         , setter(0)
265         , fieldHash(0)
266     {
267     }
268 
isHashTableDeletedValuePODTypeWrapperCacheInfo269     bool isHashTableDeletedValue() const
270     {
271         return creator == reinterpret_cast<PODTypeCreator*>(-1);
272     }
273 
PODTypeWrapperCacheInfoPODTypeWrapperCacheInfo274     PODTypeWrapperCacheInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter, unsigned _fieldHash)
275         : creator(_creator)
276         , getter(_getter)
277         , setter(_setter)
278         , fieldHash(_fieldHash)
279     {
280         ASSERT(creator);
281         ASSERT(getter);
282     }
283 
284     bool operator==(const PODTypeWrapperCacheInfo& other) const
285     {
286         return creator == other.creator && fieldHash == other.fieldHash && getter == other.getter && setter == other.setter;
287     }
288 
289     PODTypeCreator* creator;
290     GetterMethod getter;
291     SetterMethod setter;
292     unsigned fieldHash;
293 };
294 
295 template<typename PODType, typename PODTypeCreator>
296 struct PODTypeWrapperCacheInfoHash {
hashPODTypeWrapperCacheInfoHash297     static unsigned hash(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& info)
298     {
299         // We can't hash member function pointers, but we have enough material
300         // to hash the pointer and field identifier, and on a collision
301         // operator== will still differentiate the member function pointers.
302         return WTF::PairHash<void*, unsigned>::hash(std::pair<void*, unsigned>(info.creator, info.fieldHash));
303     }
304 
equalPODTypeWrapperCacheInfoHash305     static bool equal(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& a, const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& b)
306     {
307         return a == b;
308     }
309 
310     static const bool safeToCompareToEmptyOrDeleted = true;
311 };
312 
313 template<typename PODType, typename PODTypeCreator>
314 struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCacheInfo<PODType, PODTypeCreator> > {
315     typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo;
316 
317     static const bool emptyValueIsZero = true;
318     static const bool needsDestruction = false;
319 
emptyValuePODTypeWrapperCacheInfoTraits320     static const CacheInfo& emptyValue()
321     {
322         DEFINE_STATIC_LOCAL(CacheInfo, key, ());
323         return key;
324     }
325 
constructDeletedValuePODTypeWrapperCacheInfoTraits326     static void constructDeletedValue(CacheInfo& slot)
327     {
328         new (&slot) CacheInfo(WTF::HashTableDeletedValue);
329     }
330 
isDeletedValuePODTypeWrapperCacheInfoTraits331     static bool isDeletedValue(const CacheInfo& value)
332     {
333         return value.isHashTableDeletedValue();
334     }
335 };
336 
337 template<typename PODType, typename PODTypeCreator>
338 class V8SVGDynamicPODTypeWrapperCache {
339 public:
340     typedef PODType (PODTypeCreator::*GetterMethod)() const;
341     typedef void (PODTypeCreator::*SetterMethod)(PODType);
342 
343     typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo;
344     typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash;
345     typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits;
346 
347     typedef V8SVGPODTypeWrapper<PODType> WrapperBase;
348     typedef V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper;
349 
350     typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap;
351     typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator;
352 
dynamicWrapperHashMap()353     static DynamicWrapperHashMap& dynamicWrapperHashMap()
354     {
355         DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, dynamicWrapperHashMap, ());
356         return dynamicWrapperHashMap;
357     }
358 
359     // Used for readwrite attributes only
lookupOrCreateWrapper(PODTypeCreator * creator,GetterMethod getter,SetterMethod setter,unsigned fieldHash)360     static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter, unsigned fieldHash)
361     {
362         DynamicWrapperHashMap& map(dynamicWrapperHashMap());
363         CacheInfo info(creator, getter, setter, fieldHash);
364 
365         if (map.contains(info))
366             return map.get(info);
367 
368         RefPtr<DynamicWrapper> wrapper = V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::create(creator, getter, setter, forgetWrapper);
369         map.set(info, wrapper.get());
370         return wrapper.release();
371     }
372 
forgetWrapper(V8SVGPODTypeWrapper<PODType> * wrapper)373     static void forgetWrapper(V8SVGPODTypeWrapper<PODType>* wrapper)
374     {
375         DynamicWrapperHashMap& map(dynamicWrapperHashMap());
376 
377         DynamicWrapperHashMapIterator it = map.begin();
378         DynamicWrapperHashMapIterator end = map.end();
379 
380         for (; it != end; ++it) {
381             if (it->second != wrapper)
382                 continue;
383 
384             // It's guaranteed that there's just one object we need to take care of.
385             map.remove(it->first);
386             break;
387         }
388     }
389 };
390 
391 class V8SVGPODTypeUtil {
392 public:
393     template <class P>
394     static P toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok);
395 };
396 
397 template <class P>
toSVGPODType(V8ClassIndex::V8WrapperType type,v8::Handle<v8::Value> object,bool & ok)398 P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok)
399 {
400     void *wrapper = V8DOMWrapper::convertToSVGPODTypeImpl(type, object);
401     if (wrapper == NULL) {
402         ok = false;
403         return P();
404     } else {
405         ok = true;
406         return *static_cast<V8SVGPODTypeWrapper<P>*>(wrapper);
407     }
408 }
409 
410 } // namespace WebCore
411 
412 #endif // ENABLE(SVG)
413 #endif // V8SVGPODTypeWrapper_h
414