Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: third_party/WebKit/Source/core/editing/VisibleUnits.cpp

Issue 2925063002: ALL-IN-ONE: Refactor ComputeInlineBoxPosition() (Closed)
Patch Set: 2017-06-08T19:15:47 Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 static bool IsStartOfDifferentDirection(const InlineBox* inline_box) { 875 static bool IsStartOfDifferentDirection(const InlineBox* inline_box) {
876 InlineBox* prev_box = inline_box->PrevLeafChild(); 876 InlineBox* prev_box = inline_box->PrevLeafChild();
877 if (!prev_box) 877 if (!prev_box)
878 return true; 878 return true;
879 if (prev_box->Direction() == inline_box->Direction()) 879 if (prev_box->Direction() == inline_box->Direction())
880 return true; 880 return true;
881 DCHECK_NE(prev_box->BidiLevel(), inline_box->BidiLevel()); 881 DCHECK_NE(prev_box->BidiLevel(), inline_box->BidiLevel());
882 return prev_box->BidiLevel() > inline_box->BidiLevel(); 882 return prev_box->BidiLevel() > inline_box->BidiLevel();
883 } 883 }
884 884
885 // TODO(yosin): We have a forward declaration here to reduce patch size. We'll
886 // replica this with an implementation once review finished.
887 static InlineBoxPosition ComputeInlineBoxPositionInternal(LayoutObject*,
888 InlineBox*,
889 int,
890 TextDirection);
891
892 // TODO(yosin): We have a forward declaration here to reduce patch size. We'll
893 // replica this with an implementation once review finished.
894 static InlineBoxPosition ComputeInlineBoxPositionForTextNode(LayoutText*,
895 int,
896 TextAffinity,
897 TextDirection);
898
885 template <typename Strategy> 899 template <typename Strategy>
886 static InlineBoxPosition ComputeInlineBoxPositionTemplate( 900 static InlineBoxPosition ComputeInlineBoxPositionTemplate(
887 const PositionTemplate<Strategy>& position, 901 const PositionTemplate<Strategy>& position,
888 TextAffinity affinity, 902 TextAffinity affinity,
889 TextDirection primary_direction) { 903 TextDirection primary_direction) {
890 InlineBox* inline_box = nullptr; 904 const int caret_offset = position.ComputeEditingOffset();
891 int caret_offset = position.ComputeEditingOffset();
892 Node* const anchor_node = position.AnchorNode(); 905 Node* const anchor_node = position.AnchorNode();
893 LayoutObject* layout_object = 906 LayoutObject* const layout_object =
894 anchor_node->IsShadowRoot() 907 anchor_node->IsShadowRoot()
895 ? ToShadowRoot(anchor_node)->host().GetLayoutObject() 908 ? ToShadowRoot(anchor_node)->host().GetLayoutObject()
896 : anchor_node->GetLayoutObject(); 909 : anchor_node->GetLayoutObject();
897 910
898 DCHECK(layout_object) << position; 911 DCHECK(layout_object) << position;
899 912
900 if (!layout_object->IsText()) { 913 if (layout_object->IsText()) {
901 inline_box = 0; 914 return ComputeInlineBoxPositionForTextNode(
902 if (CanHaveChildrenForEditing(anchor_node) && 915 ToLayoutText(layout_object), caret_offset, affinity, primary_direction);
903 layout_object->IsLayoutBlockFlow() && 916 }
904 HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) { 917 if (CanHaveChildrenForEditing(anchor_node) &&
905 // Try a visually equivalent position with possibly opposite 918 layout_object->IsLayoutBlockFlow() &&
906 // editability. This helps in case |this| is in an editable block 919 HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) {
907 // but surrounded by non-editable positions. It acts to negate the 920 // Try a visually equivalent position with possibly opposite
908 // logic at the beginning of 921 // editability. This helps in case |this| is in an editable block
909 // |LayoutObject::createPositionWithAffinity()|. 922 // but surrounded by non-editable positions. It acts to negate the
910 PositionTemplate<Strategy> equivalent = 923 // logic at the beginning of
911 DownstreamIgnoringEditingBoundaries(position); 924 // |LayoutObject::createPositionWithAffinity()|.
912 if (equivalent == position) { 925 const PositionTemplate<Strategy>& downstream_equivalent =
913 equivalent = UpstreamIgnoringEditingBoundaries(position); 926 DownstreamIgnoringEditingBoundaries(position);
914 if (equivalent == position || 927 if (downstream_equivalent != position) {
915 DownstreamIgnoringEditingBoundaries(equivalent) == position) 928 return ComputeInlineBoxPosition(
916 return InlineBoxPosition(inline_box, caret_offset); 929 downstream_equivalent, TextAffinity::kUpstream, primary_direction);
917 } 930 }
931 const PositionTemplate<Strategy>& upstream_equivalent =
932 UpstreamIgnoringEditingBoundaries(position);
933 if (upstream_equivalent == position ||
934 DownstreamIgnoringEditingBoundaries(upstream_equivalent) == position)
935 return InlineBoxPosition();
936 return ComputeInlineBoxPosition(upstream_equivalent,
937 TextAffinity::kUpstream, primary_direction);
938 }
939 if (!layout_object->IsBox())
940 return InlineBoxPosition();
941 InlineBox* const box = ToLayoutBox(layout_object)->InlineBoxWrapper();
942 if (!box)
943 return InlineBoxPosition();
944 if (caret_offset > box->CaretMinOffset() &&
945 caret_offset < box->CaretMaxOffset()) {
946 return InlineBoxPosition(box, caret_offset);
947 }
948 return ComputeInlineBoxPositionInternal(layout_object, box, caret_offset,
949 primary_direction);
950 }
918 951
919 return ComputeInlineBoxPosition(equivalent, TextAffinity::kUpstream, 952 static InlineBoxPosition ComputeInlineBoxPositionForTextNode(
920 primary_direction); 953 LayoutText* text_layout_object,
954 int caret_offset,
955 TextAffinity affinity,
956 TextDirection primary_direction) {
957 InlineTextBox* inline_box = nullptr;
958 InlineTextBox* candidate = nullptr;
959 for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) {
960 const int caret_min_offset = box->CaretMinOffset();
961 const int caret_max_offset = box->CaretMaxOffset();
962
963 if (caret_offset < caret_min_offset || caret_offset > caret_max_offset ||
964 (caret_offset == caret_max_offset && box->IsLineBreak()))
965 continue;
966
967 if (caret_offset > caret_min_offset && caret_offset < caret_max_offset)
968 return InlineBoxPosition(box, caret_offset);
969
970 if (((caret_offset == caret_max_offset) ^
971 (affinity == TextAffinity::kDownstream)) ||
972 ((caret_offset == caret_min_offset) ^
973 (affinity == TextAffinity::kUpstream)) ||
974 (caret_offset == caret_max_offset && box->NextLeafChild() &&
975 box->NextLeafChild()->IsLineBreak())) {
976 inline_box = box;
977 break;
921 } 978 }
922 if (layout_object->IsBox()) { 979
923 inline_box = ToLayoutBox(layout_object)->InlineBoxWrapper(); 980 candidate = box;
924 if (!inline_box || (caret_offset > inline_box->CaretMinOffset() && 981 }
925 caret_offset < inline_box->CaretMaxOffset())) 982 if (candidate && candidate == text_layout_object->LastTextBox() &&
926 return InlineBoxPosition(inline_box, caret_offset); 983 affinity == TextAffinity::kDownstream) {
984 if (InlineBox* found = SearchAheadForBetterMatch(text_layout_object)) {
985 return ComputeInlineBoxPositionInternal(text_layout_object, found,
986 found->CaretMinOffset(),
987 primary_direction);
927 } 988 }
928 } else { 989 }
929 LayoutText* text_layout_object = ToLayoutText(layout_object); 990 if (inline_box) {
991 return ComputeInlineBoxPositionInternal(text_layout_object, inline_box,
992 caret_offset, primary_direction);
993 }
994 if (candidate) {
995 return ComputeInlineBoxPositionInternal(text_layout_object, candidate,
996 caret_offset, primary_direction);
997 }
998 return InlineBoxPosition();
999 }
930 1000
931 InlineTextBox* candidate = nullptr; 1001 static InlineBoxPosition ComputeInlineBoxPositionInternal(
932 1002 LayoutObject* layout_object,
933 for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) { 1003 InlineBox* inline_box,
934 int caret_min_offset = box->CaretMinOffset(); 1004 int caret_offset,
935 int caret_max_offset = box->CaretMaxOffset(); 1005 TextDirection primary_direction) {
936
937 if (caret_offset < caret_min_offset || caret_offset > caret_max_offset ||
938 (caret_offset == caret_max_offset && box->IsLineBreak()))
939 continue;
940
941 if (caret_offset > caret_min_offset && caret_offset < caret_max_offset)
942 return InlineBoxPosition(box, caret_offset);
943
944 if (((caret_offset == caret_max_offset) ^
945 (affinity == TextAffinity::kDownstream)) ||
946 ((caret_offset == caret_min_offset) ^
947 (affinity == TextAffinity::kUpstream)) ||
948 (caret_offset == caret_max_offset && box->NextLeafChild() &&
949 box->NextLeafChild()->IsLineBreak())) {
950 inline_box = box;
951 break;
952 }
953
954 candidate = box;
955 }
956 if (candidate && candidate == text_layout_object->LastTextBox() &&
957 affinity == TextAffinity::kDownstream) {
958 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
959 if (inline_box)
960 caret_offset = inline_box->CaretMinOffset();
961 }
962 if (!inline_box)
963 inline_box = candidate;
964 }
965
966 if (!inline_box)
967 return InlineBoxPosition(inline_box, caret_offset);
968
969 unsigned char level = inline_box->BidiLevel(); 1006 unsigned char level = inline_box->BidiLevel();
970 1007
971 if (inline_box->Direction() == primary_direction) { 1008 if (inline_box->Direction() == primary_direction) {
972 if (caret_offset == inline_box->CaretRightmostOffset()) { 1009 if (caret_offset == inline_box->CaretRightmostOffset()) {
973 InlineBox* next_box = inline_box->NextLeafChild(); 1010 InlineBox* next_box = inline_box->NextLeafChild();
974 if (!next_box || next_box->BidiLevel() >= level) 1011 if (!next_box || next_box->BidiLevel() >= level)
975 return InlineBoxPosition(inline_box, caret_offset); 1012 return InlineBoxPosition(inline_box, caret_offset);
976 1013
977 level = next_box->BidiLevel(); 1014 level = next_box->BidiLevel();
978 InlineBox* prev_box = inline_box; 1015 InlineBox* prev_box = inline_box;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 inline_box->PrevLeafChildIgnoringLineBreak()) { 1070 inline_box->PrevLeafChildIgnoringLineBreak()) {
1034 if (tertiary_box->BidiLevel() <= level) 1071 if (tertiary_box->BidiLevel() <= level)
1035 break; 1072 break;
1036 inline_box = tertiary_box; 1073 inline_box = tertiary_box;
1037 } 1074 }
1038 return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset()); 1075 return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset());
1039 } 1076 }
1040 return InlineBoxPosition(inline_box, caret_offset); 1077 return InlineBoxPosition(inline_box, caret_offset);
1041 } 1078 }
1042 1079
1043 if (layout_object && 1080 if (layout_object->Style()->GetUnicodeBidi() == UnicodeBidi::kPlaintext) {
1044 layout_object->Style()->GetUnicodeBidi() == UnicodeBidi::kPlaintext) {
1045 if (inline_box->BidiLevel() < level) 1081 if (inline_box->BidiLevel() < level)
1046 return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset()); 1082 return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset());
1047 return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset()); 1083 return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset());
1048 } 1084 }
1049 1085
1050 InlineBox* next_box = inline_box->NextLeafChildIgnoringLineBreak(); 1086 InlineBox* next_box = inline_box->NextLeafChildIgnoringLineBreak();
1051 if (!next_box || next_box->BidiLevel() < level) { 1087 if (!next_box || next_box->BidiLevel() < level) {
1052 // Right edge of a secondary run. Set to the left edge of the entire 1088 // Right edge of a secondary run. Set to the left edge of the entire
1053 // run. 1089 // run.
1054 while (InlineBox* prev_box = inline_box->PrevLeafChildIgnoringLineBreak()) { 1090 while (InlineBox* prev_box = inline_box->PrevLeafChildIgnoringLineBreak()) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 } 1157 }
1122 Node* node = position.AnchorNode(); 1158 Node* node = position.AnchorNode();
1123 1159
1124 layout_object = node->GetLayoutObject(); 1160 layout_object = node->GetLayoutObject();
1125 if (!layout_object) 1161 if (!layout_object)
1126 return LayoutRect(); 1162 return LayoutRect();
1127 1163
1128 InlineBoxPosition box_position = 1164 InlineBoxPosition box_position =
1129 ComputeInlineBoxPosition(position.GetPosition(), position.Affinity()); 1165 ComputeInlineBoxPosition(position.GetPosition(), position.Affinity());
1130 1166
1131 if (box_position.inline_box) 1167 if (box_position.inline_box) {
1132 layout_object = LineLayoutAPIShim::LayoutObjectFrom( 1168 return LineLayoutAPIShim::LayoutObjectFrom(
1133 box_position.inline_box->GetLineLayoutItem()); 1169 box_position.inline_box->GetLineLayoutItem())
1170 ->LocalCaretRect(box_position.inline_box, box_position.offset_in_box);
1171 }
1134 1172
1135 return layout_object->LocalCaretRect(box_position.inline_box, 1173 return layout_object->LocalCaretRect(
yosin_UTC9 2017/06/08 10:19:24 Since ComputeInlineBoxPosition() returns offset ze
1136 box_position.offset_in_box); 1174 nullptr, position.GetPosition().ComputeEditingOffset());
1137 } 1175 }
1138 1176
1139 // This function was added because the caret rect that is calculated by 1177 // This function was added because the caret rect that is calculated by
1140 // using the line top value instead of the selection top. 1178 // using the line top value instead of the selection top.
1141 template <typename Strategy> 1179 template <typename Strategy>
1142 LayoutRect LocalSelectionRectOfPositionTemplate( 1180 LayoutRect LocalSelectionRectOfPositionTemplate(
1143 const PositionWithAffinityTemplate<Strategy>& position, 1181 const PositionWithAffinityTemplate<Strategy>& position,
1144 LayoutObject*& layout_object) { 1182 LayoutObject*& layout_object) {
1145 if (position.IsNull()) { 1183 if (position.IsNull()) {
1146 layout_object = nullptr; 1184 layout_object = nullptr;
(...skipping 1470 matching lines...) Expand 10 before | Expand all | Expand 10 after
2617 2655
2618 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { 2656 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) {
2619 return EnclosingIntRect(ComputeTextRectTemplate(range)); 2657 return EnclosingIntRect(ComputeTextRectTemplate(range));
2620 } 2658 }
2621 2659
2622 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { 2660 FloatRect ComputeTextFloatRect(const EphemeralRange& range) {
2623 return ComputeTextRectTemplate(range); 2661 return ComputeTextRectTemplate(range);
2624 } 2662 }
2625 2663
2626 } // namespace blink 2664 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698