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