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