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 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 | 658 |
659 current_step_ = 0; | 659 current_step_ = 0; |
660 direction_ = static_cast<Direction>((direction_ + 1) % 4); | 660 direction_ = static_cast<Direction>((direction_ + 1) % 4); |
661 | 661 |
662 if (direction_ == RIGHT || direction_ == LEFT) { | 662 if (direction_ == RIGHT || direction_ == LEFT) { |
663 ++vertical_step_count_; | 663 ++vertical_step_count_; |
664 ++horizontal_step_count_; | 664 ++horizontal_step_count_; |
665 } | 665 } |
666 } | 666 } |
667 | 667 |
668 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator() | |
669 : BaseIterator(nullptr) { | |
670 done(); | |
671 } | |
672 | |
673 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator( | |
674 const TilingData* tiling_data, | |
675 const gfx::Rect& consider_rect, | |
676 const gfx::Rect& ignore_rect, | |
677 const gfx::Rect& center_rect) | |
678 : BaseIterator(tiling_data), | |
679 consider_left_(-1), | |
680 consider_top_(-1), | |
681 consider_right_(-1), | |
682 consider_bottom_(-1), | |
683 around_left_(-1), | |
684 around_top_(-1), | |
685 around_right_(-1), | |
686 around_bottom_(-1), | |
687 ignore_left_(-1), | |
688 ignore_top_(-1), | |
689 ignore_right_(-1), | |
690 ignore_bottom_(-1), | |
691 direction_(LEFT), | |
692 delta_x_(-1), | |
693 delta_y_(0), | |
694 current_step_(0), | |
695 horizontal_step_count_(0), | |
696 vertical_step_count_(0) { | |
697 if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) { | |
698 done(); | |
699 return; | |
700 } | |
701 | |
702 gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size()); | |
703 gfx::Rect consider(consider_rect); | |
704 gfx::Rect ignore(ignore_rect); | |
705 gfx::Rect center(center_rect); | |
706 consider.Intersect(tiling_bounds_rect); | |
707 ignore.Intersect(tiling_bounds_rect); | |
708 if (consider.IsEmpty()) { | |
709 done(); | |
710 return; | |
711 } | |
712 | |
713 consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x()); | |
714 consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y()); | |
715 consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1); | |
716 consider_bottom_ = | |
717 tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1); | |
718 | |
719 if (!ignore.IsEmpty()) { | |
720 ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x()); | |
721 ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y()); | |
722 ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1); | |
723 ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1); | |
724 | |
725 // Clamp ignore indices to consider indices. | |
726 ignore_left_ = std::max(ignore_left_, consider_left_); | |
727 ignore_top_ = std::max(ignore_top_, consider_top_); | |
728 ignore_right_ = std::min(ignore_right_, consider_right_); | |
729 ignore_bottom_ = std::min(ignore_bottom_, consider_bottom_); | |
730 } | |
731 | |
732 if (ignore_left_ == consider_left_ && ignore_right_ == consider_right_ && | |
733 ignore_top_ == consider_top_ && ignore_bottom_ == consider_bottom_) { | |
734 done(); | |
735 return; | |
736 } | |
737 | |
738 // Determine around left, such that it is between -1 and num_tiles_x. | |
739 if (center.x() < 0 || center.IsEmpty()) | |
740 around_left_ = -1; | |
741 else if (center.x() > tiling_data->tiling_size().width()) | |
danakj
2014/10/11 01:35:24
u mean >= width()?
vmpstr
2014/10/11 02:17:44
I think I do?
| |
742 around_left_ = tiling_data->num_tiles_x(); | |
743 else | |
744 around_left_ = tiling_data->TileXIndexFromSrcCoord(center.x()); | |
745 | |
746 // Determine around top, such that it is between -1 and num_tiles_y. | |
747 if (center.y() < 0 || center.IsEmpty()) | |
748 around_top_ = -1; | |
749 else if (center.y() > tiling_data->tiling_size().height()) | |
danakj
2014/10/11 01:35:24
you mean >= height()?
vmpstr
2014/10/11 02:17:44
Done.
| |
750 around_top_ = tiling_data->num_tiles_y(); | |
751 else | |
752 around_top_ = tiling_data->TileYIndexFromSrcCoord(center.y()); | |
753 | |
754 // Determine around right, such that it is between -1 and num_tiles_x. | |
755 int right_src_coord = center.right() - 1; | |
756 if (right_src_coord < 0 || center.IsEmpty()) { | |
757 around_right_ = -1; | |
758 } else if (right_src_coord > tiling_data->tiling_size().width()) { | |
danakj
2014/10/11 01:35:24
you mean >= width()?
vmpstr
2014/10/11 02:17:44
Done.
| |
759 around_right_ = tiling_data->num_tiles_x(); | |
760 } else { | |
761 around_right_ = tiling_data->TileXIndexFromSrcCoord(right_src_coord); | |
762 } | |
763 | |
764 // Determine around bottom, such that it is between -1 and num_tiles_y. | |
765 int bottom_src_coord = center.bottom() - 1; | |
766 if (bottom_src_coord < 0 || center.IsEmpty()) { | |
767 around_bottom_ = -1; | |
768 } else if (bottom_src_coord > tiling_data->tiling_size().height()) { | |
danakj
2014/10/11 01:35:24
and >= height()?
vmpstr
2014/10/11 02:17:44
Done.
| |
769 around_bottom_ = tiling_data->num_tiles_y(); | |
770 } else { | |
771 around_bottom_ = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord); | |
772 } | |
773 | |
774 // Figure out the maximum distance from the around edge to consider edge. | |
775 int max_distance = 0; | |
danakj
2014/10/11 01:35:24
what if max_distance comes out negative?
vmpstr
2014/10/11 02:17:44
That can only be if |consider| is contained in |ar
| |
776 max_distance = std::max(max_distance, around_top_ - consider_top_); | |
777 max_distance = std::max(max_distance, around_left_ - consider_left_); | |
778 max_distance = std::max(max_distance, consider_bottom_ - around_bottom_); | |
779 max_distance = std::max(max_distance, consider_right_ - around_right_); | |
780 | |
781 // The step count is the length of the edge (around_right_ - around_left_ + 1) | |
782 // plus twice the max distance to pad (to the right and to the left). This way | |
783 // the initial rect is the size proportional to the center, but big enough | |
784 // to cover the consider rect. | |
785 // | |
786 // C = consider rect | |
787 // A = around rect | |
788 // . = area of the padded around rect | |
789 // md = max distance | |
790 // I = initial starting position | |
791 // | |
792 // |md| |md| | |
793 // -.......... | |
794 // m.......... | |
795 // d.......... | |
796 // -CCCCCCC... | |
797 // CCCCAAC... | |
798 // CCCCAAC... | |
799 // -.......... | |
800 // m.......... | |
801 // d.......... | |
802 // -..........I | |
803 vertical_step_count_ = around_bottom_ - around_top_ + 1 + 2 * max_distance; | |
804 horizontal_step_count_ = around_right_ - around_left_ + 1 + 2 * max_distance; | |
805 | |
806 // Start with one to the right of the padded around rect. | |
807 index_x_ = around_right_ + max_distance + 1; | |
808 index_y_ = around_bottom_ + max_distance; | |
809 | |
810 // The current index is outside a valid tile, so advance immediately. | |
811 ++(*this); | |
812 } | |
813 | |
814 TilingData::ReverseSpiralDifferenceIterator& | |
815 TilingData::ReverseSpiralDifferenceIterator:: | |
816 operator++() { | |
817 while (!in_around_rect()) { | |
danakj
2014/10/11 01:35:24
you could avoid nesting by recursing instead. it'd
vmpstr
2014/10/11 02:17:44
Ehh.. I'm kind of weary of recursion in this funct
| |
818 if (needs_direction_switch()) | |
819 switch_direction(); | |
820 | |
821 index_x_ += delta_x_; | |
822 index_y_ += delta_y_; | |
823 ++current_step_; | |
824 | |
825 if (in_around_rect()) { | |
826 break; | |
827 } else if (in_consider_rect()) { | |
828 // If the tile is in the consider rect but not in ignore rect, then it's a | |
829 // valid tile to visit. | |
830 if (!in_ignore_rect()) | |
831 break; | |
832 | |
833 // Steps needed to reach the very edge of the ignore rect, while remaining | |
834 // inside it (so that the continue would take us outside). | |
835 int steps_to_edge = 0; | |
836 switch (direction_) { | |
837 case UP: | |
838 steps_to_edge = index_y_ - ignore_top_; | |
839 break; | |
840 case LEFT: | |
841 steps_to_edge = index_x_ - ignore_left_; | |
842 break; | |
843 case DOWN: | |
844 steps_to_edge = ignore_bottom_ - index_y_; | |
845 break; | |
846 case RIGHT: | |
847 steps_to_edge = ignore_right_ - index_x_; | |
848 break; | |
849 } | |
850 | |
851 // We need to switch directions in |max_steps|. | |
852 int max_steps = current_step_count() - current_step_; | |
853 | |
854 int steps_to_take = std::min(steps_to_edge, max_steps); | |
855 DCHECK_GE(steps_to_take, 0); | |
856 | |
857 index_x_ += steps_to_take * delta_x_; | |
858 index_y_ += steps_to_take * delta_y_; | |
859 current_step_ += steps_to_take; | |
860 } else { | |
861 // We're not in the consider rect. | |
862 | |
863 int max_steps = current_step_count() - current_step_; | |
864 int steps_to_take = max_steps; | |
865 | |
866 // We might hit the consider rect before needing to switch directions: | |
867 // update steps to take. | |
868 switch (direction_) { | |
869 case UP: | |
870 if (valid_column() && consider_bottom_ < index_y_) | |
871 steps_to_take = index_y_ - consider_bottom_ - 1; | |
872 break; | |
873 case LEFT: | |
874 if (valid_row() && consider_right_ < index_x_) | |
875 steps_to_take = index_x_ - consider_right_ - 1; | |
876 break; | |
877 case DOWN: | |
878 if (valid_column() && consider_top_ > index_y_) | |
879 steps_to_take = consider_top_ - index_y_ - 1; | |
880 break; | |
881 case RIGHT: | |
882 if (valid_row() && consider_left_ > index_x_) | |
883 steps_to_take = consider_left_ - index_x_ - 1; | |
884 break; | |
885 } | |
886 steps_to_take = std::min(steps_to_take, max_steps); | |
887 DCHECK_GE(steps_to_take, 0); | |
888 | |
889 index_x_ += steps_to_take * delta_x_; | |
890 index_y_ += steps_to_take * delta_y_; | |
891 current_step_ += steps_to_take; | |
892 } | |
893 } | |
894 | |
895 // Once we enter the around rect, we're done. | |
896 if (in_around_rect()) | |
897 done(); | |
898 return *this; | |
899 } | |
900 | |
901 bool TilingData::ReverseSpiralDifferenceIterator::needs_direction_switch() | |
902 const { | |
903 return current_step_ >= current_step_count(); | |
904 } | |
905 | |
906 void TilingData::ReverseSpiralDifferenceIterator::switch_direction() { | |
907 int new_delta_y_ = delta_x_; | |
908 delta_x_ = -delta_y_; | |
909 delta_y_ = new_delta_y_; | |
910 | |
911 current_step_ = 0; | |
912 direction_ = static_cast<Direction>((direction_ + 1) % 4); | |
913 | |
914 if (direction_ == UP || direction_ == DOWN) { | |
915 --vertical_step_count_; | |
916 --horizontal_step_count_; | |
917 | |
918 // We should always end up in an around rect at some point. | |
919 // Since the direction is now vertical, we have to ensure that we will | |
920 // advance. | |
921 DCHECK_GE(horizontal_step_count_, 1); | |
922 DCHECK_GE(vertical_step_count_, 1); | |
923 } | |
924 } | |
925 | |
668 } // namespace cc | 926 } // namespace cc |
OLD | NEW |