Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1892 Rev 3959
Line 38... Line 38...
38
/* Provide definitions for standalone compilation */
38
/* Provide definitions for standalone compilation */
39
#include "cairoint.h"
39
#include "cairoint.h"
Line 40... Line 40...
40
 
40
 
41
#include "cairo-error-private.h"
41
#include "cairo-error-private.h"
42
#include "cairo-freelist-private.h"
42
#include "cairo-freelist-private.h"
-
 
43
#include "cairo-combsort-inline.h"
Line 43... Line 44...
43
#include "cairo-combsort-private.h"
44
#include "cairo-traps-private.h"
44
 
45
 
45
#define DEBUG_PRINT_STATE 0
46
#define DEBUG_PRINT_STATE 0
Line 69... Line 70...
69
 
70
 
70
struct _cairo_bo_edge {
71
struct _cairo_bo_edge {
71
    cairo_edge_t edge;
72
    cairo_edge_t edge;
72
    cairo_bo_edge_t *prev;
73
    cairo_bo_edge_t *prev;
-
 
74
    cairo_bo_edge_t *next;
73
    cairo_bo_edge_t *next;
75
    cairo_bo_edge_t *colinear;
74
    cairo_bo_trap_t deferred_trap;
76
    cairo_bo_trap_t deferred_trap;
Line 75... Line 77...
75
};
77
};
76
 
78
 
Line 558... Line 560...
558
{
560
{
559
    return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
561
    return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
560
           a->p2.x == b->p2.x && a->p2.y == b->p2.y;
562
           a->p2.x == b->p2.x && a->p2.y == b->p2.y;
561
}
563
}
Line 562... Line 564...
562
 
564
 
563
static int
565
static inline int
564
_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t	*sweep_line,
566
_cairo_bo_sweep_line_compare_edges (const cairo_bo_sweep_line_t	*sweep_line,
565
				    const cairo_bo_edge_t	*a,
567
				    const cairo_bo_edge_t	*a,
566
				    const cairo_bo_edge_t	*b)
568
				    const cairo_bo_edge_t	*b)
