1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
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
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
42 /* private functions */
45 _compare_point_fixed_by_y (const void *av
, const void *bv
);
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
;
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
;
65 _cairo_traps_limit (cairo_traps_t
*traps
,
68 traps
->has_limits
= TRUE
;
70 traps
->limits
= *limits
;
74 _cairo_traps_get_limit (cairo_traps_t
*traps
,
77 *limits
= traps
->limits
;
78 return traps
->has_limits
;
82 _cairo_traps_clear (cairo_traps_t
*traps
)
84 traps
->status
= CAIRO_STATUS_SUCCESS
;
87 traps
->extents
.p1
.x
= traps
->extents
.p1
.y
= INT32_MAX
;
88 traps
->extents
.p2
.x
= traps
->extents
.p2
.y
= INT32_MIN
;
92 _cairo_traps_fini (cairo_traps_t
*traps
)
94 if (traps
->traps
!= traps
->traps_embedded
)
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
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 */
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
);
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
));
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
);
157 traps
->traps
= new_traps
;
158 traps
->traps_size
= new_size
;
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
)
191 if (right
->p1
.x
<= traps
->limits
.p1
.x
&&
192 right
->p2
.x
<= traps
->limits
.p1
.x
)
197 /* And reject if the trapezoid is entirely above or below */
198 if (top
> traps
->limits
.p2
.y
|| bottom
< traps
->limits
.p1
.y
)
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
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
)
239 if (traps
->num_traps
== traps
->traps_size
) {
240 if (! _cairo_traps_grow (traps
))
244 trap
= &traps
->traps
[traps
->num_traps
];
246 trap
->bottom
= bottom
;
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
;
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
;
288 _cairo_traps_translate (cairo_traps_t
*traps
, int x
, int y
)
290 cairo_fixed_t xoff
, yoff
;
291 cairo_trapezoid_t
*t
;
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
++) {
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
;
317 _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t
*offset_traps
,
318 cairo_trapezoid_t
*src_traps
,
320 double tx
, double ty
,
321 double sx
, double sy
)
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
;
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. */
363 _cairo_traps_tessellate_triangle (cairo_traps_t
*traps
,
364 const cairo_point_t t
[3])
366 cairo_point_t quad
[4];
373 return _cairo_traps_tessellate_convex_quad (traps
, quad
);
377 _cairo_traps_tessellate_rectangle (cairo_traps_t
*traps
,
378 const cairo_point_t
*top_left
,
379 const cairo_point_t
*bottom_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
;
395 _cairo_traps_tessellate_convex_quad (cairo_traps_t
*traps
,
396 const cairo_point_t q
[4])
400 cairo_slope_t ab
, ad
;
401 cairo_bool_t b_left_of_d
;
405 /* Choose a as a point with minimal y */
407 for (i
= 1; i
< 4; i
++)
408 if (_compare_point_fixed_by_y (&q
[i
], &q
[a
]) < 0)
411 /* b and d are adjacent to a, while c is opposite */
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) {
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
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
446 if (q
[a
].x
== q
[b
].x
&& q
[a
].y
== q
[b
].y
)
447 _cairo_slope_init (&ab
, &q
[a
], &q
[c
]);
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
) {
457 /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
461 * / / /| |\ a.y b.y ab ad
463 * / / | | \ \ b.y c.y bc ad
465 * | / \| \ \ c.y d.y cd ad
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
);
476 /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
479 * /| |\ \ \ a.y b.y ad ab
481 * / / | | \ \ b.y c.y ad bc
483 * / / |/ \ | c.y d.y ad cd
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
);
496 /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
499 * // / \ |\ a.y b.y ab ad
501 * / / \ \ \ \ b.y d.y bc ad
503 * // \ / \| d.y c.y bc dc
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
);
514 /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
517 * /| / \ \\ a.y b.y ad ab
519 * / / / / \ \ b.y d.y ad bc
521 * |/ \ / \\ d.y c.y dc bc
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
;
538 _cairo_trap_contains (cairo_trapezoid_t
*t
, cairo_point_t
*pt
)
540 cairo_slope_t slope_left
, slope_pt
, slope_right
;
544 if (t
->bottom
< pt
->y
)
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)
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)
563 _cairo_traps_contain (const cairo_traps_t
*traps
,
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
))
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);
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
615 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
616 * or %CAIRO_STATUS_NO_MEMORY
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
;
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
);
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;
656 if (x1
== x2
|| y1
== y2
)
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
;
667 *region
= cairo_region_create_rectangles (rects
, rect_count
);
668 status
= cairo_region_status (*region
);
670 if (rects
!= stack_rects
)
673 if (unlikely (status
)) {
674 cairo_region_destroy (*region
);
681 /* moves trap points such that they become the actual corners of the trapezoid */
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); \
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
)
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
)
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
;