msxml3: Skip leading space characters when loading from BSTR.
[wine] / dlls / ddraw / clipper.c
1 /* DirectDrawClipper implementation
2  *
3  * Copyright 2000 (c) Marcus Meissner
4  * Copyright 2000 (c) TransGaming Technologies Inc.
5  * Copyright 2006 (c) Stefan Dösinger
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include "ddraw_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
28
29 static inline struct ddraw_clipper *impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
30 {
31     return CONTAINING_RECORD(iface, struct ddraw_clipper, IDirectDrawClipper_iface);
32 }
33
34 static HRESULT WINAPI ddraw_clipper_QueryInterface(IDirectDrawClipper *iface, REFIID iid, void **object)
35 {
36     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
37
38     TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
39
40     if (IsEqualGUID(&IID_IDirectDrawClipper, iid)
41             || IsEqualGUID(&IID_IUnknown, iid))
42     {
43         IDirectDrawClipper_AddRef(&clipper->IDirectDrawClipper_iface);
44         *object = &clipper->IDirectDrawClipper_iface;
45         return S_OK;
46     }
47
48     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
49     *object = NULL;
50
51     return E_NOINTERFACE;
52 }
53
54 static ULONG WINAPI ddraw_clipper_AddRef(IDirectDrawClipper *iface)
55 {
56     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
57     ULONG refcount = InterlockedIncrement(&clipper->ref);
58
59     TRACE("%p increasing refcount to %u.\n", clipper, refcount);
60
61     return refcount;
62 }
63
64 static ULONG WINAPI ddraw_clipper_Release(IDirectDrawClipper *iface)
65 {
66     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
67     ULONG refcount = InterlockedDecrement(&clipper->ref);
68
69     TRACE("%p decreasing refcount to %u.\n", clipper, refcount);
70
71     if (!refcount)
72         HeapFree(GetProcessHeap(), 0, clipper);
73
74     return refcount;
75 }
76
77 static HRESULT WINAPI ddraw_clipper_SetHWnd(IDirectDrawClipper *iface, DWORD flags, HWND window)
78 {
79     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
80
81     TRACE("iface %p, flags %#x, window %p.\n", iface, flags, window);
82
83     if (flags)
84     {
85         FIXME("flags %#x, not supported.\n", flags);
86         return DDERR_INVALIDPARAMS;
87     }
88
89     wined3d_mutex_lock();
90     clipper->window = window;
91     wined3d_mutex_unlock();
92
93     return DD_OK;
94 }
95
96 /*****************************************************************************
97  * IDirectDrawClipper::GetClipList
98  *
99  * Retrieve a copy of the clip list
100  *
101  * Arguments:
102  *  rect: Rectangle to be used to clip the clip list or NULL for the
103  *      entire clip list.
104  *  clip_list: structure for the resulting copy of the clip list.
105  *      If NULL, fills Size up to the number of bytes necessary to hold
106  *      the entire clip.
107  *  clip_list_size: Size of resulting clip list; size of the buffer at clip_list
108  *      or, if clip_list is NULL, receives the required size of the buffer
109  *      in bytes.
110  *
111  * RETURNS
112  *  Either DD_OK or DDERR_*
113  ************************************************************************/
114 static HRESULT WINAPI ddraw_clipper_GetClipList(IDirectDrawClipper *iface, RECT *rect,
115         RGNDATA *clip_list, DWORD *clip_list_size)
116 {
117     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
118     static unsigned int once;
119
120     TRACE("iface %p, rect %s, clip_list %p, clip_list_size %p.\n",
121             iface, wine_dbgstr_rect(rect), clip_list, clip_list_size);
122
123     wined3d_mutex_lock();
124
125     if (clipper->window)
126     {
127         HDC dc = GetDCEx(clipper->window, NULL, DCX_WINDOW);
128         if (dc)
129         {
130             HRGN rgn = CreateRectRgn(0, 0, 0, 0);
131             if (GetRandomRgn(dc, rgn, SYSRGN))
132             {
133                 if (GetVersion() & 0x80000000)
134                 {
135                     POINT origin;
136                     GetDCOrgEx(dc, &origin);
137                     OffsetRgn(rgn, origin.x, origin.y);
138                 }
139                 if (rect)
140                 {
141                     HRGN clip_rgn = CreateRectRgn(rect->left, rect->top,
142                             rect->right, rect->bottom);
143                     CombineRgn(rgn, rgn, clip_rgn, RGN_AND);
144                     DeleteObject(clip_rgn);
145                 }
146                 *clip_list_size = GetRegionData(rgn, *clip_list_size, clip_list);
147             }
148             DeleteObject(rgn);
149             ReleaseDC(clipper->window, dc);
150         }
151
152         wined3d_mutex_unlock();
153         return DD_OK;
154     }
155
156     if (!once++)
157         FIXME("clipper %p, rect %s, clip_list %p, clip_list_size %p stub!\n",
158                 clipper, wine_dbgstr_rect(rect), clip_list, clip_list_size);
159
160     if (clip_list_size)
161         *clip_list_size = 0;
162
163     wined3d_mutex_unlock();
164     return DDERR_NOCLIPLIST;
165 }
166
167 /*****************************************************************************
168  * IDirectDrawClipper::SetClipList
169  *
170  * Sets or deletes (if region is NULL) the clip list
171  *
172  * This implementation is a stub and returns DD_OK always to make the app
173  * happy.
174  *
175  * PARAMS
176  *  region  Pointer to a LRGNDATA structure or NULL
177  *  flags   not used, must be 0
178  * RETURNS
179  *  Either DD_OK or DDERR_*
180  *****************************************************************************/
181 static HRESULT WINAPI ddraw_clipper_SetClipList(IDirectDrawClipper *iface, RGNDATA *region, DWORD flags)
182 {
183     FIXME("iface %p, region %p, flags %#x stub!\n", iface, region, flags);
184
185     return DD_OK;
186 }
187
188 static HRESULT WINAPI ddraw_clipper_GetHWnd(IDirectDrawClipper *iface, HWND *window)
189 {
190     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
191
192     TRACE("iface %p, window %p.\n", iface, window);
193
194     wined3d_mutex_lock();
195     *window = clipper->window;
196     wined3d_mutex_unlock();
197
198     return DD_OK;
199 }
200
201 static HRESULT WINAPI ddraw_clipper_Initialize(IDirectDrawClipper *iface,
202         IDirectDraw *ddraw, DWORD flags)
203 {
204     struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
205
206     TRACE("iface %p, ddraw %p, flags %#x.\n", iface, ddraw, flags);
207
208     wined3d_mutex_lock();
209     if (clipper->initialized)
210     {
211         wined3d_mutex_unlock();
212         return DDERR_ALREADYINITIALIZED;
213     }
214
215     clipper->initialized = TRUE;
216     wined3d_mutex_unlock();
217
218     return DD_OK;
219 }
220
221 static HRESULT WINAPI ddraw_clipper_IsClipListChanged(IDirectDrawClipper *iface, BOOL *changed)
222 {
223     FIXME("iface %p, changed %p stub!\n", iface, changed);
224
225     /* XXX What is safest? */
226     *changed = FALSE;
227
228     return DD_OK;
229 }
230
231 static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl =
232 {
233     ddraw_clipper_QueryInterface,
234     ddraw_clipper_AddRef,
235     ddraw_clipper_Release,
236     ddraw_clipper_GetClipList,
237     ddraw_clipper_GetHWnd,
238     ddraw_clipper_Initialize,
239     ddraw_clipper_IsClipListChanged,
240     ddraw_clipper_SetClipList,
241     ddraw_clipper_SetHWnd,
242 };
243
244 HRESULT ddraw_clipper_init(struct ddraw_clipper *clipper)
245 {
246     clipper->IDirectDrawClipper_iface.lpVtbl = &ddraw_clipper_vtbl;
247     clipper->ref = 1;
248
249     return DD_OK;
250 }
251
252 struct ddraw_clipper *unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
253 {
254     if (!iface)
255         return NULL;
256     assert(iface->lpVtbl == &ddraw_clipper_vtbl);
257
258     return impl_from_IDirectDrawClipper(iface);
259 }