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