Evan Stade : gdiplus: Added GdipDrawPath.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jul 12 08:32:36 CDT 2007


Module: wine
Branch: master
Commit: 9d5f568183340e53e82fb623fed0d04490f66112
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9d5f568183340e53e82fb623fed0d04490f66112

Author: Evan Stade <estade at gmail.com>
Date:   Wed Jul 11 18:07:34 2007 -0700

gdiplus: Added GdipDrawPath.

---

 dlls/gdiplus/gdiplus.spec |    2 +-
 dlls/gdiplus/graphics.c   |  148 +++++++++++++++++++++++++++++++++++++++++++++
 include/gdiplusflat.h     |    1 +
 3 files changed, 150 insertions(+), 1 deletions(-)

diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec
index d18af7f..a805bd8 100644
--- a/dlls/gdiplus/gdiplus.spec
+++ b/dlls/gdiplus/gdiplus.spec
@@ -178,7 +178,7 @@
 @ stdcall GdipDrawLineI(ptr ptr long long long long)
 @ stdcall GdipDrawLines(ptr ptr ptr long)
 @ stub GdipDrawLinesI
-@ stub GdipDrawPath
+@ stdcall GdipDrawPath(ptr ptr ptr)
 @ stdcall GdipDrawPie(ptr ptr long long long long long long)
 @ stub GdipDrawPieI
 @ stub GdipDrawPolygon
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 82260ec..c16a744 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -375,6 +375,120 @@ static void draw_polybezier(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt,
     GdipFree(ptf);
 }
 
+/* Converts from gdiplus path point type to gdi path point type. */
+static BYTE convert_path_point_type(BYTE type)
+{
+    BYTE ret;
+
+    switch(type & PathPointTypePathTypeMask){
+        case PathPointTypeBezier:
+            ret = PT_BEZIERTO;
+            break;
+        case PathPointTypeLine:
+            ret = PT_LINETO;
+            break;
+        case PathPointTypeStart:
+            ret = PT_MOVETO;
+            break;
+        default:
+            ERR("Bad point type\n");
+            return 0;
+    }
+
+    if(type & PathPointTypeCloseSubpath)
+        ret |= PT_CLOSEFIGURE;
+
+    return ret;
+}
+
+/* Draws a combination of bezier curves and lines between points. */
+static GpStatus draw_poly(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt,
+    GDIPCONST BYTE * types, INT count, BOOL caps)
+{
+    POINT *pti = GdipAlloc(count * sizeof(POINT));
+    BYTE *tp = GdipAlloc(count);
+    GpPointF *ptf = NULL;
+    REAL x = pt[count - 1].X, y = pt[count - 1].Y;
+    INT i;
+    GpStatus status = GenericError;
+
+    if(!count){
+        status = Ok;
+        goto end;
+    }
+    if(!pti || !tp){
+        status = OutOfMemory;
+        goto end;
+    }
+
+    for(i = 0; i < count; i++){
+        if((types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){
+            if((i + 2 >= count) || !(types[i + 1] & PathPointTypeBezier)
+                || !(types[i + 1] & PathPointTypeBezier)){
+                ERR("Bad bezier points\n");
+                goto end;
+            }
+
+            i += 2;
+        }
+    }
+
+    if((types[count - 1] & PathPointTypePathTypeMask) == PathPointTypeBezier){
+        ptf = GdipAlloc(4 * sizeof(GpPointF));
+        memcpy(ptf, &pt[count-4], 4 * sizeof(GpPointF));
+
+        if(caps){
+            if(pen->endcap == LineCapArrowAnchor)
+                shorten_bezier_amt(ptf, pen->width);
+
+            draw_cap(hdc, pen->color, pen->endcap, pen->width, ptf[3].X,
+                ptf[3].Y, pt[count - 1].X, pt[count - 1].Y);
+        }
+        for(i = 0; i < 4; i ++){
+            pti[i + count - 4].x = roundr(ptf[i].X);
+            pti[i + count - 4].y = roundr(ptf[i].Y);
+        }
+        for(i = 0; i < count - 4; i ++){
+            pti[i].x = roundr(pt[i].X);
+            pti[i].y = roundr(pt[i].Y);
+        }
+    }
+    else if((types[count - 1] & PathPointTypePathTypeMask) == PathPointTypeLine){
+        if(caps){
+            if(pen->endcap == LineCapArrowAnchor)
+                shorten_line_amt(pt[count-2].X, pt[count-2].Y, &x, &y, pen->width);
+
+            draw_cap(hdc, pen->color, pen->endcap, pen->width, pt[count-2].X,
+                pt[count-2].Y, pt[count - 1].X, pt[count - 1].Y);
+        }
+        pti[count - 1].x = roundr(x);
+        pti[count - 1].y = roundr(y);
+        for(i = 0; i < count - 1; i ++){
+            pti[i].x = roundr(pt[i].X);
+            pti[i].y = roundr(pt[i].Y);
+        }
+    }
+    else{
+        ERR("Bad path last point\n");
+        goto end;
+    }
+
+    for(i = 0; i < count; i++){
+        tp[i] = convert_path_point_type(types[i]);
+    }
+
+    PolyDraw(hdc, pti, tp, count);
+
+    status = Ok;
+
+end:
+    GdipFree(pti);
+    GdipFree(ptf);
+    GdipFree(tp);
+
+    return status;
+}
+
 GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
 {
     if(hdc == NULL)
@@ -564,6 +678,40 @@ GpStatus WINGDIPAPI GdipDrawLines(GpGraphics *graphics, GpPen *pen, GDIPCONST
     return Ok;
 }
 
+GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
+{
+    INT save_state, i, this_fig = 0;
+    GpStatus retval;
+
+    if(!pen || !graphics)
+        return InvalidParameter;
+
+    save_state = SaveDC(graphics->hdc);
+    EndPath(graphics->hdc);
+    SelectObject(graphics->hdc, pen->gdipen);
+
+    for(i = 0; i < path->pathdata.Count; i++){
+        if(path->pathdata.Types[i] == PathPointTypeStart){
+            retval = draw_poly(graphics->hdc, pen,
+                         &path->pathdata.Points[this_fig],
+                         &path->pathdata.Types[this_fig], i - this_fig, TRUE);
+            this_fig = i;
+
+            if(retval != Ok)
+                goto end;
+        }
+    }
+
+    retval = draw_poly(graphics->hdc, pen, &path->pathdata.Points[this_fig],
+                       &path->pathdata.Types[this_fig], path->pathdata.Count - this_fig,
+                       TRUE);
+
+end:
+    RestoreDC(graphics->hdc, save_state);
+
+    return retval;
+}
+
 GpStatus WINGDIPAPI GdipDrawPie(GpGraphics *graphics, GpPen *pen, REAL x,
     REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
 {
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 04d71a9..b5743eb 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -40,6 +40,7 @@ GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,
 GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT,REAL);
 GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics*,GpPen*,INT,INT,INT,INT);
 GpStatus WINGDIPAPI GdipDrawLines(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT);
+GpStatus WINGDIPAPI GdipDrawPath(GpGraphics*,GpPen*,GpPath*);
 GpStatus WINGDIPAPI GdipDrawPie(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
 GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics*,GpPen*,INT,INT,INT,INT);
 GpStatus WINGDIPAPI GdipFillPie(GpGraphics*,GpBrush*,REAL,REAL,REAL,REAL,REAL,REAL);




More information about the wine-cvs mailing list