Vincent Povirk : gdiplus: Implement GdipWidenPath for custom dashed lines.
Alexandre Julliard
julliard at winehq.org
Thu Oct 24 13:18:56 CDT 2013
Module: wine
Branch: master
Commit: 1c35dd6cb422c575a5cbfb3d2dd402a1cd9a1f23
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1c35dd6cb422c575a5cbfb3d2dd402a1cd9a1f23
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Wed Oct 23 13:05:50 2013 -0500
gdiplus: Implement GdipWidenPath for custom dashed lines.
---
dlls/gdiplus/graphicspath.c | 142 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 127 insertions(+), 15 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
index 62f8490..8fa3cc0 100644
--- a/dlls/gdiplus/graphicspath.c
+++ b/dlls/gdiplus/graphicspath.c
@@ -1851,8 +1851,9 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
}
}
-static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
- path_list_node_t **last_point)
+static void widen_open_figure(const GpPointF *points, GpPen *pen, int start, int end,
+ GpLineCap start_cap, GpCustomLineCap *start_custom, GpLineCap end_cap,
+ GpCustomLineCap *end_custom, path_list_node_t **last_point)
{
int i;
path_list_node_t *prev_point;
@@ -1862,22 +1863,22 @@ static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
prev_point = *last_point;
- widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
- pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point);
+ widen_cap(&points[start], &points[start+1],
+ pen, start_cap, start_custom, FALSE, TRUE, last_point);
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_joint(&points[i-1], &points[i],
+ &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);
+ widen_cap(&points[end], &points[end-1],
+ pen, end_cap, end_custom, 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_joint(&points[i+1], &points[i],
+ &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);
+ widen_cap(&points[start], &points[start+1],
+ pen, start_cap, start_custom, TRUE, FALSE, last_point);
prev_point->next->type = PathPointTypeStart;
(*last_point)->type |= PathPointTypeCloseSubpath;
@@ -1925,6 +1926,111 @@ static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end,
(*last_point)->type |= PathPointTypeCloseSubpath;
}
+static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
+ int closed, path_list_node_t **last_point)
+{
+ int i, j;
+ REAL dash_pos=0.0;
+ int dash_index=0;
+ const REAL *dash_pattern;
+ int dash_count;
+ GpPointF *tmp_points;
+ REAL segment_dy;
+ REAL segment_dx;
+ REAL segment_length;
+ REAL segment_pos;
+ int num_tmp_points=0;
+ int draw_start_cap=0;
+
+ if (end <= start)
+ return;
+
+ dash_pattern = pen->dashes;
+ dash_count = pen->numdashes;
+
+ tmp_points = GdipAlloc((end - start + 2) * sizeof(GpPoint));
+ if (!tmp_points) return; /* FIXME */
+
+ if (!closed)
+ draw_start_cap = 1;
+
+ for (j=start; j <= end; j++)
+ {
+ if (j == start)
+ {
+ if (closed)
+ i = end;
+ else
+ continue;
+ }
+ else
+ i = j-1;
+
+ segment_dy = path->pathdata.Points[j].Y - path->pathdata.Points[i].Y;
+ segment_dx = path->pathdata.Points[j].X - path->pathdata.Points[i].X;
+ segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
+ segment_pos = 0.0;
+
+ while (1)
+ {
+ if (dash_pos == 0.0)
+ {
+ if ((dash_index % 2) == 0)
+ {
+ /* start dash */
+ num_tmp_points = 1;
+ tmp_points[0].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
+ tmp_points[0].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
+ }
+ else
+ {
+ /* end dash */
+ tmp_points[num_tmp_points].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
+ tmp_points[num_tmp_points].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
+
+ widen_open_figure(tmp_points, pen, 0, num_tmp_points,
+ draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
+ LineCapFlat, NULL, last_point);
+ draw_start_cap = 0;
+ num_tmp_points = 0;
+ }
+ }
+
+ if (dash_pattern[dash_index] - dash_pos > segment_length - segment_pos)
+ {
+ /* advance to next segment */
+ if ((dash_index % 2) == 0)
+ {
+ tmp_points[num_tmp_points] = path->pathdata.Points[j];
+ num_tmp_points++;
+ }
+ dash_pos += segment_length - segment_pos;
+ break;
+ }
+ else
+ {
+ /* advance to next dash in pattern */
+ segment_pos += dash_pattern[dash_index] - dash_pos;
+ dash_pos = 0.0;
+ if (++dash_index == dash_count)
+ dash_index = 0;
+ continue;
+ }
+ }
+ }
+
+ if (dash_index % 2 == 0 && num_tmp_points != 0)
+ {
+ /* last dash overflows last segment */
+ tmp_points[num_tmp_points] = path->pathdata.Points[end];
+ widen_open_figure(tmp_points, pen, 0, num_tmp_points,
+ draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
+ closed ? LineCapFlat : pen->endcap, pen->customend, last_point);
+ }
+
+ GdipFree(tmp_points);
+}
+
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
REAL flatness)
{
@@ -1966,7 +2072,7 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
if (pen->join == LineJoinRound)
FIXME("unimplemented line join %d\n", pen->join);
- if (pen->dash != DashStyleSolid)
+ if (pen->dash != DashStyleSolid && pen->dash != DashStyleCustom)
FIXME("unimplemented dash style %d\n", pen->dash);
if (pen->align != PenAlignmentCenter)
@@ -1981,12 +2087,18 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
if ((type&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
{
- widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
+ if (pen->dash == DashStyleCustom)
+ widen_dashed_figure(flat_path, pen, subpath_start, i, 1, &last_point);
+ else
+ widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
}
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);
+ if (pen->dash == DashStyleCustom)
+ widen_dashed_figure(flat_path, pen, subpath_start, i, 0, &last_point);
+ else
+ widen_open_figure(flat_path->pathdata.Points, pen, subpath_start, i, pen->startcap, pen->customstart, pen->endcap, pen->customend, &last_point);
}
}
More information about the wine-cvs
mailing list