567
{
569
{
Line 568... Line 570...
568
    int cmp;
570
    int cmp;
569
 
571
 
-
 
572
    /* compare the edges if not identical */
-
 
573
    if (! _line_equal (&a->edge.line, &b->edge.line)) {
-
 
574
	if (MAX (a->edge.line.p1.x, a->edge.line.p2.x) <
-
 
575
	    MIN (b->edge.line.p1.x, b->edge.line.p2.x))
-
 
576
	    return -1;
-
 
577
	else if (MIN (a->edge.line.p1.x, a->edge.line.p2.x) >
-
 
578
		 MAX (b->edge.line.p1.x, b->edge.line.p2.x))
570
    /* compare the edges if not identical */
579
	    return 1;
571
    if (! _line_equal (&a->edge.line, &b->edge.line)) {
580
 
572
	cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
581
	cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
Line 573... Line 582...
573
	if (cmp)
582
	if (cmp)
Line 1038... Line 1047...
1038
static void
1047
static void
1039
_cairo_bo_event_queue_init (cairo_bo_event_queue_t	 *event_queue,
1048
_cairo_bo_event_queue_init (cairo_bo_event_queue_t	 *event_queue,
1040
			    cairo_bo_event_t		**start_events,
1049
			    cairo_bo_event_t		**start_events,
1041
			    int				  num_events)
1050
			    int				  num_events)
1042
{
1051
{
1043
    _cairo_bo_event_queue_sort (start_events, num_events);
-
 
1044
    start_events[num_events] = NULL;
-
 
1045
 
-
 
1046
    event_queue->start_events = start_events;
1052
    event_queue->start_events = start_events;
Line 1047... Line 1053...
1047
 
1053
 
1048
    _cairo_freepool_init (&event_queue->pool,
1054
    _cairo_freepool_init (&event_queue->pool,
1049
			  sizeof (cairo_bo_queue_event_t));
1055
			  sizeof (cairo_bo_queue_event_t));
Line 1078... Line 1084...
1078
							   cairo_bo_edge_t	*left,
1084
							   cairo_bo_edge_t	*left,
1079
							   cairo_bo_edge_t *right)
1085
							   cairo_bo_edge_t *right)
1080
{
1086
{
1081
    cairo_bo_point32_t intersection;
1087
    cairo_bo_point32_t intersection;
Line -... Line 1088...
-
 
1088
 
-
 
1089
    if (MAX (left->edge.line.p1.x, left->edge.line.p2.x) <=
-
 
1090
	MIN (right->edge.line.p1.x, right->edge.line.p2.x))
-
 
1091
	return CAIRO_STATUS_SUCCESS;
1082
 
1092
 
1083
    if (_line_equal (&left->edge.line, &right->edge.line))
1093
    if (_line_equal (&left->edge.line, &right->edge.line))
Line 1084... Line 1094...
1084
	return CAIRO_STATUS_SUCCESS;
1094
	return CAIRO_STATUS_SUCCESS;
1085
 
1095
 
Line 1107... Line 1117...
1107
    sweep_line->stopped = NULL;
1117
    sweep_line->stopped = NULL;
1108
    sweep_line->current_y = INT32_MIN;
1118
    sweep_line->current_y = INT32_MIN;
1109
    sweep_line->current_edge = NULL;
1119
    sweep_line->current_edge = NULL;
1110
}
1120
}
Line 1111... Line 1121...
1111
 
1121
 
1112
static cairo_status_t
1122
static void
1113
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
1123
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
1114
			     cairo_bo_edge_t		*edge)
1124
			     cairo_bo_edge_t		*edge)
1115
{
1125
{
1116
    if (sweep_line->current_edge != NULL) {
1126
    if (sweep_line->current_edge != NULL) {
Line 1160... Line 1170...
1160
		prev->next->prev = edge;
1170
		prev->next->prev = edge;
1161
	    prev->next = edge;
1171
	    prev->next = edge;
1162
	}
1172
	}
1163
    } else {
1173
    } else {
1164
	sweep_line->head = edge;
1174
	sweep_line->head = edge;
-
 
1175
	edge->next = NULL;
1165
    }
1176
    }
Line 1166... Line 1177...
1166
 
1177
 
1167
    sweep_line->current_edge = edge;
-
 
1168
 
-
 
1169
    return CAIRO_STATUS_SUCCESS;
1178
    sweep_line->current_edge = edge;
Line 1170... Line 1179...
1170
}
1179
}
1171
 
1180
 
1172
static void
1181
static void
Line 1298... Line 1307...
1298
	fclose (file);
1307
	fclose (file);
1299
    }
1308
    }
1300
}
1309
}
1301
#endif
1310
#endif
Line -... Line 1311...
-
 
1311
 
-
 
1312
#define HAS_COLINEAR(a, b) ((cairo_bo_edge_t *)(((uintptr_t)(a))&~1) == (b))
-
 
1313
#define IS_COLINEAR(e) (((uintptr_t)(e))&1)
-
 
1314
#define MARK_COLINEAR(e, v) ((cairo_bo_edge_t *)(((uintptr_t)(e))|(v)))
1302
 
1315
 
