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