diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2011-04-11 18:16:50 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-04-11 18:16:50 +0200 |
commit | c6934bd8de9d593ec51f60b7c0db9f8a2125352e (patch) | |
tree | f964a662ebe3ad5e79cd55215eedc7fd4eb05434 | |
parent | 6d2ca771127fb9186372566e5671c79c354b04b9 (diff) | |
download | mupdf-c6934bd8de9d593ec51f60b7c0db9f8a2125352e.tar.xz |
Add triangle caps; separate start, dash and end cap styles for XPS.
-rw-r--r-- | draw/draw_path.c | 77 | ||||
-rw-r--r-- | fitz/dev_trace.c | 2 | ||||
-rw-r--r-- | fitz/fitz.h | 2 | ||||
-rw-r--r-- | fitz/res_font.c | 2 | ||||
-rw-r--r-- | pdf/pdf_interpret.c | 18 | ||||
-rw-r--r-- | xps/xps_path.c | 8 |
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) |