1303
static inline cairo_bool_t
1316
static inline cairo_bool_t
1304
edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
1317
edges_colinear (cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
-
 
1318
{
-
 
1319
    unsigned p;
-
 
1320
 
-
 
1321
    if (HAS_COLINEAR(a->colinear, b))
-
 
1322
	return IS_COLINEAR(a->colinear);
-
 
1323
 
-
 
1324
    if (HAS_COLINEAR(b->colinear, a)) {
-
 
1325
	p = IS_COLINEAR(b->colinear);
-
 
1326
	a->colinear = MARK_COLINEAR(b, p);
-
 
1327
	return p;
-
 
1328
    }
-
 
1329
 
1305
{
1330
    p = 0;
-
 
1331
    p |= (a->edge.line.p1.x == b->edge.line.p1.x) << 0;
-
 
1332
    p |= (a->edge.line.p1.y == b->edge.line.p1.y) << 1;
-
 
1333
    p |= (a->edge.line.p2.x == b->edge.line.p2.x) << 3;
-
 
1334
    p |= (a->edge.line.p2.y == b->edge.line.p2.y) << 4;
-
 
1335
    if (p == ((1 << 0) | (1 << 1) | (1 << 3) | (1 << 4))) {
1306
    if (_line_equal (&a->edge.line, &b->edge.line))
1336
	a->colinear = MARK_COLINEAR(b, 1);
-
 
1337
	return TRUE;
Line 1307... Line 1338...
1307
	return TRUE;
1338
    }
-
 
1339
 
1308
 
1340
    if (_slope_compare (a, b)) {
-
 
1341
	a->colinear = MARK_COLINEAR(b, 0);
Line 1309... Line 1342...
1309
    if (_slope_compare (a, b))
1342
	return FALSE;
1310
	return FALSE;
1343
    }
1311
 
1344
 
1312
    /* The choice of y is not truly arbitrary since we must guarantee that it
1345
    /* The choice of y is not truly arbitrary since we must guarantee that it
1313
     * is greater than the start of either line.
1346
     * is greater than the start of either line.
-
 
1347
     */
1314
     */
1348
    if (p != 0) {
1315
    if (a->edge.line.p1.y == b->edge.line.p1.y) {
1349
	/* colinear if either end-point are coincident */
1316
	return a->edge.line.p1.x == b->edge.line.p1.x;
1350
	p = (((p >> 1) & p) & 5) != 0;
1317
    } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
1351
    } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
1318
	return edge_compare_for_y_against_x (b,
1352
	p = edge_compare_for_y_against_x (b,
1319
					     a->edge.line.p1.y,
1353
					  a->edge.line.p1.y,
1320
					     a->edge.line.p1.x) == 0;
1354
					  a->edge.line.p1.x) == 0;
1321
    } else {
1355
    } else {
1322
	return edge_compare_for_y_against_x (a,
1356
	p = edge_compare_for_y_against_x (a,
-
 
1357
					  b->edge.line.p1.y,
-
 
1358
					  b->edge.line.p1.x) == 0;
-
 
1359
    }
1323
					     b->edge.line.p1.y,
1360
 
Line 1324... Line 1361...
1324
					     b->edge.line.p1.x) == 0;
1361
    a->colinear = MARK_COLINEAR(b, p);
1325
    }
1362
    return p;
1326
}
1363
}
1327
 
1364
 
1328
/* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t */
1365
/* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t */
1329
static cairo_status_t
1366
static void
1330
_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
1367
_cairo_bo_edge_end_trap (cairo_bo_edge_t	*left,
Line 1356... Line 1393...
1356
		   bot);
1393
		   bot);
1357
#endif
1394
#endif
1358
    }
1395
    }
Line 1359... Line 1396...
1359
 
1396
 
1360
    trap->right = NULL;
-
 
1361
 
-
 
1362
    return _cairo_traps_status (traps);
1397
    trap->right = NULL;
Line 1363... Line 1398...
1363
}
1398
}
1364
 
1399
 
1365
 
1400
 
1366
/* Start a new trapezoid at the given top y coordinate, whose edges
1401
/* Start a new trapezoid at the given top y coordinate, whose edges
1367
 * are `edge' and `edge->next'. If `edge' already has a trapezoid,
1402
 * are `edge' and `edge->next'. If `edge' already has a trapezoid,
1368
 * then either add it to the traps in `traps', if the trapezoid's
1403
 * then either add it to the traps in `traps', if the trapezoid's
1369
 * right edge differs from `edge->next', or do nothing if the new
1404
 * right edge differs from `edge->next', or do nothing if the new
1370
 * trapezoid would be a continuation of the existing one. */
1405
 * trapezoid would be a continuation of the existing one. */
1371
static inline cairo_status_t
1406
static inline void
1372
_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t	*left,
1407
_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t	*left,
1373
				       cairo_bo_edge_t  *right,
1408
				       cairo_bo_edge_t  *right,
1374
				       int               top,
