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.
5 : *
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.
13 : *
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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 : * You should have received a copy of the MPL along with this library
18 : * in the file COPYING-MPL-1.1
19 : *
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/
24 : *
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.
28 : *
29 : * The Original Code is the cairo graphics library.
30 : *
31 : * The Initial Developer of the Original Code is Keith Packard
32 : *
33 : * Contributor(s):
34 : * Keith R. Packard <keithp@keithp.com>
35 : * Carl D. Worth <cworth@cworth.org>
36 : *
37 : * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth
38 : */
39 :
40 : #include "cairoint.h"
41 :
42 : #include "cairo-boxes-private.h"
43 : #include "cairo-error-private.h"
44 : #include "cairo-region-private.h"
45 : #include "cairo-slope-private.h"
46 :
47 : /* private functions */
48 :
49 : void
50 0 : _cairo_traps_init (cairo_traps_t *traps)
51 : {
52 : VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
53 :
54 0 : traps->status = CAIRO_STATUS_SUCCESS;
55 :
56 0 : traps->maybe_region = 1;
57 0 : traps->is_rectilinear = 0;
58 0 : traps->is_rectangular = 0;
59 :
60 0 : traps->num_traps = 0;
61 :
62 0 : traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
63 0 : traps->traps = traps->traps_embedded;
64 :
65 0 : traps->num_limits = 0;
66 0 : traps->has_intersections = FALSE;
67 0 : }
68 :
69 : void
70 0 : _cairo_traps_limit (cairo_traps_t *traps,
71 : const cairo_box_t *limits,
72 : int num_limits)
73 : {
74 0 : traps->limits = limits;
75 0 : traps->num_limits = num_limits;
76 0 : }
77 :
78 : void
79 0 : _cairo_traps_clear (cairo_traps_t *traps)
80 : {
81 0 : traps->status = CAIRO_STATUS_SUCCESS;
82 :
83 0 : traps->maybe_region = 1;
84 0 : traps->is_rectilinear = 0;
85 0 : traps->is_rectangular = 0;
86 :
87 0 : traps->num_traps = 0;
88 0 : traps->has_intersections = FALSE;
89 0 : }
90 :
91 : void
92 0 : _cairo_traps_fini (cairo_traps_t *traps)
93 : {
94 0 : if (traps->traps != traps->traps_embedded)
95 0 : free (traps->traps);
96 :
97 : VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
98 0 : }
99 :
100 : /* make room for at least one more trap */
101 : static cairo_bool_t
102 0 : _cairo_traps_grow (cairo_traps_t *traps)
103 : {
104 : cairo_trapezoid_t *new_traps;
105 0 : int new_size = 4 * traps->traps_size;
106 :
107 : if (CAIRO_INJECT_FAULT ()) {
108 : traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
109 : return FALSE;
110 : }
111 :
112 0 : if (traps->traps == traps->traps_embedded) {
113 0 : new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
114 0 : if (new_traps != NULL)
115 0 : memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
116 : } else {
117 0 : new_traps = _cairo_realloc_ab (traps->traps,
118 : new_size, sizeof (cairo_trapezoid_t));
119 : }
120 :
121 0 : if (unlikely (new_traps == NULL)) {
122 0 : traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
123 0 : return FALSE;
124 : }
125 :
126 0 : traps->traps = new_traps;
127 0 : traps->traps_size = new_size;
128 0 : return TRUE;
129 : }
130 :
131 : void
132 0 : _cairo_traps_add_trap (cairo_traps_t *traps,
133 : cairo_fixed_t top, cairo_fixed_t bottom,
134 : cairo_line_t *left, cairo_line_t *right)
135 : {
136 : cairo_trapezoid_t *trap;
137 :
138 0 : if (unlikely (traps->num_traps == traps->traps_size)) {
139 0 : if (unlikely (! _cairo_traps_grow (traps)))
140 0 : return;
141 : }
142 :
143 0 : trap = &traps->traps[traps->num_traps++];
144 0 : trap->top = top;
145 0 : trap->bottom = bottom;
146 0 : trap->left = *left;
147 0 : trap->right = *right;
148 : }
149 :
150 : /**
151 : * _cairo_traps_init_box:
152 : * @traps: a #cairo_traps_t
153 : * @box: an array box that will each be converted to a single trapezoid
154 : * to store in @traps.
155 : *
156 : * Initializes a #cairo_traps_t to contain an array of rectangular
157 : * trapezoids.
158 : **/
159 : cairo_status_t
160 0 : _cairo_traps_init_boxes (cairo_traps_t *traps,
161 : const cairo_boxes_t *boxes)
162 : {
163 : cairo_trapezoid_t *trap;
164 : const struct _cairo_boxes_chunk *chunk;
165 :
166 0 : _cairo_traps_init (traps);
167 :
168 0 : while (traps->traps_size < boxes->num_boxes) {
169 0 : if (unlikely (! _cairo_traps_grow (traps))) {
170 0 : _cairo_traps_fini (traps);
171 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
172 : }
173 : }
174 :
175 0 : traps->num_traps = boxes->num_boxes;
176 0 : traps->is_rectilinear = TRUE;
177 0 : traps->is_rectangular = TRUE;
178 0 : traps->maybe_region = boxes->is_pixel_aligned;
179 :
180 0 : trap = &traps->traps[0];
181 0 : for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
182 : const cairo_box_t *box;
183 : int i;
184 :
185 0 : box = chunk->base;
186 0 : for (i = 0; i < chunk->count; i++) {
187 0 : trap->top = box->p1.y;
188 0 : trap->bottom = box->p2.y;
189 :
190 0 : trap->left.p1 = box->p1;
191 0 : trap->left.p2.x = box->p1.x;
192 0 : trap->left.p2.y = box->p2.y;
193 :
194 0 : trap->right.p1.x = box->p2.x;
195 0 : trap->right.p1.y = box->p1.y;
196 0 : trap->right.p2 = box->p2;
197 :
198 0 : box++, trap++;
199 : }
200 : }
201 :
202 0 : return CAIRO_STATUS_SUCCESS;
203 : }
204 :
205 : cairo_status_t
206 0 : _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
207 : const cairo_point_t *top_left,
208 : const cairo_point_t *bottom_right)
209 : {
210 : cairo_line_t left;
211 : cairo_line_t right;
212 : cairo_fixed_t top, bottom;
213 :
214 0 : if (top_left->y == bottom_right->y)
215 0 : return CAIRO_STATUS_SUCCESS;
216 :
217 0 : if (top_left->x == bottom_right->x)
218 0 : return CAIRO_STATUS_SUCCESS;
219 :
220 0 : left.p1.x = left.p2.x = top_left->x;
221 0 : left.p1.y = right.p1.y = top_left->y;
222 0 : right.p1.x = right.p2.x = bottom_right->x;
223 0 : left.p2.y = right.p2.y = bottom_right->y;
224 :
225 0 : top = top_left->y;
226 0 : bottom = bottom_right->y;
227 :
228 0 : if (traps->num_limits) {
229 : cairo_bool_t reversed;
230 : int n;
231 :
232 : /* support counter-clockwise winding for rectangular tessellation */
233 0 : reversed = top_left->x > bottom_right->x;
234 0 : if (reversed) {
235 0 : right.p1.x = right.p2.x = top_left->x;
236 0 : left.p1.x = left.p2.x = bottom_right->x;
237 : }
238 :
239 0 : for (n = 0; n < traps->num_limits; n++) {
240 0 : const cairo_box_t *limits = &traps->limits[n];
241 : cairo_line_t _left, _right;
242 : cairo_fixed_t _top, _bottom;
243 :
244 0 : if (top >= limits->p2.y)
245 0 : continue;
246 0 : if (bottom <= limits->p1.y)
247 0 : continue;
248 :
249 : /* Trivially reject if trapezoid is entirely to the right or
250 : * to the left of the limits. */
251 0 : if (left.p1.x >= limits->p2.x)
252 0 : continue;
253 0 : if (right.p1.x <= limits->p1.x)
254 0 : continue;
255 :
256 : /* Otherwise, clip the trapezoid to the limits. */
257 0 : _top = top;
258 0 : if (_top < limits->p1.y)
259 0 : _top = limits->p1.y;
260 :
261 0 : _bottom = bottom;
262 0 : if (_bottom > limits->p2.y)
263 0 : _bottom = limits->p2.y;
264 :
265 0 : if (_bottom <= _top)
266 0 : continue;
267 :
268 0 : _left = left;
269 0 : if (_left.p1.x < limits->p1.x) {
270 0 : _left.p1.x = limits->p1.x;
271 0 : _left.p1.y = limits->p1.y;
272 0 : _left.p2.x = limits->p1.x;
273 0 : _left.p2.y = limits->p2.y;
274 : }
275 :
276 0 : _right = right;
277 0 : if (_right.p1.x > limits->p2.x) {
278 0 : _right.p1.x = limits->p2.x;
279 0 : _right.p1.y = limits->p1.y;
280 0 : _right.p2.x = limits->p2.x;
281 0 : _right.p2.y = limits->p2.y;
282 : }
283 :
284 0 : if (left.p1.x >= right.p1.x)
285 0 : continue;
286 :
287 0 : if (reversed)
288 0 : _cairo_traps_add_trap (traps, _top, _bottom, &_right, &_left);
289 : else
290 0 : _cairo_traps_add_trap (traps, _top, _bottom, &_left, &_right);
291 : }
292 : } else {
293 0 : _cairo_traps_add_trap (traps, top, bottom, &left, &right);
294 : }
295 :
296 0 : return traps->status;
297 : }
298 :
299 : void
300 0 : _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
301 : {
302 : cairo_fixed_t xoff, yoff;
303 : cairo_trapezoid_t *t;
304 : int i;
305 :
306 : /* Ugh. The cairo_composite/(Render) interface doesn't allow
307 : an offset for the trapezoids. Need to manually shift all
308 : the coordinates to align with the offset origin of the
309 : intermediate surface. */
310 :
311 0 : xoff = _cairo_fixed_from_int (x);
312 0 : yoff = _cairo_fixed_from_int (y);
313 :
314 0 : for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
315 0 : t->top += yoff;
316 0 : t->bottom += yoff;
317 0 : t->left.p1.x += xoff;
318 0 : t->left.p1.y += yoff;
319 0 : t->left.p2.x += xoff;
320 0 : t->left.p2.y += yoff;
321 0 : t->right.p1.x += xoff;
322 0 : t->right.p1.y += yoff;
323 0 : t->right.p2.x += xoff;
324 0 : t->right.p2.y += yoff;
325 : }
326 0 : }
327 :
328 : void
329 0 : _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
330 : cairo_trapezoid_t *src_traps,
331 : int num_traps,
332 : double tx, double ty,
333 : double sx, double sy)
334 : {
335 : int i;
336 0 : cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
337 0 : cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
338 :
339 0 : if (sx == 1.0 && sy == 1.0) {
340 0 : for (i = 0; i < num_traps; i++) {
341 0 : offset_traps[i].top = src_traps[i].top + yoff;
342 0 : offset_traps[i].bottom = src_traps[i].bottom + yoff;
343 0 : offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
344 0 : offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
345 0 : offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
346 0 : offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
347 0 : offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
348 0 : offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
349 0 : offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
350 0 : offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
351 : }
352 : } else {
353 0 : cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
354 0 : cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
355 :
356 0 : for (i = 0; i < num_traps; i++) {
357 0 : offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
358 0 : offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
359 0 : offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
360 0 : offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
361 0 : offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
362 0 : offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
363 0 : offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
364 0 : offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
365 0 : offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
366 0 : offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
367 : }
368 : }
369 0 : }
370 :
371 : static cairo_bool_t
372 0 : _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
373 : {
374 : cairo_slope_t slope_left, slope_pt, slope_right;
375 :
376 0 : if (t->top > pt->y)
377 0 : return FALSE;
378 0 : if (t->bottom < pt->y)
379 0 : return FALSE;
380 :
381 0 : _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
382 0 : _cairo_slope_init (&slope_pt, &t->left.p1, pt);
383 :
384 0 : if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
385 0 : return FALSE;
386 :
387 0 : _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
388 0 : _cairo_slope_init (&slope_pt, &t->right.p1, pt);
389 :
390 0 : if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
391 0 : return FALSE;
392 :
393 0 : return TRUE;
394 : }
395 :
396 : cairo_bool_t
397 0 : _cairo_traps_contain (const cairo_traps_t *traps,
398 : double x, double y)
399 : {
400 : int i;
401 : cairo_point_t point;
402 :
403 0 : point.x = _cairo_fixed_from_double (x);
404 0 : point.y = _cairo_fixed_from_double (y);
405 :
406 0 : for (i = 0; i < traps->num_traps; i++) {
407 0 : if (_cairo_trap_contains (&traps->traps[i], &point))
408 0 : return TRUE;
409 : }
410 :
411 0 : return FALSE;
412 : }
413 :
414 : static cairo_fixed_t
415 0 : _line_compute_intersection_x_for_y (const cairo_line_t *line,
416 : cairo_fixed_t y)
417 : {
418 0 : return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y);
419 : }
420 :
421 : void
422 0 : _cairo_traps_extents (const cairo_traps_t *traps,
423 : cairo_box_t *extents)
424 : {
425 : int i;
426 :
427 0 : if (traps->num_traps == 0) {
428 0 : extents->p1.x = extents->p1.y = 0;
429 0 : extents->p2.x = extents->p2.y = 0;
430 0 : return;
431 : }
432 :
433 0 : extents->p1.x = extents->p1.y = INT32_MAX;
434 0 : extents->p2.x = extents->p2.y = INT32_MIN;
435 :
436 0 : for (i = 0; i < traps->num_traps; i++) {
437 0 : const cairo_trapezoid_t *trap = &traps->traps[i];
438 :
439 0 : if (trap->top < extents->p1.y)
440 0 : extents->p1.y = trap->top;
441 0 : if (trap->bottom > extents->p2.y)
442 0 : extents->p2.y = trap->bottom;
443 :
444 0 : if (trap->left.p1.x < extents->p1.x) {
445 0 : cairo_fixed_t x = trap->left.p1.x;
446 0 : if (trap->top != trap->left.p1.y) {
447 0 : x = _line_compute_intersection_x_for_y (&trap->left,
448 : trap->top);
449 0 : if (x < extents->p1.x)
450 0 : extents->p1.x = x;
451 : } else
452 0 : extents->p1.x = x;
453 : }
454 0 : if (trap->left.p2.x < extents->p1.x) {
455 0 : cairo_fixed_t x = trap->left.p2.x;
456 0 : if (trap->bottom != trap->left.p2.y) {
457 0 : x = _line_compute_intersection_x_for_y (&trap->left,
458 : trap->bottom);
459 0 : if (x < extents->p1.x)
460 0 : extents->p1.x = x;
461 : } else
462 0 : extents->p1.x = x;
463 : }
464 :
465 0 : if (trap->right.p1.x > extents->p2.x) {
466 0 : cairo_fixed_t x = trap->right.p1.x;
467 0 : if (trap->top != trap->right.p1.y) {
468 0 : x = _line_compute_intersection_x_for_y (&trap->right,
469 : trap->top);
470 0 : if (x > extents->p2.x)
471 0 : extents->p2.x = x;
472 : } else
473 0 : extents->p2.x = x;
474 : }
475 0 : if (trap->right.p2.x > extents->p2.x) {
476 0 : cairo_fixed_t x = trap->right.p2.x;
477 0 : if (trap->bottom != trap->right.p2.y) {
478 0 : x = _line_compute_intersection_x_for_y (&trap->right,
479 : trap->bottom);
480 0 : if (x > extents->p2.x)
481 0 : extents->p2.x = x;
482 : } else
483 0 : extents->p2.x = x;
484 : }
485 : }
486 : }
487 :
488 :
489 : /**
490 : * _cairo_traps_extract_region:
491 : * @traps: a #cairo_traps_t
492 : * @region: a #cairo_region_t
493 : *
494 : * Determines if a set of trapezoids are exactly representable as a
495 : * cairo region. If so, the passed-in region is initialized to
496 : * the area representing the given traps. It should be finalized
497 : * with cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
498 : * is returned.
499 : *
500 : * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
501 : * or %CAIRO_STATUS_NO_MEMORY
502 : **/
503 : cairo_int_status_t
504 0 : _cairo_traps_extract_region (cairo_traps_t *traps,
505 : cairo_region_t **region)
506 : {
507 : cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
508 0 : cairo_rectangle_int_t *rects = stack_rects;
509 : cairo_int_status_t status;
510 : int i, rect_count;
511 :
512 : /* we only treat this a hint... */
513 0 : if (! traps->maybe_region)
514 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
515 :
516 0 : for (i = 0; i < traps->num_traps; i++) {
517 0 : if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
518 0 : traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
519 0 : ! _cairo_fixed_is_integer (traps->traps[i].top) ||
520 0 : ! _cairo_fixed_is_integer (traps->traps[i].bottom) ||
521 0 : ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) ||
522 0 : ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
523 : {
524 0 : traps->maybe_region = FALSE;
525 0 : return CAIRO_INT_STATUS_UNSUPPORTED;
526 : }
527 : }
528 :
529 0 : if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
530 0 : rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
531 :
532 0 : if (unlikely (rects == NULL))
533 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
534 : }
535 :
536 0 : rect_count = 0;
537 0 : for (i = 0; i < traps->num_traps; i++) {
538 0 : int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
539 0 : int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
540 0 : int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
541 0 : int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
542 :
543 0 : rects[rect_count].x = x1;
544 0 : rects[rect_count].y = y1;
545 0 : rects[rect_count].width = x2 - x1;
546 0 : rects[rect_count].height = y2 - y1;
547 :
548 0 : rect_count++;
549 : }
550 :
551 0 : *region = cairo_region_create_rectangles (rects, rect_count);
552 0 : status = (*region)->status;
553 :
554 0 : if (rects != stack_rects)
555 0 : free (rects);
556 :
557 0 : return status;
558 : }
559 :
560 : /* moves trap points such that they become the actual corners of the trapezoid */
561 : static void
562 0 : _sanitize_trap (cairo_trapezoid_t *t)
563 : {
564 0 : cairo_trapezoid_t s = *t;
565 :
566 : #define FIX(lr, tb, p) \
567 : if (t->lr.p.y != t->tb) { \
568 : 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); \
569 : t->lr.p.y = s.tb; \
570 : }
571 0 : FIX (left, top, p1);
572 0 : FIX (left, bottom, p2);
573 0 : FIX (right, top, p1);
574 0 : FIX (right, bottom, p2);
575 0 : }
576 :
577 : cairo_private cairo_status_t
578 0 : _cairo_traps_path (const cairo_traps_t *traps,
579 : cairo_path_fixed_t *path)
580 : {
581 : int i;
582 :
583 0 : for (i = 0; i < traps->num_traps; i++) {
584 : cairo_status_t status;
585 0 : cairo_trapezoid_t trap = traps->traps[i];
586 :
587 0 : if (trap.top == trap.bottom)
588 0 : continue;
589 :
590 0 : _sanitize_trap (&trap);
591 :
592 0 : status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
593 0 : if (unlikely (status)) return status;
594 0 : status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
595 0 : if (unlikely (status)) return status;
596 0 : status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
597 0 : if (unlikely (status)) return status;
598 0 : status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
599 0 : if (unlikely (status)) return status;
600 0 : status = _cairo_path_fixed_close_path (path);
601 0 : if (unlikely (status)) return status;
602 : }
603 :
604 0 : return CAIRO_STATUS_SUCCESS;
605 : }
|