From d01c697eb9e721550fb20e751d7763553b4798db Mon Sep 17 00:00:00 2001 From: Evan Stade Date: Mon, 23 Jul 2007 20:24:53 -0700 Subject: [PATCH] gdiplus: Use page unit when drawing. --- dlls/gdiplus/graphics.c | 305 ++++++++++++++++++++++++---------------- 1 file changed, 180 insertions(+), 125 deletions(-) diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 7a26d8766a6..8a53c03904a 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -72,12 +72,45 @@ static BYTE convert_path_point_type(BYTE type) return ret; } +/* 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: + * -scaling by page unit + * -applying world transformation + * -converting from float to int + * Native gdiplus uses gdi32 to do all this (via SetMapMode, SetViewportExtEx, + * SetWindowExtEx, SetWorldTransform, etc.) but we cannot because we are using + * gdi to draw, and these functions would irreparably mess with line widths. + */ +static void transform_and_round_points(GpGraphics *graphics, POINT *pti, + GDIPCONST GpPointF *ptf, INT count) +{ + REAL unitscale; + int i; + + switch(graphics->unit) + { + case UnitInch: + unitscale = GetDeviceCaps(graphics->hdc, LOGPIXELSX); + break; + default: + unitscale = 1.0; + break; + } + + for(i = 0; i < count; i++){ + pti[i].x = roundr(unitscale * ptf[i].X); + pti[i].y = roundr(unitscale * ptf[i].Y); + } +} + /* 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) { INT save_state; - REAL x_0, y_0, x_1, y_1, x_2, y_2; + GpPointF ptf[4]; + POINT pti[4]; if(!graphics) return InvalidParameter; @@ -87,14 +120,18 @@ static GpStatus draw_pie(GpGraphics *graphics, HBRUSH gdibrush, HPEN gdipen, SelectObject(graphics->hdc, gdipen); SelectObject(graphics->hdc, gdibrush); - x_0 = x + (width/2.0); - y_0 = y + (height/2.0); + ptf[0].X = x; + ptf[0].Y = y; + ptf[1].X = x + width; + ptf[1].Y = y + height; - deg2xy(startAngle+sweepAngle, x_0, y_0, &x_1, &y_1); - deg2xy(startAngle, x_0, y_0, &x_2, &y_2); + deg2xy(startAngle+sweepAngle, x + width / 2.0, y + width / 2.0, &ptf[2].X, &ptf[2].Y); + deg2xy(startAngle, x + width / 2.0, y + width / 2.0, &ptf[3].X, &ptf[3].Y); - Pie(graphics->hdc, roundr(x), roundr(y), roundr(x+width), roundr(y+height), - roundr(x_1), roundr(y_1), roundr(x_2), roundr(y_2)); + transform_and_round_points(graphics, pti, ptf, 4); + + 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); @@ -132,17 +169,17 @@ static void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, /* Draws the linecap the specified color and size on the hdc. The linecap is in * direction of the line from x1, y1 to x2, y2 and is anchored on x2, y2. Probably * should not be called on an hdc that has a path you care about. */ -static void draw_cap(HDC hdc, COLORREF color, GpLineCap cap, REAL size, +static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL size, const GpCustomLineCap *custom, REAL x1, REAL y1, REAL x2, REAL y2) { HGDIOBJ oldbrush, oldpen; GpMatrix *matrix = NULL; HBRUSH brush; HPEN pen; - PointF *custptf = NULL; + PointF ptf[4], *custptf = NULL; POINT pt[4], *custpt = NULL; BYTE *tp = NULL; - REAL theta, dsmall, dbig, dx, dy; + REAL theta, dsmall, dbig, dx, dy = 0.0; INT i, count; LOGBRUSH lb; @@ -158,8 +195,8 @@ static void draw_cap(HDC hdc, COLORREF color, GpLineCap cap, REAL size, pen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT, ((cap == LineCapCustom) && custom && (custom->fill)) ? size : 1, &lb, 0, NULL); - oldbrush = SelectObject(hdc, brush); - oldpen = SelectObject(hdc, pen); + oldbrush = SelectObject(graphics->hdc, brush); + oldpen = SelectObject(graphics->hdc, pen); switch(cap){ case LineCapFlat: @@ -177,21 +214,20 @@ static void draw_cap(HDC hdc, COLORREF color, GpLineCap cap, REAL size, dbig = sin(theta + M_PI_4) * size; } - /* calculating the latter points from the earlier points makes them - * look a little better because of rounding issues */ - pt[0].x = roundr(x2 - dsmall); - pt[1].x = roundr(((REAL)pt[0].x) + dbig + dsmall); + ptf[0].X = x2 - dsmall; + ptf[1].X = x2 + dbig; - pt[0].y = roundr(y2 - dbig); - pt[3].y = roundr(((REAL)pt[0].y) + dsmall + dbig); + ptf[0].Y = y2 - dbig; + ptf[3].Y = y2 + dsmall; - pt[1].y = roundr(y2 - dsmall); - pt[2].y = roundr(dbig + dsmall + ((REAL)pt[1].y)); + ptf[1].Y = y2 - dsmall; + ptf[2].Y = y2 + dbig; - pt[3].x = roundr(x2 - dbig); - pt[2].x = roundr(((REAL)pt[3].x) + dsmall + dbig); + ptf[3].X = x2 - dbig; + ptf[2].X = x2 + dsmall; - Polygon(hdc, pt, 4); + transform_and_round_points(graphics, pt, ptf, 4); + Polygon(graphics->hdc, pt, 4); break; case LineCapArrowAnchor: @@ -200,67 +236,74 @@ static void draw_cap(HDC hdc, COLORREF color, GpLineCap cap, REAL size, dx = cos(M_PI / 6.0 + theta) * size; dy = sin(M_PI / 6.0 + theta) * size; - pt[0].x = roundr(x2 - dx); - pt[0].y = roundr(y2 - dy); + ptf[0].X = x2 - dx; + ptf[0].Y = y2 - dy; dx = cos(- M_PI / 6.0 + theta) * size; dy = sin(- M_PI / 6.0 + theta) * size; - pt[1].x = roundr(x2 - dx); - pt[1].y = roundr(y2 - dy); + ptf[1].X = x2 - dx; + ptf[1].Y = y2 - dy; - pt[2].x = roundr(x2); - pt[2].y = roundr(y2); + ptf[2].X = x2; + ptf[2].Y = y2; - Polygon(hdc, pt, 3); + transform_and_round_points(graphics, pt, ptf, 3); + Polygon(graphics->hdc, pt, 3); break; case LineCapRoundAnchor: dx = dy = ANCHOR_WIDTH * size / 2.0; - x2 = (REAL) roundr(x2 - dx); - y2 = (REAL) roundr(y2 - dy); + ptf[0].X = x2 - dx; + ptf[0].Y = y2 - dy; + ptf[1].X = x2 + dx; + ptf[1].Y = y2 + dy; + + transform_and_round_points(graphics, pt, ptf, 2); + Ellipse(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y); - Ellipse(hdc, (INT) x2, (INT) y2, roundr(x2 + 2.0 * dx), - roundr(y2 + 2.0 * dy)); break; case LineCapTriangle: size = size / 2.0; dx = cos(M_PI_2 + theta) * size; dy = sin(M_PI_2 + theta) * size; - /* Using roundr here can make the triangle float off the end of the - * line. */ - pt[0].x = ((x2 - x1) >= 0 ? floorf(x2 - dx) : ceilf(x2 - dx)); - pt[0].y = ((y2 - y1) >= 0 ? floorf(y2 - dy) : ceilf(y2 - dy)); - pt[1].x = roundr(pt[0].x + 2.0 * dx); - pt[1].y = roundr(pt[0].y + 2.0 * dy); + ptf[0].X = x2 - dx; + ptf[0].Y = y2 - dy; + ptf[1].X = x2 + dx; + ptf[1].Y = y2 + dy; dx = cos(theta) * size; dy = sin(theta) * size; - pt[2].x = roundr(x2 + dx); - pt[2].y = roundr(y2 + dy); + ptf[2].X = x2 + dx; + ptf[2].Y = y2 + dy; - Polygon(hdc, pt, 3); + transform_and_round_points(graphics, pt, ptf, 3); + Polygon(graphics->hdc, pt, 3); break; case LineCapRound: + dx = dy = size / 2.0; + + ptf[0].X = x2 - dx; + ptf[0].Y = y2 - dy; + ptf[1].X = x2 + dx; + ptf[1].Y = y2 + dy; + dx = -cos(M_PI_2 + theta) * size; dy = -sin(M_PI_2 + theta) * size; - pt[0].x = ((x2 - x1) >= 0 ? floorf(x2 - dx) : ceilf(x2 - dx)); - pt[0].y = ((y2 - y1) >= 0 ? floorf(y2 - dy) : ceilf(y2 - dy)); - pt[1].x = roundr(pt[0].x + 2.0 * dx); - pt[1].y = roundr(pt[0].y + 2.0 * dy); + ptf[2].X = x2 - dx; + ptf[2].Y = y2 - dy; + ptf[3].X = x2 + dx; + ptf[3].Y = y2 + dy; - dx = dy = size / 2.0; + transform_and_round_points(graphics, pt, ptf, 4); + Pie(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y, pt[2].x, + pt[2].y, pt[3].x, pt[3].y); - x2 = (REAL) roundr(x2 - dx); - y2 = (REAL) roundr(y2 - dy); - - Pie(hdc, (INT) x2, (INT) y2, roundr(x2 + 2.0 * dx), - roundr(y2 + 2.0 * dy), pt[0].x, pt[0].y, pt[1].x, pt[1].y); break; case LineCapCustom: if(!custom) @@ -282,20 +325,19 @@ static void draw_cap(HDC hdc, COLORREF color, GpLineCap cap, REAL size, GdipTranslateMatrix(matrix, x2, y2, MatrixOrderAppend); GdipTransformMatrixPoints(matrix, custptf, count); - for(i = 0; i < count; i++){ - custpt[i].x = roundr(custptf[i].X); - custpt[i].y = roundr(custptf[i].Y); + transform_and_round_points(graphics, custpt, custptf, count); + + for(i = 0; i < count; i++) tp[i] = convert_path_point_type(custom->pathdata.Types[i]); - } if(custom->fill){ - BeginPath(hdc); - PolyDraw(hdc, custpt, tp, count); - EndPath(hdc); - StrokeAndFillPath(hdc); + BeginPath(graphics->hdc); + PolyDraw(graphics->hdc, custpt, tp, count); + EndPath(graphics->hdc); + StrokeAndFillPath(graphics->hdc); } else - PolyDraw(hdc, custpt, tp, count); + PolyDraw(graphics->hdc, custpt, tp, count); custend: GdipFree(custptf); @@ -307,8 +349,8 @@ custend: break; } - SelectObject(hdc, oldbrush); - SelectObject(hdc, oldpen); + SelectObject(graphics->hdc, oldbrush); + SelectObject(graphics->hdc, oldpen); DeleteObject(brush); DeleteObject(pen); } @@ -356,12 +398,11 @@ static void shorten_line_amt(REAL x1, REAL y1, REAL *x2, REAL *y2, REAL amt) /* Draws lines between the given points, and if caps is true then draws an endcap * at the end of the last line. FIXME: Startcaps not implemented. */ -static GpStatus draw_polyline(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, - INT count, BOOL caps) +static GpStatus draw_polyline(GpGraphics *graphics, GpPen *pen, + GDIPCONST GpPointF * pt, INT count, BOOL caps) { POINT *pti = NULL; GpPointF *ptcopy = NULL; - INT i; GpStatus status = GenericError; if(!count) @@ -375,9 +416,9 @@ static GpStatus draw_polyline(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, goto end; } - memcpy(ptcopy, pt, count * sizeof(GpPointF)); - if(caps){ + memcpy(ptcopy, pt, count * sizeof(GpPointF)); + if(pen->endcap == LineCapArrowAnchor) shorten_line_amt(ptcopy[count-2].X, ptcopy[count-2].Y, &ptcopy[count-1].X, &ptcopy[count-1].Y, pen->width); @@ -394,18 +435,17 @@ static GpStatus draw_polyline(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, &ptcopy[0].X, &ptcopy[0].Y, pen->customend->inset * pen->width); - draw_cap(hdc, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend, + draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend, pt[count - 2].X, pt[count - 2].Y, pt[count - 1].X, pt[count - 1].Y); - draw_cap(hdc, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart, - pt[1].X, pt[1].Y, pt[0].X, pt[0].Y); - } + draw_cap(graphics, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart, + pt[1].X, pt[1].Y, pt[0].X, pt[0].Y);\ - for(i = 0; i < count; i ++){ - pti[i].x = roundr(ptcopy[i].X); - pti[i].y = roundr(ptcopy[i].Y); + transform_and_round_points(graphics, pti, ptcopy, count); } + else + transform_and_round_points(graphics, pti, pt, count); - Polyline(hdc, pti, count); + Polyline(graphics->hdc, pti, count); end: GdipFree(pti); @@ -459,12 +499,11 @@ static void shorten_bezier_amt(GpPointF * pt, REAL amt, BOOL rev) /* Draws bezier curves between given points, and if caps is true then draws an * endcap at the end of the last line. FIXME: Startcaps not implemented. */ -static GpStatus draw_polybezier(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, - INT count, BOOL caps) +static GpStatus draw_polybezier(GpGraphics *graphics, GpPen *pen, + GDIPCONST GpPointF * pt, INT count, BOOL caps) { POINT *pti, curpos; GpPointF *ptcopy; - INT i; REAL x, y; GpStatus status = GenericError; @@ -479,9 +518,9 @@ static GpStatus draw_polybezier(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, goto end; } - memcpy(ptcopy, pt, count * sizeof(GpPointF)); - if(caps){ + memcpy(ptcopy, pt, count * sizeof(GpPointF)); + if(pen->endcap == LineCapArrowAnchor) shorten_bezier_amt(&ptcopy[count-4], pen->width, FALSE); /* FIXME The following is seemingly correct only for baseinset < 0 or @@ -492,9 +531,9 @@ static GpStatus draw_polybezier(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, y = pt[count - 1].Y; shorten_line_amt(pt[count - 2].X, pt[count - 2].Y, &x, &y, pen->width * pen->customend->inset); - MoveToEx(hdc, roundr(pt[count - 1].X), roundr(pt[count - 1].Y), &curpos); - LineTo(hdc, roundr(x), roundr(y)); - MoveToEx(hdc, curpos.x, curpos.y, NULL); + MoveToEx(graphics->hdc, roundr(pt[count - 1].X), roundr(pt[count - 1].Y), &curpos); + LineTo(graphics->hdc, roundr(x), roundr(y)); + MoveToEx(graphics->hdc, curpos.x, curpos.y, NULL); } if(pen->startcap == LineCapArrowAnchor) @@ -504,30 +543,29 @@ static GpStatus draw_polybezier(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, y = ptcopy[0].Y; shorten_line_amt(ptcopy[1].X, ptcopy[1].Y, &x, &y, pen->width * pen->customend->inset); - MoveToEx(hdc, roundr(pt[0].X), roundr(pt[0].Y), &curpos); - LineTo(hdc, roundr(x), roundr(y)); - MoveToEx(hdc, curpos.x, curpos.y, NULL); + MoveToEx(graphics->hdc, roundr(pt[0].X), roundr(pt[0].Y), &curpos); + LineTo(graphics->hdc, roundr(x), roundr(y)); + MoveToEx(graphics->hdc, curpos.x, curpos.y, NULL); } /* 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(hdc, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend, + draw_cap(graphics, pen->brush->lb.lbColor, 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(hdc, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart, + draw_cap(graphics, pen->brush->lb.lbColor, 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); - } - for(i = 0; i < count; i ++){ - pti[i].x = roundr(ptcopy[i].X); - pti[i].y = roundr(ptcopy[i].Y); + transform_and_round_points(graphics, pti, ptcopy, count); } + else + transform_and_round_points(graphics, pti, pt, count); - PolyBezier(hdc, pti, count); + PolyBezier(graphics->hdc, pti, count); status = Ok; @@ -539,7 +577,7 @@ end: } /* Draws a combination of bezier curves and lines between points. */ -static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, +static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF * pt, GDIPCONST BYTE * types, INT count, BOOL caps) { POINT *pti = GdipAlloc(count * sizeof(POINT)), curpos; @@ -583,12 +621,13 @@ static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, y = pt[count - 1].Y; shorten_line_amt(pt[count - 2].X, pt[count - 2].Y, &x, &y, pen->width * pen->customend->inset); - MoveToEx(hdc, roundr(pt[count - 1].X), roundr(pt[count - 1].Y), &curpos); - LineTo(hdc, roundr(x), roundr(y)); - MoveToEx(hdc, curpos.x, curpos.y, NULL); + MoveToEx(graphics->hdc, roundr(pt[count - 1].X), + roundr(pt[count - 1].Y), &curpos); + LineTo(graphics->hdc, roundr(x), roundr(y)); + MoveToEx(graphics->hdc, curpos.x, curpos.y, NULL); } - draw_cap(hdc, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend, + draw_cap(graphics, pen->brush->lb.lbColor, 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); @@ -604,7 +643,7 @@ static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, &ptcopy[count - 1].X, &ptcopy[count - 1].Y, pen->customend->inset * pen->width); - draw_cap(hdc, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend, + draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customend, pt[count - 2].X, pt[count - 2].Y, pt[count - 1].X, pt[count - 1].Y); @@ -627,12 +666,12 @@ static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, y = pt[j - 1].Y; shorten_line_amt(ptcopy[j].X, ptcopy[j].Y, &x, &y, pen->width * pen->customstart->inset); - MoveToEx(hdc, roundr(pt[j - 1].X), roundr(pt[j - 1].Y), &curpos); - LineTo(hdc, roundr(x), roundr(y)); - MoveToEx(hdc, curpos.x, curpos.y, NULL); + MoveToEx(graphics->hdc, roundr(pt[j - 1].X), roundr(pt[j - 1].Y), &curpos); + LineTo(graphics->hdc, roundr(x), roundr(y)); + MoveToEx(graphics->hdc, curpos.x, curpos.y, NULL); } - draw_cap(hdc, pen->brush->lb.lbColor, pen->startcap, pen->width, pen->customstart, + draw_cap(graphics, pen->brush->lb.lbColor, 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); @@ -648,7 +687,7 @@ static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, &ptcopy[j - 1].X, &ptcopy[j - 1].Y, pen->customstart->inset * pen->width); - draw_cap(hdc, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customstart, + draw_cap(graphics, pen->brush->lb.lbColor, pen->endcap, pen->width, pen->customstart, pt[j].X, pt[j].Y, pt[j - 1].X, pt[j - 1].Y); @@ -657,22 +696,16 @@ static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt, ERR("Bad path points\n"); goto end; } - for(i = 0; i < count; i++){ - pti[i].x = roundr(ptcopy[i].X); - pti[i].y = roundr(ptcopy[i].Y); - } + transform_and_round_points(graphics, pti, ptcopy, count); } else - for(i = 0; i < count; i++){ - pti[i].x = roundr(pt[i].X); - pti[i].y = roundr(pt[i].Y); - } + transform_and_round_points(graphics, pti, pt, count); for(i = 0; i < count; i++){ tp[i] = convert_path_point_type(types[i]); } - PolyDraw(hdc, pti, tp, count); + PolyDraw(graphics->hdc, pti, tp, count); status = Ok; @@ -745,7 +778,7 @@ GpStatus WINGDIPAPI GdipDrawArc(GpGraphics *graphics, GpPen *pen, REAL x, EndPath(graphics->hdc); SelectObject(graphics->hdc, pen->gdipen); - retval = draw_polybezier(graphics->hdc, pen, points, num_pts, TRUE); + retval = draw_polybezier(graphics, pen, points, num_pts, TRUE); RestoreDC(graphics->hdc, save_state); @@ -775,7 +808,7 @@ GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics *graphics, GpPen *pen, REAL x1, EndPath(graphics->hdc); SelectObject(graphics->hdc, pen->gdipen); - retval = draw_polybezier(graphics->hdc, pen, pt, 4, TRUE); + retval = draw_polybezier(graphics, pen, pt, 4, TRUE); RestoreDC(graphics->hdc, save_state); @@ -829,7 +862,7 @@ GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics *graphics, GpPen *pen, EndPath(graphics->hdc); SelectObject(graphics->hdc, pen->gdipen); - retval = draw_polybezier(graphics->hdc, pen, pt, len_pt, TRUE); + retval = draw_polybezier(graphics, pen, pt, len_pt, TRUE); GdipFree(pt); RestoreDC(graphics->hdc, save_state); @@ -856,7 +889,7 @@ GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, EndPath(graphics->hdc); SelectObject(graphics->hdc, pen->gdipen); - retval = draw_polyline(graphics->hdc, pen, pt, 2, TRUE); + retval = draw_polyline(graphics, pen, pt, 2, TRUE); RestoreDC(graphics->hdc, save_state); @@ -876,7 +909,7 @@ GpStatus WINGDIPAPI GdipDrawLines(GpGraphics *graphics, GpPen *pen, GDIPCONST EndPath(graphics->hdc); SelectObject(graphics->hdc, pen->gdipen); - retval = draw_polyline(graphics->hdc, pen, points, count, TRUE); + retval = draw_polyline(graphics, pen, points, count, TRUE); RestoreDC(graphics->hdc, save_state); @@ -895,7 +928,7 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) EndPath(graphics->hdc); SelectObject(graphics->hdc, pen->gdipen); - retval = draw_poly(graphics->hdc, pen, path->pathdata.Points, + retval = draw_poly(graphics, pen, path->pathdata.Points, path->pathdata.Types, path->pathdata.Count, TRUE); RestoreDC(graphics->hdc, save_state); @@ -948,7 +981,7 @@ GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *p : WINDING)); BeginPath(graphics->hdc); - retval = draw_poly(graphics->hdc, NULL, path->pathdata.Points, + retval = draw_poly(graphics, NULL, path->pathdata.Points, path->pathdata.Types, path->pathdata.Count, FALSE); if(retval != Ok) @@ -978,21 +1011,43 @@ GpStatus WINGDIPAPI GdipFillPie(GpGraphics *graphics, GpBrush *brush, REAL x, GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count, GpFillMode fillMode) { - INT save_state; + INT save_state, i; + GpPointF *ptf = NULL; + POINT *pti = NULL; + GpStatus retval = Ok; if(!graphics || !brush || !points || !count) return InvalidParameter; + ptf = GdipAlloc(count * sizeof(GpPointF)); + pti = GdipAlloc(count * sizeof(POINT)); + if(!ptf || !pti){ + retval = OutOfMemory; + goto end; + } + + for(i = 0; i < count; i ++){ + ptf[i].X = (REAL) points[i].X; + ptf[i].Y = (REAL) points[i].Y; + } + save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); SelectObject(graphics->hdc, brush->gdibrush); SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); SetPolyFillMode(graphics->hdc, (fillMode == FillModeAlternate ? ALTERNATE : WINDING)); - Polygon(graphics->hdc, (GDIPCONST POINT*) points, count); + + transform_and_round_points(graphics, pti, ptf, count); + Polygon(graphics->hdc, pti, count); RestoreDC(graphics->hdc, save_state); - return Ok; + +end: + GdipFree(ptf); + GdipFree(pti); + + return retval; } /* FIXME: Compositing quality is not used anywhere except the getter/setter. */