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

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

Issue 2067213002: cc: Implement tile iteration order based on pyramid sequence. [old] Base URL: https://chromium.googlesource.com/chromium/src.git@tiling_data_fix
Patch Set: for review Created 4 years, 5 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/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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698