static cairo_status_t _cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon) { int i; cairo_status_t status; int start, stop, step; int active = 0; cairo_point_t hull_point; cairo_slope_t slope, initial_slope, final_slope; cairo_point_t *point = spline->points; int num_points = spline->num_points; if (dir == CAIRO_DIRECTION_FORWARD) { start = 0; stop = num_points; step = 1; initial_slope = spline->initial_slope; final_slope = spline->final_slope; } else { start = num_points - 1; stop = -1; step = -1; initial_slope = spline->final_slope; initial_slope.dx = -initial_slope.dx; initial_slope.dy = -initial_slope.dy; final_slope = spline->initial_slope; final_slope.dx = -final_slope.dx; final_slope.dy = -final_slope.dy; } _cairo_pen_find_active_cw_vertex_index (pen, &initial_slope, &active); i = start; while (i != stop) { hull_point.x = point[i].x + pen->vertices[active].point.x; hull_point.y = point[i].y + pen->vertices[active].point.y; status = _cairo_polygon_line_to (polygon, &hull_point); if (status) return status; if (i + step == stop) slope = final_slope; else _cairo_slope_init (&slope, &point[i], &point[i+step]); if (_cairo_slope_counter_clockwise (&slope, &pen->vertices[active].slope_ccw)) { if (++active == pen->num_vertices) active = 0; } else if (_cairo_slope_clockwise (&slope, &pen->vertices[active].slope_cw)) { if (--active == -1) active = pen->num_vertices - 1; } else { i += step; } } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_filler_curve_to (void *closure, cairo_point_t *b, cairo_point_t *c, cairo_point_t *d) { int i; cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_filler_t *filler = closure; cairo_polygon_t *polygon = &filler->polygon; cairo_spline_t spline; status = _cairo_spline_init (&spline, &filler->current_point, b, c, d); if (status == CAIRO_INT_STATUS_DEGENERATE) return CAIRO_STATUS_SUCCESS; _cairo_spline_decompose (&spline, filler->tolerance); if (status) goto CLEANUP_SPLINE; for (i = 1; i < spline.num_points; i++) { status = _cairo_polygon_line_to (polygon, &spline.points[i]); if (status) break; } CLEANUP_SPLINE: _cairo_spline_fini (&spline); filler->current_point = *d; return status; }
static cairo_status_t _cairo_filler_line_to (void *closure, const cairo_point_t *point) { cairo_filler_t *filler = closure; return _cairo_polygon_line_to (filler->polygon, point); }
static cairo_status_t _cairo_filler_line_to (void *closure, cairo_point_t *point) { cairo_filler_t *filler = closure; cairo_polygon_t *polygon = &filler->polygon; _cairo_polygon_line_to (polygon, point); filler->current_point = *point; return _cairo_polygon_status (&filler->polygon); }
static cairo_status_t _cairo_filler_line_to (void *closure, cairo_point_t *point) { cairo_status_t status; cairo_filler_t *filler = closure; cairo_polygon_t *polygon = &filler->polygon; status = _cairo_polygon_line_to (polygon, point); if (status) return status; filler->current_point = *point; return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_polygon_close (cairo_polygon_t *polygon) { cairo_status_t status; if (polygon->has_current_point) { status = _cairo_polygon_line_to (polygon, &polygon->first_point); polygon->has_current_point = FALSE; } if (polygon->has_current_edge) { _cairo_polygon_add_edge (polygon, &polygon->last_point, &polygon->current_point); polygon->has_current_edge = FALSE; } return polygon->status; }
static cairo_status_t _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f) { cairo_status_t status; if (stroker->style->line_cap == CAIRO_LINE_CAP_BUTT) return CAIRO_STATUS_SUCCESS; switch (stroker->style->line_cap) { case CAIRO_LINE_CAP_ROUND: { int i; int start, stop; cairo_slope_t slope; cairo_point_t tri[3]; cairo_pen_t *pen = &stroker->pen; slope = f->dev_vector; start = _cairo_pen_find_active_cw_vertex_index (pen, &slope); slope.dx = -slope.dx; slope.dy = -slope.dy; stop = _cairo_pen_find_active_cw_vertex_index (pen, &slope); tri[0] = f->point; tri[1] = f->cw; for (i=start; i != stop; i = (i+1) % pen->num_vertices) { tri[2] = f->point; _translate_point (&tri[2], &pen->vertices[i].point); status = _cairo_traps_tessellate_triangle (stroker->traps, tri); if (unlikely (status)) return status; tri[1] = tri[2]; } tri[2] = f->ccw; return _cairo_traps_tessellate_triangle (stroker->traps, tri); } case CAIRO_LINE_CAP_SQUARE: { double dx, dy; cairo_slope_t fvector; cairo_point_t occw, ocw; cairo_polygon_t polygon; dx = f->usr_vector.x; dy = f->usr_vector.y; dx *= stroker->style->line_width / 2.0; dy *= stroker->style->line_width / 2.0; cairo_matrix_transform_distance (stroker->ctm, &dx, &dy); fvector.dx = _cairo_fixed_from_double (dx); fvector.dy = _cairo_fixed_from_double (dy); occw.x = f->ccw.x + fvector.dx; occw.y = f->ccw.y + fvector.dy; ocw.x = f->cw.x + fvector.dx; ocw.y = f->cw.y + fvector.dy; _cairo_polygon_init (&polygon); _cairo_polygon_move_to (&polygon, &f->cw); _cairo_polygon_line_to (&polygon, &ocw); _cairo_polygon_line_to (&polygon, &occw); _cairo_polygon_line_to (&polygon, &f->ccw); _cairo_polygon_close (&polygon); status = _cairo_polygon_status (&polygon); if (status == CAIRO_STATUS_SUCCESS) { status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING); } _cairo_polygon_fini (&polygon); return status; } case CAIRO_LINE_CAP_BUTT: default: return CAIRO_STATUS_SUCCESS; } }
static void _cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon) { int i; int start, stop, step; int active = 0; cairo_point_t hull_point; cairo_slope_t slope, initial_slope, final_slope; cairo_point_t *point = spline->points; int num_points = spline->num_points; if (dir == CAIRO_DIRECTION_FORWARD) { start = 0; stop = num_points; step = 1; initial_slope = spline->initial_slope; final_slope = spline->final_slope; } else { start = num_points - 1; stop = -1; step = -1; initial_slope = spline->final_slope; initial_slope.dx = -initial_slope.dx; initial_slope.dy = -initial_slope.dy; final_slope = spline->initial_slope; final_slope.dx = -final_slope.dx; final_slope.dy = -final_slope.dy; } _cairo_pen_find_active_cw_vertex_index (pen, &initial_slope, &active); i = start; while (i != stop) { hull_point.x = point[i].x + pen->vertices[active].point.x; hull_point.y = point[i].y + pen->vertices[active].point.y; _cairo_polygon_line_to (polygon, &hull_point); if (i + step == stop) slope = final_slope; else _cairo_slope_init (&slope, &point[i], &point[i+step]); /* The strict inequalities here ensure that if a spline slope * compares identically with either of the slopes of the * active vertex, then it remains the active vertex. This is * very important since otherwise we can trigger an infinite * loop in the case of a degenerate pen, (a line), where * neither vertex considers itself active for the slope---one * will consider it as equal and reject, and the other will * consider it unequal and reject. This is due to the inherent * ambiguity when comparing slopes that differ by exactly * pi. */ if (_cairo_slope_compare (&slope, &pen->vertices[active].slope_ccw) > 0) { if (++active == pen->num_vertices) active = 0; } else if (_cairo_slope_compare (&slope, &pen->vertices[active].slope_cw) < 0) { if (--active == -1) active = pen->num_vertices - 1; } else { i += step; } } }