Vincent Povirk : gdiplus: Add basic implementation of GdipWidenPath.

Alexandre Julliard julliard at winehq.org
Thu Apr 26 13:58:35 CDT 2012


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Tue Apr 24 16:32:50 2012 -0500

gdiplus: Add basic implementation of GdipWidenPath.

---

 dlls/gdiplus/graphicspath.c |  172 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 170 insertions(+), 2 deletions(-)

diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
index c41278c..8096507 100644
--- a/dlls/gdiplus/graphicspath.c
+++ b/dlls/gdiplus/graphicspath.c
@@ -1656,12 +1656,180 @@ GpStatus WINGDIPAPI GdipWarpPath(GpPath *path, GpMatrix* matrix,
     return NotImplemented;
 }
 
+static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint,
+    GpPen *pen, int right_side, path_list_node_t **last_point)
+{
+    REAL segment_dy = nextpoint->Y-endpoint->Y;
+    REAL segment_dx = nextpoint->X-endpoint->X;
+    REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
+    REAL distance = pen->width/2.0;
+    REAL bevel_dx, bevel_dy;
+
+    if (right_side)
+    {
+        bevel_dx = -distance * segment_dy / segment_length;
+        bevel_dy = distance * segment_dx / segment_length;
+    }
+    else
+    {
+        bevel_dx = distance * segment_dy / segment_length;
+        bevel_dy = -distance * segment_dx / segment_length;
+    }
+
+    *last_point = add_path_list_node(*last_point, endpoint->X + bevel_dx,
+        endpoint->Y + bevel_dy, PathPointTypeLine);
+}
+
+static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *p3,
+    GpPen* pen, path_list_node_t **last_point)
+{
+    switch (pen->join)
+    {
+    default:
+    case LineJoinBevel:
+        add_bevel_point(p2, p1, pen, 1, last_point);
+        add_bevel_point(p2, p3, pen, 0, last_point);
+        break;
+    }
+}
+
+static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
+    GpPen *pen, GpLineCap cap, GpCustomLineCap *custom, int add_first_points,
+    int add_last_point, path_list_node_t **last_point)
+{
+    switch (cap)
+    {
+    default:
+    case LineCapFlat:
+        if (add_first_points)
+            add_bevel_point(endpoint, nextpoint, pen, 1, last_point);
+        if (add_last_point)
+            add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
+        break;
+    }
+}
+
+static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
+    path_list_node_t **last_point)
+{
+    int i;
+
+    if (end <= start)
+        return;
+
+    widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
+        pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point);
+
+    (*last_point)->type = PathPointTypeStart;
+
+    for (i=start+1; i<end; i++)
+        widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
+            &path->pathdata.Points[i+1], pen, last_point);
+
+    widen_cap(&path->pathdata.Points[end], &path->pathdata.Points[end-1],
+        pen, pen->endcap, pen->customend, TRUE, TRUE, last_point);
+
+    for (i=end-1; i>start; i--)
+        widen_joint(&path->pathdata.Points[i+1], &path->pathdata.Points[i],
+            &path->pathdata.Points[i-1], pen, last_point);
+
+    widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
+        pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point);
+
+    (*last_point)->type |= PathPointTypeCloseSubpath;
+}
+
 GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
     REAL flatness)
 {
-    FIXME("(%p,%p,%p,%0.2f)\n", path, pen, matrix, flatness);
+    GpPath *flat_path=NULL;
+    GpStatus status;
+    path_list_node_t *points=NULL, *last_point=NULL;
+    int i, subpath_start=0, new_length;
+    BYTE type;
 
-    return NotImplemented;
+    TRACE("(%p,%p,%p,%0.2f)\n", path, pen, matrix, flatness);
+
+    if (!path || !pen)
+        return InvalidParameter;
+
+    if (path->pathdata.Count <= 1)
+        return OutOfMemory;
+
+    status = GdipClonePath(path, &flat_path);
+
+    if (status == Ok)
+        status = GdipFlattenPath(flat_path, matrix, flatness);
+
+    if (status == Ok && !init_path_list(&points, 314.0, 22.0))
+        status = OutOfMemory;
+
+    if (status == Ok)
+    {
+        last_point = points;
+
+        if (pen->endcap != LineCapFlat)
+            FIXME("unimplemented end cap %x\n", pen->endcap);
+
+        if (pen->startcap != LineCapFlat)
+            FIXME("unimplemented start cap %x\n", pen->startcap);
+
+        if (pen->dashcap != DashCapFlat)
+            FIXME("unimplemented dash cap %d\n", pen->dashcap);
+
+        if (pen->join != LineJoinBevel)
+            FIXME("unimplemented line join %d\n", pen->join);
+
+        if (pen->dash != DashStyleSolid)
+            FIXME("unimplemented dash style %d\n", pen->dash);
+
+        if (pen->align != PenAlignmentCenter)
+            FIXME("unimplemented pen alignment %d\n", pen->align);
+
+        for (i=0; i < flat_path->pathdata.Count; i++)
+        {
+            type = flat_path->pathdata.Types[i];
+
+            if ((type&PathPointTypePathTypeMask) == PathPointTypeStart)
+                subpath_start = i;
+
+            if ((type&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
+            {
+                FIXME("closed figures unimplemented\n");
+            }
+            else if (i == flat_path->pathdata.Count-1 ||
+                (flat_path->pathdata.Types[i+1]&PathPointTypePathTypeMask) == PathPointTypeStart)
+            {
+                widen_open_figure(flat_path, pen, subpath_start, i, &last_point);
+            }
+        }
+
+        new_length = path_list_count(points)-1;
+
+        if (!lengthen_path(path, new_length))
+            status = OutOfMemory;
+    }
+
+    if (status == Ok)
+    {
+        path->pathdata.Count = new_length;
+
+        last_point = points->next;
+        for (i = 0; i < new_length; i++)
+        {
+            path->pathdata.Points[i] = last_point->pt;
+            path->pathdata.Types[i] = last_point->type;
+            last_point = last_point->next;
+        }
+
+        path->fill = FillModeWinding;
+    }
+
+    free_path_list(points);
+
+    GdipDeletePath(flat_path);
+
+    return status;
 }
 
 GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y,




More information about the wine-cvs mailing list