Skip to content

Commit

Permalink
2008-09-03 Sebastien Pouliot <sebastien@ximian.com>
Browse files Browse the repository at this point in the history
	* general.c: Compute intermediate start/end points correctly on an
	open curve. Patch by Marek Habersack
	* graphics-path.c: Add support to compress points (skip on of two 
	identical consecutive points) under some special cases.


svn path=/branches/mono-2-0/libgdiplus/; revision=112192
  • Loading branch information
Sebastien Pouliot committed Sep 3, 2008
1 parent 959464e commit 775b9c9
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 53 deletions.
7 changes: 7 additions & 0 deletions src/ChangeLog
@@ -1,3 +1,10 @@
2008-09-03 Sebastien Pouliot <sebastien@ximian.com>

* general.c: Compute intermediate start/end points correctly on an
open curve. Patch by Marek Habersack
* graphics-path.c: Add support to compress points (skip on of two
identical consecutive points) under some special cases.

2008-08-11 Sebastien Pouliot <sebastien@ximian.com> 2008-08-11 Sebastien Pouliot <sebastien@ximian.com>


* image.c: Remove buggy loop in gdip_bitmap_clone which allocates way * image.c: Remove buggy loop in gdip_bitmap_clone which allocates way
Expand Down
2 changes: 1 addition & 1 deletion src/general.c
Expand Up @@ -199,7 +199,7 @@ gdip_open_curve_tangents (int terms, const GpPointF *points, int count, float te
if (count <= 2) if (count <= 2)
return tangents; return tangents;


for (i = 1; i < count - 1; i++) { for (i = 0; i < count; i++) {
int r = i + 1; int r = i + 1;
int s = i - 1; int s = i - 1;


Expand Down
123 changes: 71 additions & 52 deletions src/graphics-path.c
Expand Up @@ -113,12 +113,22 @@ gdip_get_first_point_type (GpPath *path)
} }


static void static void
append (GpPath *path, float x, float y, PathPointType type) append (GpPath *path, float x, float y, PathPointType type, BOOL compress)
{ {
BYTE t = (BYTE) type; BYTE t = (BYTE) type;
GpPointF pt; GpPointF pt;


pt.X = x; pt.Y = y; /* in some case we're allowed to compress identical points */
if (compress && (path->count > 0)) {
/* points (X, Y) must be identical */
GpPointF lastPoint = g_array_index (path->points, GpPointF, path->count - 1);
if ((lastPoint.X == x) && (lastPoint.Y == y)) {
/* types need not be identical but must handle closed subpaths */
PathPointType last_type = g_array_index (path->types, BYTE, path->count - 1);
if ((last_type & PathPointTypeCloseSubpath) != PathPointTypeCloseSubpath)
return;
}
}


if (path->start_new_fig) if (path->start_new_fig)
t = PathPointTypeStart; t = PathPointTypeStart;
Expand All @@ -129,6 +139,9 @@ append (GpPath *path, float x, float y, PathPointType type)
t = PathPointTypeStart; t = PathPointTypeStart;
} }


pt.X = x;
pt.Y = y;

g_array_append_val (path->points, pt); g_array_append_val (path->points, pt);
g_byte_array_append (path->types, &t, 1); g_byte_array_append (path->types, &t, 1);
path->count++; path->count++;
Expand All @@ -137,17 +150,17 @@ append (GpPath *path, float x, float y, PathPointType type)
} }


static void static void
append_point (GpPath *path, GpPointF pt, PathPointType type) append_point (GpPath *path, GpPointF pt, PathPointType type, BOOL compress)
{ {
append (path, pt.X, pt.Y, type); append (path, pt.X, pt.Y, type, compress);
} }


static void static void
append_bezier (GpPath *path, float x1, float y1, float x2, float y2, float x3, float y3) append_bezier (GpPath *path, float x1, float y1, float x2, float y2, float x3, float y3)
{ {
append (path, x1, y1, PathPointTypeBezier3); append (path, x1, y1, PathPointTypeBezier3, FALSE);
append (path, x2, y2, PathPointTypeBezier3); append (path, x2, y2, PathPointTypeBezier3, FALSE);
append (path, x3, y3, PathPointTypeBezier3); append (path, x3, y3, PathPointTypeBezier3, FALSE);
} }


