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; }
cairo_status_t _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_traps_t *traps) { cairo_status_t status; cairo_stroker_t stroker; /* Before we do anything else, we attempt the rectilinear * stroker. It's careful to generate trapezoids that align to * device-pixel boundaries when possible. Many backends can render * those much faster than non-aligned trapezoids, (by using clip * regions, etc.) */ status = _cairo_path_fixed_stroke_rectilinear (path, stroke_style, ctm, traps); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; status = _cairo_stroker_init (&stroker, stroke_style, ctm, ctm_inverse, tolerance, traps); if (unlikely (status)) return status; if (stroker.style->dash) status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, _cairo_stroker_move_to_dashed, _cairo_stroker_line_to_dashed, _cairo_stroker_curve_to_dashed, _cairo_stroker_close_path, &stroker); else status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, _cairo_stroker_move_to, _cairo_stroker_line_to, _cairo_stroker_curve_to, _cairo_stroker_close_path, &stroker); if (unlikely (status)) goto BAIL; /* Cap the start and end of the final sub path as needed */ status = _cairo_stroker_add_caps (&stroker); BAIL: _cairo_stroker_fini (&stroker); return status; }
cairo_status_t _cairo_path_fixed_stroke_to_shaper (cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_status_t (*add_triangle) (void *closure, const cairo_point_t triangle[3]), cairo_status_t (*add_triangle_fan) (void *closure, const cairo_point_t *midpt, const cairo_point_t *points, int npoints), cairo_status_t (*add_convex_quad) (void *closure, const cairo_point_t quad[4]), void *closure) { cairo_stroker_t stroker; cairo_status_t status; status = _cairo_stroker_init (&stroker, path, stroke_style, ctm, ctm_inverse, tolerance, NULL, 0); if (unlikely (status)) return status; stroker.add_triangle = add_triangle; stroker.add_triangle_fan = add_triangle_fan; stroker.add_convex_quad = add_convex_quad; stroker.closure = closure; status = _cairo_path_fixed_interpret (path, _cairo_stroker_move_to, stroker.dash.dashed ? _cairo_stroker_line_to_dashed : _cairo_stroker_line_to, _cairo_stroker_curve_to, _cairo_stroker_close_path, &stroker); if (unlikely (status)) goto BAIL; /* Cap the start and end of the final sub path as needed */ status = _cairo_stroker_add_caps (&stroker); BAIL: _cairo_stroker_fini (&stroker); return status; }
cairo_status_t _cairo_path_fixed_stroke_dashed_to_polygon (const cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_polygon_t *polygon) { cairo_stroker_t stroker; cairo_status_t status; status = _cairo_stroker_init (&stroker, stroke_style, ctm, ctm_inverse, tolerance); if (unlikely (status)) return status; stroker.add_external_edge = _cairo_polygon_add_external_edge, stroker.closure = polygon; if (polygon->num_limits) _cairo_stroker_limit (&stroker, path, polygon->limits, polygon->num_limits); status = _cairo_path_fixed_interpret (path, _cairo_stroker_move_to, stroker.dash.dashed ? _cairo_stroker_line_to_dashed : _cairo_stroker_line_to, _cairo_stroker_curve_to, _cairo_stroker_close_path, &stroker); if (unlikely (status)) goto BAIL; /* Cap the start and end of the final sub path as needed */ status = _cairo_stroker_add_caps (&stroker); BAIL: _cairo_stroker_fini (&stroker); return status; }
static cairo_status_t _cairo_stroker_move_to (void *closure, cairo_point_t *point) { cairo_status_t status; cairo_stroker_t *stroker = closure; /* Cap the start and end of the previous sub path as needed */ status = _cairo_stroker_add_caps (stroker); if (status) return status; stroker->first_point = *point; stroker->current_point = *point; stroker->has_first_face = FALSE; stroker->has_current_face = FALSE; stroker->has_initial_sub_path = FALSE; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_stroker_move_to (void *closure, const cairo_point_t *point) { cairo_stroker_t *stroker = closure; cairo_status_t status; /* reset the dash pattern for new sub paths */ _cairo_stroker_dash_start (&stroker->dash); /* Cap the start and end of the previous sub path as needed */ status = _cairo_stroker_add_caps (stroker); if (unlikely (status)) return status; stroker->first_point = *point; stroker->current_point = *point; stroker->has_first_face = FALSE; stroker->has_current_face = FALSE; stroker->has_initial_sub_path = FALSE; return CAIRO_STATUS_SUCCESS; }