From 4c424b3c16cf7dc863a36818da8cf209d1543dc4 Mon Sep 17 00:00:00 2001 From: Evan Stade Date: Tue, 24 Jul 2007 17:18:54 -0700 Subject: [PATCH] gdiplus: Create gdi pen every time gdi+ pen is used. --- dlls/gdiplus/gdiplus_private.h | 1 - dlls/gdiplus/graphics.c | 155 ++++++++++++++++++--------------- dlls/gdiplus/pen.c | 28 +----- 3 files changed, 88 insertions(+), 96 deletions(-) diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index f8e79f0f8bb..79800c29015 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -46,7 +46,6 @@ struct GpPen{ UINT style; GpUnit unit; REAL width; - HPEN gdipen; GpLineCap endcap; GpLineCap startcap; GpDashCap dashcap; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 6f022a13fb4..6535def9c41 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -72,6 +72,51 @@ static BYTE convert_path_point_type(BYTE type) return ret; } +static REAL convert_unit(HDC hdc, GpUnit unit) +{ + switch(unit) + { + case UnitInch: + return (REAL) GetDeviceCaps(hdc, LOGPIXELSX); + case UnitPoint: + return ((REAL)GetDeviceCaps(hdc, LOGPIXELSX)) / 72.0; + case UnitDocument: + return ((REAL)GetDeviceCaps(hdc, LOGPIXELSX)) / 300.0; + case UnitMillimeter: + return ((REAL)GetDeviceCaps(hdc, LOGPIXELSX)) / 25.4; + case UnitWorld: + ERR("cannot convert UnitWorld\n"); + return 0.0; + case UnitPixel: + case UnitDisplay: + default: + return 1.0; + } +} + +static INT prepare_dc(GpGraphics *graphics, GpPen *pen) +{ + HPEN gdipen; + REAL width; + INT save_state = SaveDC(graphics->hdc); + + EndPath(graphics->hdc); + + width = pen->width * convert_unit(graphics->hdc, + pen->unit == UnitWorld ? graphics->unit : pen->unit); + + gdipen = ExtCreatePen(pen->style, roundr(width), &pen->brush->lb, 0, NULL); + SelectObject(graphics->hdc, gdipen); + + return save_state; +} + +static void restore_dc(GpGraphics *graphics, INT state) +{ + DeleteObject(SelectObject(graphics->hdc, GetStockObject(NULL_PEN))); + RestoreDC(graphics->hdc, state); +} + /* This helper applies all the changes that the points listed in ptf need in * order to be drawn on the device context. In the end, this should include at * least: @@ -89,26 +134,7 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti, GpMatrix *matrix; int i; - switch(graphics->unit) - { - case UnitInch: - unitscale = GetDeviceCaps(graphics->hdc, LOGPIXELSX); - break; - case UnitPoint: - unitscale = ((REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX)) / 72.0; - break; - case UnitDocument: - unitscale = ((REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX)) / 300.0; - break; - case UnitMillimeter: - unitscale = ((REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX)) / 25.4; - break; - case UnitPixel: - case UnitDisplay: - default: - unitscale = 1.0; - break; - } + unitscale = convert_unit(graphics->hdc, graphics->unit); /* apply page scale */ if(graphics->unit != UnitDisplay) @@ -125,21 +151,12 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti, } /* GdipDrawPie/GdipFillPie helper function */ -static GpStatus draw_pie(GpGraphics *graphics, HBRUSH gdibrush, HPEN gdipen, - REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle) +static void draw_pie(GpGraphics *graphics, REAL x, REAL y, REAL width, + REAL height, REAL startAngle, REAL sweepAngle) { - INT save_state; GpPointF ptf[4]; POINT pti[4]; - if(!graphics) - return InvalidParameter; - - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, gdipen); - SelectObject(graphics->hdc, gdibrush); - ptf[0].X = x; ptf[0].Y = y; ptf[1].X = x + width; @@ -152,10 +169,6 @@ static GpStatus draw_pie(GpGraphics *graphics, HBRUSH gdibrush, HPEN gdipen, Pie(graphics->hdc, pti[0].x, pti[0].y, pti[1].x, pti[1].y, pti[2].x, pti[2].y, pti[3].x, pti[3].y); - - RestoreDC(graphics->hdc, save_state); - - return Ok; } /* GdipDrawCurve helper function. @@ -798,13 +811,11 @@ GpStatus WINGDIPAPI GdipDrawArc(GpGraphics *graphics, GpPen *pen, REAL x, num_pts = arc2polybezier(points, x, y, width, height, startAngle, sweepAngle); - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); retval = draw_polybezier(graphics, pen, points, num_pts, TRUE); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return retval; } @@ -828,13 +839,11 @@ GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics *graphics, GpPen *pen, REAL x1, pt[3].X = x4; pt[3].Y = y4; - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); retval = draw_polybezier(graphics, pen, pt, 4, TRUE); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return retval; } @@ -882,14 +891,12 @@ GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics *graphics, GpPen *pen, pt[len_pt-1].X = points[count-1].X; pt[len_pt-1].Y = points[count-1].Y; - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); retval = draw_polybezier(graphics, pen, pt, len_pt, TRUE); GdipFree(pt); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return retval; } @@ -909,13 +916,11 @@ GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, pt[1].X = (REAL)x2; pt[1].Y = (REAL)y2; - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); retval = draw_polyline(graphics, pen, pt, 2, TRUE); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return retval; } @@ -929,13 +934,11 @@ GpStatus WINGDIPAPI GdipDrawLines(GpGraphics *graphics, GpPen *pen, GDIPCONST if(!pen || !graphics || (count < 2)) return InvalidParameter; - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); retval = draw_polyline(graphics, pen, points, count, TRUE); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return retval; } @@ -948,14 +951,12 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) if(!pen || !graphics) return InvalidParameter; - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); retval = draw_poly(graphics, pen, path->pathdata.Points, path->pathdata.Types, path->pathdata.Count, TRUE); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return retval; } @@ -963,11 +964,19 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) GpStatus WINGDIPAPI GdipDrawPie(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle) { - if(!pen) + INT save_state; + + if(!graphics || !pen) return InvalidParameter; - return draw_pie(graphics, GetStockObject(NULL_BRUSH), pen->gdipen, x, y, - width, height, startAngle, sweepAngle); + save_state = prepare_dc(graphics, pen); + SelectObject(graphics->hdc, GetStockObject(NULL_BRUSH)); + + draw_pie(graphics, x, y, width, height, startAngle, sweepAngle); + + restore_dc(graphics, save_state); + + return Ok; } GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, @@ -978,14 +987,12 @@ GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, if(!pen || !graphics) return InvalidParameter; - save_state = SaveDC(graphics->hdc); - EndPath(graphics->hdc); - SelectObject(graphics->hdc, pen->gdipen); + save_state = prepare_dc(graphics, pen); SelectObject(graphics->hdc, GetStockObject(NULL_BRUSH)); Rectangle(graphics->hdc, x, y, x + width, y + height); - RestoreDC(graphics->hdc, save_state); + restore_dc(graphics, save_state); return Ok; } @@ -1025,11 +1032,21 @@ end: GpStatus WINGDIPAPI GdipFillPie(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle) { - if(!brush) + INT save_state; + + if(!graphics || !brush) return InvalidParameter; - return draw_pie(graphics, brush->gdibrush, GetStockObject(NULL_PEN), x, y, - width, height, startAngle, sweepAngle); + save_state = SaveDC(graphics->hdc); + EndPath(graphics->hdc); + SelectObject(graphics->hdc, brush->gdibrush); + SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); + + draw_pie(graphics, x, y, width, height, startAngle, sweepAngle); + + RestoreDC(graphics->hdc, save_state); + + return Ok; } GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, diff --git a/dlls/gdiplus/pen.c b/dlls/gdiplus/pen.c index 0f58b25d0f7..b088ac92003 100644 --- a/dlls/gdiplus/pen.c +++ b/dlls/gdiplus/pen.c @@ -79,10 +79,6 @@ GpStatus WINGDIPAPI GdipClonePen(GpPen *pen, GpPen **clonepen) GdipCloneCustomLineCap(pen->customend, &(*clonepen)->customend); GdipCloneBrush(pen->brush, &(*clonepen)->brush); - (*clonepen)->gdipen = ExtCreatePen((*clonepen)->style, - roundr((*clonepen)->width), - &(*clonepen)->brush->lb, 0, NULL); - return Ok; } @@ -106,10 +102,7 @@ GpStatus WINGDIPAPI GdipCreatePen1(ARGB color, FLOAT width, GpUnit unit, gp_pen->dash = DashStyleSolid; GdipCreateSolidFill(color, (GpSolidFill **)(&gp_pen->brush)); - if((gp_pen->unit == UnitWorld) || (gp_pen->unit == UnitPixel)) { - gp_pen->gdipen = ExtCreatePen(gp_pen->style, (INT) gp_pen->width, - &gp_pen->brush->lb, 0, NULL); - } else { + if(!((gp_pen->unit == UnitWorld) || (gp_pen->unit == UnitPixel))) { FIXME("UnitWorld, UnitPixel only supported units\n"); GdipFree(gp_pen); return NotImplemented; @@ -123,7 +116,6 @@ GpStatus WINGDIPAPI GdipCreatePen1(ARGB color, FLOAT width, GpUnit unit, GpStatus WINGDIPAPI GdipDeletePen(GpPen *pen) { if(!pen) return InvalidParameter; - DeleteObject(pen->gdipen); GdipDeleteBrush(pen->brush); GdipDeleteCustomLineCap(pen->customstart); @@ -164,21 +156,11 @@ GpStatus WINGDIPAPI GdipGetPenDashStyle(GpPen *pen, GpDashStyle *dash) GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen *pen, GpBrush *brush) { - GpStatus retval; - if(!pen || !brush) return InvalidParameter; GdipDeleteBrush(pen->brush); - retval = GdipCloneBrush(brush, &pen->brush); - if(retval != Ok) - return retval; - - DeleteObject(pen->gdipen); - pen->gdipen = ExtCreatePen(pen->style, roundr(pen->width), &pen->brush->lb, 0, - NULL); - - return Ok; + return GdipCloneBrush(brush, &pen->brush); } GpStatus WINGDIPAPI GdipSetPenColor(GpPen *pen, ARGB argb) @@ -229,14 +211,11 @@ GpStatus WINGDIPAPI GdipSetPenDashStyle(GpPen *pen, GpDashStyle dash) if(!pen) return InvalidParameter; - DeleteObject(pen->gdipen); pen->dash = dash; pen->style &= ~(PS_ALTERNATE | PS_SOLID | PS_DASH | PS_DOT | PS_DASHDOT | PS_DASHDOTDOT | PS_NULL | PS_USERSTYLE | PS_INSIDEFRAME); pen->style |= gdip_to_gdi_dash(dash); - pen->gdipen = ExtCreatePen(pen->style, (INT) pen->width, &pen->brush->lb, 0, NULL); - return Ok; } @@ -277,13 +256,10 @@ GpStatus WINGDIPAPI GdipSetPenLineJoin(GpPen *pen, GpLineJoin join) { if(!pen) return InvalidParameter; - DeleteObject(pen->gdipen); pen->join = join; pen->style &= ~(PS_JOIN_ROUND | PS_JOIN_BEVEL | PS_JOIN_MITER); pen->style |= gdip_to_gdi_join(join); - pen->gdipen = ExtCreatePen(pen->style, (INT) pen->width, &pen->brush->lb, 0, NULL); - return Ok; }