Vincent Povirk : gdiplus: Rewrite SOFTWARE_GdipFillRegion to call brush_fill_pixels less.

Alexandre Julliard julliard at winehq.org
Tue Mar 13 13:50:34 CDT 2012


Module: wine
Branch: master
Commit: dc3a08d840186c7692cc3cae45bdd517ab099e07
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dc3a08d840186c7692cc3cae45bdd517ab099e07

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Tue Feb 14 13:50:59 2012 -0600

gdiplus: Rewrite SOFTWARE_GdipFillRegion to call brush_fill_pixels less.

---

 dlls/gdiplus/graphics.c |  186 ++++++++++++++++++++---------------------------
 1 files changed, 79 insertions(+), 107 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 6cf0a68..ddae06e 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -413,6 +413,61 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
     }
 }
 
+static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst_y,
+    const BYTE *src, INT src_width, INT src_height, INT src_stride, HRGN hregion)
+{
+    GpStatus stat=Ok;
+
+    if (graphics->image && graphics->image->type == ImageTypeBitmap)
+    {
+        int i, size;
+        RGNDATA *rgndata;
+        RECT *rects;
+
+        size = GetRegionData(hregion, 0, NULL);
+
+        rgndata = GdipAlloc(size);
+        if (!rgndata)
+            return OutOfMemory;
+
+        GetRegionData(hregion, 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,
+                &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);
+        }
+
+        GdipFree(rgndata);
+
+        return stat;
+    }
+    else if (graphics->image && graphics->image->type == ImageTypeMetafile)
+    {
+        ERR("This should not be used for metafiles; fix caller\n");
+        return NotImplemented;
+    }
+    else
+    {
+        int save;
+
+        save = SaveDC(graphics->hdc);
+
+        ExtSelectClipRgn(graphics->hdc, hregion, RGN_AND);
+
+        stat = alpha_blend_pixels(graphics, dst_x, dst_y, src, src_width,
+            src_height, src_stride);
+
+        RestoreDC(graphics->hdc, save);
+
+        return stat;
+    }
+}
+
 static ARGB blend_colors(ARGB start, ARGB end, REAL position)
 {
     ARGB result=0;
@@ -3928,12 +3983,12 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
 {
     GpStatus stat;
     GpRegion *temp_region;
-    GpMatrix *world_to_device, *identity;
+    GpMatrix *world_to_device;
     GpRectF graphics_bounds;
-    UINT scans_count, i;
-    INT dummy;
-    GpRect *scans = NULL;
     DWORD *pixel_data;
+    HRGN hregion;
+    RECT bound_rect;
+    GpRect gp_bound_rect;
 
     if (!brush_can_fill_pixels(brush))
         return NotImplemented;
@@ -3959,125 +4014,42 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
             stat = GdipCombineRegionRect(temp_region, &graphics_bounds, CombineModeIntersect);
 
         if (stat == Ok)
-            stat = GdipCreateMatrix(&identity);
-
-        if (stat == Ok)
-        {
-            stat = GdipGetRegionScansCount(temp_region, &scans_count, identity);
-
-            if (stat == Ok && scans_count != 0)
-            {
-                scans = GdipAlloc(sizeof(*scans) * scans_count);
-                if (!scans)
-                    stat = OutOfMemory;
-
-                if (stat == Ok)
-                {
-                    stat = GdipGetRegionScansI(temp_region, scans, &dummy, identity);
-
-                    if (stat != Ok)
-                        GdipFree(scans);
-                }
-            }
-
-            GdipDeleteMatrix(identity);
-        }
+            stat = GdipGetRegionHRgn(temp_region, NULL, &hregion);
 
         GdipDeleteRegion(temp_region);
     }
 
-    if (stat == Ok && scans_count == 0)
+    if (stat == Ok && GetRgnBox(hregion, &bound_rect) == NULLREGION)
+    {
+        DeleteObject(hregion);
         return Ok;
+    }
 
     if (stat == Ok)
     {
-        if (!graphics->image)
-        {
-            /* If we have to go through gdi32, use as few alpha blends as possible. */
-            INT min_x, min_y, max_x, max_y;
-            UINT data_width, data_height;
-
-            min_x = scans[0].X;
-            min_y = scans[0].Y;
-            max_x = scans[0].X+scans[0].Width;
-            max_y = scans[0].Y+scans[0].Height;
-
-            for (i=1; i<scans_count; i++)
-            {
-                min_x = min(min_x, scans[i].X);
-                min_y = min(min_y, scans[i].Y);
-                max_x = max(max_x, scans[i].X+scans[i].Width);
-                max_y = max(max_y, scans[i].Y+scans[i].Height);
-            }
-
-            data_width = max_x - min_x;
-            data_height = max_y - min_y;
+        gp_bound_rect.X = bound_rect.left;
+        gp_bound_rect.Y = bound_rect.top;
+        gp_bound_rect.Width = bound_rect.right - bound_rect.left;
+        gp_bound_rect.Height = bound_rect.bottom - bound_rect.top;
 
-            pixel_data = GdipAlloc(sizeof(*pixel_data) * data_width * data_height);
-            if (!pixel_data)
-                stat = OutOfMemory;
-
-            if (stat == Ok)
-            {
-                for (i=0; i<scans_count; i++)
-                {
-                    stat = brush_fill_pixels(graphics, brush,
-                        pixel_data + (scans[i].X - min_x) + (scans[i].Y - min_y) * data_width,
-                        &scans[i], data_width);
+        pixel_data = GdipAlloc(sizeof(*pixel_data) * gp_bound_rect.Width * gp_bound_rect.Height);
+        if (!pixel_data)
+            stat = OutOfMemory;
 
-                    if (stat != Ok)
-                        break;
-                }
-
-                if (stat == Ok)
-                {
-                    stat = alpha_blend_pixels(graphics, min_x, min_y,
-                        (BYTE*)pixel_data, data_width, data_height,
-                        data_width * 4);
-                }
-
-                GdipFree(pixel_data);
-            }
-        }
-        else
+        if (stat == Ok)
         {
-            UINT max_size=0;
-
-            for (i=0; i<scans_count; i++)
-            {
-                UINT size = scans[i].Width * scans[i].Height;
-
-                if (size > max_size)
-                    max_size = size;
-            }
-
-            pixel_data = GdipAlloc(sizeof(*pixel_data) * max_size);
-            if (!pixel_data)
-                stat = OutOfMemory;
+            stat = brush_fill_pixels(graphics, brush, pixel_data,
+                &gp_bound_rect, gp_bound_rect.Width);
 
             if (stat == Ok)
-            {
-                for (i=0; i<scans_count; i++)
-                {
-                    stat = brush_fill_pixels(graphics, brush, pixel_data, &scans[i],
-                        scans[i].Width);
-
-                    if (stat == Ok)
-                    {
-                        stat = alpha_blend_pixels(graphics, scans[i].X, scans[i].Y,
-                            (BYTE*)pixel_data, scans[i].Width, scans[i].Height,
-                            scans[i].Width * 4);
-                    }
+                stat = alpha_blend_pixels_hrgn(graphics, gp_bound_rect.X,
+                    gp_bound_rect.Y, (BYTE*)pixel_data, gp_bound_rect.Width,
+                    gp_bound_rect.Height, gp_bound_rect.Width * 4, hregion);
 
-                    if (stat != Ok)
-                        break;
-                }
-
-                GdipFree(pixel_data);
-            }
+            GdipFree(pixel_data);
         }
 
-        GdipFree(scans);
+        DeleteObject(hregion);
     }
 
     return stat;




More information about the wine-cvs mailing list