summaryrefslogtreecommitdiff
path: root/source/fitz/draw-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/fitz/draw-path.c')
-rw-r--r--source/fitz/draw-path.c90
1 files changed, 55 insertions, 35 deletions
diff --git a/source/fitz/draw-path.c b/source/fitz/draw-path.c
index 09cb06db..deb17932 100644
--- a/source/fitz/draw-path.c
+++ b/source/fitz/draw-path.c
@@ -472,6 +472,48 @@ fz_add_arc(fz_context *ctx, sctx *s,
}
}
+/* FLT_TINY * FLT_TINY is approximately FLT_EPSILON */
+#define FLT_TINY 3.4e-4F
+static int find_normal_vectors(float dx, float dy, float linewidth, float *dlx, float *dly)
+{
+ if (dx == 0)
+ {
+ if (dy < FLT_TINY && dy > - FLT_TINY)
+ goto tiny;
+ else if (dy > 0)
+ *dlx = linewidth;
+ else
+ *dlx = -linewidth;
+ *dly = 0;
+ }
+ else if (dy == 0)
+ {
+ if (dx < FLT_TINY && dx > - FLT_TINY)
+ goto tiny;
+ else if (dx > 0)
+ *dly = -linewidth;
+ else
+ *dly = linewidth;
+ *dlx = 0;
+ }
+ else
+ {
+ float sq = dx * dx + dy * dy;
+ float scale;
+
+ if (sq < FLT_EPSILON)
+ goto tiny;
+ scale = linewidth / sqrtf(sq);
+ *dlx = dy * scale;
+ *dly = -dx * scale;
+ }
+ return 0;
+tiny:
+ *dlx = 0;
+ *dly = 0;
+ return 1;
+}
+
static void
fz_add_line_join(fz_context *ctx, sctx *s, float ax, float ay, float bx, float by, float cx, float cy, int join_under)
{
@@ -486,7 +528,6 @@ fz_add_line_join(fz_context *ctx, sctx *s, float ax, float ay, float bx, float b
float dmr2;
float scale;
float cross;
- float len0, len1;
int rev = 0;
dx0 = bx - ax;
@@ -506,33 +547,11 @@ fz_add_line_join(fz_context *ctx, sctx *s, float ax, float ay, float bx, float b
rev = !rev;
}
- len0 = dx0 * dx0 + dy0 * dy0;
- if (len0 < FLT_EPSILON)
- {
+ if (find_normal_vectors(dx0, dy0, linewidth, &dlx0, &dly0))
linejoin = FZ_LINEJOIN_BEVEL;
- dlx0 = 0;
- dly0 = 0;
- }
- else
- {
- scale = linewidth / sqrtf(len0);
- dlx0 = dy0 * scale;
- dly0 = -dx0 * scale;
- }
- len1 = dx1 * dx1 + dy1 * dy1;
- if (len1 < FLT_EPSILON)
- {
+ if (find_normal_vectors(dx1, dy1, linewidth, &dlx1, &dly1))
linejoin = FZ_LINEJOIN_BEVEL;
- dlx1 = 0;
- dly1 = 0;
- }
- else
- {
- scale = linewidth / sqrtf(len1);
- dlx1 = dy1 * scale;
- dly1 = -dx1 * scale;
- }
dmx = (dlx0 + dlx1) * 0.5f;
dmy = (dly0 + dly1) * 0.5f;
@@ -750,9 +769,9 @@ fz_stroke_lineto(fz_context *ctx, sctx *s, float x, float y, int from_bezier)
float oy = s->seg[s->sn-1].y;
float dx = x - ox;
float dy = y - oy;
- float scale, dlx, dly;
+ float dlx, dly;
- if (dx * dx + dy * dy < FLT_EPSILON)
+ if (find_normal_vectors(dx, dy, s->linewidth, &dlx, &dly))
{
if (s->dot == ONLY_MOVES && (s->cap == FZ_LINECAP_ROUND || s->dash_list))
s->dot = NULL_LINE;
@@ -763,10 +782,6 @@ fz_stroke_lineto(fz_context *ctx, sctx *s, float x, float y, int from_bezier)
if (s->sn == 2)
fz_add_line_join(ctx, s, s->seg[0].x, s->seg[0].y, ox, oy, x, y, s->from_bezier & from_bezier);
- scale = s->linewidth / sqrtf(dx * dx + dy * dy);
- dlx = dy * scale;
- dly = -dx * scale;
-
#if 1
if (0 && dx == 0)
{
@@ -805,10 +820,15 @@ fz_stroke_closepath(fz_context *ctx, sctx *s)
if (s->sn == 2)
{
fz_stroke_lineto(ctx, s, s->beg[0].x, s->beg[0].y, 0);
- if (s->seg[1].x == s->beg[0].x && s->seg[1].y == s->beg[0].y)
- fz_add_line_join(ctx, s, s->seg[0].x, s->seg[0].y, s->beg[0].x, s->beg[0].y, s->beg[1].x, s->beg[1].y, 0);
- else
- fz_add_line_join(ctx, s, s->seg[1].x, s->seg[1].y, s->beg[0].x, s->beg[0].y, s->beg[1].x, s->beg[1].y, 0);
+ /* fz_stroke_lineto will *normally* end up with s->seg[1] being the x,y coords passed in.
+ * As such, the following line should draw a linejoin between the closing segment of this
+ * subpath (seg[0]->seg[1]) == (seg[0]->beg[0]) and the first segment of this subpath
+ * (beg[0]->beg[1]).
+ * In cases where the line was already at an x,y infinitessimally close to s->beg[0],
+ * fz_stroke_lineto may exit without doing any processing. This leaves seg[0]->seg[1]
+ * pointing at the penultimate line segment. Thus this draws a linejoin between that
+ * penultimate segment and the end segment. This is what we want. */
+ fz_add_line_join(ctx, s, s->seg[0].x, s->seg[0].y, s->beg[0].x, s->beg[0].y, s->beg[1].x, s->beg[1].y, 0);
}
else if (s->dot == NULL_LINE)
fz_add_line_dot(ctx, s, s->beg[0].x, s->beg[0].y);