Index: third_party/WebKit/Source/core/layout/ng/ng_block_layout_child_iterator.h |
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_child_iterator.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_child_iterator.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3af4a5320800fb59129e44d92d80d34fd7844ef9 |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_child_iterator.h |
@@ -0,0 +1,80 @@ |
+// Copyright 2017 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. |
+ |
+#ifndef NGBlockLayoutChildIterator_h |
+#define NGBlockLayoutChildIterator_h |
+ |
+#include "core/layout/ng/ng_block_break_token.h" |
+#include "core/layout/ng/ng_layout_input_node.h" |
+ |
+namespace blink { |
+ |
+class NGBlockLayoutChildIterator { |
+ public: |
+ NGBlockLayoutChildIterator(NGLayoutInputNode* first_child, |
+ NGBlockBreakToken* break_token) |
+ : child_(first_child), break_token_(break_token), child_token_idx_(0) { |
+ Advance(); |
+ } |
+ |
+ std::pair<NGLayoutInputNode*, NGBreakToken*> NextChild() { |
+ NGLayoutInputNode* child = child_; |
+ NGBreakToken* child_token = child_token_; |
+ if (child_) |
+ child_ = child_->NextSibling(); |
+ Advance(); |
+ return std::make_pair(child, child_token); |
+ } |
+ |
+ private: |
+ // |
+ void Advance() { |
+ const auto& child_break_tokens = break_token_->ChildBreakTokens(); |
+ child_token_ = nullptr; |
+ |
+ do { |
+ NGBreakToken* next_child_token = nullptr; |
+ if (break_token_ && child_token_idx_ < child_break_tokens.size()) { |
+ next_child_token = break_token_->ChildBreakTokens()[child_token_idx_]; |
+ } |
+ |
+ if (next_child_token && next_child_token->Node() == child_) { |
+ // If we're resuming layout after a fragmentainer break, we need to skip |
+ // siblings that we're done with. We may have been able to fully lay out |
+ // some |
+ // node(s) preceding a node that we had to break inside (and therefore |
+ // were |
+ // not able to fully lay out). This happens when we have parallel flows |
+ // [1], |
+ // which are caused by floats, overflow, etc. |
+ // |
+ // [1] https://drafts.csswg.org/css-break/#parallel-flows |
+ |
+ // We may have a break token which just represents that a child has |
+ // fully completed its layout. |
+ if (next_child_token->IsFinished()) |
+ continue; |
+ |
+ // We've found our next child, return. |
+ child_token_idx_++; |
+ child_token_ = next_child_token; |
+ return; |
+ } else { |
+ // There is no break token which matches here, we've found our next |
+ // child. |
+ return; |
+ } |
+ } while ((child_ = child_->NextSibling())); |
+ } |
+ |
+ Persistent<NGLayoutInputNode> child_; |
+ Persistent<NGBreakToken> child_token_; |
+ |
+ Persistent<NGBlockBreakToken> break_token_; |
+ size_t child_token_idx_; |
+}; |
+ |
+} // namespace blink |
+ |
+#endif // NGBlockLayoutChildIterator_h |