예제 #1
0
/* Warning: This function reorders the elements of the array provided. */
cairo_status_t
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4])
{
    cairo_status_t status;

    qsort (q, 4, sizeof (cairo_point_t), _compare_point_fixed_by_y);

    if (q[1].x > q[2].x) {
	status = _cairo_traps_add_trap_from_points (traps,
						    q[0].y, q[1].y, q[0], q[2], q[0], q[1]);
	if (status)
	    return status;
	status = _cairo_traps_add_trap_from_points (traps,
						    q[1].y, q[2].y, q[0], q[2], q[1], q[3]);
	if (status)
	    return status;
	status = _cairo_traps_add_trap_from_points (traps,
						    q[2].y, q[3].y, q[2], q[3], q[1], q[3]);
	if (status)
	    return status;
    } else {
	status = _cairo_traps_add_trap_from_points (traps,
						    q[0].y, q[1].y, q[0], q[1], q[0], q[2]);
	if (status)
	    return status;
	status = _cairo_traps_add_trap_from_points (traps,
						    q[1].y, q[2].y, q[1], q[3], q[0], q[2]);
	if (status)
	    return status;
	status = _cairo_traps_add_trap_from_points (traps,
						    q[2].y, q[3].y, q[1], q[3], q[2], q[3]);
	if (status)
	    return status;
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #2
0
cairo_status_t
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
{
    int a, b, c, d;
    int i;
    cairo_slope_t ab, ad;
    cairo_bool_t b_left_of_d;

    /* Choose a as a point with minimal y */
    a = 0;
    for (i = 1; i < 4; i++)
	if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
	    a = i;

    /* b and d are adjacent to a, while c is opposite */
    b = (a + 1) % 4;
    c = (a + 2) % 4;
    d = (a + 3) % 4;

    /* Choose between b and d so that b.y is less than d.y */
    if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
	b = (a + 3) % 4;
	d = (a + 1) % 4;
    }

    /* Without freedom left to choose anything else, we have four
     * cases to tessellate.
     *
     * First, we have to determine the Y-axis sort of the four
     * vertices, (either abcd or abdc). After that we need to detemine
     * which edges will be "left" and which will be "right" in the
     * resulting trapezoids. This can be determined by computing a
     * slope comparison of ab and ad to determine if b is left of d or
     * not.
     *
     * Note that "left of" here is in the sense of which edges should
     * be the left vs. right edges of the trapezoid. In particular, b
     * left of d does *not* mean that b.x is less than d.x.
     *
     * This should hopefully be made clear in the lame ASCII art
     * below. Since the same slope comparison is used in all cases, we
     * compute it before testing for the Y-value sort. */

    /* Note: If a == b then the ab slope doesn't give us any
     * information. In that case, we can replace it with the ac (or
     * equivalenly the bc) slope which gives us exactly the same
     * information we need. At worst the names of the identifiers ab
     * and b_left_of_d are inaccurate in this case, (would be ac, and
     * c_left_of_d). */
    if (q[a].x == q[b].x && q[a].y == q[b].y)
	_cairo_slope_init (&ab, &q[a], &q[c]);
    else
	_cairo_slope_init (&ab, &q[a], &q[b]);

    _cairo_slope_init (&ad, &q[a], &q[d]);

    b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0);

    if (q[c].y <= q[d].y) {
	if (b_left_of_d) {
	    /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
	     *
	     *                      top bot left right
	     *        _a  a  a
	     *      / /  /|  |\      a.y b.y  ab   ad
	     *     b /  b |  b \
	     *    / /   | |   \ \    b.y c.y  bc   ad
	     *   c /    c |    c \
	     *  | /      \|     \ \  c.y d.y  cd   ad
	     *  d         d       d
	     */
	    _cairo_traps_add_trap_from_points (traps,
					       q[a].y, q[b].y,
					       q[a], q[b], q[a], q[d]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[b].y, q[c].y,
					       q[b], q[c], q[a], q[d]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[c].y, q[d].y,
					       q[c], q[d], q[a], q[d]);
	} else {
	    /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
	     *
	     *       a  a  a_
	     *      /|  |\  \ \     a.y b.y  ad  ab
	     *     / b  | b  \ b
	     *    / /   | |   \ \   b.y c.y  ad  bc
	     *   / c    | c    \ c
	     *  / /     |/      \ | c.y d.y  ad  cd
	     *  d       d         d
	     */
	    _cairo_traps_add_trap_from_points (traps,
					       q[a].y, q[b].y,
					       q[a], q[d], q[a], q[b]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[b].y, q[c].y,
					       q[a], q[d], q[b], q[c]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[c].y, q[d].y,
					       q[a], q[d], q[c], q[d]);
	}
    } else {
	if (b_left_of_d) {
	    /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
	     *
	     *        a   a     a
	     *       //  / \    |\     a.y b.y  ab  ad
	     *     /b/  b   \   b \
	     *    / /    \   \   \ \   b.y d.y  bc  ad
	     *   /d/      \   d   \ d
	     *  //         \ /     \|  d.y c.y  bc  dc
	     *  c           c       c
	     */
	    _cairo_traps_add_trap_from_points (traps,
					       q[a].y, q[b].y,
					       q[a], q[b], q[a], q[d]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[b].y, q[d].y,
					       q[b], q[c], q[a], q[d]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[d].y, q[c].y,
					       q[b], q[c], q[d], q[c]);
	} else {
	    /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
	     *
	     *      a     a   a
	     *     /|    / \  \\       a.y b.y  ad  ab
	     *    / b   /   b  \b\
	     *   / /   /   /    \ \    b.y d.y  ad  bc
	     *  d /   d   /	 \d\
	     *  |/     \ /         \\  d.y c.y  dc  bc
	     *  c       c	   c
	     */
	    _cairo_traps_add_trap_from_points (traps,
					       q[a].y, q[b].y,
					       q[a], q[d], q[a], q[b]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[b].y, q[d].y,
					       q[a], q[d], q[b], q[c]);
	    _cairo_traps_add_trap_from_points (traps,
					       q[d].y, q[c].y,
					       q[d], q[c], q[b], q[c]);
	}
    }

    return traps->status;
}
예제 #3
0
cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
{
    cairo_status_t status;
    cairo_line_t line;
    cairo_fixed_16_16_t intersect;
    cairo_point_t tsort[3];

    memcpy (tsort, t, 3 * sizeof (cairo_point_t));
    qsort (tsort, 3, sizeof (cairo_point_t), _compare_point_fixed_by_y);

    /* horizontal top edge requires special handling */
    if (tsort[0].y == tsort[1].y) {
	if (tsort[0].x < tsort[1].x)
	    status = _cairo_traps_add_trap_from_points (traps,
							tsort[1].y, tsort[2].y,
							tsort[0], tsort[2],
							tsort[1], tsort[2]);
	else
	    status = _cairo_traps_add_trap_from_points (traps,
							tsort[1].y, tsort[2].y,
							tsort[1], tsort[2],
							tsort[0], tsort[2]);
	return status;
    }

    line.p1 = tsort[0];
    line.p2 = tsort[1];

    intersect = _compute_x (&line, tsort[2].y);

    if (intersect < tsort[2].x) {
	status = _cairo_traps_add_trap_from_points (traps,
						    tsort[0].y, tsort[1].y,
						    tsort[0], tsort[1],
						    tsort[0], tsort[2]);
	if (status)
	    return status;
	status = _cairo_traps_add_trap_from_points (traps,
						    tsort[1].y, tsort[2].y,
						    tsort[1], tsort[2],
						    tsort[0], tsort[2]);
	if (status)
	    return status;
    } else {
	status = _cairo_traps_add_trap_from_points (traps,
						    tsort[0].y, tsort[1].y,
						    tsort[0], tsort[2],
						    tsort[0], tsort[1]);
	if (status)
	    return status;
	status = _cairo_traps_add_trap_from_points (traps,
						    tsort[1].y, tsort[2].y,
						    tsort[0], tsort[2],
						    tsort[1], tsort[2]);
	if (status)
	    return status;
    }

    return CAIRO_STATUS_SUCCESS;
}