1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef GDIObject_h
27#define GDIObject_h
28
29#include <algorithm>
30#include <memory>
31#include <wtf/Assertions.h>
32#include <wtf/Noncopyable.h>
33#include <wtf/NullPtr.h>
34
35typedef struct HBITMAP__* HBITMAP;
36typedef struct HBRUSH__* HBRUSH;
37typedef struct HDC__* HDC;
38typedef struct HFONT__* HFONT;
39typedef struct HPALETTE__* HPALETTE;
40typedef struct HPEN__* HPEN;
41typedef struct HRGN__* HRGN;
42
43namespace WebCore {
44
45template<typename T> void deleteObject(T);
46
47template<typename T> class GDIObject {
48#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
49 // If rvalue references are not supported, the copy constructor is
50 // public so GDIObject cannot be marked noncopyable. See note below.
51 WTF_MAKE_NONCOPYABLE(GDIObject);
52#endif
53public:
54 typedef T ValueType;
55 typedef ValueType* PtrType;
56
57 GDIObject() : m_obj(0) { }
58 GDIObject(const T& obj) : m_obj(obj) { }
59
60 ~GDIObject() { deleteObject<T>(m_obj); }
61
62 PtrType get() const { return &m_obj; }
63 operator HGDIOBJ () { return static_cast<HGDIOBJ>(m_obj); }
64 operator ValueType () { return m_obj; }
65
66 void clear();
67 ValueType release() WARN_UNUSED_RETURN;
68
69 bool operator!() const { return !m_obj; }
70
71 // This conversion operator allows implicit conversion to bool but not to other integer types.
72 typedef PtrType GDIObject::*UnspecifiedBoolType;
73 operator UnspecifiedBoolType() const { return m_obj ? &GDIObject::m_obj : 0; }
74
75 GDIObject<T>& operator=(T);
76 GDIObject<T>& operator=(std::nullptr_t) { clear(); return *this; }
77
78#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
79 GDIObject(GDIObject&&);
80 template<typename U> GDIObject(GDIObject<U>&&);
81
82 GDIObject& operator=(GDIObject&&);
83 template<typename U> GDIObject& operator=(GDIObject<U>&&);
84#endif
85
86 void swap(GDIObject& o) { std::swap(m_obj, o.m_obj); }
87
88private:
89#if !COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
90 // If rvalue references are supported, noncopyable takes care of this.
91 GDIObject& operator=(const GDIObject&);
92#endif
93
94 // We should never have two GDIObjects for the same underlying object (otherwise we'll get
95 // double-destruction), so these equality operators should never be needed.
96 template<typename U> bool operator==(const GDIObject<U>&) { COMPILE_ASSERT(!sizeof(U*), GDIObjects_should_never_be_equal); return false; }
97 template<typename U> bool operator!=(const GDIObject<U>&) { COMPILE_ASSERT(!sizeof(U*), GDIObjects_should_never_be_equal); return false; }
98
99 T m_obj;
100};
101
102template<typename T> inline void GDIObject<T>::clear()
103{
104 ValueType ptr = m_obj;
105 m_obj = 0;
106 deleteObject(ptr);
107}
108
109template<typename T> inline T GDIObject<T>::release()
110{
111 ValueType obj = m_obj;
112 m_obj = 0;
113 return obj;
114}
115
116#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
117template<typename T> inline GDIObject<T>::GDIObject(GDIObject<T>&& o)
118 : m_obj(o.leakObject())
119{
120}
121
122template<typename T> inline GDIObject<T>& GDIObject<T>::operator=(GDIObject<T>&& o)
123{
124 ValueType obj = m_obj;
125 m_obj = o.leakObject();
126 ASSERT(!obj || m_obj != obj);
127 deleteObject(obj);
128
129 return *this;
130}
131#endif
132
133template<typename T> inline GDIObject<T>& GDIObject<T>::operator=(T o)
134{
135 ValueType obj = m_obj;
136 m_obj = o;
137 ASSERT(!obj || m_obj != obj);
138 deleteObject(obj);
139
140 return *this;
141}
142
143template<typename T> inline void swap(GDIObject<T>& a, GDIObject<T>& b)
144{
145 a.swap(b);
146}
147
148template<typename T, typename U> inline bool operator==(const GDIObject<T>& a, U* b)
149{
150 return a.get() == b;
151}
152
153template<typename T, typename U> inline bool operator==(T* a, const GDIObject<U>& b)
154{
155 return a == b.get();
156}
157
158template<typename T, typename U> inline bool operator!=(const GDIObject<T>& a, U* b)
159{
160 return a.get() != b;
161}
162
163template<typename T, typename U> inline bool operator!=(T* a, const GDIObject<U>& b)
164{
165 return a != b.get();
166}
167
168template<typename T> inline typename GDIObject<T>::PtrType getPtr(const GDIObject<T>& p)
169{
170 return p.get();
171}
172
173// Nearly all GDI types use the same DeleteObject call.
174template<typename T> inline void deleteObject<T>(T obj)
175{
176 if (obj)
177 ::DeleteObject(obj);
178}
179
180template<> inline void deleteObject<HDC>(HDC obj)
181{
182 if (obj)
183 ::DeleteDC(obj);
184}
185
186} // namespace WebCore
187
188using WebCore::GDIObject;
189
190#endif // GDIObject_h