summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxstroke.c')
-rw-r--r--base/gxstroke.c582
1 files changed, 342 insertions, 240 deletions
diff --git a/base/gxstroke.c b/base/gxstroke.c
index 52c15437..e99497b6 100644
--- a/base/gxstroke.c
+++ b/base/gxstroke.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2019 Artifex Software, Inc.
+/* Copyright (C) 2001-2020 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -625,10 +625,10 @@ gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
Well we could use eigenvalues of the quadratic form,
but it gives same result with a bigger calculus.
*/
- double max_rr = (xx*xx + xy*xy + yx*yx + yy*yy +
- sqrt( ((xy + yx)*(xy + yx) + (xx - yy)*(xx - yy)) *
- ((xy - yx)*(xy - yx) + (xx + yy)*(xx + yy))
- )
+ double max_rr = ((double)(xx*xx + xy*xy + yx*yx + yy*yy) +
+ sqrt((double)((xy + yx)*(xy + yx) + (xx - yy)*(xx - yy)) *
+ ((xy - yx)*(xy - yx) + (xx + yy)*(xx + yy))
+ )
)/2;
always_thin = max_rr * line_width * line_width < 0.25;
@@ -1093,12 +1093,51 @@ width_is_thin(pl_ptr plp)
if ((dx = plp->vector.x) == 0)
return any_abs(wx) < fixed_half;
- /*
- * If both horizontal and vertical widths are less than
- * 0.5, the line is thin.
+ /* For the longest time, we used to have a test here that
+ * attempted to trivially accept diagonal lines as being
+ * thin based on the components of the perpendicular
+ * width vector in device space as both being less than 0.5.
+ * Bug 702196 showed some examples where this was clearly
+ * wrong.
+ *
+ * The cause for this bug was that the 0.5 figure was wrong.
+ * For the point to be less than 1/2 a pixel perpendicular
+ * distant from the line, we'd need x^2 + y^2 < .5^2.
+ * For a 45 degree line, that'd be 2(x^2) < 1/4 = x^2 < 1/8
+ * or x < sqr(1/8). 45 degree line is the "worst case", so
+ * if both horizontal and vertical widths are less than
+ * sqr(1/8), the line is thin. sqr(1/8) = 0.35355339059.
+ * So, we should be using sqr(1/8) rather than 0.5.
+ *
+ * Fixing this did indeed produce many many progressions,
+ * but left just the odd file still showing problems.
+ *
+ * Further investigations show that those cases were due to
+ * the use of "non-uniform" scaling matrices, for example
+ * (83 0 0 51 0 0). With such matrices, it's possible for
+ * nearly horizontal lines to be thin, but nearly vertical
+ * ones to be thick (or vice versa). Having the style of
+ * line "pop" between thick and thin in a single stroke
+ * looks very noticeable.
+ *
+ * We could change the trivial optimisation below to only
+ * apply in the 'uniform' case, but that would never actually
+ * trigger (as tested on the cluster), because all such
+ * cases are caught by the "always_thin" condition in the
+ * caller.
+ *
+ * Just removing the trivial test and leaving the 'complicated'
+ * test below us would leave us vulnerable to "popping",
+ * so we disable both. In practice this makes no difference
+ * to the number of tests showing diffs in the cluster.
*/
- if (any_abs(wx) < fixed_half && any_abs(wy) < fixed_half)
- return true;
+#if 0 /* DISABLED TEST, see above */
+ {
+ /* thin_threshold = fixed sqr(1/8) - see above. */
+ const fixed thin_threshold = float2fixed(0.35355339059f);
+ if (any_abs(wx) < thin_threshold && any_abs(wy) < thin_threshold)
+ return true;
+ }
/*
* We have to do this the hard way, by actually computing the
@@ -1116,6 +1155,9 @@ width_is_thin(pl_ptr plp)
/* so we don't need to do any de-scaling for the test. */
return fabs(num) < denom * 0.5;
}
+#else
+ return false;
+#endif
}
/* Adjust the endpoints and width of a stroke segment along a specified axis */
@@ -1640,6 +1682,162 @@ wide_underjoin(pl_ptr plp, pl_ptr nplp)
}
#endif
+static int
+check_miter(const gx_line_params * pgs_lp, pl_ptr plp, pl_ptr nplp,
+ const gs_matrix * pmat, p_ptr outp, p_ptr np, p_ptr mpt,
+ bool ccw0)
+{
+ /*
+ * Check whether a miter join is appropriate.
+ * Let a, b be the angles of the two lines.
+ * We check tan(a-b) against the miter_check
+ * by using the following formula:
+ * If tan(a)=u1/v1 and tan(b)=u2/v2, then
+ * tan(a-b) = (u1*v2 - u2*v1) / (u1*u2 + v1*v2).
+ *
+ * We can do all the computations unscaled,
+ * because we're only concerned with ratios.
+ * However, if we have a non-uniform coordinate
+ * system (indicated by pmat != 0), we must do the
+ * computations in user space.
+ */
+ float check;
+ double u1, v1, u2, v2;
+ double num, denom;
+ int code;
+
+ /*
+ * Don't bother with the miter check if the two
+ * points to be joined are very close together,
+ * namely, in the same square half-pixel.
+ */
+ if (fixed2long(outp->x << 1) == fixed2long(np->x << 1) &&
+ fixed2long(outp->y << 1) == fixed2long(np->y << 1))
+ return 1;
+
+ check = pgs_lp->miter_check;
+ u1 = plp->vector.y, v1 = plp->vector.x;
+ u2 = -nplp->vector.y, v2 = -nplp->vector.x;
+
+ if (pmat) {
+ gs_point pt;
+
+ code = gs_distance_transform_inverse(v1, u1, pmat, &pt);
+ if (code < 0)
+ return code;
+ v1 = pt.x, u1 = pt.y;
+ code = gs_distance_transform_inverse(v2, u2, pmat, &pt);
+ if (code < 0)
+ return code;
+ v2 = pt.x, u2 = pt.y;
+ /*
+ * We need to recompute ccw according to the
+ * relative positions of the lines in user space.
+ * We repeat the computation described above,
+ * using the cdelta values instead of the widths.
+ * Because the definition of ccw above is inverted
+ * from the intuitive one (for historical reasons),
+ * we actually have to do the test backwards.
+ */
+ ccw0 = v1 * u2 < v2 * u1;
+#if defined(DEBUG) && !defined(GS_THREADSAFE)
+ {
+ double a1 = atan2(u1, v1), a2 = atan2(u2, v2), dif = a1 - a2;
+
+ if (dif < 0)
+ dif += 2 * M_PI;
+ else if (dif >= 2 * M_PI)
+ dif -= 2 * M_PI;
+ if (dif != 0 && (dif < M_PI) != ccw0)
+ lprintf8("ccw wrong: tan(a1=%g)=%g/%g, tan(a2=%g)=%g,%g, dif=%g, ccw0=%d\n",
+ a1, u1, v1, a2, u2, v2, dif, ccw0);
+ }
+#endif
+ }
+ num = u1 * v2 - u2 * v1;
+ denom = u1 * u2 + v1 * v2;
+ /*
+ * We will want either tan(a-b) or tan(b-a)
+ * depending on the orientations of the lines.
+ * Fortunately we know the relative orientations already.
+ */
+ if (!ccw0) /* have plp - nplp, want vice versa */
+ num = -num;
+#if defined(DEBUG) && !defined(GS_THREADSAFE)
+ if (gs_debug_c('O')) {
+ dlprintf4("[o]Miter check: u1/v1=%f/%f, u2/v2=%f/%f,\n",
+ u1, v1, u2, v2);
+ dlprintf3(" num=%f, denom=%f, check=%f\n",
+ num, denom, check);
+ }
+#endif
+ /*
+ * If we define T = num / denom, then we want to use
+ * a miter join iff arctan(T) >= arctan(check).
+ * We know that both of these angles are in the 1st
+ * or 2nd quadrant, and since arctan is monotonic
+ * within each quadrant, we can do the comparisons
+ * on T and check directly, taking signs into account
+ * as follows:
+ * sign(T) sign(check) atan(T) >= atan(check)
+ * ------- ----------- ----------------------
+ * + + T >= check
+ * - + true
+ * + - false
+ * - - T >= check
+ */
+ if (num == 0 && denom == 0)
+ return_error(gs_error_unregistered); /* Must not happen. */
+ if (denom < 0)
+ num = -num, denom = -denom;
+ /* Now denom >= 0, so sign(num) = sign(T). */
+ if (check > 0 ?
+ (num < 0 || num >= denom * check) :
+ (num < 0 && num >= denom * check)
+ ) {
+ /* OK to use a miter join. */
+ gs_fixed_point dirn1, dirn2;
+
+ dirn1.x = plp->e.cdelta.x;
+ dirn1.y = plp->e.cdelta.y;
+ /* If this direction is small enough that we might have
+ * underflowed and the vector record is suitable for us
+ * to use to calculate a better one, then do so. */
+ if ((abs(dirn1.x) + abs(dirn1.y) < 16) &&
+ ((plp->vector.x != 0) || (plp->vector.y != 0)))
+ {
+ float scale = 65536.0;
+ if (abs(plp->vector.x) > abs(plp->vector.y))
+ scale /= abs(plp->vector.x);
+ else
+ scale /= abs(plp->vector.y);
+ dirn1.x = (fixed)(plp->vector.x*scale);
+ dirn1.y = (fixed)(plp->vector.y*scale);
+ }
+ dirn2.x = nplp->o.cdelta.x;
+ dirn2.y = nplp->o.cdelta.y;
+ /* If this direction is small enough that we might have
+ * underflowed and the vector record is suitable for us
+ * to use to calculate a better one, then do so. */
+ if ((abs(dirn2.x) + abs(dirn2.y) < 16) &&
+ ((nplp->vector.x != 0) || (nplp->vector.y != 0)))
+ {
+ float scale = 65536.0;
+ if (abs(nplp->vector.x) > abs(nplp->vector.y))
+ scale /= abs(nplp->vector.x);
+ else
+ scale /= abs(nplp->vector.y);
+ dirn2.x = (fixed)(-nplp->vector.x*scale);
+ dirn2.y = (fixed)(-nplp->vector.y*scale);
+ }
+ if_debug0('O', " ... passes.\n");
+ /* Compute the intersection of the extended edge lines. */
+ if (line_intersect(outp, &dirn1, np, &dirn2, mpt) == 0)
+ return 0;
+ }
+ return 1;
+}
+
/* Add a segment to the path.
* This works by crafting 2 paths, one for each edge, that will later be
* merged together. */
@@ -1660,6 +1858,14 @@ stroke_add_fast(gx_path * ppath, gx_path * rpath, bool ensure_closed, int first,
bool moveto_first = false;
bool rmoveto_first = false;
gs_line_cap start_cap, end_cap;
+ const gs_matrix *pmat = (uniform ? (const gs_matrix *)NULL : &ctm_only(pgs));
+ enum {
+ joinsense_cap = 0,
+ joinsense_cw = 1,
+ joinsense_ccw = 2,
+ joinsense_over = 4,
+ joinsense_under = 8,
+ } joinsense = joinsense_cap;
if (plp->thin) {
/* We didn't set up the endpoint parameters before, */
@@ -1702,6 +1908,100 @@ stroke_add_fast(gx_path * ppath, gx_path * rpath, bool ensure_closed, int first,
ASSIGN_POINT(&rpoints[nrpoints], plp->e.ce);
npoints++;
nrpoints++;
+
+ if (nplp != NULL && !nplp->thin) {
+ /* We need to do a join. What sense is it it? */
+ double l, r;
+
+ l = (double)(plp->width.x) /* x1 */ * (nplp->width.y) /* y2 */;
+ r = (double)(nplp->width.x) /* x2 */ * (plp->width.y) /* y1 */;
+
+ if ((l == r) && (join == gs_join_round))
+ joinsense = joinsense_cap;
+ else if ((l > r) ^ reflected)
+ joinsense = joinsense_ccw | joinsense_over | joinsense_under;
+ else
+ joinsense = joinsense_cw | joinsense_over | joinsense_under;
+
+ if (joinsense != joinsense_cap && join == gs_join_miter) {
+ /* We need to do a miter line join. Miters are 'special'
+ * in that we'd like to do them by adjusting the existing
+ * points, rather than adding new ones. */
+ gs_fixed_point mpt;
+ if (joinsense & joinsense_ccw) {
+ /* Underjoin (in reverse path):
+ * A = plp->o.co, B = plp->e.ce, C = nplp->o.co, D = nplp->e.ce */
+ double xa = plp->o.co.x, ya = plp->o.co.y;
+ double xb = plp->e.ce.x, yb = plp->e.ce.y;
+ double xc = nplp->o.co.x, yc = nplp->o.co.y;
+ double xd = nplp->e.ce.x, yd = nplp->e.ce.y;
+ double xab = xa-xb, xac = xa-xc, xcd = xc-xd;
+ double yab = ya-yb, yac = ya-yc, ycd = yc-yd;
+ double t_num = xac * ycd - yac * xcd;
+ double t_den = xab * ycd - yab * xcd;
+ code = check_miter(pgs_lp, plp, nplp, pmat, &plp->e.co,
+ &nplp->o.ce, &mpt, true);
+ if (code < 0)
+ return code;
+ if (code == 0) {
+ points[npoints-1].x = mpt.x;
+ points[npoints-1].y = mpt.y;
+ if (ensure_closed) {
+ points[npoints].x = nplp->o.ce.x;
+ points[npoints].y = nplp->o.ce.y;
+ npoints++;
+ }
+ joinsense &= ~joinsense_over;
+ } else
+ join = gs_join_bevel;
+ if (t_den != 0 &&
+ ((t_num >= 0 && t_num <= t_den) ||
+ (t_num <= 0 && t_num >= t_den))) {
+ double x = xa - xab * t_num / t_den;
+ double y = ya - yab * t_num / t_den;
+ rpoints[nrpoints-1].x = (fixed)x;
+ rpoints[nrpoints-1].y = (fixed)y;
+ joinsense &= ~joinsense_under;
+ }
+ } else {
+ /* Underjoin (in fwd path):
+ * A = plp->o.ce, B = plp->e.co, C = nplp->o.ce, D = nplp->e.co */
+ double xa = plp->o.ce.x, ya = plp->o.ce.y;
+ double xb = plp->e.co.x, yb = plp->e.co.y;
+ double xc = nplp->o.ce.x, yc = nplp->o.ce.y;
+ double xd = nplp->e.co.x, yd = nplp->e.co.y;
+ double xab = xa-xb, xac = xa-xc, xcd = xc-xd;
+ double yab = ya-yb, yac = ya-yc, ycd = yc-yd;
+ double t_num = xac * ycd - yac * xcd;
+ double t_den = xab * ycd - yab * xcd;
+ code = check_miter(pgs_lp, plp, nplp, pmat, &plp->e.ce,
+ &nplp->o.co, &mpt, false);
+ if (code < 0)
+ return code;
+ if (code == 0) {
+ rpoints[nrpoints-1].x = mpt.x;
+ rpoints[nrpoints-1].y = mpt.y;
+ if (ensure_closed) {
+ rpoints[nrpoints].x = nplp->o.co.x;
+ rpoints[nrpoints].y = nplp->o.co.y;
+ nrpoints++;
+ }
+ joinsense &= ~joinsense_over;
+ } else
+ join = gs_join_bevel;
+ if (t_den != 0 &&
+ ((t_num >= 0 && t_num <= t_den) ||
+ (t_num <= 0 && t_num >= t_den))) {
+ double x = xa - xab * t_num / t_den;
+ double y = ya - yab * t_num / t_den;
+ points[npoints-1].x = (fixed)x;
+ points[npoints-1].y = (fixed)y;
+ joinsense &= ~joinsense_under;
+ }
+ }
+ }
+ }
+
if ((code = add_points(ppath, points, npoints, moveto_first)) < 0)
return code;
if ((code = add_points(rpath, rpoints, nrpoints, rmoveto_first)) < 0)
@@ -1719,28 +2019,22 @@ stroke_add_fast(gx_path * ppath, gx_path * rpath, bool ensure_closed, int first,
} else if (nplp->thin) { /* no join */
code = cap_points(gs_cap_butt, &plp->e, points);
npoints = code;
- } else {
- /* We need to do a join */
- double l, r;
-
- l = (double)(plp->width.x) /* x1 */ * (nplp->width.y) /* y2 */;
- r = (double)(nplp->width.x) /* x2 */ * (plp->width.y) /* y1 */;
-
- if ((l == r) && (join == gs_join_round)) {
- /* Do a cap */
- code = add_pie_cap(ppath, &plp->e);
- if (code >= 0) {
- /* If the next line is in the opposite direction as the current one
- * we want to leave the point on the same side as it was
- * originally. This is required for paths that come to a stop
- * and then reverse themselves, but may produce more complexity
- * than we'd really like at the ends of smooth beziers. */
- if ((double)(plp->width.x) * nplp->width.x + (double)plp->width.y * nplp->width.y >= 0)
- code = gx_path_add_line(ppath, plp->e.co.x, plp->e.co.y);
- }
- } else if ((l > r) ^ reflected) {
- /* CCW rotation. Join in the forward path. "Underjoin" in the
- * reverse path. */
+ } else if (joinsense == joinsense_cap) {
+ /* Do a cap */
+ code = add_pie_cap(ppath, &plp->e);
+ if (code >= 0) {
+ /* If the next line is in the opposite direction as the current one
+ * we want to leave the point on the same side as it was
+ * originally. This is required for paths that come to a stop
+ * and then reverse themselves, but may produce more complexity
+ * than we'd really like at the ends of smooth beziers. */
+ if ((double)(plp->width.x) * nplp->width.x + (double)plp->width.y * nplp->width.y >= 0)
+ code = gx_path_add_line(ppath, plp->e.co.x, plp->e.co.y);
+ }
+ } else if (joinsense & joinsense_ccw) {
+ /* CCW rotation. Join in the forward path. "Underjoin" in the
+ * reverse path. */
+ if (joinsense & joinsense_over) {
/* RJW: Ideally we should include the "|| flags" clause in
* the following condition. This forces all joins between
* line segments generated from arcs to be round. This would
@@ -1750,14 +2044,13 @@ stroke_add_fast(gx_path * ppath, gx_path * rpath, bool ensure_closed, int first,
code = add_pie_join_fast_ccw(ppath, plp, nplp, reflected);
} else { /* non-round join */
code = line_join_points_fast_ccw(pgs_lp, plp, nplp,
- points,
- (uniform ? (gs_matrix *) 0 :
- &ctm_only(pgs)),
- join);
+ points, pmat, join);
npoints = code;
}
if (code < 0)
return code;
+ }
+ if (joinsense & joinsense_under) {
/* The underjoin */
#ifndef SLOWER_BUT_MORE_ACCURATE_STROKING
if ((flags & (nf_some_from_arc | nf_prev_some_from_arc)) == 0) {
@@ -1799,9 +2092,11 @@ stroke_add_fast(gx_path * ppath, gx_path * rpath, bool ensure_closed, int first,
}
#endif
code = gx_path_add_line(rpath, nplp->o.co.x, nplp->o.co.y);
- } else {
- /* CW rotation. Join in the reverse path. "Underjoin" in the
- * forward path. */
+ }
+ } else if (joinsense & joinsense) {
+ /* CW rotation. Join in the reverse path. "Underjoin" in the
+ * forward path. */
+ if (joinsense & joinsense_over) {
/* RJW: Ideally we should include the "|| flags" clause in
* the following condition. This forces all joins between
* line segments generated from arcs to be round. This would
@@ -1811,17 +2106,17 @@ stroke_add_fast(gx_path * ppath, gx_path * rpath, bool ensure_closed, int first,
code = add_pie_join_fast_cw(rpath, plp, nplp, reflected);
} else { /* non-round join */
code = line_join_points_fast_cw(pgs_lp, plp, nplp,
- rpoints,
- (uniform ? (gs_matrix *) 0 :
- &ctm_only(pgs)),
- join);
+ rpoints, pmat, join);
nrpoints = code;
}
if (code < 0)
return code;
+ }
+ if (joinsense & joinsense_under) {
/* The underjoin */
#ifndef SLOWER_BUT_MORE_ACCURATE_STROKING
- if ((flags & (nf_some_from_arc | nf_prev_some_from_arc)) == 0) {
+ if ((flags & (nf_some_from_arc | nf_prev_some_from_arc)) == 0 &&
+ join != gs_join_miter) {
/* RJW: This is an approximation. We ought to draw a line
* back to nplp->o.p, and then independently fill any exposed
* region under the curve with a round join. Sadly, that's
@@ -2047,150 +2342,6 @@ add_points(gx_path * ppath, const gs_fixed_point * points, int npoints,
/* ---------------- Join computation ---------------- */
-static int
-check_miter(const gx_line_params * pgs_lp, pl_ptr plp, pl_ptr nplp,
- const gs_matrix * pmat, p_ptr outp, p_ptr np, p_ptr mpt,
- bool ccw0)
-{
- /*
- * Check whether a miter join is appropriate.
- * Let a, b be the angles of the two lines.
- * We check tan(a-b) against the miter_check
- * by using the following formula:
- * If tan(a)=u1/v1 and tan(b)=u2/v2, then
- * tan(a-b) = (u1*v2 - u2*v1) / (u1*u2 + v1*v2).
- *
- * We can do all the computations unscaled,
- * because we're only concerned with ratios.
- * However, if we have a non-uniform coordinate
- * system (indicated by pmat != 0), we must do the
- * computations in user space.
- */
- float check = pgs_lp->miter_check;
- double u1 = plp->vector.y, v1 = plp->vector.x;
- double u2 = -nplp->vector.y, v2 = -nplp->vector.x;
- double num, denom;
- int code;
-
- if (pmat) {
- gs_point pt;
-
- code = gs_distance_transform_inverse(v1, u1, pmat, &pt);
- if (code < 0)
- return code;
- v1 = pt.x, u1 = pt.y;
- code = gs_distance_transform_inverse(v2, u2, pmat, &pt);
- if (code < 0)
- return code;
- v2 = pt.x, u2 = pt.y;
- /*
- * We need to recompute ccw according to the
- * relative positions of the lines in user space.
- * We repeat the computation described above,
- * using the cdelta values instead of the widths.
- * Because the definition of ccw above is inverted
- * from the intuitive one (for historical reasons),
- * we actually have to do the test backwards.
- */
- ccw0 = v1 * u2 < v2 * u1;
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
- {
- double a1 = atan2(u1, v1), a2 = atan2(u2, v2), dif = a1 - a2;
-
- if (dif < 0)
- dif += 2 * M_PI;
- else if (dif >= 2 * M_PI)
- dif -= 2 * M_PI;
- if (dif != 0 && (dif < M_PI) != ccw0)
- lprintf8("ccw wrong: tan(a1=%g)=%g/%g, tan(a2=%g)=%g,%g, dif=%g, ccw0=%d\n",
- a1, u1, v1, a2, u2, v2, dif, ccw0);
- }
-#endif
- }
- num = u1 * v2 - u2 * v1;
- denom = u1 * u2 + v1 * v2;
- /*
- * We will want either tan(a-b) or tan(b-a)
- * depending on the orientations of the lines.
- * Fortunately we know the relative orientations already.
- */
- if (!ccw0) /* have plp - nplp, want vice versa */
- num = -num;
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
- if (gs_debug_c('O')) {
- dlprintf4("[o]Miter check: u1/v1=%f/%f, u2/v2=%f/%f,\n",
- u1, v1, u2, v2);
- dlprintf3(" num=%f, denom=%f, check=%f\n",
- num, denom, check);
- }
-#endif
- /*
- * If we define T = num / denom, then we want to use
- * a miter join iff arctan(T) >= arctan(check).
- * We know that both of these angles are in the 1st
- * or 2nd quadrant, and since arctan is monotonic
- * within each quadrant, we can do the comparisons
- * on T and check directly, taking signs into account
- * as follows:
- * sign(T) sign(check) atan(T) >= atan(check)
- * ------- ----------- ----------------------
- * + + T >= check
- * - + true
- * + - false
- * - - T >= check
- */
- if (num == 0 && denom == 0)
- return_error(gs_error_unregistered); /* Must not happen. */
- if (denom < 0)
- num = -num, denom = -denom;
- /* Now denom >= 0, so sign(num) = sign(T). */
- if (check > 0 ?
- (num < 0 || num >= denom * check) :
- (num < 0 && num >= denom * check)
- ) {
- /* OK to use a miter join. */
- gs_fixed_point dirn1, dirn2;
-
- dirn1.x = plp->e.cdelta.x;
- dirn1.y = plp->e.cdelta.y;
- /* If this direction is small enough that we might have
- * underflowed and the vector record is suitable for us
- * to use to calculate a better one, then do so. */
- if ((abs(dirn1.x) + abs(dirn1.y) < 16) &&
- ((plp->vector.x != 0) || (plp->vector.y != 0)))
- {
- float scale = 65536.0;
- if (abs(plp->vector.x) > abs(plp->vector.y))
- scale /= abs(plp->vector.x);
- else
- scale /= abs(plp->vector.y);
- dirn1.x = (fixed)(plp->vector.x*scale);
- dirn1.y = (fixed)(plp->vector.y*scale);
- }
- dirn2.x = nplp->o.cdelta.x;
- dirn2.y = nplp->o.cdelta.y;
- /* If this direction is small enough that we might have
- * underflowed and the vector record is suitable for us
- * to use to calculate a better one, then do so. */
- if ((abs(dirn2.x) + abs(dirn2.y) < 16) &&
- ((nplp->vector.x != 0) || (nplp->vector.y != 0)))
- {
- float scale = 65536.0;
- if (abs(nplp->vector.x) > abs(nplp->vector.y))
- scale /= abs(nplp->vector.x);
- else
- scale /= abs(nplp->vector.y);
- dirn2.x = (fixed)(-nplp->vector.x*scale);
- dirn2.y = (fixed)(-nplp->vector.y*scale);
- }
- if_debug0('O', " ... passes.\n");
- /* Compute the intersection of the extended edge lines. */
- if (line_intersect(outp, &dirn1, np, &dirn2, mpt) == 0)
- return 0;
- }
- return 1;
-}
-
/* Compute the points for a bevel, miter, or triangle join. */
/* Treat no join the same as a bevel join. */
/* If pmat != 0, we must inverse-transform the distances for */
@@ -2238,6 +2389,7 @@ line_join_points(const gx_line_params * pgs_lp, pl_ptr plp, pl_ptr nplp,
bool ccw0 = ccw;
p_ptr outp, np;
int code;
+ gs_fixed_point mpt;
ccw ^= reflected;
@@ -2280,21 +2432,11 @@ line_join_points(const gx_line_params * pgs_lp, pl_ptr plp, pl_ptr nplp,
}
return 5;
}
- /*
- * Don't bother with the miter check if the two
- * points to be joined are very close together,
- * namely, in the same square half-pixel.
- */
if (join == gs_join_miter &&
- !(fixed2long(outp->x << 1) == fixed2long(np->x << 1) &&
- fixed2long(outp->y << 1) == fixed2long(np->y << 1))
- ) {
- gs_fixed_point mpt;
- code = check_miter(pgs_lp, plp, nplp, pmat, outp, np, &mpt, ccw0);
+ (code = check_miter(pgs_lp, plp, nplp, pmat, outp, np, &mpt, ccw0)) <= 0) {
if (code < 0)
return code;
- if (code == 0)
- ASSIGN_POINT(outp, mpt);
+ ASSIGN_POINT(outp, mpt);
}
return 4;
}
@@ -2324,26 +2466,6 @@ line_join_points_fast_cw(const gx_line_params * pgs_lp,
/* Set up for a Bevel join */
ASSIGN_POINT(&rjoin_points[0], nplp->o.co);
- /*
- * Don't bother with the miter check if the two
- * points to be joined are very close together,
- * namely, in the same square half-pixel.
- */
- if (join == gs_join_miter &&
- !(fixed2long(plp->e.ce.x << 1) == fixed2long(nplp->o.co.x << 1) &&
- fixed2long(plp->e.ce.y << 1) == fixed2long(nplp->o.co.y << 1))
- ) {
- gs_fixed_point mpt;
- int code = check_miter(pgs_lp, plp, nplp, pmat, &plp->e.ce,
- &nplp->o.co, &mpt, false);
- if (code < 0)
- return code;
- if (code == 0) {
- ASSIGN_POINT(&rjoin_points[0], mpt);
- ASSIGN_POINT(&rjoin_points[1], nplp->o.co);
- return 2;
- }
- }
return 1;
}
@@ -2371,26 +2493,6 @@ line_join_points_fast_ccw(const gx_line_params * pgs_lp,
/* Set up for a Bevel join */
ASSIGN_POINT(&join_points[0], nplp->o.ce);
- /*
- * Don't bother with the miter check if the two
- * points to be joined are very close together,
- * namely, in the same square half-pixel.
- */
- if (join == gs_join_miter &&
- !(fixed2long(plp->e.co.x << 1) == fixed2long(nplp->o.ce.x << 1) &&
- fixed2long(plp->e.co.y << 1) == fixed2long(nplp->o.ce.y << 1))
- ) {
- gs_fixed_point mpt;
- int code = check_miter(pgs_lp, plp, nplp, pmat, &plp->e.co,
- &nplp->o.ce, &mpt, true);
- if (code < 0)
- return code;
- if (code == 0) {
- ASSIGN_POINT(&join_points[0], mpt);
- ASSIGN_POINT(&join_points[1], nplp->o.ce);
- return 2;
- }
- }
return 1;
}
/* ---------------- Cap computations ---------------- */