From: David Kahurani k.kahurani@gmail.com
This should allow us to construct a path based on point that are all unknown at the time of list creation
Signed-off-by: David Kahurani k.kahurani@gmail.com --- dlls/gdiplus/graphicspath.c | 103 +++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 44 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 6cdc2a58059..4287845fa9b 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -75,10 +75,25 @@ static void free_path_list(path_list_node_t *node) * pointer on success * NULL on allocation problems */ -static path_list_node_t* add_path_list_node(path_list_node_t *node, REAL x, REAL y, BOOL type) +static path_list_node_t* add_path_list_node(path_list_node_t **node, REAL x, REAL y, BOOL type) { path_list_node_t *new;
+ if (!*node) + { + *node = heap_alloc_zero(sizeof(path_list_node_t)); + + if (!*node) + return NULL; + + (*node)->pt.X = x; + (*node)->pt.Y = y; + (*node)->type = type; + (*node)->next = NULL; + + return *node; + } + new = heap_alloc_zero(sizeof(path_list_node_t)); if(!new) return NULL; @@ -86,8 +101,8 @@ static path_list_node_t* add_path_list_node(path_list_node_t *node, REAL x, REAL new->pt.X = x; new->pt.Y = y; new->type = type; - new->next = node->next; - node->next = new; + new->next = (*node)->next; + (*node)->next = new;
return new; } @@ -169,7 +184,7 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R } else /* add a middle point */ - if(!(node = add_path_list_node(start, mp[2].X, mp[2].Y, PathPointTypeLine))) + if(!(node = add_path_list_node(&start, mp[2].X, mp[2].Y, PathPointTypeLine))) return FALSE;
/* do the same with halves */ @@ -1333,7 +1348,7 @@ GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatnes
/* always add line points and start points */ if((type == PathPointTypeStart) || (type == PathPointTypeLine)){ - if(!add_path_list_node(node, pt.X, pt.Y, path->pathdata.Types[i])) + if(!add_path_list_node(&node, pt.X, pt.Y, path->pathdata.Types[i])) goto memout;
node = node->next; @@ -1357,7 +1372,7 @@ GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatnes start = node; /* add Bezier end point */ type = (path->pathdata.Types[i] & ~PathPointTypePathTypeMask) | PathPointTypeLine; - if(!add_path_list_node(node, pt.X, pt.Y, type)) + if(!add_path_list_node(&node, pt.X, pt.Y, type)) goto memout; node = node->next;
@@ -1829,7 +1844,7 @@ static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint,
if (segment_length == 0.0) { - *last_point = add_path_list_node(*last_point, endpoint->X, + *last_point = add_path_list_node(last_point, endpoint->X, endpoint->Y, PathPointTypeLine); return; } @@ -1845,7 +1860,7 @@ static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint, bevel_dy = -distance * segment_dx / segment_length; }
- *last_point = add_path_list_node(*last_point, endpoint->X + bevel_dx, + *last_point = add_path_list_node(last_point, endpoint->X + bevel_dx, endpoint->Y + bevel_dy, PathPointTypeLine); }
@@ -1870,7 +1885,7 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF * float dy = (dy0*dy1*(dy0-dy1) + dx0*dx0*dy1 - dx1*dx1*dy0)/det; if (dx*dx + dy*dy < pen->miterlimit*pen->miterlimit * distance*distance) { - *last_point = add_path_list_node(*last_point, p2->X + dx, + *last_point = add_path_list_node(last_point, p2->X + dx, p2->Y + dy, PathPointTypeLine); break; } @@ -1933,11 +1948,11 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, }
if (add_first_points) - *last_point = add_path_list_node(*last_point, endpoint->X - extend_dx + bevel_dx, + *last_point = add_path_list_node(last_point, endpoint->X - extend_dx + bevel_dx, endpoint->Y - extend_dy + bevel_dy, PathPointTypeLine);
if (add_last_point) - *last_point = add_path_list_node(*last_point, endpoint->X - extend_dx - bevel_dx, + *last_point = add_path_list_node(last_point, endpoint->X - extend_dx - bevel_dx, endpoint->Y - extend_dy - bevel_dy, PathPointTypeLine); break; } @@ -1959,27 +1974,27 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, dy2 = dy * control_point_distance;
/* first 90-degree arc */ - *last_point = add_path_list_node(*last_point, endpoint->X + dy, + *last_point = add_path_list_node(last_point, endpoint->X + dy, endpoint->Y - dx, PathPointTypeLine);
- *last_point = add_path_list_node(*last_point, endpoint->X + dy + dx2, + *last_point = add_path_list_node(last_point, endpoint->X + dy + dx2, endpoint->Y - dx + dy2, PathPointTypeBezier);
- *last_point = add_path_list_node(*last_point, endpoint->X + dx + dy2, + *last_point = add_path_list_node(last_point, endpoint->X + dx + dy2, endpoint->Y + dy - dx2, PathPointTypeBezier);
/* midpoint */ - *last_point = add_path_list_node(*last_point, endpoint->X + dx, + *last_point = add_path_list_node(last_point, endpoint->X + dx, endpoint->Y + dy, PathPointTypeBezier);
/* second 90-degree arc */ - *last_point = add_path_list_node(*last_point, endpoint->X + dx - dy2, + *last_point = add_path_list_node(last_point, endpoint->X + dx - dy2, endpoint->Y + dy + dx2, PathPointTypeBezier);
- *last_point = add_path_list_node(*last_point, endpoint->X - dy + dx2, + *last_point = add_path_list_node(last_point, endpoint->X - dy + dx2, endpoint->Y + dx + dy2, PathPointTypeBezier);
- *last_point = add_path_list_node(*last_point, endpoint->X - dy, + *last_point = add_path_list_node(last_point, endpoint->X - dy, endpoint->Y + dx, PathPointTypeBezier); } else if (add_last_point) @@ -2000,7 +2015,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, if (add_first_points) { add_bevel_point(endpoint, nextpoint, pen_width, 1, last_point);
- *last_point = add_path_list_node(*last_point, endpoint->X - dx, + *last_point = add_path_list_node(last_point, endpoint->X - dx, endpoint->Y - dy, PathPointTypeLine); } if (add_first_points || add_last_point) @@ -2041,13 +2056,13 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, perp_dx = -distance * segment_dy / segment_length; perp_dy = distance * segment_dx / segment_length;
- *last_point = add_path_list_node(*last_point, endpoint->X - par_dx - perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X - par_dx - perp_dx, endpoint->Y - par_dy - perp_dy, PathPointTypeStart); - *last_point = add_path_list_node(*last_point, endpoint->X - par_dx + perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X - par_dx + perp_dx, endpoint->Y - par_dy + perp_dy, PathPointTypeLine); - *last_point = add_path_list_node(*last_point, endpoint->X + par_dx + perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X + par_dx + perp_dx, endpoint->Y + par_dy + perp_dy, PathPointTypeLine); - *last_point = add_path_list_node(*last_point, endpoint->X + par_dx - perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X + par_dx - perp_dx, endpoint->Y + par_dy - perp_dy, PathPointTypeLine); break; } @@ -2066,39 +2081,39 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, dy2 = dy * control_point_distance;
/* starting point */ - *last_point = add_path_list_node(*last_point, endpoint->X + dy, + *last_point = add_path_list_node(last_point, endpoint->X + dy, endpoint->Y - dx, PathPointTypeStart);
/* first 90-degree arc */ - *last_point = add_path_list_node(*last_point, endpoint->X + dy + dx2, + *last_point = add_path_list_node(last_point, endpoint->X + dy + dx2, endpoint->Y - dx + dy2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X + dx + dy2, + *last_point = add_path_list_node(last_point, endpoint->X + dx + dy2, endpoint->Y + dy - dx2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X + dx, + *last_point = add_path_list_node(last_point, endpoint->X + dx, endpoint->Y + dy, PathPointTypeBezier);
/* second 90-degree arc */ - *last_point = add_path_list_node(*last_point, endpoint->X + dx - dy2, + *last_point = add_path_list_node(last_point, endpoint->X + dx - dy2, endpoint->Y + dy + dx2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X - dy + dx2, + *last_point = add_path_list_node(last_point, endpoint->X - dy + dx2, endpoint->Y + dx + dy2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X - dy, + *last_point = add_path_list_node(last_point, endpoint->X - dy, endpoint->Y + dx, PathPointTypeBezier);
/* third 90-degree arc */ - *last_point = add_path_list_node(*last_point, endpoint->X - dy - dx2, + *last_point = add_path_list_node(last_point, endpoint->X - dy - dx2, endpoint->Y + dx - dy2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X - dx - dy2, + *last_point = add_path_list_node(last_point, endpoint->X - dx - dy2, endpoint->Y - dy + dx2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X - dx, + *last_point = add_path_list_node(last_point, endpoint->X - dx, endpoint->Y - dy, PathPointTypeBezier);
/* fourth 90-degree arc */ - *last_point = add_path_list_node(*last_point, endpoint->X - dx + dy2, + *last_point = add_path_list_node(last_point, endpoint->X - dx + dy2, endpoint->Y - dy - dx2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X + dy - dx2, + *last_point = add_path_list_node(last_point, endpoint->X + dy - dx2, endpoint->Y - dx - dy2, PathPointTypeBezier); - *last_point = add_path_list_node(*last_point, endpoint->X + dy, + *last_point = add_path_list_node(last_point, endpoint->X + dy, endpoint->Y - dx, PathPointTypeBezier);
break; @@ -2117,13 +2132,13 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, perp_dx = -pen_width * segment_dy / segment_length; perp_dy = pen_width * segment_dx / segment_length;
- *last_point = add_path_list_node(*last_point, endpoint->X + par_dx, + *last_point = add_path_list_node(last_point, endpoint->X + par_dx, endpoint->Y + par_dy, PathPointTypeStart); - *last_point = add_path_list_node(*last_point, endpoint->X - perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X - perp_dx, endpoint->Y - perp_dy, PathPointTypeLine); - *last_point = add_path_list_node(*last_point, endpoint->X - par_dx, + *last_point = add_path_list_node(last_point, endpoint->X - par_dx, endpoint->Y - par_dy, PathPointTypeLine); - *last_point = add_path_list_node(*last_point, endpoint->X + perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X + perp_dx, endpoint->Y + perp_dy, PathPointTypeLine); break; } @@ -2137,11 +2152,11 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, REAL perp_dx = -par_dy; REAL perp_dy = par_dx;
- *last_point = add_path_list_node(*last_point, endpoint->X, + *last_point = add_path_list_node(last_point, endpoint->X, endpoint->Y, PathPointTypeStart); - *last_point = add_path_list_node(*last_point, endpoint->X + SQRT3 * par_dx - perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X + SQRT3 * par_dx - perp_dx, endpoint->Y + SQRT3 * par_dy - perp_dy, PathPointTypeLine); - *last_point = add_path_list_node(*last_point, endpoint->X + SQRT3 * par_dx + perp_dx, + *last_point = add_path_list_node(last_point, endpoint->X + SQRT3 * par_dx + perp_dx, endpoint->Y + SQRT3 * par_dy + perp_dy, PathPointTypeLine); break; } @@ -2200,7 +2215,7 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, /* rotation of CustomCap according to line */ perp_dx = custom->pathdata.Points[i].X * cosa + (custom->pathdata.Points[i].Y - 1.0) * sina; perp_dy = custom->pathdata.Points[i].X * sina - (custom->pathdata.Points[i].Y - 1.0) * cosa; - *last_point = add_path_list_node(*last_point, posx + perp_dx, + *last_point = add_path_list_node(last_point, posx + perp_dx, posy + perp_dy, custom->pathdata.Types[i]); } }