| /* |
| * Copyright 2010 Damjan Jovanovic |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| #include "wine/port.h" |
| |
| #include <stdarg.h> |
| |
| #ifdef HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H |
| #define GetCurrentProcess GetCurrentProcess_Mac |
| #define GetCurrentThread GetCurrentThread_Mac |
| #define LoadResource LoadResource_Mac |
| #define AnimatePalette AnimatePalette_Mac |
| #define EqualRgn EqualRgn_Mac |
| #define FillRgn FillRgn_Mac |
| #define FrameRgn FrameRgn_Mac |
| #define GetPixel GetPixel_Mac |
| #define InvertRgn InvertRgn_Mac |
| #define LineTo LineTo_Mac |
| #define OffsetRgn OffsetRgn_Mac |
| #define PaintRgn PaintRgn_Mac |
| #define Polygon Polygon_Mac |
| #define ResizePalette ResizePalette_Mac |
| #define SetRectRgn SetRectRgn_Mac |
| #define EqualRect EqualRect_Mac |
| #define FillRect FillRect_Mac |
| #define FrameRect FrameRect_Mac |
| #define GetCursor GetCursor_Mac |
| #define InvertRect InvertRect_Mac |
| #define OffsetRect OffsetRect_Mac |
| #define PtInRect PtInRect_Mac |
| #define SetCursor SetCursor_Mac |
| #define SetRect SetRect_Mac |
| #define ShowCursor ShowCursor_Mac |
| #define UnionRect UnionRect_Mac |
| #include <ApplicationServices/ApplicationServices.h> |
| #undef GetCurrentProcess |
| #undef GetCurrentThread |
| #undef LoadResource |
| #undef AnimatePalette |
| #undef EqualRgn |
| #undef FillRgn |
| #undef FrameRgn |
| #undef GetPixel |
| #undef InvertRgn |
| #undef LineTo |
| #undef OffsetRgn |
| #undef PaintRgn |
| #undef Polygon |
| #undef ResizePalette |
| #undef SetRectRgn |
| #undef EqualRect |
| #undef FillRect |
| #undef FrameRect |
| #undef GetCursor |
| #undef InvertRect |
| #undef OffsetRect |
| #undef PtInRect |
| #undef SetCursor |
| #undef SetRect |
| #undef ShowCursor |
| #undef UnionRect |
| #undef DPRINTF |
| #endif |
| |
| #define COBJMACROS |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "objbase.h" |
| |
| #include "wincodecs_private.h" |
| |
| #include "wine/debug.h" |
| #include "wine/library.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); |
| |
| #if defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) && \ |
| MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4 |
| |
| typedef struct IcnsEncoder { |
| IWICBitmapEncoder IWICBitmapEncoder_iface; |
| LONG ref; |
| IStream *stream; |
| IconFamilyHandle icns_family; |
| BOOL any_frame_committed; |
| int outstanding_commits; |
| BOOL committed; |
| CRITICAL_SECTION lock; |
| } IcnsEncoder; |
| |
| static inline IcnsEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface) |
| { |
| return CONTAINING_RECORD(iface, IcnsEncoder, IWICBitmapEncoder_iface); |
| } |
| |
| typedef struct IcnsFrameEncode { |
| IWICBitmapFrameEncode IWICBitmapFrameEncode_iface; |
| IcnsEncoder *encoder; |
| LONG ref; |
| BOOL initialized; |
| UINT size; |
| OSType icns_type; |
| BYTE* icns_image; |
| int lines_written; |
| BOOL committed; |
| } IcnsFrameEncode; |
| |
| static inline IcnsFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface) |
| { |
| return CONTAINING_RECORD(iface, IcnsFrameEncode, IWICBitmapFrameEncode_iface); |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, |
| void **ppv) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); |
| |
| if (!ppv) return E_INVALIDARG; |
| |
| if (IsEqualIID(&IID_IUnknown, iid) || |
| IsEqualIID(&IID_IWICBitmapFrameEncode, iid)) |
| { |
| *ppv = &This->IWICBitmapFrameEncode_iface; |
| } |
| else |
| { |
| *ppv = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| IUnknown_AddRef((IUnknown*)*ppv); |
| return S_OK; |
| } |
| |
| static ULONG WINAPI IcnsFrameEncode_AddRef(IWICBitmapFrameEncode *iface) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) refcount=%u\n", iface, ref); |
| |
| return ref; |
| } |
| |
| static ULONG WINAPI IcnsFrameEncode_Release(IWICBitmapFrameEncode *iface) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p) refcount=%u\n", iface, ref); |
| |
| if (ref == 0) |
| { |
| if (!This->committed) |
| { |
| EnterCriticalSection(&This->encoder->lock); |
| This->encoder->outstanding_commits--; |
| LeaveCriticalSection(&This->encoder->lock); |
| } |
| HeapFree(GetProcessHeap(), 0, This->icns_image); |
| |
| IWICBitmapEncoder_Release(&This->encoder->IWICBitmapEncoder_iface); |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_Initialize(IWICBitmapFrameEncode *iface, |
| IPropertyBag2 *pIEncoderOptions) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p,%p)\n", iface, pIEncoderOptions); |
| |
| EnterCriticalSection(&This->encoder->lock); |
| |
| if (This->initialized) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| This->initialized = TRUE; |
| |
| end: |
| LeaveCriticalSection(&This->encoder->lock); |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_SetSize(IWICBitmapFrameEncode *iface, |
| UINT uiWidth, UINT uiHeight) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight); |
| |
| EnterCriticalSection(&This->encoder->lock); |
| |
| if (!This->initialized || This->icns_image) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| |
| if (uiWidth != uiHeight) |
| { |
| WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth, uiHeight); |
| hr = E_INVALIDARG; |
| goto end; |
| } |
| |
| switch (uiWidth) |
| { |
| case 16: |
| case 32: |
| case 48: |
| case 128: |
| case 256: |
| case 512: |
| break; |
| default: |
| WARN("cannot generate ICNS icon from %dx%d image\n", This->size, This->size); |
| hr = E_INVALIDARG; |
| goto end; |
| } |
| |
| This->size = uiWidth; |
| |
| end: |
| LeaveCriticalSection(&This->encoder->lock); |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_SetResolution(IWICBitmapFrameEncode *iface, |
| double dpiX, double dpiY) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY); |
| |
| EnterCriticalSection(&This->encoder->lock); |
| |
| if (!This->initialized || This->icns_image) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| |
| end: |
| LeaveCriticalSection(&This->encoder->lock); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface, |
| WICPixelFormatGUID *pPixelFormat) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat)); |
| |
| EnterCriticalSection(&This->encoder->lock); |
| |
| if (!This->initialized || This->icns_image) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| |
| memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)); |
| |
| end: |
| LeaveCriticalSection(&This->encoder->lock); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface, |
| UINT cCount, IWICColorContext **ppIColorContext) |
| { |
| FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, |
| IWICPalette *pIPalette) |
| { |
| FIXME("(%p,%p): stub\n", iface, pIPalette); |
| return WINCODEC_ERR_UNSUPPORTEDOPERATION; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface, |
| IWICBitmapSource *pIThumbnail) |
| { |
| FIXME("(%p,%p): stub\n", iface, pIThumbnail); |
| return WINCODEC_ERR_UNSUPPORTEDOPERATION; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, |
| UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| HRESULT hr = S_OK; |
| UINT i; |
| |
| TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels); |
| |
| EnterCriticalSection(&This->encoder->lock); |
| |
| if (!This->initialized || !This->size) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| if (lineCount == 0 || lineCount + This->lines_written > This->size) |
| { |
| hr = E_INVALIDARG; |
| goto end; |
| } |
| |
| if (!This->icns_image) |
| { |
| switch (This->size) |
| { |
| case 16: This->icns_type = kIconServices16PixelDataARGB; break; |
| case 32: This->icns_type = kIconServices32PixelDataARGB; break; |
| case 48: This->icns_type = kIconServices48PixelDataARGB; break; |
| case 128: This->icns_type = kIconServices128PixelDataARGB; break; |
| case 256: This->icns_type = kIconServices256PixelDataARGB; break; |
| case 512: This->icns_type = kIconServices512PixelDataARGB; break; |
| default: |
| WARN("cannot generate ICNS icon from %dx%d image\n", This->size, This->size); |
| hr = E_INVALIDARG; |
| goto end; |
| } |
| This->icns_image = HeapAlloc(GetProcessHeap(), 0, This->size * This->size * 4); |
| if (!This->icns_image) |
| { |
| WARN("failed to allocate image buffer\n"); |
| hr = E_FAIL; |
| goto end; |
| } |
| } |
| |
| for (i = 0; i < lineCount; i++) |
| { |
| BYTE *src_row, *dst_row; |
| UINT j; |
| src_row = pbPixels + cbStride * i; |
| dst_row = This->icns_image + (This->lines_written + i)*(This->size*4); |
| /* swap bgr -> rgb */ |
| for (j = 0; j < This->size*4; j += 4) |
| { |
| dst_row[j] = src_row[j+3]; |
| dst_row[j+1] = src_row[j+2]; |
| dst_row[j+2] = src_row[j+1]; |
| dst_row[j+3] = src_row[j]; |
| } |
| } |
| This->lines_written += lineCount; |
| |
| end: |
| LeaveCriticalSection(&This->encoder->lock); |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface, |
| IWICBitmapSource *pIBitmapSource, WICRect *prc) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| HRESULT hr; |
| |
| TRACE("(%p,%p,%p)\n", iface, pIBitmapSource, prc); |
| |
| if (!This->initialized) |
| return WINCODEC_ERR_WRONGSTATE; |
| |
| hr = configure_write_source(iface, pIBitmapSource, prc, |
| &GUID_WICPixelFormat32bppBGRA, This->size, This->size, |
| 1.0, 1.0); |
| |
| if (SUCCEEDED(hr)) |
| { |
| hr = write_source(iface, pIBitmapSource, prc, |
| &GUID_WICPixelFormat32bppBGRA, 32, This->size, This->size); |
| } |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_Commit(IWICBitmapFrameEncode *iface) |
| { |
| IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); |
| Handle handle; |
| OSErr ret; |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p)\n", iface); |
| |
| EnterCriticalSection(&This->encoder->lock); |
| |
| if (!This->icns_image || This->lines_written != This->size || This->committed) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| |
| ret = PtrToHand(This->icns_image, &handle, This->size * This->size * 4); |
| if (ret != noErr || !handle) |
| { |
| WARN("PtrToHand failed with error %d\n", ret); |
| hr = E_FAIL; |
| goto end; |
| } |
| |
| ret = SetIconFamilyData(This->encoder->icns_family, This->icns_type, handle); |
| DisposeHandle(handle); |
| |
| if (ret != noErr) |
| { |
| WARN("SetIconFamilyData failed for image with error %d\n", ret); |
| hr = E_FAIL; |
| goto end; |
| } |
| |
| This->committed = TRUE; |
| This->encoder->any_frame_committed = TRUE; |
| This->encoder->outstanding_commits--; |
| |
| end: |
| LeaveCriticalSection(&This->encoder->lock); |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, |
| IWICMetadataQueryWriter **ppIMetadataQueryWriter) |
| { |
| FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter); |
| return E_NOTIMPL; |
| } |
| |
| static const IWICBitmapFrameEncodeVtbl IcnsEncoder_FrameVtbl = { |
| IcnsFrameEncode_QueryInterface, |
| IcnsFrameEncode_AddRef, |
| IcnsFrameEncode_Release, |
| IcnsFrameEncode_Initialize, |
| IcnsFrameEncode_SetSize, |
| IcnsFrameEncode_SetResolution, |
| IcnsFrameEncode_SetPixelFormat, |
| IcnsFrameEncode_SetColorContexts, |
| IcnsFrameEncode_SetPalette, |
| IcnsFrameEncode_SetThumbnail, |
| IcnsFrameEncode_WritePixels, |
| IcnsFrameEncode_WriteSource, |
| IcnsFrameEncode_Commit, |
| IcnsFrameEncode_GetMetadataQueryWriter |
| }; |
| |
| static HRESULT WINAPI IcnsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid, |
| void **ppv) |
| { |
| IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface); |
| TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); |
| |
| if (!ppv) return E_INVALIDARG; |
| |
| if (IsEqualIID(&IID_IUnknown, iid) || |
| IsEqualIID(&IID_IWICBitmapEncoder, iid)) |
| { |
| *ppv = &This->IWICBitmapEncoder_iface; |
| } |
| else |
| { |
| *ppv = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| IUnknown_AddRef((IUnknown*)*ppv); |
| return S_OK; |
| } |
| |
| static ULONG WINAPI IcnsEncoder_AddRef(IWICBitmapEncoder *iface) |
| { |
| IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) refcount=%u\n", iface, ref); |
| |
| return ref; |
| } |
| |
| static ULONG WINAPI IcnsEncoder_Release(IWICBitmapEncoder *iface) |
| { |
| IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p) refcount=%u\n", iface, ref); |
| |
| if (ref == 0) |
| { |
| This->lock.DebugInfo->Spare[0] = 0; |
| DeleteCriticalSection(&This->lock); |
| if (This->icns_family) |
| DisposeHandle((Handle)This->icns_family); |
| if (This->stream) |
| IStream_Release(This->stream); |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_Initialize(IWICBitmapEncoder *iface, |
| IStream *pIStream, WICBitmapEncoderCacheOption cacheOption) |
| { |
| IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface); |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption); |
| |
| EnterCriticalSection(&This->lock); |
| |
| if (This->icns_family) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| This->icns_family = (IconFamilyHandle)NewHandle(0); |
| if (!This->icns_family) |
| { |
| WARN("error creating icns family\n"); |
| hr = E_FAIL; |
| goto end; |
| } |
| IStream_AddRef(pIStream); |
| This->stream = pIStream; |
| |
| end: |
| LeaveCriticalSection(&This->lock); |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_GetContainerFormat(IWICBitmapEncoder *iface, |
| GUID *pguidContainerFormat) |
| { |
| FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidContainerFormat)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, |
| IWICBitmapEncoderInfo **ppIEncoderInfo) |
| { |
| FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_SetColorContexts(IWICBitmapEncoder *iface, |
| UINT cCount, IWICColorContext **ppIColorContext) |
| { |
| FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette) |
| { |
| TRACE("(%p,%p)\n", iface, pIPalette); |
| return WINCODEC_ERR_UNSUPPORTEDOPERATION; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail) |
| { |
| TRACE("(%p,%p)\n", iface, pIThumbnail); |
| return WINCODEC_ERR_UNSUPPORTEDOPERATION; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview) |
| { |
| TRACE("(%p,%p)\n", iface, pIPreview); |
| return WINCODEC_ERR_UNSUPPORTEDOPERATION; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_CreateNewFrame(IWICBitmapEncoder *iface, |
| IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions) |
| { |
| IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface); |
| HRESULT hr = S_OK; |
| IcnsFrameEncode *frameEncode = NULL; |
| |
| TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions); |
| |
| EnterCriticalSection(&This->lock); |
| |
| if (!This->icns_family) |
| { |
| hr = WINCODEC_ERR_NOTINITIALIZED; |
| goto end; |
| } |
| |
| hr = CreatePropertyBag2(NULL, 0, ppIEncoderOptions); |
| if (FAILED(hr)) |
| goto end; |
| |
| frameEncode = HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsFrameEncode)); |
| if (frameEncode == NULL) |
| { |
| hr = E_OUTOFMEMORY; |
| goto end; |
| } |
| frameEncode->IWICBitmapFrameEncode_iface.lpVtbl = &IcnsEncoder_FrameVtbl; |
| frameEncode->encoder = This; |
| frameEncode->ref = 1; |
| frameEncode->initialized = FALSE; |
| frameEncode->size = 0; |
| frameEncode->icns_image = NULL; |
| frameEncode->lines_written = 0; |
| frameEncode->committed = FALSE; |
| *ppIFrameEncode = &frameEncode->IWICBitmapFrameEncode_iface; |
| This->outstanding_commits++; |
| IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface); |
| |
| end: |
| LeaveCriticalSection(&This->lock); |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_Commit(IWICBitmapEncoder *iface) |
| { |
| IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface); |
| size_t buffer_size; |
| HRESULT hr = S_OK; |
| ULONG byteswritten; |
| |
| TRACE("(%p)\n", iface); |
| |
| EnterCriticalSection(&This->lock); |
| |
| if (!This->any_frame_committed || This->outstanding_commits > 0 || This->committed) |
| { |
| hr = WINCODEC_ERR_WRONGSTATE; |
| goto end; |
| } |
| |
| buffer_size = GetHandleSize((Handle)This->icns_family); |
| hr = IStream_Write(This->stream, *This->icns_family, buffer_size, &byteswritten); |
| if (FAILED(hr) || byteswritten != buffer_size) |
| { |
| WARN("writing file failed, hr = 0x%08X\n", hr); |
| hr = E_FAIL; |
| goto end; |
| } |
| |
| This->committed = TRUE; |
| |
| end: |
| LeaveCriticalSection(&This->lock); |
| return hr; |
| } |
| |
| static HRESULT WINAPI IcnsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface, |
| IWICMetadataQueryWriter **ppIMetadataQueryWriter) |
| { |
| FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter); |
| return E_NOTIMPL; |
| } |
| |
| static const IWICBitmapEncoderVtbl IcnsEncoder_Vtbl = { |
| IcnsEncoder_QueryInterface, |
| IcnsEncoder_AddRef, |
| IcnsEncoder_Release, |
| IcnsEncoder_Initialize, |
| IcnsEncoder_GetContainerFormat, |
| IcnsEncoder_GetEncoderInfo, |
| IcnsEncoder_SetColorContexts, |
| IcnsEncoder_SetPalette, |
| IcnsEncoder_SetThumbnail, |
| IcnsEncoder_SetPreview, |
| IcnsEncoder_CreateNewFrame, |
| IcnsEncoder_Commit, |
| IcnsEncoder_GetMetadataQueryWriter |
| }; |
| |
| HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv) |
| { |
| IcnsEncoder *This; |
| HRESULT ret; |
| |
| TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); |
| |
| *ppv = NULL; |
| |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsEncoder)); |
| if (!This) return E_OUTOFMEMORY; |
| |
| This->IWICBitmapEncoder_iface.lpVtbl = &IcnsEncoder_Vtbl; |
| This->ref = 1; |
| This->stream = NULL; |
| This->icns_family = NULL; |
| This->any_frame_committed = FALSE; |
| This->outstanding_commits = 0; |
| This->committed = FALSE; |
| InitializeCriticalSection(&This->lock); |
| This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IcnsEncoder.lock"); |
| |
| ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv); |
| IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface); |
| |
| return ret; |
| } |
| |
| #else /* !defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) || |
| MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 */ |
| |
| HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv) |
| { |
| ERR("Trying to save ICNS picture, but ICNS support is not compiled in.\n"); |
| return E_FAIL; |
| } |
| |
| #endif |