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

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: rebase -> used for smoothness tests Created 3 years, 10 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
« no previous file with comments | « cc/base/pyramid_sequence.h ('k') | cc/base/pyramid_sequence_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #define ENUM_TO_INDEX(x) static_cast<unsigned int>(x)
11
12 namespace cc {
13
14 namespace {
15
16 int LevelsToSkipAlongDirection(int levels) {
17 return levels > 0 ? levels : 0;
18 }
19
20 int LevelsToSkipCrossDirection(int levels) {
21 return levels >= 0 ? levels + 1 : 0;
22 }
23
24 // The following function returns default coverage as spiral order {R, T, L, B}.
25 // TODO(prashant.n): Implement precedence in coverage directions instead of
26 // default spiral coverage. http://crbug.com/629052.
27 CoverageDirection* GetCoverageDirectionSequence() {
28 static CoverageDirection
29 spiral_coverage[ENUM_TO_INDEX(CoverageDirection::SIZE)] = {
30 CoverageDirection::RIGHT, CoverageDirection::TOP,
31 CoverageDirection::LEFT, CoverageDirection::BOTTOM};
32 return spiral_coverage;
33 }
34
35 int GetPositionForDirection(CoverageDirection* positions,
36 CoverageDirection direction) {
37 for (unsigned int i = 0; i < ENUM_TO_INDEX(CoverageDirection::SIZE); ++i) {
38 if (positions[i] == direction)
39 return i;
40 }
41
42 NOTREACHED();
43 return -1;
44 }
45
46 } // namespace
47
48 namespace internal {
49
50 // Interval implementation.
51 Interval::Iterator* Interval::Begin() {
52 return new Iterator(this);
53 }
54
55 Interval::ReverseIterator* Interval::ReverseBegin() {
56 return new ReverseIterator(this);
57 }
58
59 int Interval::GetSpan() const {
60 return empty_ ? 0 : std::abs(end_ - start_) + 1;
61 }
62
63 int Interval::GetForwardClampedIndex(int index) const {
64 DCHECK_LE(start_, end_);
65 return (index < start_) ? start_ : ((index > end_) ? end_ : index);
66 }
67
68 int Interval::GetBackwardClampedIndex(int index) const {
69 DCHECK_GE(start_, end_);
70 return (index > start_) ? start_ : ((index < end_) ? end_ : index);
71 }
72
73 void Interval::ForwardClampTo(const Interval* other) {
74 DCHECK_LE(start_, end_);
75 DCHECK_LE(other->start_, other->end_);
76 start_ = other->GetForwardClampedIndex(start_);
77 end_ = other->GetForwardClampedIndex(end_);
78 }
79
80 void Interval::BackwardClampTo(const Interval* other) {
81 DCHECK_GE(start_, end_);
82 DCHECK_GE(other->start_, other->end_);
83 start_ = other->GetBackwardClampedIndex(start_);
84 end_ = other->GetBackwardClampedIndex(end_);
85 }
86
87 void Interval::ForwardInflate(int level, Interval* output) const {
88 output->start_ = start_ - level;
89 output->end_ = end_ + level;
90 }
91
92 void Interval::BackwardInflate(int level, Interval* output) const {
93 output->start_ = start_ + level;
94 output->end_ = end_ - level;
95 }
96
97 bool Interval::Contains(int index) const {
98 return (start_ <= end_) ? (index >= start_ && index <= end_)
99 : (index <= start_ && index >= end_);
100 }
101
102 bool Interval::Intersects(const Interval* interval) const {
103 return interval->Contains(start_) || interval->Contains(end_);
104 }
105
106 void Interval::Intersect(const Interval* interval) {
107 DCHECK(Intersects(interval));
108 DCHECK(((start_ <= end_) && (interval->start_ <= interval->end_)) ||
109 ((start_ >= end_) && (interval->start_ >= interval->end_)));
110
111 bool forward_direction = (GetSpan() > interval->GetSpan())
112 ? (start_ <= end_)
113 : (interval->start_ <= interval->end_);
114
115 if (forward_direction) {
116 start_ = std::max(start_, interval->start_);
117 end_ = std::min(end_, interval->end_);
118 } else {
119 start_ = std::min(start_, interval->start_);
120 end_ = std::max(end_, interval->end_);
121 }
122 }
123
124 // Interval::IteratorBase implementation.
125 Interval::IteratorBase::IteratorBase(Interval* interval)
126 : interval_(interval), within_bounds_(!interval->empty_), step_(0) {}
127
128 Interval::IteratorBase& Interval::IteratorBase::operator++() {
129 current_index_ += step_;
130 within_bounds_ = IsWithinBounds();
131
132 return *this;
133 }
134
135 // Interval::Iterator implementation.
136 Interval::Iterator::Iterator(Interval* interval)
137 : Interval::IteratorBase(interval) {
138 step_ = (interval_->start_ <= interval_->end_) ? 1 : -1;
139 current_index_ = interval_->start_;
140 }
141
142 bool Interval::Iterator::IsWithinBounds() {
143 if (step_ == 1) {
144 DCHECK(current_index_ >= interval_->start_);
145
146 if (interval_->start_ == interval_->end_ ||
147 current_index_ > interval_->end_)
148 return false;
149
150 return true;
151 } else {
152 DCHECK(current_index_ <= interval_->start_);
153
154 if (interval_->start_ == interval_->end_ ||
155 current_index_ < interval_->end_)
156 return false;
157
158 return true;
159 }
160 }
161
162 // Interval::ReverseIterator implementation.
163 Interval::ReverseIterator::ReverseIterator(Interval* interval)
164 : Interval::IteratorBase(interval) {
165 step_ = (interval_->start_ <= interval_->end_) ? -1 : 1;
166 current_index_ = interval_->end_;
167 }
168
169 bool Interval::ReverseIterator::IsWithinBounds() {
170 if (step_ == 1) {
171 DCHECK(current_index_ >= interval_->end_);
172
173 if (interval_->start_ == interval_->end_ ||
174 current_index_ > interval_->start_)
175 return false;
176
177 return true;
178 } else {
179 DCHECK(current_index_ <= interval_->end_);
180
181 if (interval_->start_ == interval_->end_ ||
182 current_index_ < interval_->start_)
183 return false;
184
185 return true;
186 }
187 }
188
189 // LinearSequence implementation.
190 LinearSequence::LinearSequence(bool forward_direction,
191 std::unique_ptr<Interval> interval,
192 std::unique_ptr<Interval> affinity_interval,
193 std::unique_ptr<Interval> inflate_limit)
194 : forward_direction_(forward_direction),
195 interval_(std::move(interval)),
196 inflate_limit_(std::move(inflate_limit)),
197 affinity_interval_(std::move(affinity_interval)),
198 initial_interval_(std::unique_ptr<Interval>(
199 new Interval(interval_->start(), interval_->end()))) {
200 TrisectInterval();
201 }
202
203 LinearSequence::~LinearSequence() = default;
204
205 LinearSequence::Iterator* LinearSequence::Begin() {
206 return new Iterator(this);
207 }
208
209 LinearSequence::ReverseIterator* LinearSequence::ReverseBegin() {
210 return new ReverseIterator(this);
211 }
212
213 void LinearSequence::InflateToLevel(int level) {
214 if (forward_direction_) {
215 initial_interval_->ForwardInflate(level, interval_.get());
216 interval_->ForwardClampTo(inflate_limit_.get());
217 } else {
218 initial_interval_->BackwardInflate(level, interval_.get());
219 interval_->BackwardClampTo(inflate_limit_.get());
220 }
221
222 TrisectInterval();
223 }
224
225 void LinearSequence::TrisectInterval() {
226 if (interval_->IsEmpty()) {
227 affinity_sub_interval_ = Interval();
228 before_sub_interval_ = Interval();
229 after_sub_interval_ = Interval();
230 return;
231 }
232
233 if (forward_direction_) {
234 affinity_sub_interval_ = *(affinity_interval_.get());
235 if (affinity_sub_interval_.Intersects(interval_.get())) {
236 affinity_sub_interval_.Intersect(interval_.get());
237
238 // Compute before sub-interval.
239 if (affinity_sub_interval_.start() > interval_->start())
240 before_sub_interval_ =
241 Interval(affinity_sub_interval_.start() - 1, interval_->start());
242 else if (affinity_sub_interval_.start() == interval_->start())
243 before_sub_interval_ = Interval();
244
245 // Compute after sub-interval.
246 if (affinity_sub_interval_.end() < interval_->end())
247 after_sub_interval_ =
248 Interval(affinity_sub_interval_.end() + 1, interval_->end());
249 else if (affinity_sub_interval_.end() == interval_->end())
250 after_sub_interval_ = Interval();
251 } else {
252 // The affinity interval is either before or after the |interval_|.
253 if (affinity_sub_interval_.end() < interval_->start()) {
254 before_sub_interval_ = Interval();
255 after_sub_interval_ = *(interval_.get());
256 } else {
257 after_sub_interval_ = Interval();
258 before_sub_interval_ = Interval(interval_->end(), interval_->start());
259 }
260
261 affinity_sub_interval_ = Interval();
262 }
263 } else {
264 affinity_sub_interval_ = *(affinity_interval_.get());
265 if (affinity_sub_interval_.Intersects(interval_.get())) {
266 affinity_sub_interval_.Intersect(interval_.get());
267
268 // Compute before sub-interval.
269 if (affinity_sub_interval_.start() < interval_->start())
270 before_sub_interval_ =
271 Interval(affinity_sub_interval_.start() + 1, interval_->start());
272 else if (affinity_sub_interval_.start() == interval_->start())
273 before_sub_interval_ = Interval();
274
275 // Compute after sub-interval.
276 if (affinity_sub_interval_.end() > interval_->end())
277 after_sub_interval_ =
278 Interval(affinity_sub_interval_.end() - 1, interval_->end());
279 else if (affinity_sub_interval_.end() == interval_->end())
280 after_sub_interval_ = Interval();
281 } else {
282 // The affinity interval is either before or after the |interval_|.
283 if (affinity_sub_interval_.end() > interval_->start()) {
284 before_sub_interval_ = Interval();
285 after_sub_interval_ = *(interval_.get());
286 } else {
287 after_sub_interval_ = Interval();
288 before_sub_interval_ = Interval(interval_->end(), interval_->start());
289 }
290
291 affinity_sub_interval_ = Interval();
292 }
293 }
294 }
295
296 // LinearSequence::IteratorBase implementation.
297 LinearSequence::IteratorBase::IteratorBase(LinearSequence* level_sequence)
298 : level_sequence_(level_sequence), within_bounds_(true) {}
299
300 LinearSequence::IteratorBase::~IteratorBase() = default;
301
302 LinearSequence::IteratorBase& LinearSequence::IteratorBase::operator++() {
303 if (within_bounds_) {
304 ++(*(sub_interval_iterators_[ENUM_TO_INDEX(
305 current_sub_interval_iterator_)]));
306 current_sub_interval_iterator_ = GetCurrentSubIntervalIteratorType();
307 current_index_ =
308 sub_interval_iterators_[ENUM_TO_INDEX(current_sub_interval_iterator_)]
309 ->index();
310 within_bounds_ = IsWithinBounds();
311 }
312 return *this;
313 }
314
315 bool LinearSequence::IteratorBase::IsWithinBounds() {
316 return *(sub_interval_iterators_[ENUM_TO_INDEX(
317 SubIntervalIteratorType::AFFINITY)]) ||
318 *(sub_interval_iterators_[ENUM_TO_INDEX(
319 SubIntervalIteratorType::BEFORE)]) ||
320 *(sub_interval_iterators_[ENUM_TO_INDEX(
321 SubIntervalIteratorType::AFTER)]);
322 }
323
324 // LinearSequence::Iterator implementation.
325 LinearSequence::Iterator::Iterator(LinearSequence* level_sequence)
326 : LinearSequence::IteratorBase(level_sequence), before_first_(true) {
327 sub_interval_iterators_[ENUM_TO_INDEX(SubIntervalIteratorType::AFFINITY)]
328 .reset(level_sequence_->affinity_sub_interval_.Begin());
329
330 sub_interval_iterators_[ENUM_TO_INDEX(SubIntervalIteratorType::BEFORE)].reset(
331 level_sequence_->before_sub_interval_.Begin());
332
333 sub_interval_iterators_[ENUM_TO_INDEX(SubIntervalIteratorType::AFTER)].reset(
334 level_sequence_->after_sub_interval_.Begin());
335
336 current_sub_interval_iterator_ = GetCurrentSubIntervalIteratorType();
337 current_index_ =
338 sub_interval_iterators_[ENUM_TO_INDEX(current_sub_interval_iterator_)]
339 ->index();
340 }
341
342 LinearSequence::Iterator::~Iterator() = default;
343
344 LinearSequence::IteratorBase::SubIntervalIteratorType
345 LinearSequence::Iterator::GetCurrentSubIntervalIteratorType() {
346 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
347 SubIntervalIteratorType::AFFINITY)]))
348 return SubIntervalIteratorType::AFFINITY;
349
350 if (before_first_) {
351 before_first_ = false;
352 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
353 SubIntervalIteratorType::BEFORE)]))
354 return SubIntervalIteratorType::BEFORE;
355
356 return SubIntervalIteratorType::AFTER;
357 } else {
358 before_first_ = true;
359 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
360 SubIntervalIteratorType::AFTER)]))
361 return SubIntervalIteratorType::AFTER;
362
363 return SubIntervalIteratorType::BEFORE;
364 }
365 }
366
367 // LinearSequence::ReverseIterator implementation.
368 LinearSequence::ReverseIterator::ReverseIterator(LinearSequence* level_sequence)
369 : LinearSequence::IteratorBase(level_sequence),
370 after_first_(true),
371 before_sub_interval_span_(
372 level_sequence_->before_sub_interval_.GetSpan()),
373 after_sub_interval_span_(level_sequence_->after_sub_interval_.GetSpan()) {
374 sub_interval_iterators_[ENUM_TO_INDEX(SubIntervalIteratorType::AFFINITY)]
375 .reset(level_sequence_->affinity_sub_interval_.ReverseBegin());
376
377 sub_interval_iterators_[ENUM_TO_INDEX(SubIntervalIteratorType::BEFORE)].reset(
378 level_sequence_->before_sub_interval_.ReverseBegin());
379
380 sub_interval_iterators_[ENUM_TO_INDEX(SubIntervalIteratorType::AFTER)].reset(
381 level_sequence_->after_sub_interval_.ReverseBegin());
382
383 current_sub_interval_iterator_ = GetCurrentSubIntervalIteratorType();
384 current_index_ =
385 sub_interval_iterators_[ENUM_TO_INDEX(current_sub_interval_iterator_)]
386 ->index();
387 }
388
389 LinearSequence::ReverseIterator::~ReverseIterator() = default;
390
391 LinearSequence::IteratorBase::SubIntervalIteratorType
392 LinearSequence::ReverseIterator::GetCurrentSubIntervalIteratorType() {
393 if (before_sub_interval_span_ > after_sub_interval_span_) {
394 --before_sub_interval_span_;
395 return SubIntervalIteratorType::BEFORE;
396 } else if (before_sub_interval_span_ < after_sub_interval_span_) {
397 --after_sub_interval_span_;
398 return SubIntervalIteratorType::AFTER;
399 } else {
400 if (after_first_) {
401 after_first_ = false;
402 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
403 SubIntervalIteratorType::AFTER)]))
404 return SubIntervalIteratorType::AFTER;
405
406 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
407 SubIntervalIteratorType::BEFORE)]))
408 return SubIntervalIteratorType::BEFORE;
409 } else {
410 after_first_ = true;
411 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
412 SubIntervalIteratorType::BEFORE)]))
413 return SubIntervalIteratorType::BEFORE;
414
415 if (*(sub_interval_iterators_[ENUM_TO_INDEX(
416 SubIntervalIteratorType::AFTER)]))
417 return SubIntervalIteratorType::AFTER;
418 }
419 }
420
421 return SubIntervalIteratorType::AFFINITY;
422 }
423
424 // TriangularSequence implementation.
425 TriangularSequence::TriangularSequence(
426 CoverageDirection coverage_direction,
427 std::unique_ptr<LinearSequence> traversal_sequence,
428 std::unique_ptr<Interval> level_interval,
429 bool should_swap_index_representation,
430 int levels_to_skip,
431 int distance)
432 : coverage_direction_(coverage_direction),
433 traversal_sequence_(std::move(traversal_sequence)),
434 level_interval_(std::move(level_interval)),
435 should_swap_index_representation_(should_swap_index_representation),
436 levels_to_skip_(levels_to_skip),
437 distance_(distance) {}
438
439 TriangularSequence::~TriangularSequence() = default;
440
441 TriangularSequence::Iterator* TriangularSequence::Begin() {
442 return new Iterator(this);
443 }
444
445 TriangularSequence::ReverseIterator* TriangularSequence::ReverseBegin() {
446 return new ReverseIterator(this);
447 }
448
449 // TriangularSequence::IteratorBase implementation.
450 TriangularSequence::IteratorBase::IteratorBase(
451 TriangularSequence* triangular_sequence)
452 : should_swap_index_representation_(
453 triangular_sequence->should_swap_index_representation_) {
454 DCHECK_NE(triangular_sequence->coverage_direction_, CoverageDirection::NONE);
455 std::unique_ptr<Interval::Iterator> level_interval_it(
456 triangular_sequence->level_interval_->Begin());
457 traversal_sequence_ = triangular_sequence->traversal_sequence_.get();
458 int span = triangular_sequence->level_interval_->GetSpan();
459 DCHECK_GE(span, triangular_sequence->levels_to_skip_);
460
461 // Skip |levels_to_skip| levels in level interval.
462 for (int i = 0; i < triangular_sequence->levels_to_skip_; ++i)
463 ++(*level_interval_it);
464
465 for (int i = triangular_sequence->levels_to_skip_; i < span; ++i) {
466 level_distances_.push_back(LevelDistance(
467 i, level_interval_it->index(), triangular_sequence->distance_ * i));
468 ++(*level_interval_it);
469 }
470 }
471
472 TriangularSequence::IteratorBase::~IteratorBase() = default;
473
474 TriangularSequence::IteratorBase& TriangularSequence::IteratorBase::
475 operator++() {
476 Advance();
477 UpdateCurrent();
478
479 return *this;
480 }
481
482 // TriangularSequence::Iterator implementation.
483 TriangularSequence::Iterator::Iterator(TriangularSequence* triangular_sequence)
484 : TriangularSequence::IteratorBase(triangular_sequence) {
485 UpdateCurrent();
486 }
487
488 int TriangularSequence::Iterator::GetNextDistance() const {
489 DCHECK(*this);
490 return level_distances_.front().distance;
491 }
492
493 void TriangularSequence::Iterator::Advance() {
494 if (!*this)
495 return;
496
497 level_distances_.erase(level_distances_.begin());
498 }
499
500 void TriangularSequence::Iterator::UpdateCurrent() {
501 if (!*this)
502 return;
503
504 current_level_index_ = level_distances_.front().level_index;
505 traversal_sequence_->InflateToLevel(level_distances_.front().interval_level);
506 }
507
508 // TriangularSequence::ReverseIterator implementation.
509 TriangularSequence::ReverseIterator::ReverseIterator(
510 TriangularSequence* triangular_sequence)
511 : TriangularSequence::IteratorBase(triangular_sequence) {
512 UpdateCurrent();
513 }
514
515 int TriangularSequence::ReverseIterator::GetNextDistance() const {
516 DCHECK(!level_distances_.empty());
517 return level_distances_.back().distance;
518 }
519
520 void TriangularSequence::ReverseIterator::Advance() {
521 if (!*this)
522 return;
523
524 level_distances_.erase(level_distances_.end() - 1);
525 }
526
527 void TriangularSequence::ReverseIterator::UpdateCurrent() {
528 if (!*this)
529 return;
530
531 current_level_index_ = level_distances_.back().level_index;
532 traversal_sequence_->InflateToLevel(level_distances_.back().interval_level);
533 }
534
535 // PyramidSequence implementation.
536 PyramidSequence::PyramidSequence(const IndexRect& around_index_rect,
537 const IndexRect& consider_index_rect,
538 const IndexRect& ignore_index_rect,
539 int width,
540 int height)
541 : consider_index_rect_(consider_index_rect),
542 ignore_index_rect_(ignore_index_rect) {
543 // Compute center_index_rect and if it is valid (i.e. |around_index_rect| is
544 // really around some index_rect) and both |consider_index_rect| and
545 // |ignore_index_rect| are valid, then proceed, otherwise keep the pyramid
546 // sequence empty.
547
548 IndexRect center_index_rect(around_index_rect);
549 center_index_rect.Inset(1, 1, 1, 1);
550 if (!center_index_rect.is_valid() || !consider_index_rect.is_valid() ||
551 !ignore_index_rect.is_valid())
552 return;
553
554 // Compute the max possible levels along all directions.
555 int left_levels = around_index_rect.left() - consider_index_rect_.left() + 1;
556 int right_levels =
557 consider_index_rect_.right() - around_index_rect.right() + 1;
558 int top_levels = around_index_rect.top() - consider_index_rect_.top() + 1;
559 int bottom_levels =
560 consider_index_rect_.bottom() - around_index_rect.bottom() + 1;
561
562 // When center_index_rect and consider_index_rect are non-intersecting, then
563 // we need to compute the levels to skip for avoiding traversal of levels
564 // which do not fall in consider_index_rect. The pyramid sequence adds
565 // diagonal indices to left and right directions and no diagonal indices for
566 // top and bottom directions, so while considering skip levels for top/bottom,
567 // we need to consider maximum of levels to skip "along" the top/bottom
568 // directions and levels to skip "cross" left/right directions and for
569 // considering skip levels for left/right, we need to consider maximum of
570 // levels to skip "along" the left/right directions and levels to skip "along"
571 // top/bottom directions.
572 // Compute the levels to skip along and cross all directions.
573 int skip_levels_along_left =
574 around_index_rect.left() - consider_index_rect_.right();
575 int skip_levels_along_right =
576 consider_index_rect_.left() - around_index_rect.right();
577 int skip_levels_along_top =
578 around_index_rect.top() - consider_index_rect_.bottom();
579 int skip_levels_along_bottom =
580 consider_index_rect_.top() - around_index_rect.bottom();
581 int skip_levels_cross_left =
582 LevelsToSkipCrossDirection(skip_levels_along_left);
583 int skip_levels_cross_right =
584 LevelsToSkipCrossDirection(skip_levels_along_right);
585 skip_levels_along_left = LevelsToSkipAlongDirection(skip_levels_along_left);
586 skip_levels_along_right = LevelsToSkipAlongDirection(skip_levels_along_right);
587 skip_levels_along_top = LevelsToSkipAlongDirection(skip_levels_along_top);
588 skip_levels_along_bottom =
589 LevelsToSkipAlongDirection(skip_levels_along_bottom);
590
591 DCHECK(triangular_sequences_.empty());
592 triangular_sequences_.resize(ENUM_TO_INDEX(CoverageDirection::SIZE));
593 CoverageDirection* positions = GetCoverageDirectionSequence();
594 DCHECK(positions);
595
596 #define NEW_UNIQUE(type, val) std::unique_ptr<type>(new val)
597
598 // Add triangular sequences for all directions.
599 // RIGHT sequence.
600 if (right_levels > 0) {
601 int start = around_index_rect.bottom();
602 int end = around_index_rect.top();
603 int skip_levels =
604 std::max(skip_levels_along_right,
605 std::max(skip_levels_along_bottom, skip_levels_along_top));
606 if (right_levels > skip_levels) {
607 EmplaceAt(
608 GetPositionForDirection(positions, CoverageDirection::RIGHT),
609 NEW_UNIQUE(
610 TriangularSequence,
611 TriangularSequence(
612 CoverageDirection::RIGHT,
613 NEW_UNIQUE(
614 LinearSequence,
615 LinearSequence(
616 false, NEW_UNIQUE(Interval, Interval(start, end)),
617 NEW_UNIQUE(Interval,
618 Interval(center_index_rect.bottom(),
619 center_index_rect.top())),
620 NEW_UNIQUE(Interval,
621 Interval(consider_index_rect_.bottom(),
622 consider_index_rect_.top())))),
623 NEW_UNIQUE(Interval, Interval(around_index_rect.right(),
624 consider_index_rect_.right())),
625 true, skip_levels, width)));
626 }
627 }
628
629 // TOP sequence.
630 if (top_levels > 0) {
631 int start = around_index_rect.right() - 1;
632 int end = around_index_rect.left() + 1;
633 int skip_levels =
634 std::max(skip_levels_along_top,
635 std::max(skip_levels_cross_right, skip_levels_cross_left));
636 if (top_levels > skip_levels) {
637 EmplaceAt(
638 GetPositionForDirection(positions, CoverageDirection::TOP),
639 NEW_UNIQUE(
640 TriangularSequence,
641 TriangularSequence(
642 CoverageDirection::TOP,
643 NEW_UNIQUE(
644 LinearSequence,
645 LinearSequence(
646 false, NEW_UNIQUE(Interval, Interval(start, end)),
647 NEW_UNIQUE(Interval,
648 Interval(center_index_rect.right(),
649 center_index_rect.left())),
650 NEW_UNIQUE(Interval,
651 Interval(consider_index_rect_.right(),
652 consider_index_rect_.left())))),
653 NEW_UNIQUE(Interval, Interval(around_index_rect.top(),
654 consider_index_rect_.top())),
655 false, skip_levels, height)));
656 }
657 }
658
659 // LEFT sequence.
660 if (left_levels > 0) {
661 int start = around_index_rect.top();
662 int end = around_index_rect.bottom();
663 int skip_levels =
664 std::max(skip_levels_along_left,
665 std::max(skip_levels_along_top, skip_levels_along_bottom));
666 if (left_levels > skip_levels) {
667 EmplaceAt(
668 GetPositionForDirection(positions, CoverageDirection::LEFT),
669 NEW_UNIQUE(
670 TriangularSequence,
671 TriangularSequence(
672 CoverageDirection::LEFT,
673 NEW_UNIQUE(
674 LinearSequence,
675 LinearSequence(
676 true, NEW_UNIQUE(Interval, Interval(start, end)),
677 NEW_UNIQUE(Interval,
678 Interval(center_index_rect.top(),
679 center_index_rect.bottom())),
680 NEW_UNIQUE(Interval,
681 Interval(consider_index_rect_.top(),
682 consider_index_rect_.bottom())))),
683 NEW_UNIQUE(Interval, Interval(around_index_rect.left(),
684 consider_index_rect_.left())),
685 true, skip_levels, width)));
686 }
687 }
688
689 // BOTTOM sequence.
690 if (bottom_levels > 0) {
691 int start = around_index_rect.left() + 1;
692 int end = around_index_rect.right() - 1;
693 int skip_levels =
694 std::max(skip_levels_along_bottom,
695 std::max(skip_levels_cross_left, skip_levels_cross_right));
696 if (bottom_levels > skip_levels) {
697 EmplaceAt(
698 GetPositionForDirection(positions, CoverageDirection::BOTTOM),
699 NEW_UNIQUE(
700 TriangularSequence,
701 TriangularSequence(
702 CoverageDirection::BOTTOM,
703 NEW_UNIQUE(
704 LinearSequence,
705 LinearSequence(
706 true, NEW_UNIQUE(Interval, Interval(start, end)),
707 NEW_UNIQUE(Interval,
708 Interval(center_index_rect.left(),
709 center_index_rect.right())),
710 NEW_UNIQUE(Interval,
711 Interval(consider_index_rect_.left(),
712 consider_index_rect_.right())))),
713 NEW_UNIQUE(Interval, Interval(around_index_rect.bottom(),
714 consider_index_rect_.bottom())),
715 false, skip_levels, height)));
716 }
717 }
718
719 // Remove dummy triangular sequences.
720 triangular_sequences_.erase(
721 std::remove_if(
722 triangular_sequences_.begin(), triangular_sequences_.end(),
723 [](const std::unique_ptr<TriangularSequence>& triangular_sequence) {
724 return triangular_sequence.get() == nullptr;
725 }),
726 triangular_sequences_.end());
727 }
728
729 PyramidSequence::~PyramidSequence() = default;
730
731 PyramidSequence::Iterator* PyramidSequence::Begin() {
732 return new Iterator(this);
733 }
734
735 PyramidSequence::ReverseIterator* PyramidSequence::ReverseBegin() {
736 return new ReverseIterator(this);
737 }
738
739 void PyramidSequence::EmplaceAt(
740 int position,
741 std::unique_ptr<TriangularSequence> triangular_sequence) {
742 triangular_sequences_[position] = std::move(triangular_sequence);
743 }
744
745 // PyramidSequence::IteratorBase implementation.
746 PyramidSequence::IteratorBase::IteratorBase(
747 const IndexRect& consider_index_rect,
748 const IndexRect& ignore_index_rect)
749 : consider_index_rect_(consider_index_rect),
750 ignore_index_rect_(ignore_index_rect),
751 current_triangular_sequence_it_(nullptr) {}
752
753 PyramidSequence::IteratorBase::~IteratorBase() = default;
754
755 PyramidSequence::IteratorBase::operator bool() const {
756 return current_triangular_sequence_it_ && !IsEmpty();
757 }
758
759 PyramidSequence::IteratorBase& PyramidSequence::IteratorBase::operator++() {
760 Advance();
761 UpdateCurrent();
762
763 return *this;
764 }
765
766 // PyramidSequence::Iterator implementation.
767 PyramidSequence::Iterator::Iterator(PyramidSequence* pyramid_sequence)
768 : PyramidSequence::IteratorBase(pyramid_sequence->consider_index_rect_,
769 pyramid_sequence->ignore_index_rect_) {
770 for (TriangularSequence::Vector::iterator it =
771 pyramid_sequence->triangular_sequences_.begin();
772 it != pyramid_sequence->triangular_sequences_.end(); ++it) {
773 DCHECK(it->get()->coverage_direction() != CoverageDirection::NONE);
774 triangular_sequence_iterators_.emplace_back(it->get()->Begin());
775 }
776
777 current_triangular_sequence_it_ = GetNextTriangularSequenceIterator();
778 if (current_triangular_sequence_it_) {
779 if (*current_triangular_sequence_it_) {
780 current_traversal_sequence_iterator_ =
781 current_triangular_sequence_it_->traversal_sequence()->Begin();
782 }
783
784 UpdateCurrent();
785 }
786 }
787
788 PyramidSequence::Iterator::~Iterator() = default;
789
790 bool PyramidSequence::Iterator::IsEmpty() const {
791 return triangular_sequence_iterators_.empty();
792 }
793
794 void PyramidSequence::Iterator::Advance() {
795 if (!*this)
796 return;
797
798 ++(*current_traversal_sequence_iterator_);
799 if (!(*current_traversal_sequence_iterator_)) {
800 ++(*current_triangular_sequence_it_);
801 current_triangular_sequence_it_ = GetNextTriangularSequenceIterator();
802 if (current_triangular_sequence_it_) {
803 current_traversal_sequence_iterator_ =
804 current_triangular_sequence_it_->traversal_sequence()->Begin();
805 }
806 }
807 }
808
809 void PyramidSequence::Iterator::UpdateCurrent() {
810 while (*this) {
811 if (*current_traversal_sequence_iterator_) {
812 if (current_triangular_sequence_it_->is_index_representation_swapped()) {
813 index_x_ = current_triangular_sequence_it_->level_index();
814 index_y_ = current_traversal_sequence_iterator_->index();
815 } else {
816 index_x_ = current_traversal_sequence_iterator_->index();
817 index_y_ = current_triangular_sequence_it_->level_index();
818 }
819
820 if (consider_index_rect_.Contains(index_x_, index_y_) &&
821 !ignore_index_rect_.Contains(index_x_, index_y_))
822 break;
823 }
824
825 Advance();
826 }
827 }
828
829 TriangularSequence::IteratorBase*
830 PyramidSequence::Iterator::GetNextTriangularSequenceIterator() {
831 // Remove traversed TriangularSequence::Iterator(s).
832 triangular_sequence_iterators_.erase(
833 std::remove_if(
834 triangular_sequence_iterators_.begin(),
835 triangular_sequence_iterators_.end(),
836 [](const std::unique_ptr<TriangularSequence::Iterator>& it) {
837 return !(*(it.get()));
838 }),
839 triangular_sequence_iterators_.end());
840
841 if (triangular_sequence_iterators_.empty())
842 return nullptr;
843
844 std::vector<std::unique_ptr<TriangularSequence::Iterator>>::iterator
845 min_distance_it = triangular_sequence_iterators_.begin();
846
847 for (std::vector<std::unique_ptr<TriangularSequence::Iterator>>::iterator it =
848 triangular_sequence_iterators_.begin();
849 it != triangular_sequence_iterators_.end(); ++it) {
850 int distance = it->get()->GetNextDistance();
851 if (distance == 0) {
852 min_distance_it = it;
853 break;
854 }
855
856 if (min_distance_it->get()->GetNextDistance() > distance)
857 min_distance_it = it;
858 }
859
860 return min_distance_it->get();
861 }
862
863 // PyramidSequence::ReverseIterator implementation.
864 PyramidSequence::ReverseIterator::ReverseIterator(
865 PyramidSequence* pyramid_sequence)
866 : PyramidSequence::IteratorBase(pyramid_sequence->consider_index_rect_,
867 pyramid_sequence->ignore_index_rect_) {
868 for (TriangularSequence::Vector::iterator it =
869 pyramid_sequence->triangular_sequences_.begin();
870 it != pyramid_sequence->triangular_sequences_.end(); ++it) {
871 triangular_sequence_reverse_iterators_.emplace_back(
872 it->get()->ReverseBegin());
873 }
874
875 current_triangular_sequence_it_ = GetNextTriangularSequenceReverseIterator();
876 if (current_triangular_sequence_it_) {
877 if (*current_triangular_sequence_it_) {
878 current_traversal_sequence_reverse_iterator_ =
879 current_triangular_sequence_it_->traversal_sequence()->ReverseBegin();
880 }
881 UpdateCurrent();
882 }
883 }
884
885 PyramidSequence::ReverseIterator::~ReverseIterator() = default;
886
887 bool PyramidSequence::ReverseIterator::IsEmpty() const {
888 return triangular_sequence_reverse_iterators_.empty();
889 }
890
891 void PyramidSequence::ReverseIterator::Advance() {
892 if (!*this)
893 return;
894
895 ++(*current_traversal_sequence_reverse_iterator_);
896 if (!(*current_traversal_sequence_reverse_iterator_)) {
897 ++(*current_triangular_sequence_it_);
898 current_triangular_sequence_it_ =
899 GetNextTriangularSequenceReverseIterator();
900 if (current_triangular_sequence_it_) {
901 current_traversal_sequence_reverse_iterator_ =
902 current_triangular_sequence_it_->traversal_sequence()->ReverseBegin();
903 }
904 }
905 }
906
907 void PyramidSequence::ReverseIterator::UpdateCurrent() {
908 while (*this) {
909 if ((*current_traversal_sequence_reverse_iterator_)) {
910 if (current_triangular_sequence_it_->is_index_representation_swapped()) {
911 index_x_ = current_triangular_sequence_it_->level_index();
912 index_y_ = current_traversal_sequence_reverse_iterator_->index();
913 } else {
914 index_x_ = current_traversal_sequence_reverse_iterator_->index();
915 index_y_ = current_triangular_sequence_it_->level_index();
916 }
917
918 if (consider_index_rect_.Contains(index_x_, index_y_) &&
919 !ignore_index_rect_.Contains(index_x_, index_y_))
920 break;
921 }
922
923 Advance();
924 }
925 }
926
927 TriangularSequence::IteratorBase*
928 PyramidSequence::ReverseIterator::GetNextTriangularSequenceReverseIterator() {
929 // Remove traversed TriangularSequence::ReverseIterator(s).
930 triangular_sequence_reverse_iterators_.erase(
931 std::remove_if(
932 triangular_sequence_reverse_iterators_.begin(),
933 triangular_sequence_reverse_iterators_.end(),
934 [](const std::unique_ptr<TriangularSequence::ReverseIterator>& it) {
935 return !(*(it.get()));
936 }),
937 triangular_sequence_reverse_iterators_.end());
938
939 if (triangular_sequence_reverse_iterators_.empty())
940 return nullptr;
941
942 std::vector<std::unique_ptr<TriangularSequence::ReverseIterator>>::
943 reverse_iterator max_distance_it =
944 triangular_sequence_reverse_iterators_.rbegin();
945
946 for (std::vector<std::unique_ptr<TriangularSequence::ReverseIterator>>::
947 reverse_iterator it =
948 triangular_sequence_reverse_iterators_.rbegin();
949 it != triangular_sequence_reverse_iterators_.rend(); ++it) {
950 int distance = it->get()->GetNextDistance();
951
952 if (max_distance_it->get()->GetNextDistance() < distance)
953 max_distance_it = it;
954 }
955
956 return max_distance_it->get();
957 }
958
959 } // namespace internal
960
961 PyramidSequence::PyramidSequence() {}
962
963 PyramidSequence::PyramidSequence(const IndexRect& around_index_rect,
964 const IndexRect& consider_index_rect,
965 const IndexRect& ignore_index_rect,
966 int width,
967 int height)
968 : ptr_(new internal::PyramidSequence(around_index_rect,
969 consider_index_rect,
970 ignore_index_rect,
971 width,
972 height)) {}
973
974 PyramidSequence::PyramidSequence(const PyramidSequence& other) = default;
975
976 PyramidSequence::PyramidSequence(PyramidSequence&& other) = default;
977
978 PyramidSequence::~PyramidSequence() = default;
979
980 PyramidSequence& PyramidSequence::operator=(const PyramidSequence& other) =
981 default;
982
983 PyramidSequence& PyramidSequence::operator=(PyramidSequence&& other) = default;
984
985 PyramidSequence::Iterator PyramidSequence::Begin() {
986 return Iterator(ptr_->Begin());
987 }
988
989 PyramidSequence::ReverseIterator PyramidSequence::ReverseBegin() {
990 return ReverseIterator(ptr_->ReverseBegin());
991 }
992
993 // iterator
994 PyramidSequence::Iterator::Iterator() {}
995
996 PyramidSequence::Iterator::Iterator(internal::PyramidSequence::Iterator* ptr)
997 : ptr_(ptr) {}
998
999 PyramidSequence::Iterator::Iterator(const PyramidSequence::Iterator& other) =
1000 default;
1001
1002 PyramidSequence::Iterator::Iterator(PyramidSequence::Iterator&& other) =
1003 default;
1004
1005 PyramidSequence::Iterator::~Iterator() = default;
1006
1007 PyramidSequence::Iterator& PyramidSequence::Iterator::operator=(
1008 const PyramidSequence::Iterator& other) = default;
1009
1010 PyramidSequence::Iterator& PyramidSequence::Iterator::operator=(
1011 PyramidSequence::Iterator&& other) = default;
1012
1013 PyramidSequence::Iterator::operator bool() const {
1014 return *ptr_;
1015 }
1016
1017 PyramidSequence::Iterator& PyramidSequence::Iterator::operator++() {
1018 ++(*ptr_);
1019 return *this;
1020 }
1021
1022 int PyramidSequence::Iterator::index_x() const {
1023 return ptr_->index_x();
1024 }
1025
1026 int PyramidSequence::Iterator::index_y() const {
1027 return ptr_->index_y();
1028 }
1029
1030 // reverse
1031 PyramidSequence::ReverseIterator::ReverseIterator() {}
1032
1033 PyramidSequence::ReverseIterator::ReverseIterator(
1034 internal::PyramidSequence::ReverseIterator* ptr)
1035 : ptr_(ptr) {}
1036
1037 PyramidSequence::ReverseIterator::ReverseIterator(
1038 const PyramidSequence::ReverseIterator& other) = default;
1039
1040 PyramidSequence::ReverseIterator::ReverseIterator(
1041 PyramidSequence::ReverseIterator&& other) = default;
1042
1043 PyramidSequence::ReverseIterator::~ReverseIterator() = default;
1044
1045 PyramidSequence::ReverseIterator& PyramidSequence::ReverseIterator::operator=(
1046 const PyramidSequence::ReverseIterator& other) = default;
1047
1048 PyramidSequence::ReverseIterator& PyramidSequence::ReverseIterator::operator=(
1049 PyramidSequence::ReverseIterator&& other) = default;
1050
1051 PyramidSequence::ReverseIterator::operator bool() const {
1052 return *ptr_;
1053 }
1054
1055 PyramidSequence::ReverseIterator& PyramidSequence::ReverseIterator::
1056 operator++() {
1057 ++(*ptr_);
1058 return *this;
1059 }
1060
1061 int PyramidSequence::ReverseIterator::index_x() const {
1062 return ptr_->index_x();
1063 }
1064
1065 int PyramidSequence::ReverseIterator::index_y() const {
1066 return ptr_->index_y();
1067 }
1068
1069 } // namespace cc
OLDNEW
« no previous file with comments | « cc/base/pyramid_sequence.h ('k') | cc/base/pyramid_sequence_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698