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

Side by Side Diff: cc/base/reverse_spiral_iterator.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
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/base/reverse_spiral_iterator.h"
6
7 #include <algorithm>
8
9 namespace cc {
10
11 ReverseSpiralIterator::ReverseSpiralIterator()
12 : around_index_rect_(-1, -1, -1, -1),
13 consider_index_rect_(-1, -1, -1, -1),
14 ignore_index_rect_(-1, -1, -1, -1),
15 index_x_(-1),
16 index_y_(-1) {}
17
18 ReverseSpiralIterator::ReverseSpiralIterator(
19 const IndexRect& around_index_rect,
20 const IndexRect& consider_index_rect,
21 const IndexRect& ignore_index_rect)
22 : around_index_rect_(around_index_rect),
23 consider_index_rect_(consider_index_rect),
24 ignore_index_rect_(ignore_index_rect),
25 index_x_(-1),
26 index_y_(-1),
27 direction_(LEFT),
28 delta_x_(-1),
29 delta_y_(0),
30 current_step_(0),
31 horizontal_step_count_(0),
32 vertical_step_count_(0) {
33 // Figure out the maximum distance from the around edge to consider edge.
34 int max_distance = 0;
35 max_distance = std::max(
36 max_distance, around_index_rect_.top() - consider_index_rect_.top());
37 max_distance = std::max(
38 max_distance, around_index_rect_.left() - consider_index_rect_.left());
39 max_distance = std::max(max_distance, consider_index_rect_.bottom() -
40 around_index_rect_.bottom());
41 max_distance = std::max(
42 max_distance, consider_index_rect_.right() - around_index_rect_.right());
43
44 // The step count is the length of the edge
45 // (around_index_rect_.num_indices_x()) plus twice the max distance to pad
46 // (to the right and to the left). This way the initial rect is the size
47 // proportional to the center, but big enough to cover the consider rect.
48 //
49 // C = consider rect
50 // A = around rect
51 // . = area of the padded around rect
52 // md = max distance (note in the picture below, there's md written vertically
53 // as well).
54 // I = initial starting position
55 //
56 // |md| |md|
57 //
58 // - ..........
59 // m ..........
60 // d ..........
61 // - CCCCCCC...
62 // CCCCAAC...
63 // CCCCAAC...
64 // - ..........
65 // m ..........
66 // d ..........
67 // - ..........I
68 vertical_step_count_ = around_index_rect_.num_indices_y() + 2 * max_distance;
69 horizontal_step_count_ =
70 around_index_rect_.num_indices_x() + 2 * max_distance;
71
72 // Start with one to the right of the padded around rect.
73 index_x_ = around_index_rect_.right() + max_distance + 1;
74 index_y_ = around_index_rect_.bottom() + max_distance;
75
76 // The current index is outside a valid tile, so advance immediately.
77 ++(*this);
78 }
79
80 ReverseSpiralIterator::operator bool() const {
81 return index_x_ != -1 && index_y_ != -1;
82 }
83
84 ReverseSpiralIterator& ReverseSpiralIterator::operator++() {
85 while (!around_index_rect_.Contains(index_x_, index_y_)) {
86 if (needs_direction_switch())
87 switch_direction();
88
89 index_x_ += delta_x_;
90 index_y_ += delta_y_;
91 ++current_step_;
92
93 if (around_index_rect_.Contains(index_x_, index_y_)) {
94 break;
95 } else if (consider_index_rect_.Contains(index_x_, index_y_)) {
96 // If the tile is in the consider rect but not in ignore rect, then it's a
97 // valid tile to visit.
98 if (!ignore_index_rect_.Contains(index_x_, index_y_))
99 break;
100
101 // Steps needed to reach the very edge of the ignore rect, while remaining
102 // inside it (so that the continue would take us outside).
103 int steps_to_edge = 0;
104 switch (direction_) {
105 case UP:
106 steps_to_edge = index_y_ - ignore_index_rect_.top();
107 break;
108 case LEFT:
109 steps_to_edge = index_x_ - ignore_index_rect_.left();
110 break;
111 case DOWN:
112 steps_to_edge = ignore_index_rect_.bottom() - index_y_;
113 break;
114 case RIGHT:
115 steps_to_edge = ignore_index_rect_.right() - index_x_;
116 break;
117 }
118
119 // We need to switch directions in |max_steps|.
120 int max_steps = current_step_count() - current_step_;
121
122 int steps_to_take = std::min(steps_to_edge, max_steps);
123 DCHECK_GE(steps_to_take, 0);
124
125 index_x_ += steps_to_take * delta_x_;
126 index_y_ += steps_to_take * delta_y_;
127 current_step_ += steps_to_take;
128 } else {
129 // We're not in the consider rect.
130
131 int max_steps = current_step_count() - current_step_;
132 int steps_to_take = max_steps;
133
134 // We might hit the consider rect before needing to switch directions:
135 // update steps to take.
136 switch (direction_) {
137 case UP:
138 if (consider_index_rect_.valid_column(index_x_) &&
139 consider_index_rect_.bottom() < index_y_)
140 steps_to_take = index_y_ - consider_index_rect_.bottom() - 1;
141 break;
142 case LEFT:
143 if (consider_index_rect_.valid_row(index_y_) &&
144 consider_index_rect_.right() < index_x_)
145 steps_to_take = index_x_ - consider_index_rect_.right() - 1;
146 break;
147 case DOWN:
148 if (consider_index_rect_.valid_column(index_x_) &&
149 consider_index_rect_.top() > index_y_)
150 steps_to_take = consider_index_rect_.top() - index_y_ - 1;
151 break;
152 case RIGHT:
153 if (consider_index_rect_.valid_row(index_y_) &&
154 consider_index_rect_.left() > index_x_)
155 steps_to_take = consider_index_rect_.left() - index_x_ - 1;
156 break;
157 }
158 steps_to_take = std::min(steps_to_take, max_steps);
159 DCHECK_GE(steps_to_take, 0);
160
161 index_x_ += steps_to_take * delta_x_;
162 index_y_ += steps_to_take * delta_y_;
163 current_step_ += steps_to_take;
164 }
165 }
166
167 // Once we enter the around rect, we're done.
168 if (around_index_rect_.Contains(index_x_, index_y_)) {
169 index_x_ = -1;
170 index_y_ = -1;
171 }
172
173 return *this;
174 }
175
176 bool ReverseSpiralIterator::needs_direction_switch() const {
177 return current_step_ >= current_step_count();
178 }
179
180 void ReverseSpiralIterator::switch_direction() {
181 // Note that delta_x_ and delta_y_ always remain between -1 and 1.
182 int new_delta_y = delta_x_;
183 delta_x_ = -delta_y_;
184 delta_y_ = new_delta_y;
185
186 current_step_ = 0;
187 direction_ = static_cast<Direction>((direction_ + 1) % 4);
188
189 if (direction_ == UP || direction_ == DOWN) {
190 --vertical_step_count_;
191 --horizontal_step_count_;
192
193 // We should always end up in an around rect at some point.
194 // Since the direction is now vertical, we have to ensure that we will
195 // advance.
196 DCHECK_GE(horizontal_step_count_, 1);
197 DCHECK_GE(vertical_step_count_, 1);
198 }
199 }
200
201 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698