summaryrefslogtreecommitdiffstats
path: root/cc/layers/layer_list_iterator.cc
blob: e71238d602092766301981cd246d4f1d18a8f633 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// 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/layers/layer_list_iterator.h"

#include "cc/layers/layer_impl.h"

namespace cc {

LayerListIterator::LayerListIterator(LayerImpl* root_layer)
    : current_layer_(root_layer) {
  DCHECK(!root_layer || !root_layer->parent());
  list_indices_.push_back(0);
}

LayerListIterator::LayerListIterator(const LayerListIterator& other) = default;

LayerListIterator::~LayerListIterator() {}

LayerListIterator& LayerListIterator::operator++() {
  // case 0: done
  if (!current_layer_)
    return *this;

  // case 1: descend.
  const LayerImplList& current_list = current_layer_->children();
  if (!current_list.empty()) {
    current_layer_ = current_list[0];
    list_indices_.push_back(0);
    return *this;
  }

  for (LayerImpl* parent = current_layer_->parent(); parent;
       parent = parent->parent()) {
    // We now try and advance in some list of siblings.
    const LayerImplList& sibling_list = parent->children();

    // case 2: Advance to a sibling.
    if (list_indices_.back() + 1 < sibling_list.size()) {
      ++list_indices_.back();
      current_layer_ = sibling_list[list_indices_.back()];
      return *this;
    }

    // We need to ascend. We will pop an index off the stack.
    list_indices_.pop_back();
  }

  current_layer_ = nullptr;
  return *this;
}

LayerListReverseIterator::LayerListReverseIterator(LayerImpl* root_layer)
    : LayerListIterator(root_layer) {
  DescendToRightmostInSubtree();
}

LayerListReverseIterator::~LayerListReverseIterator() {}

// We will only support prefix increment.
LayerListIterator& LayerListReverseIterator::operator++() {
  // case 0: done
  if (!current_layer_)
    return *this;

  // case 1: we're the leftmost sibling.
  if (!list_indices_.back()) {
    list_indices_.pop_back();
    current_layer_ = current_layer_->parent();
    return *this;
  }

  // case 2: we're not the leftmost sibling. In this case, we want to move one
  // sibling over, and then descend to the rightmost descendant in that subtree.
  CHECK(current_layer_->parent());
  --list_indices_.back();
  const LayerImplList& parent_list = current_layer_->parent()->children();
  current_layer_ = parent_list[list_indices_.back()];
  DescendToRightmostInSubtree();
  return *this;
}

void LayerListReverseIterator::DescendToRightmostInSubtree() {
  if (!current_layer_)
    return;

  const LayerImplList& current_list = current_layer_->children();
  if (current_list.empty())
    return;

  size_t last_index = current_list.size() - 1;
  current_layer_ = current_list[last_index];
  list_indices_.push_back(last_index);
  DescendToRightmostInSubtree();
}

}  // namespace cc