Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: cc/base/tiling_data.cc

Issue 2352393002: cc: Detach spiral iterator implementation to separate file. (Closed)
Patch Set: review comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/geometry/rect.h" 9 #include "ui/gfx/geometry/rect.h"
10 #include "ui/gfx/geometry/vector2d.h" 10 #include "ui/gfx/geometry/vector2d.h"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const { 124 int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const {
125 if (num_tiles_y_ <= 1) 125 if (num_tiles_y_ <= 1)
126 return 0; 126 return 0;
127 127
128 DCHECK_GT(max_texture_size_.height() - 2 * border_texels_, 0); 128 DCHECK_GT(max_texture_size_.height() - 2 * border_texels_, 0);
129 int inner_tile_size = max_texture_size_.height() - 2 * border_texels_; 129 int inner_tile_size = max_texture_size_.height() - 2 * border_texels_;
130 int y = src_position / inner_tile_size; 130 int y = src_position / inner_tile_size;
131 return std::min(std::max(y, 0), num_tiles_y_ - 1); 131 return std::min(std::max(y, 0), num_tiles_y_ - 1);
132 } 132 }
133 133
134 IndexRect TilingData::TileAroundIndexRect(const gfx::Rect& center_rect) const {
135 int around_left = 0;
136 // Determine around left, such that it is between -1 and num_tiles_x.
137 if (center_rect.x() < 0 || center_rect.IsEmpty())
138 around_left = -1;
139 else if (center_rect.x() >= tiling_size().width())
140 around_left = num_tiles_x();
141 else
142 around_left = TileXIndexFromSrcCoord(center_rect.x());
143
144 // Determine around top, such that it is between -1 and num_tiles_y.
145 int around_top = 0;
146 if (center_rect.y() < 0 || center_rect.IsEmpty())
147 around_top = -1;
148 else if (center_rect.y() >= tiling_size().height())
149 around_top = num_tiles_y();
150 else
151 around_top = TileYIndexFromSrcCoord(center_rect.y());
152
153 // Determine around right, such that it is between -1 and num_tiles_x.
154 int around_right = 0;
155 int right_src_coord = center_rect.right() - 1;
156 if (right_src_coord < 0 || center_rect.IsEmpty()) {
157 around_right = -1;
158 } else if (right_src_coord >= tiling_size().width()) {
159 around_right = num_tiles_x();
160 } else {
161 around_right = TileXIndexFromSrcCoord(right_src_coord);
162 }
163
164 // Determine around bottom, such that it is between -1 and num_tiles_y.
165 int around_bottom = 0;
166 int bottom_src_coord = center_rect.bottom() - 1;
167 if (bottom_src_coord < 0 || center_rect.IsEmpty()) {
168 around_bottom = -1;
169 } else if (bottom_src_coord >= tiling_size().height()) {
170 around_bottom = num_tiles_y();
171 } else {
172 around_bottom = TileYIndexFromSrcCoord(bottom_src_coord);
173 }
174
175 return IndexRect(around_left, around_right, around_top, around_bottom);
176 }
177
134 gfx::Rect TilingData::ExpandRectIgnoringBordersToTileBounds( 178 gfx::Rect TilingData::ExpandRectIgnoringBordersToTileBounds(
135 const gfx::Rect& rect) const { 179 const gfx::Rect& rect) const {
136 if (rect.IsEmpty() || has_empty_bounds()) 180 if (rect.IsEmpty() || has_empty_bounds())
137 return gfx::Rect(); 181 return gfx::Rect();
138 if (rect.x() > tiling_size_.width() || rect.y() > tiling_size_.height()) 182 if (rect.x() > tiling_size_.width() || rect.y() > tiling_size_.height())
139 return gfx::Rect(); 183 return gfx::Rect();
140 int index_x = TileXIndexFromSrcCoord(rect.x()); 184 int index_x = TileXIndexFromSrcCoord(rect.x());
141 int index_y = TileYIndexFromSrcCoord(rect.y()); 185 int index_y = TileYIndexFromSrcCoord(rect.y());
142 int index_right = TileXIndexFromSrcCoord(rect.right() - 1); 186 int index_right = TileXIndexFromSrcCoord(rect.right() - 1);
143 int index_bottom = TileYIndexFromSrcCoord(rect.bottom() - 1); 187 int index_bottom = TileYIndexFromSrcCoord(rect.bottom() - 1);
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 522
479 TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator() { 523 TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator() {
480 done(); 524 done();
481 } 525 }
482 526
483 TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator( 527 TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator(
484 const TilingData* tiling_data, 528 const TilingData* tiling_data,
485 const gfx::Rect& consider_rect, 529 const gfx::Rect& consider_rect,
486 const gfx::Rect& ignore_rect, 530 const gfx::Rect& ignore_rect,
487 const gfx::Rect& center_rect) 531 const gfx::Rect& center_rect)
488 : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect), 532 : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect) {
489 direction_(RIGHT),
490 delta_x_(1),
491 delta_y_(0),
492 current_step_(0),
493 horizontal_step_count_(0),
494 vertical_step_count_(0) {
495 if (!HasConsiderRect()) { 533 if (!HasConsiderRect()) {
496 done(); 534 done();
497 return; 535 return;
498 } 536 }
499 537
500 // Determine around left, such that it is between -1 and num_tiles_x. 538 IndexRect around_index_rect = tiling_data->TileAroundIndexRect(center_rect);
501 int around_left = 0; 539 DCHECK(around_index_rect.is_valid());
502 if (center_rect.x() < 0 || center_rect.IsEmpty())
503 around_left = -1;
504 else if (center_rect.x() >= tiling_data->tiling_size().width())
505 around_left = tiling_data->num_tiles_x();
506 else
507 around_left = tiling_data->TileXIndexFromSrcCoord(center_rect.x());
508 540
509 // Determine around top, such that it is between -1 and num_tiles_y. 541 spiral_iterator_ = SpiralIterator(around_index_rect, consider_index_rect_,
510 int around_top = 0; 542 ignore_index_rect_);
511 if (center_rect.y() < 0 || center_rect.IsEmpty())
512 around_top = -1;
513 else if (center_rect.y() >= tiling_data->tiling_size().height())
514 around_top = tiling_data->num_tiles_y();
515 else
516 around_top = tiling_data->TileYIndexFromSrcCoord(center_rect.y());
517 543
518 // Determine around right, such that it is between -1 and num_tiles_x. 544 if (!spiral_iterator_) {
519 int right_src_coord = center_rect.right() - 1; 545 done();
520 int around_right = 0; 546 return;
521 if (right_src_coord < 0 || center_rect.IsEmpty()) {
522 around_right = -1;
523 } else if (right_src_coord >= tiling_data->tiling_size().width()) {
524 around_right = tiling_data->num_tiles_x();
525 } else {
526 around_right = tiling_data->TileXIndexFromSrcCoord(right_src_coord);
527 } 547 }
528 548
529 // Determine around bottom, such that it is between -1 and num_tiles_y. 549 index_x_ = spiral_iterator_.index_x();
530 int bottom_src_coord = center_rect.bottom() - 1; 550 index_y_ = spiral_iterator_.index_y();
531 int around_bottom = 0;
532 if (bottom_src_coord < 0 || center_rect.IsEmpty()) {
533 around_bottom = -1;
534 } else if (bottom_src_coord >= tiling_data->tiling_size().height()) {
535 around_bottom = tiling_data->num_tiles_y();
536 } else {
537 around_bottom = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord);
538 }
539
540 vertical_step_count_ = around_bottom - around_top + 1;
541 horizontal_step_count_ = around_right - around_left + 1;
542 current_step_ = horizontal_step_count_ - 1;
543
544 index_x_ = around_right;
545 index_y_ = around_bottom;
546
547 // The current index is the bottom right of the around rect, which is also
548 // ignored. So we have to advance.
549 ++(*this);
550 } 551 }
551 552
552 TilingData::SpiralDifferenceIterator& TilingData::SpiralDifferenceIterator:: 553 TilingData::SpiralDifferenceIterator& TilingData::SpiralDifferenceIterator::
553 operator++() { 554 operator++() {
554 int cannot_hit_consider_count = 0; 555 ++spiral_iterator_;
555 while (cannot_hit_consider_count < 4) {
556 if (needs_direction_switch())
557 switch_direction();
558 556
559 index_x_ += delta_x_; 557 if (!spiral_iterator_) {
560 index_y_ += delta_y_; 558 done();
561 ++current_step_; 559 return *this;
562
563 if (consider_index_rect_.Contains(index_x_, index_y_)) {
564 cannot_hit_consider_count = 0;
565
566 if (!ignore_index_rect_.Contains(index_x_, index_y_))
567 break;
568
569 // Steps needed to reach the very edge of the ignore rect, while remaining
570 // inside (so that the continue would take us outside).
571 int steps_to_edge = 0;
572 switch (direction_) {
573 case UP:
574 steps_to_edge = index_y_ - ignore_index_rect_.top();
575 break;
576 case LEFT:
577 steps_to_edge = index_x_ - ignore_index_rect_.left();
578 break;
579 case DOWN:
580 steps_to_edge = ignore_index_rect_.bottom() - index_y_;
581 break;
582 case RIGHT:
583 steps_to_edge = ignore_index_rect_.right() - index_x_;
584 break;
585 }
586
587 // We need to switch directions in |max_steps|.
588 int max_steps = current_step_count() - current_step_;
589
590 int steps_to_take = std::min(steps_to_edge, max_steps);
591 DCHECK_GE(steps_to_take, 0);
592
593 index_x_ += steps_to_take * delta_x_;
594 index_y_ += steps_to_take * delta_y_;
595 current_step_ += steps_to_take;
596 } else {
597 int max_steps = current_step_count() - current_step_;
598 int steps_to_take = max_steps;
599 bool can_hit_consider_rect = false;
600 switch (direction_) {
601 case UP:
602 if (consider_index_rect_.valid_column(index_x_) &&
603 consider_index_rect_.bottom() < index_y_)
604 steps_to_take = index_y_ - consider_index_rect_.bottom() - 1;
605 can_hit_consider_rect |= consider_index_rect_.right() >= index_x_;
606 break;
607 case LEFT:
608 if (consider_index_rect_.valid_row(index_y_) &&
609 consider_index_rect_.right() < index_x_)
610 steps_to_take = index_x_ - consider_index_rect_.right() - 1;
611 can_hit_consider_rect |= consider_index_rect_.top() <= index_y_;
612 break;
613 case DOWN:
614 if (consider_index_rect_.valid_column(index_x_) &&
615 consider_index_rect_.top() > index_y_)
616 steps_to_take = consider_index_rect_.top() - index_y_ - 1;
617 can_hit_consider_rect |= consider_index_rect_.left() <= index_x_;
618 break;
619 case RIGHT:
620 if (consider_index_rect_.valid_row(index_y_) &&
621 consider_index_rect_.left() > index_x_)
622 steps_to_take = consider_index_rect_.left() - index_x_ - 1;
623 can_hit_consider_rect |= consider_index_rect_.bottom() >= index_y_;
624 break;
625 }
626 steps_to_take = std::min(steps_to_take, max_steps);
627 DCHECK_GE(steps_to_take, 0);
628
629 index_x_ += steps_to_take * delta_x_;
630 index_y_ += steps_to_take * delta_y_;
631 current_step_ += steps_to_take;
632
633 if (can_hit_consider_rect)
634 cannot_hit_consider_count = 0;
635 else
636 ++cannot_hit_consider_count;
637 }
638 } 560 }
639 561
640 if (cannot_hit_consider_count >= 4) 562 index_x_ = spiral_iterator_.index_x();
641 done(); 563 index_y_ = spiral_iterator_.index_y();
564
642 return *this; 565 return *this;
643 } 566 }
644 567
645 bool TilingData::SpiralDifferenceIterator::needs_direction_switch() const { 568 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator() {
646 return current_step_ >= current_step_count();
647 }
648
649 void TilingData::SpiralDifferenceIterator::switch_direction() {
650 // Note that delta_x_ and delta_y_ always remain between -1 and 1.
651 int new_delta_x_ = delta_y_;
652 delta_y_ = -delta_x_;
653 delta_x_ = new_delta_x_;
654
655 current_step_ = 0;
656 direction_ = static_cast<Direction>((direction_ + 1) % 4);
657
658 if (direction_ == RIGHT || direction_ == LEFT) {
659 ++vertical_step_count_;
660 ++horizontal_step_count_;
661 }
662 }
663
664 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator()
665 : around_index_rect_(kNonPositiveQuadrantIndexRect) {
666 done(); 569 done();
667 } 570 }
668 571
669 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator( 572 TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator(
670 const TilingData* tiling_data, 573 const TilingData* tiling_data,
671 const gfx::Rect& consider_rect, 574 const gfx::Rect& consider_rect,
672 const gfx::Rect& ignore_rect, 575 const gfx::Rect& ignore_rect,
673 const gfx::Rect& center_rect) 576 const gfx::Rect& center_rect)
674 : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect), 577 : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect) {
675 around_index_rect_(kNonPositiveQuadrantIndexRect),
676 direction_(LEFT),
677 delta_x_(-1),
678 delta_y_(0),
679 current_step_(0),
680 horizontal_step_count_(0),
681 vertical_step_count_(0) {
682 if (!HasConsiderRect()) { 578 if (!HasConsiderRect()) {
683 done(); 579 done();
684 return; 580 return;
685 } 581 }
686 582
687 int around_left = 0; 583 IndexRect around_index_rect = tiling_data->TileAroundIndexRect(center_rect);
688 // Determine around left, such that it is between -1 and num_tiles_x. 584 DCHECK(around_index_rect.is_valid());
689 if (center_rect.x() < 0 || center_rect.IsEmpty())
690 around_left = -1;
691 else if (center_rect.x() >= tiling_data->tiling_size().width())
692 around_left = tiling_data->num_tiles_x();
693 else
694 around_left = tiling_data->TileXIndexFromSrcCoord(center_rect.x());
695 585
696 // Determine around top, such that it is between -1 and num_tiles_y. 586 reverse_spiral_iterator_ = ReverseSpiralIterator(
697 int around_top = 0; 587 around_index_rect, consider_index_rect_, ignore_index_rect_);
698 if (center_rect.y() < 0 || center_rect.IsEmpty())
699 around_top = -1;
700 else if (center_rect.y() >= tiling_data->tiling_size().height())
701 around_top = tiling_data->num_tiles_y();
702 else
703 around_top = tiling_data->TileYIndexFromSrcCoord(center_rect.y());
704 588
705 // Determine around right, such that it is between -1 and num_tiles_x. 589 if (!reverse_spiral_iterator_) {
706 int around_right = 0; 590 done();
707 int right_src_coord = center_rect.right() - 1; 591 return;
708 if (right_src_coord < 0 || center_rect.IsEmpty()) {
709 around_right = -1;
710 } else if (right_src_coord >= tiling_data->tiling_size().width()) {
711 around_right = tiling_data->num_tiles_x();
712 } else {
713 around_right = tiling_data->TileXIndexFromSrcCoord(right_src_coord);
714 } 592 }
715 593
716 // Determine around bottom, such that it is between -1 and num_tiles_y. 594 index_x_ = reverse_spiral_iterator_.index_x();
717 int around_bottom = 0; 595 index_y_ = reverse_spiral_iterator_.index_y();
718 int bottom_src_coord = center_rect.bottom() - 1;
719 if (bottom_src_coord < 0 || center_rect.IsEmpty()) {
720 around_bottom = -1;
721 } else if (bottom_src_coord >= tiling_data->tiling_size().height()) {
722 around_bottom = tiling_data->num_tiles_y();
723 } else {
724 around_bottom = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord);
725 }
726
727 around_index_rect_ =
728 IndexRect(around_left, around_right, around_top, around_bottom);
729 DCHECK(around_index_rect_.is_valid());
730
731 // Figure out the maximum distance from the around edge to consider edge.
732 int max_distance = 0;
733 max_distance = std::max(
734 max_distance, around_index_rect_.top() - consider_index_rect_.top());
735 max_distance = std::max(
736 max_distance, around_index_rect_.left() - consider_index_rect_.left());
737 max_distance = std::max(max_distance, consider_index_rect_.bottom() -
738 around_index_rect_.bottom());
739 max_distance = std::max(
740 max_distance, consider_index_rect_.right() - around_index_rect_.right());
741
742 // The step count is the length of the edge
743 // (around_index_rect_.num_indices_x()) plus twice the max distance to pad
744 // (to the right and to the left). This way the initial rect is the size
745 // proportional to the center, but big enough to cover the consider rect.
746 //
747 // C = consider rect
748 // A = around rect
749 // . = area of the padded around rect
750 // md = max distance (note in the picture below, there's md written vertically
751 // as well).
752 // I = initial starting position
753 //
754 // |md| |md|
755 //
756 // - ..........
757 // m ..........
758 // d ..........
759 // - CCCCCCC...
760 // CCCCAAC...
761 // CCCCAAC...
762 // - ..........
763 // m ..........
764 // d ..........
765 // - ..........I
766 vertical_step_count_ = around_index_rect_.num_indices_y() + 2 * max_distance;
767 horizontal_step_count_ =
768 around_index_rect_.num_indices_x() + 2 * max_distance;
769
770 // Start with one to the right of the padded around rect.
771 index_x_ = around_index_rect_.right() + max_distance + 1;
772 index_y_ = around_index_rect_.bottom() + max_distance;
773
774 // The current index is outside a valid tile, so advance immediately.
775 ++(*this);
776 } 596 }
777 597
778 TilingData::ReverseSpiralDifferenceIterator& 598 TilingData::ReverseSpiralDifferenceIterator&
779 TilingData::ReverseSpiralDifferenceIterator:: 599 TilingData::ReverseSpiralDifferenceIterator::
780 operator++() { 600 operator++() {
781 while (!around_index_rect_.Contains(index_x_, index_y_)) { 601 ++reverse_spiral_iterator_;
782 if (needs_direction_switch())
783 switch_direction();
784 602
785 index_x_ += delta_x_; 603 if (!reverse_spiral_iterator_) {
786 index_y_ += delta_y_; 604 done();
787 ++current_step_; 605 return *this;
788
789 if (around_index_rect_.Contains(index_x_, index_y_)) {
790 break;
791 } else if (consider_index_rect_.Contains(index_x_, index_y_)) {
792 // If the tile is in the consider rect but not in ignore rect, then it's a
793 // valid tile to visit.
794 if (!ignore_index_rect_.Contains(index_x_, index_y_))
795 break;
796
797 // Steps needed to reach the very edge of the ignore rect, while remaining
798 // inside it (so that the continue would take us outside).
799 int steps_to_edge = 0;
800 switch (direction_) {
801 case UP:
802 steps_to_edge = index_y_ - ignore_index_rect_.top();
803 break;
804 case LEFT:
805 steps_to_edge = index_x_ - ignore_index_rect_.left();
806 break;
807 case DOWN:
808 steps_to_edge = ignore_index_rect_.bottom() - index_y_;
809 break;
810 case RIGHT:
811 steps_to_edge = ignore_index_rect_.right() - index_x_;
812 break;
813 }
814
815 // We need to switch directions in |max_steps|.
816 int max_steps = current_step_count() - current_step_;
817
818 int steps_to_take = std::min(steps_to_edge, max_steps);
819 DCHECK_GE(steps_to_take, 0);
820
821 index_x_ += steps_to_take * delta_x_;
822 index_y_ += steps_to_take * delta_y_;
823 current_step_ += steps_to_take;
824 } else {
825 // We're not in the consider rect.
826
827 int max_steps = current_step_count() - current_step_;
828 int steps_to_take = max_steps;
829
830 // We might hit the consider rect before needing to switch directions:
831 // update steps to take.
832 switch (direction_) {
833 case UP:
834 if (consider_index_rect_.valid_column(index_x_) &&
835 consider_index_rect_.bottom() < index_y_)
836 steps_to_take = index_y_ - consider_index_rect_.bottom() - 1;
837 break;
838 case LEFT:
839 if (consider_index_rect_.valid_row(index_y_) &&
840 consider_index_rect_.right() < index_x_)
841 steps_to_take = index_x_ - consider_index_rect_.right() - 1;
842 break;
843 case DOWN:
844 if (consider_index_rect_.valid_column(index_x_) &&
845 consider_index_rect_.top() > index_y_)
846 steps_to_take = consider_index_rect_.top() - index_y_ - 1;
847 break;
848 case RIGHT:
849 if (consider_index_rect_.valid_row(index_y_) &&
850 consider_index_rect_.left() > index_x_)
851 steps_to_take = consider_index_rect_.left() - index_x_ - 1;
852 break;
853 }
854 steps_to_take = std::min(steps_to_take, 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 }
861 } 606 }
862 607
863 // Once we enter the around rect, we're done. 608 index_x_ = reverse_spiral_iterator_.index_x();
864 if (around_index_rect_.Contains(index_x_, index_y_)) 609 index_y_ = reverse_spiral_iterator_.index_y();
865 done(); 610
866 return *this; 611 return *this;
867 } 612 }
868 613
869 bool TilingData::ReverseSpiralDifferenceIterator::needs_direction_switch()
870 const {
871 return current_step_ >= current_step_count();
872 }
873
874 void TilingData::ReverseSpiralDifferenceIterator::switch_direction() {
875 // Note that delta_x_ and delta_y_ always remain between -1 and 1.
876 int new_delta_y_ = delta_x_;
877 delta_x_ = -delta_y_;
878 delta_y_ = new_delta_y_;
879
880 current_step_ = 0;
881 direction_ = static_cast<Direction>((direction_ + 1) % 4);
882
883 if (direction_ == UP || direction_ == DOWN) {
884 --vertical_step_count_;
885 --horizontal_step_count_;
886
887 // We should always end up in an around rect at some point.
888 // Since the direction is now vertical, we have to ensure that we will
889 // advance.
890 DCHECK_GE(horizontal_step_count_, 1);
891 DCHECK_GE(vertical_step_count_, 1);
892 }
893 }
894
895 } // namespace cc 614 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698