/* * 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; } } }
/* * 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); } }