Signed-off-by: Esme Povirk esme@codeweavers.com --- dlls/windowscodecs/Makefile.in | 2 +- dlls/windowscodecs/encoder.c | 26 + dlls/windowscodecs/icnsencoder.c | 296 ++++++++++ dlls/windowscodecs/icnsformat.c | 742 ------------------------- dlls/windowscodecs/main.c | 14 + dlls/windowscodecs/regsvr.c | 2 +- dlls/windowscodecs/unix_lib.c | 3 + dlls/windowscodecs/wincodecs_private.h | 4 + 8 files changed, 345 insertions(+), 744 deletions(-) create mode 100644 dlls/windowscodecs/icnsencoder.c delete mode 100644 dlls/windowscodecs/icnsformat.c
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in index 2ab89eac84c..774257f11c7 100644 --- a/dlls/windowscodecs/Makefile.in +++ b/dlls/windowscodecs/Makefile.in @@ -18,7 +18,7 @@ C_SRCS = \ encoder.c \ fliprotate.c \ gifformat.c \ - icnsformat.c \ + icnsencoder.c \ icoformat.c \ imgfactory.c \ info.c \ diff --git a/dlls/windowscodecs/encoder.c b/dlls/windowscodecs/encoder.c index b17895a6c9c..72a83822b50 100644 --- a/dlls/windowscodecs/encoder.c +++ b/dlls/windowscodecs/encoder.c @@ -220,6 +220,31 @@ static HRESULT WINAPI CommonEncoderFrame_SetSize(IWICBitmapFrameEncode *iface,
EnterCriticalSection(&This->parent->lock);
+ if (This->parent->encoder_info.flags & ENCODER_FLAGS_ICNS_SIZE) + { + 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", uiWidth, uiHeight); + hr = E_INVALIDARG; + goto end; + } + } + if (!This->initialized || This->frame_created) { hr = WINCODEC_ERR_WRONGSTATE; @@ -231,6 +256,7 @@ static HRESULT WINAPI CommonEncoderFrame_SetSize(IWICBitmapFrameEncode *iface, hr = S_OK; }
+end: LeaveCriticalSection(&This->parent->lock);
return hr; diff --git a/dlls/windowscodecs/icnsencoder.c b/dlls/windowscodecs/icnsencoder.c new file mode 100644 index 00000000000..82fa8fde380 --- /dev/null +++ b/dlls/windowscodecs/icnsencoder.c @@ -0,0 +1,296 @@ +/* + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#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 +#endif + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "winbase.h" +#include "objbase.h" + +#include "wincodecs_private.h" + +#include "wine/debug.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 { + struct encoder encoder; + IStream *stream; + IconFamilyHandle icns_family; + struct encoder_frame frame; + OSType icns_type; + BYTE* icns_image; + int lines_written; +} IcnsEncoder; + +static inline IcnsEncoder *impl_from_encoder(struct encoder *iface) +{ + return CONTAINING_RECORD(iface, IcnsEncoder, encoder); +} + +void CDECL IcnsEncoder_destroy(struct encoder *iface) +{ + IcnsEncoder *This = impl_from_encoder(iface); + + free(This->icns_image); + + if (This->icns_family) + DisposeHandle((Handle)This->icns_family); + + RtlFreeHeap(GetProcessHeap(), 0, This); +} + +HRESULT CDECL IcnsEncoder_get_supported_format(struct encoder *iface, + GUID *pixel_format, DWORD *bpp, BOOL *indexed) +{ + *pixel_format = GUID_WICPixelFormat32bppBGRA; + *bpp = 32; + *indexed = FALSE; + return S_OK; +} + +HRESULT CDECL IcnsEncoder_create_frame(struct encoder *iface, const struct encoder_frame *frame) +{ + IcnsEncoder *This = impl_from_encoder(iface); + + This->frame = *frame; + + switch (frame->width) + { + 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: + ERR("cannot generate ICNS icon from %dx%d image\n", frame->width, frame->height); + return E_INVALIDARG; + } + This->icns_image = malloc(frame->width * frame->height * 4); + if (!This->icns_image) + { + WARN("failed to allocate image buffer\n"); + return E_FAIL; + } + This->lines_written = 0; + + return S_OK; +} + +static HRESULT CDECL IcnsEncoder_write_lines(struct encoder* iface, + BYTE *data, DWORD line_count, DWORD stride) +{ + IcnsEncoder *This = impl_from_encoder(iface); + UINT i; + + for (i = 0; i < line_count; i++) + { + BYTE *src_row, *dst_row; + UINT j; + src_row = data + stride * i; + dst_row = This->icns_image + (This->lines_written + i)*(This->frame.width*4); + /* swap bgr -> rgb */ + for (j = 0; j < This->frame.width*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 += line_count; + + return S_OK; +} + +static HRESULT CDECL IcnsEncoder_commit_frame(struct encoder *iface) +{ + IcnsEncoder *This = impl_from_encoder(iface); + Handle handle; + OSErr ret; + HRESULT hr = S_OK; + + ret = PtrToHand(This->icns_image, &handle, This->frame.width * This->frame.height * 4); + if (ret != noErr || !handle) + { + WARN("PtrToHand failed with error %d\n", ret); + return E_FAIL; + } + + ret = SetIconFamilyData(This->icns_family, This->icns_type, handle); + DisposeHandle(handle); + + if (ret != noErr) + { + WARN("SetIconFamilyData failed for image with error %d\n", ret); + return E_FAIL; + } + + free(This->icns_image); + This->icns_image = NULL; + + return S_OK; +} + +static HRESULT CDECL IcnsEncoder_initialize(struct encoder *iface, IStream *stream) +{ + IcnsEncoder *This = impl_from_encoder(iface); + + This->icns_family = (IconFamilyHandle)NewHandle(0); + if (!This->icns_family) + { + WARN("error creating icns family\n"); + return E_FAIL; + } + + This->stream = stream; + + return S_OK; +} + +static HRESULT CDECL IcnsEncoder_commit_file(struct encoder *iface) +{ + IcnsEncoder *This = impl_from_encoder(iface); + size_t buffer_size; + HRESULT hr = S_OK; + ULONG byteswritten; + + buffer_size = GetHandleSize((Handle)This->icns_family); + hr = stream_write(This->stream, *This->icns_family, buffer_size, &byteswritten); + if (FAILED(hr) || byteswritten != buffer_size) + { + WARN("writing file failed, hr = 0x%08X\n", hr); + return E_FAIL; + } + + return S_OK; +} + +static const struct encoder_funcs IcnsEncoder_vtable = { + IcnsEncoder_initialize, + IcnsEncoder_get_supported_format, + IcnsEncoder_create_frame, + IcnsEncoder_write_lines, + IcnsEncoder_commit_frame, + IcnsEncoder_commit_file, + IcnsEncoder_destroy +}; + +HRESULT CDECL icns_encoder_create(struct encoder_info *info, struct encoder **result) +{ + IcnsEncoder *This; + + TRACE("\n"); + + This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(IcnsEncoder)); + if (!This) return E_OUTOFMEMORY; + + This->encoder.vtable = &IcnsEncoder_vtable; + This->stream = NULL; + This->icns_family = NULL; + This->icns_image = NULL; + + *result = &This->encoder; + info->flags = ENCODER_FLAGS_MULTI_FRAME|ENCODER_FLAGS_ICNS_SIZE; + info->container_format = GUID_WineContainerFormatIcns; + info->clsid = CLSID_WICIcnsEncoder; + info->encoder_options[0] = ENCODER_OPTION_END; + + return S_OK; +} + +#else /* !defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) || + MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 */ + +HRESULT CDECL icns_encoder_create(struct encoder_info *info, struct encoder **result) +{ + ERR("Trying to save ICNS picture, but ICNS support is not compiled in.\n"); + return E_FAIL; +} + +#endif diff --git a/dlls/windowscodecs/icnsformat.c b/dlls/windowscodecs/icnsformat.c deleted file mode 100644 index c74e4b24d71..00000000000 --- a/dlls/windowscodecs/icnsformat.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * 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 -#endif - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "objbase.h" - -#include "wincodecs_private.h" - -#include "wine/debug.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,%s)\n", iface, pIBitmapSource, debug_wic_rect(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, FALSE, 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; - } - - if (ppIEncoderOptions) - { - 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 diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c index b8ffb216186..bfdde3e3891 100644 --- a/dlls/windowscodecs/main.c +++ b/dlls/windowscodecs/main.c @@ -307,3 +307,17 @@ HRESULT JpegEncoder_CreateInstance(REFIID iid, void** ppv)
return hr; } + +HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv) +{ + HRESULT hr; + struct encoder *encoder; + struct encoder_info encoder_info; + + hr = get_unix_encoder(&CLSID_WICIcnsEncoder, &encoder_info, &encoder); + + if (SUCCEEDED(hr)) + hr = CommonEncoder_CreateInstance(encoder, &encoder_info, iid, ppv); + + return hr; +} diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 38c252c2760..365f44979fc 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1532,7 +1532,7 @@ static struct regsvr_encoder const encoder_list[] = { "ICNS Encoder", "1.0.0.0", &GUID_VendorWine, - NULL, /* no container format guid */ + &GUID_WineContainerFormatIcns, "image/icns", ".icns", icns_encode_formats diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c index f94340fc971..268a1cd9d16 100644 --- a/dlls/windowscodecs/unix_lib.c +++ b/dlls/windowscodecs/unix_lib.c @@ -92,6 +92,9 @@ HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *in if (IsEqualGUID(encoder_clsid, &CLSID_WICJpegEncoder)) return jpeg_encoder_create(info, result);
+ if (IsEqualGUID(encoder_clsid, &CLSID_WICIcnsEncoder)) + return icns_encoder_create(info, result); + return E_NOTIMPL; }
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 3814edb32bb..ebd2d20dfe7 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -31,6 +31,8 @@ DEFINE_GUID(CLSID_WICIcnsEncoder, 0x312fb6f1,0xb767,0x409d,0x8a,0x6d,0x0f,0xc1,0
DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22);
+DEFINE_GUID(GUID_WineContainerFormatIcns, 0xe4cd3e69,0x4436,0x4363,0x98,0x1d,0xcc,0xf0,0x5a,0x87,0x4c,0x73); + DEFINE_GUID(GUID_VendorWine, 0xddf46da1,0x7dc1,0x404e,0x98,0xf2,0xef,0xa4,0x8d,0xfc,0x95,0x0a);
extern IID IID_IMILBitmap; @@ -353,6 +355,7 @@ enum encoder_option };
#define ENCODER_FLAGS_MULTI_FRAME 0x1 +#define ENCODER_FLAGS_ICNS_SIZE 0x2
struct encoder_info { @@ -407,6 +410,7 @@ HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **re HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result); HRESULT CDECL tiff_encoder_create(struct encoder_info *info, struct encoder **result); HRESULT CDECL jpeg_encoder_create(struct encoder_info *info, struct encoder **result); +HRESULT CDECL icns_encoder_create(struct encoder_info *info, struct encoder **result);
struct unix_funcs {