From 1cdda642da5575eebec1f8c769256b4df0eee53e Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 20 May 2009 11:24:18 -0500 Subject: [PATCH] gdiplus: implement partially transparent solid fill brushes --- dlls/gdiplus/brush.c | 9 +++++++++ dlls/gdiplus/gdiplus.c | 35 +++++++++++++++++++++++++++++++++++ dlls/gdiplus/gdiplus_private.h | 2 ++ dlls/gdiplus/graphics.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 80 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..b287b9b 100644 --- a/dlls/gdiplus/gdiplus.c +++ b/dlls/gdiplus/gdiplus.c @@ -258,6 +258,41 @@ COLORREF ARGB2COLORREF(ARGB color) ((color & 0xff0000) >> 16); } +HBITMAP ARGB2BMP(ARGB color) +{ + HDC hdc; + BITMAPINFO bi; + HBITMAP result; + RGBQUAD *bits; + + 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].rgbRed = (color>>16)&0xff; + bits[0].rgbGreen = (color>>8)&0xff; + bits[0].rgbBlue = color&0xff; + bits[0].rgbReserved = (color>>24)&0xff; + + 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..2dc0250 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); -- 1.5.4.3