Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp b/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp |
| index ff9b7385c1b98037fdf48f10df2ec3f52d9d6725..6c69444093196019cd10ad137089540f5e0fef69 100644 |
| --- a/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp |
| +++ b/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp |
| @@ -41,8 +41,153 @@ namespace blink { |
| namespace { |
| +// The traversal strategy for |LeftPositionOf()|. |
| template <typename Strategy> |
| -static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| +struct TraversalLeft { |
| + STATIC_ONLY(TraversalLeft); |
| + |
| + static InlineBox* BackwardLeafChildOf(const InlineBox& box) { |
| + return box.NextLeafChild(); |
| + } |
| + |
| + static int CaretEndOffsetOf(const InlineBox& box) { |
| + return box.CaretRightmostOffset(); |
| + } |
| + |
| + static int CaretMinOffsetOf(TextDirection direction, const InlineBox& box) { |
| + if (direction == TextDirection::kLtr) |
| + return box.CaretMinOffset(); |
| + return box.CaretMaxOffset(); |
| + } |
| + |
| + static int CaretStartOffsetOf(const InlineBox& box) { |
| + return box.CaretLeftmostOffset(); |
| + } |
| + |
| + static int ForwardGraphemeBoundaryOf(TextDirection direction, |
| + Node* node, |
| + int offset) { |
| + if (direction == TextDirection::kLtr) |
| + return PreviousGraphemeBoundaryOf(node, offset); |
| + return NextGraphemeBoundaryOf(node, offset); |
| + } |
| + |
| + static InlineBox* ForwardLeafChildOf(const InlineBox& box) { |
| + return box.PrevLeafChild(); |
| + } |
| + |
| + static InlineBox* ForwardLeafChildIgnoringLineBreakOf(const InlineBox& box) { |
| + return box.PrevLeafChildIgnoringLineBreak(); |
| + } |
| + |
| + static PositionTemplate<Strategy> ForwardVisuallyDistinctCandidateOf( |
| + TextDirection direction, |
| + const PositionTemplate<Strategy>& position) { |
| + if (direction == TextDirection::kLtr) |
| + return PreviousVisuallyDistinctCandidate(position); |
| + return NextVisuallyDistinctCandidate(position); |
| + } |
| + |
| + static VisiblePositionTemplate<Strategy> HonorEditingBoundary( |
| + TextDirection direction, |
| + const VisiblePositionTemplate<Strategy>& visible_position, |
| + const PositionTemplate<Strategy>& anchor) { |
| + if (direction == TextDirection::kLtr) |
| + return HonorEditingBoundaryAtOrBefore(visible_position, anchor); |
| + return HonorEditingBoundaryAtOrAfter(visible_position, anchor); |
| + } |
| + |
| + static Node* LogicalStartBoxOf(TextDirection direction, |
| + const InlineBox& box, |
| + InlineBox*& result_box) { |
| + if (direction == TextDirection::kLtr) |
| + return box.Root().GetLogicalStartBoxWithNode(result_box); |
| + return box.Root().GetLogicalEndBoxWithNode(result_box); |
| + } |
| + |
| + static bool IsOvershot(int offset, const InlineBox& box) { |
| + if (box.IsLeftToRightDirection()) |
| + return offset < box.CaretMinOffset(); |
| + return offset > box.CaretMaxOffset(); |
| + } |
| +}; |
| + |
| +// The traversal strategy for |RightPositionOf()|. |
| +template <typename Strategy> |
| +struct TraversalRight { |
| + STATIC_ONLY(TraversalRight); |
| + |
| + static InlineBox* BackwardLeafChildOf(const InlineBox& box) { |
| + return box.PrevLeafChild(); |
| + } |
| + |
| + static int CaretEndOffsetOf(const InlineBox& box) { |
| + return box.CaretLeftmostOffset(); |
| + } |
| + |
| + static int CaretMinOffsetOf(TextDirection direction, const InlineBox& box) { |
| + if (direction == TextDirection::kLtr) |
| + return box.CaretMaxOffset(); |
| + return box.CaretMinOffset(); |
| + } |
| + |
| + static int CaretStartOffsetOf(const InlineBox& box) { |
| + return box.CaretRightmostOffset(); |
| + } |
| + |
| + static int ForwardGraphemeBoundaryOf(TextDirection direction, |
| + Node* node, |
| + int offset) { |
| + if (direction == TextDirection::kLtr) |
| + return NextGraphemeBoundaryOf(node, offset); |
| + return PreviousGraphemeBoundaryOf(node, offset); |
| + } |
| + |
| + static InlineBox* ForwardLeafChildOf(const InlineBox& box) { |
| + return box.NextLeafChild(); |
| + } |
| + |
| + static InlineBox* ForwardLeafChildIgnoringLineBreakOf(const InlineBox& box) { |
| + return box.NextLeafChildIgnoringLineBreak(); |
| + } |
| + |
| + static PositionTemplate<Strategy> ForwardVisuallyDistinctCandidateOf( |
| + TextDirection direction, |
| + const PositionTemplate<Strategy>& position) { |
| + if (direction == TextDirection::kLtr) |
| + return NextVisuallyDistinctCandidate(position); |
| + return PreviousVisuallyDistinctCandidate(position); |
| + } |
| + |
| + static VisiblePositionTemplate<Strategy> HonorEditingBoundary( |
| + TextDirection direction, |
| + const VisiblePositionTemplate<Strategy>& visible_position, |
| + const PositionTemplate<Strategy>& anchor) { |
| + if (direction == TextDirection::kLtr) |
| + return HonorEditingBoundaryAtOrAfter(visible_position, anchor); |
| + return HonorEditingBoundaryAtOrBefore(visible_position, anchor); |
| + } |
| + |
| + static Node* LogicalStartBoxOf(TextDirection direction, |
| + const InlineBox& box, |
| + InlineBox*& result_box) { |
| + if (direction == TextDirection::kLtr) |
| + return box.Root().GetLogicalEndBoxWithNode(result_box); |
| + return box.Root().GetLogicalStartBoxWithNode(result_box); |
| + } |
| + |
| + static bool IsOvershot(int offset, const InlineBox& box) { |
| + if (box.IsLeftToRightDirection()) |
| + return offset > box.CaretMaxOffset(); |
| + return offset < box.CaretMinOffset(); |
| + } |
| +}; |
| + |
| +// TODO(yosin): We should rename local variables in |
|
Xiaocheng
2017/06/12 18:28:15
nit: And also comments.
yosin_UTC9
2017/06/13 06:44:46
Done.
|
| +// |TraverseInternalAlgorithm()| to generic name based on |Traversal| instead of |
| +// assuming right-to-left traversal. |
| +template <typename Strategy, typename Traversal> |
| +static PositionTemplate<Strategy> TraverseInternalAlgorithm( |
| const VisiblePositionTemplate<Strategy>& visible_position) { |
| DCHECK(visible_position.IsValid()) << visible_position; |
| const PositionTemplate<Strategy> deep_position = |
| @@ -63,35 +208,30 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| InlineBox* box = box_position.inline_box; |
| int offset = box_position.offset_in_box; |
| if (!box) { |
| - return primary_direction == TextDirection::kLtr |
| - ? PreviousVisuallyDistinctCandidate(deep_position) |
| - : NextVisuallyDistinctCandidate(deep_position); |
| + return Traversal::ForwardVisuallyDistinctCandidateOf(primary_direction, |
| + deep_position); |
| } |
| LineLayoutItem line_layout_item = box->GetLineLayoutItem(); |
| while (true) { |
| if ((line_layout_item.IsAtomicInlineLevel() || line_layout_item.IsBR()) && |
| - offset == box->CaretRightmostOffset()) { |
| - return box->IsLeftToRightDirection() |
| - ? PreviousVisuallyDistinctCandidate(deep_position) |
| - : NextVisuallyDistinctCandidate(deep_position); |
| + offset == Traversal::CaretEndOffsetOf(*box)) { |
| + return Traversal::ForwardVisuallyDistinctCandidateOf(box->Direction(), |
| + deep_position); |
| } |
| if (!line_layout_item.GetNode()) { |
| - box = box->PrevLeafChild(); |
| + box = Traversal::ForwardLeafChildOf(*box); |
| if (!box) { |
| - return primary_direction == TextDirection::kLtr |
| - ? PreviousVisuallyDistinctCandidate(deep_position) |
| - : NextVisuallyDistinctCandidate(deep_position); |
| + return Traversal::ForwardVisuallyDistinctCandidateOf( |
| + primary_direction, deep_position); |
| } |
| line_layout_item = box->GetLineLayoutItem(); |
| - offset = box->CaretRightmostOffset(); |
| + offset = Traversal::CaretEndOffsetOf(*box); |
| continue; |
| } |
| - offset = |
| - box->IsLeftToRightDirection() |
| - ? PreviousGraphemeBoundaryOf(line_layout_item.GetNode(), offset) |
| - : NextGraphemeBoundaryOf(line_layout_item.GetNode(), offset); |
| + offset = Traversal::ForwardGraphemeBoundaryOf( |
| + box->Direction(), line_layout_item.GetNode(), offset); |
| const int caret_min_offset = box->CaretMinOffset(); |
| const int caret_max_offset = box->CaretMaxOffset(); |
| @@ -99,17 +239,14 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| if (offset > caret_min_offset && offset < caret_max_offset) |
| break; |
| - if (box->IsLeftToRightDirection() ? offset < caret_min_offset |
| - : offset > caret_max_offset) { |
| + if (Traversal::IsOvershot(offset, *box)) { |
| // Overshot to the left. |
|
Xiaocheng
2017/06/12 18:28:15
Like this.
yosin_UTC9
2017/06/13 06:44:46
Good catch!
|
| - InlineBox* const prev_box = box->PrevLeafChildIgnoringLineBreak(); |
| + InlineBox* const prev_box = |
| + Traversal::ForwardLeafChildIgnoringLineBreakOf(*box); |
| if (!prev_box) { |
| - PositionTemplate<Strategy> position_on_left = |
| - primary_direction == TextDirection::kLtr |
| - ? PreviousVisuallyDistinctCandidate( |
| - visible_position.DeepEquivalent()) |
| - : NextVisuallyDistinctCandidate( |
| - visible_position.DeepEquivalent()); |
| + const PositionTemplate<Strategy>& position_on_left = |
| + Traversal::ForwardVisuallyDistinctCandidateOf( |
| + primary_direction, visible_position.DeepEquivalent()); |
| if (position_on_left.IsNull()) |
| return PositionTemplate<Strategy>(); |
| @@ -126,26 +263,23 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| // edge's visual position and go for another round. |
| box = prev_box; |
| line_layout_item = box->GetLineLayoutItem(); |
| - offset = prev_box->CaretRightmostOffset(); |
| + offset = Traversal::CaretEndOffsetOf(*prev_box); |
| continue; |
| } |
| - DCHECK_EQ(offset, box->CaretLeftmostOffset()); |
| + DCHECK_EQ(offset, Traversal::CaretStartOffsetOf(*box)); |
| unsigned char level = box->BidiLevel(); |
| - InlineBox* prev_box = box->PrevLeafChild(); |
| + InlineBox* prev_box = Traversal::ForwardLeafChildOf(*box); |
| if (box->Direction() == primary_direction) { |
| if (!prev_box) { |
| InlineBox* logical_start = nullptr; |
| - if (primary_direction == TextDirection::kLtr |
| - ? box->Root().GetLogicalStartBoxWithNode(logical_start) |
| - : box->Root().GetLogicalEndBoxWithNode(logical_start)) { |
| + if (Traversal::LogicalStartBoxOf(primary_direction, *box, |
| + logical_start)) { |
| box = logical_start; |
| line_layout_item = box->GetLineLayoutItem(); |
| - offset = primary_direction == TextDirection::kLtr |
| - ? box->CaretMinOffset() |
| - : box->CaretMaxOffset(); |
| + offset = Traversal::CaretMinOffsetOf(primary_direction, *box); |
| } |
| break; |
| } |
| @@ -156,7 +290,7 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| InlineBox* next_box = box; |
| do { |
| - next_box = next_box->NextLeafChild(); |
| + next_box = Traversal::BackwardLeafChildOf(*next_box); |
| } while (next_box && next_box->BidiLevel() > level); |
| if (next_box && next_box->BidiLevel() == level) |
| @@ -164,22 +298,22 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| box = prev_box; |
| line_layout_item = box->GetLineLayoutItem(); |
| - offset = box->CaretRightmostOffset(); |
| + offset = Traversal::CaretEndOffsetOf(*box); |
| if (box->Direction() == primary_direction) |
| break; |
| continue; |
| } |
| while (prev_box && !prev_box->GetLineLayoutItem().GetNode()) |
| - prev_box = prev_box->PrevLeafChild(); |
| + prev_box = Traversal::ForwardLeafChildOf(*prev_box); |
| if (prev_box) { |
| box = prev_box; |
| line_layout_item = box->GetLineLayoutItem(); |
| - offset = box->CaretRightmostOffset(); |
| + offset = Traversal::CaretEndOffsetOf(*box); |
| if (box->BidiLevel() > level) { |
| do { |
| - prev_box = prev_box->PrevLeafChild(); |
| + prev_box = Traversal::ForwardLeafChildOf(*prev_box); |
| } while (prev_box && prev_box->BidiLevel() > level); |
| if (!prev_box || prev_box->BidiLevel() < level) |
| @@ -189,7 +323,7 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| // Trailing edge of a secondary run. Set to the leading edge of |
| // the entire run. |
| while (true) { |
| - while (InlineBox* next_box = box->NextLeafChild()) { |
| + while (InlineBox* next_box = Traversal::BackwardLeafChildOf(*box)) { |
| if (next_box->BidiLevel() < level) |
| break; |
| box = next_box; |
| @@ -197,7 +331,7 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| if (box->BidiLevel() == level) |
| break; |
| level = box->BidiLevel(); |
| - while (InlineBox* prev_box = box->PrevLeafChild()) { |
| + while (InlineBox* prev_box = Traversal::ForwardLeafChildOf(*box)) { |
| if (prev_box->BidiLevel() < level) |
| break; |
| box = prev_box; |
| @@ -207,9 +341,7 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| level = box->BidiLevel(); |
| } |
| line_layout_item = box->GetLineLayoutItem(); |
| - offset = primary_direction == TextDirection::kLtr |
| - ? box->CaretMinOffset() |
| - : box->CaretMaxOffset(); |
| + offset = Traversal::CaretMinOffsetOf(primary_direction, *box); |
| } |
| break; |
| } |
| @@ -226,259 +358,48 @@ static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate( |
| } |
| } |
| -template <typename Strategy> |
| -VisiblePositionTemplate<Strategy> LeftPositionOfAlgorithm( |
| +template <typename Strategy, typename Traversal> |
| +VisiblePositionTemplate<Strategy> TraverseAlgorithm( |
| const VisiblePositionTemplate<Strategy>& visible_position) { |
| DCHECK(visible_position.IsValid()) << visible_position; |
| const PositionTemplate<Strategy> pos = |
| - LeftVisuallyDistinctCandidate(visible_position); |
| + TraverseInternalAlgorithm<Strategy, Traversal>(visible_position); |
| // TODO(yosin) Why can't we move left from the last position in a tree? |
| if (pos.AtStartOfTree() || pos.AtEndOfTree()) |
| return VisiblePositionTemplate<Strategy>(); |
| - const VisiblePositionTemplate<Strategy> left = CreateVisiblePosition(pos); |
| - DCHECK_NE(left.DeepEquivalent(), visible_position.DeepEquivalent()); |
| - |
| - return DirectionOfEnclosingBlockOf(left.DeepEquivalent()) == |
| - TextDirection::kLtr |
| - ? HonorEditingBoundaryAtOrBefore(left, |
| - visible_position.DeepEquivalent()) |
| - : HonorEditingBoundaryAtOrAfter(left, |
| - visible_position.DeepEquivalent()); |
| -} |
| - |
| -template <typename Strategy> |
| -PositionTemplate<Strategy> RightVisuallyDistinctCandidate( |
| - const VisiblePositionTemplate<Strategy>& visible_position) { |
| - DCHECK(visible_position.IsValid()) << visible_position; |
| - const PositionTemplate<Strategy> deep_position = |
| - visible_position.DeepEquivalent(); |
| - PositionTemplate<Strategy> p = deep_position; |
| - if (p.IsNull()) |
| - return PositionTemplate<Strategy>(); |
| - |
| - const PositionTemplate<Strategy> downstream_start = |
| - MostForwardCaretPosition(p); |
| - const TextDirection primary_direction = PrimaryDirectionOf(*p.AnchorNode()); |
| - const TextAffinity affinity = visible_position.Affinity(); |
| - |
| - while (true) { |
| - InlineBoxPosition box_position = |
| - ComputeInlineBoxPosition(p, affinity, primary_direction); |
| - InlineBox* box = box_position.inline_box; |
| - int offset = box_position.offset_in_box; |
| - if (!box) { |
| - return primary_direction == TextDirection::kLtr |
| - ? NextVisuallyDistinctCandidate(deep_position) |
| - : PreviousVisuallyDistinctCandidate(deep_position); |
| - } |
| - LayoutObject* layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - |
| - while (true) { |
| - if ((layout_object->IsAtomicInlineLevel() || layout_object->IsBR()) && |
| - offset == box->CaretLeftmostOffset()) { |
| - return box->IsLeftToRightDirection() |
| - ? NextVisuallyDistinctCandidate(deep_position) |
| - : PreviousVisuallyDistinctCandidate(deep_position); |
| - } |
| - if (!layout_object->GetNode()) { |
| - box = box->NextLeafChild(); |
| - if (!box) { |
| - return primary_direction == TextDirection::kLtr |
| - ? NextVisuallyDistinctCandidate(deep_position) |
| - : PreviousVisuallyDistinctCandidate(deep_position); |
| - } |
| - layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - offset = box->CaretLeftmostOffset(); |
| - continue; |
| - } |
| - |
| - offset = |
| - box->IsLeftToRightDirection() |
| - ? NextGraphemeBoundaryOf(layout_object->GetNode(), offset) |
| - : PreviousGraphemeBoundaryOf(layout_object->GetNode(), offset); |
| - |
| - const int caret_min_offset = box->CaretMinOffset(); |
| - const int caret_max_offset = box->CaretMaxOffset(); |
| - |
| - if (offset > caret_min_offset && offset < caret_max_offset) |
| - break; |
| - |
| - if (box->IsLeftToRightDirection() ? offset > caret_max_offset |
| - : offset < caret_min_offset) { |
| - // Overshot to the right. |
| - InlineBox* const next_box = box->NextLeafChildIgnoringLineBreak(); |
| - if (!next_box) { |
| - PositionTemplate<Strategy> position_on_right = |
| - primary_direction == TextDirection::kLtr |
| - ? NextVisuallyDistinctCandidate(deep_position) |
| - : PreviousVisuallyDistinctCandidate(deep_position); |
| - if (position_on_right.IsNull()) |
| - return PositionTemplate<Strategy>(); |
| - |
| - InlineBox* box_on_right = |
| - ComputeInlineBoxPosition(position_on_right, affinity, |
| - primary_direction) |
| - .inline_box; |
| - if (box_on_right && box_on_right->Root() == box->Root()) |
| - return PositionTemplate<Strategy>(); |
| - return position_on_right; |
| - } |
| - |
| - // Reposition at the other logical position corresponding to our |
| - // edge's visual position and go for another round. |
| - box = next_box; |
| - layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - offset = next_box->CaretLeftmostOffset(); |
| - continue; |
| - } |
| - |
| - DCHECK_EQ(offset, box->CaretRightmostOffset()); |
| - |
| - unsigned char level = box->BidiLevel(); |
| - InlineBox* next_box = box->NextLeafChild(); |
| - |
| - if (box->Direction() == primary_direction) { |
| - if (!next_box) { |
| - InlineBox* logical_end = nullptr; |
| - if (primary_direction == TextDirection::kLtr |
| - ? box->Root().GetLogicalEndBoxWithNode(logical_end) |
| - : box->Root().GetLogicalStartBoxWithNode(logical_end)) { |
| - box = logical_end; |
| - layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - offset = primary_direction == TextDirection::kLtr |
| - ? box->CaretMaxOffset() |
| - : box->CaretMinOffset(); |
| - } |
| - break; |
| - } |
| - |
| - if (next_box->BidiLevel() >= level) |
| - break; |
| - |
| - level = next_box->BidiLevel(); |
| - |
| - InlineBox* prev_box = box; |
| - do { |
| - prev_box = prev_box->PrevLeafChild(); |
| - } while (prev_box && prev_box->BidiLevel() > level); |
| - |
| - // For example, abc FED 123 ^ CBA |
| - if (prev_box && prev_box->BidiLevel() == level) |
| - break; |
| - |
| - // For example, abc 123 ^ CBA or 123 ^ CBA abc |
| - box = next_box; |
| - layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - offset = box->CaretLeftmostOffset(); |
| - if (box->Direction() == primary_direction) |
| - break; |
| - continue; |
| - } |
| - |
| - while (next_box && !next_box->GetLineLayoutItem().GetNode()) |
| - next_box = next_box->NextLeafChild(); |
| - |
| - if (next_box) { |
| - box = next_box; |
| - layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - offset = box->CaretLeftmostOffset(); |
| - |
| - if (box->BidiLevel() > level) { |
| - do { |
| - next_box = next_box->NextLeafChild(); |
| - } while (next_box && next_box->BidiLevel() > level); |
| - |
| - if (!next_box || next_box->BidiLevel() < level) |
| - continue; |
| - } |
| - } else { |
| - // Trailing edge of a secondary run. Set to the leading edge of the |
| - // entire run. |
| - while (true) { |
| - while (InlineBox* prev_box = box->PrevLeafChild()) { |
| - if (prev_box->BidiLevel() < level) |
| - break; |
| - box = prev_box; |
| - } |
| - if (box->BidiLevel() == level) |
| - break; |
| - level = box->BidiLevel(); |
| - while (InlineBox* next_box = box->NextLeafChild()) { |
| - if (next_box->BidiLevel() < level) |
| - break; |
| - box = next_box; |
| - } |
| - if (box->BidiLevel() == level) |
| - break; |
| - level = box->BidiLevel(); |
| - } |
| - layout_object = |
| - LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()); |
| - offset = primary_direction == TextDirection::kLtr |
| - ? box->CaretMaxOffset() |
| - : box->CaretMinOffset(); |
| - } |
| - break; |
| - } |
| - |
| - p = PositionTemplate<Strategy>::EditingPositionOf(layout_object->GetNode(), |
| - offset); |
| - |
| - if ((IsVisuallyEquivalentCandidate(p) && |
| - MostForwardCaretPosition(p) != downstream_start) || |
| - p.AtStartOfTree() || p.AtEndOfTree()) |
| - return p; |
| - |
| - DCHECK_NE(p, deep_position); |
| - } |
| -} |
| - |
| -template <typename Strategy> |
| -VisiblePositionTemplate<Strategy> RightPositionOfAlgorithm( |
| - const VisiblePositionTemplate<Strategy>& visible_position) { |
| - DCHECK(visible_position.IsValid()) << visible_position; |
| - const PositionTemplate<Strategy> pos = |
| - RightVisuallyDistinctCandidate(visible_position); |
| - // TODO(editing-dev): Why can't we move left from the last position in a tree? |
| - if (pos.AtStartOfTree() || pos.AtEndOfTree()) |
| - return VisiblePositionTemplate<Strategy>(); |
| - |
| - const VisiblePositionTemplate<Strategy> right = CreateVisiblePosition(pos); |
| - DCHECK_NE(right.DeepEquivalent(), visible_position.DeepEquivalent()); |
| + const VisiblePositionTemplate<Strategy> result = CreateVisiblePosition(pos); |
| + DCHECK_NE(result.DeepEquivalent(), visible_position.DeepEquivalent()); |
| - return DirectionOfEnclosingBlockOf(right.DeepEquivalent()) == |
| - TextDirection::kLtr |
| - ? HonorEditingBoundaryAtOrAfter(right, |
| - visible_position.DeepEquivalent()) |
| - : HonorEditingBoundaryAtOrBefore( |
| - right, visible_position.DeepEquivalent()); |
| + return Traversal::HonorEditingBoundary( |
| + DirectionOfEnclosingBlockOf(result.DeepEquivalent()), result, |
| + visible_position.DeepEquivalent()); |
| } |
| } // namespace |
| VisiblePosition LeftPositionOf(const VisiblePosition& visible_position) { |
| - return LeftPositionOfAlgorithm<EditingStrategy>(visible_position); |
| + return TraverseAlgorithm<EditingStrategy, TraversalLeft<EditingStrategy>>( |
| + visible_position); |
| } |
| VisiblePositionInFlatTree LeftPositionOf( |
| const VisiblePositionInFlatTree& visible_position) { |
| - return LeftPositionOfAlgorithm<EditingInFlatTreeStrategy>(visible_position); |
| + return TraverseAlgorithm<EditingInFlatTreeStrategy, |
| + TraversalLeft<EditingInFlatTreeStrategy>>( |
| + visible_position); |
| } |
| VisiblePosition RightPositionOf(const VisiblePosition& visible_position) { |
| - return RightPositionOfAlgorithm<EditingStrategy>(visible_position); |
| + return TraverseAlgorithm<EditingStrategy, TraversalRight<EditingStrategy>>( |
| + visible_position); |
| } |
| VisiblePositionInFlatTree RightPositionOf( |
| const VisiblePositionInFlatTree& visible_position) { |
| - return RightPositionOfAlgorithm<EditingInFlatTreeStrategy>(visible_position); |
| + return TraverseAlgorithm<EditingInFlatTreeStrategy, |
| + TraversalRight<EditingInFlatTreeStrategy>>( |
| + visible_position); |
| } |
| } // namespace blink |