summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2011-04-11 18:16:50 +0200
committerTor Andersson <tor.andersson@artifex.com>2011-04-11 18:16:50 +0200
commitc6934bd8de9d593ec51f60b7c0db9f8a2125352e (patch)
treef964a662ebe3ad5e79cd55215eedc7fd4eb05434
parent6d2ca771127fb9186372566e5671c79c354b04b9 (diff)
downloadmupdf-c6934bd8de9d593ec51f60b7c0db9f8a2125352e.tar.xz
Add triangle caps; separate start, dash and end cap styles for XPS.
-rw-r--r--draw/draw_path.c77
-rw-r--r--fitz/dev_trace.c2
-rw-r--r--fitz/fitz.h2
-rw-r--r--fitz/res_font.c2
-rw-r--r--pdf/pdf_interpret.c18
-rw-r--r--xps/xps_path.c8
6 files changed, 66 insertions, 43 deletions
diff --git a/draw/draw_path.c b/draw/draw_path.c
index 988f4d23..45731c7c 100644
--- a/draw/draw_path.c
+++ b/draw/draw_path.c
@@ -2,7 +2,7 @@
#define MAX_DEPTH 8
-enum { BUTT = 0, ROUND = 1, SQUARE = 2, MITER = 0, BEVEL = 2 };
+enum { BUTT = 0, ROUND = 1, SQUARE = 2, TRIANGLE = 3, MITER = 0, BEVEL = 2 };
static void
line(fz_gel *gel, fz_matrix *ctm, float x0, float y0, float x1, float y1)
@@ -130,7 +130,6 @@ struct sctx
fz_matrix *ctm;
float flatness;
- int linecap;
int linejoin;
float linewidth;
float miterlimit;
@@ -142,7 +141,7 @@ struct sctx
float *dash_list;
float dash_phase;
int dash_len;
- int toggle;
+ int toggle, cap;
int offset;
float phase;
fz_point cur;
@@ -303,11 +302,10 @@ fz_add_line_join(struct sctx *s, fz_point a, fz_point b, fz_point c)
}
static void
-fz_add_line_cap(struct sctx *s, fz_point a, fz_point b)
+fz_add_line_cap(struct sctx *s, fz_point a, fz_point b, int linecap)
{
float flatness = s->flatness;
float linewidth = s->linewidth;
- int linecap = s->linecap;
float dx = b.x - a.x;
float dy = b.y - a.y;
@@ -342,16 +340,20 @@ fz_add_line_cap(struct sctx *s, fz_point a, fz_point b)
if (linecap == SQUARE)
{
fz_add_line(s, b.x - dlx, b.y - dly,
- b.x - dlx - dly,
- b.y - dly + dlx);
- fz_add_line(s, b.x - dlx - dly,
- b.y - dly + dlx,
- b.x + dlx - dly,
- b.y + dly + dlx);
- fz_add_line(s, b.x + dlx - dly,
- b.y + dly + dlx,
+ b.x - dlx - dly, b.y - dly + dlx);
+ fz_add_line(s, b.x - dlx - dly, b.y - dly + dlx,
+ b.x + dlx - dly, b.y + dly + dlx);
+ fz_add_line(s, b.x + dlx - dly, b.y + dly + dlx,
b.x + dlx, b.y + dly);
}
+
+ if (linecap == TRIANGLE)
+ {
+ float mx = -dly;
+ float my = dlx;
+ fz_add_line(s, b.x - dlx, b.y - dly, b.x + mx, b.y + my);
+ fz_add_line(s, b.x + mx, b.y + my, b.x + dlx, b.y + dly);
+ }
}
static void
@@ -380,12 +382,12 @@ fz_add_line_dot(struct sctx *s, fz_point a)
}
static void
-fz_stroke_flush(struct sctx *s)
+fz_stroke_flush(struct sctx *s, int start_cap, int end_cap)
{
if (s->sn == 2)
{
- fz_add_line_cap(s, s->beg[1], s->beg[0]);
- fz_add_line_cap(s, s->seg[0], s->seg[1]);
+ fz_add_line_cap(s, s->beg[1], s->beg[0], start_cap);
+ fz_add_line_cap(s, s->seg[0], s->seg[1], end_cap);
}
else if (s->dot)
{
@@ -396,7 +398,6 @@ fz_stroke_flush(struct sctx *s)
static void
fz_stroke_moveto(struct sctx *s, fz_point cur)
{
- fz_stroke_flush(s);
s->seg[0] = cur;
s->beg[0] = cur;
s->sn = 1;
@@ -521,7 +522,6 @@ fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_m
s.ctm = &ctm;
s.flatness = flatness;
- s.linecap = stroke->linecap;
s.linejoin = stroke->linejoin;
s.linewidth = linewidth * 0.5f; /* hairlines use a different value from the path value */
s.miterlimit = stroke->miterlimit;
@@ -546,6 +546,7 @@ fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_m
case FZ_MOVETO:
p1.x = path->items[i++].v;
p1.y = path->items[i++].v;
+ fz_stroke_flush(&s, stroke->start_cap, stroke->end_cap);
fz_stroke_moveto(&s, p1);
p0 = p1;
break;
@@ -574,11 +575,11 @@ fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_m
}
}
- fz_stroke_flush(&s);
+ fz_stroke_flush(&s, stroke->start_cap, stroke->end_cap);
}
static void
-fz_dash_moveto(struct sctx *s, fz_point a)
+fz_dash_moveto(struct sctx *s, fz_point a, int start_cap, int end_cap)
{
s->toggle = 1;
s->offset = 0;
@@ -596,11 +597,15 @@ fz_dash_moveto(struct sctx *s, fz_point a)
s->cur = a;
if (s->toggle)
+ {
+ fz_stroke_flush(s, s->cap, end_cap);
+ s->cap = start_cap;
fz_stroke_moveto(s, a);
+ }
}
static void
-fz_dash_lineto(struct sctx *s, fz_point b)
+fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap)
{
float dx, dy;
float total, used, ratio;
@@ -621,9 +626,15 @@ fz_dash_lineto(struct sctx *s, fz_point b)
m.y = a.y + ratio * dy;
if (s->toggle)
+ {
fz_stroke_lineto(s, m);
+ }
else
+ {
+ fz_stroke_flush(s, s->cap, dash_cap);
+ s->cap = dash_cap;
fz_stroke_moveto(s, m);
+ }
s->toggle = !s->toggle;
s->phase = 0;
@@ -637,7 +648,9 @@ fz_dash_lineto(struct sctx *s, fz_point b)
s->cur = b;
if (s->toggle)
+ {
fz_stroke_lineto(s, b);
+ }
}
static void
@@ -645,7 +658,8 @@ fz_dash_bezier(struct sctx *s,
float xa, float ya,
float xb, float yb,
float xc, float yc,
- float xd, float yd, int depth)
+ float xd, float yd, int depth,
+ int dash_cap)
{
float dmax;
float xab, yab;
@@ -665,7 +679,7 @@ fz_dash_bezier(struct sctx *s,
fz_point p;
p.x = xd;
p.y = yd;
- fz_dash_lineto(s, p);
+ fz_dash_lineto(s, p, dash_cap);
return;
}
@@ -693,8 +707,8 @@ fz_dash_bezier(struct sctx *s,
xabcd *= 0.125f; yabcd *= 0.125f;
- fz_dash_bezier(s, xa, ya, xab, yab, xabc, yabc, xabcd, yabcd, depth + 1);
- fz_dash_bezier(s, xabcd, yabcd, xbcd, ybcd, xcd, ycd, xd, yd, depth + 1);
+ fz_dash_bezier(s, xa, ya, xab, yab, xabc, yabc, xabcd, yabcd, depth + 1, dash_cap);
+ fz_dash_bezier(s, xabcd, yabcd, xbcd, ybcd, xcd, ycd, xd, yd, depth + 1, dash_cap);
}
void
@@ -709,7 +723,6 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat
s.ctm = &ctm;
s.flatness = flatness;
- s.linecap = stroke->linecap;
s.linejoin = stroke->linejoin;
s.linewidth = linewidth * 0.5f;
s.miterlimit = stroke->miterlimit;
@@ -724,6 +737,8 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat
s.offset = 0;
s.phase = 0;
+ s.cap = stroke->start_cap;
+
if (path->len > 0 && path->items[0].k != FZ_MOVETO)
{
fz_warn("assert: path must begin with moveto");
@@ -749,14 +764,14 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat
case FZ_MOVETO:
p1.x = path->items[i++].v;
p1.y = path->items[i++].v;
- fz_dash_moveto(&s, p1);
+ fz_dash_moveto(&s, p1, stroke->start_cap, stroke->end_cap);
beg = p0 = p1;
break;
case FZ_LINETO:
p1.x = path->items[i++].v;
p1.y = path->items[i++].v;
- fz_dash_lineto(&s, p1);
+ fz_dash_lineto(&s, p1, stroke->dash_cap);
p0 = p1;
break;
@@ -767,16 +782,16 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat
p2.y = path->items[i++].v;
p3.x = path->items[i++].v;
p3.y = path->items[i++].v;
- fz_dash_bezier(&s, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, 0);
+ fz_dash_bezier(&s, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, 0, stroke->dash_cap);
p0 = p3;
break;
case FZ_CLOSE_PATH:
- fz_dash_lineto(&s, beg);
+ fz_dash_lineto(&s, beg, stroke->dash_cap);
p0 = p1 = beg;
break;
}
}
- fz_stroke_flush(&s);
+ fz_stroke_flush(&s, s.cap, stroke->end_cap);
}
diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c
index 758a18f9..9e6853b8 100644
--- a/fitz/dev_trace.c
+++ b/fitz/dev_trace.c
@@ -84,7 +84,7 @@ fz_trace_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matr
printf("<stroke_path ");
printf("linewidth=\"%g\" ", stroke->linewidth);
printf("miterlimit=\"%g\" ", stroke->miterlimit);
- printf("linecap=\"%d\" ", stroke->linecap);
+ printf("linecap=\"%d,%d,%d\" ", stroke->start_cap, stroke->dash_cap, stroke->end_cap);
printf("linejoin=\"%d\" ", stroke->linejoin);
if (stroke->dash_len)
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 399c7665..7f35c417 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -784,7 +784,7 @@ struct fz_path_s
struct fz_stroke_state_s
{
- int linecap;
+ int start_cap, dash_cap, end_cap;
int linejoin;
float linewidth;
float miterlimit;
diff --git a/fitz/res_font.c b/fitz/res_font.c
index e2542f9b..fdcfb77b 100644
--- a/fitz/res_font.c
+++ b/fitz/res_font.c
@@ -432,7 +432,7 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm,
return NULL;
}
- FT_Stroker_Set(stroker, linewidth, state->linecap, state->linejoin, state->miterlimit * 65536);
+ FT_Stroker_Set(stroker, linewidth, state->start_cap, state->linejoin, state->miterlimit * 65536);
fterr = FT_Get_Glyph(face->glyph, &glyph);
if (fterr)
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index d25446d5..27061637 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -609,9 +609,11 @@ pdf_init_gstate(pdf_gstate *gs, fz_matrix ctm)
gs->ctm = ctm;
gs->clip_depth = 0;
- gs->stroke_state.linewidth = 1;
- gs->stroke_state.linecap = 0;
+ gs->stroke_state.start_cap = 0;
+ gs->stroke_state.dash_cap = 0;
+ gs->stroke_state.end_cap = 0;
gs->stroke_state.linejoin = 0;
+ gs->stroke_state.linewidth = 1;
gs->stroke_state.miterlimit = 10;
gs->stroke_state.dash_phase = 0;
gs->stroke_state.dash_len = 0;
@@ -1142,10 +1144,14 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate)
return fz_throw("malformed /Font dictionary");
}
+ else if (!strcmp(s, "LC"))
+ {
+ gstate->stroke_state.start_cap = fz_to_int(val);
+ gstate->stroke_state.dash_cap = fz_to_int(val);
+ gstate->stroke_state.end_cap = fz_to_int(val);
+ }
else if (!strcmp(s, "LW"))
gstate->stroke_state.linewidth = fz_to_real(val);
- else if (!strcmp(s, "LC"))
- gstate->stroke_state.linecap = fz_to_int(val);
else if (!strcmp(s, "LJ"))
gstate->stroke_state.linejoin = fz_to_int(val);
else if (!strcmp(s, "ML"))
@@ -1472,7 +1478,9 @@ static void pdf_run_G(pdf_csi *csi)
static void pdf_run_J(pdf_csi *csi)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
- gstate->stroke_state.linecap = csi->stack[0];
+ gstate->stroke_state.start_cap = csi->stack[0];
+ gstate->stroke_state.dash_cap = csi->stack[0];
+ gstate->stroke_state.end_cap = csi->stack[0];
}
static void pdf_run_K(pdf_csi *csi)
diff --git a/xps/xps_path.c b/xps/xps_path.c
index 547deed8..c2444779 100644
--- a/xps/xps_path.c
+++ b/xps/xps_path.c
@@ -741,7 +741,7 @@ xps_parse_line_cap(char *attr)
if (!strcmp(attr, "Flat")) return 0;
if (!strcmp(attr, "Round")) return 1;
if (!strcmp(attr, "Square")) return 2;
- if (!strcmp(attr, "Triangle")) return 3; /* FIXME add triangle caps */
+ if (!strcmp(attr, "Triangle")) return 3;
}
return 0;
}
@@ -880,9 +880,9 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di
stroke_tag = NULL;
}
- stroke.linecap = xps_parse_line_cap(stroke_start_line_cap_att);
-// fz_setlineendcap(ctx->pgs, xps_parse_line_cap(stroke_end_line_cap_att));
-// fz_setlinedashcap(ctx->pgs, xps_parse_line_cap(stroke_dash_cap_att));
+ stroke.start_cap = xps_parse_line_cap(stroke_start_line_cap_att);
+ stroke.dash_cap = xps_parse_line_cap(stroke_dash_cap_att);
+ stroke.end_cap = xps_parse_line_cap(stroke_end_line_cap_att);
stroke.linejoin = 0;
if (stroke_line_join_att)