2 * Copyright 2010 Damjan Jovanovic
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.
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.
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
19 #ifdef HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H
20 #define GetCurrentProcess GetCurrentProcess_Mac
21 #define GetCurrentThread GetCurrentThread_Mac
22 #define LoadResource LoadResource_Mac
23 #define AnimatePalette AnimatePalette_Mac
24 #define EqualRgn EqualRgn_Mac
25 #define FillRgn FillRgn_Mac
26 #define FrameRgn FrameRgn_Mac
27 #define GetPixel GetPixel_Mac
28 #define InvertRgn InvertRgn_Mac
29 #define LineTo LineTo_Mac
30 #define OffsetRgn OffsetRgn_Mac
31 #define PaintRgn PaintRgn_Mac
32 #define Polygon Polygon_Mac
33 #define ResizePalette ResizePalette_Mac
34 #define SetRectRgn SetRectRgn_Mac
35 #define EqualRect EqualRect_Mac
36 #define FillRect FillRect_Mac
37 #define FrameRect FrameRect_Mac
38 #define GetCursor GetCursor_Mac
39 #define InvertRect InvertRect_Mac
40 #define OffsetRect OffsetRect_Mac
41 #define PtInRect PtInRect_Mac
42 #define SetCursor SetCursor_Mac
43 #define SetRect SetRect_Mac
44 #define ShowCursor ShowCursor_Mac
45 #define UnionRect UnionRect_Mac
46 #include <ApplicationServices/ApplicationServices.h>
47 #undef GetCurrentProcess
48 #undef GetCurrentThread
76 #include "wincodecs_private.h"
78 #if defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) && \
79 MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
81 typedef struct IcnsEncoder
{
82 IWICBitmapEncoder IWICBitmapEncoder_iface
;
85 IconFamilyHandle icns_family
;
86 BOOL any_frame_committed
;
87 int outstanding_commits
;
89 CRITICAL_SECTION lock
;
92 static inline IcnsEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
94 return CONTAINING_RECORD(iface
, IcnsEncoder
, IWICBitmapEncoder_iface
);
97 typedef struct IcnsFrameEncode
{
98 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface
;
109 static inline IcnsFrameEncode
*impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface
)
111 return CONTAINING_RECORD(iface
, IcnsFrameEncode
, IWICBitmapFrameEncode_iface
);
114 static HRESULT WINAPI
IcnsFrameEncode_QueryInterface(IWICBitmapFrameEncode
*iface
, REFIID iid
,
117 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
118 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
120 if (!ppv
) return E_INVALIDARG
;
122 if (IsEqualIID(&IID_IUnknown
, iid
) ||
123 IsEqualIID(&IID_IWICBitmapFrameEncode
, iid
))
125 *ppv
= &This
->IWICBitmapFrameEncode_iface
;
130 return E_NOINTERFACE
;
133 IUnknown_AddRef((IUnknown
*)*ppv
);
137 static ULONG WINAPI
IcnsFrameEncode_AddRef(IWICBitmapFrameEncode
*iface
)
139 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
140 ULONG ref
= InterlockedIncrement(&This
->ref
);
142 TRACE("(%p) refcount=%u\n", iface
, ref
);
147 static ULONG WINAPI
IcnsFrameEncode_Release(IWICBitmapFrameEncode
*iface
)
149 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
150 ULONG ref
= InterlockedDecrement(&This
->ref
);
152 TRACE("(%p) refcount=%u\n", iface
, ref
);
156 if (!This
->committed
)
158 EnterCriticalSection(&This
->encoder
->lock
);
159 This
->encoder
->outstanding_commits
--;
160 LeaveCriticalSection(&This
->encoder
->lock
);
162 if (This
->icns_image
!= NULL
)
163 HeapFree(GetProcessHeap(), 0, This
->icns_image
);
165 IUnknown_Release((IUnknown
*)This
->encoder
);
166 HeapFree(GetProcessHeap(), 0, This
);
172 static HRESULT WINAPI
IcnsFrameEncode_Initialize(IWICBitmapFrameEncode
*iface
,
173 IPropertyBag2
*pIEncoderOptions
)
175 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
178 TRACE("(%p,%p)\n", iface
, pIEncoderOptions
);
180 EnterCriticalSection(&This
->encoder
->lock
);
182 if (This
->initialized
)
184 hr
= WINCODEC_ERR_WRONGSTATE
;
187 This
->initialized
= TRUE
;
190 LeaveCriticalSection(&This
->encoder
->lock
);
194 static HRESULT WINAPI
IcnsFrameEncode_SetSize(IWICBitmapFrameEncode
*iface
,
195 UINT uiWidth
, UINT uiHeight
)
197 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
200 TRACE("(%p,%u,%u)\n", iface
, uiWidth
, uiHeight
);
202 EnterCriticalSection(&This
->encoder
->lock
);
204 if (!This
->initialized
|| This
->icns_image
)
206 hr
= WINCODEC_ERR_WRONGSTATE
;
210 if (uiWidth
!= uiHeight
)
212 WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth
, uiHeight
);
227 WARN("cannot generate ICNS icon from %dx%d image\n", This
->size
, This
->size
);
232 This
->size
= uiWidth
;
235 LeaveCriticalSection(&This
->encoder
->lock
);
239 static HRESULT WINAPI
IcnsFrameEncode_SetResolution(IWICBitmapFrameEncode
*iface
,
240 double dpiX
, double dpiY
)
242 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
245 TRACE("(%p,%0.2f,%0.2f)\n", iface
, dpiX
, dpiY
);
247 EnterCriticalSection(&This
->encoder
->lock
);
249 if (!This
->initialized
|| This
->icns_image
)
251 hr
= WINCODEC_ERR_WRONGSTATE
;
256 LeaveCriticalSection(&This
->encoder
->lock
);
260 static HRESULT WINAPI
IcnsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
261 WICPixelFormatGUID
*pPixelFormat
)
263 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
266 TRACE("(%p,%s)\n", iface
, debugstr_guid(pPixelFormat
));
268 EnterCriticalSection(&This
->encoder
->lock
);
270 if (!This
->initialized
|| This
->icns_image
)
272 hr
= WINCODEC_ERR_WRONGSTATE
;
276 memcpy(pPixelFormat
, &GUID_WICPixelFormat32bppBGRA
, sizeof(GUID
));
279 LeaveCriticalSection(&This
->encoder
->lock
);
283 static HRESULT WINAPI
IcnsFrameEncode_SetColorContexts(IWICBitmapFrameEncode
*iface
,
284 UINT cCount
, IWICColorContext
**ppIColorContext
)
286 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
290 static HRESULT WINAPI
IcnsFrameEncode_SetPalette(IWICBitmapFrameEncode
*iface
,
291 IWICPalette
*pIPalette
)
293 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
294 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
297 static HRESULT WINAPI
IcnsFrameEncode_SetThumbnail(IWICBitmapFrameEncode
*iface
,
298 IWICBitmapSource
*pIThumbnail
)
300 FIXME("(%p,%p): stub\n", iface
, pIThumbnail
);
301 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
304 static HRESULT WINAPI
IcnsFrameEncode_WritePixels(IWICBitmapFrameEncode
*iface
,
305 UINT lineCount
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbPixels
)
307 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
311 TRACE("(%p,%u,%u,%u,%p)\n", iface
, lineCount
, cbStride
, cbBufferSize
, pbPixels
);
313 EnterCriticalSection(&This
->encoder
->lock
);
315 if (!This
->initialized
|| !This
->size
)
317 hr
= WINCODEC_ERR_WRONGSTATE
;
320 if (lineCount
== 0 || lineCount
+ This
->lines_written
> This
->size
)
326 if (!This
->icns_image
)
330 case 16: This
->icns_type
= kIconServices16PixelDataARGB
; break;
331 case 32: This
->icns_type
= kIconServices32PixelDataARGB
; break;
332 case 48: This
->icns_type
= kIconServices48PixelDataARGB
; break;
333 case 128: This
->icns_type
= kIconServices128PixelDataARGB
; break;
334 case 256: This
->icns_type
= kIconServices256PixelDataARGB
; break;
335 case 512: This
->icns_type
= kIconServices512PixelDataARGB
; break;
337 WARN("cannot generate ICNS icon from %dx%d image\n", This
->size
, This
->size
);
341 This
->icns_image
= HeapAlloc(GetProcessHeap(), 0, This
->size
* This
->size
* 4);
342 if (!This
->icns_image
)
344 WARN("failed to allocate image buffer\n");
350 for (i
= 0; i
< lineCount
; i
++)
352 BYTE
*src_row
, *dst_row
;
354 src_row
= pbPixels
+ cbStride
* i
;
355 dst_row
= This
->icns_image
+ (This
->lines_written
+ i
)*(This
->size
*4);
356 /* swap bgr -> rgb */
357 for (j
= 0; j
< This
->size
*4; j
+= 4)
359 dst_row
[j
] = src_row
[j
+3];
360 dst_row
[j
+1] = src_row
[j
+2];
361 dst_row
[j
+2] = src_row
[j
+1];
362 dst_row
[j
+3] = src_row
[j
];
365 This
->lines_written
+= lineCount
;
368 LeaveCriticalSection(&This
->encoder
->lock
);
372 static HRESULT WINAPI
IcnsFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface
,
373 IWICBitmapSource
*pIBitmapSource
, WICRect
*prc
)
375 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
378 TRACE("(%p,%p,%p)\n", iface
, pIBitmapSource
, prc
);
380 if (!This
->initialized
)
381 return WINCODEC_ERR_WRONGSTATE
;
383 hr
= configure_write_source(iface
, pIBitmapSource
, &prc
,
384 &GUID_WICPixelFormat32bppBGRA
, This
->size
, This
->size
,
389 hr
= write_source(iface
, pIBitmapSource
, prc
,
390 &GUID_WICPixelFormat32bppBGRA
, 32, This
->size
, This
->size
);
396 static HRESULT WINAPI
IcnsFrameEncode_Commit(IWICBitmapFrameEncode
*iface
)
398 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
403 TRACE("(%p): stub\n", iface
);
405 EnterCriticalSection(&This
->encoder
->lock
);
407 if (!This
->icns_image
|| This
->lines_written
!= This
->size
|| This
->committed
)
409 hr
= WINCODEC_ERR_WRONGSTATE
;
413 ret
= PtrToHand(This
->icns_image
, &handle
, This
->size
* This
->size
* 4);
414 if (ret
!= noErr
|| !handle
)
416 WARN("PtrToHand failed with error %d\n", ret
);
421 ret
= SetIconFamilyData(This
->encoder
->icns_family
, This
->icns_type
, handle
);
422 DisposeHandle(handle
);
426 WARN("SetIconFamilyData failed for image with error %d\n", ret
);
431 This
->committed
= TRUE
;
432 This
->encoder
->any_frame_committed
= TRUE
;
433 This
->encoder
->outstanding_commits
--;
436 LeaveCriticalSection(&This
->encoder
->lock
);
440 static HRESULT WINAPI
IcnsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
441 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
443 FIXME("(%p, %p): stub\n", iface
, ppIMetadataQueryWriter
);
447 static const IWICBitmapFrameEncodeVtbl IcnsEncoder_FrameVtbl
= {
448 IcnsFrameEncode_QueryInterface
,
449 IcnsFrameEncode_AddRef
,
450 IcnsFrameEncode_Release
,
451 IcnsFrameEncode_Initialize
,
452 IcnsFrameEncode_SetSize
,
453 IcnsFrameEncode_SetResolution
,
454 IcnsFrameEncode_SetPixelFormat
,
455 IcnsFrameEncode_SetColorContexts
,
456 IcnsFrameEncode_SetPalette
,
457 IcnsFrameEncode_SetThumbnail
,
458 IcnsFrameEncode_WritePixels
,
459 IcnsFrameEncode_WriteSource
,
460 IcnsFrameEncode_Commit
,
461 IcnsFrameEncode_GetMetadataQueryWriter
464 static HRESULT WINAPI
IcnsEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
467 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
468 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
470 if (!ppv
) return E_INVALIDARG
;
472 if (IsEqualIID(&IID_IUnknown
, iid
) ||
473 IsEqualIID(&IID_IWICBitmapEncoder
, iid
))
480 return E_NOINTERFACE
;
483 IUnknown_AddRef((IUnknown
*)*ppv
);
487 static ULONG WINAPI
IcnsEncoder_AddRef(IWICBitmapEncoder
*iface
)
489 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
490 ULONG ref
= InterlockedIncrement(&This
->ref
);
492 TRACE("(%p) refcount=%u\n", iface
, ref
);
497 static ULONG WINAPI
IcnsEncoder_Release(IWICBitmapEncoder
*iface
)
499 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
500 ULONG ref
= InterlockedDecrement(&This
->ref
);
502 TRACE("(%p) refcount=%u\n", iface
, ref
);
506 This
->lock
.DebugInfo
->Spare
[0] = 0;
507 DeleteCriticalSection(&This
->lock
);
508 if (This
->icns_family
)
509 DisposeHandle((Handle
)This
->icns_family
);
511 IStream_Release(This
->stream
);
512 HeapFree(GetProcessHeap(), 0, This
);
518 static HRESULT WINAPI
IcnsEncoder_Initialize(IWICBitmapEncoder
*iface
,
519 IStream
*pIStream
, WICBitmapEncoderCacheOption cacheOption
)
521 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
524 TRACE("(%p,%p,%u)\n", iface
, pIStream
, cacheOption
);
526 EnterCriticalSection(&This
->lock
);
528 if (This
->icns_family
)
530 hr
= WINCODEC_ERR_WRONGSTATE
;
533 This
->icns_family
= (IconFamilyHandle
)NewHandle(0);
534 if (!This
->icns_family
)
536 WARN("error creating icns family\n");
540 IStream_AddRef(pIStream
);
541 This
->stream
= pIStream
;
544 LeaveCriticalSection(&This
->lock
);
549 static HRESULT WINAPI
IcnsEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
,
550 GUID
*pguidContainerFormat
)
552 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pguidContainerFormat
));
556 static HRESULT WINAPI
IcnsEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
,
557 IWICBitmapEncoderInfo
**ppIEncoderInfo
)
559 FIXME("(%p,%p): stub\n", iface
, ppIEncoderInfo
);
563 static HRESULT WINAPI
IcnsEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
564 UINT cCount
, IWICColorContext
**ppIColorContext
)
566 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
570 static HRESULT WINAPI
IcnsEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*pIPalette
)
572 TRACE("(%p,%p)\n", iface
, pIPalette
);
573 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
576 static HRESULT WINAPI
IcnsEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
578 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
579 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
582 static HRESULT WINAPI
IcnsEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
584 TRACE("(%p,%p)\n", iface
, pIPreview
);
585 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
588 static HRESULT WINAPI
IcnsEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
589 IWICBitmapFrameEncode
**ppIFrameEncode
, IPropertyBag2
**ppIEncoderOptions
)
591 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
593 IcnsFrameEncode
*frameEncode
= NULL
;
595 TRACE("(%p,%p,%p)\n", iface
, ppIFrameEncode
, ppIEncoderOptions
);
597 EnterCriticalSection(&This
->lock
);
599 if (!This
->icns_family
)
601 hr
= WINCODEC_ERR_NOTINITIALIZED
;
605 hr
= CreatePropertyBag2(NULL
, 0, ppIEncoderOptions
);
609 frameEncode
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsFrameEncode
));
610 if (frameEncode
== NULL
)
615 frameEncode
->IWICBitmapFrameEncode_iface
.lpVtbl
= &IcnsEncoder_FrameVtbl
;
616 frameEncode
->encoder
= This
;
617 frameEncode
->ref
= 1;
618 frameEncode
->initialized
= FALSE
;
619 frameEncode
->size
= 0;
620 frameEncode
->icns_image
= NULL
;
621 frameEncode
->lines_written
= 0;
622 frameEncode
->committed
= FALSE
;
623 *ppIFrameEncode
= &frameEncode
->IWICBitmapFrameEncode_iface
;
624 This
->outstanding_commits
++;
625 IUnknown_AddRef((IUnknown
*)This
);
628 LeaveCriticalSection(&This
->lock
);
633 static HRESULT WINAPI
IcnsEncoder_Commit(IWICBitmapEncoder
*iface
)
635 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
640 TRACE("(%p)\n", iface
);
642 EnterCriticalSection(&This
->lock
);
644 if (!This
->any_frame_committed
|| This
->outstanding_commits
> 0 || This
->committed
)
646 hr
= WINCODEC_ERR_WRONGSTATE
;
650 buffer_size
= GetHandleSize((Handle
)This
->icns_family
);
651 hr
= IStream_Write(This
->stream
, *This
->icns_family
, buffer_size
, &byteswritten
);
652 if (FAILED(hr
) || byteswritten
!= buffer_size
)
654 WARN("writing file failed, hr = 0x%08X\n", hr
);
659 This
->committed
= TRUE
;
662 LeaveCriticalSection(&This
->lock
);
666 static HRESULT WINAPI
IcnsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
667 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
669 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
673 static const IWICBitmapEncoderVtbl IcnsEncoder_Vtbl
= {
674 IcnsEncoder_QueryInterface
,
677 IcnsEncoder_Initialize
,
678 IcnsEncoder_GetContainerFormat
,
679 IcnsEncoder_GetEncoderInfo
,
680 IcnsEncoder_SetColorContexts
,
681 IcnsEncoder_SetPalette
,
682 IcnsEncoder_SetThumbnail
,
683 IcnsEncoder_SetPreview
,
684 IcnsEncoder_CreateNewFrame
,
686 IcnsEncoder_GetMetadataQueryWriter
689 HRESULT
IcnsEncoder_CreateInstance(REFIID iid
, void** ppv
)
694 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
698 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsEncoder
));
699 if (!This
) return E_OUTOFMEMORY
;
701 This
->IWICBitmapEncoder_iface
.lpVtbl
= &IcnsEncoder_Vtbl
;
704 This
->icns_family
= NULL
;
705 This
->any_frame_committed
= FALSE
;
706 This
->outstanding_commits
= 0;
707 This
->committed
= FALSE
;
708 InitializeCriticalSection(&This
->lock
);
709 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IcnsEncoder.lock");
711 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
712 IUnknown_Release((IUnknown
*)This
);
717 #else /* !defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) ||
718 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 */
720 HRESULT
IcnsEncoder_CreateInstance(REFIID iid
, void** ppv
)
722 ERR("Trying to save ICNS picture, but ICNS support is not compiled in.\n");