From 930cdab2e9d17be1d1cb1c38f2f28dc764d98b90 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Tue, 24 Apr 2012 16:32:50 -0500 Subject: [PATCH] gdiplus: Add basic implementation of GdipWidenPath. --- dlls/gdiplus/graphicspath.c | 172 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 2 deletions(-) diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index c41278c250d..8096507661d 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; ipathdata.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, -- 2.11.4.GIT