slot 0.0.1
A real time UI render framework
载入中...
搜索中...
未找到
LayoutableChildren.h
浏览该文件的文档.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#pragma once
9
10#include <cstdint>
11#include <forward_list>
12#include <utility>
13
14#include <yoga/enums/Display.h>
15
16namespace facebook::yoga {
17
18class Node;
19
20template <typename T>
22 public:
23 struct Iterator {
24 using iterator_category = std::input_iterator_tag;
25 using difference_type = std::ptrdiff_t;
26 using value_type = T*;
27 using pointer = T*;
28 using reference = T*;
29
30 Iterator() = default;
31
32 Iterator(const T* node, size_t childIndex)
33 : node_(node), childIndex_(childIndex) {}
34
35 T* operator*() const {
36 return node_->getChild(childIndex_);
37 }
38
40 next();
41 return *this;
42 }
43
45 Iterator tmp = *this;
46 ++(*this);
47 return tmp;
48 }
49
50 friend bool operator==(const Iterator& a, const Iterator& b) {
51 return a.node_ == b.node_ && a.childIndex_ == b.childIndex_;
52 }
53
54 friend bool operator!=(const Iterator& a, const Iterator& b) {
55 return a.node_ != b.node_ || a.childIndex_ != b.childIndex_;
56 }
57
58 private:
59 void next() {
60 if (childIndex_ + 1 >= node_->getChildCount()) {
61 // if the current node has no more children, try to backtrack and
62 // visit its successor
63 if (backtrack_.empty()) [[likely]] {
64 // if there are no nodes to backtrack to, the last node has been
65 // visited
66 *this = Iterator{};
67 } else {
68 // pop and restore the latest backtrack entry
69 const auto& back = backtrack_.front();
70 node_ = back.first;
71 childIndex_ = back.second;
72 backtrack_.pop_front();
73
74 // go to the next node
75 next();
76 }
77 } else {
78 // current node has more children to visit, go to next
80 // skip all display: contents nodes, possibly going deeper into the
81 // tree
82 if (node_->getChild(childIndex_)->style().display() ==
83 Display::Contents) [[unlikely]] {
85 }
86 }
87 }
88
90 // get the node that would be returned from the iterator
91 auto currentNode = node_->getChild(childIndex_);
92 while (currentNode->style().display() == Display::Contents &&
93 currentNode->getChildCount() > 0) {
94 // if it has display: contents set, it shouldn't be returned but its
95 // children should in its place push the current node and child index
96 // so that the current state can be restored when backtracking
97 backtrack_.push_front({node_, childIndex_});
98 // traverse the child
99 node_ = currentNode;
100 childIndex_ = 0;
101
102 // repeat until a node without display: contents is found in the
103 // subtree or a leaf is reached
104 currentNode = currentNode->getChild(childIndex_);
105 }
106
107 // if no node without display: contents was found, try to backtrack
108 if (currentNode->style().display() == Display::Contents) {
109 next();
110 }
111 }
112
113 const T* node_{nullptr};
114 size_t childIndex_{0};
115 std::forward_list<std::pair<const T*, size_t>> backtrack_;
116
118 };
119
120 explicit LayoutableChildren(const T* node) : node_(node) {
121 static_assert(std::input_iterator<LayoutableChildren<T>::Iterator>);
122 static_assert(
123 std::is_base_of<Node, T>::value,
124 "Type parameter of LayoutableChildren must derive from yoga::Node");
125 }
126
127 Iterator begin() const {
128 if (node_->getChildCount() > 0) {
129 auto result = Iterator(node_, 0);
130 if (node_->getChild(0)->style().display() == Display::Contents)
131 [[unlikely]] {
132 result.skipContentsNodes();
133 }
134 return result;
135 } else {
136 return Iterator{};
137 }
138 }
139
140 Iterator end() const {
141 return Iterator{};
142 }
143
144 private:
145 const T* node_;
146};
147
148} // namespace facebook::yoga
Definition LayoutableChildren.h:21
LayoutableChildren(const T *node)
Definition LayoutableChildren.h:120
Iterator begin() const
Definition LayoutableChildren.h:127
const T * node_
Definition LayoutableChildren.h:145
Iterator end() const
Definition LayoutableChildren.h:140
Definition Benchmark.cpp:19
Definition LayoutableChildren.h:23
Iterator operator++(int)
Definition LayoutableChildren.h:44
std::forward_list< std::pair< const T *, size_t > > backtrack_
Definition LayoutableChildren.h:115
friend bool operator!=(const Iterator &a, const Iterator &b)
Definition LayoutableChildren.h:54
const T * node_
Definition LayoutableChildren.h:113
std::ptrdiff_t difference_type
Definition LayoutableChildren.h:25
void next()
Definition LayoutableChildren.h:59
T * value_type
Definition LayoutableChildren.h:26
void skipContentsNodes()
Definition LayoutableChildren.h:89
Iterator(const T *node, size_t childIndex)
Definition LayoutableChildren.h:32
Iterator & operator++()
Definition LayoutableChildren.h:39
T * pointer
Definition LayoutableChildren.h:27
std::input_iterator_tag iterator_category
Definition LayoutableChildren.h:24
T * operator*() const
Definition LayoutableChildren.h:35
friend bool operator==(const Iterator &a, const Iterator &b)
Definition LayoutableChildren.h:50
friend LayoutableChildren
Definition LayoutableChildren.h:117
size_t childIndex_
Definition LayoutableChildren.h:114
T * reference
Definition LayoutableChildren.h:28