示例#1
0
/* We're using two different algorithms here for dashed and un-dashed
 * splines. The dashed algorithm 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 algorithms 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_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_stroker_line_to_dashed (closure, d);

    /* If the line width is so small that the pen is reduced to a
       single point, then we have nothing to do. */
    if (stroker->pen.num_vertices <= 1)
	goto CLEANUP_SPLINE;

    /* Temporarily modify the stroker to use round joins to guarantee
     * smooth stroked curves. */
    line_join_save = stroker->style->line_join;
    stroker->style->line_join = CAIRO_LINE_JOIN_ROUND;

    status = _cairo_spline_decompose (&spline, stroker->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:
    stroker->style->line_join = line_join_save;

  CLEANUP_SPLINE:
    _cairo_spline_fini (&spline);

    return status;
}
示例#2
0
static cairo_status_t
_cairo_stroker_close_path (void *closure)
{
    cairo_stroker_t *stroker = closure;
    cairo_status_t status;

    if (stroker->dash.dashed)
	status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
    else
	status = _cairo_stroker_line_to (stroker, &stroker->first_point);
    if (unlikely (status))
	return status;

    if (stroker->has_first_face && stroker->has_current_face) {
	/* Join first and final faces of sub path */
	status = _cairo_stroker_join (stroker,
				      &stroker->current_face,
				      &stroker->first_face);
	if (unlikely (status))
	    return status;
    } else {
	/* Cap the start and end of the sub path as needed */
	status = _cairo_stroker_add_caps (stroker);
	if (unlikely (status))
	    return status;
    }

    stroker->has_initial_sub_path = FALSE;
    stroker->has_first_face = FALSE;
    stroker->has_current_face = FALSE;

    return CAIRO_STATUS_SUCCESS;
}
示例#3
0
/* We're using two different algorithms here for dashed and un-dashed
 * splines. The dashed algorithm 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 algorithms 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,
				const cairo_point_t *b,
				const cairo_point_t *c,
				const cairo_point_t *d)
{
    cairo_stroker_t *stroker = closure;
    cairo_spline_t spline;
    cairo_point_t *a = &stroker->current_point;
    cairo_line_join_t line_join_save;
    cairo_status_t status;

    if (! _cairo_spline_init (&spline,
			      stroker->dashed ?
			      _cairo_stroker_line_to_dashed :
			      _cairo_stroker_line_to,
			      stroker,
			      a, b, c, d))
    {
	return _cairo_stroker_line_to_dashed (closure, d);
    }

    /* If the line width is so small that the pen is reduced to a
       single point, then we have nothing to do. */
    if (stroker->pen.num_vertices <= 1)
	return CAIRO_STATUS_SUCCESS;

    /* Temporarily modify the stroker to use round joins to guarantee
     * smooth stroked curves. */
    line_join_save = stroker->style->line_join;
    stroker->style->line_join = CAIRO_LINE_JOIN_ROUND;

    status = _cairo_spline_decompose (&spline, stroker->tolerance);

    stroker->style->line_join = line_join_save;

    return status;
}