summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h')
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h141
1 files changed, 141 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
new file mode 100644
index 00000000000..c4927f0acad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
@@ -0,0 +1,141 @@
+// Copyright 2020 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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_CHILD_ITERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_CHILD_ITERATOR_H_
+
+#include "base/containers/span.h"
+#include "base/optional.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_link.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+
+namespace blink {
+
+class LayoutObject;
+class NGBlockBreakToken;
+
+// Iterator for children of a box fragment. Supports fragment items and break
+// tokens. To advance to the next sibling, call |Advance()|. To descend into
+// children of the current child, call |Descend()|.
+//
+// Using this class requires LayoutNGFragmentItem to be enabled. While fragment
+// items are in a flat list representing the contents of an inline formatting
+// context, the iterator will to a certain extent restore the object hierarchy,
+// so that we can calculate the global offset of children of a relatively
+// positioned inline correctly.
+class CORE_EXPORT NGFragmentChildIterator {
+ STACK_ALLOCATED();
+
+ public:
+ explicit NGFragmentChildIterator(
+ const NGPhysicalBoxFragment& parent,
+ const NGBlockBreakToken* parent_break_token = nullptr);
+
+ // Create a child iterator for the current child.
+ NGFragmentChildIterator Descend() const;
+
+ // Move to the next sibling. Return false if there's no next sibling. Once
+ // false is returned, this object is in an unusable state, with the exception
+ // that calling IsAtEnd() is allowed.
+ bool Advance() {
+ if (current_.cursor_)
+ return AdvanceWithCursor();
+ return AdvanceChildFragment();
+ }
+
+ bool IsAtEnd() {
+ if (current_.cursor_)
+ return !*current_.cursor_;
+ DCHECK(parent_fragment_);
+ const auto children = parent_fragment_->Children();
+ return child_fragment_idx_ >= children.size();
+ }
+
+ class Current {
+ friend class NGFragmentChildIterator;
+
+ public:
+ // Return the current NGLink. Note that its offset is relative to the inline
+ // formatting context root, if the fragment / item participates in one.
+ const NGLink& Link() const { return link_; }
+
+ const NGPhysicalBoxFragment* BoxFragment() const {
+ return To<NGPhysicalBoxFragment>(link_.fragment);
+ }
+ const NGFragmentItem* FragmentItem() const {
+ if (!cursor_)
+ return nullptr;
+ return cursor_->CurrentItem();
+ }
+
+ // Get the incoming break token for the current child, i.e. the context at
+ // which layout of this child's node was resumed. Note that for text and
+ // non-atomic inlines this will be the incoming block break token to the
+ // inline formatting context root. For monolithic content, no break token
+ // will be returned (since such content isn't considered to participate in a
+ // fragmentation context).
+ const NGBlockBreakToken* BlockBreakToken() const {
+ if (LIKELY(!block_break_token_))
+ return nullptr;
+ if (link_.fragment) {
+ // Don't pass the break token into monolithic content.
+ if (link_.fragment->IsMonolithic())
+ return nullptr;
+ // If the break token we've found is from a fragmentainer, it's only to
+ // be used by a subsequent fragmentainer. Other fragment types (such as
+ // column spanners) need to ignore it.
+ if (break_token_for_fragmentainer_only_ &&
+ !link_.fragment->IsColumnBox())
+ return nullptr;
+ }
+ return block_break_token_;
+ }
+
+ const LayoutObject* GetLayoutObject() const {
+ if (const NGFragmentItem* item = FragmentItem())
+ return item->GetLayoutObject();
+ return BoxFragment()->GetLayoutObject();
+ }
+
+ private:
+ NGLink link_;
+ base::Optional<NGInlineCursor> cursor_;
+ const NGBlockBreakToken* block_break_token_ = nullptr;
+ bool break_token_for_fragmentainer_only_ = false;
+ };
+
+ const Current& GetCurrent() const { return current_; }
+ const Current& operator*() const { return current_; }
+ const Current* operator->() const { return &current_; }
+
+ private:
+ NGFragmentChildIterator(
+ const NGInlineCursor& parent,
+ const NGBlockBreakToken* parent_break_token,
+ base::span<const NGBreakToken* const> child_break_tokens);
+
+ bool AdvanceChildFragment();
+ void UpdateSelfFromFragment(
+ const NGPhysicalBoxFragment* previous_fragment = nullptr);
+
+ bool AdvanceWithCursor();
+ void UpdateSelfFromCursor();
+ void SkipToBoxFragment();
+ void SkipToBlockBreakToken();
+
+ const NGPhysicalBoxFragment* parent_fragment_ = nullptr;
+ const NGBlockBreakToken* parent_break_token_ = nullptr;
+ Current current_;
+ base::span<const NGBreakToken* const> child_break_tokens_;
+ wtf_size_t child_fragment_idx_ = 0;
+ wtf_size_t child_break_token_idx_ = 0;
+ bool is_fragmentation_context_root_ = false;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_CHILD_ITERATOR_H_