rsaenh/tests: Adjust length value to pass on Win 10.
[wine/multimedia.git] / dlls / windowscodecs / clipper.c
blob6f8a05b1ad2e0cb829518a0de73d5ca8dd72fbf9
1 /*
2 * Copyright 2013 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "wincodec.h"
28 #include "wincodecs_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
34 typedef struct BitmapClipper {
35 IWICBitmapClipper IWICBitmapClipper_iface;
36 LONG ref;
37 IWICBitmapSource *source;
38 WICRect rect;
39 CRITICAL_SECTION lock; /* must be held when initialized */
40 } BitmapClipper;
42 static inline BitmapClipper *impl_from_IWICBitmapClipper(IWICBitmapClipper *iface)
44 return CONTAINING_RECORD(iface, BitmapClipper, IWICBitmapClipper_iface);
47 static HRESULT WINAPI BitmapClipper_QueryInterface(IWICBitmapClipper *iface, REFIID iid,
48 void **ppv)
50 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
51 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
53 if (!ppv) return E_INVALIDARG;
55 if (IsEqualIID(&IID_IUnknown, iid) ||
56 IsEqualIID(&IID_IWICBitmapSource, iid) ||
57 IsEqualIID(&IID_IWICBitmapClipper, iid))
59 *ppv = &This->IWICBitmapClipper_iface;
61 else
63 *ppv = NULL;
64 return E_NOINTERFACE;
67 IUnknown_AddRef((IUnknown*)*ppv);
68 return S_OK;
71 static ULONG WINAPI BitmapClipper_AddRef(IWICBitmapClipper *iface)
73 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
74 ULONG ref = InterlockedIncrement(&This->ref);
76 TRACE("(%p) refcount=%u\n", iface, ref);
78 return ref;
81 static ULONG WINAPI BitmapClipper_Release(IWICBitmapClipper *iface)
83 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
84 ULONG ref = InterlockedDecrement(&This->ref);
86 TRACE("(%p) refcount=%u\n", iface, ref);
88 if (ref == 0)
90 This->lock.DebugInfo->Spare[0] = 0;
91 DeleteCriticalSection(&This->lock);
92 if (This->source) IWICBitmapSource_Release(This->source);
93 HeapFree(GetProcessHeap(), 0, This);
96 return ref;
99 static HRESULT WINAPI BitmapClipper_GetSize(IWICBitmapClipper *iface,
100 UINT *width, UINT *height)
102 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
104 TRACE("(%p,%p,%p)\n", iface, width, height);
106 if (!width || !height)
107 return E_INVALIDARG;
109 if (!This->source)
110 return WINCODEC_ERR_WRONGSTATE;
112 *width = This->rect.Width;
113 *height = This->rect.Height;
115 return S_OK;
118 static HRESULT WINAPI BitmapClipper_GetPixelFormat(IWICBitmapClipper *iface,
119 WICPixelFormatGUID *format)
121 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
122 TRACE("(%p,%p)\n", iface, format);
124 if (!format)
125 return E_INVALIDARG;
127 if (!This->source)
128 return WINCODEC_ERR_WRONGSTATE;
130 return IWICBitmapSource_GetPixelFormat(This->source, format);
133 static HRESULT WINAPI BitmapClipper_GetResolution(IWICBitmapClipper *iface,
134 double *dpiX, double *dpiY)
136 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
138 TRACE("(%p,%p,%p)\n", iface, dpiX, dpiY);
140 if (!dpiX || !dpiY)
141 return E_INVALIDARG;
143 if (!This->source)
144 return WINCODEC_ERR_WRONGSTATE;
146 return IWICBitmapSource_GetResolution(This->source, dpiX, dpiY);
149 static HRESULT WINAPI BitmapClipper_CopyPalette(IWICBitmapClipper *iface,
150 IWICPalette *palette)
152 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
154 TRACE("(%p,%p)\n", iface, palette);
156 if (!palette)
157 return E_INVALIDARG;
159 if (!This->source)
160 return WINCODEC_ERR_WRONGSTATE;
162 return IWICBitmapSource_CopyPalette(This->source, palette);
165 static HRESULT WINAPI BitmapClipper_CopyPixels(IWICBitmapClipper *iface,
166 const WICRect *rc, UINT stride, UINT buffer_size, BYTE *buffer)
168 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
169 WICRect rect;
171 TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, buffer_size, buffer);
173 if (!This->source)
174 return WINCODEC_ERR_WRONGSTATE;
176 if (rc)
178 rect = *rc;
180 /* transform to source coordinates */
181 rect.X += This->rect.X;
182 rect.Y += This->rect.Y;
184 if ((rect.X + rect.Width > This->rect.X + This->rect.Width) ||
185 (rect.Y + rect.Height > This->rect.Y + This->rect.Height))
186 return E_INVALIDARG;
188 rc = &rect;
190 else
191 rc = &This->rect;
193 return IWICBitmapSource_CopyPixels(This->source, rc, stride, buffer_size, buffer);
196 static HRESULT WINAPI BitmapClipper_Initialize(IWICBitmapClipper *iface,
197 IWICBitmapSource *source, const WICRect *rc)
199 BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
200 UINT width, height;
201 HRESULT hr = S_OK;
203 TRACE("(%p,%p,%p)\n", iface, source, rc);
205 EnterCriticalSection(&This->lock);
207 if (This->source)
209 hr = WINCODEC_ERR_WRONGSTATE;
210 goto end;
213 hr = IWICBitmapSource_GetSize(source, &width, &height);
214 if (FAILED(hr)) goto end;
216 if ((rc->X + rc->Width > width) || (rc->Y + rc->Height > height))
218 hr = E_INVALIDARG;
219 goto end;
222 This->rect = *rc;
223 This->source = source;
224 IWICBitmapSource_AddRef(This->source);
226 end:
227 LeaveCriticalSection(&This->lock);
229 return hr;
232 static const IWICBitmapClipperVtbl BitmapClipper_Vtbl = {
233 BitmapClipper_QueryInterface,
234 BitmapClipper_AddRef,
235 BitmapClipper_Release,
236 BitmapClipper_GetSize,
237 BitmapClipper_GetPixelFormat,
238 BitmapClipper_GetResolution,
239 BitmapClipper_CopyPalette,
240 BitmapClipper_CopyPixels,
241 BitmapClipper_Initialize
244 HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper)
246 BitmapClipper *This;
248 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapClipper));
249 if (!This) return E_OUTOFMEMORY;
251 This->IWICBitmapClipper_iface.lpVtbl = &BitmapClipper_Vtbl;
252 This->ref = 1;
253 This->source = NULL;
254 InitializeCriticalSection(&This->lock);
255 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapClipper.lock");
257 *clipper = &This->IWICBitmapClipper_iface;
259 return S_OK;