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