static void static void
Expand All @@ -156,7 +169,7 @@ append_curve (GpPath *path, const GpPointF *points, GpPointF *tangents, int offs
int i; int i;
PathPointType ptype = ((type == CURVE_CLOSE) || (path->count == 0)) ? PathPointTypeStart : PathPointTypeLine; PathPointType ptype = ((type == CURVE_CLOSE) || (path->count == 0)) ? PathPointTypeStart : PathPointTypeLine;


append_point (path, points [offset], ptype); append_point (path, points [offset], ptype, TRUE);
for (i = offset; i < offset + length; i++) { for (i = offset; i < offset + length; i++) {
int j = i + 1; int j = i + 1;


Expand Down Expand Up @@ -697,8 +710,9 @@ GdipAddPathLine (GpPath *path, float x1, float y1, float x2, float y2)
if (!path) if (!path)
return InvalidParameter; return InvalidParameter;


append (path, x1, y1, PathPointTypeLine); /* only the first point can be compressed (i.e. removed if identical to previous) */
append (path, x2, y2, PathPointTypeLine); append (path, x1, y1, PathPointTypeLine, TRUE);
append (path, x2, y2, PathPointTypeLine, FALSE);


return Ok; return Ok;
} }
Expand All @@ -712,10 +726,9 @@ GdipAddPathLine2 (GpPath *path, const GpPointF *points, int count)
if (!path || !points || (count < 0)) if (!path || !points || (count < 0))
return InvalidParameter; return InvalidParameter;


tmp = (GpPointF *) points; /* only the first point can be compressed (i.e. removed if identical to previous) */

for (i = 0, tmp = (GpPointF*) points; i < count; i++, tmp++)
for (i = 0; i < count; i++, tmp++) append (path, tmp->X, tmp->Y, PathPointTypeLine, (i == 0));
append_point (path, *tmp, PathPointTypeLine);


return Ok; return Ok;
} }
Expand Down Expand Up @@ -763,7 +776,7 @@ append_arc (GpPath *path, BOOL start, float x, float y, float width, float heigh
/* starting point */ /* starting point */
sx = cx + rx * cos_alpha; sx = cx + rx * cos_alpha;
sy = cy + ry * sin_alpha; sy = cy + ry * sin_alpha;
append (path, sx, sy, PathPointTypeLine); append (path, sx, sy, PathPointTypeLine, FALSE);
} }


append_bezier (path, append_bezier (path,
Expand Down Expand Up @@ -838,7 +851,7 @@ GdipAddPathBezier (GpPath *path,
if (!path) if (!path)
return InvalidParameter; return InvalidParameter;


append (path, x1, y1, PathPointTypeLine); append (path, x1, y1, PathPointTypeLine, TRUE);
append_bezier (path, x2, y2, x3, y3, x4, y4); append_bezier (path, x2, y2, x3, y3, x4, y4);


return Ok; return Ok;
Expand All @@ -857,11 +870,11 @@ GdipAddPathBeziers (GpPath *path, const GpPointF *points, int count)
if ((count < 4) || ((count % 3) != 1)) if ((count < 4) || ((count % 3) != 1))
return InvalidParameter; return InvalidParameter;


append_point (path, *tmp, PathPointTypeLine); append_point (path, *tmp, PathPointTypeLine, TRUE);
tmp++; tmp++;


for (i = 1; i < count; i++, tmp++) for (i = 1; i < count; i++, tmp++)
append_point (path, *tmp, PathPointTypeBezier3); append_point (path, *tmp, PathPointTypeBezier3, FALSE);


return Ok; return Ok;
} }
Expand Down Expand Up @@ -952,10 +965,13 @@ GdipAddPathRectangle (GpPath *path, float x, float y, float width, float height)
if (!path) if (!path)
return InvalidParameter; return InvalidParameter;


append (path, x, y, PathPointTypeStart); if ((width == 0.0) || (height == 0.0))
append (path, x + width, y, PathPointTypeLine); return Ok;
append (path, x + width, y + height, PathPointTypeLine);
append (path, x, y + height, PathPointTypeLine | PathPointTypeCloseSubpath); append (path, x, y, PathPointTypeStart, FALSE);
append (path, x + width, y, PathPointTypeLine, FALSE);
append (path, x + width, y + height, PathPointTypeLine, FALSE);
append (path, x, y + height, PathPointTypeLine | PathPointTypeCloseSubpath, FALSE);


return Ok; return Ok;
} }
Expand Down Expand Up @@ -991,7 +1007,7 @@ GdipAddPathEllipse (GpPath *path, float x, float y, float width, float height)
return InvalidParameter; return InvalidParameter;


