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 31... | Line 31... | ||
31 | * Chris Wilson |
31 | * Chris Wilson |
32 | */ |
32 | */ |
Line 33... | Line 33... | ||
33 | 33 | ||
Line 34... | Line 34... | ||
34 | #include "cairoint.h" |
34 | #include "cairoint.h" |
35 | 35 | ||
36 | #include "cairo-combsort-private.h" |
36 | #include "cairo-combsort-inline.h" |
37 | #include "cairo-error-private.h" |
37 | #include "cairo-error-private.h" |
38 | #include "cairo-freelist-private.h" |
38 | #include "cairo-freelist-private.h" |
Line 377... | Line 377... | ||
377 | prev_coverage = coverage = 0; |
377 | prev_coverage = coverage = 0; |
378 | prev_x = INT_MIN; |
378 | prev_x = INT_MIN; |
379 | for (cell = sweep->coverage.head.next; cell != &sweep->coverage.tail; cell = cell->next) { |
379 | for (cell = sweep->coverage.head.next; cell != &sweep->coverage.tail; cell = cell->next) { |
380 | if (cell->x != prev_x && coverage != prev_coverage) { |
380 | if (cell->x != prev_x && coverage != prev_coverage) { |
381 | int n = sweep->num_spans++; |
381 | int n = sweep->num_spans++; |
- | 382 | int c = coverage >> (CAIRO_FIXED_FRAC_BITS * 2 - 8); |
|
382 | sweep->spans[n].x = prev_x; |
383 | sweep->spans[n].x = prev_x; |
383 | sweep->spans[n].coverage = coverage >> (CAIRO_FIXED_FRAC_BITS * 2 - 8); |
384 | sweep->spans[n].inverse = 0; |
384 | sweep->spans[n].coverage -= sweep->spans[n].coverage >> 8; |
385 | sweep->spans[n].coverage = c - (c >> 8); |
385 | prev_coverage = coverage; |
386 | prev_coverage = coverage; |
386 | } |
387 | } |
Line 387... | Line 388... | ||
387 | 388 | ||
388 | coverage += cell->covered; |
389 | coverage += cell->covered; |
389 | if (coverage != prev_coverage) { |
390 | if (coverage != prev_coverage) { |
- | 391 | int n = sweep->num_spans++; |
|
390 | int n = sweep->num_spans++; |
392 | int c = coverage >> (CAIRO_FIXED_FRAC_BITS * 2 - 8); |
391 | sweep->spans[n].x = cell->x; |
393 | sweep->spans[n].x = cell->x; |
392 | sweep->spans[n].coverage = coverage >> (CAIRO_FIXED_FRAC_BITS * 2 - 8); |
394 | sweep->spans[n].inverse = 0; |
393 | sweep->spans[n].coverage -= sweep->spans[n].coverage >> 8; |
395 | sweep->spans[n].coverage = c - (c >> 8); |
394 | prev_coverage = coverage; |
396 | prev_coverage = coverage; |
395 | } |
397 | } |
396 | coverage += cell->uncovered; |
398 | coverage += cell->uncovered; |
397 | prev_x = cell->x + 1; |
399 | prev_x = cell->x + 1; |
398 | } |
400 | } |
Line 399... | Line 401... | ||
399 | _cairo_freepool_reset (&sweep->coverage.pool); |
401 | _cairo_freepool_reset (&sweep->coverage.pool); |
400 | 402 | ||
401 | if (sweep->num_spans) { |
403 | if (sweep->num_spans) { |
- | 404 | if (prev_x <= sweep->xmax) { |
|
402 | if (prev_x <= sweep->xmax) { |
405 | int n = sweep->num_spans++; |
- | 406 | int c = coverage >> (CAIRO_FIXED_FRAC_BITS * 2 - 8); |
|
403 | int n = sweep->num_spans++; |
407 | sweep->spans[n].x = prev_x; |
404 | sweep->spans[n].x = prev_x; |
408 | sweep->spans[n].inverse = 0; |
Line 405... | Line 409... | ||
405 | sweep->spans[n].coverage = coverage; |
409 | sweep->spans[n].coverage = c - (c >> 8); |
406 | } |
410 | } |
407 | 411 | ||
- | 412 | if (coverage && prev_x < sweep->xmax) { |
|
408 | if (coverage && prev_x < sweep->xmax) { |
413 | int n = sweep->num_spans++; |
409 | int n = sweep->num_spans++; |
414 | sweep->spans[n].x = sweep->xmax; |
410 | sweep->spans[n].x = sweep->xmax; |
415 | sweep->spans[n].inverse = 1; |
411 | sweep->spans[n].coverage = 0; |
416 | sweep->spans[n].coverage = 0; |
Line 487... | Line 492... | ||
487 | sweep_line_t sweep_line; |
492 | sweep_line_t sweep_line; |
488 | rectangle_t *start, *stop; |
493 | rectangle_t *start, *stop; |
489 | cairo_status_t status; |
494 | cairo_status_t status; |
Line 490... | Line 495... | ||
490 | 495 | ||
491 | sweep_line_init (&sweep_line); |
496 | sweep_line_init (&sweep_line); |
492 | sweep_line.xmin = self->xmin; |
497 | sweep_line.xmin = _cairo_fixed_integer_part (self->extents.p1.x); |
493 | sweep_line.xmax = self->xmax; |
498 | sweep_line.xmax = _cairo_fixed_integer_part (self->extents.p2.x); |
494 | sweep_line.start = rectangles; |
499 | sweep_line.start = rectangles; |
495 | if ((status = setjmp (sweep_line.jmpbuf))) |
500 | if ((status = setjmp (sweep_line.jmpbuf))) |
Line 496... | Line 501... | ||
496 | goto BAIL; |
501 | goto out; |
497 | 502 | ||
498 | sweep_line.current_y = self->ymin; |
503 | sweep_line.current_y = _cairo_fixed_integer_part (self->extents.p1.y); |
499 | start = *sweep_line.start++; |
504 | start = *sweep_line.start++; |
500 | do { |
505 | do { |
501 | if (start->top_y != sweep_line.current_y) { |
506 | if (start->top_y != sweep_line.current_y) { |
Line 552... | Line 557... | ||
552 | stop = peek_stop (&sweep_line); |
557 | stop = peek_stop (&sweep_line); |
553 | if (stop == NULL) |
558 | if (stop == NULL) |
554 | goto out; |
559 | goto out; |
555 | } |
560 | } |
Line 556... | Line 561... | ||
556 | 561 | ||
557 | sweep_line.current_y++; |
- | |
558 | - | ||
559 | do { |
562 | while (++sweep_line.current_y < _cairo_fixed_integer_part (self->extents.p2.y)) { |
560 | if (stop->bottom_y != sweep_line.current_y) { |
563 | if (stop->bottom_y != sweep_line.current_y) { |
561 | render_rows (&sweep_line, renderer, |
564 | render_rows (&sweep_line, renderer, |
562 | stop->bottom_y - sweep_line.current_y); |
565 | stop->bottom_y - sweep_line.current_y); |
563 | sweep_line.current_y = stop->bottom_y; |
566 | sweep_line.current_y = stop->bottom_y; |
Line 570... | Line 573... | ||
570 | stop = peek_stop (&sweep_line); |
573 | stop = peek_stop (&sweep_line); |
571 | if (stop == NULL) |
574 | if (stop == NULL) |
572 | goto out; |
575 | goto out; |
573 | } while (stop->bottom_y == sweep_line.current_y); |
576 | } while (stop->bottom_y == sweep_line.current_y); |
Line 574... | Line -... | ||
574 | - | ||
575 | sweep_line.current_y++; |
577 | |
Line 576... | Line 578... | ||
576 | } while (TRUE); |
578 | } |
577 | - | ||
578 | out: |
- | |
579 | status = renderer->render_rows (renderer, |
- | |
580 | sweep_line.current_y, |
- | |
581 | self->ymax - sweep_line.current_y, |
- | |
582 | NULL, 0); |
- | |
583 | 579 | ||
Line 584... | Line 580... | ||
584 | BAIL: |
580 | out: |
585 | sweep_line_fini (&sweep_line); |
581 | sweep_line_fini (&sweep_line); |
- | 582 | ||
- | 583 | return status; |
|
- | 584 | } |
|
- | 585 | static void generate_row(cairo_span_renderer_t *renderer, |
|
- | 586 | const rectangle_t *r, |
|
- | 587 | int y, int h, |
|
- | 588 | uint16_t coverage) |
|
- | 589 | { |
|
- | 590 | cairo_half_open_span_t spans[4]; |
|
- | 591 | unsigned int num_spans = 0; |
|
- | 592 | int x1 = _cairo_fixed_integer_part (r->left); |
|
- | 593 | int x2 = _cairo_fixed_integer_part (r->right); |
|
- | 594 | if (x2 > x1) { |
|
- | 595 | if (! _cairo_fixed_is_integer (r->left)) { |
|
- | 596 | spans[num_spans].x = x1; |
|
- | 597 | spans[num_spans].coverage = |
|
- | 598 | coverage * (256 - _cairo_fixed_fractional_part (r->left)) >> 8; |
|
- | 599 | num_spans++; |
|
- | 600 | x1++; |
|
- | 601 | } |
|
- | 602 | ||
- | 603 | if (x2 > x1) { |
|
- | 604 | spans[num_spans].x = x1; |
|
- | 605 | spans[num_spans].coverage = coverage - (coverage >> 8); |
|
- | 606 | num_spans++; |
|
- | 607 | } |
|
- | 608 | ||
- | 609 | if (! _cairo_fixed_is_integer (r->right)) { |
|
- | 610 | spans[num_spans].x = x2++; |
|
- | 611 | spans[num_spans].coverage = |
|
- | 612 | coverage * _cairo_fixed_fractional_part (r->right) >> 8; |
|
- | 613 | num_spans++; |
|
- | 614 | } |
|
- | 615 | } else { |
|
- | 616 | spans[num_spans].x = x2++; |
|
- | 617 | spans[num_spans].coverage = coverage * (r->right - r->left) >> 8; |
|
- | 618 | num_spans++; |
|
- | 619 | } |
|
- | 620 | ||
- | 621 | spans[num_spans].x = x2; |
|
- | 622 | spans[num_spans].coverage = 0; |
|
- | 623 | num_spans++; |
|
- | 624 | ||
- | 625 | renderer->render_rows (renderer, y, h, spans, num_spans); |
|
- | 626 | } |
|
- | 627 | ||
- | 628 | static cairo_status_t |
|
- | 629 | generate_box (cairo_rectangular_scan_converter_t *self, |
|
- | 630 | cairo_span_renderer_t *renderer) |
|
- | 631 | { |
|
- | 632 | const rectangle_t *r = self->chunks.base; |
|
- | 633 | int y1 = _cairo_fixed_integer_part (r->top); |
|
- | 634 | int y2 = _cairo_fixed_integer_part (r->bottom); |
|
- | 635 | if (y2 > y1) { |
|
- | 636 | if (! _cairo_fixed_is_integer (r->top)) { |
|
- | 637 | generate_row(renderer, r, y1, 1, |
|
- | 638 | 256 - _cairo_fixed_fractional_part (r->top)); |
|
- | 639 | y1++; |
|
- | 640 | } |
|
- | 641 | ||
- | 642 | if (y2 > y1) |
|
- | 643 | generate_row(renderer, r, y1, y2-y1, 256); |
|
- | 644 | ||
- | 645 | if (! _cairo_fixed_is_integer (r->bottom)) |
|
- | 646 | generate_row(renderer, r, y2, 1, |
|
- | 647 | _cairo_fixed_fractional_part (r->bottom)); |
|
- | 648 | } else |
|
- | 649 | generate_row(renderer, r, y1, 1, r->bottom - r->top); |
|
Line 586... | Line 650... | ||
586 | 650 | ||
587 | return status; |
651 | return CAIRO_STATUS_SUCCESS; |
588 | } |
652 | } |
589 | 653 | ||
Line 598... | Line 662... | ||
598 | cairo_status_t status; |
662 | cairo_status_t status; |
599 | int i, j; |
663 | int i, j; |
Line 600... | Line 664... | ||
600 | 664 | ||
601 | if (unlikely (self->num_rectangles == 0)) { |
665 | if (unlikely (self->num_rectangles == 0)) { |
602 | return renderer->render_rows (renderer, |
666 | return renderer->render_rows (renderer, |
- | 667 | _cairo_fixed_integer_part (self->extents.p1.y), |
|
603 | self->ymin, self->ymax - self->ymin, |
668 | _cairo_fixed_integer_part (self->extents.p2.y - self->extents.p1.y), |
604 | NULL, 0); |
669 | NULL, 0); |
Line -... | Line 670... | ||
- | 670 | } |
|
- | 671 | ||
- | 672 | if (self->num_rectangles == 1) |
|
605 | } |
673 | return generate_box (self, renderer); |
606 | 674 | ||
607 | rectangles = rectangles_stack; |
675 | rectangles = rectangles_stack; |
608 | if (unlikely (self->num_rectangles >= ARRAY_LENGTH (rectangles_stack))) { |
676 | if (unlikely (self->num_rectangles >= ARRAY_LENGTH (rectangles_stack))) { |
609 | rectangles = _cairo_malloc_ab (self->num_rectangles + 1, |
677 | rectangles = _cairo_malloc_ab (self->num_rectangles + 1, |
Line 670... | Line 738... | ||
670 | 738 | ||
671 | rectangle = _allocate_rectangle (self); |
739 | rectangle = _allocate_rectangle (self); |
672 | if (unlikely (rectangle == NULL)) |
740 | if (unlikely (rectangle == NULL)) |
Line 673... | Line -... | ||
673 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
674 | - | ||
675 | rectangle->left = box->p1.x; |
741 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | 742 | ||
- | 743 | rectangle->dir = dir; |
|
- | 744 | rectangle->left = MAX (box->p1.x, self->extents.p1.x); |
|
- | 745 | rectangle->right = MIN (box->p2.x, self->extents.p2.x); |
|
- | 746 | if (unlikely (rectangle->right <= rectangle->left)) { |
|
- | 747 | self->tail->count--; |
|
Line 676... | Line 748... | ||
676 | rectangle->right = box->p2.x; |
748 | return CAIRO_STATUS_SUCCESS; |
677 | rectangle->dir = dir; |
749 | } |
678 | 750 | ||
679 | rectangle->top = box->p1.y; |
751 | rectangle->top = MAX (box->p1.y, self->extents.p1.y); |
680 | rectangle->top_y = _cairo_fixed_integer_floor (box->p1.y); |
752 | rectangle->top_y = _cairo_fixed_integer_floor (rectangle->top); |
681 | rectangle->bottom = box->p2.y; |
- | |
682 | rectangle->bottom_y = _cairo_fixed_integer_floor (box->p2.y); |
753 | rectangle->bottom = MIN (box->p2.y, self->extents.p2.y); |
- | 754 | rectangle->bottom_y = _cairo_fixed_integer_floor (rectangle->bottom); |
|
- | 755 | if (likely (rectangle->bottom > rectangle->top)) |
|
Line 683... | Line 756... | ||
683 | assert (rectangle->bottom_y >= rectangle->top_y); |
756 | self->num_rectangles++; |
684 | 757 | else |
|
Line 685... | Line 758... | ||
685 | self->num_rectangles++; |
758 | self->tail->count--; |
Line 702... | Line 775... | ||
702 | void |
775 | void |
703 | _cairo_rectangular_scan_converter_init (cairo_rectangular_scan_converter_t *self, |
776 | _cairo_rectangular_scan_converter_init (cairo_rectangular_scan_converter_t *self, |
704 | const cairo_rectangle_int_t *extents) |
777 | const cairo_rectangle_int_t *extents) |
705 | { |
778 | { |
706 | self->base.destroy = _cairo_rectangular_scan_converter_destroy; |
779 | self->base.destroy = _cairo_rectangular_scan_converter_destroy; |
707 | self->base.add_edge = NULL; |
- | |
708 | self->base.add_polygon = NULL; |
- | |
709 | self->base.generate = _cairo_rectangular_scan_converter_generate; |
780 | self->base.generate = _cairo_rectangular_scan_converter_generate; |
Line 710... | Line -... | ||
710 | - | ||
711 | self->xmin = extents->x; |
- | |
712 | self->xmax = extents->x + extents->width; |
- | |
713 | self->ymin = extents->y; |
781 | |
Line 714... | Line 782... | ||
714 | self->ymax = extents->y + extents->height; |
782 | _cairo_box_from_rectangle (&self->extents, extents); |
715 | 783 | ||
716 | self->chunks.base = self->buf; |
784 | self->chunks.base = self->buf; |
717 | self->chunks.next = NULL; |
785 | self->chunks.next = NULL; |