OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |