| 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..9809c33c2d7e2a706861c29bc6cbb9b576a4b4ab 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 and comments in
|
| +// |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.
|
| - 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
|
|
|