gdiplus: Implement partially transparent solid fill brushes.

This commit is contained in:
Vincent Povirk 2009-05-20 11:24:18 -05:00 committed by Alexandre Julliard
parent 122af07a30
commit 60167dfb74
4 changed files with 81 additions and 0 deletions

View file

@ -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);

View file

@ -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)
{

View file

@ -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{

View file

@ -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);