/* origin */ /* origin */
append (path, cx + rx, cy, PathPointTypeStart); append (path, cx + rx, cy, PathPointTypeStart, FALSE);


/* quadrant I */ /* quadrant I */
append_bezier (path, append_bezier (path,
Expand Down Expand Up @@ -1048,19 +1064,18 @@ GdipAddPathPie (GpPath *path, float x, float y, float width, float height, float
return InvalidParameter; return InvalidParameter;


/* move to center */ /* move to center */
append (path, cx, cy, PathPointTypeStart); append (path, cx, cy, PathPointTypeStart, FALSE);


/* draw pie edge */ /* draw pie edge */
if (fabs (sweepAngle) < 360) if (fabs (sweepAngle) < 360)
append (path, cx + rx * cos_alpha, cy + ry * sin_alpha, append (path, cx + rx * cos_alpha, cy + ry * sin_alpha, PathPointTypeLine, FALSE);
PathPointTypeLine);


/* draw the arcs */ /* draw the arcs */
append_arcs (path, x, y, width, height, startAngle, sweepAngle); append_arcs (path, x, y, width, height, startAngle, sweepAngle);


/* draw pie edge */ /* draw pie edge */
if (fabs (sweepAngle) < 360) if (fabs (sweepAngle) < 360)
append (path, cx, cy, PathPointTypeLine); append (path, cx, cy, PathPointTypeLine, FALSE);


/* close the path */ /* close the path */
return GdipClosePathFigure (path); return GdipClosePathFigure (path);
Expand All @@ -1074,19 +1089,21 @@ GdipAddPathPolygon (GpPath *path, const GpPointF *points, int count)


if (!path || !points || (count < 3)) if (!path || !points || (count < 3))
return InvalidParameter; return InvalidParameter;

append_point (path, *tmp, PathPointTypeStart);
tmp ++;


for (i = 1; i < count; i++, tmp++) /* note: polygon points are never compressed (i.e. removed if identical) */
append_point (path, *tmp, PathPointTypeLine);
append_point (path, *tmp, PathPointTypeStart, FALSE);
tmp ++;

for (i = 1; i < count; i++, tmp++)
append_point (path, *tmp, PathPointTypeLine, FALSE);


/* /*
* Add a line from the last point back to the first point if * Add a line from the last point back to the first point if
* they're not the same * they're not the same
*/ */
if (points [0].X != points [count - 1].X && points [0].Y != points [count - 1].Y) if (points [0].X != points [count - 1].X && points [0].Y != points [count - 1].Y)
append_point (path, points [0], PathPointTypeLine); append_point (path, points [0], PathPointTypeLine, FALSE);


/* close the path */ /* close the path */
return GdipClosePathFigure (path); return GdipClosePathFigure (path);
Expand Down Expand Up @@ -1124,10 +1141,10 @@ GdipAddPathPath (GpPath *path, GDIPCONST GpPath *addingPath, BOOL connect)
*/ */
first = connect ? gdip_get_first_point_type (path) : PathPointTypeStart; first = connect ? gdip_get_first_point_type (path) : PathPointTypeStart;


append_point (path, pts [0], first); append_point (path, pts [0], first, FALSE);


for (i = 1; i < length; i++) for (i = 1; i < length; i++)
append_point (path, pts [i], types [i]); append_point (path, pts [i], types [i], FALSE);


GdipFree(pts); GdipFree(pts);
GdipFree(types); GdipFree(types);
Expand Down Expand Up @@ -1220,15 +1237,15 @@ GdipAddPathString (GpPath *path, GDIPCONST WCHAR *string, int length,


switch (data->header.type) { switch (data->header.type) {
case CAIRO_PATH_MOVE_TO: case CAIRO_PATH_MOVE_TO:
append (path, data[1].point.x, data[1].point.y, type); append (path, data[1].point.x, data[1].point.y, type, FALSE);
break; break;
case CAIRO_PATH_LINE_TO: case CAIRO_PATH_LINE_TO:
append (path, data[1].point.x, data[1].point.y, type | PathPointTypeLine); append (path, data[1].point.x, data[1].point.y, type | PathPointTypeLine, FALSE);
break; break;
case CAIRO_PATH_CURVE_TO: case CAIRO_PATH_CURVE_TO:
append (path, data[1].point.x, data[1].point.y, PathPointTypeBezier); append (path, data[1].point.x, data[1].point.y, PathPointTypeBezier, FALSE);
append (path, data[2].point.x, data[2].point.y, PathPointTypeBezier); append (path, data[2].point.x, data[2].point.y, PathPointTypeBezier, FALSE);
append (path, data[3].point.x, data[3].point.y, type | PathPointTypeBezier); append (path, data[3].point.x, data[3].point.y, type | PathPointTypeBezier, FALSE);
break; break;
case CAIRO_PATH_CLOSE_PATH: case CAIRO_PATH_CLOSE_PATH:
break; break;
Expand Down Expand Up @@ -1282,9 +1299,9 @@ GdipAddPathLine2I (GpPath* path, const GpPoint *points, int count)
if (!path || !points || (count < 0)) if (!path || !points || (count < 0))
return InvalidParameter; return InvalidParameter;


for (i = 0, tmp = (GpPoint*) points; i < count; i++, tmp++) { /* only the first point can be compressed (i.e. removed if identical to previous) */
append (path, tmp->X, tmp->Y, PathPointTypeLine); for (i = 0, tmp = (GpPoint*) points; i < count; i++, tmp++)
} append (path, tmp->X, tmp->Y, PathPointTypeLine, (i == 0));


return Ok; return Ok;
} }
Expand Down Expand Up @@ -1315,11 +1332,11 @@ GdipAddPathBeziersI (GpPath *path, const GpPoint *points, int count)
return InvalidParameter; return InvalidParameter;


tmp = (GpPoint*) points; tmp = (GpPoint*) points;
append (path, tmp->X, tmp->Y, PathPointTypeLine); append (path, tmp->X, tmp->Y, PathPointTypeLine, TRUE);
tmp++; tmp++;


for (i = 1; i < count; i++, tmp++) for (i = 1; i < count; i++, tmp++)
append (path, tmp->X, tmp->Y, PathPointTypeBezier3); append (path, tmp->X, tmp->Y, PathPointTypeBezier3, FALSE);


return Ok; return Ok;
} }
Expand Down Expand Up @@ -1442,19 +1459,21 @@ GdipAddPathPolygonI (GpPath *path, const GpPoint *points, int count)
if (!path || !points || (count < 3)) if (!path || !points || (count < 3))
return InvalidParameter; return InvalidParameter;


/* note: polygon points are never compressed (i.e. removed if identical) */

tmp = (GpPoint *) points; tmp = (GpPoint *) points;
append (path, tmp->X, tmp->Y, PathPointTypeStart); append (path, tmp->X, tmp->Y, PathPointTypeStart, FALSE);
tmp ++; tmp++;


for (i = 1; i < count; i++, tmp++) for (i = 1; i < count; i++, tmp++)
append (path, tmp->X, tmp->Y, PathPointTypeLine); append (path, tmp->X, tmp->Y, PathPointTypeLine, FALSE);


/* /*
* Add a line from the last point back to the first point if * Add a line from the last point back to the first point if
* they're not the same * they're not the same
*/ */
if (points [0].X != points [count - 1].X && points [0].Y != points [count - 1].Y) if (points [0].X != points [count - 1].X && points [0].Y != points [count - 1].Y)
append (path, points [0].X, points [0].Y, PathPointTypeLine); append (path, points [0].X, points [0].Y, PathPointTypeLine, FALSE);


/* close the path */ /* close the path */
return GdipClosePathFigure (path); return GdipClosePathFigure (path);
Expand Down

0 comments on commit 775b9c9

Please sign in to comment.