diff options
author | Robin Watts <robin.watts@artifex.com> | 2016-09-16 18:20:34 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2016-09-19 16:52:31 +0100 |
commit | 352efd644b2398f11f74e267f262f05969752141 (patch) | |
tree | b09f43b7c8a4f3f17d3f46ab732c0838aa3356c7 /source/svg | |
parent | 9d430e88deff3e7f0c88ae14edfd0f11331fb53d (diff) | |
download | mupdf-352efd644b2398f11f74e267f262f05969752141.tar.xz |
Update SVG document handler; circles.
Cope with circles, rounded rects, etc. Not the worlds best
approximation to a circular arc, but it's better than nothing.
Diffstat (limited to 'source/svg')
-rw-r--r-- | source/svg/svg-run.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/source/svg/svg-run.c b/source/svg/svg-run.c index 0a72e508..c65a808f 100644 --- a/source/svg/svg-run.c +++ b/source/svg/svg-run.c @@ -51,6 +51,25 @@ static void svg_draw_path(fz_context *ctx, fz_device *dev, svg_document *doc, fz svg_stroke(ctx, dev, doc, path, state); } +/* + We use the MAGIC number 0.551915 as a bezier subdivision to approximate + a quarter circle arc. The reasons for this can be found here: + http://mechanicalexpressions.com/explore/geometric-modeling/circle-spline-approximation.pdf +*/ +static const float MAGIC_CIRCLE = 0.551915f; + +static void approx_circle(fz_context *ctx, fz_path *path, float cx, float cy, float rx, float ry) +{ + float rxs = rx * MAGIC_CIRCLE; + float rys = ry * MAGIC_CIRCLE; + fz_moveto(ctx, path, cx, cy+ry); + fz_curveto(ctx, path, cx + rxs, cy + ry, cx + rx, cy + rys, cx + rx, cy); + fz_curveto(ctx, path, cx + rx, cy - rys, cx + rxs, cy - rys, cx, cy - ry); + fz_curveto(ctx, path, cx - rxs, cy - ry, cx - rx, cy - rys, cx - rx, cy); + fz_curveto(ctx, path, cx - rx, cy + rys, cx - rxs, cy + rys, cx, cy + ry); + fz_closepath(ctx, path); +} + static void svg_run_rect(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node, const svg_state *inherit_state) { @@ -93,13 +112,27 @@ svg_run_rect(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node, c if (w <= 0 || h <= 0) return; - /* TODO: we need elliptical arcs to draw rounded corners */ - path = fz_new_path(ctx); - fz_moveto(ctx, path, x, y); - fz_lineto(ctx, path, x + w, y); - fz_lineto(ctx, path, x + w, y + h); - fz_lineto(ctx, path, x, y + h); + if (rx == 0 || ry == 0) + { + fz_moveto(ctx, path, x, y); + fz_lineto(ctx, path, x + w, y); + fz_lineto(ctx, path, x + w, y + h); + fz_lineto(ctx, path, x, y + h); + } + else + { + float rxs = rx * MAGIC_CIRCLE; + float rys = rx * MAGIC_CIRCLE; + fz_moveto(ctx, path, x + w - rx, y); + fz_curveto(ctx, path, x + w - rxs, y, x + w, y + rys, x + w, y + ry); + fz_lineto(ctx, path, x + w, y + h - ry); + fz_curveto(ctx, path, x + w, y + h - rys, x + w - rxs, y + h, x + w - rx, y + h); + fz_lineto(ctx, path, x + rx, y + h); + fz_curveto(ctx, path, x + rxs, y + h, x, y + h - rys, x, y + h - rx); + fz_lineto(ctx, path, x, y + rx); + fz_curveto(ctx, path, x, y + rxs, x + rxs, y, x + rx, y); + } fz_closepath(ctx, path); svg_draw_path(ctx, dev, doc, path, &local_state); @@ -131,15 +164,7 @@ svg_run_circle(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node, return; path = fz_new_path(ctx); - // FIXME! - //fz_moveto(ctx, path, cx + r, cy); - //fz_arcn(ctx, path, cx, cy, r, 0, 90); - //fz_arcn(ctx, path, cx, cy, r, 90, 180); - //fz_arcn(ctx, path, cx, cy, r, 180, 270); - //fz_arcn(ctx, path, cx, cy, r, 270, 360); - //fz_closepath(ctx, path); - (void)cx; // avoid compiler warning until this is fixed - (void)cy; + approx_circle(ctx, path, cx, cy, r, r); svg_draw_path(ctx, dev, doc, path, &local_state); fz_drop_path(ctx, path); } @@ -172,10 +197,7 @@ svg_run_ellipse(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node return; path = fz_new_path(ctx); - /* TODO: we need elliptic arcs */ - // TODO: arc... - (void)cx; // avoid compiler warning until this is fixed - (void)cy; + approx_circle(ctx, path, cx, cy, rx, ry); svg_draw_path(ctx, dev, doc, path, &local_state); fz_drop_path(ctx, path); } |