Vincent Povirk : gdiplus: Call GdiAlphaBlend only once per GdipFillRegion call.

Alexandre Julliard julliard at winehq.org
Tue Mar 15 11:33:55 CDT 2011


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Thu Mar 10 15:58:22 2011 -0600

gdiplus: Call GdiAlphaBlend only once per GdipFillRegion call.

---

 dlls/gdiplus/graphics.c |   93 ++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 4d059f8..83e0f24 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -3856,39 +3856,90 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
 
     if (stat == Ok)
     {
-        UINT max_size=0;
-
-        for (i=0; i<scans_count; i++)
+        if (!graphics->image)
         {
-            UINT size = scans[i].Width * scans[i].Height;
+            /* 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;
 
-            if (size > max_size)
-                max_size = size;
-        }
+            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;
 
-        pixel_data = GdipAlloc(sizeof(*pixel_data) * max_size);
-        if (!pixel_data)
-            stat = OutOfMemory;
+            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);
+            }
 
-        if (stat == Ok)
-        {
-            for (i=0; i<scans_count; i++)
+            data_width = max_x - min_x;
+            data_height = max_y - min_y;
+
+            pixel_data = GdipAlloc(sizeof(*pixel_data) * data_width * data_height);
+            if (!pixel_data)
+                stat = OutOfMemory;
+
+            if (stat == Ok)
             {
-                stat = brush_fill_pixels(graphics, brush, pixel_data, &scans[i],
-                    scans[i].Width);
+                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);
+
+                    if (stat != Ok)
+                        break;
+                }
 
                 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(graphics, min_x, min_y,
+                        (BYTE*)pixel_data, data_width, data_height,
+                        data_width * 4);
                 }
 
-                if (stat != Ok)
-                    break;
+                GdipFree(pixel_data);
             }
+        }
+        else
+        {
+            UINT max_size=0;
 
-            GdipFree(pixel_data);
+            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;
+
+            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);
+                    }
+
+                    if (stat != Ok)
+                        break;
+                }
+
+                GdipFree(pixel_data);
+            }
         }
 
         GdipFree(scans);




More information about the wine-cvs mailing list