diff options
-rw-r--r-- | fitz/fitz.h | 1 | ||||
-rw-r--r-- | fitz/res_path.c | 90 |
2 files changed, 84 insertions, 7 deletions
diff --git a/fitz/fitz.h b/fitz/fitz.h index 82a16ecf..769111e3 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1130,6 +1130,7 @@ struct fz_path_s { int len, cap; fz_path_item *items; + int last; }; struct fz_stroke_state_s diff --git a/fitz/res_path.c b/fitz/res_path.c index a062f813..64452a28 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -10,6 +10,7 @@ fz_new_path(fz_context *ctx) path->len = 0; path->cap = 0; path->items = NULL; + path->last = -1; return path; } @@ -51,16 +52,25 @@ grow_path(fz_context *ctx, fz_path *path, int n) { int newcap = path->cap; if (path->len + n <= path->cap) + { + path->last = path->len; return; + } while (path->len + n > newcap) newcap = newcap + 36; path->items = fz_resize_array(ctx, path->items, newcap, sizeof(fz_path_item)); path->cap = newcap; + path->last = path->len; } void fz_moveto(fz_context *ctx, fz_path *path, float x, float y) { + if (path->last >= 0 && path->items[path->last].k == FZ_MOVETO) + { + /* No point in having MOVETO then MOVETO */ + path->len = path->last; + } grow_path(ctx, path, 3); path->items[path->len++].k = FZ_MOVETO; path->items[path->len++].v = x; @@ -70,11 +80,26 @@ fz_moveto(fz_context *ctx, fz_path *path, float x, float y) void fz_lineto(fz_context *ctx, fz_path *path, float x, float y) { - if (path->len == 0) + float x0, y0; + + if (path->last < 0) { fz_warn(ctx, "lineto with no current point"); return; } + if (path->items[path->last].k == FZ_CLOSE_PATH) + { + x0 = path->items[path->last-2].v; + y0 = path->items[path->last-1].v; + } + else + { + x0 = path->items[path->len-2].v; + y0 = path->items[path->len-1].v; + } + /* Anything other than MoveTo followed by LineTo the same place is a nop */ + if (path->items[path->last].k != FZ_MOVETO && x0 == x && y0 == y) + return; grow_path(ctx, path, 3); path->items[path->len++].k = FZ_LINETO; path->items[path->len++].v = x; @@ -87,11 +112,50 @@ fz_curveto(fz_context *ctx, fz_path *path, float x2, float y2, float x3, float y3) { - if (path->len == 0) + float x0, y0; + + if (path->last < 0) { fz_warn(ctx, "curveto with no current point"); return; } + if (path->items[path->last].k == FZ_CLOSE_PATH) + { + x0 = path->items[path->last-2].v; + y0 = path->items[path->last-1].v; + } + else + { + x0 = path->items[path->len-2].v; + y0 = path->items[path->len-1].v; + } + + /* Check for degenerate cases: */ + if (x0 == x1 && y0 == y1) + { + if (x2 == x3 && y2 == y3) + { + /* If (x1,y1)==(x2,y2) and prev wasn't a moveto, then skip */ + if (x1 == x2 && y1 == y2 && path->items[path->last].k != FZ_MOVETO) + return; + /* Otherwise a line will suffice */ + fz_lineto(ctx, path, x3, y3); + return; + } + if (x1 == x2 && y1 == y2) + { + /* A line will suffice */ + fz_lineto(ctx, path, x3, y3); + return; + } + } + else if (x1 == x2 && y1 == y2 && x2 == x3 && y2 == y3) + { + /* A line will suffice */ + fz_lineto(ctx, path, x3, y3); + return; + } + grow_path(ctx, path, 7); path->items[path->len++].k = FZ_CURVETO; path->items[path->len++].v = x1; @@ -106,13 +170,21 @@ void fz_curvetov(fz_context *ctx, fz_path *path, float x2, float y2, float x3, float y3) { float x1, y1; - if (path->len == 0) + if (path->last < 0) { fz_warn(ctx, "curvetov with no current point"); return; } - x1 = path->items[path->len-2].v; - y1 = path->items[path->len-1].v; + if (path->items[path->last].k == FZ_CLOSE_PATH) + { + x1 = path->items[path->last-2].v; + y1 = path->items[path->last-1].v; + } + else + { + x1 = path->items[path->len-2].v; + y1 = path->items[path->len-1].v; + } fz_curveto(ctx, path, x1, y1, x2, y2, x3, y3); } @@ -125,11 +197,14 @@ fz_curvetoy(fz_context *ctx, fz_path *path, float x1, float y1, float x3, float void fz_closepath(fz_context *ctx, fz_path *path) { - if (path->len == 0) + if (path->last < 0) { fz_warn(ctx, "closepath with no current point"); return; } + /* CLOSE following a CLOSE is a NOP */ + if (path->items[path->last].k == FZ_CLOSE_PATH) + return; grow_path(ctx, path, 1); path->items[path->len++].k = FZ_CLOSE_PATH; } @@ -193,7 +268,8 @@ fz_bound_path(fz_path *path, fz_stroke_state *stroke, fz_matrix ctm) if (expand == 0) expand = 1.0f; expand *= fz_matrix_max_expansion(ctm); - expand *= stroke->miterlimit; + if (stroke->miterlimit > 1) + expand *= stroke->miterlimit; r.x0 -= expand; r.y0 -= expand; r.x1 += expand; |