summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fitz/fitz.h1
-rw-r--r--fitz/res_path.c90
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;