[WINDOWSCODECS]
[reactos.git] / reactos / dll / win32 / windowscodecs / icnsformat.c
1 /*
2 * Copyright 2010 Damjan Jovanovic
3 *
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.
8 *
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.
13 *
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
17 */
18
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
49 #undef LoadResource
50 #undef AnimatePalette
51 #undef EqualRgn
52 #undef FillRgn
53 #undef FrameRgn
54 #undef GetPixel
55 #undef InvertRgn
56 #undef LineTo
57 #undef OffsetRgn
58 #undef PaintRgn
59 #undef Polygon
60 #undef ResizePalette
61 #undef SetRectRgn
62 #undef EqualRect
63 #undef FillRect
64 #undef FrameRect
65 #undef GetCursor
66 #undef InvertRect
67 #undef OffsetRect
68 #undef PtInRect
69 #undef SetCursor
70 #undef SetRect
71 #undef ShowCursor
72 #undef UnionRect
73 #undef DPRINTF
74 #endif
75
76 #include "wincodecs_private.h"
77
78 #if defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) && \
79 MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
80
81 typedef struct IcnsEncoder {
82 IWICBitmapEncoder IWICBitmapEncoder_iface;
83 LONG ref;
84 IStream *stream;
85 IconFamilyHandle icns_family;
86 BOOL any_frame_committed;
87 int outstanding_commits;
88 BOOL committed;
89 CRITICAL_SECTION lock;
90 } IcnsEncoder;
91
92 static inline IcnsEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
93 {
94 return CONTAINING_RECORD(iface, IcnsEncoder, IWICBitmapEncoder_iface);
95 }
96
97 typedef struct IcnsFrameEncode {
98 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
99 IcnsEncoder *encoder;
100 LONG ref;
101 BOOL initialized;
102 UINT size;
103 OSType icns_type;
104 BYTE* icns_image;
105 int lines_written;
106 BOOL committed;
107 } IcnsFrameEncode;
108
109 static inline IcnsFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
110 {
111 return CONTAINING_RECORD(iface, IcnsFrameEncode, IWICBitmapFrameEncode_iface);
112 }
113
114 static HRESULT WINAPI IcnsFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
115 void **ppv)
116 {
117 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
118 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
119
120 if (!ppv) return E_INVALIDARG;
121
122 if (IsEqualIID(&IID_IUnknown, iid) ||
123 IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
124 {
125 *ppv = &This->IWICBitmapFrameEncode_iface;
126 }
127 else
128 {
129 *ppv = NULL;
130 return E_NOINTERFACE;
131 }
132
133 IUnknown_AddRef((IUnknown*)*ppv);
134 return S_OK;
135 }
136
137 static ULONG WINAPI IcnsFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
138 {
139 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
140 ULONG ref = InterlockedIncrement(&This->ref);
141
142 TRACE("(%p) refcount=%u\n", iface, ref);
143
144 return ref;
145 }
146
147 static ULONG WINAPI IcnsFrameEncode_Release(IWICBitmapFrameEncode *iface)
148 {
149 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
150 ULONG ref = InterlockedDecrement(&This->ref);
151
152 TRACE("(%p) refcount=%u\n", iface, ref);
153
154 if (ref == 0)
155 {
156 if (!This->committed)
157 {
158 EnterCriticalSection(&This->encoder->lock);
159 This->encoder->outstanding_commits--;
160 LeaveCriticalSection(&This->encoder->lock);
161 }
162 if (This->icns_image != NULL)
163 HeapFree(GetProcessHeap(), 0, This->icns_image);
164
165 IUnknown_Release((IUnknown*)This->encoder);
166 HeapFree(GetProcessHeap(), 0, This);
167 }
168
169 return ref;
170 }
171
172 static HRESULT WINAPI IcnsFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
173 IPropertyBag2 *pIEncoderOptions)
174 {
175 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
176 HRESULT hr = S_OK;
177
178 TRACE("(%p,%p)\n", iface, pIEncoderOptions);
179
180 EnterCriticalSection(&This->encoder->lock);
181
182 if (This->initialized)
183 {
184 hr = WINCODEC_ERR_WRONGSTATE;
185 goto end;
186 }
187 This->initialized = TRUE;
188
189 end:
190 LeaveCriticalSection(&This->encoder->lock);
191 return hr;
192 }
193
194 static HRESULT WINAPI IcnsFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
195 UINT uiWidth, UINT uiHeight)
196 {
197 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
198 HRESULT hr = S_OK;
199
200 TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
201
202 EnterCriticalSection(&This->encoder->lock);
203
204 if (!This->initialized || This->icns_image)
205 {
206 hr = WINCODEC_ERR_WRONGSTATE;
207 goto end;
208 }
209
210 if (uiWidth != uiHeight)
211 {
212 WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth, uiHeight);
213 hr = E_INVALIDARG;
214 goto end;
215 }
216
217 switch (uiWidth)
218 {
219 case 16:
220 case 32:
221 case 48:
222 case 128:
223 case 256:
224 case 512:
225 break;
226 default:
227 WARN("cannot generate ICNS icon from %dx%d image\n", This->size, This->size);
228 hr = E_INVALIDARG;
229 goto end;
230 }
231
232 This->size = uiWidth;
233
234 end:
235 LeaveCriticalSection(&This->encoder->lock);
236 return hr;
237 }
238
239 static HRESULT WINAPI IcnsFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
240 double dpiX, double dpiY)
241 {
242 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
243 HRESULT hr = S_OK;
244
245 TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
246
247 EnterCriticalSection(&This->encoder->lock);
248
249 if (!This->initialized || This->icns_image)
250 {
251 hr = WINCODEC_ERR_WRONGSTATE;
252 goto end;
253 }
254
255 end:
256 LeaveCriticalSection(&This->encoder->lock);
257 return S_OK;
258 }
259
260 static HRESULT WINAPI IcnsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
261 WICPixelFormatGUID *pPixelFormat)
262 {
263 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
264 HRESULT hr = S_OK;
265
266 TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
267
268 EnterCriticalSection(&This->encoder->lock);
269
270 if (!This->initialized || This->icns_image)
271 {
272 hr = WINCODEC_ERR_WRONGSTATE;
273 goto end;
274 }
275
276 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
277
278 end:
279 LeaveCriticalSection(&This->encoder->lock);
280 return S_OK;
281 }
282
283 static HRESULT WINAPI IcnsFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
284 UINT cCount, IWICColorContext **ppIColorContext)
285 {
286 FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
287 return E_NOTIMPL;
288 }
289
290 static HRESULT WINAPI IcnsFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
291 IWICPalette *pIPalette)
292 {
293 FIXME("(%p,%p): stub\n", iface, pIPalette);
294 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
295 }
296
297 static HRESULT WINAPI IcnsFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
298 IWICBitmapSource *pIThumbnail)
299 {
300 FIXME("(%p,%p): stub\n", iface, pIThumbnail);
301 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
302 }
303
304 static HRESULT WINAPI IcnsFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
305 UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
306 {
307 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
308 HRESULT hr = S_OK;
309 UINT i;
310
311 TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
312
313 EnterCriticalSection(&This->encoder->lock);
314
315 if (!This->initialized || !This->size)
316 {
317 hr = WINCODEC_ERR_WRONGSTATE;
318 goto end;
319 }
320 if (lineCount == 0 || lineCount + This->lines_written > This->size)
321 {
322 hr = E_INVALIDARG;
323 goto end;
324 }
325
326 if (!This->icns_image)
327 {
328 switch (This->size)
329 {
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;
336 default:
337 WARN("cannot generate ICNS icon from %dx%d image\n", This->size, This->size);
338 hr = E_INVALIDARG;
339 goto end;
340 }
341 This->icns_image = HeapAlloc(GetProcessHeap(), 0, This->size * This->size * 4);
342 if (!This->icns_image)
343 {
344 WARN("failed to allocate image buffer\n");
345 hr = E_FAIL;
346 goto end;
347 }
348 }
349
350 for (i = 0; i < lineCount; i++)
351 {
352 BYTE *src_row, *dst_row;
353 UINT j;
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)
358 {
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];
363 }
364 }
365 This->lines_written += lineCount;
366
367 end:
368 LeaveCriticalSection(&This->encoder->lock);
369 return hr;
370 }
371
372 static HRESULT WINAPI IcnsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
373 IWICBitmapSource *pIBitmapSource, WICRect *prc)
374 {
375 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
376 HRESULT hr;
377
378 TRACE("(%p,%p,%p)\n", iface, pIBitmapSource, prc);
379
380 if (!This->initialized)
381 return WINCODEC_ERR_WRONGSTATE;
382
383 hr = configure_write_source(iface, pIBitmapSource, &prc,
384 &GUID_WICPixelFormat32bppBGRA, This->size, This->size,
385 1.0, 1.0);
386
387 if (SUCCEEDED(hr))
388 {
389 hr = write_source(iface, pIBitmapSource, prc,
390 &GUID_WICPixelFormat32bppBGRA, 32, This->size, This->size);
391 }
392
393 return hr;
394 }
395
396 static HRESULT WINAPI IcnsFrameEncode_Commit(IWICBitmapFrameEncode *iface)
397 {
398 IcnsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
399 Handle handle;
400 OSErr ret;
401 HRESULT hr = S_OK;
402
403 TRACE("(%p): stub\n", iface);
404
405 EnterCriticalSection(&This->encoder->lock);
406
407 if (!This->icns_image || This->lines_written != This->size || This->committed)
408 {
409 hr = WINCODEC_ERR_WRONGSTATE;
410 goto end;
411 }
412
413 ret = PtrToHand(This->icns_image, &handle, This->size * This->size * 4);
414 if (ret != noErr || !handle)
415 {
416 WARN("PtrToHand failed with error %d\n", ret);
417 hr = E_FAIL;
418 goto end;
419 }
420
421 ret = SetIconFamilyData(This->encoder->icns_family, This->icns_type, handle);
422 DisposeHandle(handle);
423
424 if (ret != noErr)
425 {
426 WARN("SetIconFamilyData failed for image with error %d\n", ret);
427 hr = E_FAIL;
428 goto end;
429 }
430
431 This->committed = TRUE;
432 This->encoder->any_frame_committed = TRUE;
433 This->encoder->outstanding_commits--;
434
435 end:
436 LeaveCriticalSection(&This->encoder->lock);
437 return hr;
438 }
439
440 static HRESULT WINAPI IcnsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
441 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
442 {
443 FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
444 return E_NOTIMPL;
445 }
446
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
462 };
463
464 static HRESULT WINAPI IcnsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
465 void **ppv)
466 {
467 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
468 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
469
470 if (!ppv) return E_INVALIDARG;
471
472 if (IsEqualIID(&IID_IUnknown, iid) ||
473 IsEqualIID(&IID_IWICBitmapEncoder, iid))
474 {
475 *ppv = This;
476 }
477 else
478 {
479 *ppv = NULL;
480 return E_NOINTERFACE;
481 }
482
483 IUnknown_AddRef((IUnknown*)*ppv);
484 return S_OK;
485 }
486
487 static ULONG WINAPI IcnsEncoder_AddRef(IWICBitmapEncoder *iface)
488 {
489 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
490 ULONG ref = InterlockedIncrement(&This->ref);
491
492 TRACE("(%p) refcount=%u\n", iface, ref);
493
494 return ref;
495 }
496
497 static ULONG WINAPI IcnsEncoder_Release(IWICBitmapEncoder *iface)
498 {
499 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
500 ULONG ref = InterlockedDecrement(&This->ref);
501
502 TRACE("(%p) refcount=%u\n", iface, ref);
503
504 if (ref == 0)
505 {
506 This->lock.DebugInfo->Spare[0] = 0;
507 DeleteCriticalSection(&This->lock);
508 if (This->icns_family)
509 DisposeHandle((Handle)This->icns_family);
510 if (This->stream)
511 IStream_Release(This->stream);
512 HeapFree(GetProcessHeap(), 0, This);
513 }
514
515 return ref;
516 }
517
518 static HRESULT WINAPI IcnsEncoder_Initialize(IWICBitmapEncoder *iface,
519 IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
520 {
521 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
522 HRESULT hr = S_OK;
523
524 TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
525
526 EnterCriticalSection(&This->lock);
527
528 if (This->icns_family)
529 {
530 hr = WINCODEC_ERR_WRONGSTATE;
531 goto end;
532 }
533 This->icns_family = (IconFamilyHandle)NewHandle(0);
534 if (!This->icns_family)
535 {
536 WARN("error creating icns family\n");
537 hr = E_FAIL;
538 goto end;
539 }
540 IStream_AddRef(pIStream);
541 This->stream = pIStream;
542
543 end:
544 LeaveCriticalSection(&This->lock);
545
546 return hr;
547 }
548
549 static HRESULT WINAPI IcnsEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
550 GUID *pguidContainerFormat)
551 {
552 FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidContainerFormat));
553 return E_NOTIMPL;
554 }
555
556 static HRESULT WINAPI IcnsEncoder_GetEncoderInfo(IWICBitmapEncoder *iface,
557 IWICBitmapEncoderInfo **ppIEncoderInfo)
558 {
559 FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo);
560 return E_NOTIMPL;
561 }
562
563 static HRESULT WINAPI IcnsEncoder_SetColorContexts(IWICBitmapEncoder *iface,
564 UINT cCount, IWICColorContext **ppIColorContext)
565 {
566 FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
567 return E_NOTIMPL;
568 }
569
570 static HRESULT WINAPI IcnsEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
571 {
572 TRACE("(%p,%p)\n", iface, pIPalette);
573 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
574 }
575
576 static HRESULT WINAPI IcnsEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
577 {
578 TRACE("(%p,%p)\n", iface, pIThumbnail);
579 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
580 }
581
582 static HRESULT WINAPI IcnsEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
583 {
584 TRACE("(%p,%p)\n", iface, pIPreview);
585 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
586 }
587
588 static HRESULT WINAPI IcnsEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
589 IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
590 {
591 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
592 HRESULT hr = S_OK;
593 IcnsFrameEncode *frameEncode = NULL;
594
595 TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
596
597 EnterCriticalSection(&This->lock);
598
599 if (!This->icns_family)
600 {
601 hr = WINCODEC_ERR_NOTINITIALIZED;
602 goto end;
603 }
604
605 hr = CreatePropertyBag2(NULL, 0, ppIEncoderOptions);
606 if (FAILED(hr))
607 goto end;
608
609 frameEncode = HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsFrameEncode));
610 if (frameEncode == NULL)
611 {
612 hr = E_OUTOFMEMORY;
613 goto end;
614 }
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);
626
627 end:
628 LeaveCriticalSection(&This->lock);
629
630 return hr;
631 }
632
633 static HRESULT WINAPI IcnsEncoder_Commit(IWICBitmapEncoder *iface)
634 {
635 IcnsEncoder *This = impl_from_IWICBitmapEncoder(iface);
636 size_t buffer_size;
637 HRESULT hr = S_OK;
638 ULONG byteswritten;
639
640 TRACE("(%p)\n", iface);
641
642 EnterCriticalSection(&This->lock);
643
644 if (!This->any_frame_committed || This->outstanding_commits > 0 || This->committed)
645 {
646 hr = WINCODEC_ERR_WRONGSTATE;
647 goto end;
648 }
649
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)
653 {
654 WARN("writing file failed, hr = 0x%08X\n", hr);
655 hr = E_FAIL;
656 goto end;
657 }
658
659 This->committed = TRUE;
660
661 end:
662 LeaveCriticalSection(&This->lock);
663 return hr;
664 }
665
666 static HRESULT WINAPI IcnsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
667 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
668 {
669 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
670 return E_NOTIMPL;
671 }
672
673 static const IWICBitmapEncoderVtbl IcnsEncoder_Vtbl = {
674 IcnsEncoder_QueryInterface,
675 IcnsEncoder_AddRef,
676 IcnsEncoder_Release,
677 IcnsEncoder_Initialize,
678 IcnsEncoder_GetContainerFormat,
679 IcnsEncoder_GetEncoderInfo,
680 IcnsEncoder_SetColorContexts,
681 IcnsEncoder_SetPalette,
682 IcnsEncoder_SetThumbnail,
683 IcnsEncoder_SetPreview,
684 IcnsEncoder_CreateNewFrame,
685 IcnsEncoder_Commit,
686 IcnsEncoder_GetMetadataQueryWriter
687 };
688
689 HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv)
690 {
691 IcnsEncoder *This;
692 HRESULT ret;
693
694 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
695
696 *ppv = NULL;
697
698 This = HeapAlloc(GetProcessHeap(), 0, sizeof(IcnsEncoder));
699 if (!This) return E_OUTOFMEMORY;
700
701 This->IWICBitmapEncoder_iface.lpVtbl = &IcnsEncoder_Vtbl;
702 This->ref = 1;
703 This->stream = NULL;
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");
710
711 ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
712 IUnknown_Release((IUnknown*)This);
713
714 return ret;
715 }
716
717 #else /* !defined(HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H) ||
718 MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 */
719
720 HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv)
721 {
722 ERR("Trying to save ICNS picture, but ICNS support is not compiled in.\n");
723 return E_FAIL;
724 }
725
726 #endif