summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--src/cairo-path-stroke.c76
2 files changed, 86 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 956147bf2..84605389a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-09-16 Carl Worth <cworth@cworth.org>
+
+ Tested by: John Ellson
+ Closes bug #4408
+ https://bugs.freedesktop.org/show_bug.cgi?id=4408
+
+ * src/cairo-path-stroke.c: (_cairo_stroker_curve_to_dashed),
+ (_cairo_path_fixed_stroke_to_traps): Add support for dashed
+ splines. (The antialiasing quality isn't perfect, but at least the
+ curves are dashed now).
+
2005-09-13 Carl Worth <cworth@cworth.org>
* src/cairo-ft-font.c: (_cairo_ft_scaled_font_text_to_glyphs):
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 45a491afd..5bffcea8e 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -81,6 +81,12 @@ _cairo_stroker_curve_to (void *closure,
cairo_point_t *d);
static cairo_status_t
+_cairo_stroker_curve_to_dashed (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d);
+
+static cairo_status_t
_cairo_stroker_close_path (void *closure);
static void
@@ -801,6 +807,74 @@ _cairo_stroker_curve_to (void *closure,
return status;
}
+/* We're using two different algorithms here for dashed and un-dashed
+ * splines. The dashed alogorithm uses the existing line dashing
+ * code. It's linear in path length, but gets subtly wrong results for
+ * self-intersecting paths (an outstanding but for self-intersecting
+ * non-curved paths as well). The non-dashed algorithm tessellates a
+ * single polygon for the whole curve. It handles the
+ * self-intersecting problem, but it's (unsurprisingly) not O(n) and
+ * more significantly, it doesn't yet handle dashes.
+ *
+ * The only reason we're doing split algortihms here is to
+ * minimize the impact of fixing the splines-aren't-dashed bug for
+ * 1.0.2. Long-term the right answer is to rewrite the whole pile
+ * of stroking code so that the entire result is computed as a
+ * single polygon that is tessellated, (that is, stroking can be
+ * built on top of filling). That will solve the self-intersecting
+ * problem. It will also increase the importance of implementing
+ * an efficient and more robust tessellator.
+ */
+static cairo_status_t
+_cairo_stroker_curve_to_dashed (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_stroker_t *stroker = closure;
+ cairo_gstate_t *gstate = stroker->gstate;
+ cairo_spline_t spline;
+ cairo_point_t *a = &stroker->current_point;
+ cairo_line_join_t line_join_save;
+ int i;
+
+ status = _cairo_spline_init (&spline, a, b, c, d);
+ if (status == CAIRO_INT_STATUS_DEGENERATE)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* If the line width is so small that the pen is reduced to a
+ single point, then we have nothing to do. */
+ if (gstate->pen_regular.num_vertices <= 1)
+ goto CLEANUP_SPLINE;
+
+ /* Temporarily modify the gstate to use round joins to guarantee
+ * smooth stroked curves. */
+ line_join_save = gstate->line_join;
+ gstate->line_join = CAIRO_LINE_JOIN_ROUND;
+
+ status = _cairo_spline_decompose (&spline, gstate->tolerance);
+ if (status)
+ goto CLEANUP_GSTATE;
+
+ for (i = 1; i < spline.num_points; i++) {
+ if (stroker->dashed)
+ status = _cairo_stroker_line_to_dashed (stroker, &spline.points[i]);
+ else
+ status = _cairo_stroker_line_to (stroker, &spline.points[i]);
+ if (status)
+ break;
+ }
+
+ CLEANUP_GSTATE:
+ gstate->line_join = line_join_save;
+
+ CLEANUP_SPLINE:
+ _cairo_spline_fini (&spline);
+
+ return status;
+}
+
static cairo_status_t
_cairo_stroker_close_path (void *closure)
{
@@ -844,7 +918,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
CAIRO_DIRECTION_FORWARD,
_cairo_stroker_move_to,
_cairo_stroker_line_to_dashed,
- _cairo_stroker_curve_to,
+ _cairo_stroker_curve_to_dashed,
_cairo_stroker_close_path,
&stroker);
else