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., 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
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 #include "cairo-boxes-private.h"
43 #include "cairo-error-private.h"
44 #include "cairo-region-private.h"
45 #include "cairo-slope-private.h"
46 #include "cairo-traps-private.h"
47 #include "cairo-spans-private.h"
49 /* private functions */
52 _cairo_traps_init (cairo_traps_t *traps)
54 VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
56 traps->status = CAIRO_STATUS_SUCCESS;
58 traps->maybe_region = 1;
59 traps->is_rectilinear = 0;
60 traps->is_rectangular = 0;
64 traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
65 traps->traps = traps->traps_embedded;
67 traps->num_limits = 0;
68 traps->has_intersections = FALSE;
72 _cairo_traps_limit (cairo_traps_t *traps,
73 const cairo_box_t *limits,
76 traps->limits = limits;
77 traps->num_limits = num_limits;
81 _cairo_traps_init_with_clip (cairo_traps_t *traps,
82 const cairo_clip_t *clip)
84 _cairo_traps_init (traps);
86 _cairo_traps_limit (traps, clip->boxes, clip->num_boxes);
90 _cairo_traps_clear (cairo_traps_t *traps)
92 traps->status = CAIRO_STATUS_SUCCESS;
94 traps->maybe_region = 1;
95 traps->is_rectilinear = 0;
96 traps->is_rectangular = 0;
99 traps->has_intersections = FALSE;
103 _cairo_traps_fini (cairo_traps_t *traps)
105 if (traps->traps != traps->traps_embedded)
108 VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
111 /* make room for at least one more trap */
113 _cairo_traps_grow (cairo_traps_t *traps)
115 cairo_trapezoid_t *new_traps;
116 int new_size = 4 * traps->traps_size;
118 if (CAIRO_INJECT_FAULT ()) {
119 traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
123 if (traps->traps == traps->traps_embedded) {
124 new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
125 if (new_traps != NULL)
126 memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
128 new_traps = _cairo_realloc_ab (traps->traps,
129 new_size, sizeof (cairo_trapezoid_t));
132 if (unlikely (new_traps == NULL)) {
133 traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
137 traps->traps = new_traps;
138 traps->traps_size = new_size;
143 _cairo_traps_add_trap (cairo_traps_t *traps,
144 cairo_fixed_t top, cairo_fixed_t bottom,
145 cairo_line_t *left, cairo_line_t *right)
147 cairo_trapezoid_t *trap;
149 if (unlikely (traps->num_traps == traps->traps_size)) {
150 if (unlikely (! _cairo_traps_grow (traps)))
154 trap = &traps->traps[traps->num_traps++];
156 trap->bottom = bottom;
158 trap->right = *right;
162 * _cairo_traps_init_boxes:
163 * @traps: a #cairo_traps_t
164 * @box: an array box that will each be converted to a single trapezoid
165 * to store in @traps.
167 * Initializes a #cairo_traps_t to contain an array of rectangular
171 _cairo_traps_init_boxes (cairo_traps_t *traps,
172 const cairo_boxes_t *boxes)
174 cairo_trapezoid_t *trap;
175 const struct _cairo_boxes_chunk *chunk;
177 _cairo_traps_init (traps);
179 while (traps->traps_size < boxes->num_boxes) {
180 if (unlikely (! _cairo_traps_grow (traps))) {
181 _cairo_traps_fini (traps);
182 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
186 traps->num_traps = boxes->num_boxes;
187 traps->is_rectilinear = TRUE;
188 traps->is_rectangular = TRUE;
189 traps->maybe_region = boxes->is_pixel_aligned;
191 trap = &traps->traps[0];
192 for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
193 const cairo_box_t *box;
197 for (i = 0; i < chunk->count; i++) {
198 trap->top = box->p1.y;
199 trap->bottom = box->p2.y;
201 trap->left.p1 = box->p1;
202 trap->left.p2.x = box->p1.x;
203 trap->left.p2.y = box->p2.y;
205 trap->right.p1.x = box->p2.x;
206 trap->right.p1.y = box->p1.y;
207 trap->right.p2 = box->p2;
213 return CAIRO_STATUS_SUCCESS;
217 _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
218 const cairo_point_t *top_left,
219 const cairo_point_t *bottom_right)
223 cairo_fixed_t top, bottom;
225 if (top_left->y == bottom_right->y)
226 return CAIRO_STATUS_SUCCESS;
228 if (top_left->x == bottom_right->x)
229 return CAIRO_STATUS_SUCCESS;
231 left.p1.x = left.p2.x = top_left->x;
232 left.p1.y = right.p1.y = top_left->y;
233 right.p1.x = right.p2.x = bottom_right->x;
234 left.p2.y = right.p2.y = bottom_right->y;
237 bottom = bottom_right->y;
239 if (traps->num_limits) {
240 cairo_bool_t reversed;
243 /* support counter-clockwise winding for rectangular tessellation */
244 reversed = top_left->x > bottom_right->x;
246 right.p1.x = right.p2.x = top_left->x;
247 left.p1.x = left.p2.x = bottom_right->x;
250 for (n = 0; n < traps->num_limits; n++) {
251 const cairo_box_t *limits = &traps->limits[n];
252 cairo_line_t _left, _right;
253 cairo_fixed_t _top, _bottom;
255 if (top >= limits->p2.y)
257 if (bottom <= limits->p1.y)
260 /* Trivially reject if trapezoid is entirely to the right or
261 * to the left of the limits. */
262 if (left.p1.x >= limits->p2.x)
264 if (right.p1.x <= limits->p1.x)
267 /* Otherwise, clip the trapezoid to the limits. */
269 if (_top < limits->p1.y)
273 if (_bottom > limits->p2.y)
274 _bottom = limits->p2.y;
280 if (_left.p1.x < limits->p1.x) {
281 _left.p1.x = limits->p1.x;
282 _left.p1.y = limits->p1.y;
283 _left.p2.x = limits->p1.x;
284 _left.p2.y = limits->p2.y;
288 if (_right.p1.x > limits->p2.x) {
289 _right.p1.x = limits->p2.x;
290 _right.p1.y = limits->p1.y;
291 _right.p2.x = limits->p2.x;
292 _right.p2.y = limits->p2.y;
295 if (left.p1.x >= right.p1.x)
299 _cairo_traps_add_trap (traps, _top, _bottom, &_right, &_left);
301 _cairo_traps_add_trap (traps, _top, _bottom, &_left, &_right);
304 _cairo_traps_add_trap (traps, top, bottom, &left, &right);
307 return traps->status;
311 _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
313 cairo_fixed_t xoff, yoff;
314 cairo_trapezoid_t *t;
317 /* Ugh. The cairo_composite/(Render) interface doesn't allow
318 an offset for the trapezoids. Need to manually shift all
319 the coordinates to align with the offset origin of the
320 intermediate surface. */
322 xoff = _cairo_fixed_from_int (x);
323 yoff = _cairo_fixed_from_int (y);
325 for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
328 t->left.p1.x += xoff;
329 t->left.p1.y += yoff;
330 t->left.p2.x += xoff;
331 t->left.p2.y += yoff;
332 t->right.p1.x += xoff;
333 t->right.p1.y += yoff;
334 t->right.p2.x += xoff;
335 t->right.p2.y += yoff;
340 _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
341 cairo_trapezoid_t *src_traps,
343 double tx, double ty,
344 double sx, double sy)
347 cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
348 cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
350 if (sx == 1.0 && sy == 1.0) {
351 for (i = 0; i < num_traps; i++) {
352 offset_traps[i].top = src_traps[i].top + yoff;
353 offset_traps[i].bottom = src_traps[i].bottom + yoff;
354 offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
355 offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
356 offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
357 offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
358 offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
359 offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
360 offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
361 offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
364 cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
365 cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
367 for (i = 0; i < num_traps; i++) {
368 offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
369 offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
370 offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
371 offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
372 offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
373 offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
374 offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
375 offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
376 offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
377 offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
383 _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
385 cairo_slope_t slope_left, slope_pt, slope_right;
389 if (t->bottom < pt->y)
392 _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
393 _cairo_slope_init (&slope_pt, &t->left.p1, pt);
395 if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
398 _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
399 _cairo_slope_init (&slope_pt, &t->right.p1, pt);
401 if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
408 _cairo_traps_contain (const cairo_traps_t *traps,
414 point.x = _cairo_fixed_from_double (x);
415 point.y = _cairo_fixed_from_double (y);
417 for (i = 0; i < traps->num_traps; i++) {
418 if (_cairo_trap_contains (&traps->traps[i], &point))
426 _line_compute_intersection_x_for_y (const cairo_line_t *line,
429 return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y);
433 _cairo_traps_extents (const cairo_traps_t *traps,
434 cairo_box_t *extents)
438 if (traps->num_traps == 0) {
439 extents->p1.x = extents->p1.y = 0;
440 extents->p2.x = extents->p2.y = 0;
444 extents->p1.x = extents->p1.y = INT32_MAX;
445 extents->p2.x = extents->p2.y = INT32_MIN;
447 for (i = 0; i < traps->num_traps; i++) {
448 const cairo_trapezoid_t *trap = &traps->traps[i];
450 if (trap->top < extents->p1.y)
451 extents->p1.y = trap->top;
452 if (trap->bottom > extents->p2.y)
453 extents->p2.y = trap->bottom;
455 if (trap->left.p1.x < extents->p1.x) {
456 cairo_fixed_t x = trap->left.p1.x;
457 if (trap->top != trap->left.p1.y) {
458 x = _line_compute_intersection_x_for_y (&trap->left,
460 if (x < extents->p1.x)
465 if (trap->left.p2.x < extents->p1.x) {
466 cairo_fixed_t x = trap->left.p2.x;
467 if (trap->bottom != trap->left.p2.y) {
468 x = _line_compute_intersection_x_for_y (&trap->left,
470 if (x < extents->p1.x)
476 if (trap->right.p1.x > extents->p2.x) {
477 cairo_fixed_t x = trap->right.p1.x;
478 if (trap->top != trap->right.p1.y) {
479 x = _line_compute_intersection_x_for_y (&trap->right,
481 if (x > extents->p2.x)
486 if (trap->right.p2.x > extents->p2.x) {
487 cairo_fixed_t x = trap->right.p2.x;
488 if (trap->bottom != trap->right.p2.y) {
489 x = _line_compute_intersection_x_for_y (&trap->right,
491 if (x > extents->p2.x)
500 _mono_edge_is_vertical (const cairo_line_t *line)
502 return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
506 _traps_are_pixel_aligned (cairo_traps_t *traps,
507 cairo_antialias_t antialias)
511 if (antialias == CAIRO_ANTIALIAS_NONE) {
512 for (i = 0; i < traps->num_traps; i++) {
513 if (! _mono_edge_is_vertical (&traps->traps[i].left) ||
514 ! _mono_edge_is_vertical (&traps->traps[i].right))
516 traps->maybe_region = FALSE;
521 for (i = 0; i < traps->num_traps; i++) {
522 if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
523 traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
524 ! _cairo_fixed_is_integer (traps->traps[i].top) ||
525 ! _cairo_fixed_is_integer (traps->traps[i].bottom) ||
526 ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) ||
527 ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
529 traps->maybe_region = FALSE;
539 * _cairo_traps_extract_region:
540 * @traps: a #cairo_traps_t
541 * @region: a #cairo_region_t
543 * Determines if a set of trapezoids are exactly representable as a
544 * cairo region. If so, the passed-in region is initialized to
545 * the area representing the given traps. It should be finalized
546 * with cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
549 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
550 * or %CAIRO_STATUS_NO_MEMORY
553 _cairo_traps_extract_region (cairo_traps_t *traps,
554 cairo_antialias_t antialias,
555 cairo_region_t **region)
557 cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
558 cairo_rectangle_int_t *rects = stack_rects;
559 cairo_int_status_t status;
562 /* we only treat this a hint... */
563 if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region)
564 return CAIRO_INT_STATUS_UNSUPPORTED;
566 if (! _traps_are_pixel_aligned (traps, antialias)) {
567 traps->maybe_region = FALSE;
568 return CAIRO_INT_STATUS_UNSUPPORTED;
571 if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
572 rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
574 if (unlikely (rects == NULL))
575 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
579 for (i = 0; i < traps->num_traps; i++) {
582 if (antialias == CAIRO_ANTIALIAS_NONE) {
583 x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x);
584 y1 = _cairo_fixed_integer_round_down (traps->traps[i].top);
585 x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x);
586 y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom);
588 x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
589 y1 = _cairo_fixed_integer_part (traps->traps[i].top);
590 x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
591 y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
594 if (x2 > x1 && y2 > y1) {
595 rects[rect_count].x = x1;
596 rects[rect_count].y = y1;
597 rects[rect_count].width = x2 - x1;
598 rects[rect_count].height = y2 - y1;
604 *region = cairo_region_create_rectangles (rects, rect_count);
605 status = (*region)->status;
607 if (rects != stack_rects)
614 _cairo_traps_to_boxes (cairo_traps_t *traps,
615 cairo_antialias_t antialias,
616 cairo_boxes_t *boxes)
620 for (i = 0; i < traps->num_traps; i++) {
621 if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
622 traps->traps[i].right.p1.x != traps->traps[i].right.p2.x)
626 _cairo_boxes_init (boxes);
628 boxes->num_boxes = traps->num_traps;
629 boxes->chunks.base = (cairo_box_t *) traps->traps;
630 boxes->chunks.count = traps->num_traps;
631 boxes->chunks.size = traps->num_traps;
633 if (antialias != CAIRO_ANTIALIAS_NONE) {
634 for (i = 0; i < traps->num_traps; i++) {
635 /* Note the traps and boxes alias so we need to take the local copies first. */
636 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
637 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
638 cairo_fixed_t y1 = traps->traps[i].top;
639 cairo_fixed_t y2 = traps->traps[i].bottom;
641 boxes->chunks.base[i].p1.x = x1;
642 boxes->chunks.base[i].p1.y = y1;
643 boxes->chunks.base[i].p2.x = x2;
644 boxes->chunks.base[i].p2.y = y2;
646 if (boxes->is_pixel_aligned) {
647 boxes->is_pixel_aligned =
648 _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
649 _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
653 boxes->is_pixel_aligned = TRUE;
655 for (i = 0; i < traps->num_traps; i++) {
656 /* Note the traps and boxes alias so we need to take the local copies first. */
657 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
658 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
659 cairo_fixed_t y1 = traps->traps[i].top;
660 cairo_fixed_t y2 = traps->traps[i].bottom;
662 /* round down here to match Pixman's behavior when using traps. */
663 boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
664 boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
665 boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
666 boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
673 /* moves trap points such that they become the actual corners of the trapezoid */
675 _sanitize_trap (cairo_trapezoid_t *t)
677 cairo_trapezoid_t s = *t;
679 #define FIX(lr, tb, p) \
680 if (t->lr.p.y != t->tb) { \
681 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); \
685 FIX (left, bottom, p2);
686 FIX (right, top, p1);
687 FIX (right, bottom, p2);
690 cairo_private cairo_status_t
691 _cairo_traps_path (const cairo_traps_t *traps,
692 cairo_path_fixed_t *path)
696 for (i = 0; i < traps->num_traps; i++) {
697 cairo_status_t status;
698 cairo_trapezoid_t trap = traps->traps[i];
700 if (trap.top == trap.bottom)
703 _sanitize_trap (&trap);
705 status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
706 if (unlikely (status)) return status;
707 status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
708 if (unlikely (status)) return status;
709 status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
710 if (unlikely (status)) return status;
711 status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
712 if (unlikely (status)) return status;
713 status = _cairo_path_fixed_close_path (path);
714 if (unlikely (status)) return status;
717 return CAIRO_STATUS_SUCCESS;
721 _cairo_debug_print_traps (FILE *file, const cairo_traps_t *traps)
727 if (traps->has_limits) {
728 printf ("%s: limits=(%d, %d, %d, %d)\n",
730 traps->limits.p1.x, traps->limits.p1.y,
731 traps->limits.p2.x, traps->limits.p2.y);
735 _cairo_traps_extents (traps, &extents);
736 fprintf (file, "extents=(%d, %d, %d, %d)\n",
737 extents.p1.x, extents.p1.y,
738 extents.p2.x, extents.p2.y);
740 for (n = 0; n < traps->num_traps; n++) {
741 fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
743 traps->traps[n].bottom,
744 traps->traps[n].left.p1.x,
745 traps->traps[n].left.p1.y,
746 traps->traps[n].left.p2.x,
747 traps->traps[n].left.p2.y,
748 traps->traps[n].right.p1.x,
749 traps->traps[n].right.p1.y,
750 traps->traps[n].right.p2.x,
751 traps->traps[n].right.p2.y);
755 struct cairo_trap_renderer {
756 cairo_span_renderer_t base;
757 cairo_traps_t *traps;
760 static cairo_status_t
761 span_to_traps (void *abstract_renderer, int y, int h,
762 const cairo_half_open_span_t *spans, unsigned num_spans)
764 struct cairo_trap_renderer *r = abstract_renderer;
765 cairo_fixed_t top, bot;
768 return CAIRO_STATUS_SUCCESS;
770 top = _cairo_fixed_from_int (y);
771 bot = _cairo_fixed_from_int (y + h);
773 if (spans[0].coverage) {
774 cairo_fixed_t x0 = _cairo_fixed_from_int(spans[0].x);
775 cairo_fixed_t x1 = _cairo_fixed_from_int(spans[1].x);
776 cairo_line_t left = { { x0, top }, { x0, bot } },
777 right = { { x1, top }, { x1, bot } };
778 _cairo_traps_add_trap (r->traps, top, bot, &left, &right);
781 } while (--num_spans > 1);
783 return CAIRO_STATUS_SUCCESS;
787 _cairo_rasterise_polygon_to_traps (cairo_polygon_t *polygon,
788 cairo_fill_rule_t fill_rule,
789 cairo_antialias_t antialias,
790 cairo_traps_t *traps)
792 struct cairo_trap_renderer renderer;
793 cairo_scan_converter_t *converter;
794 cairo_int_status_t status;
795 cairo_rectangle_int_t r;
797 TRACE ((stderr, "%s: fill_rule=%d, antialias=%d\n",
798 __FUNCTION__, fill_rule, antialias));
799 assert(antialias == CAIRO_ANTIALIAS_NONE);
801 renderer.traps = traps;
802 renderer.base.render_rows = span_to_traps;
804 _cairo_box_round_to_rectangle (&polygon->extents, &r);
805 converter = _cairo_mono_scan_converter_create (r.x, r.y,
809 status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
810 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
811 status = converter->generate (converter, &renderer.base);
812 converter->destroy (converter);