[6/14] gdiplus: create gdi pen every time gdi+ pen is used
Evan Stade
estade at gmail.com
Tue Jul 24 19:18:54 CDT 2007
Hi,
The width of a pen is different on different GpGraphics objects (if
pen is UnitWorld it takes on the width of the graphics object's page
unit). Thus we have to reconstruct the gdi pen every time we use a
pen on a graphics object. To this end I had to rework some of the
pen.c code (actually mostly deletions).
Changelog:
*remove GpPen.gdipen member
*remove all ExtCreatePen calls from pen.c
*pull unit conversion code into a helper
*pull pen selection/SaveDC/etc. code into a helper
dlls/gdiplus/gdiplus_private.h | 1
dlls/gdiplus/graphics.c | 155 ++++++++++++++++++++++------------------
dlls/gdiplus/pen.c | 28 +------
3 files changed, 88 insertions(+), 96 deletions(-)
--
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index f8e79f0..79800c2 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 6f022a1..6535def 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -72,6 +72,51 @@ static BYTE convert_path_point_type(BYTE
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(G
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(G
}
/* 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 *gra
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(GpGraphi
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(GpGra
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(GpGra
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(GpGrap
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(GpGrap
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(GpGraph
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(GpGraph
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(G
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 0f58b25..b088ac9 100644
--- a/dlls/gdiplus/pen.c
+++ b/dlls/gdiplus/pen.c
@@ -79,10 +79,6 @@ GpStatus WINGDIPAPI GdipClonePen(GpPen *
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
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
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(
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(
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(G
{
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;
}
--
1.4.1
More information about the wine-patches
mailing list