Vincent Povirk : gdiplus: Implement partially transparent solid fill brushes.

Alexandre Julliard julliard at winehq.org
Thu May 21 09:35:53 CDT 2009


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Wed May 20 11:24:18 2009 -0500

gdiplus: Implement partially transparent solid fill brushes.

---

 dlls/gdiplus/brush.c           |    9 +++++++++
 dlls/gdiplus/gdiplus.c         |   36 ++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/gdiplus_private.h |    2 ++
 dlls/gdiplus/graphics.c        |   34 ++++++++++++++++++++++++++++++++++
 4 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/dlls/gdiplus/brush.c b/dlls/gdiplus/brush.c
index 76e6a0f..92052f7 100644
--- a/dlls/gdiplus/brush.c
+++ b/dlls/gdiplus/brush.c
@@ -46,13 +46,19 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
 
     switch(brush->bt){
         case BrushTypeSolidColor:
+        {
+            GpSolidFill *fill;
             *clone = GdipAlloc(sizeof(GpSolidFill));
             if (!*clone) return OutOfMemory;
 
+            fill = (GpSolidFill*)*clone;
+
             memcpy(*clone, brush, sizeof(GpSolidFill));
 
             (*clone)->gdibrush = CreateBrushIndirect(&(*clone)->lb);
+            fill->bmp = ARGB2BMP(fill->color);
             break;
+        }
         case BrushTypeHatchFill:
             *clone = GdipAlloc(sizeof(GpHatch));
             if (!*clone) return OutOfMemory;
@@ -560,6 +566,7 @@ GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
     (*sf)->brush.gdibrush = CreateSolidBrush(col);
     (*sf)->brush.bt = BrushTypeSolidColor;
     (*sf)->color = color;
+    (*sf)->bmp = ARGB2BMP(color);
 
     return Ok;
 }
@@ -842,6 +849,8 @@ GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
             GdipFree(((GpPathGradient*) brush)->blendpos);
             break;
         case BrushTypeSolidColor:
+            if (((GpSolidFill*)brush)->bmp)
+                DeleteObject(((GpSolidFill*)brush)->bmp);
             break;
         case BrushTypeLinearGradient:
             GdipFree(((GpLineGradient*)brush)->blendfac);
diff --git a/dlls/gdiplus/gdiplus.c b/dlls/gdiplus/gdiplus.c
index 950e002..06019a2 100644
--- a/dlls/gdiplus/gdiplus.c
+++ b/dlls/gdiplus/gdiplus.c
@@ -258,6 +258,42 @@ COLORREF ARGB2COLORREF(ARGB color)
            ((color & 0xff0000) >> 16);
 }
 
+HBITMAP ARGB2BMP(ARGB color)
+{
+    HDC hdc;
+    BITMAPINFO bi;
+    HBITMAP result;
+    RGBQUAD *bits;
+    int alpha;
+
+    if ((color & 0xff000000) == 0xff000000) return 0;
+
+    hdc = CreateCompatibleDC(NULL);
+
+    bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+    bi.bmiHeader.biWidth = 1;
+    bi.bmiHeader.biHeight = 1;
+    bi.bmiHeader.biPlanes = 1;
+    bi.bmiHeader.biBitCount = 32;
+    bi.bmiHeader.biCompression = BI_RGB;
+    bi.bmiHeader.biSizeImage = 0;
+    bi.bmiHeader.biXPelsPerMeter = 0;
+    bi.bmiHeader.biYPelsPerMeter = 0;
+    bi.bmiHeader.biClrUsed = 0;
+    bi.bmiHeader.biClrImportant = 0;
+
+    result = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void*)&bits, NULL, 0);
+
+    bits[0].rgbReserved = alpha = (color>>24)&0xff;
+    bits[0].rgbRed = ((color>>16)&0xff)*alpha/255;
+    bits[0].rgbGreen = ((color>>8)&0xff)*alpha/255;
+    bits[0].rgbBlue = (color&0xff)*alpha/255;
+
+    DeleteDC(hdc);
+
+    return result;
+}
+
 /* Like atan2, but puts angle in correct quadrant if dx is 0. */
 REAL gdiplus_atan2(REAL dy, REAL dx)
 {
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index af20c75..95133ca 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -41,6 +41,7 @@
 #define TENSION_CONST (0.3)
 
 COLORREF ARGB2COLORREF(ARGB color);
+HBITMAP ARGB2BMP(ARGB color);
 extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
     REAL startAngle, REAL sweepAngle);
 extern REAL gdiplus_atan2(REAL dy, REAL dx);
@@ -126,6 +127,7 @@ struct GpHatch{
 struct GpSolidFill{
     GpBrush brush;
     ARGB color;
+    HBITMAP bmp;
 };
 
 struct GpPathGradient{
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 78700ea..1c128d4 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -346,6 +346,40 @@ static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
         }
         break;
     }
+    case BrushTypeSolidColor:
+    {
+        GpSolidFill *fill = (GpSolidFill*)brush;
+        if (fill->bmp)
+        {
+            RECT rc;
+            /* partially transparent fill */
+
+            SelectClipPath(graphics->hdc, RGN_AND);
+            if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
+            {
+                HDC hdc = CreateCompatibleDC(NULL);
+                HBITMAP oldbmp;
+                BLENDFUNCTION bf;
+
+                if (!hdc) break;
+
+                oldbmp = SelectObject(hdc, fill->bmp);
+
+                bf.BlendOp = AC_SRC_OVER;
+                bf.BlendFlags = 0;
+                bf.SourceConstantAlpha = 255;
+                bf.AlphaFormat = AC_SRC_ALPHA;
+
+                GdiAlphaBlend(graphics->hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, hdc, 0, 0, 1, 1, bf);
+
+                SelectObject(hdc, oldbmp);
+                DeleteDC(hdc);
+            }
+
+            break;
+        }
+        /* else fall through */
+    }
     default:
         SelectObject(graphics->hdc, brush->gdibrush);
         FillPath(graphics->hdc);




More information about the wine-cvs mailing list