| 672 | } |
| 673 | |
| 674 | void |
| 675 | Bitmap::render_contour (std::vector<lay::RenderEdge> &edges) |
| 676 | { |
| 677 | // this is the generic case |
| 678 | for (std::vector<lay::RenderEdge>::iterator e = edges.begin (); e != edges.end (); ++e) { |
| 679 | |
| 680 | // This is the line render algorithm |
| 681 | // The basic idea is to decompose the line into stripes |
| 682 | // associated with a integer y value. The stripe extends |
| 683 | // from x1 to x2 then. The algorithm tries to find a |
| 684 | // set of pixels on the y line that covers the range x1 |
| 685 | // to x2 as good as possible and advances to the next y |
| 686 | // value then. |
| 687 | |
| 688 | // TODO: the rendering would be somewhat more efficient if |
| 689 | // we would first clip the line and then render it. This |
| 690 | // way we could remove the tests in the rendering loop. |
| 691 | |
| 692 | if (e->y1 () < double (height ()) - 0.5 && e->y2 () >= -0.5) { |
| 693 | |
| 694 | double y = std::max (floor (e->y1 () + 0.5), 0.0); |
| 695 | double x = e->pos (y - 0.5); |
| 696 | |
| 697 | double dx = e->pos (y + 0.5) - x; |
| 698 | double dx1 = (e->y2 () - e->y1 ()) < 1e-6 ? 0.0 : (e->x2 () - e->x1 ()) / (e->y2 () - e->y1 ()); |
| 699 | |
| 700 | double y2m = e->y2 () - 0.5; |
| 701 | |
| 702 | unsigned int yeint = (unsigned int) std::min (double (height () - 1), std::max (floor (e->y2 () + 0.5), 0.0)); |
| 703 | |
| 704 | unsigned int xint = (unsigned int) (std::max (0.0, std::min (double (width () - 1), x) + 0.5)); |
| 705 | unsigned int yint = (unsigned int) y; |
| 706 | |
| 707 | if (x < (double) width () - 0.5 && x >= 0.0) { |
| 708 | fill (yint, xint, xint + 1); |
| 709 | } |
| 710 | |
| 711 | if (e->x2 () > e->x1 ()) { |
| 712 | |
| 713 | while (yint <= yeint) { |
| 714 | |
| 715 | double xx; |
| 716 | if (double (yint) > y2m) { |
| 717 | xx = e->x2 () + 0.5; |
| 718 | } else { |
| 719 | xx = x + dx; |
| 720 | dx = dx1; |
| 721 | } |
| 722 | |
| 723 | unsigned int xe; |
| 724 | if (xx >= 0.0) { |
| 725 | if (xx >= (double) width ()) { |
| 726 | if (x >= (double) width () - 1) { |
| 727 | break; // done. |
| 728 | } |
| 729 | xe = width () - 1; |
| 730 | } else { |
| 731 | xe = (unsigned int) (xx); |