From 0d7bc4b325de1788dc2643ac84d5579bed82d562 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Thu, 8 Mar 2012 20:32:28 +0800 Subject: [PATCH] gdiplus: Create GDI brush only when needed. --- dlls/gdiplus/brush.c | 150 ++------------------------ dlls/gdiplus/gdiplus_private.h | 2 - dlls/gdiplus/graphics.c | 189 ++++++++++++++++++++++++++++++--- 3 files changed, 188 insertions(+), 153 deletions(-) diff --git a/dlls/gdiplus/brush.c b/dlls/gdiplus/brush.c index ee1fd39c5d..ca4d8eb3bc 100644 --- a/dlls/gdiplus/brush.c +++ b/dlls/gdiplus/brush.c @@ -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; } diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 9afe15bc1e..2a5fe69063 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -170,9 +170,7 @@ struct GpGraphics{ }; struct GpBrush{ - HBRUSH gdibrush; GpBrushType bt; - LOGBRUSH lb; }; struct GpHatch{ diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 65a381502a..d300f595f9 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -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); -- 2.32.0.93.g670b81a890