in class/System.Windows/System.Windows/:
[moon.git] / cairo / src / cairo-traps.c
blobb76e9089cd05a34d31f4fb65eed7b9477cf8a3b4
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 traps->status = CAIRO_STATUS_SUCCESS;
52 traps->num_traps = 0;
54 traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
55 traps->traps = traps->traps_embedded;
56 traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
57 traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
59 traps->has_limits = FALSE;
62 void
63 _cairo_traps_limit (cairo_traps_t *traps,
64 cairo_box_t *limits)
66 traps->has_limits = TRUE;
68 traps->limits = *limits;
71 cairo_bool_t
72 _cairo_traps_get_limit (cairo_traps_t *traps,
73 cairo_box_t *limits)
75 *limits = traps->limits;
76 return traps->has_limits;
79 void
80 _cairo_traps_clear (cairo_traps_t *traps)
82 traps->status = CAIRO_STATUS_SUCCESS;
84 traps->num_traps = 0;
85 traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
86 traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
89 void
90 _cairo_traps_fini (cairo_traps_t *traps)
92 if (traps->traps != traps->traps_embedded)
93 free (traps->traps);
96 /**
97 * _cairo_traps_init_box:
98 * @traps: a #cairo_traps_t
99 * @box: a box that will be converted to a single trapezoid
100 * to store in @traps.
102 * Initializes a #cairo_traps_t to contain a single rectangular
103 * trapezoid.
105 void
106 _cairo_traps_init_box (cairo_traps_t *traps,
107 const cairo_box_t *box)
109 _cairo_traps_init (traps);
111 assert (traps->traps_size >= 1);
113 traps->num_traps = 1;
115 traps->traps[0].top = box->p1.y;
116 traps->traps[0].bottom = box->p2.y;
117 traps->traps[0].left.p1 = box->p1;
118 traps->traps[0].left.p2.x = box->p1.x;
119 traps->traps[0].left.p2.y = box->p2.y;
120 traps->traps[0].right.p1.x = box->p2.x;
121 traps->traps[0].right.p1.y = box->p1.y;
122 traps->traps[0].right.p2 = box->p2;
124 traps->extents = *box;
127 /* make room for at least one more trap */
128 static cairo_bool_t
129 _cairo_traps_grow (cairo_traps_t *traps)
131 cairo_trapezoid_t *new_traps;
132 int new_size = 2 * MAX (traps->traps_size, 16);
134 if (traps->traps == traps->traps_embedded) {
135 new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
136 if (new_traps != NULL)
137 memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
138 } else {
139 new_traps = _cairo_realloc_ab (traps->traps,
140 new_size, sizeof (cairo_trapezoid_t));
143 if (new_traps == NULL) {
144 traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
145 return FALSE;
148 traps->traps = new_traps;
149 traps->traps_size = new_size;
150 return TRUE;
153 void
154 _cairo_traps_add_trap (cairo_traps_t *traps,
155 cairo_fixed_t top, cairo_fixed_t bottom,
156 cairo_line_t *left, cairo_line_t *right)
158 cairo_trapezoid_t *trap;
160 /* Note: With the goofy trapezoid specification, (where an
161 * arbitrary two points on the lines can specified for the left
162 * and right edges), these limit checks would not work in
163 * general. For example, one can imagine a trapezoid entirely
164 * within the limits, but with two points used to specify the left
165 * edge entirely to the right of the limits. Fortunately, for our
166 * purposes, cairo will never generate such a crazy
167 * trapezoid. Instead, cairo always uses for its points the
168 * extreme positions of the edge that are visible on at least some
169 * trapezoid. With this constraint, it's impossible for both
170 * points to be outside the limits while the relevant edge is
171 * entirely inside the limits.
173 if (traps->has_limits) {
174 /* Trivially reject if trapezoid is entirely to the right or
175 * to the left of the limits. */
176 if (left->p1.x >= traps->limits.p2.x &&
177 left->p2.x >= traps->limits.p2.x)
179 return;
182 if (right->p1.x <= traps->limits.p1.x &&
183 right->p2.x <= traps->limits.p1.x)
185 return;
188 /* And reject if the trapezoid is entirely above or below */
189 if (top > traps->limits.p2.y || bottom < traps->limits.p1.y)
190 return;
192 /* Otherwise, clip the trapezoid to the limits. We only clip
193 * where an edge is entirely outside the limits. If we wanted
194 * to be more clever, we could handle cases where a trapezoid
195 * edge intersects the edge of the limits, but that would
196 * require slicing this trapezoid into multiple trapezoids,
197 * and I'm not sure the effort would be worth it. */
198 if (top < traps->limits.p1.y)
199 top = traps->limits.p1.y;
201 if (bottom > traps->limits.p2.y)
202 bottom = traps->limits.p2.y;
204 if (left->p1.x <= traps->limits.p1.x &&
205 left->p2.x <= traps->limits.p1.x)
207 left->p1.x = traps->limits.p1.x;
208 left->p2.x = traps->limits.p1.x;
211 if (right->p1.x >= traps->limits.p2.x &&
212 right->p2.x >= traps->limits.p2.x)
214 right->p1.x = traps->limits.p2.x;
215 right->p2.x = traps->limits.p2.x;
219 /* Trivial discards for empty trapezoids that are likely to be produced
220 * by our tessellators (most notably convex_quad when given a simple
221 * rectangle).
223 if (top >= bottom)
224 return;
225 /* cheap colinearity check */
226 if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y &&
227 right->p2.x <= left->p2.x && right->p2.y == left->p2.y)
228 return;
230 if (traps->num_traps == traps->traps_size) {
231 if (! _cairo_traps_grow (traps))
232 return;
235 trap = &traps->traps[traps->num_traps];
236 trap->top = top;
237 trap->bottom = bottom;
238 trap->left = *left;
239 trap->right = *right;
241 if (top < traps->extents.p1.y)
242 traps->extents.p1.y = top;
243 if (bottom > traps->extents.p2.y)
244 traps->extents.p2.y = bottom;
246 * This isn't generally accurate, but it is close enough for
247 * this purpose. Assuming that the left and right segments always
248 * contain the trapezoid vertical extents, these compares will
249 * yield a containing box. Assuming that the points all come from
250 * the same figure which will eventually be completely drawn, then
251 * the compares will yield the correct overall extents
253 if (left->p1.x < traps->extents.p1.x)
254 traps->extents.p1.x = left->p1.x;
255 if (left->p2.x < traps->extents.p1.x)
256 traps->extents.p1.x = left->p2.x;
258 if (right->p1.x > traps->extents.p2.x)
259 traps->extents.p2.x = right->p1.x;
260 if (right->p2.x > traps->extents.p2.x)
261 traps->extents.p2.x = right->p2.x;
263 traps->num_traps++;
266 static int
267 _compare_point_fixed_by_y (const void *av, const void *bv)
269 const cairo_point_t *a = av, *b = bv;
271 int ret = a->y - b->y;
272 if (ret == 0) {
273 ret = a->x - b->x;
275 return ret;
278 void
279 _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
281 cairo_fixed_t xoff, yoff;
282 cairo_trapezoid_t *t;
283 int i;
285 /* Ugh. The cairo_composite/(Render) interface doesn't allow
286 an offset for the trapezoids. Need to manually shift all
287 the coordinates to align with the offset origin of the
288 intermediate surface. */
290 xoff = _cairo_fixed_from_int (x);
291 yoff = _cairo_fixed_from_int (y);
293 for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
294 t->top += yoff;
295 t->bottom += yoff;
296 t->left.p1.x += xoff;
297 t->left.p1.y += yoff;
298 t->left.p2.x += xoff;
299 t->left.p2.y += yoff;
300 t->right.p1.x += xoff;
301 t->right.p1.y += yoff;
302 t->right.p2.x += xoff;
303 t->right.p2.y += yoff;
307 void
308 _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
309 cairo_trapezoid_t *src_traps,
310 int num_traps,
311 double tx, double ty,
312 double sx, double sy)
314 int i;
315 cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
316 cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
318 if (sx == 1.0 && sy == 1.0) {
319 for (i = 0; i < num_traps; i++) {
320 offset_traps[i].top = src_traps[i].top + yoff;
321 offset_traps[i].bottom = src_traps[i].bottom + yoff;
322 offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
323 offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
324 offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
325 offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
326 offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
327 offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
328 offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
329 offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
331 } else {
332 cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
333 cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
335 for (i = 0; i < num_traps; i++) {
336 offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
337 offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
338 offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
339 offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
340 offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
341 offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
342 offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
343 offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
344 offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
345 offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
350 /* A triangle is simply a degenerate case of a convex
351 * quadrilateral. We would not benefit from having any distinct
352 * implementation of triangle vs. quadrilateral tessellation here. */
353 cairo_status_t
354 _cairo_traps_tessellate_triangle (cairo_traps_t *traps,
355 const cairo_point_t t[3])
357 cairo_point_t quad[4];
359 quad[0] = t[0];
360 quad[1] = t[0];
361 quad[2] = t[1];
362 quad[3] = t[2];
364 return _cairo_traps_tessellate_convex_quad (traps, quad);
367 cairo_status_t
368 _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
369 const cairo_point_t *top_left,
370 const cairo_point_t *bottom_right)
372 cairo_line_t left;
373 cairo_line_t right;
375 left.p1.x = left.p2.x = top_left->x;
376 left.p1.y = right.p1.y = top_left->y;
377 right.p1.x = right.p2.x = bottom_right->x;
378 left.p2.y = right.p2.y = bottom_right->y;
380 _cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
382 return traps->status;
385 cairo_status_t
386 _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
387 const cairo_point_t q[4])
389 int a, b, c, d;
390 int i;
391 cairo_slope_t ab, ad;
392 cairo_bool_t b_left_of_d;
393 cairo_line_t left;
394 cairo_line_t right;
396 /* Choose a as a point with minimal y */
397 a = 0;
398 for (i = 1; i < 4; i++)
399 if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
400 a = i;
402 /* b and d are adjacent to a, while c is opposite */
403 b = (a + 1) % 4;
404 c = (a + 2) % 4;
405 d = (a + 3) % 4;
407 /* Choose between b and d so that b.y is less than d.y */
408 if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
409 b = (a + 3) % 4;
410 d = (a + 1) % 4;
413 /* Without freedom left to choose anything else, we have four
414 * cases to tessellate.
416 * First, we have to determine the Y-axis sort of the four
417 * vertices, (either abcd or abdc). After that we need to detemine
418 * which edges will be "left" and which will be "right" in the
419 * resulting trapezoids. This can be determined by computing a
420 * slope comparison of ab and ad to determine if b is left of d or
421 * not.
423 * Note that "left of" here is in the sense of which edges should
424 * be the left vs. right edges of the trapezoid. In particular, b
425 * left of d does *not* mean that b.x is less than d.x.
427 * This should hopefully be made clear in the lame ASCII art
428 * below. Since the same slope comparison is used in all cases, we
429 * compute it before testing for the Y-value sort. */
431 /* Note: If a == b then the ab slope doesn't give us any
432 * information. In that case, we can replace it with the ac (or
433 * equivalenly the bc) slope which gives us exactly the same
434 * information we need. At worst the names of the identifiers ab
435 * and b_left_of_d are inaccurate in this case, (would be ac, and
436 * c_left_of_d). */
437 if (q[a].x == q[b].x && q[a].y == q[b].y)
438 _cairo_slope_init (&ab, &q[a], &q[c]);
439 else
440 _cairo_slope_init (&ab, &q[a], &q[b]);
442 _cairo_slope_init (&ad, &q[a], &q[d]);
444 b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0);
446 if (q[c].y <= q[d].y) {
447 if (b_left_of_d) {
448 /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
450 * top bot left right
451 * _a a a
452 * / / /| |\ a.y b.y ab ad
453 * b / b | b \
454 * / / | | \ \ b.y c.y bc ad
455 * c / c | c \
456 * | / \| \ \ c.y d.y cd ad
457 * d d d
459 left.p1 = q[a]; left.p2 = q[b];
460 right.p1 = q[a]; right.p2 = q[d];
461 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
462 left.p1 = q[b]; left.p2 = q[c];
463 _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
464 left.p1 = q[c]; left.p2 = q[d];
465 _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
466 } else {
467 /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
469 * a a a_
470 * /| |\ \ \ a.y b.y ad ab
471 * / b | b \ b
472 * / / | | \ \ b.y c.y ad bc
473 * / c | c \ c
474 * / / |/ \ | c.y d.y ad cd
475 * d d d
477 left.p1 = q[a]; left.p2 = q[d];
478 right.p1 = q[a]; right.p2 = q[b];
479 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
480 right.p1 = q[b]; right.p2 = q[c];
481 _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
482 right.p1 = q[c]; right.p2 = q[d];
483 _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
485 } else {
486 if (b_left_of_d) {
487 /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
489 * a a a
490 * // / \ |\ a.y b.y ab ad
491 * /b/ b \ b \
492 * / / \ \ \ \ b.y d.y bc ad
493 * /d/ \ d \ d
494 * // \ / \| d.y c.y bc dc
495 * c c c
497 left.p1 = q[a]; left.p2 = q[b];
498 right.p1 = q[a]; right.p2 = q[d];
499 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
500 left.p1 = q[b]; left.p2 = q[c];
501 _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
502 right.p1 = q[d]; right.p2 = q[c];
503 _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
504 } else {
505 /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
507 * a a a
508 * /| / \ \\ a.y b.y ad ab
509 * / b / b \b\
510 * / / / / \ \ b.y d.y ad bc
511 * d / d / \d\
512 * |/ \ / \\ d.y c.y dc bc
513 * c c c
515 left.p1 = q[a]; left.p2 = q[d];
516 right.p1 = q[a]; right.p2 = q[b];
517 _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
518 right.p1 = q[b]; right.p2 = q[c];
519 _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
520 left.p1 = q[d]; left.p2 = q[c];
521 _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
525 return traps->status;
528 static cairo_bool_t
529 _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
531 cairo_slope_t slope_left, slope_pt, slope_right;
533 if (t->top > pt->y)
534 return FALSE;
535 if (t->bottom < pt->y)
536 return FALSE;
538 _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
539 _cairo_slope_init (&slope_pt, &t->left.p1, pt);
541 if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
542 return FALSE;
544 _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
545 _cairo_slope_init (&slope_pt, &t->right.p1, pt);
547 if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
548 return FALSE;
550 return TRUE;
553 cairo_bool_t
554 _cairo_traps_contain (const cairo_traps_t *traps,
555 double x, double y)
557 int i;
558 cairo_point_t point;
560 point.x = _cairo_fixed_from_double (x);
561 point.y = _cairo_fixed_from_double (y);
563 for (i = 0; i < traps->num_traps; i++) {
564 if (_cairo_trap_contains (&traps->traps[i], &point))
565 return TRUE;
568 return FALSE;
571 void
572 _cairo_traps_extents (const cairo_traps_t *traps,
573 cairo_box_t *extents)
575 if (traps->num_traps == 0) {
576 extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
577 extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
578 } else {
579 *extents = traps->extents;
580 if (traps->has_limits) {
581 /* clip the traps to the imposed limits */
582 if (extents->p1.x < traps->limits.p1.x)
583 extents->p1.x = traps->limits.p1.x;
584 if (extents->p2.x > traps->limits.p2.x)
585 extents->p2.x = traps->limits.p2.x;
587 if (extents->p1.y < traps->limits.p1.y)
588 extents->p1.y = traps->limits.p1.y;
589 if (extents->p2.y > traps->limits.p2.y)
590 extents->p2.y = traps->limits.p2.y;
596 * _cairo_traps_extract_region:
597 * @traps: a #cairo_traps_t
598 * @region: a #cairo_region_t
600 * Determines if a set of trapezoids are exactly representable as a
601 * cairo region. If so, the passed-in region is initialized to
602 * the area representing the given traps. It should be finalized
603 * with _cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
604 * is returned.
606 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
607 * or %CAIRO_STATUS_NO_MEMORY
609 cairo_int_status_t
610 _cairo_traps_extract_region (const cairo_traps_t *traps,
611 cairo_region_t *region)
613 cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
614 cairo_box_int_t *boxes = stack_boxes;
615 int i, box_count;
616 cairo_int_status_t status;
618 for (i = 0; i < traps->num_traps; i++)
619 if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
620 && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x
621 && _cairo_fixed_is_integer(traps->traps[i].top)
622 && _cairo_fixed_is_integer(traps->traps[i].bottom)
623 && _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
624 && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
625 return CAIRO_INT_STATUS_UNSUPPORTED;
628 if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) {
629 boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t));
631 if (boxes == NULL)
632 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
635 box_count = 0;
637 for (i = 0; i < traps->num_traps; i++) {
638 int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
639 int y1 = _cairo_fixed_integer_part(traps->traps[i].top);
640 int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x);
641 int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom);
643 /* XXX: Sometimes we get degenerate trapezoids from the tesellator;
644 * skip these.
646 if (x1 == x2 || y1 == y2)
647 continue;
649 boxes[box_count].p1.x = x1;
650 boxes[box_count].p1.y = y1;
651 boxes[box_count].p2.x = x2;
652 boxes[box_count].p2.y = y2;
654 box_count++;
657 status = _cairo_region_init_boxes (region, boxes, box_count);
659 if (boxes != stack_boxes)
660 free (boxes);
662 if (status)
663 _cairo_region_fini (region);
665 return status;
668 /* moves trap points such that they become the actual corners of the trapezoid */
669 static void
670 _sanitize_trap (cairo_trapezoid_t *t)
672 cairo_trapezoid_t s = *t;
674 #define FIX(lr, tb, p) \
675 if (t->lr.p.y != t->tb) { \
676 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); \
677 t->lr.p.y = s.tb; \
679 FIX (left, top, p1);
680 FIX (left, bottom, p2);
681 FIX (right, top, p1);
682 FIX (right, bottom, p2);
685 cairo_private cairo_status_t
686 _cairo_traps_path (const cairo_traps_t *traps,
687 cairo_path_fixed_t *path)
689 int i;
691 for (i = 0; i < traps->num_traps; i++) {
692 cairo_status_t status;
693 cairo_trapezoid_t trap = traps->traps[i];
695 if (trap.top == trap.bottom)
696 continue;
698 _sanitize_trap (&trap);
700 status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
701 if (status) return status;
702 status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
703 if (status) return status;
704 status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
705 if (status) return status;
706 status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
707 if (status) return status;
708 status = _cairo_path_fixed_close_path (path);
709 if (status) return status;
712 return CAIRO_STATUS_SUCCESS;