/*
 * Construct a fan around the midpoint using the vertices from pen between
 * inpt and outpt.
 */
static void
add_fan (struct stroker *stroker,
	 const cairo_slope_t *in_vector,
	 const cairo_slope_t *out_vector,
	 const cairo_point_t *midpt,
	 cairo_bool_t clockwise,
	 struct stroke_contour *c)
{
    cairo_pen_t *pen = &stroker->pen;
    int start, stop;

    if (stroker->has_bounds &&
	! _cairo_box_contains_point (&stroker->bounds, midpt))
	return;

    assert (stroker->pen.num_vertices);

    if (clockwise) {
	_cairo_pen_find_active_cw_vertices (pen,
					    in_vector, out_vector,
					    &start, &stop);
	while (start != stop) {
	    cairo_point_t p = *midpt;
	    translate_point (&p, &pen->vertices[start].point);
	    contour_add_point (stroker, c, &p);

	    if (++start == pen->num_vertices)
		start = 0;
	}
    } else {
	_cairo_pen_find_active_ccw_vertices (pen,
					     in_vector, out_vector,
					     &start, &stop);
	while (start != stop) {
	    cairo_point_t p = *midpt;
	    translate_point (&p, &pen->vertices[start].point);
	    contour_add_point (stroker, c, &p);

	    if (start-- == 0)
		start += pen->num_vertices;
	}
    }
}
示例#2
0
/*
 * Construct a fan around the midpoint using the vertices from pen between
 * inpt and outpt.
 */
static cairo_status_t
_tessellate_fan (cairo_stroker_t *stroker,
		 const cairo_slope_t *in_vector,
		 const cairo_slope_t *out_vector,
		 const cairo_point_t *midpt,
		 const cairo_point_t *inpt,
		 const cairo_point_t *outpt,
		 cairo_bool_t clockwise)
{
    cairo_point_t stack_points[64], *points = stack_points;
    cairo_pen_t *pen = &stroker->pen;
    int start, stop, num_points = 0;
    cairo_status_t status;

    if (stroker->has_bounds &&
	! _cairo_box_contains_point (&stroker->bounds, midpt))
	goto BEVEL;

    assert (stroker->pen.num_vertices);

    if (clockwise) {
	_cairo_pen_find_active_ccw_vertices (pen,
					     in_vector, out_vector,
					     &start, &stop);
	if (stroker->add_external_edge) {
	    cairo_point_t last;
	    last = *inpt;
	    while (start != stop) {
		cairo_point_t p = *midpt;
		_translate_point (&p, &pen->vertices[start].point);

		status = stroker->add_external_edge (stroker->closure,
						     &last, &p);
		if (unlikely (status))
		    return status;
		last = p;

		if (start-- == 0)
		    start += pen->num_vertices;
	    }
	    status = stroker->add_external_edge (stroker->closure,
						 &last, outpt);
	} else {
	    if (start == stop)
		goto BEVEL;

	    num_points = stop - start;
	    if (num_points < 0)
		num_points += pen->num_vertices;
	    num_points += 2;
	    if (num_points > ARRAY_LENGTH(stack_points)) {
		points = _cairo_malloc_ab (num_points, sizeof (cairo_point_t));
		if (unlikely (points == NULL))
		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
	    }

	    points[0] = *inpt;
	    num_points = 1;
	    while (start != stop) {
		points[num_points] = *midpt;
		_translate_point (&points[num_points], &pen->vertices[start].point);
		num_points++;

		if (start-- == 0)
		    start += pen->num_vertices;
	    }
	    points[num_points++] = *outpt;
	}
    } else {
	_cairo_pen_find_active_cw_vertices (pen,
					    in_vector, out_vector,
					    &start, &stop);
	if (stroker->add_external_edge) {
	    cairo_point_t last;
	    last = *inpt;
	    while (start != stop) {
		cairo_point_t p = *midpt;
		_translate_point (&p, &pen->vertices[start].point);

		status = stroker->add_external_edge (stroker->closure,
						     &p, &last);
		if (unlikely (status))
		    return status;
		last = p;

		if (++start == pen->num_vertices)
		    start = 0;
	    }
	    status = stroker->add_external_edge (stroker->closure,
						 outpt, &last);
	} else {
	    if (start == stop)
		goto BEVEL;

	    num_points = stop - start;
	    if (num_points < 0)
		num_points += pen->num_vertices;
	    num_points += 2;
	    if (num_points > ARRAY_LENGTH(stack_points)) {
		points = _cairo_malloc_ab (num_points, sizeof (cairo_point_t));
		if (unlikely (points == NULL))
		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
	    }

	    points[0] = *inpt;
	    num_points = 1;
	    while (start != stop) {
		points[num_points] = *midpt;
		_translate_point (&points[num_points], &pen->vertices[start].point);
		num_points++;

		if (++start == pen->num_vertices)
		    start = 0;
	    }
	    points[num_points++] = *outpt;
	}
    }

    if (num_points) {
	status = stroker->add_triangle_fan (stroker->closure,
					    midpt, points, num_points);
    }

    if (points != stack_points)
	free (points);

    return status;

BEVEL:
    /* Ensure a leak free connection... */
    if (stroker->add_external_edge != NULL) {
	if (clockwise)
	    return stroker->add_external_edge (stroker->closure, inpt, outpt);
	else
	    return stroker->add_external_edge (stroker->closure, outpt, inpt);
    } else {
	stack_points[0] = *midpt;
	stack_points[1] = *inpt;
	stack_points[2] = *outpt;
	return stroker->add_triangle (stroker->closure, stack_points);
    }
}