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