mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 03:28:09 +02:00
[traps] Compute extents on demand.
This commit is contained in:
parent
f8bb3617c3
commit
9d51c03bad
5 changed files with 144 additions and 367 deletions
|
|
@ -60,11 +60,6 @@ cairo_private void
|
|||
_cairo_region_init_rectangle (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_region_init_rectangles (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rects,
|
||||
int count);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_fini (cairo_region_t *region);
|
||||
|
||||
|
|
|
|||
|
|
@ -144,23 +144,28 @@ cairo_region_create (void)
|
|||
}
|
||||
slim_hidden_def (cairo_region_create);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_region_init_rectangles (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rects,
|
||||
int count)
|
||||
cairo_region_t *
|
||||
cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
|
||||
int count)
|
||||
{
|
||||
pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
|
||||
pixman_box32_t *pboxes = stack_pboxes;
|
||||
cairo_status_t status;
|
||||
cairo_region_t *region;
|
||||
int i;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0);
|
||||
region = _cairo_malloc (sizeof (cairo_region_t));
|
||||
if (unlikely (region == NULL)) {
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
|
||||
if (count > ARRAY_LENGTH (stack_pboxes)) {
|
||||
pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
|
||||
if (unlikely (pboxes == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
if (unlikely (pboxes == NULL)) {
|
||||
free (region);
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
|
@ -170,35 +175,19 @@ _cairo_region_init_rectangles (cairo_region_t *region,
|
|||
pboxes[i].y2 = rects[i].y + rects[i].height;
|
||||
}
|
||||
|
||||
if (! pixman_region32_init_rects (®ion->rgn, pboxes, count))
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
i = pixman_region32_init_rects (®ion->rgn, pboxes, count);
|
||||
|
||||
if (pboxes != stack_pboxes)
|
||||
free (pboxes);
|
||||
|
||||
return region->status = status;
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
|
||||
int count)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
cairo_status_t status;
|
||||
|
||||
region = _cairo_malloc (sizeof (cairo_region_t));
|
||||
if (unlikely (region == NULL)) {
|
||||
if (unlikely (i == 0)) {
|
||||
free (region);
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
|
||||
status = _cairo_region_init_rectangles (region, rects, count);
|
||||
if (unlikely (status)) {
|
||||
cairo_region_destroy (region);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1);
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
return region;
|
||||
}
|
||||
slim_hidden_def (cairo_region_create_rectangles);
|
||||
|
|
|
|||
|
|
@ -752,16 +752,6 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
|
|||
/* Otherwise render the trapezoids to a mask and composite in the usual
|
||||
* fashion.
|
||||
*/
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_int_t trap_extents;
|
||||
cairo_box_t trap_box;
|
||||
|
||||
_cairo_traps_extents (traps, &trap_box);
|
||||
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
|
||||
if (! _cairo_rectangle_intersect (extents, &trap_extents))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
traps_info.traps = traps;
|
||||
traps_info.antialias = antialias;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@
|
|||
|
||||
/* private functions */
|
||||
|
||||
static int
|
||||
_compare_point_fixed_by_y (const void *av, const void *bv);
|
||||
|
||||
void
|
||||
_cairo_traps_init (cairo_traps_t *traps)
|
||||
{
|
||||
|
|
@ -59,8 +56,6 @@ _cairo_traps_init (cairo_traps_t *traps)
|
|||
|
||||
traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
|
||||
traps->traps = traps->traps_embedded;
|
||||
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
|
||||
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
|
||||
|
||||
traps->has_limits = FALSE;
|
||||
traps->has_intersections = FALSE;
|
||||
|
|
@ -84,8 +79,6 @@ _cairo_traps_clear (cairo_traps_t *traps)
|
|||
|
||||
traps->num_traps = 0;
|
||||
traps->has_intersections = FALSE;
|
||||
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
|
||||
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -124,8 +117,6 @@ _cairo_traps_init_box (cairo_traps_t *traps,
|
|||
traps->traps[0].right.p1.x = box->p2.x;
|
||||
traps->traps[0].right.p1.y = box->p1.y;
|
||||
traps->traps[0].right.p2 = box->p2;
|
||||
|
||||
traps->extents = *box;
|
||||
}
|
||||
|
||||
/* make room for at least one more trap */
|
||||
|
|
@ -159,12 +150,6 @@ _cairo_traps_grow (cairo_traps_t *traps)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_fixed_t
|
||||
_line_compute_intersection_x_for_y (const cairo_line_t *line,
|
||||
cairo_fixed_t y)
|
||||
{
|
||||
return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y);
|
||||
}
|
||||
void
|
||||
_cairo_traps_add_trap (cairo_traps_t *traps,
|
||||
cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
|
|
@ -172,37 +157,55 @@ _cairo_traps_add_trap (cairo_traps_t *traps,
|
|||
{
|
||||
cairo_trapezoid_t *trap;
|
||||
|
||||
/* Note: With the goofy trapezoid specification, (where an
|
||||
* arbitrary two points on the lines can specified for the left
|
||||
* and right edges), these limit checks would not work in
|
||||
* general. For example, one can imagine a trapezoid entirely
|
||||
* within the limits, but with two points used to specify the left
|
||||
* edge entirely to the right of the limits. Fortunately, for our
|
||||
* purposes, cairo will never generate such a crazy
|
||||
* trapezoid. Instead, cairo always uses for its points the
|
||||
* extreme positions of the edge that are visible on at least some
|
||||
* trapezoid. With this constraint, it's impossible for both
|
||||
* points to be outside the limits while the relevant edge is
|
||||
* entirely inside the limits.
|
||||
*/
|
||||
assert (top < bottom);
|
||||
|
||||
if (traps->num_traps == traps->traps_size) {
|
||||
if (! _cairo_traps_grow (traps))
|
||||
return;
|
||||
}
|
||||
|
||||
trap = &traps->traps[traps->num_traps++];
|
||||
trap->top = top;
|
||||
trap->bottom = bottom;
|
||||
trap->left = *left;
|
||||
trap->right = *right;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
|
||||
const cairo_point_t *top_left,
|
||||
const cairo_point_t *bottom_right)
|
||||
{
|
||||
cairo_line_t left;
|
||||
cairo_line_t right;
|
||||
cairo_fixed_t top, bottom;
|
||||
|
||||
left.p1.x = left.p2.x = top_left->x;
|
||||
left.p1.y = right.p1.y = top_left->y;
|
||||
right.p1.x = right.p2.x = bottom_right->x;
|
||||
left.p2.y = right.p2.y = bottom_right->y;
|
||||
|
||||
top = top_left->y;
|
||||
bottom = bottom_right->y;
|
||||
|
||||
if (traps->has_limits) {
|
||||
/* Trivially reject if trapezoid is entirely to the right or
|
||||
* to the left of the limits. */
|
||||
if (left->p1.x >= traps->limits.p2.x &&
|
||||
left->p2.x >= traps->limits.p2.x)
|
||||
if (left.p1.x >= traps->limits.p2.x &&
|
||||
left.p2.x >= traps->limits.p2.x)
|
||||
{
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (right->p1.x <= traps->limits.p1.x &&
|
||||
right->p2.x <= traps->limits.p1.x)
|
||||
if (right.p1.x <= traps->limits.p1.x &&
|
||||
right.p2.x <= traps->limits.p1.x)
|
||||
{
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* And reject if the trapezoid is entirely above or below */
|
||||
if (top > traps->limits.p2.y || bottom < traps->limits.p1.y)
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* Otherwise, clip the trapezoid to the limits. We only clip
|
||||
* where an edge is entirely outside the limits. If we wanted
|
||||
|
|
@ -216,98 +219,34 @@ _cairo_traps_add_trap (cairo_traps_t *traps,
|
|||
if (bottom > traps->limits.p2.y)
|
||||
bottom = traps->limits.p2.y;
|
||||
|
||||
if (left->p1.x <= traps->limits.p1.x &&
|
||||
left->p2.x <= traps->limits.p1.x)
|
||||
if (left.p1.x <= traps->limits.p1.x &&
|
||||
left.p2.x <= traps->limits.p1.x)
|
||||
{
|
||||
left->p1.x = traps->limits.p1.x;
|
||||
left->p2.x = traps->limits.p1.x;
|
||||
left.p1.x = traps->limits.p1.x;
|
||||
left.p1.y = traps->limits.p1.y;
|
||||
left.p2.x = traps->limits.p1.x;
|
||||
left.p2.y = traps->limits.p2.y;
|
||||
}
|
||||
|
||||
if (right->p1.x >= traps->limits.p2.x &&
|
||||
right->p2.x >= traps->limits.p2.x)
|
||||
if (right.p1.x >= traps->limits.p2.x &&
|
||||
right.p2.x >= traps->limits.p2.x)
|
||||
{
|
||||
right->p1.x = traps->limits.p2.x;
|
||||
right->p2.x = traps->limits.p2.x;
|
||||
right.p1.x = traps->limits.p2.x;
|
||||
right.p1.y = traps->limits.p1.y;
|
||||
right.p2.x = traps->limits.p2.x;
|
||||
right.p2.y = traps->limits.p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Trivial discards for empty trapezoids that are likely to be produced
|
||||
* by our tessellators (most notably convex_quad when given a simple
|
||||
* rectangle).
|
||||
*/
|
||||
if (top >= bottom)
|
||||
return;
|
||||
/* cheap colinearity check */
|
||||
if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y &&
|
||||
right->p2.x <= left->p2.x && right->p2.y == left->p2.y)
|
||||
return;
|
||||
if (top == bottom)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (traps->num_traps == traps->traps_size) {
|
||||
if (! _cairo_traps_grow (traps))
|
||||
return;
|
||||
}
|
||||
if (left.p1.x == right.p1.x)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
trap = &traps->traps[traps->num_traps];
|
||||
trap->top = top;
|
||||
trap->bottom = bottom;
|
||||
trap->left = *left;
|
||||
trap->right = *right;
|
||||
_cairo_traps_add_trap (traps, top, bottom, &left, &right);
|
||||
|
||||
if (top < traps->extents.p1.y)
|
||||
traps->extents.p1.y = top;
|
||||
if (bottom > traps->extents.p2.y)
|
||||
traps->extents.p2.y = bottom;
|
||||
|
||||
if (left->p1.x < traps->extents.p1.x) {
|
||||
cairo_fixed_t x = left->p1.x;
|
||||
if (top != left->p1.y) {
|
||||
x = _line_compute_intersection_x_for_y (left, top);
|
||||
if (x < traps->extents.p1.x)
|
||||
traps->extents.p1.x = x;
|
||||
} else
|
||||
traps->extents.p1.x = x;
|
||||
}
|
||||
if (left->p2.x < traps->extents.p1.x) {
|
||||
cairo_fixed_t x = left->p2.x;
|
||||
if (bottom != left->p2.y) {
|
||||
x = _line_compute_intersection_x_for_y (left, bottom);
|
||||
if (x < traps->extents.p1.x)
|
||||
traps->extents.p1.x = x;
|
||||
} else
|
||||
traps->extents.p1.x = x;
|
||||
}
|
||||
|
||||
if (right->p1.x > traps->extents.p2.x) {
|
||||
cairo_fixed_t x = right->p1.x;
|
||||
if (top != right->p1.y) {
|
||||
x = _line_compute_intersection_x_for_y (right, top);
|
||||
if (x > traps->extents.p2.x)
|
||||
traps->extents.p2.x = x;
|
||||
} else
|
||||
traps->extents.p2.x = x;
|
||||
}
|
||||
if (right->p2.x > traps->extents.p2.x) {
|
||||
cairo_fixed_t x = right->p2.x;
|
||||
if (bottom != right->p2.y) {
|
||||
x = _line_compute_intersection_x_for_y (right, bottom);
|
||||
if (x > traps->extents.p2.x)
|
||||
traps->extents.p2.x = x;
|
||||
} else
|
||||
traps->extents.p2.x = x;
|
||||
}
|
||||
|
||||
traps->num_traps++;
|
||||
}
|
||||
|
||||
static int
|
||||
_compare_point_fixed_by_y (const void *av, const void *bv)
|
||||
{
|
||||
const cairo_point_t *a = av, *b = bv;
|
||||
|
||||
int ret = a->y - b->y;
|
||||
if (ret == 0)
|
||||
ret = a->x - b->x;
|
||||
return ret;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -382,184 +321,6 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
|
|||
}
|
||||
}
|
||||
|
||||
/* A triangle is simply a degenerate case of a convex
|
||||
* quadrilateral. We would not benefit from having any distinct
|
||||
* implementation of triangle vs. quadrilateral tessellation here. */
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
|
||||
const cairo_point_t t[3])
|
||||
{
|
||||
cairo_point_t quad[4];
|
||||
|
||||
quad[0] = t[0];
|
||||
quad[1] = t[0];
|
||||
quad[2] = t[1];
|
||||
quad[3] = t[2];
|
||||
|
||||
return _cairo_traps_tessellate_convex_quad (traps, quad);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
|
||||
const cairo_point_t *top_left,
|
||||
const cairo_point_t *bottom_right)
|
||||
{
|
||||
cairo_line_t left;
|
||||
cairo_line_t right;
|
||||
|
||||
left.p1.x = left.p2.x = top_left->x;
|
||||
left.p1.y = right.p1.y = top_left->y;
|
||||
right.p1.x = right.p2.x = bottom_right->x;
|
||||
left.p2.y = right.p2.y = bottom_right->y;
|
||||
|
||||
_cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
|
||||
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
|
||||
const cairo_point_t q[4])
|
||||
{
|
||||
int a, b, c, d;
|
||||
int i;
|
||||
cairo_slope_t ab, ad;
|
||||
cairo_bool_t b_left_of_d;
|
||||
cairo_line_t left;
|
||||
cairo_line_t right;
|
||||
|
||||
/* 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
|
||||
*/
|
||||
left.p1 = q[a]; left.p2 = q[b];
|
||||
right.p1 = q[a]; right.p2 = q[d];
|
||||
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||
left.p1 = q[b]; left.p2 = q[c];
|
||||
_cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
|
||||
left.p1 = q[c]; left.p2 = q[d];
|
||||
_cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
|
||||
} 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
|
||||
*/
|
||||
left.p1 = q[a]; left.p2 = q[d];
|
||||
right.p1 = q[a]; right.p2 = q[b];
|
||||
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||
right.p1 = q[b]; right.p2 = q[c];
|
||||
_cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
|
||||
right.p1 = q[c]; right.p2 = q[d];
|
||||
_cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
|
||||
}
|
||||
} 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
|
||||
*/
|
||||
left.p1 = q[a]; left.p2 = q[b];
|
||||
right.p1 = q[a]; right.p2 = q[d];
|
||||
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||
left.p1 = q[b]; left.p2 = q[c];
|
||||
_cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
|
||||
right.p1 = q[d]; right.p2 = q[c];
|
||||
_cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
|
||||
} 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
|
||||
*/
|
||||
left.p1 = q[a]; left.p2 = q[d];
|
||||
right.p1 = q[a]; right.p2 = q[b];
|
||||
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||
right.p1 = q[b]; right.p2 = q[c];
|
||||
_cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
|
||||
left.p1 = q[d]; left.p2 = q[c];
|
||||
_cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
|
||||
}
|
||||
}
|
||||
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
|
||||
{
|
||||
|
|
@ -603,30 +364,81 @@ _cairo_traps_contain (const cairo_traps_t *traps,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_fixed_t
|
||||
_line_compute_intersection_x_for_y (const cairo_line_t *line,
|
||||
cairo_fixed_t y)
|
||||
{
|
||||
return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_traps_extents (const cairo_traps_t *traps,
|
||||
cairo_box_t *extents)
|
||||
cairo_box_t *extents)
|
||||
{
|
||||
if (traps->num_traps == 0) {
|
||||
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
|
||||
extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
|
||||
} else {
|
||||
*extents = traps->extents;
|
||||
if (traps->has_limits) {
|
||||
/* clip the traps to the imposed limits */
|
||||
if (extents->p1.x < traps->limits.p1.x)
|
||||
extents->p1.x = traps->limits.p1.x;
|
||||
if (extents->p2.x > traps->limits.p2.x)
|
||||
extents->p2.x = traps->limits.p2.x;
|
||||
int i;
|
||||
|
||||
if (extents->p1.y < traps->limits.p1.y)
|
||||
extents->p1.y = traps->limits.p1.y;
|
||||
if (extents->p2.y > traps->limits.p2.y)
|
||||
extents->p2.y = traps->limits.p2.y;
|
||||
if (traps->num_traps == 0) {
|
||||
extents->p1.x = extents->p1.y = 0;
|
||||
extents->p2.x = extents->p2.y = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
extents->p1.x = extents->p1.y = INT32_MAX;
|
||||
extents->p2.x = extents->p2.y = INT32_MIN;
|
||||
|
||||
for (i = 0; i < traps->num_traps; i++) {
|
||||
const cairo_trapezoid_t *trap = &traps->traps[i];
|
||||
|
||||
if (trap->top < extents->p1.y)
|
||||
extents->p1.y = trap->top;
|
||||
if (trap->bottom > extents->p2.y)
|
||||
extents->p2.y = trap->bottom;
|
||||
|
||||
if (trap->left.p1.x < extents->p1.x) {
|
||||
cairo_fixed_t x = trap->left.p1.x;
|
||||
if (trap->top != trap->left.p1.y) {
|
||||
x = _line_compute_intersection_x_for_y (&trap->left,
|
||||
trap->top);
|
||||
if (x < extents->p1.x)
|
||||
extents->p1.x = x;
|
||||
} else
|
||||
extents->p1.x = x;
|
||||
}
|
||||
if (trap->left.p2.x < extents->p1.x) {
|
||||
cairo_fixed_t x = trap->left.p2.x;
|
||||
if (trap->bottom != trap->left.p2.y) {
|
||||
x = _line_compute_intersection_x_for_y (&trap->left,
|
||||
trap->bottom);
|
||||
if (x < extents->p1.x)
|
||||
extents->p1.x = x;
|
||||
} else
|
||||
extents->p1.x = x;
|
||||
}
|
||||
|
||||
if (trap->right.p1.x > extents->p2.x) {
|
||||
cairo_fixed_t x = trap->right.p1.x;
|
||||
if (trap->top != trap->right.p1.y) {
|
||||
x = _line_compute_intersection_x_for_y (&trap->right,
|
||||
trap->top);
|
||||
if (x > extents->p2.x)
|
||||
extents->p2.x = x;
|
||||
} else
|
||||
extents->p2.x = x;
|
||||
}
|
||||
if (trap->right.p2.x > extents->p2.x) {
|
||||
cairo_fixed_t x = trap->right.p2.x;
|
||||
if (trap->bottom != trap->right.p2.y) {
|
||||
x = _line_compute_intersection_x_for_y (&trap->right,
|
||||
trap->bottom);
|
||||
if (x > extents->p2.x)
|
||||
extents->p2.x = x;
|
||||
} else
|
||||
extents->p2.x = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_traps_extract_region:
|
||||
* @traps: a #cairo_traps_t
|
||||
|
|
@ -684,8 +496,8 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
|
|||
/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
|
||||
* skip these.
|
||||
*/
|
||||
if (x1 == x2 || y1 == y2)
|
||||
continue;
|
||||
assert (x1 != x2);
|
||||
assert (y1 != y2);
|
||||
|
||||
rects[rect_count].x = x1;
|
||||
rects[rect_count].y = y1;
|
||||
|
|
@ -712,7 +524,7 @@ _sanitize_trap (cairo_trapezoid_t *t)
|
|||
|
||||
#define FIX(lr, tb, p) \
|
||||
if (t->lr.p.y != t->tb) { \
|
||||
t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \
|
||||
t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div_floor (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \
|
||||
t->lr.p.y = s.tb; \
|
||||
}
|
||||
FIX (left, top, p1);
|
||||
|
|
|
|||
|
|
@ -951,7 +951,6 @@ typedef struct _cairo_surface_attributes {
|
|||
typedef struct _cairo_traps {
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_box_t extents;
|
||||
cairo_box_t limits;
|
||||
|
||||
unsigned int maybe_region : 1; /* hint: 0 implies that it cannot be */
|
||||
|
|
@ -2364,14 +2363,6 @@ _cairo_traps_fini (cairo_traps_t *traps);
|
|||
cairo_private void
|
||||
_cairo_traps_translate (cairo_traps_t *traps, int x, int y);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
|
||||
const cairo_point_t t[3]);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
|
||||
const cairo_point_t q[4]);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
|
||||
const cairo_point_t *top_left,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue