From 895c6d8e1ea81ae10f927463692c01bffd58fda5 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 28 Aug 2009 17:21:10 -0500 Subject: [PATCH] gdiplus: Use AlphaBlend for 32-bit images with alpha channels. --- dlls/gdiplus/gdiplus.c | 19 +++++++++ dlls/gdiplus/gdiplus_private.h | 3 ++ dlls/gdiplus/graphics.c | 71 ++++++++++++++++++++++++++++------ 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/dlls/gdiplus/gdiplus.c b/dlls/gdiplus/gdiplus.c index 06019a24e35..ec956f34f57 100644 --- a/dlls/gdiplus/gdiplus.c +++ b/dlls/gdiplus/gdiplus.c @@ -399,6 +399,25 @@ BOOL lengthen_path(GpPath *path, INT len) return TRUE; } +void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, + BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) +{ + UINT x, y; + for (y=0; yhdc; - bm_is_selected = (hdc != 0); - - if (!bm_is_selected) + if (bitmap->format == PixelFormat32bppARGB) { + BITMAPINFOHEADER bih; + BYTE *temp_bits; + + /* we need a bitmap with premultiplied alpha */ hdc = CreateCompatibleDC(0); - old_hbm = SelectObject(hdc, bitmap->hbitmap); + temp_hdc = 1; + temp_bitmap = 1; + + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = bitmap->width; + bih.biHeight = -bitmap->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; + + hbitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, + (void**)&temp_bits, NULL, 0); + + convert_32bppARGB_to_32bppPARGB(bitmap->width, bitmap->height, + temp_bits, bitmap->width*4, bitmap->bits, bitmap->stride); + } + else + { + hbitmap = bitmap->hbitmap; + hdc = bitmap->hdc; + temp_hdc = (hdc == 0); } - /* FIXME: maybe alpha blend depending on the format */ - StretchBlt(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y, - hdc, srcx*dx, srcy*dy, srcwidth*dx, srcheight*dy, SRCCOPY); + if (temp_hdc) + { + if (!hdc) hdc = CreateCompatibleDC(0); + old_hbm = SelectObject(hdc, hbitmap); + } - if (!bm_is_selected) + if (bitmap->format == PixelFormat32bppARGB || bitmap->format == PixelFormat32bppPARGB) + { + BLENDFUNCTION bf; + + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + + GdiAlphaBlend(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y, + hdc, srcx*dx, srcy*dy, srcwidth*dx, srcheight*dy, bf); + } + else + { + StretchBlt(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y, + hdc, srcx*dx, srcy*dy, srcwidth*dx, srcheight*dy, SRCCOPY); + } + + if (temp_hdc) { SelectObject(hdc, old_hbm); DeleteDC(hdc); } + + if (temp_bitmap) + DeleteObject(hbitmap); } else {