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; }
/* Find active pen vertex for counterclockwise edge of stroke at the given slope. * * NOTE: The behavior of this function is sensitive to the sense of * the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise. */ cairo_status_t _cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen, cairo_slope_t *slope, int *active) { int i; cairo_slope_t slope_reverse; slope_reverse = *slope; slope_reverse.dx = -slope_reverse.dx; slope_reverse.dy = -slope_reverse.dy; for (i=pen->num_vertices-1; i >= 0; i--) { if (_cairo_slope_counter_clockwise (&pen->vertices[i].slope_ccw, &slope_reverse) && _cairo_slope_clockwise (&pen->vertices[i].slope_cw, &slope_reverse)) break; } /* If the desired slope cannot be found between any of the pen * vertices, then we must have a degenerate pen, (such as a pen * that's been transformed to a line). In that case, we consider * the last pen vertex as the appropriate counterclockwise vertex. */ if (i < 0) i = pen->num_vertices - 1; *active = i; return CAIRO_STATUS_SUCCESS; }
/* * Find active pen vertex for clockwise edge of stroke at the given slope. * * NOTE: The behavior of this function is sensitive to the sense of * the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise. * * The issue is that the slope_ccw member of one pen vertex will be * equivalent to the slope_cw member of the next pen vertex in a * counterclockwise order. However, for this function, we care * strongly about which vertex is returned. */ cairo_status_t _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen, cairo_slope_t *slope, int *active) { int i; for (i=0; i < pen->num_vertices; i++) { if (_cairo_slope_clockwise (slope, &pen->vertices[i].slope_ccw) && _cairo_slope_counter_clockwise (slope, &pen->vertices[i].slope_cw)) break; } /* If the desired slope cannot be found between any of the pen * vertices, then we must have a degenerate pen, (such as a pen * that's been transformed to a line). In that case, we consider * the first pen vertex as the appropriate clockwise vertex. */ if (i == pen->num_vertices) i = 0; *active = i; return CAIRO_STATUS_SUCCESS; }
/* * Find active pen vertex for clockwise edge of stroke at the given slope. * * NOTE: The behavior of this function is sensitive to the sense of * the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise. * * The issue is that the slope_ccw member of one pen vertex will be * equivalent to the slope_cw member of the next pen vertex in a * counterclockwise order. However, for this function, we care * strongly about which vertex is returned. */ cairo_status_t _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen, cairo_slope_t *slope, int *active) { int i; for (i=0; i < pen->num_vertices; i++) { if (_cairo_slope_clockwise (slope, &pen->vertices[i].slope_ccw) && _cairo_slope_counter_clockwise (slope, &pen->vertices[i].slope_cw)) break; } *active = i; return CAIRO_STATUS_SUCCESS; }
/* Find active pen vertex for counterclockwise edge of stroke at the given slope. * * NOTE: The behavior of this function is sensitive to the sense of * the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise. */ cairo_status_t _cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen, cairo_slope_t *slope, int *active) { int i; cairo_slope_t slope_reverse; slope_reverse = *slope; slope_reverse.dx = -slope_reverse.dx; slope_reverse.dy = -slope_reverse.dy; for (i=pen->num_vertices-1; i >= 0; i--) { if (_cairo_slope_counter_clockwise (&pen->vertices[i].slope_ccw, &slope_reverse) && _cairo_slope_clockwise (&pen->vertices[i].slope_cw, &slope_reverse)) break; } *active = i; return CAIRO_STATUS_SUCCESS; }
int _cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b) { return ! _cairo_slope_clockwise (a, b); }