Commit 4d281c8d authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Make InlineContents traverse flat tree for previous and next

Currently, InlineContents creation and previous/next movement are done
by different implementations:

- When creating from a position, it traverses the flat tree until
  finding a node in a usable block flow;
- When moving previous/next, it traverses the layout tree until finding
  a useable block flow.

Since these operations are very similar, this patch change the latter
to also traverse on flat tree and share the traversal algorithm to
reduce duplicated logic. This also makes it easier to change
TextOffsetMapping not to cross text control boundaries (*).

(*) crrev.com/c/1327962

Bug: 901492
Change-Id: If7c3dd262903c1a0f81166f729614a8d810f5d27
Reviewed-on: https://chromium-review.googlesource.com/c/1327531Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarYoichi Osato <yoichio@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606748}
parent 7d6ae34d
...@@ -235,6 +235,7 @@ TextOffsetMapping::ForwardRange TextOffsetMapping::ForwardRangeOf( ...@@ -235,6 +235,7 @@ TextOffsetMapping::ForwardRange TextOffsetMapping::ForwardRangeOf(
// static // static
TextOffsetMapping::InlineContents TextOffsetMapping::FindBackwardInlineContents( TextOffsetMapping::InlineContents TextOffsetMapping::FindBackwardInlineContents(
const PositionInFlatTree& position) { const PositionInFlatTree& position) {
// TODO(xiaochengh): Make this function not cross text control boundaries.
for (const Node* node = position.NodeAsRangeLastNode(); node; for (const Node* node = position.NodeAsRangeLastNode(); node;
node = FlatTreeTraversal::Previous(*node)) { node = FlatTreeTraversal::Previous(*node)) {
const InlineContents inline_contents = ComputeInlineContentsFromNode(*node); const InlineContents inline_contents = ComputeInlineContentsFromNode(*node);
...@@ -249,6 +250,7 @@ TextOffsetMapping::InlineContents TextOffsetMapping::FindBackwardInlineContents( ...@@ -249,6 +250,7 @@ TextOffsetMapping::InlineContents TextOffsetMapping::FindBackwardInlineContents(
// with AfterNode(IMG) for <body><img></body> // with AfterNode(IMG) for <body><img></body>
TextOffsetMapping::InlineContents TextOffsetMapping::FindForwardInlineContents( TextOffsetMapping::InlineContents TextOffsetMapping::FindForwardInlineContents(
const PositionInFlatTree& position) { const PositionInFlatTree& position) {
// TODO(xiaochengh): Make this function not cross text control boundaries.
for (const Node* node = position.NodeAsRangeFirstNode(); node; for (const Node* node = position.NodeAsRangeFirstNode(); node;
node = FlatTreeTraversal::Next(*node)) { node = FlatTreeTraversal::Next(*node)) {
const InlineContents inline_contents = ComputeInlineContentsFromNode(*node); const InlineContents inline_contents = ComputeInlineContentsFromNode(*node);
...@@ -323,38 +325,38 @@ EphemeralRangeInFlatTree TextOffsetMapping::InlineContents::GetRange() const { ...@@ -323,38 +325,38 @@ EphemeralRangeInFlatTree TextOffsetMapping::InlineContents::GetRange() const {
: PositionInFlatTree::AfterNode(last_node)); : PositionInFlatTree::AfterNode(last_node));
} }
PositionInFlatTree
TextOffsetMapping::InlineContents::LastPositionBeforeBlockFlow() const {
DCHECK(block_flow_);
if (const Node* node = block_flow_->NonPseudoNode())
return PositionInFlatTree::BeforeNode(*node);
DCHECK(first_);
DCHECK(first_->NonPseudoNode());
return PositionInFlatTree::BeforeNode(*first_->NonPseudoNode());
}
PositionInFlatTree
TextOffsetMapping::InlineContents::FirstPositionAfterBlockFlow() const {
DCHECK(block_flow_);
if (const Node* node = block_flow_->NonPseudoNode())
return PositionInFlatTree::AfterNode(*node);
DCHECK(last_);
DCHECK(last_->NonPseudoNode());
return PositionInFlatTree::AfterNode(*last_->NonPseudoNode());
}
// static // static
TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::NextOf( TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::NextOf(
const InlineContents& inline_contents) { const InlineContents& inline_contents) {
for (LayoutObject* runner = return TextOffsetMapping::FindForwardInlineContents(
inline_contents.block_flow_->NextInPreOrderAfterChildren(); inline_contents.FirstPositionAfterBlockFlow());
runner; runner = runner->NextInPreOrder()) {
if (!CanBeInlineContentsContainer(*runner))
continue;
const LayoutBlockFlow& block_flow = ToLayoutBlockFlow(*runner);
if (block_flow.IsFloatingOrOutOfFlowPositioned())
continue;
DCHECK(!block_flow.IsAtomicInlineLevel()) << block_flow;
return CreateInlineContentsFromBlockFlow(block_flow);
}
return InlineContents();
} }
// static // static
TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::PreviousOf( TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::PreviousOf(
const InlineContents& inline_contents) { const InlineContents& inline_contents) {
for (LayoutObject* runner = inline_contents.block_flow_->PreviousInPreOrder(); return TextOffsetMapping::FindBackwardInlineContents(
runner; runner = runner->PreviousInPreOrder()) { inline_contents.LastPositionBeforeBlockFlow());
const LayoutBlockFlow* const block_flow =
ComputeInlineContentsAsBlockFlow(*runner);
if (!block_flow || block_flow->IsFloatingOrOutOfFlowPositioned())
continue;
DCHECK(!block_flow->IsDescendantOf(inline_contents.block_flow_))
<< block_flow;
DCHECK(!block_flow->IsAtomicInlineLevel()) << block_flow;
return CreateInlineContentsFromBlockFlow(*block_flow);
}
return InlineContents();
} }
std::ostream& operator<<( std::ostream& operator<<(
......
...@@ -71,6 +71,9 @@ class CORE_EXPORT TextOffsetMapping final { ...@@ -71,6 +71,9 @@ class CORE_EXPORT TextOffsetMapping final {
private: private:
friend class TextOffsetMapping; friend class TextOffsetMapping;
PositionInFlatTree FirstPositionAfterBlockFlow() const;
PositionInFlatTree LastPositionBeforeBlockFlow() const;
const LayoutBlockFlow* block_flow_ = nullptr; const LayoutBlockFlow* block_flow_ = nullptr;
const LayoutObject* first_ = nullptr; const LayoutObject* first_ = nullptr;
const LayoutObject* last_ = nullptr; const LayoutObject* last_ = nullptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment