OLD | NEW |
---|---|
(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/pyramid_sequence.h" | |
6 | |
7 #include <algorithm> | |
8 #include <string> | |
9 | |
10 namespace cc { | |
11 | |
12 namespace { | |
13 | |
14 int ClampNumberInForwardInterval(int number, | |
15 int interval_start, | |
16 int interval_end) { | |
17 DCHECK_LE(interval_start, interval_end); | |
18 if (number < interval_start) | |
19 return interval_start; | |
20 if (number > interval_end) | |
21 return interval_end; | |
22 return number; | |
23 } | |
24 | |
25 int ClampNumberInBackwardInterval(int number, | |
26 int interval_start, | |
27 int interval_end) { | |
28 DCHECK_GE(interval_start, interval_end); | |
29 if (number > interval_start) | |
30 return interval_start; | |
31 if (number < interval_end) | |
32 return interval_end; | |
33 return number; | |
34 } | |
35 | |
36 int LevelsToSkipAlongDirection(int levels) { | |
37 return levels > 0 ? levels : 0; | |
38 } | |
39 | |
40 int LevelsToSkipPerpendicularToDirection(int levels) { | |
41 return levels >= 0 ? levels + 1 : 0; | |
42 } | |
43 | |
44 enum class TilingCoverageDirection : uint8_t { | |
45 RIGHT = 0, | |
46 TOP_RIGHT, | |
47 TOP, | |
48 TOP_LEFT, | |
49 LEFT, | |
50 BOTTOM_LEFT, | |
51 BOTTOM, | |
52 BOTTOM_RIGHT | |
53 }; | |
54 | |
55 // The pyramid sequence covers following 8 directions while iterating. | |
56 // | |
57 // TL T TR | |
58 // L * R ---> | |
59 // BL B BR | |
60 // | |
61 // The pyramid sequence can yeild better iteration order, if the positions of | |
62 // its inlined level distance sequences are properly considered. Suppose primary | |
63 // direction for coverage is right, then it can have inclination either to top | |
64 // right or bottom right. This inclination is input by secondary direction. | |
65 // The positions for right and inclined to bottom right (which is now considered | |
66 // as default) is R, BR, TR, B, T, BL, TL, L. | |
67 // This function returns the positions for different directions. | |
prashant.n
2016/07/20 03:10:49
This function will play important role in giving b
| |
68 TilingCoverageDirection* GetCoverageDirectionSequenceForDirections( | |
69 TilingCoverageDirection primary_direction, | |
70 TilingCoverageDirection secondary_direction) { | |
71 switch (primary_direction) { | |
72 case TilingCoverageDirection::RIGHT: | |
73 switch (secondary_direction) { | |
74 case TilingCoverageDirection::TOP_RIGHT: | |
75 static TilingCoverageDirection right_top_right[] = { | |
76 TilingCoverageDirection::RIGHT, | |
77 TilingCoverageDirection::TOP_RIGHT, | |
78 TilingCoverageDirection::BOTTOM_RIGHT, | |
79 TilingCoverageDirection::TOP, | |
80 TilingCoverageDirection::BOTTOM, | |
81 TilingCoverageDirection::TOP_LEFT, | |
82 TilingCoverageDirection::BOTTOM_LEFT, | |
83 TilingCoverageDirection::LEFT}; | |
84 return right_top_right; | |
85 case TilingCoverageDirection::BOTTOM_RIGHT: | |
86 static TilingCoverageDirection right_bottom_right[] = { | |
87 TilingCoverageDirection::RIGHT, | |
88 TilingCoverageDirection::BOTTOM_RIGHT, | |
89 TilingCoverageDirection::TOP_RIGHT, | |
90 TilingCoverageDirection::BOTTOM, | |
91 TilingCoverageDirection::TOP, | |
92 TilingCoverageDirection::BOTTOM_LEFT, | |
93 TilingCoverageDirection::TOP_LEFT, | |
94 TilingCoverageDirection::LEFT}; | |
95 return right_bottom_right; | |
96 default: | |
97 NOTREACHED(); | |
98 } | |
99 break; | |
100 | |
101 case TilingCoverageDirection::TOP_RIGHT: | |
102 switch (secondary_direction) { | |
103 case TilingCoverageDirection::TOP: | |
104 static TilingCoverageDirection top_right_top[] = { | |
105 TilingCoverageDirection::TOP_RIGHT, | |
106 TilingCoverageDirection::TOP, | |
107 TilingCoverageDirection::RIGHT, | |
108 TilingCoverageDirection::TOP_LEFT, | |
109 TilingCoverageDirection::BOTTOM_RIGHT, | |
110 TilingCoverageDirection::LEFT, | |
111 TilingCoverageDirection::BOTTOM, | |
112 TilingCoverageDirection::BOTTOM_LEFT}; | |
113 return top_right_top; | |
114 case TilingCoverageDirection::RIGHT: | |
115 static TilingCoverageDirection top_right_right[] = { | |
116 TilingCoverageDirection::TOP_RIGHT, | |
117 TilingCoverageDirection::RIGHT, | |
118 TilingCoverageDirection::TOP, | |
119 TilingCoverageDirection::BOTTOM_RIGHT, | |
120 TilingCoverageDirection::TOP_LEFT, | |
121 TilingCoverageDirection::BOTTOM, | |
122 TilingCoverageDirection::LEFT, | |
123 TilingCoverageDirection::BOTTOM_LEFT}; | |
124 return top_right_right; | |
125 default: | |
126 NOTREACHED(); | |
127 } | |
128 break; | |
129 | |
130 case TilingCoverageDirection::TOP: | |
131 switch (secondary_direction) { | |
132 case TilingCoverageDirection::TOP_RIGHT: | |
133 static TilingCoverageDirection top_top_right[] = { | |
134 TilingCoverageDirection::TOP, | |
135 TilingCoverageDirection::TOP_RIGHT, | |
136 TilingCoverageDirection::TOP_LEFT, | |
137 TilingCoverageDirection::RIGHT, | |
138 TilingCoverageDirection::LEFT, | |
139 TilingCoverageDirection::BOTTOM_RIGHT, | |
140 TilingCoverageDirection::BOTTOM_LEFT, | |
141 TilingCoverageDirection::BOTTOM}; | |
142 return top_top_right; | |
143 case TilingCoverageDirection::TOP_LEFT: | |
144 static TilingCoverageDirection top_top_left[] = { | |
145 TilingCoverageDirection::TOP, | |
146 TilingCoverageDirection::TOP_LEFT, | |
147 TilingCoverageDirection::TOP_RIGHT, | |
148 TilingCoverageDirection::LEFT, | |
149 TilingCoverageDirection::RIGHT, | |
150 TilingCoverageDirection::BOTTOM_LEFT, | |
151 TilingCoverageDirection::BOTTOM_RIGHT, | |
152 TilingCoverageDirection::BOTTOM}; | |
153 return top_top_left; | |
154 default: | |
155 NOTREACHED(); | |
156 } | |
157 break; | |
158 | |
159 case TilingCoverageDirection::TOP_LEFT: | |
160 switch (secondary_direction) { | |
161 case TilingCoverageDirection::TOP: | |
162 static TilingCoverageDirection top_left_top[] = { | |
163 TilingCoverageDirection::TOP_LEFT, | |
164 TilingCoverageDirection::TOP, | |
165 TilingCoverageDirection::LEFT, | |
166 TilingCoverageDirection::TOP_RIGHT, | |
167 TilingCoverageDirection::BOTTOM_LEFT, | |
168 TilingCoverageDirection::RIGHT, | |
169 TilingCoverageDirection::BOTTOM, | |
170 TilingCoverageDirection::BOTTOM_RIGHT}; | |
171 return top_left_top; | |
172 case TilingCoverageDirection::LEFT: | |
173 static TilingCoverageDirection top_left_left[] = { | |
174 TilingCoverageDirection::TOP_LEFT, | |
175 TilingCoverageDirection::LEFT, | |
176 TilingCoverageDirection::TOP, | |
177 TilingCoverageDirection::BOTTOM_LEFT, | |
178 TilingCoverageDirection::TOP_RIGHT, | |
179 TilingCoverageDirection::BOTTOM, | |
180 TilingCoverageDirection::RIGHT, | |
181 TilingCoverageDirection::BOTTOM_RIGHT}; | |
182 return top_left_left; | |
183 default: | |
184 NOTREACHED(); | |
185 } | |
186 break; | |
187 | |
188 case TilingCoverageDirection::LEFT: | |
189 switch (secondary_direction) { | |
190 case TilingCoverageDirection::TOP_LEFT: | |
191 static TilingCoverageDirection left_top_left[] = { | |
192 TilingCoverageDirection::LEFT, | |
193 TilingCoverageDirection::TOP_LEFT, | |
194 TilingCoverageDirection::BOTTOM_LEFT, | |
195 TilingCoverageDirection::TOP, | |
196 TilingCoverageDirection::BOTTOM, | |
197 TilingCoverageDirection::TOP_RIGHT, | |
198 TilingCoverageDirection::BOTTOM_RIGHT, | |
199 TilingCoverageDirection::RIGHT}; | |
200 return left_top_left; | |
201 case TilingCoverageDirection::BOTTOM_LEFT: | |
202 static TilingCoverageDirection left_bottom_left[] = { | |
203 TilingCoverageDirection::LEFT, | |
204 TilingCoverageDirection::BOTTOM_LEFT, | |
205 TilingCoverageDirection::TOP_LEFT, | |
206 TilingCoverageDirection::BOTTOM, | |
207 TilingCoverageDirection::TOP, | |
208 TilingCoverageDirection::BOTTOM_RIGHT, | |
209 TilingCoverageDirection::TOP_RIGHT, | |
210 TilingCoverageDirection::RIGHT}; | |
211 return left_bottom_left; | |
212 default: | |
213 NOTREACHED(); | |
214 } | |
215 break; | |
216 | |
217 case TilingCoverageDirection::BOTTOM_LEFT: | |
218 switch (secondary_direction) { | |
219 case TilingCoverageDirection::LEFT: | |
220 static TilingCoverageDirection bottom_left_left[] = { | |
221 TilingCoverageDirection::BOTTOM_LEFT, | |
222 TilingCoverageDirection::LEFT, | |
223 TilingCoverageDirection::BOTTOM, | |
224 TilingCoverageDirection::TOP_LEFT, | |
225 TilingCoverageDirection::BOTTOM_RIGHT, | |
226 TilingCoverageDirection::TOP, | |
227 TilingCoverageDirection::RIGHT, | |
228 TilingCoverageDirection::TOP_RIGHT}; | |
229 return bottom_left_left; | |
230 case TilingCoverageDirection::BOTTOM: | |
231 static TilingCoverageDirection bottom_left_bottom[] = { | |
232 TilingCoverageDirection::BOTTOM_LEFT, | |
233 TilingCoverageDirection::BOTTOM, | |
234 TilingCoverageDirection::LEFT, | |
235 TilingCoverageDirection::BOTTOM_RIGHT, | |
236 TilingCoverageDirection::TOP_LEFT, | |
237 TilingCoverageDirection::RIGHT, | |
238 TilingCoverageDirection::TOP, | |
239 TilingCoverageDirection::TOP_RIGHT}; | |
240 return bottom_left_bottom; | |
241 default: | |
242 NOTREACHED(); | |
243 } | |
244 break; | |
245 | |
246 case TilingCoverageDirection::BOTTOM: | |
247 switch (secondary_direction) { | |
248 case TilingCoverageDirection::BOTTOM_LEFT: | |
249 static TilingCoverageDirection bottom_bottom_left[] = { | |
250 TilingCoverageDirection::BOTTOM, | |
251 TilingCoverageDirection::BOTTOM_LEFT, | |
252 TilingCoverageDirection::BOTTOM_RIGHT, | |
253 TilingCoverageDirection::LEFT, | |
254 TilingCoverageDirection::RIGHT, | |
255 TilingCoverageDirection::TOP_LEFT, | |
256 TilingCoverageDirection::TOP_RIGHT, | |
257 TilingCoverageDirection::TOP}; | |
258 return bottom_bottom_left; | |
259 case TilingCoverageDirection::BOTTOM_RIGHT: | |
260 static TilingCoverageDirection bottom_bottom_right[] = { | |
261 TilingCoverageDirection::BOTTOM, | |
262 TilingCoverageDirection::BOTTOM_RIGHT, | |
263 TilingCoverageDirection::BOTTOM_LEFT, | |
264 TilingCoverageDirection::RIGHT, | |
265 TilingCoverageDirection::LEFT, | |
266 TilingCoverageDirection::TOP_RIGHT, | |
267 TilingCoverageDirection::TOP_LEFT, | |
268 TilingCoverageDirection::TOP}; | |
269 return bottom_bottom_right; | |
270 default: | |
271 NOTREACHED(); | |
272 } | |
273 break; | |
274 | |
275 case TilingCoverageDirection::BOTTOM_RIGHT: | |
276 switch (secondary_direction) { | |
277 case TilingCoverageDirection::BOTTOM: | |
278 static TilingCoverageDirection bottom_right_bottom[] = { | |
279 TilingCoverageDirection::BOTTOM_RIGHT, | |
280 TilingCoverageDirection::BOTTOM, | |
281 TilingCoverageDirection::RIGHT, | |
282 TilingCoverageDirection::BOTTOM_LEFT, | |
283 TilingCoverageDirection::TOP_RIGHT, | |
284 TilingCoverageDirection::LEFT, | |
285 TilingCoverageDirection::TOP, | |
286 TilingCoverageDirection::TOP_LEFT}; | |
287 return bottom_right_bottom; | |
288 case TilingCoverageDirection::RIGHT: | |
289 static TilingCoverageDirection bottom_right_right[] = { | |
290 TilingCoverageDirection::BOTTOM_RIGHT, | |
291 TilingCoverageDirection::RIGHT, | |
292 TilingCoverageDirection::BOTTOM, | |
293 TilingCoverageDirection::TOP_RIGHT, | |
294 TilingCoverageDirection::BOTTOM_LEFT, | |
295 TilingCoverageDirection::TOP, | |
296 TilingCoverageDirection::LEFT, | |
297 TilingCoverageDirection::TOP_LEFT}; | |
298 return bottom_right_right; | |
299 default: | |
300 NOTREACHED(); | |
301 } | |
302 break; | |
303 } | |
304 | |
305 return nullptr; | |
306 } | |
307 | |
308 int GetPositionForDirection(TilingCoverageDirection* positions, | |
309 TilingCoverageDirection direction) { | |
310 for (int i = 0; i < 8; ++i) { | |
311 if (positions[i] == direction) | |
312 return i; | |
313 } | |
314 | |
315 NOTREACHED(); | |
316 return -1; | |
317 } | |
318 | |
319 } // namespace | |
320 | |
321 // TriangularSequence implementation. | |
322 TriangularSequence::TriangularSequence(std::string&& name, | |
323 Type type, | |
324 Interval&& interval, | |
325 Interval&& interval_inflate_limit, | |
326 int levels, | |
327 int levels_to_skip, | |
328 bool reverse) | |
329 : name_(std::move(name)), | |
330 type_(type), | |
331 interval_(std::move(interval)), | |
332 interval_inflate_limit_(std::move(interval_inflate_limit)), | |
333 initial_interval_(interval_), | |
334 levels_(levels), | |
335 levels_traversed_(0), | |
336 levels_limit_(levels), | |
337 reverse_(reverse), | |
338 within_bounds_(true), | |
339 inflate_(nullptr), | |
340 is_within_bounds_(nullptr) { | |
341 DCHECK_GE(levels, 0); | |
342 Init(type); | |
343 (this->*inflate_)(levels_to_skip); | |
344 | |
345 if (reverse) { | |
346 levels_limit_ = levels_traversed_; | |
347 int last_level = levels - levels_to_skip - 1; | |
348 (this->*inflate_)(last_level); | |
349 } | |
350 } | |
351 | |
352 TriangularSequence::TriangularSequence(const TriangularSequence& other) = | |
353 default; | |
354 | |
355 TriangularSequence::TriangularSequence(TriangularSequence&& other) = default; | |
356 | |
357 TriangularSequence::~TriangularSequence() { | |
358 inflate_ = nullptr; | |
359 is_within_bounds_ = nullptr; | |
360 } | |
361 | |
362 TriangularSequence& TriangularSequence::operator=( | |
363 const TriangularSequence& other) = default; | |
364 | |
365 TriangularSequence& TriangularSequence::operator=(TriangularSequence&& other) = | |
366 default; | |
367 | |
368 int TriangularSequence::GetInitialIntervalSpan() { | |
369 return step_ == 1 ? initial_interval_.end - initial_interval_.start + 1 | |
370 : initial_interval_.start - initial_interval_.end + 1; | |
371 } | |
372 | |
373 int TriangularSequence::GetCurrentSequenceNumber() { | |
374 DCHECK(inflate_); | |
375 if (levels_traversed_ < levels_limit_ && !within_bounds_) | |
376 (this->*inflate_)(1); | |
377 | |
378 return current_sequence_number_; | |
379 } | |
380 | |
381 int TriangularSequence::GetReverseCurrentSequenceNumber() { | |
382 DCHECK(inflate_); | |
383 if (levels_traversed_ >= levels_limit_ && !within_bounds_) | |
384 (this->*inflate_)(-1); | |
385 | |
386 return current_sequence_number_; | |
387 } | |
388 | |
389 void TriangularSequence::Advance() { | |
390 DCHECK(is_within_bounds_); | |
391 current_sequence_number_ += step_; | |
392 within_bounds_ = (this->*is_within_bounds_)(); | |
393 } | |
394 | |
395 void TriangularSequence::Init(TriangularSequence::Type type) { | |
396 switch (type) { | |
397 case TriangularSequence::Type::FORWARD: | |
398 inflate_ = &TriangularSequence::InflateForward; | |
399 is_within_bounds_ = &TriangularSequence::IsWithinBoundsForward; | |
400 step_ = reverse_ ? -1 : 1; | |
401 break; | |
402 case TriangularSequence::Type::BACKWARD: | |
403 inflate_ = &TriangularSequence::InflateBackward; | |
404 is_within_bounds_ = &TriangularSequence::IsWithinBoundsBackward; | |
405 step_ = reverse_ ? 1 : -1; | |
406 break; | |
407 case TriangularSequence::Type::DIAGONAL_FORWARD: | |
408 DCHECK_EQ(interval_.start, interval_.end); | |
409 inflate_ = &TriangularSequence::InflateDiagonalForward; | |
410 is_within_bounds_ = &TriangularSequence::IsWithinBoundsDiagonal; | |
411 step_ = reverse_ ? -1 : 1; | |
412 break; | |
413 case TriangularSequence::Type::DIAGONAL_BACKWARD: | |
414 DCHECK_EQ(interval_.start, interval_.end); | |
415 inflate_ = &TriangularSequence::InflateDiagonalBackward; | |
416 is_within_bounds_ = &TriangularSequence::IsWithinBoundsDiagonal; | |
417 step_ = reverse_ ? 1 : -1; | |
418 break; | |
419 } | |
420 } | |
421 | |
422 void TriangularSequence::Reset() { | |
423 current_sequence_number_ = reverse_ ? interval_.end : interval_.start; | |
424 within_bounds_ = true; | |
425 } | |
426 | |
427 void TriangularSequence::InflateForward(int levels) { | |
428 levels_traversed_ += levels; | |
429 interval_.start = initial_interval_.start - levels_traversed_; | |
430 interval_.end = initial_interval_.end + levels_traversed_; | |
431 | |
432 interval_.start = ClampNumberInForwardInterval(interval_.start, | |
433 interval_inflate_limit_.start, | |
434 interval_inflate_limit_.end); | |
435 interval_.end = | |
436 ClampNumberInForwardInterval(interval_.end, interval_inflate_limit_.start, | |
437 interval_inflate_limit_.end); | |
438 | |
439 Reset(); | |
440 } | |
441 | |
442 void TriangularSequence::InflateBackward(int levels) { | |
443 levels_traversed_ += levels; | |
444 interval_.start = initial_interval_.start + levels_traversed_; | |
445 interval_.end = initial_interval_.end - levels_traversed_; | |
446 interval_.start = ClampNumberInBackwardInterval(interval_.start, | |
447 interval_inflate_limit_.start, | |
448 interval_inflate_limit_.end); | |
449 interval_.end = ClampNumberInBackwardInterval(interval_.end, | |
450 interval_inflate_limit_.start, | |
451 interval_inflate_limit_.end); | |
452 | |
453 Reset(); | |
454 } | |
455 | |
456 void TriangularSequence::InflateDiagonalForward(int levels) { | |
457 levels_traversed_ += levels; | |
458 interval_.start = initial_interval_.start + levels_traversed_; | |
459 interval_.end = initial_interval_.end + levels_traversed_; | |
460 | |
461 Reset(); | |
462 } | |
463 | |
464 void TriangularSequence::InflateDiagonalBackward(int levels) { | |
465 levels_traversed_ += levels; | |
466 interval_.start = initial_interval_.start - levels_traversed_; | |
467 interval_.end = initial_interval_.end - levels_traversed_; | |
468 | |
469 Reset(); | |
470 } | |
471 | |
472 bool TriangularSequence::IsWithinBoundsForward() { | |
473 DCHECK(reverse_ ? current_sequence_number_ <= interval_.end | |
474 : current_sequence_number_ >= interval_.start); | |
475 | |
476 if (interval_.start == interval_.end || | |
477 (reverse_ ? current_sequence_number_ < interval_.start | |
478 : current_sequence_number_ > interval_.end)) | |
479 return false; | |
480 | |
481 return true; | |
482 } | |
483 | |
484 bool TriangularSequence::IsWithinBoundsBackward() { | |
485 DCHECK(reverse_ ? current_sequence_number_ >= interval_.end | |
486 : current_sequence_number_ <= interval_.start); | |
487 | |
488 if (interval_.start == interval_.end || | |
489 (reverse_ ? current_sequence_number_ > interval_.start | |
490 : current_sequence_number_ < interval_.end)) | |
491 return false; | |
492 | |
493 return true; | |
494 } | |
495 | |
496 bool TriangularSequence::IsWithinBoundsDiagonal() { | |
497 DCHECK_EQ(interval_.start, interval_.end); | |
498 if (current_sequence_number_ != interval_.start) | |
499 return false; | |
500 | |
501 return true; | |
502 } | |
503 | |
504 // LevelDistanceSequence implementation. | |
505 LevelDistanceSequence::LevelDistanceSequence() | |
506 : traversal_sequence_(TriangularSequence(std::string("dummy"), | |
507 TriangularSequence::Type::FORWARD, | |
508 TriangularSequence::Interval(0, 0), | |
509 TriangularSequence::Interval(0, 0), | |
510 0, | |
511 0, | |
512 false)), | |
513 swapped_(false), | |
514 reverse_(false), | |
515 current_sequence_index_(-1), | |
516 current_level_index_(-1) {} | |
517 | |
518 LevelDistanceSequence::LevelDistanceSequence( | |
519 TriangularSequence&& traversal_sequence, | |
520 TriangularSequence&& level_sequence, | |
521 bool swapped, | |
522 int levels_to_skip, | |
523 int levels_delta, | |
524 int distance, | |
525 bool reverse) | |
526 : traversal_sequence_(std::move(traversal_sequence)), | |
527 swapped_(swapped), | |
528 reverse_(reverse) { | |
529 for (int i = levels_to_skip; i < level_sequence.GetInitialIntervalSpan(); | |
530 ++i) { | |
531 int d = distance * i; | |
532 int l = level_sequence.GetCurrentSequenceNumber() + levels_delta; | |
533 | |
534 level_distances_.push_back(LevelDistance(l, d)); | |
535 level_sequence.Advance(); | |
536 } | |
537 if (IsValid()) | |
538 Reset(); | |
539 } | |
540 | |
541 LevelDistanceSequence::LevelDistanceSequence( | |
542 const LevelDistanceSequence& other) = default; | |
543 | |
544 LevelDistanceSequence::LevelDistanceSequence(LevelDistanceSequence&& other) = | |
545 default; | |
546 | |
547 LevelDistanceSequence::~LevelDistanceSequence() { | |
548 level_distances_.clear(); | |
549 } | |
550 | |
551 LevelDistanceSequence& LevelDistanceSequence::operator=( | |
552 const LevelDistanceSequence& other) = default; | |
553 | |
554 LevelDistanceSequence& LevelDistanceSequence::operator=( | |
555 LevelDistanceSequence&& other) = default; | |
556 | |
557 int LevelDistanceSequence::GetCurrentIndexX() const { | |
558 return swapped_ ? current_level_index_ : current_sequence_index_; | |
559 } | |
560 | |
561 int LevelDistanceSequence::GetCurrentIndexY() const { | |
562 return swapped_ ? current_sequence_index_ : current_level_index_; | |
563 } | |
564 | |
565 int LevelDistanceSequence::GetMinimumDistance() const { | |
566 DCHECK(!level_distances_.empty()); | |
567 return level_distances_.front().distance; | |
568 } | |
569 | |
570 int LevelDistanceSequence::GetMaximumDistance() const { | |
571 DCHECK(!level_distances_.empty()); | |
572 return level_distances_.back().distance; | |
573 } | |
574 | |
575 bool LevelDistanceSequence::Advance() { | |
576 traversal_sequence_.Advance(); | |
577 if (!traversal_sequence_.is_within_bounds()) { | |
578 level_distances_.erase(level_distances_.begin()); | |
579 if (IsValid()) | |
580 Reset(); | |
581 | |
582 return false; | |
583 } | |
584 | |
585 current_sequence_index_ = traversal_sequence_.GetCurrentSequenceNumber(); | |
586 return true; | |
587 } | |
588 | |
589 bool LevelDistanceSequence::ReverseAdvance() { | |
590 traversal_sequence_.Advance(); | |
591 if (!traversal_sequence_.is_within_bounds()) { | |
592 level_distances_.erase(level_distances_.end() - 1); | |
593 if (IsValid()) | |
594 Reset(); | |
595 | |
596 return false; | |
597 } | |
598 | |
599 current_sequence_index_ = | |
600 traversal_sequence_.GetReverseCurrentSequenceNumber(); | |
601 return true; | |
602 } | |
603 | |
604 void LevelDistanceSequence::Reset() { | |
605 DCHECK(!level_distances_.empty()); | |
606 if (reverse_) { | |
607 current_sequence_index_ = | |
608 traversal_sequence_.GetReverseCurrentSequenceNumber(); | |
609 current_level_index_ = level_distances_.back().level; | |
610 } else { | |
611 current_sequence_index_ = traversal_sequence_.GetCurrentSequenceNumber(); | |
612 current_level_index_ = level_distances_.front().level; | |
613 } | |
614 } | |
615 | |
616 // PyramidSequence implementation. | |
617 PyramidSequence::PyramidSequence(bool reverse) | |
618 : reverse_(reverse), | |
619 current_level_distance_sequence_(nullptr), | |
620 index_x_(-1), | |
621 index_y_(-1) {} | |
622 | |
623 PyramidSequence::PyramidSequence(const PyramidSequence& other) = default; | |
624 | |
625 PyramidSequence::PyramidSequence(PyramidSequence&& other) = default; | |
626 | |
627 PyramidSequence::~PyramidSequence() { | |
628 level_distance_sequences_.clear(); | |
629 current_level_distance_sequence_ = nullptr; | |
630 } | |
631 | |
632 PyramidSequence& PyramidSequence::operator=(const PyramidSequence& other) = | |
633 default; | |
634 | |
635 PyramidSequence& PyramidSequence::operator=(PyramidSequence&& other) = default; | |
636 | |
637 bool PyramidSequence::IsTraversed() { | |
638 if (!current_level_distance_sequence_) | |
639 return true; | |
640 | |
641 return level_distance_sequences_.empty(); | |
642 } | |
643 | |
644 void PyramidSequence::Init(int around_left, | |
645 int around_right, | |
646 int around_top, | |
647 int around_bottom, | |
648 int consider_left, | |
649 int consider_right, | |
650 int consider_top, | |
651 int consider_bottom, | |
652 int ignore_left, | |
653 int ignore_right, | |
654 int ignore_top, | |
655 int ignore_bottom, | |
656 int width, | |
657 int height) { | |
658 consider_left_ = consider_left; | |
659 consider_right_ = consider_right; | |
660 consider_top_ = consider_top; | |
661 consider_bottom_ = consider_bottom; | |
662 ignore_left_ = ignore_left; | |
663 ignore_right_ = ignore_right; | |
664 ignore_top_ = ignore_top; | |
665 ignore_bottom_ = ignore_bottom; | |
666 | |
667 int left_levels = around_left - consider_left + 1; | |
668 int right_levels = consider_right - around_right + 1; | |
669 int top_levels = around_top - consider_top + 1; | |
670 int bottom_levels = consider_bottom - around_bottom + 1; | |
671 | |
672 int skip_left_levels = around_left - consider_right; | |
673 int skip_right_levels = consider_left - around_right; | |
674 int skip_top_levels = around_top - consider_bottom; | |
675 int skip_bottom_levels = consider_top - around_bottom; | |
676 | |
677 int skip_left_levels_perp = | |
678 LevelsToSkipPerpendicularToDirection(skip_left_levels); | |
679 int skip_right_levels_perp = | |
680 LevelsToSkipPerpendicularToDirection(skip_right_levels); | |
681 int skip_top_levels_perp = | |
682 LevelsToSkipPerpendicularToDirection(skip_top_levels); | |
683 int skip_bottom_levels_perp = | |
684 LevelsToSkipPerpendicularToDirection(skip_bottom_levels); | |
685 | |
686 skip_left_levels = LevelsToSkipAlongDirection(skip_left_levels); | |
687 skip_right_levels = LevelsToSkipAlongDirection(skip_right_levels); | |
688 skip_top_levels = LevelsToSkipAlongDirection(skip_top_levels); | |
689 skip_bottom_levels = LevelsToSkipAlongDirection(skip_bottom_levels); | |
690 | |
691 int diagonal_length = std::max(width, height); | |
692 | |
693 DCHECK(level_distance_sequences_.empty()); | |
694 level_distance_sequences_.resize(8); | |
695 // TODO(prashant.n): Implement direction of movement for this instead of | |
696 // default right direction. http://crbug.com/629052. | |
697 TilingCoverageDirection* positions = | |
698 GetCoverageDirectionSequenceForDirections( | |
699 TilingCoverageDirection::RIGHT, | |
700 TilingCoverageDirection::BOTTOM_RIGHT); | |
701 DCHECK(positions); | |
702 | |
703 // RIGHT seq | |
704 if (right_levels > 0) { | |
705 int start = around_bottom - 1; | |
706 int end = around_top + 1; | |
707 int skip_levels = | |
708 std::max(skip_right_levels, | |
709 std::max(skip_bottom_levels_perp, skip_top_levels_perp)); | |
710 if (right_levels > skip_levels) { | |
711 EmplaceAt( | |
712 GetPositionForDirection(positions, TilingCoverageDirection::RIGHT), | |
713 LevelDistanceSequence( | |
714 TriangularSequence( | |
715 std::string("r.seq"), TriangularSequence::Type::BACKWARD, | |
716 TriangularSequence::Interval(start, end), | |
717 TriangularSequence::Interval(consider_bottom, consider_top), | |
718 right_levels, skip_levels, reverse_), | |
719 TriangularSequence( | |
720 std::string("r.lev"), TriangularSequence::Type::FORWARD, | |
721 TriangularSequence::Interval(around_right, consider_right), | |
722 TriangularSequence::Interval(consider_left, consider_right), | |
723 1, 0, false), | |
724 true, skip_levels, skip_levels - skip_right_levels, width, | |
725 reverse_)); | |
726 } | |
727 } | |
728 | |
729 // TOP_RIGHT seq | |
730 if (right_levels > 0 && top_levels > 0) { | |
731 int skip_levels = std::max(skip_right_levels, skip_top_levels); | |
732 int diagonal_levels = std::min(right_levels, top_levels); | |
733 if (diagonal_levels > skip_levels) { | |
734 EmplaceAt( | |
735 GetPositionForDirection(positions, | |
736 TilingCoverageDirection::TOP_RIGHT), | |
737 LevelDistanceSequence( | |
738 TriangularSequence( | |
739 std::string("tr.seq"), | |
740 TriangularSequence::Type::DIAGONAL_FORWARD, | |
741 TriangularSequence::Interval(around_right, around_right), | |
742 TriangularSequence::Interval(consider_left, consider_right), | |
743 diagonal_levels, skip_levels, reverse_), | |
744 TriangularSequence( | |
745 std::string("tr.lev"), TriangularSequence::Type::BACKWARD, | |
746 TriangularSequence::Interval( | |
747 around_top, around_top - diagonal_levels + 1), | |
748 TriangularSequence::Interval(consider_bottom, consider_top), | |
749 1, 0, false), | |
750 false, skip_levels, skip_levels - skip_top_levels, | |
751 diagonal_length, reverse_)); | |
752 } | |
753 } | |
754 | |
755 // TOP seq | |
756 if (top_levels > 0) { | |
757 int start = around_right - 1; | |
758 int end = around_left + 1; | |
759 int skip_levels = | |
760 std::max(skip_top_levels, | |
761 std::max(skip_right_levels_perp, skip_left_levels_perp)); | |
762 if (top_levels > skip_levels) { | |
763 EmplaceAt( | |
764 GetPositionForDirection(positions, TilingCoverageDirection::TOP), | |
765 LevelDistanceSequence( | |
766 TriangularSequence( | |
767 std::string("t.seq"), TriangularSequence::Type::BACKWARD, | |
768 TriangularSequence::Interval(start, end), | |
769 TriangularSequence::Interval(consider_right, consider_left), | |
770 top_levels, skip_levels, reverse_), | |
771 TriangularSequence( | |
772 std::string("t.lev"), TriangularSequence::Type::BACKWARD, | |
773 TriangularSequence::Interval(around_top, consider_top), | |
774 TriangularSequence::Interval(consider_bottom, consider_top), | |
775 1, 0, false), | |
776 false, skip_levels, skip_levels - skip_top_levels, height, | |
777 reverse_)); | |
778 } | |
779 } | |
780 | |
781 // TOP_LEFT seq | |
782 if (top_levels > 0 && left_levels > 0) { | |
783 int skip_levels = std::max(skip_top_levels, skip_left_levels); | |
784 int diagonal_levels = std::min(top_levels, left_levels); | |
785 if (diagonal_levels > skip_levels) { | |
786 EmplaceAt( | |
787 GetPositionForDirection(positions, TilingCoverageDirection::TOP_LEFT), | |
788 LevelDistanceSequence( | |
789 TriangularSequence( | |
790 std::string("tl.seq"), | |
791 TriangularSequence::Type::DIAGONAL_BACKWARD, | |
792 TriangularSequence::Interval(around_left, around_left), | |
793 TriangularSequence::Interval(consider_right, consider_left), | |
794 diagonal_levels, skip_levels, reverse_), | |
795 TriangularSequence( | |
796 std::string("tl.lev"), TriangularSequence::Type::BACKWARD, | |
797 TriangularSequence::Interval( | |
798 around_top, around_top - diagonal_levels + 1), | |
799 TriangularSequence::Interval(consider_bottom, consider_top), | |
800 1, 0, false), | |
801 false, skip_levels, skip_levels - skip_top_levels, | |
802 diagonal_length, reverse_)); | |
803 } | |
804 } | |
805 | |
806 // LEFT seq | |
807 if (left_levels > 0) { | |
808 int start = around_top + 1; | |
809 int end = around_bottom - 1; | |
810 int skip_levels = | |
811 std::max(skip_left_levels, | |
812 std::max(skip_top_levels_perp, skip_bottom_levels_perp)); | |
813 if (left_levels > skip_levels) { | |
814 EmplaceAt( | |
815 GetPositionForDirection(positions, TilingCoverageDirection::LEFT), | |
816 LevelDistanceSequence( | |
817 TriangularSequence( | |
818 std::string("l.seq"), TriangularSequence::Type::FORWARD, | |
819 TriangularSequence::Interval(start, end), | |
820 TriangularSequence::Interval(consider_top, consider_bottom), | |
821 left_levels, skip_levels, reverse_), | |
822 TriangularSequence( | |
823 std::string("l.lev"), TriangularSequence::Type::BACKWARD, | |
824 TriangularSequence::Interval(around_left, consider_left), | |
825 TriangularSequence::Interval(consider_right, consider_left), | |
826 1, 0, false), | |
827 true, skip_levels, skip_levels - skip_left_levels, width, | |
828 reverse_)); | |
829 } | |
830 } | |
831 | |
832 // BOTTOM_LEFT seq | |
833 if (left_levels > 0 && bottom_levels > 0) { | |
834 int skip_levels = std::max(skip_left_levels, skip_bottom_levels); | |
835 int diagonal_levels = std::min(left_levels, bottom_levels); | |
836 if (diagonal_levels > skip_levels) { | |
837 EmplaceAt( | |
838 GetPositionForDirection(positions, | |
839 TilingCoverageDirection::BOTTOM_LEFT), | |
840 LevelDistanceSequence( | |
841 TriangularSequence( | |
842 std::string("bl.seq"), | |
843 TriangularSequence::Type::DIAGONAL_BACKWARD, | |
844 TriangularSequence::Interval(around_left, around_left), | |
845 TriangularSequence::Interval(consider_right, consider_left), | |
846 diagonal_levels, skip_levels, reverse_), | |
847 TriangularSequence( | |
848 std::string("bl.lev"), TriangularSequence::Type::FORWARD, | |
849 TriangularSequence::Interval( | |
850 around_bottom, around_bottom + diagonal_levels - 1), | |
851 TriangularSequence::Interval(consider_top, consider_bottom), | |
852 1, 0, false), | |
853 false, skip_levels, skip_levels - skip_bottom_levels, | |
854 diagonal_length, reverse_)); | |
855 } | |
856 } | |
857 | |
858 // BOTTOM seq | |
859 if (bottom_levels > 0) { | |
860 int start = around_left + 1; | |
861 int end = around_right - 1; | |
862 int skip_levels = | |
863 std::max(skip_bottom_levels, | |
864 std::max(skip_left_levels_perp, skip_right_levels_perp)); | |
865 if (bottom_levels > skip_levels) { | |
866 EmplaceAt( | |
867 GetPositionForDirection(positions, TilingCoverageDirection::BOTTOM), | |
868 LevelDistanceSequence( | |
869 TriangularSequence( | |
870 std::string("b.seq"), TriangularSequence::Type::FORWARD, | |
871 TriangularSequence::Interval(start, end), | |
872 TriangularSequence::Interval(consider_left, consider_right), | |
873 bottom_levels, skip_levels, reverse_), | |
874 TriangularSequence( | |
875 std::string("b.lev"), TriangularSequence::Type::FORWARD, | |
876 TriangularSequence::Interval(around_bottom, consider_bottom), | |
877 TriangularSequence::Interval(consider_top, consider_bottom), | |
878 1, 0, false), | |
879 false, skip_levels, skip_levels - skip_bottom_levels, height, | |
880 reverse_)); | |
881 } | |
882 } | |
883 | |
884 // BOTTOM_RIGHT seq | |
885 if (bottom_levels > 0 && right_levels > 0) { | |
886 int skip_levels = std::max(skip_bottom_levels, skip_right_levels); | |
887 int diagonal_levels = std::min(bottom_levels, right_levels); | |
888 if (diagonal_levels > skip_levels) { | |
889 EmplaceAt( | |
890 GetPositionForDirection(positions, | |
891 TilingCoverageDirection::BOTTOM_RIGHT), | |
892 LevelDistanceSequence( | |
893 TriangularSequence( | |
894 std::string("br.seq"), | |
895 TriangularSequence::Type::DIAGONAL_FORWARD, | |
896 TriangularSequence::Interval(around_right, around_right), | |
897 TriangularSequence::Interval(consider_left, consider_right), | |
898 diagonal_levels, skip_levels, reverse_), | |
899 TriangularSequence( | |
900 std::string("br.lev"), TriangularSequence::Type::FORWARD, | |
901 TriangularSequence::Interval( | |
902 around_bottom, around_bottom + diagonal_levels - 1), | |
903 TriangularSequence::Interval(consider_top, consider_bottom), | |
904 1, 0, false), | |
905 false, skip_levels, skip_levels - skip_bottom_levels, | |
906 diagonal_length, reverse_)); | |
907 } | |
908 } | |
909 | |
910 current_level_distance_sequence_ = GetNextLevelDistanceSequence(); | |
911 UpdateCurrent(); | |
912 } | |
913 | |
914 void PyramidSequence::EmplaceAt( | |
915 int position, | |
916 LevelDistanceSequence&& level_distance_sequence) { | |
917 LevelDistanceSequence::Iterator it = level_distance_sequences_.begin(); | |
918 std::advance(it, position); | |
919 level_distance_sequences_.emplace(it, std::move(level_distance_sequence)); | |
920 LevelDistanceSequence::Iterator erase_it = level_distance_sequences_.begin(); | |
921 std::advance(erase_it, position + 1); | |
922 level_distance_sequences_.erase(erase_it); | |
923 } | |
924 | |
925 void PyramidSequence::UpdateCurrent() { | |
926 while (!IsTraversed()) { | |
927 DCHECK(current_level_distance_sequence_->IsValid()); | |
928 | |
929 index_x_ = current_level_distance_sequence_->GetCurrentIndexX(); | |
930 index_y_ = current_level_distance_sequence_->GetCurrentIndexY(); | |
931 | |
932 if (InConsiderRect() && !InIgnoreRect()) | |
933 break; | |
934 | |
935 Advance(); | |
936 } | |
937 } | |
938 | |
939 bool PyramidSequence::InConsiderRect() const { | |
940 return index_x_ >= consider_left_ && index_x_ <= consider_right_ && | |
941 index_y_ >= consider_top_ && index_y_ <= consider_bottom_; | |
942 } | |
943 | |
944 bool PyramidSequence::InIgnoreRect() const { | |
945 return index_x_ >= ignore_left_ && index_x_ <= ignore_right_ && | |
946 index_y_ >= ignore_top_ && index_y_ <= ignore_bottom_; | |
947 } | |
948 | |
949 void PyramidSequence::RemoveEmptyLevelDistanceSequences() { | |
950 level_distance_sequences_.erase( | |
951 std::remove_if( | |
952 level_distance_sequences_.begin(), level_distance_sequences_.end(), | |
953 [](const LevelDistanceSequence& seq) { return !seq.IsValid(); }), | |
954 level_distance_sequences_.end()); | |
955 } | |
956 | |
957 // TopDownPyramidSequence implementation. | |
958 TopDownPyramidSequence::TopDownPyramidSequence() : PyramidSequence(false) {} | |
959 | |
960 TopDownPyramidSequence::TopDownPyramidSequence( | |
961 const TopDownPyramidSequence& other) = default; | |
962 | |
963 TopDownPyramidSequence::TopDownPyramidSequence(TopDownPyramidSequence&& other) = | |
964 default; | |
965 | |
966 TopDownPyramidSequence::~TopDownPyramidSequence() {} | |
967 | |
968 TopDownPyramidSequence& TopDownPyramidSequence::operator=( | |
969 const TopDownPyramidSequence& other) = default; | |
970 | |
971 TopDownPyramidSequence& TopDownPyramidSequence::operator=( | |
972 TopDownPyramidSequence&& other) = default; | |
973 | |
974 void TopDownPyramidSequence::Advance() { | |
975 if (IsTraversed()) | |
976 return; | |
977 | |
978 if (!current_level_distance_sequence_->Advance()) | |
979 current_level_distance_sequence_ = GetNextLevelDistanceSequence(); | |
980 } | |
981 | |
982 LevelDistanceSequence* TopDownPyramidSequence::GetNextLevelDistanceSequence() { | |
983 RemoveEmptyLevelDistanceSequences(); | |
984 | |
985 if (level_distance_sequences_.empty()) | |
986 return nullptr; | |
987 | |
988 LevelDistanceSequence::Iterator min_distance_it = | |
989 level_distance_sequences_.begin(); | |
990 | |
991 for (LevelDistanceSequence::Iterator it = level_distance_sequences_.begin(); | |
992 it != level_distance_sequences_.end(); ++it) { | |
993 int distance = it->GetMinimumDistance(); | |
994 if (distance == 0) | |
995 return &(*it); | |
996 | |
997 if (min_distance_it->GetMinimumDistance() > distance) | |
998 min_distance_it = it; | |
999 } | |
1000 | |
1001 return &(*min_distance_it); | |
1002 } | |
1003 | |
1004 // BottomUpPyramidSequence implementation. | |
1005 BottomUpPyramidSequence::BottomUpPyramidSequence() : PyramidSequence(true) {} | |
1006 | |
1007 BottomUpPyramidSequence::BottomUpPyramidSequence( | |
1008 const BottomUpPyramidSequence& other) | |
1009 : PyramidSequence(other) {} | |
1010 | |
1011 BottomUpPyramidSequence::BottomUpPyramidSequence( | |
1012 BottomUpPyramidSequence&& other) | |
1013 : PyramidSequence(std::move(other)) {} | |
1014 | |
1015 BottomUpPyramidSequence::~BottomUpPyramidSequence() {} | |
1016 | |
1017 BottomUpPyramidSequence& BottomUpPyramidSequence::operator=( | |
1018 const BottomUpPyramidSequence& other) { | |
1019 PyramidSequence::operator=(other); | |
1020 return *this; | |
1021 } | |
1022 | |
1023 BottomUpPyramidSequence& BottomUpPyramidSequence::operator=( | |
1024 BottomUpPyramidSequence&& other) { | |
1025 PyramidSequence::operator=(std::move(other)); | |
1026 return *this; | |
1027 } | |
1028 | |
1029 void BottomUpPyramidSequence::Advance() { | |
1030 if (IsTraversed()) | |
1031 return; | |
1032 | |
1033 if (!current_level_distance_sequence_->ReverseAdvance()) | |
1034 current_level_distance_sequence_ = GetNextLevelDistanceSequence(); | |
1035 } | |
1036 | |
1037 LevelDistanceSequence* BottomUpPyramidSequence::GetNextLevelDistanceSequence() { | |
1038 RemoveEmptyLevelDistanceSequences(); | |
1039 | |
1040 if (level_distance_sequences_.empty()) | |
1041 return nullptr; | |
1042 | |
1043 LevelDistanceSequence::ReverseIterator max_distance_it = | |
1044 level_distance_sequences_.rbegin(); | |
1045 | |
1046 for (LevelDistanceSequence::ReverseIterator it = | |
1047 level_distance_sequences_.rbegin(); | |
1048 it != level_distance_sequences_.rend(); ++it) { | |
1049 int distance = it->GetMaximumDistance(); | |
1050 | |
1051 if (max_distance_it->GetMaximumDistance() < distance) | |
1052 max_distance_it = it; | |
1053 } | |
1054 | |
1055 return &(*max_distance_it); | |
1056 } | |
1057 | |
1058 } // namespace cc | |
OLD | NEW |