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++) { |