Vincent Povirk : gdiplus: Use a helper function to draw image data from bitmaps in software.

Alexandre Julliard julliard at winehq.org
Fri Apr 16 10:56:01 CDT 2010


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Thu Apr 15 14:11:07 2010 -0500

gdiplus: Use a helper function to draw image data from bitmaps in software.

This will make it possible to use the same codepath for non-bitmap graphics
objects and to create a software implementation for other drawing operations.

---

 dlls/gdiplus/graphics.c |   60 +++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 7b3f64f..6a1dc10 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -173,6 +173,35 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti,
     }
 }
 
+/* Draw non-premultiplied ARGB data to the given graphics object */
+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)
+{
+    if (graphics->image && graphics->image->type == ImageTypeBitmap)
+    {
+        GpBitmap *dst_bitmap = (GpBitmap*)graphics->image;
+        INT x, y;
+
+        for (x=0; x<src_width; x++)
+        {
+            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));
+            }
+        }
+
+        return Ok;
+    }
+    else
+    {
+        ERR("Not implemented for non-bitmap DC's\n");
+        return GenericError;
+    }
+}
+
 static ARGB blend_colors(ARGB start, ARGB end, REAL position)
 {
     ARGB result=0;
@@ -1939,9 +1968,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
         if (use_software)
         {
             RECT src_area, dst_area;
-            int i, x, y;
+            int i, x, y, stride;
             GpMatrix *dst_to_src;
             REAL m11, m12, m21, m22, mdx, mdy;
+            LPBYTE data;
 
             src_area.left = srcx*dx;
             src_area.top = srcy*dy;
@@ -1975,13 +2005,22 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
                 return stat;
             }
 
+            data = GdipAlloc(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top));
+            if (!data)
+            {
+                GdipDeleteMatrix(dst_to_src);
+                return OutOfMemory;
+            }
+
+            stride = sizeof(ARGB) * (dst_area.right - dst_area.left);
+
             for (x=dst_area.left; x<dst_area.right; x++)
             {
                 for (y=dst_area.top; y<dst_area.bottom; y++)
                 {
                     GpPointF src_pointf;
                     int src_x, src_y;
-                    ARGB src_color, dst_color;
+                    ARGB *src_color;
 
                     src_pointf.X = x;
                     src_pointf.Y = y;
@@ -1991,18 +2030,25 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
                     src_x = roundr(src_pointf.X);
                     src_y = roundr(src_pointf.Y);
 
+                    src_color = (ARGB*)(data + stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
+
                     if (src_x < src_area.left || src_x >= src_area.right ||
                         src_y < src_area.top || src_y >= src_area.bottom)
                         /* FIXME: Use wrapmode */
-                        continue;
-
-                    GdipBitmapGetPixel(bitmap, src_x, src_y, &src_color);
-                    GdipBitmapGetPixel((GpBitmap*)graphics->image, x, y, &dst_color);
-                    GdipBitmapSetPixel((GpBitmap*)graphics->image, x, y, color_over(dst_color, src_color));
+                        *src_color = 0;
+                    else
+                        GdipBitmapGetPixel(bitmap, src_x, src_y, src_color);
                 }
             }
 
             GdipDeleteMatrix(dst_to_src);
+
+            stat = alpha_blend_pixels(graphics, dst_area.left, dst_area.top,
+                data, dst_area.right - dst_area.left, dst_area.bottom - dst_area.top, stride);
+
+            GdipFree(data);
+
+            return stat;
         }
         else
         {




More information about the wine-cvs mailing list