summaryrefslogtreecommitdiff
path: root/source/svg
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-09-16 18:20:34 +0100
committerRobin Watts <robin.watts@artifex.com>2016-09-19 16:52:31 +0100
commit352efd644b2398f11f74e267f262f05969752141 (patch)
treeb09f43b7c8a4f3f17d3f46ab732c0838aa3356c7 /source/svg
parent9d430e88deff3e7f0c88ae14edfd0f11331fb53d (diff)
downloadmupdf-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.c60
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);
}