Changes.
[cairo/gpu.git] / src / cairo-traps.c
blobd8464cc88dd2622fb48a419059015f81575cf8f3
1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /*
3 * Copyright © 2002 Keith Packard
4 * Copyright © 2007 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Keith Packard
33 * Contributor(s):
34 * Keith R. Packard <keithp@keithp.com>
35 * Carl D. Worth <cworth@cworth.org>
37 * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth
40 #include "cairoint.h"
42 /* private functions */
44 static int
45 _compare_point_fixed_by_y (const void *av, const void *bv);
47 void
48 _cairo_traps_init (cairo_traps_t *traps)
50 VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
52 traps->status = CAIRO_STATUS_SUCCESS;
54 traps->num_traps = 0;
56 traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
57 traps->traps = traps->traps_embedded;
58 traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
59 traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
61 traps->has_limits = FALSE;
64 void
65 _cairo_traps_limit (cairo_traps_t *traps,
66 cairo_box_t *limits)
68 traps->has_limits = TRUE;
70 traps->limits = *limits;
73 cairo_bool_t
74 _cairo_traps_get_limit (cairo_traps_t *traps,
75 cairo_box_t *limits)
77 *limits = traps->limits;
78 return traps->has_limits;
81 void
82 _cairo_traps_clear (cairo_traps_t *traps)
84 traps->status = CAIRO_STATUS_SUCCESS;
86 traps->num_traps = 0;
87 traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
88 traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
91 void
92 _cairo_traps_fini (cairo_traps_t *traps)
94 if (traps->traps != traps->traps_embedded)
95 free (traps->traps);
97 VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
101 * _cairo_traps_init_box:
102 * @traps: a #cairo_traps_t
103 * @box: a box that will be converted to a single trapezoid
104 * to store in @traps.
106 * Initializes a #cairo_traps_t to contain a single rectangular
107 * trapezoid.
109 void
110 _cairo_traps_init_box (cairo_traps_t *traps,
111 const cairo_box_t *box)
113 _cairo_traps_init (traps);
115 assert (traps->traps_size >= 1);
117 traps->num_traps = 1;
119 traps->traps[0].top = box->p1.y;
120 traps->traps[0].bottom = box->p2.y;
121 traps->traps[0].left.p1 = box->p1;
122 traps->traps[0].left.p2.x = box->p1.x;
123 traps->traps[0].left.p2.y = box->p2.y;
124 traps->traps[0].right.p1.x = box->p2.x;
125 traps->traps[0].right.p1.y = box->p1.y;
126 traps->traps[0].right.p2 = box->p2;
128 traps->extents = *box;
131 /* make room for at least one more trap */
132 static cairo_bool_t
133 _cairo_traps_grow (cairo_traps_t *traps)
135 cairo_trapezoid_t *new_traps;
136 int new_size = 2 * MAX (traps->traps_size, 16);
138 if (CAIRO_INJECT_FAULT ()) {
139 traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
140 return FALSE;
143 if (traps->traps == traps->traps_embedded) {
144 new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
145 if (new_traps != NULL)
146 memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
147 } else {
148 new_traps = _cairo_realloc_ab (traps->traps,
149 new_size, sizeof (cairo_trapezoid_t));
152 if (unlikely (new_traps == NULL)) {
153 traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
154 return FALSE;
157 traps->traps = new_traps;
158 traps->traps_size = new_size;
159 return TRUE;
162 void
163 _cairo_traps_add_trap (cairo_traps_t *traps,
164 cairo_fixed_t top, cairo_fixed_t bottom,
165 cairo_line_t *left, cairo_line_t *right)
167 cairo_trapezoid_t *trap;
169 /* Note: With the goofy trapezoid specification, (where an
170 * arbitrary two points on the lines can specified for the left
171 * and right edges), these limit checks would not work in
172 * general. For example, one can imagine a trapezoid entirely
173 * within the limits, but with two points used to specify the left
174 * edge entirely to the right of the limits. Fortunately, for our
175 * purposes, cairo will never generate such a crazy
176 * trapezoid. Instead, cairo always uses for its points the
177 * extreme positions of the edge that are visible on at least some
178 * trapezoid. With this constraint, it's impossible for both
179 * points to be outside the limits while the relevant edge is
180 * entirely inside the limits.
182 if (traps->has_limits) {
183 /* Trivially reject if trapezoid is entirely to the right or
184 * to the left of the limits. */
185 if (left->p1.x >= traps->limits.p2.x &&
186 left->p2.x >= traps->limits.p2.x)
188 return;
191 if (right->p1.x <= traps->limits.p1.x &&
192 right->p2.x <= traps->limits.p1.x)
194 return;
197 /* And reject if the trapezoid is entirely above or below */
198 if (top > traps->limits.p2.y || bottom < traps->limits.p1.y)
199 return;
201 /* Otherwise, clip the trapezoid to the limits. We only clip
202 * where an edge is entirely outside the limits. If we wanted
203 * to be more clever, we could handle cases where a trapezoid
204 * edge intersects the edge of the limits, but that would
205 * require slicing this trapezoid into multiple trapezoids,
206 * and I'm not sure the effort would be worth it. */
207 if (top < traps->limits.p1.y)
208 top = traps->limits.p1.y;
210 if (bottom > traps->limits.p2.y)
211 bottom = traps->limits.p2.y;
213 if (left->p1.x <= traps->limits.p1.x &&
214 left->p2.x <= traps->limits.p1.x)
216 left->p1.x = traps->limits.p1.x;
217 left->p2.x = traps->limits.p1.x;
220 if (right->p1.x >= traps->limits.p2.x &&
221 right->p2.x >= traps->limits.p2.x)
223 right->p1.x = traps->limits.p2.x;
224 right->p2.x = traps->limits.p2.x;
228 /* Trivial discards for empty trapezoids that are likely to be produced
229 * by our tessellators (most notably convex_quad when given a simple
230 * rectangle).
232 if (top >= bottom)
233 return;
234 /* cheap colinearity check */
235 if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y &&
236 right->p2.x <= left->p2.x && right->p2.y == left->p2.y)
237 return;
239 if (traps->num_traps == traps->traps_size) {
240 if (! _cairo_traps_grow (traps))
241 return;
244 trap = &traps->traps[traps->num_traps];
245 trap->top = top;
246 trap->bottom = bottom;
247 trap->left = *left;
248 trap->right = *right;
250 if (top < traps->extents.p1.y)
251 traps->extents.p1.y = top;
252 if (bottom > traps->extents.p2.y)
253 traps->extents.p2.y = bottom;
255 * This isn't generally accurate, but it is close enough for
256 * this purpose. Assuming that the left and right segments always
257 * contain the trapezoid vertical extents, these compares will
258 * yield a containing box. Assuming that the points all come from
259 * the same figure which will eventually be completely drawn, then
260 * the compares will yield the correct overall extents
262 if (left->p1.x < traps->extents.p1.x)
263 traps->extents.p1.x = left->p1.x;
264 if (left->p2.x < traps->extents.p1.x)
265 traps->extents.p1.x = left->p2.x;
267 if (right->p1.x > traps->extents.p2.x)
268 traps->extents.p2.x = right->p1.x;
269 if (right->p2.x > traps->extents.p2.x)
270 traps->extents.p2.x = right->p2.x;
272 traps->num_traps++;
275 static int
276 _compare_point_fixed_by_y (const void *av, const void *bv)
278 const cairo_point_t *a = av, *b = bv;
280 int ret = a->y - b->y;
281 if (ret == 0) {
282 ret = a->x - b->x;
284 return ret;
287 void
288 _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
290 cairo_fixed_t xoff, yoff;
291 cairo_trapezoid_t *t;
292 int i;
294 /* Ugh. The cairo_composite/(Render) interface doesn't allow
295 an offset for the trapezoids. Need to manually shift all
296 the coordinates to align with the offset origin of the
297 intermediate surface. */
299 xoff = _cairo_fixed_from_int (x);
300 yoff = _cairo_fixed_from_int (y);
302 for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
303 t->top += yoff;
304 t->bottom += yoff;
305 t->left.p1.x += xoff;
306 t->left.p1.y += yoff;
307 t->left.p2.x += xoff;
308 t->left.p2.y += yoff;
309 t->right.p1.x += xoff;
310 t->right.p1.y += yoff;
311 t->right.p2.x += xoff;
312 t->right.p2.y += yoff;
316 void
317 _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
318 cairo_trapezoid_t *src_traps,
319 int num_traps,
320 double tx, double ty,
321 double sx, double sy)
323 int i;
324 cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
325 cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
327 if (sx == 1.0 && sy == 1.0) {
328 for (i = 0; i < num_traps; i++) {
329 offset_traps[i].top = src_traps[i].top + yoff;
330 offset_traps[i].bottom = src_traps[i].bottom + yoff;
331 offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
332 offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
333 offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
334 offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
335 offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
336 offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
337 offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
338 offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
340 } else {
341 cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
342 cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
344 for (i = 0; i < num_traps; i++) {
345 offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
346 offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
347 offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
348 offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
349 offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
350 offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
351 offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
352 offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
353 offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
354 offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
359 /* A triangle is simply a degenerate case of a convex
360 * quadrilateral. We would not benefit from having any distinct
361 * implementation of triangle vs. quadrilateral tessellation here. */
362 cairo_status_t
363 _cairo_traps_tessellate_triangle (cairo_traps_t *traps,
364 const cairo_point_t t[3])
366 cairo_point_t quad[4];
368 quad[0] = t[0];
369 quad[1] = t[0];
370 quad[2] = t[1];
371 quad[3] = t[2];
373 return _cairo_traps_tessellate_convex_quad (traps, quad);
376 cairo_status_t
377 _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
378 const cairo_point_t *top_left,
379 const cairo_point_t *bottom_right)
381 cairo_line_t left;
382 cairo_line_t right;
384 left.p1.x = left.p2.x = top_left->x;
385 left.p1.y = right.p1.y = top_left->y;
386 right.p1.x = right.p2.x = bottom_right->x;
387 left.p2.y = right.p2.y = bottom_right->y;
389 _cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
391 return traps->status;
394 cairo_status_t
395 _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
396 const cairo_point_t q[4])
398 int a, b, c, d;
399 int i;
400 cairo_slope_t ab, ad;
401 cairo_bool_t b_left_of_d;
402 cairo_line_t left;
403 cairo_line_t right;
405 /* Choose a as a point with minimal y */
406 a = 0;
407 for (i = 1; i < 4; i++)
408 if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
409 a = i;
411 /* b and d are adjacent to a, while c is opposite */
412 b = (a + 1) % 4;
413 c = (a + 2) % 4;
414 d = (a + 3) % 4;
416 /* Choose between b and d so that b.y is less than d.y */
417 if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
418 b = (a + 3) % 4;
419 d = (a + 1) % 4;
422 /* Without freedom left to choose anything else, we have four
423 * cases to tessellate.
425 * First, we have to determine the Y-axis sort of the four
426 * vertices, (either abcd or abdc). After that we need to detemine
427 * which edges will be "left" and which will be "right" in the
428 * resulting trapezoids. This can be determined by computing a
429 * slope comparison of ab and ad to determine if b is left of d or
430 * not.
432 * Note that "left of" here is in the sense of which edges should
433 * be the left vs. right edges of the trapezoid. In particular, b
434 * left of d does *not* mean that b.x is less than d.x.
436 * This should hopefully be made clear in the lame ASCII art
437 * below. Since the same slope comparison is used in all cases, we
438 * compute it before testing for the Y-value sort. */
440 /* Note: If a == b then the ab slope doesn't give us any
441 * information. In that case, we can replace it with the ac (or
442 * equivalenly the bc) slope which gives us exactly the same
443 * information we need. At worst the names of the identifiers ab
444 * and b_left_of_d are inaccurate in this case, (would be ac, and
445 * c_left_of_d). */
446 if (q[a].x == q[b].x && q[a].y == q[b].y)
447 _cairo_slope_init (&ab, &q[a], &q[c]);
448 else
449 _cairo_slope_init (&ab, &q[a], &q[b]);
451 _cairo_slope_init (&ad, &q[a], &q[d]);
453 b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0);
455 if (q[c].y <= q[d].y) {
456 if (b_left_of_d) {
457 /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
459 * top bot left right
460 * _a a a
461 * / / /| |\ a.y b.y ab ad
462 * b / b | b \
463 * / / | | \ \ b.y c.y bc ad
464 * c / c | c \
465 * | / \| \ \ c.y d.y cd ad
466 * d d d
468 left.p1 = q[a]; left.p2 = q[b];
469 right.p1 = q[a]; right.p2 = q[d];
470 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
471 left.p1 = q[b]; left.p2 = q[c];
472 _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
473 left.p1 = q[c]; left.p2 = q[d];
474 _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
475 } else {
476 /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
478 * a a a_
479 * /| |\ \ \ a.y b.y ad ab
480 * / b | b \ b
481 * / / | | \ \ b.y c.y ad bc
482 * / c | c \ c
483 * / / |/ \ | c.y d.y ad cd
484 * d d d
486 left.p1 = q[a]; left.p2 = q[d];
487 right.p1 = q[a]; right.p2 = q[b];
488 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
489 right.p1 = q[b]; right.p2 = q[c];
490 _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
491 right.p1 = q[c]; right.p2 = q[d];
492 _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
494 } else {
495 if (b_left_of_d) {
496 /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
498 * a a a
499 * // / \ |\ a.y b.y ab ad
500 * /b/ b \ b \
501 * / / \ \ \ \ b.y d.y bc ad
502 * /d/ \ d \ d
503 * // \ / \| d.y c.y bc dc
504 * c c c
506 left.p1 = q[a]; left.p2 = q[b];
507 right.p1 = q[a]; right.p2 = q[d];
508 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
509 left.p1 = q[b]; left.p2 = q[c];
510 _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
511 right.p1 = q[d]; right.p2 = q[c];
512 _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
513 } else {
514 /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
516 * a a a
517 * /| / \ \\ a.y b.y ad ab
518 * / b / b \b\
519 * / / / / \ \ b.y d.y ad bc
520 * d / d / \d\
521 * |/ \ / \\ d.y c.y dc bc
522 * c c c
524 left.p1 = q[a]; left.p2 = q[d];
525 right.p1 = q[a]; right.p2 = q[b];
526 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
527 right.p1 = q[b]; right.p2 = q[c];
528 _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
529 left.p1 = q[d]; left.p2 = q[c];
530 _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
534 return traps->status;
537 static cairo_bool_t
538 _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
540 cairo_slope_t slope_left, slope_pt, slope_right;
542 if (t->top > pt->y)
543 return FALSE;
544 if (t->bottom < pt->y)
545 return FALSE;
547 _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
548 _cairo_slope_init (&slope_pt, &t->left.p1, pt);
550 if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
551 return FALSE;
553 _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
554 _cairo_slope_init (&slope_pt, &t->right.p1, pt);
556 if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
557 return FALSE;
559 return TRUE;
562 cairo_bool_t
563 _cairo_traps_contain (const cairo_traps_t *traps,
564 double x, double y)
566 int i;
567 cairo_point_t point;
569 point.x = _cairo_fixed_from_double (x);
570 point.y = _cairo_fixed_from_double (y);
572 for (i = 0; i < traps->num_traps; i++) {
573 if (_cairo_trap_contains (&traps->traps[i], &point))
574 return TRUE;
577 return FALSE;
580 void
581 _cairo_traps_extents (const cairo_traps_t *traps,
582 cairo_box_t *extents)
584 if (traps->num_traps == 0) {
585 extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
586 extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
587 } else {
588 *extents = traps->extents;
589 if (traps->has_limits) {
590 /* clip the traps to the imposed limits */
591 if (extents->p1.x < traps->limits.p1.x)
592 extents->p1.x = traps->limits.p1.x;
593 if (extents->p2.x > traps->limits.p2.x)
594 extents->p2.x = traps->limits.p2.x;
596 if (extents->p1.y < traps->limits.p1.y)
597 extents->p1.y = traps->limits.p1.y;
598 if (extents->p2.y > traps->limits.p2.y)
599 extents->p2.y = traps->limits.p2.y;
605 * _cairo_traps_extract_region:
606 * @traps: a #cairo_traps_t
607 * @region: a #cairo_region_t
609 * Determines if a set of trapezoids are exactly representable as a
610 * cairo region. If so, the passed-in region is initialized to
611 * the area representing the given traps. It should be finalized
612 * with cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
613 * is returned.
615 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
616 * or %CAIRO_STATUS_NO_MEMORY
618 cairo_int_status_t
619 _cairo_traps_extract_region (const cairo_traps_t *traps,
620 cairo_region_t **region)
622 cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
623 cairo_rectangle_int_t *rects = stack_rects;
624 cairo_int_status_t status;
625 int i, rect_count;
627 for (i = 0; i < traps->num_traps; i++) {
628 if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
629 traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
630 ! _cairo_fixed_is_integer (traps->traps[i].top) ||
631 ! _cairo_fixed_is_integer (traps->traps[i].bottom) ||
632 ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) ||
633 ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
635 return CAIRO_INT_STATUS_UNSUPPORTED;
639 if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
640 rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
642 if (unlikely (rects == NULL))
643 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
646 rect_count = 0;
647 for (i = 0; i < traps->num_traps; i++) {
648 int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
649 int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
650 int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
651 int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
653 /* XXX: Sometimes we get degenerate trapezoids from the tesellator;
654 * skip these.
656 if (x1 == x2 || y1 == y2)
657 continue;
659 rects[rect_count].x = x1;
660 rects[rect_count].y = y1;
661 rects[rect_count].width = x2 - x1;
662 rects[rect_count].height = y2 - y1;
664 rect_count++;
667 *region = cairo_region_create_rectangles (rects, rect_count);
668 status = cairo_region_status (*region);
670 if (rects != stack_rects)
671 free (rects);
673 if (unlikely (status)) {
674 cairo_region_destroy (*region);
675 *region = NULL;
678 return status;
681 /* moves trap points such that they become the actual corners of the trapezoid */
682 static void
683 _sanitize_trap (cairo_trapezoid_t *t)
685 cairo_trapezoid_t s = *t;
687 #define FIX(lr, tb, p) \
688 if (t->lr.p.y != t->tb) { \
689 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); \
690 t->lr.p.y = s.tb; \
692 FIX (left, top, p1);
693 FIX (left, bottom, p2);
694 FIX (right, top, p1);
695 FIX (right, bottom, p2);
698 cairo_private cairo_status_t
699 _cairo_traps_path (const cairo_traps_t *traps,
700 cairo_path_fixed_t *path)
702 int i;
704 for (i = 0; i < traps->num_traps; i++) {
705 cairo_status_t status;
706 cairo_trapezoid_t trap = traps->traps[i];
708 if (trap.top == trap.bottom)
709 continue;
711 _sanitize_trap (&trap);
713 status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
714 if (unlikely (status)) return status;
715 status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
716 if (unlikely (status)) return status;
717 status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
718 if (unlikely (status)) return status;
719 status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
720 if (unlikely (status)) return status;
721 status = _cairo_path_fixed_close_path (path);
722 if (unlikely (status)) return status;
725 return CAIRO_STATUS_SUCCESS;