[PATCH] windowscodecs: Move ICNS encoding to the unix lib.
Esme Povirk
esme at codeweavers.com
Sun Nov 29 16:13:15 CST 2020
Signed-off-by: Esme Povirk <esme at 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
{
--
2.17.1
More information about the wine-devel
mailing list