Exemplo n.º 1
0
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;
    }
}
Exemplo n.º 2
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;
    }
}
Exemplo n.º 3
0
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;
    }
}