Commit 0d7bc4b3 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

gdiplus: Create GDI brush only when needed.

parent 7a9fce25
......@@ -55,7 +55,6 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
memcpy(*clone, brush, sizeof(GpSolidFill));
(*clone)->gdibrush = CreateBrushIndirect(&(*clone)->lb);
fill->bmp = ARGB2BMP(fill->color);
break;
}
......@@ -123,8 +122,6 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
memcpy(dest, src, sizeof(GpLineGradient));
dest->brush.gdibrush = CreateSolidBrush(dest->brush.lb.lbColor);
count = dest->blendcount;
dest->blendfac = GdipAlloc(count * sizeof(REAL));
dest->blendpos = GdipAlloc(count * sizeof(REAL));
......@@ -142,7 +139,6 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
GdipFree(dest->blendpos);
GdipFree(dest->pblendcolor);
GdipFree(dest->pblendpos);
DeleteObject(dest->brush.gdibrush);
GdipFree(dest);
return OutOfMemory;
}
......@@ -241,9 +237,6 @@ GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result)
*/
GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush)
{
COLORREF fgcol = ARGB2COLORREF(forecol);
GpStatus stat = Ok;
TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush);
if(!brush) return InvalidParameter;
......@@ -251,80 +244,13 @@ GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, AR
*brush = GdipAlloc(sizeof(GpHatch));
if (!*brush) return OutOfMemory;
if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
{
HBITMAP hbmp;
HDC hdc;
BITMAPINFOHEADER bmih;
DWORD* bits;
int x, y;
hdc = CreateCompatibleDC(0);
if (hdc)
{
bmih.biSize = sizeof(bmih);
bmih.biWidth = 8;
bmih.biHeight = 8;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
if (hbmp)
{
for (y=0; y<8; y++)
for (x=0; x<8; x++)
if ((HatchBrushes[hatchstyle][y] & (0x80 >> x)) != 0)
bits[y*8+x] = forecol;
else
bits[y*8+x] = backcol;
}
else
stat = GenericError;
DeleteDC(hdc);
}
else
stat = GenericError;
if (stat == Ok)
{
(*brush)->brush.lb.lbStyle = BS_PATTERN;
(*brush)->brush.lb.lbColor = 0;
(*brush)->brush.lb.lbHatch = (ULONG_PTR)hbmp;
(*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
DeleteObject(hbmp);
}
}
else
{
FIXME("Unimplemented hatch style %d\n", hatchstyle);
(*brush)->brush.lb.lbStyle = BS_SOLID;
(*brush)->brush.lb.lbColor = fgcol;
(*brush)->brush.lb.lbHatch = 0;
(*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
}
if (stat == Ok)
{
(*brush)->brush.bt = BrushTypeHatchFill;
(*brush)->forecol = forecol;
(*brush)->backcol = backcol;
(*brush)->hatchstyle = hatchstyle;
TRACE("<-- %p\n", *brush);
}
else
{
GdipFree(*brush);
*brush = NULL;
}
(*brush)->brush.bt = BrushTypeHatchFill;
(*brush)->forecol = forecol;
(*brush)->backcol = backcol;
(*brush)->hatchstyle = hatchstyle;
TRACE("<-- %p\n", *brush);
return stat;
return Ok;
}
/******************************************************************************
......@@ -334,8 +260,6 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor,
GpWrapMode wrap, GpLineGradient **line)
{
COLORREF col = ARGB2COLORREF(startcolor);
TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint),
debugstr_pointf(endpoint), startcolor, endcolor, wrap, line);
......@@ -348,10 +272,6 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
*line = GdipAlloc(sizeof(GpLineGradient));
if(!*line) return OutOfMemory;
(*line)->brush.lb.lbStyle = BS_SOLID;
(*line)->brush.lb.lbColor = col;
(*line)->brush.lb.lbHatch = 0;
(*line)->brush.gdibrush = CreateSolidBrush(col);
(*line)->brush.bt = BrushTypeLinearGradient;
(*line)->startpoint.X = startpoint->X;
......@@ -387,7 +307,6 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
{
GdipFree((*line)->blendfac);
GdipFree((*line)->blendpos);
DeleteObject((*line)->brush.gdibrush);
GdipFree(*line);
*line = NULL;
return OutOfMemory;
......@@ -580,8 +499,6 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect
GpStatus WINGDIPAPI GdipCreatePathGradient(GDIPCONST GpPointF* points,
INT count, GpWrapMode wrap, GpPathGradient **grad)
{
COLORREF col = ARGB2COLORREF(0xffffffff);
TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
if(!points || !grad)
......@@ -620,11 +537,6 @@ GpStatus WINGDIPAPI GdipCreatePathGradient(GDIPCONST GpPointF* points,
memcpy((*grad)->pathdata.Points, points, count * sizeof(PointF));
memset((*grad)->pathdata.Types, PathPointTypeLine, count);
(*grad)->brush.lb.lbStyle = BS_SOLID;
(*grad)->brush.lb.lbColor = col;
(*grad)->brush.lb.lbHatch = 0;
(*grad)->brush.gdibrush = CreateSolidBrush(col);
(*grad)->brush.bt = BrushTypePathGradient;
(*grad)->centercolor = 0xffffffff;
(*grad)->wrap = wrap;
......@@ -677,8 +589,6 @@ GpStatus WINGDIPAPI GdipCreatePathGradientI(GDIPCONST GpPoint* points,
GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
GpPathGradient **grad)
{
COLORREF col = ARGB2COLORREF(0xffffffff);
TRACE("(%p, %p)\n", path, grad);
if(!path || !grad)
......@@ -715,11 +625,6 @@ GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
path->pathdata.Count * sizeof(PointF));
memcpy((*grad)->pathdata.Types, path->pathdata.Types, path->pathdata.Count);
(*grad)->brush.lb.lbStyle = BS_SOLID;
(*grad)->brush.lb.lbColor = col;
(*grad)->brush.lb.lbHatch = 0;
(*grad)->brush.gdibrush = CreateSolidBrush(col);
(*grad)->brush.bt = BrushTypePathGradient;
(*grad)->centercolor = 0xffffffff;
(*grad)->wrap = WrapModeClamp;
......@@ -740,8 +645,6 @@ GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
*/
GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
{
COLORREF col = ARGB2COLORREF(color);
TRACE("(%x, %p)\n", color, sf);
if(!sf) return InvalidParameter;
......@@ -749,11 +652,6 @@ GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
*sf = GdipAlloc(sizeof(GpSolidFill));
if (!*sf) return OutOfMemory;
(*sf)->brush.lb.lbStyle = BS_SOLID;
(*sf)->brush.lb.lbColor = col;
(*sf)->brush.lb.lbHatch = 0;
(*sf)->brush.gdibrush = CreateSolidBrush(col);
(*sf)->brush.bt = BrushTypeSolidColor;
(*sf)->color = color;
(*sf)->bmp = ARGB2BMP(color);
......@@ -843,7 +741,6 @@ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width,
REAL height, GpTexture **texture)
{
HBITMAP hbm=NULL;
GpStatus status;
GpImage *new_image=NULL;
......@@ -864,13 +761,6 @@ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
if (status != Ok)
return status;
status = GdipCreateHBITMAPFromBitmap((GpBitmap*)new_image, &hbm, 0);
if(!hbm)
{
status = GenericError;
goto exit;
}
*texture = GdipAlloc(sizeof(GpTexture));
if (!*texture){
status = OutOfMemory;
......@@ -891,16 +781,11 @@ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
if (status == Ok)
(*texture)->imageattributes->wrap = WrapModeTile;
}
if (status != Ok)
goto exit;
(*texture)->brush.lb.lbStyle = BS_PATTERN;
(*texture)->brush.lb.lbColor = 0;
(*texture)->brush.lb.lbHatch = (ULONG_PTR)hbm;
(*texture)->brush.gdibrush = CreateBrushIndirect(&(*texture)->brush.lb);
(*texture)->brush.bt = BrushTypeTextureFill;
(*texture)->image = new_image;
if (status == Ok)
{
(*texture)->brush.bt = BrushTypeTextureFill;
(*texture)->image = new_image;
}
exit:
if (status == Ok)
......@@ -920,8 +805,6 @@ exit:
TRACE("<-- error %u\n", status);
}
DeleteObject(hbm);
return status;
}
......@@ -1036,7 +919,6 @@ GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
break;
}
DeleteObject(brush->gdibrush);
GdipFree(brush);
return Ok;
......@@ -1576,11 +1458,6 @@ GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad,
return InvalidParameter;
grad->centercolor = argb;
grad->brush.lb.lbColor = ARGB2COLORREF(argb);
DeleteObject(grad->brush.gdibrush);
grad->brush.gdibrush = CreateSolidBrush(grad->brush.lb.lbColor);
return Ok;
}
......@@ -1773,11 +1650,6 @@ GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
return InvalidParameter;
sf->color = argb;
sf->brush.lb.lbColor = ARGB2COLORREF(argb);
DeleteObject(sf->brush.gdibrush);
sf->brush.gdibrush = CreateSolidBrush(sf->brush.lb.lbColor);
return Ok;
}
......
......@@ -170,9 +170,7 @@ struct GpGraphics{
};
struct GpBrush{
HBRUSH gdibrush;
GpBrushType bt;
LOGBRUSH lb;
};
struct GpHatch{
......
......@@ -90,8 +90,158 @@ static REAL graphics_res(GpGraphics *graphics)
else return (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX);
}
static COLORREF get_gdi_brush_color(const GpBrush *brush)
{
ARGB argb;
switch (brush->bt)
{
case BrushTypeSolidColor:
{
const GpSolidFill *sf = (const GpSolidFill *)brush;
argb = sf->color;
break;
}
case BrushTypeHatchFill:
{
const GpHatch *hatch = (const GpHatch *)brush;
argb = hatch->forecol;
break;
}
case BrushTypeLinearGradient:
{
const GpLineGradient *line = (const GpLineGradient *)brush;
argb = line->startcolor;
break;
}
case BrushTypePathGradient:
{
const GpPathGradient *grad = (const GpPathGradient *)brush;
argb = grad->centercolor;
break;
}
default:
FIXME("unhandled brush type %d\n", brush->bt);
argb = 0;
break;
}
return ARGB2COLORREF(argb);
}
static HBITMAP create_hatch_bitmap(const GpHatch *hatch)
{
HBITMAP hbmp;
HDC hdc;
BITMAPINFOHEADER bmih;
DWORD *bits;
int x, y;
hdc = CreateCompatibleDC(0);
if (!hdc) return 0;
bmih.biSize = sizeof(bmih);
bmih.biWidth = 8;
bmih.biHeight = 8;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
hbmp = CreateDIBSection(hdc, (BITMAPINFO *)&bmih, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
if (hbmp)
{
const char *hatch_data;
if (get_hatch_data(hatch->hatchstyle, &hatch_data) == Ok)
{
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
if (hatch_data[y] & (0x80 >> x))
bits[y * 8 + x] = hatch->forecol;
else
bits[y * 8 + x] = hatch->backcol;
}
}
}
else
{
FIXME("Unimplemented hatch style %d\n", hatch->hatchstyle);
for (y = 0; y < 64; y++)
bits[y] = hatch->forecol;
}
}
DeleteDC(hdc);
return hbmp;
}
static GpStatus create_gdi_logbrush(const GpBrush *brush, LOGBRUSH *lb)
{
switch (brush->bt)
{
case BrushTypeSolidColor:
{
const GpSolidFill *sf = (const GpSolidFill *)brush;
lb->lbStyle = BS_SOLID;
lb->lbColor = ARGB2COLORREF(sf->color);
lb->lbHatch = 0;
return Ok;
}
case BrushTypeHatchFill:
{
const GpHatch *hatch = (const GpHatch *)brush;
HBITMAP hbmp;
hbmp = create_hatch_bitmap(hatch);
if (!hbmp) return OutOfMemory;
lb->lbStyle = BS_PATTERN;
lb->lbColor = 0;
lb->lbHatch = (ULONG_PTR)hbmp;
return Ok;
}
default:
FIXME("unhandled brush type %d\n", brush->bt);
lb->lbStyle = BS_SOLID;
lb->lbColor = get_gdi_brush_color(brush);
lb->lbHatch = 0;
return Ok;
}
}
static GpStatus free_gdi_logbrush(LOGBRUSH *lb)
{
switch (lb->lbStyle)
{
case BS_PATTERN:
DeleteObject((HGDIOBJ)(ULONG_PTR)lb->lbHatch);
break;
}
return Ok;
}
static HBRUSH create_gdi_brush(const GpBrush *brush)
{
LOGBRUSH lb;
HBRUSH gdibrush;
if (create_gdi_logbrush(brush, &lb) != Ok) return 0;
gdibrush = CreateBrushIndirect(&lb);
free_gdi_logbrush(&lb);
return gdibrush;
}
static INT prepare_dc(GpGraphics *graphics, GpPen *pen)
{
LOGBRUSH lb;
HPEN gdipen;
REAL width;
INT save_state, i, numdashes;
......@@ -130,11 +280,17 @@ static INT prepare_dc(GpGraphics *graphics, GpPen *pen)
}
TRACE("\n and the pen style is %x\n", pen->style);
gdipen = ExtCreatePen(pen->style, roundr(width), &pen->brush->lb,
create_gdi_logbrush(pen->brush, &lb);
gdipen = ExtCreatePen(pen->style, roundr(width), &lb,
numdashes, dash_array);
free_gdi_logbrush(&lb);
}
else
gdipen = ExtCreatePen(pen->style, roundr(width), &pen->brush->lb, 0, NULL);
{
create_gdi_logbrush(pen->brush, &lb);
gdipen = ExtCreatePen(pen->style, roundr(width), &lb, 0, NULL);
free_gdi_logbrush(&lb);
}
SelectObject(graphics->hdc, gdipen);
......@@ -723,10 +879,19 @@ static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
/* else fall through */
}
default:
SelectObject(graphics->hdc, brush->gdibrush);
{
HBRUSH gdibrush, old_brush;
gdibrush = create_gdi_brush(brush);
if (!gdibrush) return;
old_brush = SelectObject(graphics->hdc, gdibrush);
FillPath(graphics->hdc);
SelectObject(graphics->hdc, old_brush);
DeleteObject(gdibrush);
break;
}
}
}
static INT brush_can_fill_pixels(GpBrush *brush)
......@@ -1253,9 +1418,9 @@ static GpStatus draw_polyline(GpGraphics *graphics, GpPen *pen,
&ptcopy[0].X, &ptcopy[0].Y,
pen->customstart->inset * pen->width);
draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->endcap, pen->width, pen->customend,
pt[count - 2].X, pt[count - 2].Y, pt[count - 1].X, pt[count - 1].Y);
draw_cap(graphics, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->startcap, pen->width, pen->customstart,
pt[1].X, pt[1].Y, pt[0].X, pt[0].Y);
}
......@@ -1351,12 +1516,12 @@ static GpStatus draw_polybezier(GpGraphics *graphics, GpPen *pen,
/* the direction of the line cap is parallel to the direction at the
* end of the bezier (which, if it has been shortened, is not the same
* as the direction from pt[count-2] to pt[count-1]) */
draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->endcap, pen->width, pen->customend,
pt[count - 1].X - (ptcopy[count - 1].X - ptcopy[count - 2].X),
pt[count - 1].Y - (ptcopy[count - 1].Y - ptcopy[count - 2].Y),
pt[count - 1].X, pt[count - 1].Y);
draw_cap(graphics, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->startcap, pen->width, pen->customstart,
pt[0].X - (ptcopy[0].X - ptcopy[1].X),
pt[0].Y - (ptcopy[0].Y - ptcopy[1].Y), pt[0].X, pt[0].Y);
}
......@@ -1417,7 +1582,7 @@ static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *
shorten_bezier_amt(&ptcopy[count - 4],
pen->width * pen->customend->inset, FALSE);
draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->endcap, pen->width, pen->customend,
pt[count - 1].X - (ptcopy[count - 1].X - ptcopy[count - 2].X),
pt[count - 1].Y - (ptcopy[count - 1].Y - ptcopy[count - 2].Y),
pt[count - 1].X, pt[count - 1].Y);
......@@ -1433,7 +1598,7 @@ static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *
&ptcopy[count - 1].X, &ptcopy[count - 1].Y,
pen->customend->inset * pen->width);
draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->endcap, pen->width, pen->customend,
pt[count - 2].X, pt[count - 2].Y, pt[count - 1].X,
pt[count - 1].Y);
......@@ -1455,7 +1620,7 @@ static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *
shorten_bezier_amt(&ptcopy[j - 1],
pen->width * pen->customstart->inset, TRUE);
draw_cap(graphics, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->startcap, pen->width, pen->customstart,
pt[j - 1].X - (ptcopy[j - 1].X - ptcopy[j].X),
pt[j - 1].Y - (ptcopy[j - 1].Y - ptcopy[j].Y),
pt[j - 1].X, pt[j - 1].Y);
......@@ -1471,7 +1636,7 @@ static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *
&ptcopy[j - 1].X, &ptcopy[j - 1].Y,
pen->customstart->inset * pen->width);
draw_cap(graphics, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart,
draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->startcap, pen->width, pen->customstart,
pt[j].X, pt[j].Y, pt[j - 1].X,
pt[j - 1].Y);
......@@ -5787,7 +5952,7 @@ static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT1
save_state = SaveDC(graphics->hdc);
SetBkMode(graphics->hdc, TRANSPARENT);
SetTextColor(graphics->hdc, brush->lb.lbColor);
SetTextColor(graphics->hdc, get_gdi_brush_color(brush));
pt = positions[0];
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &pt, 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment