added MouseWheel event support for Silverlight 3.0
[moon.git] / cairo / src / cairo-bentley-ottmann.c
blobc657dd9cdb803552c7398f046ec32b918a4d507e
1 /*
2 * Copyright © 2004 Carl Worth
3 * Copyright © 2006 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Carl Worth
32 * Contributor(s):
33 * Carl D. Worth <cworth@cworth.org>
36 /* Provide definitions for standalone compilation */
37 #include "cairoint.h"
39 #include "cairo-skiplist-private.h"
40 #include "cairo-freelist-private.h"
42 #define DEBUG_VALIDATE 0
43 #define DEBUG_PRINT_STATE 0
45 typedef cairo_point_t cairo_bo_point32_t;
47 typedef struct _cairo_bo_point128 {
48 cairo_int128_t x;
49 cairo_int128_t y;
50 } cairo_bo_point128_t;
52 typedef struct _cairo_bo_intersect_ordinate {
53 int32_t ordinate;
54 enum { EXACT, INEXACT } exactness;
55 } cairo_bo_intersect_ordinate_t;
57 typedef struct _cairo_bo_intersect_point {
58 cairo_bo_intersect_ordinate_t x;
59 cairo_bo_intersect_ordinate_t y;
60 } cairo_bo_intersect_point_t;
62 typedef struct _cairo_bo_edge cairo_bo_edge_t;
63 typedef struct _sweep_line_elt sweep_line_elt_t;
64 typedef struct _cairo_bo_trap cairo_bo_trap_t;
65 typedef struct _cairo_bo_traps cairo_bo_traps_t;
67 /* A deferred trapezoid of an edge. */
68 struct _cairo_bo_trap {
69 cairo_bo_edge_t *right;
70 int32_t top;
73 struct _cairo_bo_traps {
74 cairo_traps_t *traps;
75 cairo_freelist_t freelist;
77 /* These form the closed bounding box of the original input
78 * points. */
79 cairo_fixed_t xmin;
80 cairo_fixed_t ymin;
81 cairo_fixed_t xmax;
82 cairo_fixed_t ymax;
85 struct _cairo_bo_edge {
86 cairo_bo_point32_t top;
87 cairo_bo_point32_t middle;
88 cairo_bo_point32_t bottom;
89 cairo_bool_t reversed;
90 cairo_bo_edge_t *prev;
91 cairo_bo_edge_t *next;
92 cairo_bo_trap_t *deferred_trap;
93 sweep_line_elt_t *sweep_line_elt;
96 struct _sweep_line_elt {
97 cairo_bo_edge_t *edge;
98 skip_elt_t elt;
101 #define SKIP_ELT_TO_EDGE_ELT(elt) SKIP_LIST_ELT_TO_DATA (sweep_line_elt_t, (elt))
102 #define SKIP_ELT_TO_EDGE(elt) (SKIP_ELT_TO_EDGE_ELT (elt)->edge)
104 typedef enum {
105 CAIRO_BO_STATUS_INTERSECTION,
106 CAIRO_BO_STATUS_PARALLEL,
107 CAIRO_BO_STATUS_NO_INTERSECTION
108 } cairo_bo_status_t;
110 typedef enum {
111 CAIRO_BO_EVENT_TYPE_START,
112 CAIRO_BO_EVENT_TYPE_STOP,
113 CAIRO_BO_EVENT_TYPE_INTERSECTION
114 } cairo_bo_event_type_t;
116 typedef struct _cairo_bo_event {
117 cairo_bo_event_type_t type;
118 cairo_bo_edge_t *e1;
119 cairo_bo_edge_t *e2;
120 cairo_bo_point32_t point;
121 skip_elt_t elt;
122 } cairo_bo_event_t;
124 #define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
126 typedef struct _cairo_bo_event_queue {
127 cairo_skip_list_t intersection_queue;
129 cairo_bo_event_t *startstop_events;
130 cairo_bo_event_t **sorted_startstop_event_ptrs;
131 unsigned next_startstop_event_index;
132 unsigned num_startstop_events;
133 } cairo_bo_event_queue_t;
135 /* This structure extends #cairo_skip_list_t, which must come first. */
136 typedef struct _cairo_bo_sweep_line {
137 cairo_skip_list_t active_edges;
138 cairo_bo_edge_t *head;
139 cairo_bo_edge_t *tail;
140 int32_t current_y;
141 } cairo_bo_sweep_line_t;
144 static inline int
145 _cairo_bo_point32_compare (cairo_bo_point32_t const *a,
146 cairo_bo_point32_t const *b)
148 int cmp = a->y - b->y;
149 if (cmp) return cmp;
150 return a->x - b->x;
153 /* Compare the slope of a to the slope of b, returning 1, 0, -1 if the
154 * slope a is respectively greater than, equal to, or less than the
155 * slope of b.
157 * For each edge, consider the direction vector formed from:
159 * top -> bottom
161 * which is:
163 * (dx, dy) = (bottom.x - top.x, bottom.y - top.y)
165 * We then define the slope of each edge as dx/dy, (which is the
166 * inverse of the slope typically used in math instruction). We never
167 * compute a slope directly as the value approaches infinity, but we
168 * can derive a slope comparison without division as follows, (where
169 * the ? represents our compare operator).
171 * 1. slope(a) ? slope(b)
172 * 2. adx/ady ? bdx/bdy
173 * 3. (adx * bdy) ? (bdx * ady)
175 * Note that from step 2 to step 3 there is no change needed in the
176 * sign of the result since both ady and bdy are guaranteed to be
177 * greater than or equal to 0.
179 * When using this slope comparison to sort edges, some care is needed
180 * when interpreting the results. Since the slope compare operates on
181 * distance vectors from top to bottom it gives a correct left to
182 * right sort for edges that have a common top point, (such as two
183 * edges with start events at the same location). On the other hand,
184 * the sense of the result will be exactly reversed for two edges that
185 * have a common stop point.
187 static int
188 _slope_compare (cairo_bo_edge_t *a,
189 cairo_bo_edge_t *b)
191 /* XXX: We're assuming here that dx and dy will still fit in 32
192 * bits. That's not true in general as there could be overflow. We
193 * should prevent that before the tessellation algorithm
194 * begins.
196 int32_t adx = a->bottom.x - a->top.x;
197 int32_t bdx = b->bottom.x - b->top.x;
199 /* Since the dy's are all positive by construction we can fast
200 * path the case where the two edges point in different directions
201 * with respect to x. */
202 if ((adx ^ bdx) < 0) {
203 return adx < 0 ? -1 : +1;
204 } else {
205 int32_t ady = a->bottom.y - a->top.y;
206 int32_t bdy = b->bottom.y - b->top.y;
207 cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
208 cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
210 return _cairo_int64_cmp (adx_bdy, bdx_ady);
215 * We need to compare the x-coordinates of a pair of lines for a particular y,
216 * without loss of precision.
218 * The x-coordinate along an edge for a given y is:
219 * X = A_x + (Y - A_y) * A_dx / A_dy
221 * So the inequality we wish to test is:
222 * A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy,
223 * where -?- is our inequality operator.
225 * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
226 * all positive, so we can rearrange it thus without causing a sign change:
227 * A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy
228 * - (Y - A_y) * A_dx * B_dy
230 * Given the assumption that all the deltas fit within 32 bits, we can compute
231 * this comparison directly using 128 bit arithmetic.
233 * (And put the burden of the work on developing fast 128 bit ops, which are
234 * required throughout the tessellator.)
236 * See the similar discussion for _slope_compare().
238 static int
239 edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
240 const cairo_bo_edge_t *b,
241 int32_t y)
243 /* XXX: We're assuming here that dx and dy will still fit in 32
244 * bits. That's not true in general as there could be overflow. We
245 * should prevent that before the tessellation algorithm
246 * begins.
248 int32_t adx, ady;
249 int32_t bdx, bdy;
250 cairo_int128_t L, R;
252 adx = a->bottom.x - a->top.x;
253 ady = a->bottom.y - a->top.y;
255 bdx = b->bottom.x - b->top.x;
256 bdy = b->bottom.y - b->top.y;
258 L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy),
259 a->top.x - b->top.x);
261 R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx,
262 ady),
263 y - b->top.y),
264 _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx,
265 bdy),
266 y - a->top.y));
268 /* return _cairo_int128_cmp (L, R); */
269 if (_cairo_int128_lt (L, R))
270 return -1;
271 if (_cairo_int128_gt (L, R))
272 return 1;
273 return 0;
277 * We need to compare the x-coordinate of a line for a particular y wrt to a
278 * given x, without loss of precision.
280 * The x-coordinate along an edge for a given y is:
281 * X = A_x + (Y - A_y) * A_dx / A_dy
283 * So the inequality we wish to test is:
284 * A_x + (Y - A_y) * A_dx / A_dy -?- X
285 * where -?- is our inequality operator.
287 * By construction, we know that A_dy (and (Y - A_y)) are
288 * all positive, so we can rearrange it thus without causing a sign change:
289 * (Y - A_y) * A_dx -?- (X - A_x) * A_dy
291 * Given the assumption that all the deltas fit within 32 bits, we can compute
292 * this comparison directly using 64 bit arithmetic.
294 * See the similar discussion for _slope_compare() and
295 * edges_compare_x_for_y_general().
297 static int
298 edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
299 int32_t y,
300 int32_t x)
302 int32_t adx, ady;
303 int32_t dx, dy;
304 cairo_int64_t L, R;
306 adx = a->bottom.x - a->top.x;
307 ady = a->bottom.y - a->top.y;
309 dy = y - a->top.y;
310 dx = x - a->top.x;
312 L = _cairo_int32x32_64_mul (dy, adx);
313 R = _cairo_int32x32_64_mul (dx, ady);
315 return _cairo_int64_cmp (L, R);
318 static int
319 edges_compare_x_for_y (const cairo_bo_edge_t *a,
320 const cairo_bo_edge_t *b,
321 int32_t y)
323 /* If the sweep-line is currently on an end-point of a line,
324 * then we know its precise x value (and considering that we often need to
325 * compare events at end-points, this happens frequently enough to warrant
326 * special casing).
328 enum {
329 HAVE_NEITHER = 0x0,
330 HAVE_AX = 0x1,
331 HAVE_BX = 0x2,
332 HAVE_BOTH = HAVE_AX | HAVE_BX
333 } have_ax_bx = HAVE_BOTH;
334 int32_t ax, bx;
336 if (y == a->top.y)
337 ax = a->top.x;
338 else if (y == a->bottom.y)
339 ax = a->bottom.x;
340 else
341 have_ax_bx &= ~HAVE_AX;
343 if (y == b->top.y)
344 bx = b->top.x;
345 else if (y == b->bottom.y)
346 bx = b->bottom.x;
347 else
348 have_ax_bx &= ~HAVE_BX;
350 switch (have_ax_bx) {
351 default:
352 case HAVE_NEITHER:
353 return edges_compare_x_for_y_general (a, b, y);
354 case HAVE_AX:
355 return - edge_compare_for_y_against_x (b, y, ax);
356 case HAVE_BX:
357 return edge_compare_for_y_against_x (a, y, bx);
358 case HAVE_BOTH:
359 return ax - bx;
363 static int
364 _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
365 cairo_bo_edge_t *a,
366 cairo_bo_edge_t *b)
368 int cmp;
370 if (a == b)
371 return 0;
373 /* don't bother solving for abscissa if the edges' bounding boxes
374 * can be used to order them. */
376 int32_t amin, amax;
377 int32_t bmin, bmax;
378 if (a->middle.x < a->bottom.x) {
379 amin = a->middle.x;
380 amax = a->bottom.x;
381 } else {
382 amin = a->bottom.x;
383 amax = a->middle.x;
385 if (b->middle.x < b->bottom.x) {
386 bmin = b->middle.x;
387 bmax = b->bottom.x;
388 } else {
389 bmin = b->bottom.x;
390 bmax = b->middle.x;
392 if (amax < bmin) return -1;
393 if (amin > bmax) return +1;
396 cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
397 if (cmp)
398 return cmp;
400 /* The two edges intersect exactly at y, so fall back on slope
401 * comparison. We know that this compare_edges function will be
402 * called only when starting a new edge, (not when stopping an
403 * edge), so we don't have to worry about conditionally inverting
404 * the sense of _slope_compare. */
405 cmp = _slope_compare (a, b);
406 if (cmp)
407 return cmp;
409 /* We've got two collinear edges now. */
411 /* Since we're dealing with start events, prefer comparing top
412 * edges before bottom edges. */
413 cmp = _cairo_bo_point32_compare (&a->top, &b->top);
414 if (cmp)
415 return cmp;
417 cmp = _cairo_bo_point32_compare (&a->bottom, &b->bottom);
418 if (cmp)
419 return cmp;
421 /* Finally, we've got two identical edges. Let's finally
422 * discriminate by a simple pointer comparison, (which works only
423 * because we "know" the edges are all in a single array and don't
424 * move. */
425 if (a > b)
426 return 1;
427 else
428 return -1;
431 static int
432 _sweep_line_elt_compare (void *list,
433 void *a,
434 void *b)
436 cairo_bo_sweep_line_t *sweep_line = list;
437 sweep_line_elt_t *edge_elt_a = a;
438 sweep_line_elt_t *edge_elt_b = b;
440 return _cairo_bo_sweep_line_compare_edges (sweep_line,
441 edge_elt_a->edge,
442 edge_elt_b->edge);
445 static inline int
446 cairo_bo_event_compare (cairo_bo_event_t const *a,
447 cairo_bo_event_t const *b)
449 int cmp;
451 /* The major motion of the sweep line is vertical (top-to-bottom),
452 * and the minor motion is horizontal (left-to-right), dues to the
453 * infinitesimal tilt rule.
455 * Our point comparison function respects these rules.
457 cmp = _cairo_bo_point32_compare (&a->point, &b->point);
458 if (cmp)
459 return cmp;
461 /* The events share a common point, so further discrimination is
462 * determined by the event type. Due to the infinitesimal
463 * shortening rule, stop events come first, then intersection
464 * events, then start events.
466 if (a->type != b->type) {
467 if (a->type == CAIRO_BO_EVENT_TYPE_STOP)
468 return -1;
469 if (a->type == CAIRO_BO_EVENT_TYPE_START)
470 return 1;
472 if (b->type == CAIRO_BO_EVENT_TYPE_STOP)
473 return 1;
474 if (b->type == CAIRO_BO_EVENT_TYPE_START)
475 return -1;
478 /* At this stage we are looking at two events of the same type at
479 * the same point. The final sort key is a slope comparison. We
480 * need a different sense for start and stop events based on the
481 * shortening rule.
483 * Note: Fortunately, we get to ignore errors in the relative
484 * ordering of intersection events. This means we don't even have
485 * to look at e2 here, nor worry about which sense of the slope
486 * comparison test is used for intersection events.
488 cmp = _slope_compare (a->e1, b->e1);
489 if (cmp) {
490 if (a->type == CAIRO_BO_EVENT_TYPE_START)
491 return cmp;
492 else
493 return - cmp;
496 /* Next look at the opposite point. This leaves ambiguities only
497 * for identical edges. */
498 if (a->type == CAIRO_BO_EVENT_TYPE_START) {
499 cmp = _cairo_bo_point32_compare (&b->e1->bottom,
500 &a->e1->bottom);
501 if (cmp)
502 return cmp;
504 else if (a->type == CAIRO_BO_EVENT_TYPE_STOP) {
505 cmp = _cairo_bo_point32_compare (&a->e1->top,
506 &b->e1->top);
507 if (cmp)
508 return cmp;
510 else { /* CAIRO_BO_EVENT_TYPE_INTERSECT */
511 /* For two intersection events at the identical point, we
512 * don't care what order they sort in, but we do care that we
513 * have a stable sort. In particular intersections between
514 * different pairs of edges must never return 0. */
515 cmp = _cairo_bo_point32_compare (&a->e2->top, &b->e2->top);
516 if (cmp)
517 return cmp;
518 cmp = _cairo_bo_point32_compare (&a->e2->bottom, &b->e2->bottom);
519 if (cmp)
520 return cmp;
521 cmp = _cairo_bo_point32_compare (&a->e1->top, &b->e1->top);
522 if (cmp)
523 return cmp;
524 cmp = _cairo_bo_point32_compare (&a->e1->bottom, &b->e1->bottom);
525 if (cmp)
526 return cmp;
529 /* Discrimination based on the edge pointers. */
530 if (a->e1 < b->e1)
531 return -1;
532 if (a->e1 > b->e1)
533 return +1;
534 if (a->e2 < b->e2)
535 return -1;
536 if (a->e2 > b->e2)
537 return +1;
538 return 0;
541 static int
542 cairo_bo_event_compare_abstract (void *list,
543 void *a,
544 void *b)
546 cairo_bo_event_t *event_a = a;
547 cairo_bo_event_t *event_b = b;
549 return cairo_bo_event_compare (event_a, event_b);
552 static int
553 cairo_bo_event_compare_pointers (void const *voida,
554 void const *voidb)
556 cairo_bo_event_t const * const *a = voida;
557 cairo_bo_event_t const * const *b = voidb;
558 if (*a != *b) {
559 int cmp = cairo_bo_event_compare (*a, *b);
560 if (cmp)
561 return cmp;
562 if (*a < *b)
563 return -1;
564 if (*a > *b)
565 return +1;
567 return 0;
570 static inline cairo_int64_t
571 det32_64 (int32_t a,
572 int32_t b,
573 int32_t c,
574 int32_t d)
576 cairo_int64_t ad;
577 cairo_int64_t bc;
579 /* det = a * d - b * c */
580 ad = _cairo_int32x32_64_mul (a, d);
581 bc = _cairo_int32x32_64_mul (b, c);
583 return _cairo_int64_sub (ad, bc);
586 static inline cairo_int128_t
587 det64x32_128 (cairo_int64_t a,
588 int32_t b,
589 cairo_int64_t c,
590 int32_t d)
592 cairo_int128_t ad;
593 cairo_int128_t bc;
595 /* det = a * d - b * c */
596 ad = _cairo_int64x32_128_mul (a, d);
597 bc = _cairo_int64x32_128_mul (c, b);
599 return _cairo_int128_sub (ad, bc);
602 /* Compute the intersection of two lines as defined by two edges. The
603 * result is provided as a coordinate pair of 128-bit integers.
605 * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
606 * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
608 static cairo_bo_status_t
609 intersect_lines (cairo_bo_edge_t *a,
610 cairo_bo_edge_t *b,
611 cairo_bo_intersect_point_t *intersection)
613 cairo_int64_t a_det, b_det;
615 /* XXX: We're assuming here that dx and dy will still fit in 32
616 * bits. That's not true in general as there could be overflow. We
617 * should prevent that before the tessellation algorithm begins.
618 * What we're doing to mitigate this is to perform clamping in
619 * cairo_bo_tessellate_polygon().
621 int32_t dx1 = a->top.x - a->bottom.x;
622 int32_t dy1 = a->top.y - a->bottom.y;
624 int32_t dx2 = b->top.x - b->bottom.x;
625 int32_t dy2 = b->top.y - b->bottom.y;
627 cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
628 cairo_quorem64_t qr;
630 if (_cairo_int64_is_zero (den_det))
631 return CAIRO_BO_STATUS_PARALLEL;
633 a_det = det32_64 (a->top.x, a->top.y,
634 a->bottom.x, a->bottom.y);
635 b_det = det32_64 (b->top.x, b->top.y,
636 b->bottom.x, b->bottom.y);
638 /* x = det (a_det, dx1, b_det, dx2) / den_det */
639 qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
640 b_det, dx2),
641 den_det);
642 if (_cairo_int64_eq (qr.rem, den_det))
643 return CAIRO_BO_STATUS_NO_INTERSECTION;
644 intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
645 intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
647 /* y = det (a_det, dy1, b_det, dy2) / den_det */
648 qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
649 b_det, dy2),
650 den_det);
651 if (_cairo_int64_eq (qr.rem, den_det))
652 return CAIRO_BO_STATUS_NO_INTERSECTION;
653 intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
654 intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
656 return CAIRO_BO_STATUS_INTERSECTION;
659 static int
660 _cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t a,
661 int32_t b)
663 /* First compare the quotient */
664 if (a.ordinate > b)
665 return +1;
666 if (a.ordinate < b)
667 return -1;
668 /* With quotient identical, if remainder is 0 then compare equal */
669 /* Otherwise, the non-zero remainder makes a > b */
670 return INEXACT == a.exactness;
673 /* Does the given edge contain the given point. The point must already
674 * be known to be contained within the line determined by the edge,
675 * (most likely the point results from an intersection of this edge
676 * with another).
678 * If we had exact arithmetic, then this function would simply be a
679 * matter of examining whether the y value of the point lies within
680 * the range of y values of the edge. But since intersection points
681 * are not exact due to being rounded to the nearest integer within
682 * the available precision, we must also examine the x value of the
683 * point.
685 * The definition of "contains" here is that the given intersection
686 * point will be seen by the sweep line after the start event for the
687 * given edge and before the stop event for the edge. See the comments
688 * in the implementation for more details.
690 static cairo_bool_t
691 _cairo_bo_edge_contains_intersect_point (cairo_bo_edge_t *edge,
692 cairo_bo_intersect_point_t *point)
694 int cmp_top, cmp_bottom;
696 /* XXX: When running the actual algorithm, we don't actually need to
697 * compare against edge->top at all here, since any intersection above
698 * top is eliminated early via a slope comparison. We're leaving these
699 * here for now only for the sake of the quadratic-time intersection
700 * finder which needs them.
703 cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->top.y);
704 cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y, edge->bottom.y);
706 if (cmp_top < 0 || cmp_bottom > 0)
708 return FALSE;
711 if (cmp_top > 0 && cmp_bottom < 0)
713 return TRUE;
716 /* At this stage, the point lies on the same y value as either
717 * edge->top or edge->bottom, so we have to examine the x value in
718 * order to properly determine containment. */
720 /* If the y value of the point is the same as the y value of the
721 * top of the edge, then the x value of the point must be greater
722 * to be considered as inside the edge. Similarly, if the y value
723 * of the point is the same as the y value of the bottom of the
724 * edge, then the x value of the point must be less to be
725 * considered as inside. */
727 if (cmp_top == 0)
728 return (_cairo_bo_intersect_ordinate_32_compare (point->x, edge->top.x) > 0);
729 else /* cmp_bottom == 0 */
730 return (_cairo_bo_intersect_ordinate_32_compare (point->x, edge->bottom.x) < 0);
733 /* Compute the intersection of two edges. The result is provided as a
734 * coordinate pair of 128-bit integers.
736 * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection
737 * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the
738 * intersection of the lines defined by the edges occurs outside of
739 * one or both edges, and %CAIRO_BO_STATUS_PARALLEL if the two edges
740 * are exactly parallel.
742 * Note that when determining if a candidate intersection is "inside"
743 * an edge, we consider both the infinitesimal shortening and the
744 * infinitesimal tilt rules described by John Hobby. Specifically, if
745 * the intersection is exactly the same as an edge point, it is
746 * effectively outside (no intersection is returned). Also, if the
747 * intersection point has the same
749 static cairo_bo_status_t
750 _cairo_bo_edge_intersect (cairo_bo_edge_t *a,
751 cairo_bo_edge_t *b,
752 cairo_bo_point32_t *intersection)
754 cairo_bo_status_t status;
755 cairo_bo_intersect_point_t quorem;
757 status = intersect_lines (a, b, &quorem);
758 if (status)
759 return status;
761 if (! _cairo_bo_edge_contains_intersect_point (a, &quorem))
762 return CAIRO_BO_STATUS_NO_INTERSECTION;
764 if (! _cairo_bo_edge_contains_intersect_point (b, &quorem))
765 return CAIRO_BO_STATUS_NO_INTERSECTION;
767 /* Now that we've correctly compared the intersection point and
768 * determined that it lies within the edge, then we know that we
769 * no longer need any more bits of storage for the intersection
770 * than we do for our edge coordinates. We also no longer need the
771 * remainder from the division. */
772 intersection->x = quorem.x.ordinate;
773 intersection->y = quorem.y.ordinate;
775 return CAIRO_BO_STATUS_INTERSECTION;
778 static void
779 _cairo_bo_event_init (cairo_bo_event_t *event,
780 cairo_bo_event_type_t type,
781 cairo_bo_edge_t *e1,
782 cairo_bo_edge_t *e2,
783 cairo_bo_point32_t point)
785 event->type = type;
786 event->e1 = e1;
787 event->e2 = e2;
788 event->point = point;
791 static cairo_status_t
792 _cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
793 cairo_bo_event_t *event)
795 cairo_status_t status = CAIRO_STATUS_SUCCESS;
796 /* Don't insert if there's already an equivalent intersection event in the queue. */
797 if (_cairo_skip_list_insert (&queue->intersection_queue, event,
798 event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL)
799 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
800 return status;
803 static void
804 _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
805 cairo_bo_event_t *event)
807 if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
808 _cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
811 static cairo_bo_event_t *
812 _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
814 skip_elt_t *elt = event_queue->intersection_queue.chains[0];
815 cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL;
816 cairo_bo_event_t *startstop;
818 if (event_queue->next_startstop_event_index == event_queue->num_startstop_events)
819 return intersection;
820 startstop = event_queue->sorted_startstop_event_ptrs[
821 event_queue->next_startstop_event_index];
823 if (!intersection || cairo_bo_event_compare (startstop, intersection) <= 0)
825 event_queue->next_startstop_event_index++;
826 return startstop;
828 return intersection;
831 static cairo_status_t
832 _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
833 cairo_bo_edge_t *edges,
834 int num_edges)
836 int i;
837 cairo_bo_event_t *events, **sorted_event_ptrs;
838 unsigned num_events = 2*num_edges;
840 memset (event_queue, 0, sizeof(*event_queue));
842 _cairo_skip_list_init (&event_queue->intersection_queue,
843 cairo_bo_event_compare_abstract,
844 sizeof (cairo_bo_event_t));
845 if (0 == num_edges)
846 return CAIRO_STATUS_SUCCESS;
848 /* The skip_elt_t field of a cairo_bo_event_t isn't used for start
849 * or stop events, so this allocation is safe. XXX: make the
850 * event type a union so it doesn't always contain the skip
851 * elt? */
852 events = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*));
853 if (events == NULL)
854 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
856 sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events);
857 event_queue->startstop_events = events;
858 event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs;
859 event_queue->num_startstop_events = num_events;
860 event_queue->next_startstop_event_index = 0;
862 for (i = 0; i < num_edges; i++) {
863 sorted_event_ptrs[2*i] = &events[2*i];
864 sorted_event_ptrs[2*i+1] = &events[2*i+1];
866 /* Initialize "middle" to top */
867 edges[i].middle = edges[i].top;
869 _cairo_bo_event_init (&events[2*i],
870 CAIRO_BO_EVENT_TYPE_START,
871 &edges[i], NULL,
872 edges[i].top);
874 _cairo_bo_event_init (&events[2*i+1],
875 CAIRO_BO_EVENT_TYPE_STOP,
876 &edges[i], NULL,
877 edges[i].bottom);
880 qsort (sorted_event_ptrs, num_events,
881 sizeof(cairo_bo_event_t *),
882 cairo_bo_event_compare_pointers);
883 return CAIRO_STATUS_SUCCESS;
886 static void
887 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
889 _cairo_skip_list_fini (&event_queue->intersection_queue);
890 if (event_queue->startstop_events)
891 free (event_queue->startstop_events);
894 static cairo_status_t
895 _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue,
896 cairo_bo_edge_t *left,
897 cairo_bo_edge_t *right)
899 cairo_bo_status_t status;
900 cairo_bo_point32_t intersection;
901 cairo_bo_event_t event;
903 if (left == NULL || right == NULL)
904 return CAIRO_STATUS_SUCCESS;
906 /* The names "left" and "right" here are correct descriptions of
907 * the order of the two edges within the active edge list. So if a
908 * slope comparison also puts left less than right, then we know
909 * that the intersection of these two segments has oalready
910 * occurred before the current sweep line position. */
911 if (_slope_compare (left, right) < 0)
912 return CAIRO_STATUS_SUCCESS;
914 status = _cairo_bo_edge_intersect (left, right, &intersection);
915 if (status == CAIRO_BO_STATUS_PARALLEL ||
916 status == CAIRO_BO_STATUS_NO_INTERSECTION)
918 return CAIRO_STATUS_SUCCESS;
921 _cairo_bo_event_init (&event,
922 CAIRO_BO_EVENT_TYPE_INTERSECTION,
923 left, right,
924 intersection);
926 return _cairo_bo_event_queue_insert (event_queue, &event);
929 static void
930 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
932 _cairo_skip_list_init (&sweep_line->active_edges,
933 _sweep_line_elt_compare,
934 sizeof (sweep_line_elt_t));
935 sweep_line->head = NULL;
936 sweep_line->tail = NULL;
937 sweep_line->current_y = 0;
940 static void
941 _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
943 _cairo_skip_list_fini (&sweep_line->active_edges);
946 static cairo_status_t
947 _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
948 cairo_bo_edge_t *edge)
950 skip_elt_t *next_elt;
951 sweep_line_elt_t *sweep_line_elt;
952 cairo_bo_edge_t **prev_of_next, **next_of_prev;
954 sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
955 1 /* unique inserts*/);
956 if (sweep_line_elt == NULL)
957 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
959 next_elt = sweep_line_elt->elt.next[0];
960 if (next_elt)
961 prev_of_next = & (SKIP_ELT_TO_EDGE (next_elt)->prev);
962 else
963 prev_of_next = &sweep_line->tail;
965 if (*prev_of_next)
966 next_of_prev = &(*prev_of_next)->next;
967 else
968 next_of_prev = &sweep_line->head;
970 edge->prev = *prev_of_next;
971 edge->next = *next_of_prev;
972 *prev_of_next = edge;
973 *next_of_prev = edge;
975 edge->sweep_line_elt = sweep_line_elt;
977 return CAIRO_STATUS_SUCCESS;
980 static void
981 _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line,
982 cairo_bo_edge_t *edge)
984 cairo_bo_edge_t **left_next, **right_prev;
986 _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
988 left_next = &sweep_line->head;
989 if (edge->prev)
990 left_next = &edge->prev->next;
992 right_prev = &sweep_line->tail;
993 if (edge->next)
994 right_prev = &edge->next->prev;
996 *left_next = edge->next;
997 *right_prev = edge->prev;
1000 static void
1001 _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line,
1002 cairo_bo_edge_t *left,
1003 cairo_bo_edge_t *right)
1005 sweep_line_elt_t *left_elt, *right_elt;
1006 cairo_bo_edge_t **before_left, **after_right;
1008 /* Within the skip list we can do the swap simply by swapping the
1009 * pointers to the edge elements and leaving all of the skip list
1010 * elements and pointers unchanged. */
1011 left_elt = left->sweep_line_elt;
1012 right_elt = SKIP_ELT_TO_EDGE_ELT (left_elt->elt.next[0]);
1014 left_elt->edge = right;
1015 right->sweep_line_elt = left_elt;
1017 right_elt->edge = left;
1018 left->sweep_line_elt = right_elt;
1020 /* Within the doubly-linked list of edges, there's a bit more
1021 * bookkeeping involved with the swap. */
1022 before_left = &sweep_line->head;
1023 if (left->prev)
1024 before_left = &left->prev->next;
1025 *before_left = right;
1027 after_right = &sweep_line->tail;
1028 if (right->next)
1029 after_right = &right->next->prev;
1030 *after_right = left;
1032 left->next = right->next;
1033 right->next = left;
1035 right->prev = left->prev;
1036 left->prev = right;
1039 #if DEBUG_PRINT_STATE
1040 static void
1041 _cairo_bo_edge_print (cairo_bo_edge_t *edge)
1043 printf ("(0x%x, 0x%x)-(0x%x, 0x%x)",
1044 edge->top.x, edge->top.y,
1045 edge->bottom.x, edge->bottom.y);
1048 static void
1049 _cairo_bo_event_print (cairo_bo_event_t *event)
1051 switch (event->type) {
1052 case CAIRO_BO_EVENT_TYPE_START:
1053 printf ("Start: ");
1054 break;
1055 case CAIRO_BO_EVENT_TYPE_STOP:
1056 printf ("Stop: ");
1057 break;
1058 case CAIRO_BO_EVENT_TYPE_INTERSECTION:
1059 printf ("Intersection: ");
1060 break;
1062 printf ("(%d, %d)\t", event->point.x, event->point.y);
1063 _cairo_bo_edge_print (event->e1);
1064 if (event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) {
1065 printf (" X ");
1066 _cairo_bo_edge_print (event->e2);
1068 printf ("\n");
1071 static void
1072 _cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue)
1074 skip_elt_t *elt;
1075 /* XXX: fixme to print the start/stop array too. */
1076 cairo_skip_list_t *queue = &event_queue->intersection_queue;
1077 cairo_bo_event_t *event;
1079 printf ("Event queue:\n");
1081 for (elt = queue->chains[0];
1082 elt;
1083 elt = elt->next[0])
1085 event = SKIP_ELT_TO_EVENT (elt);
1086 _cairo_bo_event_print (event);
1090 static void
1091 _cairo_bo_sweep_line_print (cairo_bo_sweep_line_t *sweep_line)
1093 cairo_bool_t first = TRUE;
1094 skip_elt_t *elt;
1095 cairo_bo_edge_t *edge;
1097 printf ("Sweep line (reversed): ");
1099 for (edge = sweep_line->tail;
1100 edge;
1101 edge = edge->prev)
1103 if (!first)
1104 printf (", ");
1105 _cairo_bo_edge_print (edge);
1106 first = FALSE;
1108 printf ("\n");
1111 printf ("Sweep line from edge list: ");
1112 first = TRUE;
1113 for (edge = sweep_line->head;
1114 edge;
1115 edge = edge->next)
1117 if (!first)
1118 printf (", ");
1119 _cairo_bo_edge_print (edge);
1120 first = FALSE;
1122 printf ("\n");
1124 printf ("Sweep line from skip list: ");
1125 first = TRUE;
1126 for (elt = sweep_line->active_edges.chains[0];
1127 elt;
1128 elt = elt->next[0])
1130 if (!first)
1131 printf (", ");
1132 _cairo_bo_edge_print (SKIP_ELT_TO_EDGE (elt));
1133 first = FALSE;
1135 printf ("\n");
1138 static void
1139 print_state (const char *msg,
1140 cairo_bo_event_queue_t *event_queue,
1141 cairo_bo_sweep_line_t *sweep_line)
1143 printf ("%s\n", msg);
1144 _cairo_bo_event_queue_print (event_queue);
1145 _cairo_bo_sweep_line_print (sweep_line);
1146 printf ("\n");
1148 #endif
1150 /* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t
1151 * of bo_traps. */
1152 static cairo_status_t
1153 _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
1154 int32_t bot,
1155 cairo_bo_traps_t *bo_traps)
1157 cairo_fixed_t fixed_top, fixed_bot;
1158 cairo_bo_trap_t *trap = left->deferred_trap;
1159 cairo_bo_edge_t *right;
1161 if (!trap)
1162 return CAIRO_STATUS_SUCCESS;
1164 /* If the right edge of the trapezoid stopped earlier than the
1165 * left edge, then cut the trapezoid bottom early. */
1166 right = trap->right;
1167 if (right->bottom.y < bot)
1168 bot = right->bottom.y;
1170 fixed_top = trap->top;
1171 fixed_bot = bot;
1173 /* Only emit trapezoids with positive height. */
1174 if (fixed_top < fixed_bot) {
1175 cairo_line_t left_line;
1176 cairo_line_t right_line;
1177 cairo_fixed_t xmin = bo_traps->xmin;
1178 cairo_fixed_t ymin = bo_traps->ymin;
1179 fixed_top += ymin;
1180 fixed_bot += ymin;
1182 left_line.p1.x = left->top.x + xmin;
1183 left_line.p1.y = left->top.y + ymin;
1184 right_line.p1.x = right->top.x + xmin;
1185 right_line.p1.y = right->top.y + ymin;
1187 left_line.p2.x = left->bottom.x + xmin;
1188 left_line.p2.y = left->bottom.y + ymin;
1189 right_line.p2.x = right->bottom.x + xmin;
1190 right_line.p2.y = right->bottom.y + ymin;
1192 /* Avoid emitting the trapezoid if it is obviously degenerate.
1193 * TODO: need a real collinearity test here for the cases
1194 * where the trapezoid is degenerate, yet the top and bottom
1195 * coordinates aren't equal. */
1196 if (left_line.p1.x != right_line.p1.x ||
1197 left_line.p1.y != right_line.p1.y ||
1198 left_line.p2.x != right_line.p2.x ||
1199 left_line.p2.y != right_line.p2.y)
1201 _cairo_traps_add_trap (bo_traps->traps,
1202 fixed_top, fixed_bot,
1203 &left_line, &right_line);
1205 #if DEBUG_PRINT_STATE
1206 printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
1207 "right=(%08x,%08x)-(%08x,%08x) top=%08x, bot=%08x\n",
1208 left->top.x, left->top.y, left->bottom.x, left->bottom.y,
1209 right->top.x, right->top.y, right->bottom.x, right->bottom.y,
1210 trap->top, bot);
1211 #endif
1215 _cairo_freelist_free (&bo_traps->freelist, trap);
1216 left->deferred_trap = NULL;
1218 return _cairo_traps_status (bo_traps->traps);
1221 /* Start a new trapezoid at the given top y coordinate, whose edges
1222 * are `edge' and `edge->next'. If `edge' already has a trapezoid,
1223 * then either add it to the traps in `bo_traps', if the trapezoid's
1224 * right edge differs from `edge->next', or do nothing if the new
1225 * trapezoid would be a continuation of the existing one. */
1226 static cairo_status_t
1227 _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *edge,
1228 int32_t top,
1229 cairo_bo_traps_t *bo_traps)
1231 cairo_status_t status;
1232 cairo_bo_trap_t *trap = edge->deferred_trap;
1234 if (trap) {
1235 if (trap->right == edge->next) return CAIRO_STATUS_SUCCESS;
1236 status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
1237 if (status)
1238 return status;
1241 if (edge->next) {
1242 trap = edge->deferred_trap = _cairo_freelist_alloc (&bo_traps->freelist);
1243 if (!edge->deferred_trap)
1244 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1246 trap->right = edge->next;
1247 trap->top = top;
1249 return CAIRO_STATUS_SUCCESS;
1252 static void
1253 _cairo_bo_traps_init (cairo_bo_traps_t *bo_traps,
1254 cairo_traps_t *traps,
1255 cairo_fixed_t xmin,
1256 cairo_fixed_t ymin,
1257 cairo_fixed_t xmax,
1258 cairo_fixed_t ymax)
1260 bo_traps->traps = traps;
1261 _cairo_freelist_init (&bo_traps->freelist, sizeof(cairo_bo_trap_t));
1262 bo_traps->xmin = xmin;
1263 bo_traps->ymin = ymin;
1264 bo_traps->xmax = xmax;
1265 bo_traps->ymax = ymax;
1268 static void
1269 _cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps)
1271 _cairo_freelist_fini (&bo_traps->freelist);
1274 #if DEBUG_VALIDATE
1275 static void
1276 _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
1278 cairo_bo_edge_t *edge;
1279 skip_elt_t *elt;
1281 /* March through both the skip list's singly-linked list and the
1282 * sweep line's own list through pointers in the edges themselves
1283 * and make sure they agree at every point. */
1285 for (edge = sweep_line->head, elt = sweep_line->active_edges.chains[0];
1286 edge && elt;
1287 edge = edge->next, elt = elt->next[0])
1289 if (SKIP_ELT_TO_EDGE (elt) != edge) {
1290 fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n");
1291 abort ();
1295 if (edge || elt) {
1296 fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n");
1297 abort ();
1300 #endif
1303 static cairo_status_t
1304 _active_edges_to_traps (cairo_bo_edge_t *head,
1305 int32_t top,
1306 cairo_fill_rule_t fill_rule,
1307 cairo_bo_traps_t *bo_traps)
1309 cairo_status_t status;
1310 int in_out = 0;
1311 cairo_bo_edge_t *edge;
1313 for (edge = head; edge; edge = edge->next) {
1314 if (fill_rule == CAIRO_FILL_RULE_WINDING) {
1315 if (edge->reversed)
1316 in_out++;
1317 else
1318 in_out--;
1319 if (in_out == 0) {
1320 status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
1321 if (status)
1322 return status;
1323 continue;
1325 } else {
1326 in_out++;
1327 if ((in_out & 1) == 0) {
1328 status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
1329 if (status)
1330 return status;
1331 continue;
1335 status = _cairo_bo_edge_start_or_continue_trap (edge, top, bo_traps);
1336 if (status)
1337 return status;
1340 return CAIRO_STATUS_SUCCESS;
1343 /* Execute a single pass of the Bentley-Ottmann algorithm on edges,
1344 * generating trapezoids according to the fill_rule and appending them
1345 * to traps. */
1346 static cairo_status_t
1347 _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
1348 int num_edges,
1349 cairo_fill_rule_t fill_rule,
1350 cairo_traps_t *traps,
1351 cairo_fixed_t xmin,
1352 cairo_fixed_t ymin,
1353 cairo_fixed_t xmax,
1354 cairo_fixed_t ymax,
1355 int *num_intersections)
1357 cairo_status_t status;
1358 int intersection_count = 0;
1359 cairo_bo_event_queue_t event_queue;
1360 cairo_bo_sweep_line_t sweep_line;
1361 cairo_bo_traps_t bo_traps;
1362 cairo_bo_event_t *event, event_saved;
1363 cairo_bo_edge_t *edge;
1364 cairo_bo_edge_t *left, *right;
1365 cairo_bo_edge_t *edge1, *edge2;
1367 status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
1368 if (status)
1369 return status;
1371 _cairo_bo_sweep_line_init (&sweep_line);
1372 _cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
1374 #if DEBUG_PRINT_STATE
1375 print_state ("After initializing", &event_queue, &sweep_line);
1376 #endif
1378 while (1)
1380 event = _cairo_bo_event_dequeue (&event_queue);
1381 if (!event)
1382 break;
1384 if (event->point.y != sweep_line.current_y) {
1385 status = _active_edges_to_traps (sweep_line.head,
1386 sweep_line.current_y,
1387 fill_rule, &bo_traps);
1388 if (status)
1389 goto unwind;
1391 sweep_line.current_y = event->point.y;
1394 event_saved = *event;
1395 _cairo_bo_event_queue_delete (&event_queue, event);
1396 event = &event_saved;
1398 switch (event->type) {
1399 case CAIRO_BO_EVENT_TYPE_START:
1400 edge = event->e1;
1402 status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
1403 if (status)
1404 goto unwind;
1405 /* Cache the insert position for use in pass 2.
1406 event->e2 = Sortlist::prev (sweep_line, edge);
1409 left = edge->prev;
1410 right = edge->next;
1412 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
1413 if (status)
1414 goto unwind;
1416 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
1417 if (status)
1418 goto unwind;
1420 #if DEBUG_PRINT_STATE
1421 print_state ("After processing start", &event_queue, &sweep_line);
1422 #endif
1423 break;
1425 case CAIRO_BO_EVENT_TYPE_STOP:
1426 edge = event->e1;
1428 left = edge->prev;
1429 right = edge->next;
1431 _cairo_bo_sweep_line_delete (&sweep_line, edge);
1433 status = _cairo_bo_edge_end_trap (edge, edge->bottom.y, &bo_traps);
1434 if (status)
1435 goto unwind;
1437 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
1438 if (status)
1439 goto unwind;
1441 #if DEBUG_PRINT_STATE
1442 print_state ("After processing stop", &event_queue, &sweep_line);
1443 #endif
1444 break;
1446 case CAIRO_BO_EVENT_TYPE_INTERSECTION:
1447 edge1 = event->e1;
1448 edge2 = event->e2;
1450 /* skip this intersection if its edges are not adjacent */
1451 if (edge2 != edge1->next)
1452 break;
1454 intersection_count++;
1456 edge1->middle = event->point;
1457 edge2->middle = event->point;
1459 left = edge1->prev;
1460 right = edge2->next;
1462 _cairo_bo_sweep_line_swap (&sweep_line, edge1, edge2);
1464 /* after the swap e2 is left of e1 */
1466 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
1467 left, edge2);
1468 if (status)
1469 goto unwind;
1471 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
1472 edge1, right);
1473 if (status)
1474 goto unwind;
1476 #if DEBUG_PRINT_STATE
1477 print_state ("After processing intersection", &event_queue, &sweep_line);
1478 #endif
1479 break;
1481 #if DEBUG_VALIDATE
1482 _cairo_bo_sweep_line_validate (&sweep_line);
1483 #endif
1486 *num_intersections = intersection_count;
1487 unwind:
1488 for (edge = sweep_line.head; edge; edge = edge->next) {
1489 cairo_status_t status2 = _cairo_bo_edge_end_trap (edge,
1490 sweep_line.current_y,
1491 &bo_traps);
1492 if (!status)
1493 status = status2;
1495 _cairo_bo_traps_fini (&bo_traps);
1496 _cairo_bo_sweep_line_fini (&sweep_line);
1497 _cairo_bo_event_queue_fini (&event_queue);
1498 return status;
1501 static void
1502 update_minmax(cairo_fixed_t *inout_min,
1503 cairo_fixed_t *inout_max,
1504 cairo_fixed_t v)
1506 if (v < *inout_min)
1507 *inout_min = v;
1508 if (v > *inout_max)
1509 *inout_max = v;
1512 cairo_status_t
1513 _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
1514 const cairo_polygon_t *polygon,
1515 cairo_fill_rule_t fill_rule)
1517 int intersections;
1518 cairo_status_t status;
1519 cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)];
1520 cairo_bo_edge_t *edges;
1521 cairo_fixed_t xmin = 0x7FFFFFFF;
1522 cairo_fixed_t ymin = 0x7FFFFFFF;
1523 cairo_fixed_t xmax = -0x80000000;
1524 cairo_fixed_t ymax = -0x80000000;
1525 cairo_box_t limit;
1526 cairo_bool_t has_limits;
1527 int num_bo_edges;
1528 int i;
1530 if (0 == polygon->num_edges)
1531 return CAIRO_STATUS_SUCCESS;
1533 has_limits = _cairo_traps_get_limit (traps, &limit);
1535 if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
1536 edges = stack_edges;
1537 } else {
1538 edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
1539 if (edges == NULL)
1540 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1543 /* Figure out the bounding box of the input coordinates and
1544 * validate that we're not given invalid polygon edges. */
1545 for (i = 0; i < polygon->num_edges; i++) {
1546 update_minmax (&xmin, &xmax, polygon->edges[i].edge.p1.x);
1547 update_minmax (&ymin, &ymax, polygon->edges[i].edge.p1.y);
1548 update_minmax (&xmin, &xmax, polygon->edges[i].edge.p2.x);
1549 update_minmax (&ymin, &ymax, polygon->edges[i].edge.p2.y);
1550 assert (polygon->edges[i].edge.p1.y <= polygon->edges[i].edge.p2.y &&
1551 "BUG: tessellator given upside down or horizontal edges");
1554 /* The tessellation functions currently assume that no line
1555 * segment extends more than 2^31-1 in either dimension. We
1556 * guarantee this by offsetting the internal coordinates to the
1557 * range [0,2^31-1], and clamping to 2^31-1 if a coordinate
1558 * exceeds the range (and yes, this generates an incorrect
1559 * result). First we have to clamp the bounding box itself. */
1560 /* XXX: Rather than changing the input values, a better approach
1561 * would be to detect out-of-bounds input and return a
1562 * CAIRO_STATUS_OVERFLOW value to the user. */
1563 if (xmax - xmin < 0)
1564 xmax = xmin + 0x7FFFFFFF;
1565 if (ymax - ymin < 0)
1566 ymax = ymin + 0x7FFFFFFF;
1568 for (i = 0, num_bo_edges = 0; i < polygon->num_edges; i++) {
1569 cairo_bo_edge_t *edge = &edges[num_bo_edges];
1570 cairo_point_t top = polygon->edges[i].edge.p1;
1571 cairo_point_t bot = polygon->edges[i].edge.p2;
1573 /* Discard the edge if it lies outside the limits of traps. */
1574 if (has_limits) {
1575 /* Strictly above or below the limits? */
1576 if (bot.y <= limit.p1.y || top.y >= limit.p2.y)
1577 continue;
1580 /* Offset coordinates into the non-negative range. */
1581 top.x -= xmin;
1582 top.y -= ymin;
1583 bot.x -= xmin;
1584 bot.y -= ymin;
1586 /* If the coordinates are still negative, then their extent is
1587 * overflowing 2^31-1. We're going to kludge it and clamp the
1588 * coordinates into the clamped bounding box. */
1589 if (top.x < 0) top.x = xmax - xmin;
1590 if (top.y < 0) top.y = ymax - ymin;
1591 if (bot.x < 0) bot.x = xmax - xmin;
1592 if (bot.y < 0) bot.y = ymax - ymin;
1594 if (top.y == bot.y) {
1595 /* Clamping might have produced horizontal edges. Ignore
1596 * those. */
1597 continue;
1599 assert (top.y < bot.y &&
1600 "BUG: clamping the input range flipped the "
1601 "orientation of an edge");
1603 edge->top.x = top.x;
1604 edge->top.y = top.y;
1605 edge->bottom.x = bot.x;
1606 edge->bottom.y = bot.y;
1607 /* XXX: The 'clockWise' name that cairo_polygon_t uses is
1608 * totally bogus. It's really a (negated!) description of
1609 * whether the edge is reversed. */
1610 edge->reversed = (! polygon->edges[i].clockWise);
1611 edge->deferred_trap = NULL;
1612 edge->prev = NULL;
1613 edge->next = NULL;
1614 edge->sweep_line_elt = NULL;
1616 num_bo_edges++;
1619 /* XXX: This would be the convenient place to throw in multiple
1620 * passes of the Bentley-Ottmann algorithm. It would merely
1621 * require storing the results of each pass into a temporary
1622 * cairo_traps_t. */
1623 status = _cairo_bentley_ottmann_tessellate_bo_edges (edges, num_bo_edges,
1624 fill_rule, traps,
1625 xmin, ymin, xmax, ymax,
1626 &intersections);
1628 if (edges != stack_edges)
1629 free (edges);
1631 return status;
1634 #if 0
1635 static cairo_bool_t
1636 edges_have_an_intersection_quadratic (cairo_bo_edge_t *edges,
1637 int num_edges)
1640 int i, j;
1641 cairo_bo_edge_t *a, *b;
1642 cairo_bo_point32_t intersection;
1643 cairo_bo_status_t status;
1645 /* We must not be given any upside-down edges. */
1646 for (i = 0; i < num_edges; i++) {
1647 assert (_cairo_bo_point32_compare (&edges[i].top, &edges[i].bottom) < 0);
1648 edges[i].top.x <<= CAIRO_BO_GUARD_BITS;
1649 edges[i].top.y <<= CAIRO_BO_GUARD_BITS;
1650 edges[i].bottom.x <<= CAIRO_BO_GUARD_BITS;
1651 edges[i].bottom.y <<= CAIRO_BO_GUARD_BITS;
1654 for (i = 0; i < num_edges; i++) {
1655 for (j = 0; j < num_edges; j++) {
1656 if (i == j)
1657 continue;
1659 a = &edges[i];
1660 b = &edges[j];
1662 status = _cairo_bo_edge_intersect (a, b, &intersection);
1663 if (status == CAIRO_BO_STATUS_PARALLEL ||
1664 status == CAIRO_BO_STATUS_NO_INTERSECTION)
1666 continue;
1669 printf ("Found intersection (%d,%d) between (%d,%d)-(%d,%d) and (%d,%d)-(%d,%d)\n",
1670 intersection.x,
1671 intersection.y,
1672 a->top.x, a->top.y,
1673 a->bottom.x, a->bottom.y,
1674 b->top.x, b->top.y,
1675 b->bottom.x, b->bottom.y);
1677 return TRUE;
1680 return FALSE;
1683 #define TEST_MAX_EDGES 10
1685 typedef struct test {
1686 const char *name;
1687 const char *description;
1688 int num_edges;
1689 cairo_bo_edge_t edges[TEST_MAX_EDGES];
1690 } test_t;
1692 static test_t
1693 tests[] = {
1695 "3 near misses",
1696 "3 edges all intersecting very close to each other",
1699 { { 4, 2}, {0, 0}, { 9, 9}, NULL, NULL },
1700 { { 7, 2}, {0, 0}, { 2, 3}, NULL, NULL },
1701 { { 5, 2}, {0, 0}, { 1, 7}, NULL, NULL }
1705 "inconsistent data",
1706 "Derived from random testing---was leading to skip list and edge list disagreeing.",
1709 { { 2, 3}, {0, 0}, { 8, 9}, NULL, NULL },
1710 { { 2, 3}, {0, 0}, { 6, 7}, NULL, NULL }
1714 "failed sort",
1715 "A test derived from random testing that leads to an inconsistent sort --- looks like we just can't attempt to validate the sweep line with edge_compare?",
1718 { { 6, 2}, {0, 0}, { 6, 5}, NULL, NULL },
1719 { { 3, 5}, {0, 0}, { 5, 6}, NULL, NULL },
1720 { { 9, 2}, {0, 0}, { 5, 6}, NULL, NULL },
1724 "minimal-intersection",
1725 "Intersection of a two from among the smallest possible edges.",
1728 { { 0, 0}, {0, 0}, { 1, 1}, NULL, NULL },
1729 { { 1, 0}, {0, 0}, { 0, 1}, NULL, NULL }
1733 "simple",
1734 "A simple intersection of two edges at an integer (2,2).",
1737 { { 1, 1}, {0, 0}, { 3, 3}, NULL, NULL },
1738 { { 2, 1}, {0, 0}, { 2, 3}, NULL, NULL }
1742 "bend-to-horizontal",
1743 "With intersection truncation one edge bends to horizontal",
1746 { { 9, 1}, {0, 0}, {3, 7}, NULL, NULL },
1747 { { 3, 5}, {0, 0}, {9, 9}, NULL, NULL }
1754 "endpoint",
1755 "An intersection that occurs at the endpoint of a segment.",
1757 { { 4, 6}, { 5, 6}, NULL, { { NULL }} },
1758 { { 4, 5}, { 5, 7}, NULL, { { NULL }} },
1759 { { 0, 0}, { 0, 0}, NULL, { { NULL }} },
1763 name = "overlapping",
1764 desc = "Parallel segments that share an endpoint, with different slopes.",
1765 edges = {
1766 { top = { x = 2, y = 0}, bottom = { x = 1, y = 1}},
1767 { top = { x = 2, y = 0}, bottom = { x = 0, y = 2}},
1768 { top = { x = 0, y = 3}, bottom = { x = 1, y = 3}},
1769 { top = { x = 0, y = 3}, bottom = { x = 2, y = 3}},
1770 { top = { x = 0, y = 4}, bottom = { x = 0, y = 6}},
1771 { top = { x = 0, y = 5}, bottom = { x = 0, y = 6}}
1775 name = "hobby_stage_3",
1776 desc = "A particularly tricky part of the 3rd stage of the 'hobby' test below.",
1777 edges = {
1778 { top = { x = -1, y = -2}, bottom = { x = 4, y = 2}},
1779 { top = { x = 5, y = 3}, bottom = { x = 9, y = 5}},
1780 { top = { x = 5, y = 3}, bottom = { x = 6, y = 3}},
1784 name = "hobby",
1785 desc = "Example from John Hobby's paper. Requires 3 passes of the iterative algorithm.",
1786 edges = {
1787 { top = { x = 0, y = 0}, bottom = { x = 9, y = 5}},
1788 { top = { x = 0, y = 0}, bottom = { x = 13, y = 6}},
1789 { top = { x = -1, y = -2}, bottom = { x = 9, y = 5}}
1793 name = "slope",
1794 desc = "Edges with same start/stop points but different slopes",
1795 edges = {
1796 { top = { x = 4, y = 1}, bottom = { x = 6, y = 3}},
1797 { top = { x = 4, y = 1}, bottom = { x = 2, y = 3}},
1798 { top = { x = 2, y = 4}, bottom = { x = 4, y = 6}},
1799 { top = { x = 6, y = 4}, bottom = { x = 4, y = 6}}
1803 name = "horizontal",
1804 desc = "Test of a horizontal edge",
1805 edges = {
1806 { top = { x = 1, y = 1}, bottom = { x = 6, y = 6}},
1807 { top = { x = 2, y = 3}, bottom = { x = 5, y = 3}}
1811 name = "vertical",
1812 desc = "Test of a vertical edge",
1813 edges = {
1814 { top = { x = 5, y = 1}, bottom = { x = 5, y = 7}},
1815 { top = { x = 2, y = 4}, bottom = { x = 8, y = 5}}
1819 name = "congruent",
1820 desc = "Two overlapping edges with the same slope",
1821 edges = {
1822 { top = { x = 5, y = 1}, bottom = { x = 5, y = 7}},
1823 { top = { x = 5, y = 2}, bottom = { x = 5, y = 6}},
1824 { top = { x = 2, y = 4}, bottom = { x = 8, y = 5}}
1828 name = "multi",
1829 desc = "Several segments with a common intersection point",
1830 edges = {
1831 { top = { x = 1, y = 2}, bottom = { x = 5, y = 4} },
1832 { top = { x = 1, y = 1}, bottom = { x = 5, y = 5} },
1833 { top = { x = 2, y = 1}, bottom = { x = 4, y = 5} },
1834 { top = { x = 4, y = 1}, bottom = { x = 2, y = 5} },
1835 { top = { x = 5, y = 1}, bottom = { x = 1, y = 5} },
1836 { top = { x = 5, y = 2}, bottom = { x = 1, y = 4} }
1842 static int
1843 run_test (const char *test_name,
1844 cairo_bo_edge_t *test_edges,
1845 int num_edges)
1847 int i, intersections, passes;
1848 cairo_bo_edge_t *edges;
1849 cairo_array_t intersected_edges;
1851 printf ("Testing: %s\n", test_name);
1853 _cairo_array_init (&intersected_edges, sizeof (cairo_bo_edge_t));
1855 intersections = _cairo_bentley_ottmann_intersect_edges (test_edges, num_edges, &intersected_edges);
1856 if (intersections)
1857 printf ("Pass 1 found %d intersections:\n", intersections);
1860 /* XXX: Multi-pass Bentley-Ottmmann. Preferable would be to add a
1861 * pass of Hobby's tolerance-square algorithm instead. */
1862 passes = 1;
1863 while (intersections) {
1864 int num_edges = _cairo_array_num_elements (&intersected_edges);
1865 passes++;
1866 edges = _cairo_malloc_ab (num_edges, sizeof (cairo_bo_edge_t));
1867 assert (edges != NULL);
1868 memcpy (edges, _cairo_array_index (&intersected_edges, 0), num_edges * sizeof (cairo_bo_edge_t));
1869 _cairo_array_fini (&intersected_edges);
1870 _cairo_array_init (&intersected_edges, sizeof (cairo_bo_edge_t));
1871 intersections = _cairo_bentley_ottmann_intersect_edges (edges, num_edges, &intersected_edges);
1872 free (edges);
1874 if (intersections){
1875 printf ("Pass %d found %d remaining intersections:\n", passes, intersections);
1876 } else {
1877 if (passes > 3)
1878 for (i = 0; i < passes; i++)
1879 printf ("*");
1880 printf ("No remainining intersections found after pass %d\n", passes);
1884 if (edges_have_an_intersection_quadratic (_cairo_array_index (&intersected_edges, 0),
1885 _cairo_array_num_elements (&intersected_edges)))
1886 printf ("*** FAIL ***\n");
1887 else
1888 printf ("PASS\n");
1890 _cairo_array_fini (&intersected_edges);
1892 return 0;
1895 #define MAX_RANDOM 300
1898 main (void)
1900 char random_name[] = "random-XX";
1901 cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
1902 unsigned int i, num_random;
1903 test_t *test;
1905 for (i = 0; i < ARRAY_LENGTH (tests); i++) {
1906 test = &tests[i];
1907 run_test (test->name, test->edges, test->num_edges);
1910 for (num_random = 0; num_random < MAX_RANDOM; num_random++) {
1911 srand (0);
1912 for (i = 0; i < num_random; i++) {
1913 do {
1914 edge = &random_edges[i];
1915 edge->top.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
1916 edge->top.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
1917 edge->bottom.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
1918 edge->bottom.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
1919 if (edge->top.y > edge->bottom.y) {
1920 int32_t tmp = edge->top.y;
1921 edge->top.y = edge->bottom.y;
1922 edge->bottom.y = tmp;
1924 } while (edge->top.y == edge->bottom.y);
1927 sprintf (random_name, "random-%02d", num_random);
1929 run_test (random_name, random_edges, num_random);
1932 return 0;
1934 #endif