38fe46341bdef44d89e0ae523ba3ab8d8f21994c
[framework/graphics/cairo.git] / src / cairo-bentley-ottmann.c
1 /*
2  * Copyright © 2004 Carl Worth
3  * Copyright © 2006 Red Hat, Inc.
4  * Copyright © 2008 Chris Wilson
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 Carl Worth
32  *
33  * Contributor(s):
34  *      Carl D. Worth <cworth@cworth.org>
35  *      Chris Wilson <chris@chris-wilson.co.uk>
36  */
37
38 /* Provide definitions for standalone compilation */
39 #include "cairoint.h"
40
41 #include "cairo-error-private.h"
42 #include "cairo-freelist-private.h"
43 #include "cairo-combsort-inline.h"
44 #include "cairo-traps-private.h"
45
46 #define DEBUG_PRINT_STATE 0
47 #define DEBUG_EVENTS 0
48 #define DEBUG_TRAPS 0
49
50 typedef cairo_point_t cairo_bo_point32_t;
51
52 typedef struct _cairo_bo_intersect_ordinate {
53     int32_t ordinate;
54     enum { EXACT, INEXACT } exactness;
55 } cairo_bo_intersect_ordinate_t;
56
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;
61
62 typedef struct _cairo_bo_edge cairo_bo_edge_t;
63 typedef struct _cairo_bo_trap cairo_bo_trap_t;
64
65 /* A deferred trapezoid of an edge */
66 struct _cairo_bo_trap {
67     cairo_bo_edge_t *right;
68     int32_t top;
69 };
70
71 struct _cairo_bo_edge {
72     cairo_edge_t edge;
73     cairo_bo_edge_t *prev;
74     cairo_bo_edge_t *next;
75     cairo_bo_trap_t deferred_trap;
76 };
77
78 /* the parent is always given by index/2 */
79 #define PQ_PARENT_INDEX(i) ((i) >> 1)
80 #define PQ_FIRST_ENTRY 1
81
82 /* left and right children are index * 2 and (index * 2) +1 respectively */
83 #define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
84
85 typedef enum {
86     CAIRO_BO_EVENT_TYPE_STOP,
87     CAIRO_BO_EVENT_TYPE_INTERSECTION,
88     CAIRO_BO_EVENT_TYPE_START
89 } cairo_bo_event_type_t;
90
91 typedef struct _cairo_bo_event {
92     cairo_bo_event_type_t type;
93     cairo_point_t point;
94 } cairo_bo_event_t;
95
96 typedef struct _cairo_bo_start_event {
97     cairo_bo_event_type_t type;
98     cairo_point_t point;
99     cairo_bo_edge_t edge;
100 } cairo_bo_start_event_t;
101
102 typedef struct _cairo_bo_queue_event {
103     cairo_bo_event_type_t type;
104     cairo_point_t point;
105     cairo_bo_edge_t *e1;
106     cairo_bo_edge_t *e2;
107 } cairo_bo_queue_event_t;
108
109 typedef struct _pqueue {
110     int size, max_size;
111
112     cairo_bo_event_t **elements;
113     cairo_bo_event_t *elements_embedded[1024];
114 } pqueue_t;
115
116 typedef struct _cairo_bo_event_queue {
117     cairo_freepool_t pool;
118     pqueue_t pqueue;
119     cairo_bo_event_t **start_events;
120 } cairo_bo_event_queue_t;
121
122 typedef struct _cairo_bo_sweep_line {
123     cairo_bo_edge_t *head;
124     cairo_bo_edge_t *stopped;
125     int32_t current_y;
126     cairo_bo_edge_t *current_edge;
127 } cairo_bo_sweep_line_t;
128
129 #if DEBUG_TRAPS
130 static void
131 dump_traps (cairo_traps_t *traps, const char *filename)
132 {
133     FILE *file;
134     cairo_box_t extents;
135     int n;
136
137     if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
138         return;
139
140 #if 0
141     if (traps->has_limits) {
142         printf ("%s: limits=(%d, %d, %d, %d)\n",
143                 filename,
144                 traps->limits.p1.x, traps->limits.p1.y,
145                 traps->limits.p2.x, traps->limits.p2.y);
146     }
147 #endif
148     _cairo_traps_extents (traps, &extents);
149     printf ("%s: extents=(%d, %d, %d, %d)\n",
150             filename,
151             extents.p1.x, extents.p1.y,
152             extents.p2.x, extents.p2.y);
153
154     file = fopen (filename, "a");
155     if (file != NULL) {
156         for (n = 0; n < traps->num_traps; n++) {
157             fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
158                      traps->traps[n].top,
159                      traps->traps[n].bottom,
160                      traps->traps[n].left.p1.x,
161                      traps->traps[n].left.p1.y,
162                      traps->traps[n].left.p2.x,
163                      traps->traps[n].left.p2.y,
164                      traps->traps[n].right.p1.x,
165                      traps->traps[n].right.p1.y,
166                      traps->traps[n].right.p2.x,
167                      traps->traps[n].right.p2.y);
168         }
169         fprintf (file, "\n");
170         fclose (file);
171     }
172 }
173
174 static void
175 dump_edges (cairo_bo_start_event_t *events,
176             int num_edges,
177             const char *filename)
178 {
179     FILE *file;
180     int n;
181
182     if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
183         return;
184
185     file = fopen (filename, "a");
186     if (file != NULL) {
187         for (n = 0; n < num_edges; n++) {
188             fprintf (file, "(%d, %d), (%d, %d) %d %d %d\n",
189                      events[n].edge.edge.line.p1.x,
190                      events[n].edge.edge.line.p1.y,
191                      events[n].edge.edge.line.p2.x,
192                      events[n].edge.edge.line.p2.y,
193                      events[n].edge.edge.top,
194                      events[n].edge.edge.bottom,
195                      events[n].edge.edge.dir);
196         }
197         fprintf (file, "\n");
198         fclose (file);
199     }
200 }
201 #endif
202
203 static cairo_fixed_t
204 _line_compute_intersection_x_for_y (const cairo_line_t *line,
205                                     cairo_fixed_t y)
206 {
207     cairo_fixed_t x, dy;
208
209     if (y == line->p1.y)
210         return line->p1.x;
211     if (y == line->p2.y)
212         return line->p2.x;
213
214     x = line->p1.x;
215     dy = line->p2.y - line->p1.y;
216     if (dy != 0) {
217         x += _cairo_fixed_mul_div_floor (y - line->p1.y,
218                                          line->p2.x - line->p1.x,
219                                          dy);
220     }
221
222     return x;
223 }
224
225 static inline int
226 _cairo_bo_point32_compare (cairo_bo_point32_t const *a,
227                            cairo_bo_point32_t const *b)
228 {
229     int cmp;
230
231     cmp = a->y - b->y;
232     if (cmp)
233         return cmp;
234
235     return a->x - b->x;
236 }
237
238 /* Compare the slope of a to the slope of b, returning 1, 0, -1 if the
239  * slope a is respectively greater than, equal to, or less than the
240  * slope of b.
241  *
242  * For each edge, consider the direction vector formed from:
243  *
244  *      top -> bottom
245  *
246  * which is:
247  *
248  *      (dx, dy) = (line.p2.x - line.p1.x, line.p2.y - line.p1.y)
249  *
250  * We then define the slope of each edge as dx/dy, (which is the
251  * inverse of the slope typically used in math instruction). We never
252  * compute a slope directly as the value approaches infinity, but we
253  * can derive a slope comparison without division as follows, (where
254  * the ? represents our compare operator).
255  *
256  * 1.      slope(a) ? slope(b)
257  * 2.       adx/ady ? bdx/bdy
258  * 3.   (adx * bdy) ? (bdx * ady)
259  *
260  * Note that from step 2 to step 3 there is no change needed in the
261  * sign of the result since both ady and bdy are guaranteed to be
262  * greater than or equal to 0.
263  *
264  * When using this slope comparison to sort edges, some care is needed
265  * when interpreting the results. Since the slope compare operates on
266  * distance vectors from top to bottom it gives a correct left to
267  * right sort for edges that have a common top point, (such as two
268  * edges with start events at the same location). On the other hand,
269  * the sense of the result will be exactly reversed for two edges that
270  * have a common stop point.
271  */
272 static inline int
273 _slope_compare (const cairo_bo_edge_t *a,
274                 const cairo_bo_edge_t *b)
275 {
276     /* XXX: We're assuming here that dx and dy will still fit in 32
277      * bits. That's not true in general as there could be overflow. We
278      * should prevent that before the tessellation algorithm
279      * begins.
280      */
281     int32_t adx = a->edge.line.p2.x - a->edge.line.p1.x;
282     int32_t bdx = b->edge.line.p2.x - b->edge.line.p1.x;
283
284     /* Since the dy's are all positive by construction we can fast
285      * path several common cases.
286      */
287
288     /* First check for vertical lines. */
289     if (adx == 0)
290         return -bdx;
291     if (bdx == 0)
292         return adx;
293
294     /* Then where the two edges point in different directions wrt x. */
295     if ((adx ^ bdx) < 0)
296         return adx;
297
298     /* Finally we actually need to do the general comparison. */
299     {
300         int32_t ady = a->edge.line.p2.y - a->edge.line.p1.y;
301         int32_t bdy = b->edge.line.p2.y - b->edge.line.p1.y;
302         cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
303         cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
304
305         return _cairo_int64_cmp (adx_bdy, bdx_ady);
306     }
307 }
308
309 /*
310  * We need to compare the x-coordinates of a pair of lines for a particular y,
311  * without loss of precision.
312  *
313  * The x-coordinate along an edge for a given y is:
314  *   X = A_x + (Y - A_y) * A_dx / A_dy
315  *
316  * So the inequality we wish to test is:
317  *   A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
318  * where ∘ is our inequality operator.
319  *
320  * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
321  * all positive, so we can rearrange it thus without causing a sign change:
322  *   A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
323  *                                 - (Y - A_y) * A_dx * B_dy
324  *
325  * Given the assumption that all the deltas fit within 32 bits, we can compute
326  * this comparison directly using 128 bit arithmetic. For certain, but common,
327  * input we can reduce this down to a single 32 bit compare by inspecting the
328  * deltas.
329  *
330  * (And put the burden of the work on developing fast 128 bit ops, which are
331  * required throughout the tessellator.)
332  *
333  * See the similar discussion for _slope_compare().
334  */
335 static int
336 edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
337                                const cairo_bo_edge_t *b,
338                                int32_t y)
339 {
340     /* XXX: We're assuming here that dx and dy will still fit in 32
341      * bits. That's not true in general as there could be overflow. We
342      * should prevent that before the tessellation algorithm
343      * begins.
344      */
345     int32_t dx;
346     int32_t adx, ady;
347     int32_t bdx, bdy;
348     enum {
349        HAVE_NONE    = 0x0,
350        HAVE_DX      = 0x1,
351        HAVE_ADX     = 0x2,
352        HAVE_DX_ADX  = HAVE_DX | HAVE_ADX,
353        HAVE_BDX     = 0x4,
354        HAVE_DX_BDX  = HAVE_DX | HAVE_BDX,
355        HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
356        HAVE_ALL     = HAVE_DX | HAVE_ADX | HAVE_BDX
357     } have_dx_adx_bdx = HAVE_ALL;
358
359     /* don't bother solving for abscissa if the edges' bounding boxes
360      * can be used to order them. */
361     {
362            int32_t amin, amax;
363            int32_t bmin, bmax;
364            if (a->edge.line.p1.x < a->edge.line.p2.x) {
365                    amin = a->edge.line.p1.x;
366                    amax = a->edge.line.p2.x;
367            } else {
368                    amin = a->edge.line.p2.x;
369                    amax = a->edge.line.p1.x;
370            }
371            if (b->edge.line.p1.x < b->edge.line.p2.x) {
372                    bmin = b->edge.line.p1.x;
373                    bmax = b->edge.line.p2.x;
374            } else {
375                    bmin = b->edge.line.p2.x;
376                    bmax = b->edge.line.p1.x;
377            }
378            if (amax < bmin) return -1;
379            if (amin > bmax) return +1;
380     }
381
382     ady = a->edge.line.p2.y - a->edge.line.p1.y;
383     adx = a->edge.line.p2.x - a->edge.line.p1.x;
384     if (adx == 0)
385         have_dx_adx_bdx &= ~HAVE_ADX;
386
387     bdy = b->edge.line.p2.y - b->edge.line.p1.y;
388     bdx = b->edge.line.p2.x - b->edge.line.p1.x;
389     if (bdx == 0)
390         have_dx_adx_bdx &= ~HAVE_BDX;
391
392     dx = a->edge.line.p1.x - b->edge.line.p1.x;
393     if (dx == 0)
394         have_dx_adx_bdx &= ~HAVE_DX;
395
396 #define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
397 #define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y)
398 #define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y)
399     switch (have_dx_adx_bdx) {
400     default:
401     case HAVE_NONE:
402         return 0;
403     case HAVE_DX:
404         /* A_dy * B_dy * (A_x - B_x) ∘ 0 */
405         return dx; /* ady * bdy is positive definite */
406     case HAVE_ADX:
407         /* 0 ∘  - (Y - A_y) * A_dx * B_dy */
408         return adx; /* bdy * (y - a->top.y) is positive definite */
409     case HAVE_BDX:
410         /* 0 ∘ (Y - B_y) * B_dx * A_dy */
411         return -bdx; /* ady * (y - b->top.y) is positive definite */
412     case HAVE_ADX_BDX:
413         /*  0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
414         if ((adx ^ bdx) < 0) {
415             return adx;
416         } else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */
417             cairo_int64_t adx_bdy, bdx_ady;
418
419             /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
420
421             adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
422             bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
423
424             return _cairo_int64_cmp (adx_bdy, bdx_ady);
425         } else
426             return _cairo_int128_cmp (A, B);
427     case HAVE_DX_ADX:
428         /* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
429         if ((-adx ^ dx) < 0) {
430             return dx;
431         } else {
432             cairo_int64_t ady_dx, dy_adx;
433
434             ady_dx = _cairo_int32x32_64_mul (ady, dx);
435             dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
436
437             return _cairo_int64_cmp (ady_dx, dy_adx);
438         }
439     case HAVE_DX_BDX:
440         /* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
441         if ((bdx ^ dx) < 0) {
442             return dx;
443         } else {
444             cairo_int64_t bdy_dx, dy_bdx;
445
446             bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
447             dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx);
448
449             return _cairo_int64_cmp (bdy_dx, dy_bdx);
450         }
451     case HAVE_ALL:
452         /* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */
453         return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
454     }
455 #undef B
456 #undef A
457 #undef L
458 }
459
460 /*
461  * We need to compare the x-coordinate of a line for a particular y wrt to a
462  * given x, without loss of precision.
463  *
464  * The x-coordinate along an edge for a given y is:
465  *   X = A_x + (Y - A_y) * A_dx / A_dy
466  *
467  * So the inequality we wish to test is:
468  *   A_x + (Y - A_y) * A_dx / A_dy ∘ X
469  * where ∘ is our inequality operator.
470  *
471  * By construction, we know that A_dy (and (Y - A_y)) are
472  * all positive, so we can rearrange it thus without causing a sign change:
473  *   (Y - A_y) * A_dx ∘ (X - A_x) * A_dy
474  *
475  * Given the assumption that all the deltas fit within 32 bits, we can compute
476  * this comparison directly using 64 bit arithmetic.
477  *
478  * See the similar discussion for _slope_compare() and
479  * edges_compare_x_for_y_general().
480  */
481 static int
482 edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
483                               int32_t y,
484                               int32_t x)
485 {
486     int32_t adx, ady;
487     int32_t dx, dy;
488     cairo_int64_t L, R;
489
490     if (x < a->edge.line.p1.x && x < a->edge.line.p2.x)
491         return 1;
492     if (x > a->edge.line.p1.x && x > a->edge.line.p2.x)
493         return -1;
494
495     adx = a->edge.line.p2.x - a->edge.line.p1.x;
496     dx = x - a->edge.line.p1.x;
497
498     if (adx == 0)
499         return -dx;
500     if (dx == 0 || (adx ^ dx) < 0)
501         return adx;
502
503     dy = y - a->edge.line.p1.y;
504     ady = a->edge.line.p2.y - a->edge.line.p1.y;
505
506     L = _cairo_int32x32_64_mul (dy, adx);
507     R = _cairo_int32x32_64_mul (dx, ady);
508
509     return _cairo_int64_cmp (L, R);
510 }
511
512 static int
513 edges_compare_x_for_y (const cairo_bo_edge_t *a,
514                        const cairo_bo_edge_t *b,
515                        int32_t y)
516 {
517     /* If the sweep-line is currently on an end-point of a line,
518      * then we know its precise x value (and considering that we often need to
519      * compare events at end-points, this happens frequently enough to warrant
520      * special casing).
521      */
522     enum {
523        HAVE_NEITHER = 0x0,
524        HAVE_AX      = 0x1,
525        HAVE_BX      = 0x2,
526        HAVE_BOTH    = HAVE_AX | HAVE_BX
527     } have_ax_bx = HAVE_BOTH;
528     int32_t ax, bx;
529
530     if (y == a->edge.line.p1.y)
531         ax = a->edge.line.p1.x;
532     else if (y == a->edge.line.p2.y)
533         ax = a->edge.line.p2.x;
534     else
535         have_ax_bx &= ~HAVE_AX;
536
537     if (y == b->edge.line.p1.y)
538         bx = b->edge.line.p1.x;
539     else if (y == b->edge.line.p2.y)
540         bx = b->edge.line.p2.x;
541     else
542         have_ax_bx &= ~HAVE_BX;
543
544     switch (have_ax_bx) {
545     default:
546     case HAVE_NEITHER:
547         return edges_compare_x_for_y_general (a, b, y);
548     case HAVE_AX:
549         return -edge_compare_for_y_against_x (b, y, ax);
550     case HAVE_BX:
551         return edge_compare_for_y_against_x (a, y, bx);
552     case HAVE_BOTH:
553         return ax - bx;
554     }
555 }
556
557 static inline int
558 _line_equal (const cairo_line_t *a, const cairo_line_t *b)
559 {
560     return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
561            a->p2.x == b->p2.x && a->p2.y == b->p2.y;
562 }
563
564 static int
565 _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t       *sweep_line,
566                                     const cairo_bo_edge_t       *a,
567                                     const cairo_bo_edge_t       *b)
568 {
569     int cmp;
570
571     /* compare the edges if not identical */
572     if (! _line_equal (&a->edge.line, &b->edge.line)) {
573         if (MAX (a->edge.line.p1.x, a->edge.line.p2.x) <
574             MIN (b->edge.line.p1.x, b->edge.line.p2.x))
575             return -1;
576         else if (MIN (a->edge.line.p1.x, a->edge.line.p2.x) >
577                  MAX (b->edge.line.p1.x, b->edge.line.p2.x))
578             return 1;
579
580         cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
581         if (cmp)
582             return cmp;
583
584         /* The two edges intersect exactly at y, so fall back on slope
585          * comparison. We know that this compare_edges function will be
586          * called only when starting a new edge, (not when stopping an
587          * edge), so we don't have to worry about conditionally inverting
588          * the sense of _slope_compare. */
589         cmp = _slope_compare (a, b);
590         if (cmp)
591             return cmp;
592     }
593
594     /* We've got two collinear edges now. */
595     return b->edge.bottom - a->edge.bottom;
596 }
597
598 static inline cairo_int64_t
599 det32_64 (int32_t a, int32_t b,
600           int32_t c, int32_t d)
601 {
602     /* det = a * d - b * c */
603     return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
604                              _cairo_int32x32_64_mul (b, c));
605 }
606
607 static inline cairo_int128_t
608 det64x32_128 (cairo_int64_t a, int32_t       b,
609               cairo_int64_t c, int32_t       d)
610 {
611     /* det = a * d - b * c */
612     return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d),
613                               _cairo_int64x32_128_mul (c, b));
614 }
615
616 /* Compute the intersection of two lines as defined by two edges. The
617  * result is provided as a coordinate pair of 128-bit integers.
618  *
619  * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
620  * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
621  */
622 static cairo_bool_t
623 intersect_lines (cairo_bo_edge_t                *a,
624                  cairo_bo_edge_t                *b,
625                  cairo_bo_intersect_point_t     *intersection)
626 {
627     cairo_int64_t a_det, b_det;
628
629     /* XXX: We're assuming here that dx and dy will still fit in 32
630      * bits. That's not true in general as there could be overflow. We
631      * should prevent that before the tessellation algorithm begins.
632      * What we're doing to mitigate this is to perform clamping in
633      * cairo_bo_tessellate_polygon().
634      */
635     int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x;
636     int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y;
637
638     int32_t dx2 = b->edge.line.p1.x - b->edge.line.p2.x;
639     int32_t dy2 = b->edge.line.p1.y - b->edge.line.p2.y;
640
641     cairo_int64_t den_det;
642     cairo_int64_t R;
643     cairo_quorem64_t qr;
644
645     den_det = det32_64 (dx1, dy1, dx2, dy2);
646
647      /* Q: Can we determine that the lines do not intersect (within range)
648       * much more cheaply than computing the intersection point i.e. by
649       * avoiding the division?
650       *
651       *   X = ax + t * adx = bx + s * bdx;
652       *   Y = ay + t * ady = by + s * bdy;
653       *   ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
654       *   => t * L = R
655       *
656       * Therefore we can reject any intersection (under the criteria for
657       * valid intersection events) if:
658       *   L^R < 0 => t < 0, or
659       *   L<R => t > 1
660       *
661       * (where top/bottom must at least extend to the line endpoints).
662       *
663       * A similar substitution can be performed for s, yielding:
664       *   s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
665       */
666     R = det32_64 (dx2, dy2,
667                   b->edge.line.p1.x - a->edge.line.p1.x,
668                   b->edge.line.p1.y - a->edge.line.p1.y);
669     if (_cairo_int64_negative (den_det)) {
670         if (_cairo_int64_ge (den_det, R))
671             return FALSE;
672     } else {
673         if (_cairo_int64_le (den_det, R))
674             return FALSE;
675     }
676
677     R = det32_64 (dy1, dx1,
678                   a->edge.line.p1.y - b->edge.line.p1.y,
679                   a->edge.line.p1.x - b->edge.line.p1.x);
680     if (_cairo_int64_negative (den_det)) {
681         if (_cairo_int64_ge (den_det, R))
682             return FALSE;
683     } else {
684         if (_cairo_int64_le (den_det, R))
685             return FALSE;
686     }
687
688     /* We now know that the two lines should intersect within range. */
689
690     a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y,
691                       a->edge.line.p2.x, a->edge.line.p2.y);
692     b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y,
693                       b->edge.line.p2.x, b->edge.line.p2.y);
694
695     /* x = det (a_det, dx1, b_det, dx2) / den_det */
696     qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
697                                                        b_det, dx2),
698                                          den_det);
699     if (_cairo_int64_eq (qr.rem, den_det))
700         return FALSE;
701 #if 0
702     intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
703 #else
704     intersection->x.exactness = EXACT;
705     if (! _cairo_int64_is_zero (qr.rem)) {
706         if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
707             qr.rem = _cairo_int64_negate (qr.rem);
708         qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
709         if (_cairo_int64_ge (qr.rem, den_det)) {
710             qr.quo = _cairo_int64_add (qr.quo,
711                                        _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
712         } else
713             intersection->x.exactness = INEXACT;
714     }
715 #endif
716     intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
717
718     /* y = det (a_det, dy1, b_det, dy2) / den_det */
719     qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
720                                                        b_det, dy2),
721                                          den_det);
722     if (_cairo_int64_eq (qr.rem, den_det))
723         return FALSE;
724 #if 0
725     intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
726 #else
727     intersection->y.exactness = EXACT;
728     if (! _cairo_int64_is_zero (qr.rem)) {
729         if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
730             qr.rem = _cairo_int64_negate (qr.rem);
731         qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
732         if (_cairo_int64_ge (qr.rem, den_det)) {
733             qr.quo = _cairo_int64_add (qr.quo,
734                                        _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
735         } else
736             intersection->y.exactness = INEXACT;
737     }
738 #endif
739     intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
740
741     return TRUE;
742 }
743
744 static int
745 _cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t  a,
746                                          int32_t                        b)
747 {
748     /* First compare the quotient */
749     if (a.ordinate > b)
750         return +1;
751     if (a.ordinate < b)
752         return -1;
753     /* With quotient identical, if remainder is 0 then compare equal */
754     /* Otherwise, the non-zero remainder makes a > b */
755     return INEXACT == a.exactness;
756 }
757
758 /* Does the given edge contain the given point. The point must already
759  * be known to be contained within the line determined by the edge,
760  * (most likely the point results from an intersection of this edge
761  * with another).
762  *
763  * If we had exact arithmetic, then this function would simply be a
764  * matter of examining whether the y value of the point lies within
765  * the range of y values of the edge. But since intersection points
766  * are not exact due to being rounded to the nearest integer within
767  * the available precision, we must also examine the x value of the
768  * point.
769  *
770  * The definition of "contains" here is that the given intersection
771  * point will be seen by the sweep line after the start event for the
772  * given edge and before the stop event for the edge. See the comments
773  * in the implementation for more details.
774  */
775 static cairo_bool_t
776 _cairo_bo_edge_contains_intersect_point (cairo_bo_edge_t                *edge,
777                                          cairo_bo_intersect_point_t     *point)
778 {
779     int cmp_top, cmp_bottom;
780
781     /* XXX: When running the actual algorithm, we don't actually need to
782      * compare against edge->top at all here, since any intersection above
783      * top is eliminated early via a slope comparison. We're leaving these
784      * here for now only for the sake of the quadratic-time intersection
785      * finder which needs them.
786      */
787
788     cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y,
789                                                        edge->edge.top);
790     cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y,
791                                                           edge->edge.bottom);
792
793     if (cmp_top < 0 || cmp_bottom > 0)
794     {
795         return FALSE;
796     }
797
798     if (cmp_top > 0 && cmp_bottom < 0)
799     {
800         return TRUE;
801     }
802
803     /* At this stage, the point lies on the same y value as either
804      * edge->top or edge->bottom, so we have to examine the x value in
805      * order to properly determine containment. */
806
807     /* If the y value of the point is the same as the y value of the
808      * top of the edge, then the x value of the point must be greater
809      * to be considered as inside the edge. Similarly, if the y value
810      * of the point is the same as the y value of the bottom of the
811      * edge, then the x value of the point must be less to be
812      * considered as inside. */
813
814     if (cmp_top == 0) {
815         cairo_fixed_t top_x;
816
817         top_x = _line_compute_intersection_x_for_y (&edge->edge.line,
818                                                     edge->edge.top);
819         return _cairo_bo_intersect_ordinate_32_compare (point->x, top_x) > 0;
820     } else { /* cmp_bottom == 0 */
821         cairo_fixed_t bot_x;
822
823         bot_x = _line_compute_intersection_x_for_y (&edge->edge.line,
824                                                     edge->edge.bottom);
825         return _cairo_bo_intersect_ordinate_32_compare (point->x, bot_x) < 0;
826     }
827 }
828
829 /* Compute the intersection of two edges. The result is provided as a
830  * coordinate pair of 128-bit integers.
831  *
832  * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection
833  * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the
834  * intersection of the lines defined by the edges occurs outside of
835  * one or both edges, and %CAIRO_BO_STATUS_PARALLEL if the two edges
836  * are exactly parallel.
837  *
838  * Note that when determining if a candidate intersection is "inside"
839  * an edge, we consider both the infinitesimal shortening and the
840  * infinitesimal tilt rules described by John Hobby. Specifically, if
841  * the intersection is exactly the same as an edge point, it is
842  * effectively outside (no intersection is returned). Also, if the
843  * intersection point has the same
844  */
845 static cairo_bool_t
846 _cairo_bo_edge_intersect (cairo_bo_edge_t       *a,
847                           cairo_bo_edge_t       *b,
848                           cairo_bo_point32_t    *intersection)
849 {
850     cairo_bo_intersect_point_t quorem;
851
852     if (! intersect_lines (a, b, &quorem))
853         return FALSE;
854
855     if (! _cairo_bo_edge_contains_intersect_point (a, &quorem))
856         return FALSE;
857
858     if (! _cairo_bo_edge_contains_intersect_point (b, &quorem))
859         return FALSE;
860
861     /* Now that we've correctly compared the intersection point and
862      * determined that it lies within the edge, then we know that we
863      * no longer need any more bits of storage for the intersection
864      * than we do for our edge coordinates. We also no longer need the
865      * remainder from the division. */
866     intersection->x = quorem.x.ordinate;
867     intersection->y = quorem.y.ordinate;
868
869     return TRUE;
870 }
871
872 static inline int
873 cairo_bo_event_compare (const cairo_bo_event_t *a,
874                         const cairo_bo_event_t *b)
875 {
876     int cmp;
877
878     cmp = _cairo_bo_point32_compare (&a->point, &b->point);
879     if (cmp)
880         return cmp;
881
882     cmp = a->type - b->type;
883     if (cmp)
884         return cmp;
885
886     return a - b;
887 }
888
889 static inline void
890 _pqueue_init (pqueue_t *pq)
891 {
892     pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
893     pq->size = 0;
894
895     pq->elements = pq->elements_embedded;
896 }
897
898 static inline void
899 _pqueue_fini (pqueue_t *pq)
900 {
901     if (pq->elements != pq->elements_embedded)
902         free (pq->elements);
903 }
904
905 static cairo_status_t
906 _pqueue_grow (pqueue_t *pq)
907 {
908     cairo_bo_event_t **new_elements;
909     pq->max_size *= 2;
910
911     if (pq->elements == pq->elements_embedded) {
912         new_elements = _cairo_malloc_ab (pq->max_size,
913                                          sizeof (cairo_bo_event_t *));
914         if (unlikely (new_elements == NULL))
915             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
916
917         memcpy (new_elements, pq->elements_embedded,
918                 sizeof (pq->elements_embedded));
919     } else {
920         new_elements = _cairo_realloc_ab (pq->elements,
921                                           pq->max_size,
922                                           sizeof (cairo_bo_event_t *));
923         if (unlikely (new_elements == NULL))
924             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
925     }
926
927     pq->elements = new_elements;
928     return CAIRO_STATUS_SUCCESS;
929 }
930
931 static inline cairo_status_t
932 _pqueue_push (pqueue_t *pq, cairo_bo_event_t *event)
933 {
934     cairo_bo_event_t **elements;
935     int i, parent;
936
937     if (unlikely (pq->size + 1 == pq->max_size)) {
938         cairo_status_t status;
939
940         status = _pqueue_grow (pq);
941         if (unlikely (status))
942             return status;
943     }
944
945     elements = pq->elements;
946
947     for (i = ++pq->size;
948          i != PQ_FIRST_ENTRY &&
949          cairo_bo_event_compare (event,
950                                  elements[parent = PQ_PARENT_INDEX (i)]) < 0;
951          i = parent)
952     {
953         elements[i] = elements[parent];
954     }
955
956     elements[i] = event;
957
958     return CAIRO_STATUS_SUCCESS;
959 }
960
961 static inline void
962 _pqueue_pop (pqueue_t *pq)
963 {
964     cairo_bo_event_t **elements = pq->elements;
965     cairo_bo_event_t *tail;
966     int child, i;
967
968     tail = elements[pq->size--];
969     if (pq->size == 0) {
970         elements[PQ_FIRST_ENTRY] = NULL;
971         return;
972     }
973
974     for (i = PQ_FIRST_ENTRY;
975          (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
976          i = child)
977     {
978         if (child != pq->size &&
979             cairo_bo_event_compare (elements[child+1],
980                                     elements[child]) < 0)
981         {
982             child++;
983         }
984
985         if (cairo_bo_event_compare (elements[child], tail) >= 0)
986             break;
987
988         elements[i] = elements[child];
989     }
990     elements[i] = tail;
991 }
992
993 static inline cairo_status_t
994 _cairo_bo_event_queue_insert (cairo_bo_event_queue_t    *queue,
995                               cairo_bo_event_type_t      type,
996                               cairo_bo_edge_t           *e1,
997                               cairo_bo_edge_t           *e2,
998                               const cairo_point_t        *point)
999 {
1000     cairo_bo_queue_event_t *event;
1001
1002     event = _cairo_freepool_alloc (&queue->pool);
1003     if (unlikely (event == NULL))
1004         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1005
1006     event->type = type;
1007     event->e1 = e1;
1008     event->e2 = e2;
1009     event->point = *point;
1010
1011     return _pqueue_push (&queue->pqueue, (cairo_bo_event_t *) event);
1012 }
1013
1014 static void
1015 _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
1016                               cairo_bo_event_t       *event)
1017 {
1018     _cairo_freepool_free (&queue->pool, event);
1019 }
1020
1021 static cairo_bo_event_t *
1022 _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
1023 {
1024     cairo_bo_event_t *event, *cmp;
1025
1026     event = event_queue->pqueue.elements[PQ_FIRST_ENTRY];
1027     cmp = *event_queue->start_events;
1028     if (event == NULL ||
1029         (cmp != NULL && cairo_bo_event_compare (cmp, event) < 0))
1030     {
1031         event = cmp;
1032         event_queue->start_events++;
1033     }
1034     else
1035     {
1036         _pqueue_pop (&event_queue->pqueue);
1037     }
1038
1039     return event;
1040 }
1041
1042 CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
1043                         cairo_bo_event_t *,
1044                         cairo_bo_event_compare)
1045
1046 static void
1047 _cairo_bo_event_queue_init (cairo_bo_event_queue_t       *event_queue,
1048                             cairo_bo_event_t            **start_events,
1049                             int                           num_events)
1050 {
1051     event_queue->start_events = start_events;
1052
1053     _cairo_freepool_init (&event_queue->pool,
1054                           sizeof (cairo_bo_queue_event_t));
1055     _pqueue_init (&event_queue->pqueue);
1056     event_queue->pqueue.elements[PQ_FIRST_ENTRY] = NULL;
1057 }
1058
1059 static cairo_status_t
1060 _cairo_bo_event_queue_insert_stop (cairo_bo_event_queue_t       *event_queue,
1061                                    cairo_bo_edge_t              *edge)
1062 {
1063     cairo_bo_point32_t point;
1064
1065     point.y = edge->edge.bottom;
1066     point.x = _line_compute_intersection_x_for_y (&edge->edge.line,
1067                                                   point.y);
1068     return _cairo_bo_event_queue_insert (event_queue,
1069                                          CAIRO_BO_EVENT_TYPE_STOP,
1070                                          edge, NULL,
1071                                          &point);
1072 }
1073
1074 static void
1075 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
1076 {
1077     _pqueue_fini (&event_queue->pqueue);
1078     _cairo_freepool_fini (&event_queue->pool);
1079 }
1080
1081 static inline cairo_status_t
1082 _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t       *event_queue,
1083                                                            cairo_bo_edge_t      *left,
1084                                                            cairo_bo_edge_t *right)
1085 {
1086     cairo_bo_point32_t intersection;
1087
1088     if (MAX (left->edge.line.p1.x, left->edge.line.p2.x) <=
1089         MIN (right->edge.line.p1.x, right->edge.line.p2.x))
1090         return CAIRO_STATUS_SUCCESS;
1091
1092     if (_line_equal (&left->edge.line, &right->edge.line))
1093         return CAIRO_STATUS_SUCCESS;
1094
1095     /* The names "left" and "right" here are correct descriptions of
1096      * the order of the two edges within the active edge list. So if a
1097      * slope comparison also puts left less than right, then we know
1098      * that the intersection of these two segments has already
1099      * occurred before the current sweep line position. */
1100     if (_slope_compare (left, right) <= 0)
1101         return CAIRO_STATUS_SUCCESS;
1102
1103     if (! _cairo_bo_edge_intersect (left, right, &intersection))
1104         return CAIRO_STATUS_SUCCESS;
1105
1106     return _cairo_bo_event_queue_insert (event_queue,
1107                                          CAIRO_BO_EVENT_TYPE_INTERSECTION,
1108                                          left, right,
1109                                          &intersection);
1110 }
1111
1112 static void
1113 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
1114 {
1115     sweep_line->head = NULL;
1116     sweep_line->stopped = NULL;
1117     sweep_line->current_y = INT32_MIN;
1118     sweep_line->current_edge = NULL;
1119 }
1120
1121 static cairo_status_t
1122 _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t      *sweep_line,
1123                              cairo_bo_edge_t            *edge)
1124 {
1125     if (sweep_line->current_edge != NULL) {
1126         cairo_bo_edge_t *prev, *next;
1127         int cmp;
1128
1129         cmp = _cairo_bo_sweep_line_compare_edges (sweep_line,
1130                                                   sweep_line->current_edge,
1131                                                   edge);
1132         if (cmp < 0) {
1133             prev = sweep_line->current_edge;
1134             next = prev->next;
1135             while (next != NULL &&
1136                    _cairo_bo_sweep_line_compare_edges (sweep_line,
1137                                                        next, edge) < 0)
1138             {
1139                 prev = next, next = prev->next;
1140             }
1141
1142             prev->next = edge;
1143             edge->prev = prev;
1144             edge->next = next;
1145             if (next != NULL)
1146                 next->prev = edge;
1147         } else if (cmp > 0) {
1148             next = sweep_line->current_edge;
1149             prev = next->prev;
1150             while (prev != NULL &&
1151                    _cairo_bo_sweep_line_compare_edges (sweep_line,
1152                                                        prev, edge) > 0)
1153             {
1154                 next = prev, prev = next->prev;
1155             }
1156
1157             next->prev = edge;
1158             edge->next = next;
1159             edge->prev = prev;
1160             if (prev != NULL)
1161                 prev->next = edge;
1162             else
1163                 sweep_line->head = edge;
1164         } else {
1165             prev = sweep_line->current_edge;
1166             edge->prev = prev;
1167             edge->next = prev->next;
1168             if (prev->next != NULL)
1169                 prev->next->prev = edge;
1170             prev->next = edge;
1171         }
1172     } else {
1173         sweep_line->head = edge;
1174         edge->next = NULL;
1175     }
1176
1177     sweep_line->current_edge = edge;
1178
1179     return CAIRO_STATUS_SUCCESS;
1180 }
1181
1182 static void
1183 _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t      *sweep_line,
1184                              cairo_bo_edge_t    *edge)
1185 {
1186     if (edge->prev != NULL)
1187         edge->prev->next = edge->next;
1188     else
1189         sweep_line->head = edge->next;
1190
1191     if (edge->next != NULL)
1192         edge->next->prev = edge->prev;
1193
1194     if (sweep_line->current_edge == edge)
1195         sweep_line->current_edge = edge->prev ? edge->prev : edge->next;
1196 }
1197
1198 static void
1199 _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t        *sweep_line,
1200                            cairo_bo_edge_t              *left,
1201                            cairo_bo_edge_t              *right)
1202 {
1203     if (left->prev != NULL)
1204         left->prev->next = right;
1205     else
1206         sweep_line->head = right;
1207
1208     if (right->next != NULL)
1209         right->next->prev = left;
1210
1211     left->next = right->next;
1212     right->next = left;
1213
1214     right->prev = left->prev;
1215     left->prev = right;
1216 }
1217
1218 #if DEBUG_PRINT_STATE
1219 static void
1220 _cairo_bo_edge_print (cairo_bo_edge_t *edge)
1221 {
1222     printf ("(0x%x, 0x%x)-(0x%x, 0x%x)",
1223             edge->edge.line.p1.x, edge->edge.line.p1.y,
1224             edge->edge.line.p2.x, edge->edge.line.p2.y);
1225 }
1226
1227 static void
1228 _cairo_bo_event_print (cairo_bo_event_t *event)
1229 {
1230     switch (event->type) {
1231     case CAIRO_BO_EVENT_TYPE_START:
1232         printf ("Start: ");
1233         break;
1234     case CAIRO_BO_EVENT_TYPE_STOP:
1235         printf ("Stop: ");
1236         break;
1237     case CAIRO_BO_EVENT_TYPE_INTERSECTION:
1238         printf ("Intersection: ");
1239         break;
1240     }
1241     printf ("(%d, %d)\t", event->point.x, event->point.y);
1242     _cairo_bo_edge_print (event->e1);
1243     if (event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) {
1244         printf (" X ");
1245         _cairo_bo_edge_print (event->e2);
1246     }
1247     printf ("\n");
1248 }
1249
1250 static void
1251 _cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue)
1252 {
1253     /* XXX: fixme to print the start/stop array too. */
1254     printf ("Event queue:\n");
1255 }
1256
1257 static void
1258 _cairo_bo_sweep_line_print (cairo_bo_sweep_line_t *sweep_line)
1259 {
1260     cairo_bool_t first = TRUE;
1261     cairo_bo_edge_t *edge;
1262
1263     printf ("Sweep line from edge list: ");
1264     first = TRUE;
1265     for (edge = sweep_line->head;
1266          edge;
1267          edge = edge->next)
1268     {
1269         if (!first)
1270             printf (", ");
1271         _cairo_bo_edge_print (edge);
1272         first = FALSE;
1273     }
1274     printf ("\n");
1275 }
1276
1277 static void
1278 print_state (const char                 *msg,
1279              cairo_bo_event_t           *event,
1280              cairo_bo_event_queue_t     *event_queue,
1281              cairo_bo_sweep_line_t      *sweep_line)
1282 {
1283     printf ("%s ", msg);
1284     _cairo_bo_event_print (event);
1285     _cairo_bo_event_queue_print (event_queue);
1286     _cairo_bo_sweep_line_print (sweep_line);
1287     printf ("\n");
1288 }
1289 #endif
1290
1291 #if DEBUG_EVENTS
1292 static void CAIRO_PRINTF_FORMAT (1, 2)
1293 event_log (const char *fmt, ...)
1294 {
1295     FILE *file;
1296
1297     if (getenv ("CAIRO_DEBUG_EVENTS") == NULL)
1298         return;
1299
1300     file = fopen ("bo-events.txt", "a");
1301     if (file != NULL) {
1302         va_list ap;
1303
1304         va_start (ap, fmt);
1305         vfprintf (file, fmt, ap);
1306         va_end (ap);
1307
1308         fclose (file);
1309     }
1310 }
1311 #endif
1312
1313 static inline cairo_bool_t
1314 edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
1315 {
1316     unsigned p;
1317
1318     p = 0;
1319     p |= (a->edge.line.p1.x == b->edge.line.p1.x) << 0;
1320     p |= (a->edge.line.p1.y == b->edge.line.p1.y) << 1;
1321     p |= (a->edge.line.p2.x == b->edge.line.p2.x) << 3;
1322     p |= (a->edge.line.p2.y == b->edge.line.p2.y) << 4;
1323     if (p == ((1 << 0) | (1 << 1) | (1 << 3) | (1 << 4)))
1324         return TRUE;
1325
1326     if (_slope_compare (a, b))
1327         return FALSE;
1328
1329     /* The choice of y is not truly arbitrary since we must guarantee that it
1330      * is greater than the start of either line.
1331      */
1332     if (p != 0) {
1333         /* colinear if either end-point are coincident */
1334         return ((p >> 1) & p) != 0;
1335     } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
1336         return edge_compare_for_y_against_x (b,
1337                                              a->edge.line.p1.y,
1338                                              a->edge.line.p1.x) == 0;
1339     } else {
1340         return edge_compare_for_y_against_x (a,
1341                                              b->edge.line.p1.y,
1342                                              b->edge.line.p1.x) == 0;
1343     }
1344 }
1345
1346 /* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t */
1347 static cairo_status_t
1348 _cairo_bo_edge_end_trap (cairo_bo_edge_t        *left,
1349                          int32_t                 bot,
1350                          cairo_traps_t          *traps)
1351 {
1352     cairo_bo_trap_t *trap = &left->deferred_trap;
1353
1354     /* Only emit (trivial) non-degenerate trapezoids with positive height. */
1355     if (likely (trap->top < bot)) {
1356         _cairo_traps_add_trap (traps,
1357                                trap->top, bot,
1358                                &left->edge.line, &trap->right->edge.line);
1359
1360 #if DEBUG_PRINT_STATE
1361         printf ("Deferred trap: left=(%x, %x)-(%x,%x) "
1362                 "right=(%x,%x)-(%x,%x) top=%x, bot=%x\n",
1363                 left->edge.line.p1.x, left->edge.line.p1.y,
1364                 left->edge.line.p2.x, left->edge.line.p2.y,
1365                 trap->right->edge.line.p1.x, trap->right->edge.line.p1.y,
1366                 trap->right->edge.line.p2.x, trap->right->edge.line.p2.y,
1367                 trap->top, bot);
1368 #endif
1369 #if DEBUG_EVENTS
1370         event_log ("end trap: %lu %lu %d %d\n",
1371                    (long) left,
1372                    (long) trap->right,
1373                    trap->top,
1374                    bot);
1375 #endif
1376     }
1377
1378     trap->right = NULL;
1379
1380     return _cairo_traps_status (traps);
1381 }
1382
1383
1384 /* Start a new trapezoid at the given top y coordinate, whose edges
1385  * are `edge' and `edge->next'. If `edge' already has a trapezoid,
1386  * then either add it to the traps in `traps', if the trapezoid's
1387  * right edge differs from `edge->next', or do nothing if the new
1388  * trapezoid would be a continuation of the existing one. */
1389 static inline cairo_status_t
1390 _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t  *left,
1391                                        cairo_bo_edge_t  *right,
1392                                        int               top,
1393                                        cairo_traps_t    *traps)
1394 {
1395     cairo_status_t status;
1396
1397     if (left->deferred_trap.right == right)
1398         return CAIRO_STATUS_SUCCESS;
1399
1400     assert (right);
1401     if (left->deferred_trap.right != NULL) {
1402         if (edges_colinear (left->deferred_trap.right, right))
1403         {
1404             /* continuation on right, so just swap edges */
1405             left->deferred_trap.right = right;
1406             return CAIRO_STATUS_SUCCESS;
1407         }
1408
1409         status = _cairo_bo_edge_end_trap (left, top, traps);
1410         if (unlikely (status))
1411             return status;
1412     }
1413
1414     if (! edges_colinear (left, right)) {
1415         left->deferred_trap.top = top;
1416         left->deferred_trap.right = right;
1417
1418 #if DEBUG_EVENTS
1419         event_log ("begin trap: %lu %lu %d\n",
1420                    (long) left,
1421                    (long) right,
1422                    top);
1423 #endif
1424     }
1425
1426     return CAIRO_STATUS_SUCCESS;
1427 }
1428
1429 static inline cairo_status_t
1430 _active_edges_to_traps (cairo_bo_edge_t *pos,
1431                         int32_t          top,
1432                         unsigned         mask,
1433                         cairo_traps_t        *traps)
1434 {
1435     cairo_bo_edge_t *left;
1436     cairo_status_t status;
1437     int in_out;
1438
1439
1440 #if DEBUG_PRINT_STATE
1441     printf ("Processing active edges for %x\n", top);
1442 #endif
1443
1444     in_out = 0;
1445     left = pos;
1446     while (pos != NULL) {
1447         if (pos != left && pos->deferred_trap.right) {
1448             /* XXX It shouldn't be possible to here with 2 deferred traps
1449              * on colinear edges... See bug-bo-rictoz.
1450              */
1451             if (left->deferred_trap.right == NULL &&
1452                 edges_colinear (left, pos))
1453             {
1454                 /* continuation on left */
1455                 left->deferred_trap = pos->deferred_trap;
1456                 pos->deferred_trap.right = NULL;
1457             }
1458             else
1459             {
1460                 status = _cairo_bo_edge_end_trap (pos, top, traps);
1461                 if (unlikely (status))
1462                     return status;
1463             }
1464         }
1465
1466         in_out += pos->edge.dir;
1467         if ((in_out & mask) == 0) {
1468             /* skip co-linear edges */
1469             if (pos->next == NULL || ! edges_colinear (pos, pos->next)) {
1470                 status = _cairo_bo_edge_start_or_continue_trap (left, pos,
1471                                                                 top, traps);
1472                 if (unlikely (status))
1473                     return status;
1474
1475                 left = pos->next;
1476             }
1477         }
1478
1479         pos = pos->next;
1480     }
1481
1482     return CAIRO_STATUS_SUCCESS;
1483 }
1484
1485
1486 /* Execute a single pass of the Bentley-Ottmann algorithm on edges,
1487  * generating trapezoids according to the fill_rule and appending them
1488  * to traps. */
1489 static cairo_status_t
1490 _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t   **start_events,
1491                                             int                  num_events,
1492                                             unsigned             fill_rule,
1493                                             cairo_traps_t       *traps,
1494                                             int                 *num_intersections)
1495 {
1496     cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
1497     int intersection_count = 0;
1498     cairo_bo_event_queue_t event_queue;
1499     cairo_bo_sweep_line_t sweep_line;
1500     cairo_bo_event_t *event;
1501     cairo_bo_edge_t *left, *right;
1502     cairo_bo_edge_t *e1, *e2;
1503
1504     /* convert the fill_rule into a winding mask */
1505     if (fill_rule == CAIRO_FILL_RULE_WINDING)
1506         fill_rule = (unsigned) -1;
1507     else
1508         fill_rule = 1;
1509
1510 #if DEBUG_EVENTS
1511     {
1512         int i;
1513
1514         for (i = 0; i < num_events; i++) {
1515             cairo_bo_start_event_t *event =
1516                 ((cairo_bo_start_event_t **) start_events)[i];
1517             event_log ("edge: %lu (%d, %d) (%d, %d) (%d, %d) %d\n",
1518                        (long) &events[i].edge,
1519                        event->edge.edge.line.p1.x,
1520                        event->edge.edge.line.p1.y,
1521                        event->edge.edge.line.p2.x,
1522                        event->edge.edge.line.p2.y,
1523                        event->edge.top,
1524                        event->edge.bottom,
1525                        event->edge.edge.dir);
1526         }
1527     }
1528 #endif
1529
1530     _cairo_bo_event_queue_init (&event_queue, start_events, num_events);
1531     _cairo_bo_sweep_line_init (&sweep_line);
1532
1533     while ((event = _cairo_bo_event_dequeue (&event_queue))) {
1534         if (event->point.y != sweep_line.current_y) {
1535             for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
1536                 if (e1->deferred_trap.right != NULL) {
1537                     status = _cairo_bo_edge_end_trap (e1,
1538                                                       e1->edge.bottom,
1539                                                       traps);
1540                     if (unlikely (status))
1541                         goto unwind;
1542                 }
1543             }
1544             sweep_line.stopped = NULL;
1545
1546             status = _active_edges_to_traps (sweep_line.head,
1547                                              sweep_line.current_y,
1548                                              fill_rule, traps);
1549             if (unlikely (status))
1550                 goto unwind;
1551
1552             sweep_line.current_y = event->point.y;
1553         }
1554
1555 #if DEBUG_EVENTS
1556         event_log ("event: %d (%ld, %ld) %lu, %lu\n",
1557                    event->type,
1558                    (long) event->point.x,
1559                    (long) event->point.y,
1560                    (long) event->e1,
1561                    (long) event->e2);
1562 #endif
1563
1564         switch (event->type) {
1565         case CAIRO_BO_EVENT_TYPE_START:
1566             e1 = &((cairo_bo_start_event_t *) event)->edge;
1567
1568             status = _cairo_bo_sweep_line_insert (&sweep_line, e1);
1569             if (unlikely (status))
1570                 goto unwind;
1571
1572             status = _cairo_bo_event_queue_insert_stop (&event_queue, e1);
1573             if (unlikely (status))
1574                 goto unwind;
1575
1576             /* check to see if this is a continuation of a stopped edge */
1577             /* XXX change to an infinitesimal lengthening rule */
1578             for (left = sweep_line.stopped; left; left = left->next) {
1579                 if (e1->edge.top <= left->edge.bottom &&
1580                     edges_colinear (e1, left))
1581                 {
1582                     e1->deferred_trap = left->deferred_trap;
1583                     if (left->prev != NULL)
1584                         left->prev = left->next;
1585                     else
1586                         sweep_line.stopped = left->next;
1587                     if (left->next != NULL)
1588                         left->next->prev = left->prev;
1589                     break;
1590                 }
1591             }
1592
1593             left = e1->prev;
1594             right = e1->next;
1595
1596             if (left != NULL) {
1597                 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, e1);
1598                 if (unlikely (status))
1599                     goto unwind;
1600             }
1601
1602             if (right != NULL) {
1603                 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
1604                 if (unlikely (status))
1605                     goto unwind;
1606             }
1607
1608             break;
1609
1610         case CAIRO_BO_EVENT_TYPE_STOP:
1611             e1 = ((cairo_bo_queue_event_t *) event)->e1;
1612             _cairo_bo_event_queue_delete (&event_queue, event);
1613
1614             left = e1->prev;
1615             right = e1->next;
1616
1617             _cairo_bo_sweep_line_delete (&sweep_line, e1);
1618
1619             /* first, check to see if we have a continuation via a fresh edge */
1620             if (e1->deferred_trap.right != NULL) {
1621                 e1->next = sweep_line.stopped;
1622                 if (sweep_line.stopped != NULL)
1623                     sweep_line.stopped->prev = e1;
1624                 sweep_line.stopped = e1;
1625                 e1->prev = NULL;
1626             }
1627
1628             if (left != NULL && right != NULL) {
1629                 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
1630                 if (unlikely (status))
1631                     goto unwind;
1632             }
1633
1634             break;
1635
1636         case CAIRO_BO_EVENT_TYPE_INTERSECTION:
1637             e1 = ((cairo_bo_queue_event_t *) event)->e1;
1638             e2 = ((cairo_bo_queue_event_t *) event)->e2;
1639             _cairo_bo_event_queue_delete (&event_queue, event);
1640
1641             /* skip this intersection if its edges are not adjacent */
1642             if (e2 != e1->next)
1643                 break;
1644
1645             intersection_count++;
1646
1647             left = e1->prev;
1648             right = e2->next;
1649
1650             _cairo_bo_sweep_line_swap (&sweep_line, e1, e2);
1651
1652             /* after the swap e2 is left of e1 */
1653
1654             if (left != NULL) {
1655                 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, e2);
1656                 if (unlikely (status))
1657                     goto unwind;
1658             }
1659
1660             if (right != NULL) {
1661                 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
1662                 if (unlikely (status))
1663                     goto unwind;
1664             }
1665
1666             break;
1667         }
1668     }
1669
1670     *num_intersections = intersection_count;
1671     for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
1672         if (e1->deferred_trap.right != NULL) {
1673             status = _cairo_bo_edge_end_trap (e1, e1->edge.bottom, traps);
1674             if (unlikely (status))
1675                 break;
1676         }
1677     }
1678  unwind:
1679     _cairo_bo_event_queue_fini (&event_queue);
1680
1681 #if DEBUG_EVENTS
1682     event_log ("\n");
1683 #endif
1684
1685     return status;
1686 }
1687
1688 cairo_status_t
1689 _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t         *traps,
1690                                            const cairo_polygon_t *polygon,
1691                                            cairo_fill_rule_t      fill_rule)
1692 {
1693     int intersections;
1694     cairo_status_t status;
1695     cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
1696     cairo_bo_start_event_t *events;
1697     cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
1698     cairo_bo_event_t **event_ptrs;
1699     cairo_bo_start_event_t *stack_event_y[64];
1700     cairo_bo_start_event_t **event_y = NULL;
1701     int i, num_events, y, ymin, ymax;
1702
1703     num_events = polygon->num_edges;
1704     if (unlikely (0 == num_events))
1705         return CAIRO_STATUS_SUCCESS;
1706
1707     if (polygon->num_limits) {
1708         ymin = _cairo_fixed_integer_floor (polygon->limit.p1.y);
1709         ymax = _cairo_fixed_integer_ceil (polygon->limit.p2.y) - ymin;
1710
1711         if (ymax > 64)
1712             event_y = _cairo_malloc_ab(sizeof (cairo_bo_event_t*), ymax);
1713         else
1714             event_y = stack_event_y;
1715         memset (event_y, 0, ymax * sizeof(cairo_bo_event_t *));
1716     }
1717
1718     events = stack_events;
1719     event_ptrs = stack_event_ptrs;
1720     if (num_events > ARRAY_LENGTH (stack_events)) {
1721         events = _cairo_malloc_ab_plus_c (num_events,
1722                                           sizeof (cairo_bo_start_event_t) +
1723                                           sizeof (cairo_bo_event_t *),
1724                                           sizeof (cairo_bo_event_t *));
1725         if (unlikely (events == NULL))
1726             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1727
1728         event_ptrs = (cairo_bo_event_t **) (events + num_events);
1729     }
1730
1731     for (i = 0; i < num_events; i++) {
1732         events[i].type = CAIRO_BO_EVENT_TYPE_START;
1733         events[i].point.y = polygon->edges[i].top;
1734         events[i].point.x =
1735             _line_compute_intersection_x_for_y (&polygon->edges[i].line,
1736                                                 events[i].point.y);
1737
1738         events[i].edge.edge = polygon->edges[i];
1739         events[i].edge.deferred_trap.right = NULL;
1740         events[i].edge.prev = NULL;
1741         events[i].edge.next = NULL;
1742
1743         if (event_y) {
1744             y = _cairo_fixed_integer_floor (events[i].point.y) - ymin;
1745             events[i].edge.next = (cairo_bo_edge_t *) event_y[y];
1746             event_y[y] = (cairo_bo_start_event_t *) &events[i];
1747         } else
1748             event_ptrs[i] = (cairo_bo_event_t *) &events[i];
1749     }
1750
1751     if (event_y) {
1752         for (y = i = 0; y < ymax && i < num_events; y++) {
1753             cairo_bo_start_event_t *e;
1754             int j = i;
1755             for (e = event_y[y]; e; e = (cairo_bo_start_event_t *)e->edge.next)
1756                 event_ptrs[i++] = (cairo_bo_event_t *) e;
1757             if (i > j + 1)
1758                 _cairo_bo_event_queue_sort (event_ptrs+j, i-j);
1759         }
1760         if (event_y != stack_event_y)
1761             free (event_y);
1762     } else
1763         _cairo_bo_event_queue_sort (event_ptrs, i);
1764     event_ptrs[i] = NULL;
1765
1766 #if DEBUG_TRAPS
1767     dump_edges (events, num_events, "bo-polygon-edges.txt");
1768 #endif
1769
1770     /* XXX: This would be the convenient place to throw in multiple
1771      * passes of the Bentley-Ottmann algorithm. It would merely
1772      * require storing the results of each pass into a temporary
1773      * cairo_traps_t. */
1774     status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs, num_events,
1775                                                          fill_rule, traps,
1776                                                          &intersections);
1777 #if DEBUG_TRAPS
1778     dump_traps (traps, "bo-polygon-out.txt");
1779 #endif
1780
1781     if (events != stack_events)
1782         free (events);
1783
1784     return status;
1785 }
1786
1787 cairo_status_t
1788 _cairo_bentley_ottmann_tessellate_traps (cairo_traps_t *traps,
1789                                          cairo_fill_rule_t fill_rule)
1790 {
1791     cairo_status_t status;
1792     cairo_polygon_t polygon;
1793     int i;
1794
1795     if (unlikely (0 == traps->num_traps))
1796         return CAIRO_STATUS_SUCCESS;
1797
1798 #if DEBUG_TRAPS
1799     dump_traps (traps, "bo-traps-in.txt");
1800 #endif
1801
1802     _cairo_polygon_init (&polygon, traps->limits, traps->num_limits);
1803
1804     for (i = 0; i < traps->num_traps; i++) {
1805         status = _cairo_polygon_add_line (&polygon,
1806                                           &traps->traps[i].left,
1807                                           traps->traps[i].top,
1808                                           traps->traps[i].bottom,
1809                                           1);
1810         if (unlikely (status))
1811             goto CLEANUP;
1812
1813         status = _cairo_polygon_add_line (&polygon,
1814                                           &traps->traps[i].right,
1815                                           traps->traps[i].top,
1816                                           traps->traps[i].bottom,
1817                                           -1);
1818         if (unlikely (status))
1819             goto CLEANUP;
1820     }
1821
1822     _cairo_traps_clear (traps);
1823     status = _cairo_bentley_ottmann_tessellate_polygon (traps,
1824                                                         &polygon,
1825                                                         fill_rule);
1826
1827 #if DEBUG_TRAPS
1828     dump_traps (traps, "bo-traps-out.txt");
1829 #endif
1830
1831   CLEANUP:
1832     _cairo_polygon_fini (&polygon);
1833
1834     return status;
1835 }
1836
1837 #if 0
1838 static cairo_bool_t
1839 edges_have_an_intersection_quadratic (cairo_bo_edge_t   *edges,
1840                                       int                num_edges)
1841
1842 {
1843     int i, j;
1844     cairo_bo_edge_t *a, *b;
1845     cairo_bo_point32_t intersection;
1846
1847     /* We must not be given any upside-down edges. */
1848     for (i = 0; i < num_edges; i++) {
1849         assert (_cairo_bo_point32_compare (&edges[i].top, &edges[i].bottom) < 0);
1850         edges[i].line.p1.x <<= CAIRO_BO_GUARD_BITS;
1851         edges[i].line.p1.y <<= CAIRO_BO_GUARD_BITS;
1852         edges[i].line.p2.x <<= CAIRO_BO_GUARD_BITS;
1853         edges[i].line.p2.y <<= CAIRO_BO_GUARD_BITS;
1854     }
1855
1856     for (i = 0; i < num_edges; i++) {
1857         for (j = 0; j < num_edges; j++) {
1858             if (i == j)
1859                 continue;
1860
1861             a = &edges[i];
1862             b = &edges[j];
1863
1864             if (! _cairo_bo_edge_intersect (a, b, &intersection))
1865                 continue;
1866
1867             printf ("Found intersection (%d,%d) between (%d,%d)-(%d,%d) and (%d,%d)-(%d,%d)\n",
1868                     intersection.x,
1869                     intersection.y,
1870                     a->line.p1.x, a->line.p1.y,
1871                     a->line.p2.x, a->line.p2.y,
1872                     b->line.p1.x, b->line.p1.y,
1873                     b->line.p2.x, b->line.p2.y);
1874
1875             return TRUE;
1876         }
1877     }
1878     return FALSE;
1879 }
1880
1881 #define TEST_MAX_EDGES 10
1882
1883 typedef struct test {
1884     const char *name;
1885     const char *description;
1886     int num_edges;
1887     cairo_bo_edge_t edges[TEST_MAX_EDGES];
1888 } test_t;
1889
1890 static test_t
1891 tests[] = {
1892     {
1893         "3 near misses",
1894         "3 edges all intersecting very close to each other",
1895         3,
1896         {
1897             { { 4, 2}, {0, 0}, { 9, 9}, NULL, NULL },
1898             { { 7, 2}, {0, 0}, { 2, 3}, NULL, NULL },
1899             { { 5, 2}, {0, 0}, { 1, 7}, NULL, NULL }
1900         }
1901     },
1902     {
1903         "inconsistent data",
1904         "Derived from random testing---was leading to skip list and edge list disagreeing.",
1905         2,
1906         {
1907             { { 2, 3}, {0, 0}, { 8, 9}, NULL, NULL },
1908             { { 2, 3}, {0, 0}, { 6, 7}, NULL, NULL }
1909         }
1910     },
1911     {
1912         "failed sort",
1913         "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?",
1914         3,
1915         {
1916             { { 6, 2}, {0, 0}, { 6, 5}, NULL, NULL },
1917             { { 3, 5}, {0, 0}, { 5, 6}, NULL, NULL },
1918             { { 9, 2}, {0, 0}, { 5, 6}, NULL, NULL },
1919         }
1920     },
1921     {
1922         "minimal-intersection",
1923         "Intersection of a two from among the smallest possible edges.",
1924         2,
1925         {
1926             { { 0, 0}, {0, 0}, { 1, 1}, NULL, NULL },
1927             { { 1, 0}, {0, 0}, { 0, 1}, NULL, NULL }
1928         }
1929     },
1930     {
1931         "simple",
1932         "A simple intersection of two edges at an integer (2,2).",
1933         2,
1934         {
1935             { { 1, 1}, {0, 0}, { 3, 3}, NULL, NULL },
1936             { { 2, 1}, {0, 0}, { 2, 3}, NULL, NULL }
1937         }
1938     },
1939     {
1940         "bend-to-horizontal",
1941         "With intersection truncation one edge bends to horizontal",
1942         2,
1943         {
1944             { { 9, 1}, {0, 0}, {3, 7}, NULL, NULL },
1945             { { 3, 5}, {0, 0}, {9, 9}, NULL, NULL }
1946         }
1947     }
1948 };
1949
1950 /*
1951     {
1952         "endpoint",
1953         "An intersection that occurs at the endpoint of a segment.",
1954         {
1955             { { 4, 6}, { 5, 6}, NULL, { { NULL }} },
1956             { { 4, 5}, { 5, 7}, NULL, { { NULL }} },
1957             { { 0, 0}, { 0, 0}, NULL, { { NULL }} },
1958         }
1959     }
1960     {
1961         name = "overlapping",
1962         desc = "Parallel segments that share an endpoint, with different slopes.",
1963         edges = {
1964             { top = { x = 2, y = 0}, bottom = { x = 1, y = 1}},
1965             { top = { x = 2, y = 0}, bottom = { x = 0, y = 2}},
1966             { top = { x = 0, y = 3}, bottom = { x = 1, y = 3}},
1967             { top = { x = 0, y = 3}, bottom = { x = 2, y = 3}},
1968             { top = { x = 0, y = 4}, bottom = { x = 0, y = 6}},
1969             { top = { x = 0, y = 5}, bottom = { x = 0, y = 6}}
1970         }
1971     },
1972     {
1973         name = "hobby_stage_3",
1974         desc = "A particularly tricky part of the 3rd stage of the 'hobby' test below.",
1975         edges = {
1976             { top = { x = -1, y = -2}, bottom = { x =  4, y = 2}},
1977             { top = { x =  5, y =  3}, bottom = { x =  9, y = 5}},
1978             { top = { x =  5, y =  3}, bottom = { x =  6, y = 3}},
1979         }
1980     },
1981     {
1982         name = "hobby",
1983         desc = "Example from John Hobby's paper. Requires 3 passes of the iterative algorithm.",
1984         edges = {
1985             { top = { x =   0, y =   0}, bottom = { x =   9, y =   5}},
1986             { top = { x =   0, y =   0}, bottom = { x =  13, y =   6}},
1987             { top = { x =  -1, y =  -2}, bottom = { x =   9, y =   5}}
1988         }
1989     },
1990     {
1991         name = "slope",
1992         desc = "Edges with same start/stop points but different slopes",
1993         edges = {
1994             { top = { x = 4, y = 1}, bottom = { x = 6, y = 3}},
1995             { top = { x = 4, y = 1}, bottom = { x = 2, y = 3}},
1996             { top = { x = 2, y = 4}, bottom = { x = 4, y = 6}},
1997             { top = { x = 6, y = 4}, bottom = { x = 4, y = 6}}
1998         }
1999     },
2000     {
2001         name = "horizontal",
2002         desc = "Test of a horizontal edge",
2003         edges = {
2004             { top = { x = 1, y = 1}, bottom = { x = 6, y = 6}},
2005             { top = { x = 2, y = 3}, bottom = { x = 5, y = 3}}
2006         }
2007     },
2008     {
2009         name = "vertical",
2010         desc = "Test of a vertical edge",
2011         edges = {
2012             { top = { x = 5, y = 1}, bottom = { x = 5, y = 7}},
2013             { top = { x = 2, y = 4}, bottom = { x = 8, y = 5}}
2014         }
2015     },
2016     {
2017         name = "congruent",
2018         desc = "Two overlapping edges with the same slope",
2019         edges = {
2020             { top = { x = 5, y = 1}, bottom = { x = 5, y = 7}},
2021             { top = { x = 5, y = 2}, bottom = { x = 5, y = 6}},
2022             { top = { x = 2, y = 4}, bottom = { x = 8, y = 5}}
2023         }
2024     },
2025     {
2026         name = "multi",
2027         desc = "Several segments with a common intersection point",
2028         edges = {
2029             { top = { x = 1, y = 2}, bottom = { x = 5, y = 4} },
2030             { top = { x = 1, y = 1}, bottom = { x = 5, y = 5} },
2031             { top = { x = 2, y = 1}, bottom = { x = 4, y = 5} },
2032             { top = { x = 4, y = 1}, bottom = { x = 2, y = 5} },
2033             { top = { x = 5, y = 1}, bottom = { x = 1, y = 5} },
2034             { top = { x = 5, y = 2}, bottom = { x = 1, y = 4} }
2035         }
2036     }
2037 };
2038 */
2039
2040 static int
2041 run_test (const char            *test_name,
2042           cairo_bo_edge_t       *test_edges,
2043           int                    num_edges)
2044 {
2045     int i, intersections, passes;
2046     cairo_bo_edge_t *edges;
2047     cairo_array_t intersected_edges;
2048
2049     printf ("Testing: %s\n", test_name);
2050
2051     _cairo_array_init (&intersected_edges, sizeof (cairo_bo_edge_t));
2052
2053     intersections = _cairo_bentley_ottmann_intersect_edges (test_edges, num_edges, &intersected_edges);
2054     if (intersections)
2055         printf ("Pass 1 found %d intersections:\n", intersections);
2056
2057
2058     /* XXX: Multi-pass Bentley-Ottmmann. Preferable would be to add a
2059      * pass of Hobby's tolerance-square algorithm instead. */
2060     passes = 1;
2061     while (intersections) {
2062         int num_edges = _cairo_array_num_elements (&intersected_edges);
2063         passes++;
2064         edges = _cairo_malloc_ab (num_edges, sizeof (cairo_bo_edge_t));
2065         assert (edges != NULL);
2066         memcpy (edges, _cairo_array_index (&intersected_edges, 0), num_edges * sizeof (cairo_bo_edge_t));
2067         _cairo_array_fini (&intersected_edges);
2068         _cairo_array_init (&intersected_edges, sizeof (cairo_bo_edge_t));
2069         intersections = _cairo_bentley_ottmann_intersect_edges (edges, num_edges, &intersected_edges);
2070         free (edges);
2071
2072         if (intersections){
2073             printf ("Pass %d found %d remaining intersections:\n", passes, intersections);
2074         } else {
2075             if (passes > 3)
2076                 for (i = 0; i < passes; i++)
2077                     printf ("*");
2078             printf ("No remainining intersections found after pass %d\n", passes);
2079         }
2080     }
2081
2082     if (edges_have_an_intersection_quadratic (_cairo_array_index (&intersected_edges, 0),
2083                                               _cairo_array_num_elements (&intersected_edges)))
2084         printf ("*** FAIL ***\n");
2085     else
2086         printf ("PASS\n");
2087
2088     _cairo_array_fini (&intersected_edges);
2089
2090     return 0;
2091 }
2092
2093 #define MAX_RANDOM 300
2094
2095 int
2096 main (void)
2097 {
2098     char random_name[] = "random-XX";
2099     cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
2100     unsigned int i, num_random;
2101     test_t *test;
2102
2103     for (i = 0; i < ARRAY_LENGTH (tests); i++) {
2104         test = &tests[i];
2105         run_test (test->name, test->edges, test->num_edges);
2106     }
2107
2108     for (num_random = 0; num_random < MAX_RANDOM; num_random++) {
2109         srand (0);
2110         for (i = 0; i < num_random; i++) {
2111             do {
2112                 edge = &random_edges[i];
2113                 edge->line.p1.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
2114                 edge->line.p1.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
2115                 edge->line.p2.x = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
2116                 edge->line.p2.y = (int32_t) (10.0 * (rand() / (RAND_MAX + 1.0)));
2117                 if (edge->line.p1.y > edge->line.p2.y) {
2118                     int32_t tmp = edge->line.p1.y;
2119                     edge->line.p1.y = edge->line.p2.y;
2120                     edge->line.p2.y = tmp;
2121                 }
2122             } while (edge->line.p1.y == edge->line.p2.y);
2123         }
2124
2125         sprintf (random_name, "random-%02d", num_random);
2126
2127         run_test (random_name, random_edges, num_random);
2128     }
2129
2130     return 0;
2131 }
2132 #endif