1 /* 2 * Copyright 2013 Nikolay Sivov for CodeWeavers 3 * 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. 8 * 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. 13 * 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 17 */ 18 19 #include <stdarg.h> 20 21 #define COBJMACROS 22 23 #include "windef.h" 24 #include "winbase.h" 25 #include "objbase.h" 26 27 #include "wincodecs_private.h" 28 29 #include "wine/debug.h" 30 31 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 32 33 typedef struct BitmapClipper { 34 IWICBitmapClipper IWICBitmapClipper_iface; 35 LONG ref; 36 IWICBitmapSource *source; 37 WICRect rect; 38 CRITICAL_SECTION lock; /* must be held when initialized */ 39 } BitmapClipper; 40 41 static inline BitmapClipper *impl_from_IWICBitmapClipper(IWICBitmapClipper *iface) 42 { 43 return CONTAINING_RECORD(iface, BitmapClipper, IWICBitmapClipper_iface); 44 } 45 46 static HRESULT WINAPI BitmapClipper_QueryInterface(IWICBitmapClipper *iface, REFIID iid, 47 void **ppv) 48 { 49 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 50 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 51 52 if (!ppv) return E_INVALIDARG; 53 54 if (IsEqualIID(&IID_IUnknown, iid) || 55 IsEqualIID(&IID_IWICBitmapSource, iid) || 56 IsEqualIID(&IID_IWICBitmapClipper, iid)) 57 { 58 *ppv = &This->IWICBitmapClipper_iface; 59 } 60 else 61 { 62 *ppv = NULL; 63 return E_NOINTERFACE; 64 } 65 66 IUnknown_AddRef((IUnknown*)*ppv); 67 return S_OK; 68 } 69 70 static ULONG WINAPI BitmapClipper_AddRef(IWICBitmapClipper *iface) 71 { 72 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 73 ULONG ref = InterlockedIncrement(&This->ref); 74 75 TRACE("(%p) refcount=%u\n", iface, ref); 76 77 return ref; 78 } 79 80 static ULONG WINAPI BitmapClipper_Release(IWICBitmapClipper *iface) 81 { 82 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 83 ULONG ref = InterlockedDecrement(&This->ref); 84 85 TRACE("(%p) refcount=%u\n", iface, ref); 86 87 if (ref == 0) 88 { 89 This->lock.DebugInfo->Spare[0] = 0; 90 DeleteCriticalSection(&This->lock); 91 if (This->source) IWICBitmapSource_Release(This->source); 92 HeapFree(GetProcessHeap(), 0, This); 93 } 94 95 return ref; 96 } 97 98 static HRESULT WINAPI BitmapClipper_GetSize(IWICBitmapClipper *iface, 99 UINT *width, UINT *height) 100 { 101 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 102 103 TRACE("(%p,%p,%p)\n", iface, width, height); 104 105 if (!width || !height) 106 return E_INVALIDARG; 107 108 if (!This->source) 109 return WINCODEC_ERR_WRONGSTATE; 110 111 *width = This->rect.Width; 112 *height = This->rect.Height; 113 114 return S_OK; 115 } 116 117 static HRESULT WINAPI BitmapClipper_GetPixelFormat(IWICBitmapClipper *iface, 118 WICPixelFormatGUID *format) 119 { 120 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 121 TRACE("(%p,%p)\n", iface, format); 122 123 if (!format) 124 return E_INVALIDARG; 125 126 if (!This->source) 127 return WINCODEC_ERR_WRONGSTATE; 128 129 return IWICBitmapSource_GetPixelFormat(This->source, format); 130 } 131 132 static HRESULT WINAPI BitmapClipper_GetResolution(IWICBitmapClipper *iface, 133 double *dpiX, double *dpiY) 134 { 135 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 136 137 TRACE("(%p,%p,%p)\n", iface, dpiX, dpiY); 138 139 if (!dpiX || !dpiY) 140 return E_INVALIDARG; 141 142 if (!This->source) 143 return WINCODEC_ERR_WRONGSTATE; 144 145 return IWICBitmapSource_GetResolution(This->source, dpiX, dpiY); 146 } 147 148 static HRESULT WINAPI BitmapClipper_CopyPalette(IWICBitmapClipper *iface, 149 IWICPalette *palette) 150 { 151 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 152 153 TRACE("(%p,%p)\n", iface, palette); 154 155 if (!palette) 156 return E_INVALIDARG; 157 158 if (!This->source) 159 return WINCODEC_ERR_WRONGSTATE; 160 161 return IWICBitmapSource_CopyPalette(This->source, palette); 162 } 163 164 static HRESULT WINAPI BitmapClipper_CopyPixels(IWICBitmapClipper *iface, 165 const WICRect *rc, UINT stride, UINT buffer_size, BYTE *buffer) 166 { 167 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 168 WICRect rect; 169 170 TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, buffer_size, buffer); 171 172 if (!This->source) 173 return WINCODEC_ERR_WRONGSTATE; 174 175 if (rc) 176 { 177 rect = *rc; 178 179 /* transform to source coordinates */ 180 rect.X += This->rect.X; 181 rect.Y += This->rect.Y; 182 183 if ((rect.X + rect.Width > This->rect.X + This->rect.Width) || 184 (rect.Y + rect.Height > This->rect.Y + This->rect.Height)) 185 return E_INVALIDARG; 186 187 rc = ▭ 188 } 189 else 190 rc = &This->rect; 191 192 return IWICBitmapSource_CopyPixels(This->source, rc, stride, buffer_size, buffer); 193 } 194 195 static HRESULT WINAPI BitmapClipper_Initialize(IWICBitmapClipper *iface, 196 IWICBitmapSource *source, const WICRect *rc) 197 { 198 BitmapClipper *This = impl_from_IWICBitmapClipper(iface); 199 UINT width, height; 200 HRESULT hr = S_OK; 201 202 TRACE("(%p,%p,%p)\n", iface, source, rc); 203 204 EnterCriticalSection(&This->lock); 205 206 if (This->source) 207 { 208 hr = WINCODEC_ERR_WRONGSTATE; 209 goto end; 210 } 211 212 hr = IWICBitmapSource_GetSize(source, &width, &height); 213 if (FAILED(hr)) goto end; 214 215 if ((rc->X + rc->Width > width) || (rc->Y + rc->Height > height)) 216 { 217 hr = E_INVALIDARG; 218 goto end; 219 } 220 221 This->rect = *rc; 222 This->source = source; 223 IWICBitmapSource_AddRef(This->source); 224 225 end: 226 LeaveCriticalSection(&This->lock); 227 228 return hr; 229 } 230 231 static const IWICBitmapClipperVtbl BitmapClipper_Vtbl = { 232 BitmapClipper_QueryInterface, 233 BitmapClipper_AddRef, 234 BitmapClipper_Release, 235 BitmapClipper_GetSize, 236 BitmapClipper_GetPixelFormat, 237 BitmapClipper_GetResolution, 238 BitmapClipper_CopyPalette, 239 BitmapClipper_CopyPixels, 240 BitmapClipper_Initialize 241 }; 242 243 HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper) 244 { 245 BitmapClipper *This; 246 247 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapClipper)); 248 if (!This) return E_OUTOFMEMORY; 249 250 This->IWICBitmapClipper_iface.lpVtbl = &BitmapClipper_Vtbl; 251 This->ref = 1; 252 This->source = NULL; 253 InitializeCriticalSection(&This->lock); 254 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapClipper.lock"); 255 256 *clipper = &This->IWICBitmapClipper_iface; 257 258 return S_OK; 259 } 260