From 423d50eb3b4edd3140880ed2ccbe9d6ca665dcb5 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Tue, 27 Nov 2012 13:42:07 -0600 Subject: [PATCH] gdiplus: Use clipping region in alpha_blend_pixels. --- dlls/gdiplus/graphics.c | 161 ++++++++++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 59 deletions(-) diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index f56682b0e28..247b17d9046 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -359,68 +359,67 @@ static void gdi_alpha_blend(GpGraphics *graphics, INT dst_x, INT dst_y, INT dst_ } } +static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn) +{ + return GdipGetRegionHRgn(graphics->clip, graphics, hrgn); +} + /* Draw non-premultiplied ARGB data to the given graphics object */ -static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, +static GpStatus alpha_blend_bmp_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, const BYTE *src, INT src_width, INT src_height, INT src_stride) { - if (graphics->image && graphics->image->type == ImageTypeBitmap) - { - GpBitmap *dst_bitmap = (GpBitmap*)graphics->image; - INT x, y; + GpBitmap *dst_bitmap = (GpBitmap*)graphics->image; + INT x, y; - for (x=0; ximage && graphics->image->type == ImageTypeMetafile) - { - ERR("This should not be used for metafiles; fix caller\n"); - return NotImplemented; } - else - { - HDC hdc; - HBITMAP hbitmap; - BITMAPINFOHEADER bih; - BYTE *temp_bits; - - hdc = CreateCompatibleDC(0); - - bih.biSize = sizeof(BITMAPINFOHEADER); - bih.biWidth = src_width; - bih.biHeight = -src_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(src_width, src_height, temp_bits, - 4 * src_width, src, src_stride); - - SelectObject(hdc, hbitmap); - gdi_alpha_blend(graphics, dst_x, dst_y, src_width, src_height, - hdc, 0, 0, src_width, src_height); - DeleteDC(hdc); - DeleteObject(hbitmap); - return Ok; - } + return Ok; +} + +static GpStatus alpha_blend_hdc_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, + const BYTE *src, INT src_width, INT src_height, INT src_stride) +{ + HDC hdc; + HBITMAP hbitmap; + BITMAPINFOHEADER bih; + BYTE *temp_bits; + + hdc = CreateCompatibleDC(0); + + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = src_width; + bih.biHeight = -src_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(src_width, src_height, temp_bits, + 4 * src_width, src, src_stride); + + SelectObject(hdc, hbitmap); + gdi_alpha_blend(graphics, dst_x, dst_y, src_width, src_height, + hdc, 0, 0, src_width, src_height); + DeleteDC(hdc); + DeleteObject(hbitmap); + + return Ok; } static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst_y, @@ -433,20 +432,44 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst int i, size; RGNDATA *rgndata; RECT *rects; + HRGN hrgn, visible_rgn; + + hrgn = CreateRectRgn(dst_x, dst_y, dst_x + src_width, dst_y + src_height); + if (!hrgn) + return OutOfMemory; + + stat = get_clip_hrgn(graphics, &visible_rgn); + if (stat != Ok) + { + DeleteObject(hrgn); + return stat; + } + + if (visible_rgn) + { + CombineRgn(hrgn, hrgn, visible_rgn, RGN_AND); + DeleteObject(visible_rgn); + } - size = GetRegionData(hregion, 0, NULL); + if (hregion) + CombineRgn(hrgn, hrgn, hregion, RGN_AND); + + size = GetRegionData(hrgn, 0, NULL); rgndata = GdipAlloc(size); if (!rgndata) + { + DeleteObject(hrgn); return OutOfMemory; + } - GetRegionData(hregion, size, rgndata); + GetRegionData(hrgn, size, rgndata); rects = (RECT*)&rgndata->Buffer; for (i=0; stat == Ok && irdh.nCount; i++) { - stat = alpha_blend_pixels(graphics, rects[i].left, rects[i].top, + stat = alpha_blend_bmp_pixels(graphics, rects[i].left, rects[i].top, &src[(rects[i].left - dst_x) * 4 + (rects[i].top - dst_y) * src_stride], rects[i].right - rects[i].left, rects[i].bottom - rects[i].top, src_stride); @@ -454,6 +477,8 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst GdipFree(rgndata); + DeleteObject(hrgn); + return stat; } else if (graphics->image && graphics->image->type == ImageTypeMetafile) @@ -463,21 +488,39 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst } else { + HRGN hrgn; int save; + stat = get_clip_hrgn(graphics, &hrgn); + + if (stat != Ok) + return stat; + save = SaveDC(graphics->hdc); - ExtSelectClipRgn(graphics->hdc, hregion, RGN_AND); + if (hrgn) + ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); - stat = alpha_blend_pixels(graphics, dst_x, dst_y, src, src_width, + if (hregion) + ExtSelectClipRgn(graphics->hdc, hregion, RGN_AND); + + stat = alpha_blend_hdc_pixels(graphics, dst_x, dst_y, src, src_width, src_height, src_stride); RestoreDC(graphics->hdc, save); + DeleteObject(hrgn); + return stat; } } +static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, + const BYTE *src, INT src_width, INT src_height, INT src_stride) +{ + return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL); +} + static ARGB blend_colors(ARGB start, ARGB end, REAL position) { ARGB result=0; -- 2.11.4.GIT