-
 
1375
				       cairo_traps_t	*traps)
-
 
1376
{
1409
				       int               top,
1377
    cairo_status_t status;
1410
				       cairo_traps_t	*traps)
Line -... Line 1411...
-
 
1411
{
1378
 
1412
    if (left->deferred_trap.right == right)
1379
    if (left->deferred_trap.right == right)
1413
	return;
1380
	return CAIRO_STATUS_SUCCESS;
1414
 
1381
 
1415
    assert (right);
1382
    if (left->deferred_trap.right != NULL) {
1416
    if (left->deferred_trap.right != NULL) {
1383
	if (right != NULL && edges_colinear (left->deferred_trap.right, right))
1417
	if (edges_colinear (left->deferred_trap.right, right))
1384
	{
1418
	{
Line 1385... Line 1419...
1385
	    /* continuation on right, so just swap edges */
1419
	    /* continuation on right, so just swap edges */
1386
	    left->deferred_trap.right = right;
-
 
1387
	    return CAIRO_STATUS_SUCCESS;
-
 
1388
	}
1420
	    left->deferred_trap.right = right;
Line 1389... Line 1421...
1389
 
1421
	    return;
1390
	status = _cairo_bo_edge_end_trap (left, top, traps);
1422
	}
1391
	if (unlikely (status))
1423
 
Line 1392... Line 1424...
1392
	    return status;
1424
	_cairo_bo_edge_end_trap (left, top, traps);
1393
    }
1425
    }
1394
 
1426
 
1395
    if (right != NULL && ! edges_colinear (left, right)) {
1427
    if (! edges_colinear (left, right)) {
1396
	left->deferred_trap.top = top;
1428
	left->deferred_trap.top = top;
1397
	left->deferred_trap.right = right;
1429
	left->deferred_trap.right = right;
1398
 
1430
 
1399
#if DEBUG_EVENTS
-
 
1400
	event_log ("begin trap: %lu %lu %d\n",
-
 
1401
		   (long) left,
1431
#if DEBUG_EVENTS
Line 1402... Line 1432...
1402
		   (long) right,
1432
	event_log ("begin trap: %lu %lu %d\n",
1403
		   top);
1433
		   (long) left,
1404
#endif
1434
		   (long) right,
1405
    }
1435
		   top);
1406
 
1436
#endif
1407
    return CAIRO_STATUS_SUCCESS;
1437
    }
1408
}
1438
}
1409
 
1439
 
-
 
