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

Unified 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: spiral coverage sequence Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: cc/base/pyramid_sequence.cc
diff --git a/cc/base/pyramid_sequence.cc b/cc/base/pyramid_sequence.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5f13eb821f79c1090b67a0b8b2cc2d7026999655
--- /dev/null
+++ b/cc/base/pyramid_sequence.cc
@@ -0,0 +1,722 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/base/pyramid_sequence.h"
+
+#include <algorithm>
+#include <string>
+
+namespace cc {
+
+namespace {
+
+int ClampNumberInForwardInterval(int number, int start_limit, int end_limit) {
+ DCHECK_LE(start_limit, end_limit);
+ if (number < start_limit)
+ return start_limit;
+ if (number > end_limit)
+ return end_limit;
+ return number;
+}
+
+int ClampNumberInBackwardInterval(int number, int start_limit, int end_limit) {
+ DCHECK_GE(start_limit, end_limit);
+ if (number > start_limit)
+ return start_limit;
+ if (number < end_limit)
+ return end_limit;
+ return number;
+}
+
+int LevelsToSkipAlongDirection(int levels) {
+ return levels > 0 ? levels : 0;
+}
+
+int LevelsToSkipPerpendicularToDirection(int levels) {
+ return levels >= 0 ? levels + 1 : 0;
+}
+
+enum class CoverageDirection : uint8_t {
+ RIGHT = 0,
+ TOP_RIGHT,
+ TOP,
+ TOP_LEFT,
+ LEFT,
+ BOTTOM_LEFT,
+ BOTTOM,
+ BOTTOM_RIGHT
+};
+
+// The pyramid sequence covers following 8 directions while iterating.
+// TL T TR
+// L * R
+// BL B BR
+//
+// where -
+// R = right
+// TR = top right
+// T = top
+// TL = top left
+// L = left
+// BL = bottom left
+// B = bottom
+// BR = bottom right
+//
+// The following function returns the spiral order {R, TR, T, TL, L, BL, B, BR}.
+CoverageDirection* GetCoverageDirectionSequence() {
+ static CoverageDirection right_top_right[8] = {
+ CoverageDirection::RIGHT, CoverageDirection::TOP_RIGHT,
+ CoverageDirection::TOP, CoverageDirection::TOP_LEFT,
+ CoverageDirection::LEFT, CoverageDirection::BOTTOM_LEFT,
+ CoverageDirection::BOTTOM, CoverageDirection::BOTTOM_RIGHT};
+ return right_top_right;
+}
+
+int GetPositionForDirection(CoverageDirection* positions,
+ CoverageDirection direction) {
+ for (int i = 0; i < 8; ++i) {
+ if (positions[i] == direction)
+ return i;
+ }
+
+ NOTREACHED();
+ return -1;
+}
+
+} // namespace
+
+// Interval implementation.
+Interval::Interval(Type type,
+ int start,
+ int end,
+ int start_inflate_limit,
+ int end_inflate_limit,
+ bool reverse_order)
+ : start_(start),
+ end_(end),
+ initial_start_(start),
+ initial_end_(end),
+ start_inflate_limit_(start_inflate_limit),
+ end_inflate_limit_(end_inflate_limit),
+ reverse_order_(reverse_order),
+ within_bounds_(true),
+ inflate_to_level_ptr_(nullptr),
+ is_within_bounds_ptr_(nullptr) {
+ Init(type);
+ Reset();
+}
+
+Interval::Interval(const Interval& other) = default;
+
+Interval::Interval(Interval&& other) = default;
+
+Interval::~Interval() {
+ inflate_to_level_ptr_ = nullptr;
+ is_within_bounds_ptr_ = nullptr;
+}
+
+Interval& Interval::operator=(const Interval& other) = default;
+
+Interval& Interval::operator=(Interval&& other) = default;
+
+Interval& Interval::operator++() {
+ DCHECK(is_within_bounds_ptr_);
+ current_index_ += step_;
+ within_bounds_ = (this->*is_within_bounds_ptr_)();
+
+ return *this;
+}
+
+void Interval::InflateToLevel(int level) {
+ DCHECK(inflate_to_level_ptr_);
+ (this->*inflate_to_level_ptr_)(level);
+}
+
+int Interval::GetSpan() {
+ return std::abs(end_ - start_) + 1;
+}
+
+void Interval::Init(Interval::Type type) {
+ switch (type) {
+ case Interval::Type::FORWARD:
+ inflate_to_level_ptr_ = &Interval::InflateToLevelForward;
+ is_within_bounds_ptr_ = &Interval::IsWithinBoundsForward;
+ step_ = reverse_order_ ? -1 : 1;
+ break;
+ case Interval::Type::BACKWARD:
+ inflate_to_level_ptr_ = &Interval::InflateToLevelBackward;
+ is_within_bounds_ptr_ = &Interval::IsWithinBoundsBackward;
+ step_ = reverse_order_ ? 1 : -1;
+ break;
+ case Interval::Type::DIAGONAL_FORWARD:
+ DCHECK_EQ(start_, end_);
+ inflate_to_level_ptr_ = &Interval::InflateToLevelDiagonalForward;
+ is_within_bounds_ptr_ = &Interval::IsWithinBoundsDiagonal;
+ step_ = reverse_order_ ? -1 : 1;
+ break;
+ case Interval::Type::DIAGONAL_BACKWARD:
+ DCHECK_EQ(start_, end_);
+ inflate_to_level_ptr_ = &Interval::InflateToLevelDiagonalBackward;
+ is_within_bounds_ptr_ = &Interval::IsWithinBoundsDiagonal;
+ step_ = reverse_order_ ? 1 : -1;
+ break;
+ }
+}
+
+void Interval::Reset() {
+ current_index_ = reverse_order_ ? end_ : start_;
+ within_bounds_ = true;
+}
+
+void Interval::InflateToLevelForward(int level) {
+ start_ = initial_start_ - level;
+ end_ = initial_end_ + level;
+
+ start_ = ClampNumberInForwardInterval(start_, start_inflate_limit_,
+ end_inflate_limit_);
+ end_ = ClampNumberInForwardInterval(end_, start_inflate_limit_,
+ end_inflate_limit_);
+
+ Reset();
+}
+
+void Interval::InflateToLevelBackward(int level) {
+ start_ = initial_start_ + level;
+ end_ = initial_end_ - level;
+ start_ = ClampNumberInBackwardInterval(start_, start_inflate_limit_,
+ end_inflate_limit_);
+ end_ = ClampNumberInBackwardInterval(end_, start_inflate_limit_,
+ end_inflate_limit_);
+
+ Reset();
+}
+
+void Interval::InflateToLevelDiagonalForward(int level) {
+ start_ = initial_start_ + level;
+ end_ = initial_end_ + level;
+
+ Reset();
+}
+
+void Interval::InflateToLevelDiagonalBackward(int level) {
+ start_ = initial_start_ - level;
+ end_ = initial_end_ - level;
+
+ Reset();
+}
+
+bool Interval::IsWithinBoundsForward() {
+ DCHECK(reverse_order_ ? current_index_ <= end_ : current_index_ >= start_);
+
+ if (start_ == end_ ||
+ (reverse_order_ ? current_index_ < start_ : current_index_ > end_))
+ return false;
+
+ return true;
+}
+
+bool Interval::IsWithinBoundsBackward() {
+ DCHECK(reverse_order_ ? current_index_ >= end_ : current_index_ <= start_);
+
+ if (start_ == end_ ||
+ (reverse_order_ ? current_index_ > start_ : current_index_ < end_))
+ return false;
+
+ return true;
+}
+
+bool Interval::IsWithinBoundsDiagonal() {
+ DCHECK_EQ(start_, end_);
+ if (current_index_ != start_)
+ return false;
+
+ return true;
+}
+
+// TriangularSequence implementation.
+TriangularSequence::TriangularSequence()
+ : name_(std::string("dummy")),
+ traversal_interval_(Interval::Type::FORWARD, 0, 0, 0, 0, false),
+ swapped_(false),
+ reverse_order_(false),
+ current_level_index_(-1) {}
+
+TriangularSequence::TriangularSequence(std::string&& name,
+ Interval&& traversal_interval,
+ Interval&& level_interval,
+ bool swapped,
+ int levels_to_skip,
+ int distance,
+ bool reverse_order)
+ : name_(std::move(name)),
+ traversal_interval_(std::move(traversal_interval)),
+ swapped_(swapped),
+ reverse_order_(reverse_order) {
+ int span = level_interval.GetSpan();
+ DCHECK_GE(span, levels_to_skip);
+
+ // Skip |levels_to_skip| levels in level interval.
+ for (int i = 0; i < levels_to_skip; ++i)
+ ++level_interval;
+
+ for (int i = levels_to_skip; i < span; ++i) {
+ level_distances_.push_back(
+ LevelDistance(i, level_interval.index(), distance * i));
+ ++level_interval;
+ }
+
+ UpdateCurrent();
+}
+
+TriangularSequence::TriangularSequence(const TriangularSequence& other) =
+ default;
+
+TriangularSequence::TriangularSequence(TriangularSequence&& other) = default;
+
+TriangularSequence::~TriangularSequence() {
+ level_distances_.clear();
+}
+
+TriangularSequence& TriangularSequence::operator=(
+ const TriangularSequence& other) = default;
+
+TriangularSequence& TriangularSequence::operator=(TriangularSequence&& other) =
+ default;
+
+TriangularSequence& TriangularSequence::operator++() {
+ Advance();
+ UpdateCurrent();
+
+ return *this;
+}
+
+int TriangularSequence::GetMinimumDistance() const {
+ DCHECK(!level_distances_.empty());
+ return level_distances_.front().distance;
+}
+
+int TriangularSequence::GetMaximumDistance() const {
+ DCHECK(!level_distances_.empty());
+ return level_distances_.back().distance;
+}
+
+void TriangularSequence::Advance() {
+ if (!*this)
+ return;
+
+ if (reverse_order_)
+ level_distances_.erase(level_distances_.end() - 1);
+ else
+ level_distances_.erase(level_distances_.begin());
+}
+
+void TriangularSequence::UpdateCurrent() {
+ if (!*this)
+ return;
+
+ if (reverse_order_) {
+ current_level_index_ = level_distances_.back().level_index;
+ traversal_interval_.InflateToLevel(level_distances_.back().interval_level);
+ } else {
+ current_level_index_ = level_distances_.front().level_index;
+ traversal_interval_.InflateToLevel(level_distances_.front().interval_level);
+ }
+}
+
+// PyramidSequence implementation.
+PyramidSequence::PyramidSequence(bool reverse_order)
+ : reverse_order_(reverse_order),
+ current_triangular_sequence_(nullptr),
+ index_x_(-1),
+ index_y_(-1) {}
+
+PyramidSequence::PyramidSequence(const PyramidSequence& other) = default;
+
+PyramidSequence::PyramidSequence(PyramidSequence&& other) = default;
+
+PyramidSequence::~PyramidSequence() {
+ triangular_sequences_.clear();
+ current_triangular_sequence_ = nullptr;
+}
+
+PyramidSequence& PyramidSequence::operator=(const PyramidSequence& other) =
+ default;
+
+PyramidSequence& PyramidSequence::operator=(PyramidSequence&& other) = default;
+
+void PyramidSequence::Init(int around_left,
+ int around_right,
+ int around_top,
+ int around_bottom,
+ int consider_left,
+ int consider_right,
+ int consider_top,
+ int consider_bottom,
+ int ignore_left,
+ int ignore_right,
+ int ignore_top,
+ int ignore_bottom,
+ int width,
+ int height) {
+ consider_left_ = consider_left;
+ consider_right_ = consider_right;
+ consider_top_ = consider_top;
+ consider_bottom_ = consider_bottom;
+ ignore_left_ = ignore_left;
+ ignore_right_ = ignore_right;
+ ignore_top_ = ignore_top;
+ ignore_bottom_ = ignore_bottom;
+
+ int left_levels = around_left - consider_left + 1;
+ int right_levels = consider_right - around_right + 1;
+ int top_levels = around_top - consider_top + 1;
+ int bottom_levels = consider_bottom - around_bottom + 1;
+
+ int skip_left_levels = around_left - consider_right;
+ int skip_right_levels = consider_left - around_right;
+ int skip_top_levels = around_top - consider_bottom;
+ int skip_bottom_levels = consider_top - around_bottom;
+
+ int skip_left_levels_perp =
+ LevelsToSkipPerpendicularToDirection(skip_left_levels);
+ int skip_right_levels_perp =
+ LevelsToSkipPerpendicularToDirection(skip_right_levels);
+ int skip_top_levels_perp =
+ LevelsToSkipPerpendicularToDirection(skip_top_levels);
+ int skip_bottom_levels_perp =
+ LevelsToSkipPerpendicularToDirection(skip_bottom_levels);
+
+ skip_left_levels = LevelsToSkipAlongDirection(skip_left_levels);
+ skip_right_levels = LevelsToSkipAlongDirection(skip_right_levels);
+ skip_top_levels = LevelsToSkipAlongDirection(skip_top_levels);
+ skip_bottom_levels = LevelsToSkipAlongDirection(skip_bottom_levels);
+
+ int diagonal_distance = std::max(width, height);
+
+ DCHECK(triangular_sequences_.empty());
+ triangular_sequences_.resize(8);
+ // TODO(prashant.n): Implement precedence in coverage directions instead of
+ // default right direction. http://crbug.com/629052.
+ CoverageDirection* positions = GetCoverageDirectionSequence();
+ DCHECK(positions);
+
+ // RIGHT sequence.
+ if (right_levels > 0) {
+ int start = around_bottom - 1;
+ int end = around_top + 1;
+ int skip_levels =
+ std::max(skip_right_levels,
+ std::max(skip_bottom_levels_perp, skip_top_levels_perp));
+ if (right_levels > skip_levels) {
+ EmplaceAt(
+ GetPositionForDirection(positions, CoverageDirection::RIGHT),
+ TriangularSequence(
+ std::string("r.seq"),
+ Interval(Interval::Type::BACKWARD, start, end, consider_bottom,
+ consider_top, reverse_order_),
+ Interval(Interval::Type::FORWARD, around_right, consider_right,
+ consider_left, consider_right, false),
+ true, skip_levels, width, reverse_order_));
+ }
+ }
+
+ // TOP_RIGHT sequence.
+ if (right_levels > 0 && top_levels > 0) {
+ int skip_levels = std::max(skip_right_levels, skip_top_levels);
+ int diagonal_levels = std::min(right_levels, top_levels);
+ if (diagonal_levels > skip_levels) {
+ EmplaceAt(
+ GetPositionForDirection(positions, CoverageDirection::TOP_RIGHT),
+ TriangularSequence(std::string("tr.seq"),
+ Interval(Interval::Type::DIAGONAL_FORWARD,
+ around_right, around_right, consider_left,
+ consider_right, reverse_order_),
+ Interval(Interval::Type::BACKWARD, around_top,
+ around_top - diagonal_levels + 1,
+ consider_bottom, consider_top, false),
+ false, skip_levels, diagonal_distance,
+ reverse_order_));
+ }
+ }
+
+ // TOP sequence.
+ if (top_levels > 0) {
+ int start = around_right - 1;
+ int end = around_left + 1;
+ int skip_levels =
+ std::max(skip_top_levels,
+ std::max(skip_right_levels_perp, skip_left_levels_perp));
+ if (top_levels > skip_levels) {
+ EmplaceAt(GetPositionForDirection(positions, CoverageDirection::TOP),
+ TriangularSequence(
+ std::string("t.seq"),
+ Interval(Interval::Type::BACKWARD, start, end,
+ consider_right, consider_left, reverse_order_),
+ Interval(Interval::Type::BACKWARD, around_top, consider_top,
+ consider_bottom, consider_top, false),
+ false, skip_levels, height, reverse_order_));
+ }
+ }
+
+ // TOP_LEFT sequence.
+ if (top_levels > 0 && left_levels > 0) {
+ int skip_levels = std::max(skip_top_levels, skip_left_levels);
+ int diagonal_levels = std::min(top_levels, left_levels);
+ if (diagonal_levels > skip_levels) {
+ EmplaceAt(GetPositionForDirection(positions, CoverageDirection::TOP_LEFT),
+ TriangularSequence(
+ std::string("tl.seq"),
+ Interval(Interval::Type::DIAGONAL_BACKWARD, around_left,
+ around_left, consider_right, consider_left,
+ reverse_order_),
+ Interval(Interval::Type::BACKWARD, around_top,
+ around_top - diagonal_levels + 1, consider_bottom,
+ consider_top, false),
+ false, skip_levels, diagonal_distance, reverse_order_));
+ }
+ }
+
+ // LEFT sequence.
+ if (left_levels > 0) {
+ int start = around_top + 1;
+ int end = around_bottom - 1;
+ int skip_levels =
+ std::max(skip_left_levels,
+ std::max(skip_top_levels_perp, skip_bottom_levels_perp));
+ if (left_levels > skip_levels) {
+ EmplaceAt(
+ GetPositionForDirection(positions, CoverageDirection::LEFT),
+ TriangularSequence(
+ std::string("l.seq"),
+ Interval(Interval::Type::FORWARD, start, end, consider_top,
+ consider_bottom, reverse_order_),
+ Interval(Interval::Type::BACKWARD, around_left, consider_left,
+ consider_right, consider_left, false),
+ true, skip_levels, width, reverse_order_));
+ }
+ }
+
+ // BOTTOM_LEFT sequence.
+ if (left_levels > 0 && bottom_levels > 0) {
+ int skip_levels = std::max(skip_left_levels, skip_bottom_levels);
+ int diagonal_levels = std::min(left_levels, bottom_levels);
+ if (diagonal_levels > skip_levels) {
+ EmplaceAt(
+ GetPositionForDirection(positions, CoverageDirection::BOTTOM_LEFT),
+ TriangularSequence(std::string("bl.seq"),
+ Interval(Interval::Type::DIAGONAL_BACKWARD,
+ around_left, around_left, consider_right,
+ consider_left, reverse_order_),
+ Interval(Interval::Type::FORWARD, around_bottom,
+ around_bottom + diagonal_levels - 1,
+ consider_top, consider_bottom, false),
+ false, skip_levels, diagonal_distance,
+ reverse_order_));
+ }
+ }
+
+ // BOTTOM sequence.
+ if (bottom_levels > 0) {
+ int start = around_left + 1;
+ int end = around_right - 1;
+ int skip_levels =
+ std::max(skip_bottom_levels,
+ std::max(skip_left_levels_perp, skip_right_levels_perp));
+ if (bottom_levels > skip_levels) {
+ EmplaceAt(
+ GetPositionForDirection(positions, CoverageDirection::BOTTOM),
+ TriangularSequence(
+ std::string("b.seq"),
+ Interval(Interval::Type::FORWARD, start, end, consider_left,
+ consider_right, reverse_order_),
+ Interval(Interval::Type::FORWARD, around_bottom, consider_bottom,
+ consider_top, consider_bottom, false),
+ false, skip_levels, height, reverse_order_));
+ }
+ }
+
+ // BOTTOM_RIGHT sequence.
+ if (bottom_levels > 0 && right_levels > 0) {
+ int skip_levels = std::max(skip_bottom_levels, skip_right_levels);
+ int diagonal_levels = std::min(bottom_levels, right_levels);
+ if (diagonal_levels > skip_levels) {
+ EmplaceAt(
+ GetPositionForDirection(positions, CoverageDirection::BOTTOM_RIGHT),
+ TriangularSequence(std::string("br.seq"),
+ Interval(Interval::Type::DIAGONAL_FORWARD,
+ around_right, around_right, consider_left,
+ consider_right, reverse_order_),
+ Interval(Interval::Type::FORWARD, around_bottom,
+ around_bottom + diagonal_levels - 1,
+ consider_top, consider_bottom, false),
+ false, skip_levels, diagonal_distance,
+ reverse_order_));
+ }
+ }
+
+ current_triangular_sequence_ = GetNextTriangularSequence();
+ if (current_triangular_sequence_) {
+ if (*current_triangular_sequence_)
+ current_traversal_interval_ =
+ current_triangular_sequence_->traversal_interval();
+ UpdateCurrent();
+ }
+}
+
+PyramidSequence::operator bool() const {
+ return current_triangular_sequence_ && !triangular_sequences_.empty();
+}
+
+PyramidSequence& PyramidSequence::operator++() {
+ Advance();
+ UpdateCurrent();
+
+ return *this;
+}
+
+void PyramidSequence::EmplaceAt(int position,
+ TriangularSequence&& triangular_sequence) {
+ TriangularSequence::Iterator it = triangular_sequences_.begin();
+ std::advance(it, position);
+ triangular_sequences_.emplace(it, std::move(triangular_sequence));
+ TriangularSequence::Iterator erase_it = triangular_sequences_.begin();
+ std::advance(erase_it, position + 1);
+ triangular_sequences_.erase(erase_it);
+}
+
+void PyramidSequence::Advance() {
+ if (!*this)
+ return;
+
+ ++(*current_traversal_interval_);
+ if (!*current_traversal_interval_) {
+ ++(*current_triangular_sequence_);
+ current_triangular_sequence_ = GetNextTriangularSequence();
+ if (current_triangular_sequence_) {
+ current_traversal_interval_ =
+ current_triangular_sequence_->traversal_interval();
+ }
+ }
+}
+
+void PyramidSequence::UpdateCurrent() {
+ while (*this) {
+ if (current_traversal_interval_ && (*current_traversal_interval_)) {
+ if (current_triangular_sequence_->is_swapped()) {
+ index_x_ = current_triangular_sequence_->level_index();
+ index_y_ = current_traversal_interval_->index();
+ } else {
+ index_x_ = current_traversal_interval_->index();
+ index_y_ = current_triangular_sequence_->level_index();
+ }
+
+ if (InConsiderRect() && !InIgnoreRect())
+ break;
+ }
+
+ Advance();
+ }
+}
+
+void PyramidSequence::RemoveEmptyTriangularSequences() {
+ triangular_sequences_.erase(
+ std::remove_if(triangular_sequences_.begin(), triangular_sequences_.end(),
+ [](const TriangularSequence& seq) { return !seq; }),
+ triangular_sequences_.end());
+}
+
+bool PyramidSequence::InConsiderRect() const {
+ return index_x_ >= consider_left_ && index_x_ <= consider_right_ &&
+ index_y_ >= consider_top_ && index_y_ <= consider_bottom_;
+}
+
+bool PyramidSequence::InIgnoreRect() const {
+ return index_x_ >= ignore_left_ && index_x_ <= ignore_right_ &&
+ index_y_ >= ignore_top_ && index_y_ <= ignore_bottom_;
+}
+
+// TopDownPyramidSequence implementation.
+TopDownPyramidSequence::TopDownPyramidSequence() : PyramidSequence(false) {}
+
+TopDownPyramidSequence::TopDownPyramidSequence(
+ const TopDownPyramidSequence& other) = default;
+
+TopDownPyramidSequence::TopDownPyramidSequence(TopDownPyramidSequence&& other) =
+ default;
+
+TopDownPyramidSequence::~TopDownPyramidSequence() {}
+
+TopDownPyramidSequence& TopDownPyramidSequence::operator=(
+ const TopDownPyramidSequence& other) = default;
+
+TopDownPyramidSequence& TopDownPyramidSequence::operator=(
+ TopDownPyramidSequence&& other) = default;
+
+TriangularSequence* TopDownPyramidSequence::GetNextTriangularSequence() {
+ RemoveEmptyTriangularSequences();
+
+ if (triangular_sequences_.empty())
+ return nullptr;
+
+ TriangularSequence::Iterator min_distance_it = triangular_sequences_.begin();
+
+ for (TriangularSequence::Iterator it = triangular_sequences_.begin();
+ it != triangular_sequences_.end(); ++it) {
+ int distance = it->GetMinimumDistance();
+ if (distance == 0)
+ return &(*it);
+
+ if (min_distance_it->GetMinimumDistance() > distance)
+ min_distance_it = it;
+ }
+
+ return &(*min_distance_it);
+}
+
+// BottomUpPyramidSequence implementation.
+BottomUpPyramidSequence::BottomUpPyramidSequence() : PyramidSequence(true) {}
+
+BottomUpPyramidSequence::BottomUpPyramidSequence(
+ const BottomUpPyramidSequence& other)
+ : PyramidSequence(other) {}
+
+BottomUpPyramidSequence::BottomUpPyramidSequence(
+ BottomUpPyramidSequence&& other)
+ : PyramidSequence(std::move(other)) {}
+
+BottomUpPyramidSequence::~BottomUpPyramidSequence() {}
+
+BottomUpPyramidSequence& BottomUpPyramidSequence::operator=(
+ const BottomUpPyramidSequence& other) {
+ PyramidSequence::operator=(other);
+ return *this;
+}
+
+BottomUpPyramidSequence& BottomUpPyramidSequence::operator=(
+ BottomUpPyramidSequence&& other) {
+ PyramidSequence::operator=(std::move(other));
+ return *this;
+}
+
+TriangularSequence* BottomUpPyramidSequence::GetNextTriangularSequence() {
+ RemoveEmptyTriangularSequences();
+
+ if (triangular_sequences_.empty())
+ return nullptr;
+
+ TriangularSequence::ReverseIterator max_distance_it =
+ triangular_sequences_.rbegin();
+
+ for (TriangularSequence::ReverseIterator it = triangular_sequences_.rbegin();
+ it != triangular_sequences_.rend(); ++it) {
+ int distance = it->GetMaximumDistance();
+
+ if (max_distance_it->GetMaximumDistance() < distance)
+ max_distance_it = it;
+ }
+
+ return &(*max_distance_it);
+}
+
+} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698