Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
| index 8bf72e4bb23fdd0318d0ae852edb090b2a798f10..b9c70ccd23c3f09a9e39706d2d157ce810d3b37e 100644 |
| --- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
| +++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
| @@ -882,90 +882,127 @@ static bool IsStartOfDifferentDirection(const InlineBox* inline_box) { |
| return prev_box->BidiLevel() > inline_box->BidiLevel(); |
| } |
| +// TODO(yosin): We have a forward declaration here to reduce patch size. We'll |
| +// replica this with an implementation once review finished. |
| +static InlineBoxPosition ComputeInlineBoxPositionInternal(LayoutObject*, |
| + InlineBox*, |
| + int, |
| + TextDirection); |
| + |
| +// TODO(yosin): We have a forward declaration here to reduce patch size. We'll |
| +// replica this with an implementation once review finished. |
| +static InlineBoxPosition ComputeInlineBoxPositionForTextNode(LayoutText*, |
| + int, |
| + TextAffinity, |
| + TextDirection); |
| + |
| template <typename Strategy> |
| static InlineBoxPosition ComputeInlineBoxPositionTemplate( |
| const PositionTemplate<Strategy>& position, |
| TextAffinity affinity, |
| TextDirection primary_direction) { |
| - InlineBox* inline_box = nullptr; |
| - int caret_offset = position.ComputeEditingOffset(); |
| + const int caret_offset = position.ComputeEditingOffset(); |
| Node* const anchor_node = position.AnchorNode(); |
| - LayoutObject* layout_object = |
| + LayoutObject* const layout_object = |
| anchor_node->IsShadowRoot() |
| ? ToShadowRoot(anchor_node)->host().GetLayoutObject() |
| : anchor_node->GetLayoutObject(); |
| DCHECK(layout_object) << position; |
| - if (!layout_object->IsText()) { |
| - inline_box = 0; |
| - if (CanHaveChildrenForEditing(anchor_node) && |
| - layout_object->IsLayoutBlockFlow() && |
| - HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) { |
| - // Try a visually equivalent position with possibly opposite |
| - // editability. This helps in case |this| is in an editable block |
| - // but surrounded by non-editable positions. It acts to negate the |
| - // logic at the beginning of |
| - // |LayoutObject::createPositionWithAffinity()|. |
| - PositionTemplate<Strategy> equivalent = |
| - DownstreamIgnoringEditingBoundaries(position); |
| - if (equivalent == position) { |
| - equivalent = UpstreamIgnoringEditingBoundaries(position); |
| - if (equivalent == position || |
| - DownstreamIgnoringEditingBoundaries(equivalent) == position) |
| - return InlineBoxPosition(inline_box, caret_offset); |
| - } |
| - |
| - return ComputeInlineBoxPosition(equivalent, TextAffinity::kUpstream, |
| - primary_direction); |
| - } |
| - if (layout_object->IsBox()) { |
| - inline_box = ToLayoutBox(layout_object)->InlineBoxWrapper(); |
| - if (!inline_box || (caret_offset > inline_box->CaretMinOffset() && |
| - caret_offset < inline_box->CaretMaxOffset())) |
| - return InlineBoxPosition(inline_box, caret_offset); |
| + if (layout_object->IsText()) { |
| + return ComputeInlineBoxPositionForTextNode( |
| + ToLayoutText(layout_object), caret_offset, affinity, primary_direction); |
| + } |
| + if (CanHaveChildrenForEditing(anchor_node) && |
| + layout_object->IsLayoutBlockFlow() && |
| + HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) { |
| + // Try a visually equivalent position with possibly opposite |
| + // editability. This helps in case |this| is in an editable block |
| + // but surrounded by non-editable positions. It acts to negate the |
| + // logic at the beginning of |
| + // |LayoutObject::createPositionWithAffinity()|. |
| + const PositionTemplate<Strategy>& downstream_equivalent = |
| + DownstreamIgnoringEditingBoundaries(position); |
| + if (downstream_equivalent != position) { |
| + return ComputeInlineBoxPosition( |
| + downstream_equivalent, TextAffinity::kUpstream, primary_direction); |
| } |
| - } else { |
| - LayoutText* text_layout_object = ToLayoutText(layout_object); |
| - |
| - InlineTextBox* candidate = nullptr; |
| - |
| - for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) { |
| - int caret_min_offset = box->CaretMinOffset(); |
| - int caret_max_offset = box->CaretMaxOffset(); |
| + const PositionTemplate<Strategy>& upstream_equivalent = |
| + UpstreamIgnoringEditingBoundaries(position); |
| + if (upstream_equivalent == position || |
| + DownstreamIgnoringEditingBoundaries(upstream_equivalent) == position) |
| + return InlineBoxPosition(); |
| + return ComputeInlineBoxPosition(upstream_equivalent, |
| + TextAffinity::kUpstream, primary_direction); |
| + } |
| + if (!layout_object->IsBox()) |
| + return InlineBoxPosition(); |
| + InlineBox* const box = ToLayoutBox(layout_object)->InlineBoxWrapper(); |
| + if (!box) |
| + return InlineBoxPosition(); |
| + if (caret_offset > box->CaretMinOffset() && |
| + caret_offset < box->CaretMaxOffset()) { |
| + return InlineBoxPosition(box, caret_offset); |
| + } |
| + return ComputeInlineBoxPositionInternal(layout_object, box, caret_offset, |
| + primary_direction); |
| +} |
| - if (caret_offset < caret_min_offset || caret_offset > caret_max_offset || |
| - (caret_offset == caret_max_offset && box->IsLineBreak())) |
| - continue; |
| +static InlineBoxPosition ComputeInlineBoxPositionForTextNode( |
| + LayoutText* text_layout_object, |
| + int caret_offset, |
| + TextAffinity affinity, |
| + TextDirection primary_direction) { |
| + InlineTextBox* inline_box = nullptr; |
| + InlineTextBox* candidate = nullptr; |
| + for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) { |
| + const int caret_min_offset = box->CaretMinOffset(); |
| + const int caret_max_offset = box->CaretMaxOffset(); |
| - if (caret_offset > caret_min_offset && caret_offset < caret_max_offset) |
| - return InlineBoxPosition(box, caret_offset); |
| + if (caret_offset < caret_min_offset || caret_offset > caret_max_offset || |
| + (caret_offset == caret_max_offset && box->IsLineBreak())) |
| + continue; |
| - if (((caret_offset == caret_max_offset) ^ |
| - (affinity == TextAffinity::kDownstream)) || |
| - ((caret_offset == caret_min_offset) ^ |
| - (affinity == TextAffinity::kUpstream)) || |
| - (caret_offset == caret_max_offset && box->NextLeafChild() && |
| - box->NextLeafChild()->IsLineBreak())) { |
| - inline_box = box; |
| - break; |
| - } |
| + if (caret_offset > caret_min_offset && caret_offset < caret_max_offset) |
| + return InlineBoxPosition(box, caret_offset); |
| - candidate = box; |
| + if (((caret_offset == caret_max_offset) ^ |
| + (affinity == TextAffinity::kDownstream)) || |
| + ((caret_offset == caret_min_offset) ^ |
| + (affinity == TextAffinity::kUpstream)) || |
| + (caret_offset == caret_max_offset && box->NextLeafChild() && |
| + box->NextLeafChild()->IsLineBreak())) { |
| + inline_box = box; |
| + break; |
| } |
| - if (candidate && candidate == text_layout_object->LastTextBox() && |
| - affinity == TextAffinity::kDownstream) { |
| - inline_box = SearchAheadForBetterMatch(text_layout_object); |
|
Xiaocheng
2017/06/08 21:34:12
I don't understand this part.
It seems to be sett
yosin_UTC9
2017/06/09 01:55:55
Setting |inline_box| is one in the loop at L976. A
|
| - if (inline_box) |
| - caret_offset = inline_box->CaretMinOffset(); |
| + |
| + candidate = box; |
| + } |
| + if (candidate && candidate == text_layout_object->LastTextBox() && |
| + affinity == TextAffinity::kDownstream) { |
| + if (InlineBox* found = SearchAheadForBetterMatch(text_layout_object)) { |
| + return ComputeInlineBoxPositionInternal(text_layout_object, found, |
| + found->CaretMinOffset(), |
| + primary_direction); |
| } |
| - if (!inline_box) |
| - inline_box = candidate; |
| } |
| + if (inline_box) { |
| + return ComputeInlineBoxPositionInternal(text_layout_object, inline_box, |
| + caret_offset, primary_direction); |
| + } |
| + if (candidate) { |
| + return ComputeInlineBoxPositionInternal(text_layout_object, candidate, |
| + caret_offset, primary_direction); |
| + } |
| + return InlineBoxPosition(); |
| +} |
| - if (!inline_box) |
| - return InlineBoxPosition(inline_box, caret_offset); |
| - |
| +static InlineBoxPosition ComputeInlineBoxPositionInternal( |
| + LayoutObject* layout_object, |
| + InlineBox* inline_box, |
| + int caret_offset, |
| + TextDirection primary_direction) { |
| unsigned char level = inline_box->BidiLevel(); |
| if (inline_box->Direction() == primary_direction) { |
| @@ -1040,8 +1077,7 @@ static InlineBoxPosition ComputeInlineBoxPositionTemplate( |
| return InlineBoxPosition(inline_box, caret_offset); |
| } |
| - if (layout_object && |
| - layout_object->Style()->GetUnicodeBidi() == UnicodeBidi::kPlaintext) { |
| + if (layout_object->Style()->GetUnicodeBidi() == UnicodeBidi::kPlaintext) { |
| if (inline_box->BidiLevel() < level) |
| return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset()); |
| return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset()); |
| @@ -1128,12 +1164,14 @@ LayoutRect LocalCaretRectOfPositionTemplate( |
| InlineBoxPosition box_position = |
| ComputeInlineBoxPosition(position.GetPosition(), position.Affinity()); |
| - if (box_position.inline_box) |
| - layout_object = LineLayoutAPIShim::LayoutObjectFrom( |
| - box_position.inline_box->GetLineLayoutItem()); |
| + if (box_position.inline_box) { |
| + return LineLayoutAPIShim::LayoutObjectFrom( |
| + box_position.inline_box->GetLineLayoutItem()) |
| + ->LocalCaretRect(box_position.inline_box, box_position.offset_in_box); |
| + } |
| - return layout_object->LocalCaretRect(box_position.inline_box, |
| - box_position.offset_in_box); |
| + return layout_object->LocalCaretRect( |
|
yosin_UTC9
2017/06/08 10:19:24
Since ComputeInlineBoxPosition() returns offset ze
|
| + nullptr, position.GetPosition().ComputeEditingOffset()); |
| } |
| // This function was added because the caret rect that is calculated by |