static inline cairo_bool_t edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b) { if (_line_equal (&a->edge.line, &b->edge.line)) return TRUE; if (_slope_compare (a, b)) return FALSE; /* The choice of y is not truly arbitrary since we must guarantee that it * is greater than the start of either line. */ if (a->edge.line.p1.y == b->edge.line.p1.y) { return a->edge.line.p1.x == b->edge.line.p1.x; } else if (a->edge.line.p2.y == b->edge.line.p2.y) { return a->edge.line.p2.x == b->edge.line.p2.x; } else if (a->edge.line.p1.y < b->edge.line.p1.y) { return edge_compare_for_y_against_x (b, a->edge.line.p1.y, a->edge.line.p1.x) == 0; } else { return edge_compare_for_y_against_x (a, b->edge.line.p1.y, b->edge.line.p1.x) == 0; } }
static void _cairo_in_fill_add_edge (cairo_in_fill_t *in_fill, const cairo_point_t *p1, const cairo_point_t *p2) { int dir; if (in_fill->on_edge) return; /* count the number of edge crossing to -∞ */ dir = 1; if (p2->y < p1->y) { const cairo_point_t *tmp; tmp = p1; p1 = p2; p2 = tmp; dir = -1; } /* First check whether the query is on an edge */ if ((p1->x == in_fill->x && p1->y == in_fill->y) || (p2->x == in_fill->x && p2->y == in_fill->y) || (! (p2->y < in_fill->y || p1->y > in_fill->y || (p1->x > in_fill->x && p2->x > in_fill->x) || (p1->x < in_fill->x && p2->x < in_fill->x)) && edge_compare_for_y_against_x (p1, p2, in_fill->y, in_fill->x) == 0)) { in_fill->on_edge = TRUE; return; } /* edge is entirely above or below, note the shortening rule */ if (p2->y <= in_fill->y || p1->y > in_fill->y) return; /* edge lies wholly to the right */ if (p1->x >= in_fill->x && p2->x >= in_fill->x) return; if ((p1->x <= in_fill->x && p2->x <= in_fill->x) || edge_compare_for_y_against_x (p1, p2, in_fill->y, in_fill->x) < 0) { in_fill->winding += dir; } }
static int edges_compare_x_for_y (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b, int32_t y) { /* If the sweep-line is currently on an end-point of a line, * then we know its precise x value (and considering that we often need to * compare events at end-points, this happens frequently enough to warrant * special casing). */ enum { HAVE_NEITHER = 0x0, HAVE_AX = 0x1, HAVE_BX = 0x2, HAVE_BOTH = HAVE_AX | HAVE_BX } have_ax_bx = HAVE_BOTH; int32_t ax = 0, bx = 0; if (y == a->edge.line.p1.y) ax = a->edge.line.p1.x; else if (y == a->edge.line.p2.y) ax = a->edge.line.p2.x; else have_ax_bx &= ~HAVE_AX; if (y == b->edge.line.p1.y) bx = b->edge.line.p1.x; else if (y == b->edge.line.p2.y) bx = b->edge.line.p2.x; else have_ax_bx &= ~HAVE_BX; switch (have_ax_bx) { default: case HAVE_NEITHER: return edges_compare_x_for_y_general (a, b, y); case HAVE_AX: return -edge_compare_for_y_against_x (b, y, ax); case HAVE_BX: return edge_compare_for_y_against_x (a, y, bx); case HAVE_BOTH: return ax - bx; } }