1440
static inline void
Line 1410... Line 1441...
1410
static inline cairo_status_t
1441
_active_edges_to_traps (cairo_bo_edge_t	*pos,
1411
_active_edges_to_traps (cairo_bo_edge_t		*left,
1442
			int32_t		 top,
1412
			int32_t			 top,
1443
			unsigned	 mask,
Line 1413... Line 1444...
1413
			cairo_fill_rule_t	 fill_rule,
1444
			cairo_traps_t        *traps)
-
 
1445
{
1414
			cairo_traps_t	        *traps)
1446
    cairo_bo_edge_t *left;
1415
{
1447
    int in_out;
1416
    cairo_bo_edge_t *right;
-
 
1417
    cairo_status_t status;
1448
 
1418
 
1449
 
1419
#if DEBUG_PRINT_STATE
1450
#if DEBUG_PRINT_STATE
1420
    printf ("Processing active edges for %x\n", top);
-
 
1421
#endif
-
 
1422
 
-
 
1423
    if (fill_rule == CAIRO_FILL_RULE_WINDING) {
-
 
1424
	while (left != NULL) {
1451
    printf ("Processing active edges for %x\n", top);
1425
	    int in_out;
-
 
1426
 
1452
#endif
1427
	    /* Greedily search for the closing edge, so that we generate the
1453
 
1428
	     * maximal span width with the minimal number of trapezoids.
-
 
1429
	     */
1454
    in_out = 0;
1430
	    in_out = left->edge.dir;
1455
    left = pos;
1431
 
1456
    while (pos != NULL) {
1432
	    /* Check if there is a co-linear edge with an existing trap */
-
 
1433
	    right = left->next;
-
 
1434
	    if (left->deferred_trap.right == NULL) {
-
 
1435
		while (right != NULL && right->deferred_trap.right == NULL)
-
 
1436
		    right = right->next;
-
 
1437
 
-
 
1438
		if (right != NULL && edges_colinear (left, right)) {
-
 
1439
		    /* continuation on left */
-
 
1440
		    left->deferred_trap = right->deferred_trap;
-
 
1441
		    right->deferred_trap.right = NULL;
-
 
1442
		}
-
 
1443
	    }
-
 
1444
 
-
 
1445
	    /* End all subsumed traps */
-
 
1446
	    right = left->next;
-
 
1447
	    while (right != NULL) {
-
 
1448
		if (right->deferred_trap.right != NULL) {
-
 
1449
		    status = _cairo_bo_edge_end_trap (right, top, traps);
-
 
1450
		    if (unlikely (status))
-
 
1451
			return status;
-
 
1452
		}
-
 
1453
 
-
 
1454
		in_out += right->edge.dir;
-
 
1455
		if (in_out == 0) {
-
 
1456
		    cairo_bo_edge_t *next;
1457
	if (pos != left && pos->deferred_trap.right) {
-
 
1458
	    /* XXX It shouldn't be possible to here with 2 deferred traps
1457
		    cairo_bool_t skip = FALSE;
1459
	     * on colinear edges... See bug-bo-rictoz.
1458
 
1460
	     */
1459
		    /* skip co-linear edges */
1461
	    if (left->deferred_trap.right == NULL &&
1460
		    next = right->next;
-
 
1461
		    if (next != NULL)
-
 
1462
			skip = edges_colinear (right, next);
-
 
1463
 
-
 
1464
		    if (! skip)
-
 
1465
			break;
-
 
1466
		}
-
 
1467
 
-
 
1468
		right = right->next;
-
 
1469
	    }
1462
		edges_colinear (left, pos))
1470
 
-
 
1471
	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-
 
1472
							    top, traps);
-
 
1473
	    if (unlikely (status))
-
 
1474
		return status;
-
 
1475
 
-
 
1476
	    left = right;
-
 
1477
	    if (left != NULL)
-
 
1478
		left = left->next;
-
 
1479
	}
-
 
1480
    } else {
-
 
1481
	while (left != NULL) {
-
 
1482
	    int in_out = 0;
-
 
1483
 
-
 
1484
	    right = left->next;
-
 
Line -... Line 1463...
-
 
1463
	    {
-
 
1464
		/* continuation on left */
1485
	    while (right != NULL) {
1465
		left->deferred_trap = pos->deferred_trap;
1486
		if (right->deferred_trap.right != NULL) {
-
 
1487
		    status = _cairo_bo_edge_end_trap (right, top, traps);
1466
		pos->deferred_trap.right = NULL;
1488
		    if (unlikely (status))
1467
	    }
1489
			return status;
-
 
1490
		}
1468
	    else
1491
 
-
 
1492
		if ((in_out++ & 1) == 0) {
1469
	    {
1493
		    cairo_bo_edge_t *next;
-
 
1494
		    cairo_bool_t skip = FALSE;
-
 
1495
 
1470
		_cairo_bo_edge_end_trap (pos, top, traps);
Line 1496... Line -...
1496
		    /* skip co-linear edges */
-
 
1497
		    next = right->next;
-
 
1498
		    if (next != NULL)
-
 
1499
			skip = edges_colinear (right, next);
-
 
1500
 
-
 
1501
		    if (! skip)
-
 
1502
			break;
-
 
1503
		}
1471
	    }
1504
 
1472
	}
1505
		right = right->next;
1473
 
Line 1506... Line -...
1506
	    }
-
 
1507
 
-
 
1508
	    status = _cairo_bo_edge_start_or_continue_trap (left, right,
-
 
1509
							    top, traps);
-
 
1510
	    if (unlikely (status))
1474
	in_out += pos->edge.dir;
1511
		return status;
1475
	if ((in_out & mask) == 0) {
1512
 
1476
	    /* skip co-linear edges */
1513
	    left = right;
1477
	    if (pos->next == NULL || ! edges_colinear (pos, pos->next)) {
1514
	    if (left != NULL)
1478
		_cairo_bo_edge_start_or_continue_trap (left, pos, top, traps);
1515
		left = left->next;
1479
		left = pos->next;
1516
	}
1480
	    }
1517
    }
1481
	}
1518
 
1482
 
1519
    return CAIRO_STATUS_SUCCESS;
1483
	pos = pos->next;
1520
}
1484
    }
