Commit a2aa26cd authored by Raph Levien's avatar Raph Levien

Stability and correctness fixes for the aa canvas rendering (it was dealing

very poorly with stroking of zero-length vectors).
parent a8722268
Wed Jun 2 21:56:30 1999 Raph Levien <raph@gimp.org>
* art_svp_vpath_stroke.c (art_svp_vpath_stroke_raw): Made the
closed path detection capable of PostScript semantics (i.e. it
now senses the difference between ART_MOVETO and ART_MOVETO_OPEN).
* art_svp_vpath_stroke.c (art_svp_vpath_stroke_raw): it now
filters out successive points that are (nearly) coincident. This
fixes some of the crashes and hangs, including Tim Janik's
singularity (trying to stroke MOVETO 50, 50; LINETO 50, 50; END).
* art_svp_wind.c (art_svp_rewind_uncrossed): added a test to
correctly handle empty input svp's.
* art_svp_wind.c (art_svp_uncross): added a test to correctly
handle empty input svp's.
Sun Jan 17 20:53:40 1999 Jeff Garzik <jgarzik@pobox.com>
* art_affine.c:
......
......@@ -280,6 +280,9 @@ art_svp_vpath_stroke_raw (ArtVpath *vpath,
ArtVpath *result;
int n_result, n_result_max;
double half_lw = 0.5 * line_width;
int closed;
int last, this, next, second;
double dx, dy;
n_forw_max = 16;
forw = art_new (ArtVpath, n_forw_max);
......@@ -296,29 +299,58 @@ art_svp_vpath_stroke_raw (ArtVpath *vpath,
n_forw = 0;
n_rev = 0;
closed = (vpath[begin_idx].code == ART_MOVETO);
/* we don't know what the first point joins with until we get to the
last point and see if it's closed. So we start with the second
line in the path. */
for (i = begin_idx; vpath[i + 1].code == ART_LINETO;
i++)
line in the path.
Note: this is not strictly true (we now know it's closed from
the opening pathcode), but why fix code that isn't broken?
*/
this = begin_idx;
/* skip over identical points at the beginning of the subpath */
for (i = this + 1; vpath[i].code == ART_LINETO; i++)
{
dx = vpath[i].x - vpath[this].x;
dy = vpath[i].y - vpath[this].y;
if (dx * dx + dy * dy > EPSILON_2)
break;
}
next = i;
second = next;
/* invariant: this doesn't coincide with next */
while (vpath[next].code == ART_LINETO)
{
/* render the segment from [i] to [i + 1], joining with [i - 1]
and [i + 2] */
if (vpath[i + 2].code != ART_LINETO)
last = this;
this = next;
/* skip over identical points after the beginning of the subpath */
for (i = this + 1; vpath[i].code == ART_LINETO; i++)
{
dx = vpath[i].x - vpath[this].x;
dy = vpath[i].y - vpath[this].y;
if (dx * dx + dy * dy > EPSILON_2)
break;
}
next = i;
if (vpath[next].code != ART_LINETO)
{
/* reached end of path */
/* todo: make "closed" detection conform to PostScript
/* make "closed" detection conform to PostScript
semantics (i.e. explicit closepath code rather than
the fact that end of the path is the beginning) */
if (vpath[i + 1].x == vpath[begin_idx].x &&
vpath[i + 1].y == vpath[begin_idx].y)
just the fact that end of the path is the beginning) */
if (closed &&
vpath[this].x == vpath[begin_idx].x &&
vpath[this].y == vpath[begin_idx].y)
{
int j;
/* path is closed, render join to beginning */
render_seg (&forw, &n_forw, &n_forw_max,
&rev, &n_rev, &n_rev_max,
vpath, i, i + 1, begin_idx + 1,
vpath, last, this, second,
join, half_lw, miter_limit);
#ifdef VERBOSE
......@@ -350,7 +382,7 @@ art_svp_vpath_stroke_raw (ArtVpath *vpath,
/* add to forw rather than result to ensure that
forw has at least one point. */
render_cap (&forw, &n_forw, &n_forw_max,
vpath, i, i + 1,
vpath, last, this,
cap, half_lw);
art_vpath_add_point (&result, &n_result, &n_result_max,
ART_MOVETO, forw[0].x,
......@@ -364,7 +396,7 @@ art_svp_vpath_stroke_raw (ArtVpath *vpath,
ART_LINETO, rev[j].x,
rev[j].y);
render_cap (&result, &n_result, &n_result_max,
vpath, begin_idx + 1, begin_idx,
vpath, second, begin_idx,
cap, half_lw);
art_vpath_add_point (&result, &n_result, &n_result_max,
ART_LINETO, forw[0].x,
......@@ -374,10 +406,10 @@ art_svp_vpath_stroke_raw (ArtVpath *vpath,
else
render_seg (&forw, &n_forw, &n_forw_max,
&rev, &n_rev, &n_rev_max,
vpath, i, i + 1, i + 2,
vpath, last, this, next,
join, half_lw, miter_limit);
}
end_idx = i + 1;
end_idx = next;
}
art_free (forw);
......
......@@ -981,6 +981,14 @@ art_svp_uncross (ArtSVP *vp)
double share_x;
ArtPoint *pts;
n_segs_max = 16;
new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
(n_segs_max - 1) * sizeof(ArtSVPSeg));
new_vp->n_segs = 0;
if (vp->n_segs == 0)
return new_vp;
active_segs = art_new (int, vp->n_segs);
cursor = art_new (int, vp->n_segs);
......@@ -989,10 +997,6 @@ art_svp_uncross (ArtSVP *vp)
n_ips_max = art_new (int, vp->n_segs);
ips = art_new (ArtPoint *, vp->n_segs);
n_segs_max = 16;
new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
(n_segs_max - 1) * sizeof(ArtSVPSeg));
new_vp->n_segs = 0;
n_points_max = art_new (int, n_segs_max);
n_active_segs = 0;
......@@ -1309,6 +1313,9 @@ art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule)
(n_segs_max - 1) * sizeof(ArtSVPSeg));
new_vp->n_segs = 0;
if (vp->n_segs == 0)
return new_vp;
winding = art_new (int, vp->n_segs);
active_segs = art_new (int, vp->n_segs);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment