OLD | NEW |
1 // Copyright 2010 The Chromium Authors. All rights reserved. | 1 // Copyright 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/base/tiling_data.h" | 5 #include "cc/base/tiling_data.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ui/gfx/rect.h" | 9 #include "ui/gfx/rect.h" |
10 #include "ui/gfx/vector2d.h" | 10 #include "ui/gfx/vector2d.h" |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 if (ignore_left_ == consider_left_ && ignore_right_ == consider_right_ && | 503 if (ignore_left_ == consider_left_ && ignore_right_ == consider_right_ && |
504 ignore_top_ == consider_top_ && ignore_bottom_ == consider_bottom_) { | 504 ignore_top_ == consider_top_ && ignore_bottom_ == consider_bottom_) { |
505 done(); | 505 done(); |
506 return; | 506 return; |
507 } | 507 } |
508 | 508 |
509 // Determine around left, such that it is between -1 and num_tiles_x. | 509 // Determine around left, such that it is between -1 and num_tiles_x. |
510 int around_left = 0; | 510 int around_left = 0; |
511 if (center.x() < 0 || center.IsEmpty()) | 511 if (center.x() < 0 || center.IsEmpty()) |
512 around_left = -1; | 512 around_left = -1; |
513 else if (center.x() > tiling_data->tiling_size().width()) | 513 else if (center.x() >= tiling_data->tiling_size().width()) |
514 around_left = tiling_data->num_tiles_x(); | 514 around_left = tiling_data->num_tiles_x(); |
515 else | 515 else |
516 around_left = tiling_data->TileXIndexFromSrcCoord(center.x()); | 516 around_left = tiling_data->TileXIndexFromSrcCoord(center.x()); |
517 | 517 |
518 // Determine around top, such that it is between -1 and num_tiles_y. | 518 // Determine around top, such that it is between -1 and num_tiles_y. |
519 int around_top = 0; | 519 int around_top = 0; |
520 if (center.y() < 0 || center.IsEmpty()) | 520 if (center.y() < 0 || center.IsEmpty()) |
521 around_top = -1; | 521 around_top = -1; |
522 else if (center.y() > tiling_data->tiling_size().height()) | 522 else if (center.y() >= tiling_data->tiling_size().height()) |
523 around_top = tiling_data->num_tiles_y(); | 523 around_top = tiling_data->num_tiles_y(); |
524 else | 524 else |
525 around_top = tiling_data->TileYIndexFromSrcCoord(center.y()); | 525 around_top = tiling_data->TileYIndexFromSrcCoord(center.y()); |
526 | 526 |
527 // Determine around right, such that it is between -1 and num_tiles_x. | 527 // Determine around right, such that it is between -1 and num_tiles_x. |
528 int right_src_coord = center.right() - 1; | 528 int right_src_coord = center.right() - 1; |
529 int around_right = 0; | 529 int around_right = 0; |
530 if (right_src_coord < 0 || center.IsEmpty()) { | 530 if (right_src_coord < 0 || center.IsEmpty()) { |
531 around_right = -1; | 531 around_right = -1; |
532 } else if (right_src_coord > tiling_data->tiling_size().width()) { | 532 } else if (right_src_coord >= tiling_data->tiling_size().width()) { |
533 around_right = tiling_data->num_tiles_x(); | 533 around_right = tiling_data->num_tiles_x(); |
534 } else { | 534 } else { |
535 around_right = tiling_data->TileXIndexFromSrcCoord(right_src_coord); | 535 around_right = tiling_data->TileXIndexFromSrcCoord(right_src_coord); |
536 } | 536 } |
537 | 537 |
538 // Determine around bottom, such that it is between -1 and num_tiles_y. | 538 // Determine around bottom, such that it is between -1 and num_tiles_y. |
539 int bottom_src_coord = center.bottom() - 1; | 539 int bottom_src_coord = center.bottom() - 1; |
540 int around_bottom = 0; | 540 int around_bottom = 0; |
541 if (bottom_src_coord < 0 || center.IsEmpty()) { | 541 if (bottom_src_coord < 0 || center.IsEmpty()) { |
542 around_bottom = -1; | 542 around_bottom = -1; |
543 } else if (bottom_src_coord > tiling_data->tiling_size().height()) { | 543 } else if (bottom_src_coord >= tiling_data->tiling_size().height()) { |
544 around_bottom = tiling_data->num_tiles_y(); | 544 around_bottom = tiling_data->num_tiles_y(); |
545 } else { | 545 } else { |
546 around_bottom = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord); | 546 around_bottom = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord); |
547 } | 547 } |
548 | 548 |
549 vertical_step_count_ = around_bottom - around_top + 1; | 549 vertical_step_count_ = around_bottom - around_top + 1; |
550 horizontal_step_count_ = around_right - around_left + 1; | 550 horizontal_step_count_ = around_right - around_left + 1; |
551 current_step_ = horizontal_step_count_ - 1; | 551 current_step_ = horizontal_step_count_ - 1; |
552 | 552 |
553 index_x_ = around_right; | 553 index_x_ = around_right; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 if (cannot_hit_consider_count >= 4) | 645 if (cannot_hit_consider_count >= 4) |
646 done(); | 646 done(); |
647 return *this; | 647 return *this; |
648 } | 648 } |
649 | 649 |
650 bool TilingData::SpiralDifferenceIterator::needs_direction_switch() const { | 650 bool TilingData::SpiralDifferenceIterator::needs_direction_switch() const { |
651 return current_step_ >= current_step_count(); | 651 return current_step_ >= current_step_count(); |
652 } | 652 } |
653 | 653 |
654 void TilingData::SpiralDifferenceIterator::switch_direction() { | 654 void TilingData::SpiralDifferenceIterator::switch_direction() { |
| 655 // Note that delta_x_ and delta_y_ always remain between -1 and 1. |
655 int new_delta_x_ = delta_y_; | 656 int new_delta_x_ = delta_y_; |
656 delta_y_ = -delta_x_; | 657 delta_y_ = -delta_x_; |
657 delta_x_ = new_delta_x_; | 658 delta_x_ = new_delta_x_; |
658 | 659 |
659 current_step_ = 0; | 660 current_step_ = 0; |
660 direction_ = static_cast<Direction>((direction_ + 1) % 4); | 661 direction_ = static_cast<Direction>((direction_ + 1) % 4); |
661 | 662 |
662 if (direction_ == RIGHT || direction_ == LEFT) { | 663 if (direction_ == RIGHT || direction_ == LEFT) { |
663 ++vertical_step_count_; | 664 ++vertical_step_count_; |
664 ++horizontal_step_count_; | 665 ++horizontal_step_count_; |
665 } | 666 } |
666 } | 667 } |
667 | 668 |
| 669 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator() |
| 670 : BaseIterator(nullptr) { |
| 671 done(); |
| 672 } |
| 673 |
| 674 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator( |
| 675 const TilingData* tiling_data, |
| 676 const gfx::Rect& consider_rect, |
| 677 const gfx::Rect& ignore_rect, |
| 678 const gfx::Rect& center_rect) |
| 679 : BaseIterator(tiling_data), |
| 680 consider_left_(-1), |
| 681 consider_top_(-1), |
| 682 consider_right_(-1), |
| 683 consider_bottom_(-1), |
| 684 around_left_(-1), |
| 685 around_top_(-1), |
| 686 around_right_(-1), |
| 687 around_bottom_(-1), |
| 688 ignore_left_(-1), |
| 689 ignore_top_(-1), |
| 690 ignore_right_(-1), |
| 691 ignore_bottom_(-1), |
| 692 direction_(LEFT), |
| 693 delta_x_(-1), |
| 694 delta_y_(0), |
| 695 current_step_(0), |
| 696 horizontal_step_count_(0), |
| 697 vertical_step_count_(0) { |
| 698 if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) { |
| 699 done(); |
| 700 return; |
| 701 } |
| 702 |
| 703 gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size()); |
| 704 gfx::Rect consider(consider_rect); |
| 705 gfx::Rect ignore(ignore_rect); |
| 706 gfx::Rect center(center_rect); |
| 707 consider.Intersect(tiling_bounds_rect); |
| 708 ignore.Intersect(tiling_bounds_rect); |
| 709 if (consider.IsEmpty()) { |
| 710 done(); |
| 711 return; |
| 712 } |
| 713 |
| 714 consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x()); |
| 715 consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y()); |
| 716 consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1); |
| 717 consider_bottom_ = |
| 718 tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1); |
| 719 |
| 720 if (!ignore.IsEmpty()) { |
| 721 ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x()); |
| 722 ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y()); |
| 723 ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1); |
| 724 ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1); |
| 725 |
| 726 // Clamp ignore indices to consider indices. |
| 727 ignore_left_ = std::max(ignore_left_, consider_left_); |
| 728 ignore_top_ = std::max(ignore_top_, consider_top_); |
| 729 ignore_right_ = std::min(ignore_right_, consider_right_); |
| 730 ignore_bottom_ = std::min(ignore_bottom_, consider_bottom_); |
| 731 } |
| 732 |
| 733 if (ignore_left_ == consider_left_ && ignore_right_ == consider_right_ && |
| 734 ignore_top_ == consider_top_ && ignore_bottom_ == consider_bottom_) { |
| 735 done(); |
| 736 return; |
| 737 } |
| 738 |
| 739 // Determine around left, such that it is between -1 and num_tiles_x. |
| 740 if (center.x() < 0 || center.IsEmpty()) |
| 741 around_left_ = -1; |
| 742 else if (center.x() >= tiling_data->tiling_size().width()) |
| 743 around_left_ = tiling_data->num_tiles_x(); |
| 744 else |
| 745 around_left_ = tiling_data->TileXIndexFromSrcCoord(center.x()); |
| 746 |
| 747 // Determine around top, such that it is between -1 and num_tiles_y. |
| 748 if (center.y() < 0 || center.IsEmpty()) |
| 749 around_top_ = -1; |
| 750 else if (center.y() >= tiling_data->tiling_size().height()) |
| 751 around_top_ = tiling_data->num_tiles_y(); |
| 752 else |
| 753 around_top_ = tiling_data->TileYIndexFromSrcCoord(center.y()); |
| 754 |
| 755 // Determine around right, such that it is between -1 and num_tiles_x. |
| 756 int right_src_coord = center.right() - 1; |
| 757 if (right_src_coord < 0 || center.IsEmpty()) { |
| 758 around_right_ = -1; |
| 759 } else if (right_src_coord >= tiling_data->tiling_size().width()) { |
| 760 around_right_ = tiling_data->num_tiles_x(); |
| 761 } else { |
| 762 around_right_ = tiling_data->TileXIndexFromSrcCoord(right_src_coord); |
| 763 } |
| 764 |
| 765 // Determine around bottom, such that it is between -1 and num_tiles_y. |
| 766 int bottom_src_coord = center.bottom() - 1; |
| 767 if (bottom_src_coord < 0 || center.IsEmpty()) { |
| 768 around_bottom_ = -1; |
| 769 } else if (bottom_src_coord >= tiling_data->tiling_size().height()) { |
| 770 around_bottom_ = tiling_data->num_tiles_y(); |
| 771 } else { |
| 772 around_bottom_ = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord); |
| 773 } |
| 774 |
| 775 // Figure out the maximum distance from the around edge to consider edge. |
| 776 int max_distance = 0; |
| 777 max_distance = std::max(max_distance, around_top_ - consider_top_); |
| 778 max_distance = std::max(max_distance, around_left_ - consider_left_); |
| 779 max_distance = std::max(max_distance, consider_bottom_ - around_bottom_); |
| 780 max_distance = std::max(max_distance, consider_right_ - around_right_); |
| 781 |
| 782 // The step count is the length of the edge (around_right_ - around_left_ + 1) |
| 783 // plus twice the max distance to pad (to the right and to the left). This way |
| 784 // the initial rect is the size proportional to the center, but big enough |
| 785 // to cover the consider rect. |
| 786 // |
| 787 // C = consider rect |
| 788 // A = around rect |
| 789 // . = area of the padded around rect |
| 790 // md = max distance (note in the picture below, there's md written vertically |
| 791 // as well). |
| 792 // I = initial starting position |
| 793 // |
| 794 // |md| |md| |
| 795 // |
| 796 // - .......... |
| 797 // m .......... |
| 798 // d .......... |
| 799 // - CCCCCCC... |
| 800 // CCCCAAC... |
| 801 // CCCCAAC... |
| 802 // - .......... |
| 803 // m .......... |
| 804 // d .......... |
| 805 // - ..........I |
| 806 vertical_step_count_ = around_bottom_ - around_top_ + 1 + 2 * max_distance; |
| 807 horizontal_step_count_ = around_right_ - around_left_ + 1 + 2 * max_distance; |
| 808 |
| 809 // Start with one to the right of the padded around rect. |
| 810 index_x_ = around_right_ + max_distance + 1; |
| 811 index_y_ = around_bottom_ + max_distance; |
| 812 |
| 813 // The current index is outside a valid tile, so advance immediately. |
| 814 ++(*this); |
| 815 } |
| 816 |
| 817 TilingData::ReverseSpiralDifferenceIterator& |
| 818 TilingData::ReverseSpiralDifferenceIterator:: |
| 819 operator++() { |
| 820 while (!in_around_rect()) { |
| 821 if (needs_direction_switch()) |
| 822 switch_direction(); |
| 823 |
| 824 index_x_ += delta_x_; |
| 825 index_y_ += delta_y_; |
| 826 ++current_step_; |
| 827 |
| 828 if (in_around_rect()) { |
| 829 break; |
| 830 } else if (in_consider_rect()) { |
| 831 // If the tile is in the consider rect but not in ignore rect, then it's a |
| 832 // valid tile to visit. |
| 833 if (!in_ignore_rect()) |
| 834 break; |
| 835 |
| 836 // Steps needed to reach the very edge of the ignore rect, while remaining |
| 837 // inside it (so that the continue would take us outside). |
| 838 int steps_to_edge = 0; |
| 839 switch (direction_) { |
| 840 case UP: |
| 841 steps_to_edge = index_y_ - ignore_top_; |
| 842 break; |
| 843 case LEFT: |
| 844 steps_to_edge = index_x_ - ignore_left_; |
| 845 break; |
| 846 case DOWN: |
| 847 steps_to_edge = ignore_bottom_ - index_y_; |
| 848 break; |
| 849 case RIGHT: |
| 850 steps_to_edge = ignore_right_ - index_x_; |
| 851 break; |
| 852 } |
| 853 |
| 854 // We need to switch directions in |max_steps|. |
| 855 int max_steps = current_step_count() - current_step_; |
| 856 |
| 857 int steps_to_take = std::min(steps_to_edge, max_steps); |
| 858 DCHECK_GE(steps_to_take, 0); |
| 859 |
| 860 index_x_ += steps_to_take * delta_x_; |
| 861 index_y_ += steps_to_take * delta_y_; |
| 862 current_step_ += steps_to_take; |
| 863 } else { |
| 864 // We're not in the consider rect. |
| 865 |
| 866 int max_steps = current_step_count() - current_step_; |
| 867 int steps_to_take = max_steps; |
| 868 |
| 869 // We might hit the consider rect before needing to switch directions: |
| 870 // update steps to take. |
| 871 switch (direction_) { |
| 872 case UP: |
| 873 if (valid_column() && consider_bottom_ < index_y_) |
| 874 steps_to_take = index_y_ - consider_bottom_ - 1; |
| 875 break; |
| 876 case LEFT: |
| 877 if (valid_row() && consider_right_ < index_x_) |
| 878 steps_to_take = index_x_ - consider_right_ - 1; |
| 879 break; |
| 880 case DOWN: |
| 881 if (valid_column() && consider_top_ > index_y_) |
| 882 steps_to_take = consider_top_ - index_y_ - 1; |
| 883 break; |
| 884 case RIGHT: |
| 885 if (valid_row() && consider_left_ > index_x_) |
| 886 steps_to_take = consider_left_ - index_x_ - 1; |
| 887 break; |
| 888 } |
| 889 steps_to_take = std::min(steps_to_take, max_steps); |
| 890 DCHECK_GE(steps_to_take, 0); |
| 891 |
| 892 index_x_ += steps_to_take * delta_x_; |
| 893 index_y_ += steps_to_take * delta_y_; |
| 894 current_step_ += steps_to_take; |
| 895 } |
| 896 } |
| 897 |
| 898 // Once we enter the around rect, we're done. |
| 899 if (in_around_rect()) |
| 900 done(); |
| 901 return *this; |
| 902 } |
| 903 |
| 904 bool TilingData::ReverseSpiralDifferenceIterator::needs_direction_switch() |
| 905 const { |
| 906 return current_step_ >= current_step_count(); |
| 907 } |
| 908 |
| 909 void TilingData::ReverseSpiralDifferenceIterator::switch_direction() { |
| 910 // Note that delta_x_ and delta_y_ always remain between -1 and 1. |
| 911 int new_delta_y_ = delta_x_; |
| 912 delta_x_ = -delta_y_; |
| 913 delta_y_ = new_delta_y_; |
| 914 |
| 915 current_step_ = 0; |
| 916 direction_ = static_cast<Direction>((direction_ + 1) % 4); |
| 917 |
| 918 if (direction_ == UP || direction_ == DOWN) { |
| 919 --vertical_step_count_; |
| 920 --horizontal_step_count_; |
| 921 |
| 922 // We should always end up in an around rect at some point. |
| 923 // Since the direction is now vertical, we have to ensure that we will |
| 924 // advance. |
| 925 DCHECK_GE(horizontal_step_count_, 1); |
| 926 DCHECK_GE(vertical_step_count_, 1); |
| 927 } |
| 928 } |
| 929 |
668 } // namespace cc | 930 } // namespace cc |
OLD | NEW |