1521
 
1485
}
1522
 
1486
 
1523
/* Execute a single pass of the Bentley-Ottmann algorithm on edges,
1487
/* Execute a single pass of the Bentley-Ottmann algorithm on edges,
1524
 * generating trapezoids according to the fill_rule and appending them
1488
 * generating trapezoids according to the fill_rule and appending them
1525
 * to traps. */
1489
 * to traps. */
1526
static cairo_status_t
1490
static cairo_status_t
Line -... Line 1491...
-
 
1491
_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t   **start_events,
-
 
1492
					    int			 num_events,
-
 
1493
					    unsigned		 fill_rule,
-
 
1494
					    cairo_traps_t	*traps,
-
 
1495
					    int			*num_intersections)
-
 
1496
{
1527
_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t   **start_events,
1497
    cairo_status_t status;
1528
					    int			 num_events,
1498
    int intersection_count = 0;
1529
					    cairo_fill_rule_t	 fill_rule,
1499
    cairo_bo_event_queue_t event_queue;
Line 1530... Line 1500...
1530
					    cairo_traps_t	*traps,
1500
    cairo_bo_sweep_line_t sweep_line;
Line 1563... Line 1533...
1563
 
1533
 
1564
    while ((event = _cairo_bo_event_dequeue (&event_queue))) {
1534
    while ((event = _cairo_bo_event_dequeue (&event_queue))) {
1565
	if (event->point.y != sweep_line.current_y) {
1535
	if (event->point.y != sweep_line.current_y) {
1566
	    for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
1536
	    for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
1567
		if (e1->deferred_trap.right != NULL) {
1537
		if (e1->deferred_trap.right != NULL) {
1568
		    status = _cairo_bo_edge_end_trap (e1,
1538
		    _cairo_bo_edge_end_trap (e1,
1569
						      e1->edge.bottom,
1539
					     e1->edge.bottom,
1570
						      traps);
-
 
1571
		    if (unlikely (status))
-
 
1572
			goto unwind;
1540
					     traps);
1573
		}
1541
		}
1574
	    }
1542
	    }
Line 1575... Line 1543...
1575
	    sweep_line.stopped = NULL;
1543
	    sweep_line.stopped = NULL;
1576
 
1544
 
1577
	    status = _active_edges_to_traps (sweep_line.head,
1545
	    _active_edges_to_traps (sweep_line.head,
1578
					     sweep_line.current_y,
-
 
1579
					     fill_rule, traps);
-
 
Line 1580... Line 1546...
1580
	    if (unlikely (status))
1546
				    sweep_line.current_y,
1581
		goto unwind;
1547
				    fill_rule, traps);
Line 1582... Line 1548...
1582
 
1548
 
Line 1594... Line 1560...
1594
 
1560
 
1595
	switch (event->type) {
1561
	switch (event->type) {
1596
	case CAIRO_BO_EVENT_TYPE_START:
1562
	case CAIRO_BO_EVENT_TYPE_START:
Line 1597... Line 1563...
1597
	    e1 = &((cairo_bo_start_event_t *) event)->edge;
1563
	    e1 = &((cairo_bo_start_event_t *) event)->edge;
1598
 
-
 
1599
	    status = _cairo_bo_sweep_line_insert (&sweep_line, e1);
-
 
Line 1600... Line 1564...
1600
	    if (unlikely (status))
1564
 
1601
		goto unwind;
1565
	    _cairo_bo_sweep_line_insert (&sweep_line, e1);
1602
 
1566
 
Line 1699... Line 1663...
1699
    }
1663
    }
Line 1700... Line 1664...
1700
 
1664
 
1701
    *num_intersections = intersection_count;
1665
    *num_intersections = intersection_count;
1702
    for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
1666
    for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
1703
	if (e1->deferred_trap.right != NULL) {
1667
	if (e1->deferred_trap.right != NULL) {
1704
	    status = _cairo_bo_edge_end_trap (e1, e1->edge.bottom, traps);
-
 
1705
	    if (unlikely (status))
-
 
1706
		break;
1668
	    _cairo_bo_edge_end_trap (e1, e1->edge.bottom, traps);
1707
	}
1669
	}
-
 
1670
    }
1708
    }
1671
    status = traps->status;
1709
 unwind:
1672
 unwind:
Line 1710... Line 1673...
1710
    _cairo_bo_event_queue_fini (&event_queue);
1673
    _cairo_bo_event_queue_fini (&event_queue);
1711
 
1674
 
Line 1720... Line 1683...
1720
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
1683
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
1721
					   const cairo_polygon_t *polygon,
1684
					   const cairo_polygon_t *polygon,
1722
					   cairo_fill_rule_t	  fill_rule)
