From 8f3158a9812821fd951cc17418a170b6d2e4aed8 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 24 Aug 2009 17:05:24 -0500 Subject: [PATCH] gdiplus: reimplement GdipCreateBitmapFromHICON based on RGBA bitmaps --- dlls/gdiplus/image.c | 170 +++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 146 insertions(+), 24 deletions(-) diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 164ab29..730d981 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -625,48 +625,170 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height, GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap) { - HICON icon_copy; + GpStatus stat; ICONINFO iinfo; - PICTDESC desc; + BITMAP bm; + int ret; + UINT width, height; + GpRect rect; + BitmapData lockeddata; + HDC screendc; + BOOL has_alpha; + int x, y; + BYTE *bits; + BITMAPINFOHEADER bih; + DWORD *src; + BYTE *dst_row; + DWORD *dst; TRACE("%p, %p\n", hicon, bitmap); if(!bitmap || !GetIconInfo(hicon, &iinfo)) + { + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); return InvalidParameter; + } - *bitmap = GdipAlloc(sizeof(GpBitmap)); - if(!*bitmap) return OutOfMemory; + /* get the size of the icon */ + ret = GetObjectA(iinfo.hbmColor ? iinfo.hbmColor : iinfo.hbmMask, sizeof(bm), &bm); + if (ret == 0) { + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + return GenericError; + } - icon_copy = CreateIconIndirect(&iinfo); + width = bm.bmWidth; - if(!icon_copy){ - GdipFree(*bitmap); - return InvalidParameter; + if (iinfo.hbmColor) + height = abs(bm.bmHeight); + else /* combined bitmap + mask */ + height = abs(bm.bmHeight) / 2; + + bits = HeapAlloc(GetProcessHeap(), 0, 4*width*height); + if (!bits) { + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + return OutOfMemory; } - desc.cbSizeofstruct = sizeof(PICTDESC); - desc.picType = PICTYPE_ICON; - desc.u.icon.hicon = icon_copy; + stat = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, NULL, bitmap); + if (stat != Ok) { + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + HeapFree(GetProcessHeap(), 0, bits); + return stat; + } - if(OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, - (LPVOID*) &((*bitmap)->image.picture)) != S_OK){ - DestroyIcon(icon_copy); - GdipFree(*bitmap); - return GenericError; + rect.X = 0; + rect.Y = 0; + rect.Width = width; + rect.Height = height; + + stat = GdipBitmapLockBits(*bitmap, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &lockeddata); + if (stat != Ok) { + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + HeapFree(GetProcessHeap(), 0, bits); + GdipDisposeImage((GpImage*)*bitmap); + return stat; } - (*bitmap)->format = PixelFormat32bppARGB; - (*bitmap)->image.type = ImageTypeBitmap; - (*bitmap)->image.flags = ImageFlagsNone; - (*bitmap)->width = ipicture_pixel_width((*bitmap)->image.picture); - (*bitmap)->height = ipicture_pixel_height((*bitmap)->image.picture); - (*bitmap)->hbitmap = NULL; - (*bitmap)->hdc = NULL; - (*bitmap)->bits = NULL; + bih.biSize = sizeof(bih); + bih.biWidth = width; + bih.biHeight = -height; + bih.biPlanes = 1; + bih.biBitCount = 32; + bih.biCompression = BI_RGB; + bih.biSizeImage = 0; + bih.biXPelsPerMeter = 0; + bih.biYPelsPerMeter = 0; + bih.biClrUsed = 0; + bih.biClrImportant = 0; + + screendc = GetDC(0); + if (iinfo.hbmColor) + { + GetDIBits(screendc, iinfo.hbmColor, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); + + if (bm.bmBitsPixel == 32) + { + has_alpha = FALSE; + + /* If any pixel has a non-zero alpha, ignore hbmMask */ + src = (DWORD*)bits; + for (x=0; x