gdiplus: Use clipping region in alpha_blend_pixels.

Vincent Povirk madewokherd at gmail.com
Tue Nov 27 13:45:45 CST 2012


-------------- next part --------------
From 21bf3ac38f3f60bcff0ecf40e753d9edc86077b6 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
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 f56682b..247b17d 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; x<src_width; x++)
+    for (x=0; x<src_width; x++)
+    {
+        for (y=0; y<src_height; y++)
         {
-            for (y=0; y<src_height; y++)
-            {
-                ARGB dst_color, src_color;
-                GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color);
-                src_color = ((ARGB*)(src + src_stride * y))[x];
-                GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color));
-            }
+            ARGB dst_color, src_color;
+            GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color);
+            src_color = ((ARGB*)(src + src_stride * y))[x];
+            GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color));
         }
-
-        return Ok;
-    }
-    else if (graphics->image && 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 && i<rgndata->rdh.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;
-- 
1.7.10.4


More information about the wine-patches mailing list