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 HeapFree(GetProcessHeap(), 0, This
->icns_image
);
164 IWICBitmapEncoder_Release(&This
->encoder
->IWICBitmapEncoder_iface
);
165 HeapFree(GetProcessHeap(), 0, This
);
171 static HRESULT WINAPI
IcnsFrameEncode_Initialize(IWICBitmapFrameEncode
*iface
,
172 IPropertyBag2
*pIEncoderOptions
)
174 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
177 TRACE("(%p,%p)\n", iface
, pIEncoderOptions
);
179 EnterCriticalSection(&This
->encoder
->lock
);
181 if (This
->initialized
)
183 hr
= WINCODEC_ERR_WRONGSTATE
;
186 This
->initialized
= TRUE
;
189 LeaveCriticalSection(&This
->encoder
->lock
);
193 static HRESULT WINAPI
IcnsFrameEncode_SetSize(IWICBitmapFrameEncode
*iface
,
194 UINT uiWidth
, UINT uiHeight
)
196 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
199 TRACE("(%p,%u,%u)\n", iface
, uiWidth
, uiHeight
);
201 EnterCriticalSection(&This
->encoder
->lock
);
203 if (!This
->initialized
|| This
->icns_image
)
205 hr
= WINCODEC_ERR_WRONGSTATE
;
209 if (uiWidth
!= uiHeight
)
211 WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth
, uiHeight
);
226 WARN("cannot generate ICNS icon from %dx%d image\n", This
->size
, This
->size
);
231 This
->size
= uiWidth
;
234 LeaveCriticalSection(&This
->encoder
->lock
);
238 static HRESULT WINAPI
IcnsFrameEncode_SetResolution(IWICBitmapFrameEncode
*iface
,
239 double dpiX
, double dpiY
)
241 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
244 TRACE("(%p,%0.2f,%0.2f)\n", iface
, dpiX
, dpiY
);
246 EnterCriticalSection(&This
->encoder
->lock
);
248 if (!This
->initialized
|| This
->icns_image
)
250 hr
= WINCODEC_ERR_WRONGSTATE
;
255 LeaveCriticalSection(&This
->encoder
->lock
);
259 static HRESULT WINAPI
IcnsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
260 WICPixelFormatGUID
*pPixelFormat
)
262 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
265 TRACE("(%p,%s)\n", iface
, debugstr_guid(pPixelFormat
));
267 EnterCriticalSection(&This
->encoder
->lock
);
269 if (!This
->initialized
|| This
->icns_image
)
271 hr
= WINCODEC_ERR_WRONGSTATE
;
275 memcpy(pPixelFormat
, &GUID_WICPixelFormat32bppBGRA
, sizeof(GUID
));
278 LeaveCriticalSection(&This
->encoder
->lock
);
282 static HRESULT WINAPI
IcnsFrameEncode_SetColorContexts(IWICBitmapFrameEncode
*iface
,
283 UINT cCount
, IWICColorContext
**ppIColorContext
)
285 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
289 static HRESULT WINAPI
IcnsFrameEncode_SetPalette(IWICBitmapFrameEncode
*iface
,
290 IWICPalette
*pIPalette
)
292 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
293 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
296 static HRESULT WINAPI
IcnsFrameEncode_SetThumbnail(IWICBitmapFrameEncode
*iface
,
297 IWICBitmapSource
*pIThumbnail
)
299 FIXME("(%p,%p): stub\n", iface
, pIThumbnail
);
300 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
303 static HRESULT WINAPI
IcnsFrameEncode_WritePixels(IWICBitmapFrameEncode
*iface
,
304 UINT lineCount
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbPixels
)
306 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
310 TRACE("(%p,%u,%u,%u,%p)\n", iface
, lineCount
, cbStride
, cbBufferSize
, pbPixels
);
312 EnterCriticalSection(&This
->encoder
->lock
);
314 if (!This
->initialized
|| !This
->size
)
316 hr
= WINCODEC_ERR_WRONGSTATE
;
319 if (lineCount
== 0 || lineCount
+ This
->lines_written
> This
->size
)
325 if (!This
->icns_image
)
329 case 16: This
->icns_type
= kIconServices16PixelDataARGB
; break;
330 case 32: This
->icns_type
= kIconServices32PixelDataARGB
; break;
331 case 48: This
->icns_type
= kIconServices48PixelDataARGB
; break;
332 case 128: This
->icns_type
= kIconServices128PixelDataARGB
; break;
333 case 256: This
->icns_type
= kIconServices256PixelDataARGB
; break;
334 case 512: This
->icns_type
= kIconServices512PixelDataARGB
; break;
336 WARN("cannot generate ICNS icon from %dx%d image\n", This
->size
, This
->size
);
340 This
->icns_image
= HeapAlloc(GetProcessHeap(), 0, This
->size
* This
->size
* 4);
341 if (!This
->icns_image
)
343 WARN("failed to allocate image buffer\n");
349 for (i
= 0; i
< lineCount
; i
++)
351 BYTE
*src_row
, *dst_row
;
353 src_row
= pbPixels
+ cbStride
* i
;
354 dst_row
= This
->icns_image
+ (This
->lines_written
+ i
)*(This
->size
*4);
355 /* swap bgr -> rgb */
356 for (j
= 0; j
< This
->size
*4; j
+= 4)
358 dst_row
[j
] = src_row
[j
+3];
359 dst_row
[j
+1] = src_row
[j
+2];
360 dst_row
[j
+2] = src_row
[j
+1];
361 dst_row
[j
+3] = src_row
[j
];
364 This
->lines_written
+= lineCount
;
367 LeaveCriticalSection(&This
->encoder
->lock
);
371 static HRESULT WINAPI
IcnsFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface
,
372 IWICBitmapSource
*pIBitmapSource
, WICRect
*prc
)
374 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
377 TRACE("(%p,%p,%p)\n", iface
, pIBitmapSource
, prc
);
379 if (!This
->initialized
)
380 return WINCODEC_ERR_WRONGSTATE
;
382 hr
= configure_write_source(iface
, pIBitmapSource
, prc
,
383 &GUID_WICPixelFormat32bppBGRA
, This
->size
, This
->size
,
388 hr
= write_source(iface
, pIBitmapSource
, prc
,
389 &GUID_WICPixelFormat32bppBGRA
, 32, This
->size
, This
->size
);
395 static HRESULT WINAPI
IcnsFrameEncode_Commit(IWICBitmapFrameEncode
*iface
)
397 IcnsFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
402 TRACE("(%p): stub\n", iface
);
404 EnterCriticalSection(&This
->encoder
->lock
);
406 if (!This
->icns_image
|| This
->lines_written
!= This
->size
|| This
->committed
)
408 hr
= WINCODEC_ERR_WRONGSTATE
;
412 ret
= PtrToHand(This
->icns_image
, &handle
, This
->size
* This
->size
* 4);
413 if (ret
!= noErr
|| !handle
)
415 WARN("PtrToHand failed with error %d\n", ret
);
420 ret
= SetIconFamilyData(This
->encoder
->icns_family
, This
->icns_type
, handle
);
421 DisposeHandle(handle
);
425 WARN("SetIconFamilyData failed for image with error %d\n", ret
);
430 This
->committed
= TRUE
;
431 This
->encoder
->any_frame_committed
= TRUE
;
432 This
->encoder
->outstanding_commits
--;
435 LeaveCriticalSection(&This
->encoder
->lock
);
439 static HRESULT WINAPI
IcnsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
440 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
442 FIXME("(%p, %p): stub\n", iface
, ppIMetadataQueryWriter
);
446 static const IWICBitmapFrameEncodeVtbl IcnsEncoder_FrameVtbl
= {
447 IcnsFrameEncode_QueryInterface
,
448 IcnsFrameEncode_AddRef
,
449 IcnsFrameEncode_Release
,
450 IcnsFrameEncode_Initialize
,
451 IcnsFrameEncode_SetSize
,
452 IcnsFrameEncode_SetResolution
,
453 IcnsFrameEncode_SetPixelFormat
,
454 IcnsFrameEncode_SetColorContexts
,
455 IcnsFrameEncode_SetPalette
,
456 IcnsFrameEncode_SetThumbnail
,
457 IcnsFrameEncode_WritePixels
,
458 IcnsFrameEncode_WriteSource
,
459 IcnsFrameEncode_Commit
,
460 IcnsFrameEncode_GetMetadataQueryWriter
463 static HRESULT WINAPI
IcnsEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
466 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
467 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
469 if (!ppv
) return E_INVALIDARG
;
471 if (IsEqualIID(&IID_IUnknown
, iid
) ||
472 IsEqualIID(&IID_IWICBitmapEncoder
, iid
))
474 *ppv
= &This
->IWICBitmapEncoder_iface
;
479 return E_NOINTERFACE
;
482 IUnknown_AddRef((IUnknown
*)*ppv
);
486 static ULONG WINAPI
IcnsEncoder_AddRef(IWICBitmapEncoder
*iface
)
488 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
489 ULONG ref
= InterlockedIncrement(&This
->ref
);
491 TRACE("(%p) refcount=%u\n", iface
, ref
);
496 static ULONG WINAPI
IcnsEncoder_Release(IWICBitmapEncoder
*iface
)
498 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
499 ULONG ref
= InterlockedDecrement(&This
->ref
);
501 TRACE("(%p) refcount=%u\n", iface
, ref
);
505 This
->lock
.DebugInfo
->Spare
[0] = 0;
506 DeleteCriticalSection(&This
->lock
);
507 if (This
->icns_family
)
508 DisposeHandle((Handle
)This
->icns_family
);
510 IStream_Release(This
->stream
);
511 HeapFree(GetProcessHeap(), 0, This
);
517 static HRESULT WINAPI
IcnsEncoder_Initialize(IWICBitmapEncoder
*iface
,
518 IStream
*pIStream
, WICBitmapEncoderCacheOption cacheOption
)
520 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
523 TRACE("(%p,%p,%u)\n", iface
, pIStream
, cacheOption
);
525 EnterCriticalSection(&This
->lock
);
527 if (This
->icns_family
)
529 hr
= WINCODEC_ERR_WRONGSTATE
;
532 This
->icns_family
= (IconFamilyHandle
)NewHandle(0);
533 if (!This
->icns_family
)
535 WARN("error creating icns family\n");
539 IStream_AddRef(pIStream
);
540 This
->stream
= pIStream
;
543 LeaveCriticalSection(&This
->lock
);
548 static HRESULT WINAPI
IcnsEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
,
549 GUID
*pguidContainerFormat
)
551 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pguidContainerFormat
));
555 static HRESULT WINAPI
IcnsEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
,
556 IWICBitmapEncoderInfo
**ppIEncoderInfo
)
558 FIXME("(%p,%p): stub\n", iface
, ppIEncoderInfo
);
562 static HRESULT WINAPI
IcnsEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
563 UINT cCount
, IWICColorContext
**ppIColorContext
)
565 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
569 static HRESULT WINAPI
IcnsEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*pIPalette
)
571 TRACE("(%p,%p)\n", iface
, pIPalette
);
572 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
575 static HRESULT WINAPI
IcnsEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
577 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
578 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
581 static HRESULT WINAPI
IcnsEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
583 TRACE("(%p,%p)\n", iface
, pIPreview
);
584 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
587 static HRESULT WINAPI
IcnsEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
588 IWICBitmapFrameEncode
**ppIFrameEncode
, IPropertyBag2
**ppIEncoderOptions
)
590 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
592 IcnsFrameEncode
*frameEncode
= NULL
;
594 TRACE("(%p,%p,%p)\n", iface
, ppIFrameEncode
, ppIEncoderOptions
);
596 EnterCriticalSection(&This
->lock
);
598 if (!This
->icns_family
)
600 hr
= WINCODEC_ERR_NOTINITIALIZED
;
604 hr
= CreatePropertyBag2(NULL
, 0, ppIEncoderOptions
);
608 frameEncode
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsFrameEncode
));
609 if (frameEncode
== NULL
)
614 frameEncode
->IWICBitmapFrameEncode_iface
.lpVtbl
= &IcnsEncoder_FrameVtbl
;
615 frameEncode
->encoder
= This
;
616 frameEncode
->ref
= 1;
617 frameEncode
->initialized
= FALSE
;
618 frameEncode
->size
= 0;
619 frameEncode
->icns_image
= NULL
;
620 frameEncode
->lines_written
= 0;
621 frameEncode
->committed
= FALSE
;
622 *ppIFrameEncode
= &frameEncode
->IWICBitmapFrameEncode_iface
;
623 This
->outstanding_commits
++;
624 IWICBitmapEncoder_AddRef(&This
->IWICBitmapEncoder_iface
);
627 LeaveCriticalSection(&This
->lock
);
632 static HRESULT WINAPI
IcnsEncoder_Commit(IWICBitmapEncoder
*iface
)
634 IcnsEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
639 TRACE("(%p)\n", iface
);
641 EnterCriticalSection(&This
->lock
);
643 if (!This
->any_frame_committed
|| This
->outstanding_commits
> 0 || This
->committed
)
645 hr
= WINCODEC_ERR_WRONGSTATE
;
649 buffer_size
= GetHandleSize((Handle
)This
->icns_family
);
650 hr
= IStream_Write(This
->stream
, *This
->icns_family
, buffer_size
, &byteswritten
);
651 if (FAILED(hr
) || byteswritten
!= buffer_size
)
653 WARN("writing file failed, hr = 0x%08X\n", hr
);
658 This
->committed
= TRUE
;
661 LeaveCriticalSection(&This
->lock
);
665 static HRESULT WINAPI
IcnsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
666 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
668 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
672 static const IWICBitmapEncoderVtbl IcnsEncoder_Vtbl
= {
673 IcnsEncoder_QueryInterface
,
676 IcnsEncoder_Initialize
,
677 IcnsEncoder_GetContainerFormat
,
678 IcnsEncoder_GetEncoderInfo
,
679 IcnsEncoder_SetColorContexts
,
680 IcnsEncoder_SetPalette
,
681 IcnsEncoder_SetThumbnail
,
682 IcnsEncoder_SetPreview
,
683 IcnsEncoder_CreateNewFrame
,
685 IcnsEncoder_GetMetadataQueryWriter
688 HRESULT
IcnsEncoder_CreateInstance(REFIID iid
, void** ppv
)
693 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
697 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsEncoder
));
698 if (!This
) return E_OUTOFMEMORY
;
700 This
->IWICBitmapEncoder_iface
.lpVtbl
= &IcnsEncoder_Vtbl
;
703 This
->icns_family
= NULL
;
704 This
->any_frame_committed
= FALSE
;
705 This
->outstanding_commits
= 0;
706 This
->committed
= FALSE
;
707 InitializeCriticalSection(&This
->lock
);
708 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IcnsEncoder.lock");
710 ret
= IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
711 IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);
716 #else /* !defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) ||
717 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 */
719 HRESULT
IcnsEncoder_CreateInstance(REFIID iid
, void** ppv
)
721 ERR("Trying to save ICNS picture, but ICNS support is not compiled in.\n");