1685
					   cairo_fill_rule_t	  fill_rule)
1723
{
1686
{
1724
    int intersections;
1687
    int intersections;
1725
    cairo_status_t status;
-
 
1726
    cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
1688
    cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
1727
    cairo_bo_start_event_t *events;
1689
    cairo_bo_start_event_t *events;
1728
    cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
1690
    cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
1729
    cairo_bo_event_t **event_ptrs;
1691
    cairo_bo_event_t **event_ptrs;
-
 
1692
    cairo_bo_start_event_t *stack_event_y[64];
-
 
1693
    cairo_bo_start_event_t **event_y = NULL;
1730
    int num_events;
1694
    int i, num_events, y, ymin, ymax;
1731
    int i;
1695
    cairo_status_t status;
Line 1732... Line 1696...
1732
 
1696
 
1733
    num_events = polygon->num_edges;
1697
    num_events = polygon->num_edges;
1734
    if (unlikely (0 == num_events))
1698
    if (unlikely (0 == num_events))
Line -... Line 1699...
-
 
1699
	return CAIRO_STATUS_SUCCESS;
-
 
1700
 
-
 
1701
    if (polygon->num_limits) {
-
 
1702
	ymin = _cairo_fixed_integer_floor (polygon->limit.p1.y);
-
 
1703
	ymax = _cairo_fixed_integer_ceil (polygon->limit.p2.y) - ymin;
-
 
1704
 
-
 
1705
	if (ymax > 64)
-
 
1706
	    event_y = _cairo_malloc_ab(sizeof (cairo_bo_event_t*), ymax);
-
 
1707
	else
-
 
1708
	    event_y = stack_event_y;
-
 
1709
	memset (event_y, 0, ymax * sizeof(cairo_bo_event_t *));
1735
	return CAIRO_STATUS_SUCCESS;
1710
    }
1736
 
1711
 
1737
    events = stack_events;
1712
    events = stack_events;
1738
    event_ptrs = stack_event_ptrs;
1713
    event_ptrs = stack_event_ptrs;
1739
    if (num_events > ARRAY_LENGTH (stack_events)) {
1714
    if (num_events > ARRAY_LENGTH (stack_events)) {
Line 1746... Line 1721...
1746
 
1721
 
1747
	event_ptrs = (cairo_bo_event_t **) (events + num_events);
1722
	event_ptrs = (cairo_bo_event_t **) (events + num_events);
Line 1748... Line 1723...
1748
    }
1723
    }
1749
 
-
 
1750
    for (i = 0; i < num_events; i++) {
-
 
1751
	event_ptrs[i] = (cairo_bo_event_t *) &events[i];
1724
 
1752
 
1725
    for (i = 0; i < num_events; i++) {
1753
	events[i].type = CAIRO_BO_EVENT_TYPE_START;
1726
	events[i].type = CAIRO_BO_EVENT_TYPE_START;
1754
	events[i].point.y = polygon->edges[i].top;
1727
	events[i].point.y = polygon->edges[i].top;
1755
	events[i].point.x =
1728
	events[i].point.x =
Line 1756... Line 1729...
1756
	    _line_compute_intersection_x_for_y (&polygon->edges[i].line,
1729
	    _line_compute_intersection_x_for_y (&polygon->edges[i].line,
1757
						events[i].point.y);
1730
						events[i].point.y);
1758
 
1731
 
1759
	events[i].edge.edge = polygon->edges[i];
1732
	events[i].edge.edge = polygon->edges[i];
-
 
1733
	events[i].edge.deferred_trap.right = NULL;
-
 
1734
	events[i].edge.prev = NULL;
-
 
1735
	events[i].edge.next = NULL;
-
 
1736
	events[i].edge.colinear = NULL;
-
 
1737
 
-
 
1738
	if (event_y) {
-
 
1739
	    y = _cairo_fixed_integer_floor (events[i].point.y) - ymin;
-
 
1740
	    events[i].edge.next = (cairo_bo_edge_t *) event_y[y];
1760
	events[i].edge.deferred_trap.right = NULL;
1741
	    event_y[y] = (cairo_bo_start_event_t *) &events[i];
Line -... Line 1742...
-
 
1742
	} else
-
 
1743
	    event_ptrs[i] = (cairo_bo_event_t *) &events[i];
-
 
1744
    }
-
 
1745
 
-
 
1746
    if (event_y) {
-
 
1747
	for (y = i = 0; y < ymax && i < num_events; y++) {
-
 
1748
	    cairo_bo_start_event_t *e;
-
 
1749
	    int j = i;
-
 
1750
	    for (e = event_y[y]; e; e = (cairo_bo_start_event_t *)e->edge.next)
-
 
1751
		event_ptrs[i++] = (cairo_bo_event_t *) e;
-
 
1752
	    if (i > j + 1)
-
 
1753
		_cairo_bo_event_queue_sort (event_ptrs+j, i-j);
-
 
1754
	}
-
 
1755
	if (event_y != stack_event_y)
-
 
1756
	    free (event_y);
1761
	events[i].edge.prev = NULL;
1757
    } else
1762
	events[i].edge.next = NULL;
1758
	_cairo_bo_event_queue_sort (event_ptrs, i);
1763
    }
1759
    event_ptrs[i] = NULL;
Line 1764... Line 1760...
1764
 
1760
 
1765
#if DEBUG_TRAPS
1761
#if DEBUG_TRAPS
1766
    dump_edges (events, num_events, "bo-polygon-edges.txt");
1762
    dump_edges (events, num_events, "bo-polygon-edges.txt");
1767
#endif
1763
#endif
1768
 
1764
 
1769
    /* XXX: This would be the convenient place to throw in multiple
-
 
1770
     * passes of the Bentley-Ottmann algorithm. It would merely
1765
    /* XXX: This would be the convenient place to throw in multiple
1771
     * require storing the results of each pass into a temporary
1766
     * passes of the Bentley-Ottmann algorithm. It would merely
1772
     * cairo_traps_t. */
1767
     * require storing the results of each pass into a temporary
1773
    status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
1768
     * cairo_traps_t. */
1774
							 num_events,
1769
    status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs, num_events,
Line 1797... Line 1792...
1797
 
1792
 
1798
#if DEBUG_TRAPS
1793
#if DEBUG_TRAPS
1799
    dump_traps (traps, "bo-traps-in.txt");
1794
    dump_traps (traps, "bo-traps-in.txt");
Line 1800... Line -...
1800
#endif
-
 
1801
 
1795
#endif
Line 1802... Line 1796...
1802
    _cairo_polygon_init (&polygon);
1796
 
1803
    _cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
1797
    _cairo_polygon_init (&polygon, traps->limits, traps->num_limits);
1804
 
1798
 
1805
    for (i = 0; i < traps->num_traps; i++) {
1799
    for (i = 0; i < traps->num_traps; i++) {