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

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

Issue 2930863002: Move LeftPositionOf() and RightPositionOf() to SelectionModifierCharacter.cpp (Closed)
Patch Set: 2017-06-08T18:53: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 1960 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 1971
1972 UChar32 CharacterBefore(const VisiblePosition& visible_position) { 1972 UChar32 CharacterBefore(const VisiblePosition& visible_position) {
1973 return CharacterBeforeAlgorithm<EditingStrategy>(visible_position); 1973 return CharacterBeforeAlgorithm<EditingStrategy>(visible_position);
1974 } 1974 }
1975 1975
1976 UChar32 CharacterBefore(const VisiblePositionInFlatTree& visible_position) { 1976 UChar32 CharacterBefore(const VisiblePositionInFlatTree& visible_position) {
1977 return CharacterBeforeAlgorithm<EditingInFlatTreeStrategy>(visible_position); 1977 return CharacterBeforeAlgorithm<EditingInFlatTreeStrategy>(visible_position);
1978 } 1978 }
1979 1979
1980 template <typename Strategy> 1980 template <typename Strategy>
1981 static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate(
1982 const VisiblePositionTemplate<Strategy>& visible_position) {
1983 DCHECK(visible_position.IsValid()) << visible_position;
1984 const PositionTemplate<Strategy> deep_position =
1985 visible_position.DeepEquivalent();
1986 PositionTemplate<Strategy> p = deep_position;
1987
1988 if (p.IsNull())
1989 return PositionTemplate<Strategy>();
1990
1991 const PositionTemplate<Strategy> downstream_start =
1992 MostForwardCaretPosition(p);
1993 TextDirection primary_direction = PrimaryDirectionOf(*p.AnchorNode());
1994 const TextAffinity affinity = visible_position.Affinity();
1995
1996 while (true) {
1997 InlineBoxPosition box_position =
1998 ComputeInlineBoxPosition(p, affinity, primary_direction);
1999 InlineBox* box = box_position.inline_box;
2000 int offset = box_position.offset_in_box;
2001 if (!box)
2002 return primary_direction == TextDirection::kLtr
2003 ? PreviousVisuallyDistinctCandidate(deep_position)
2004 : NextVisuallyDistinctCandidate(deep_position);
2005
2006 LineLayoutItem line_layout_item = box->GetLineLayoutItem();
2007
2008 while (true) {
2009 if ((line_layout_item.IsAtomicInlineLevel() || line_layout_item.IsBR()) &&
2010 offset == box->CaretRightmostOffset())
2011 return box->IsLeftToRightDirection()
2012 ? PreviousVisuallyDistinctCandidate(deep_position)
2013 : NextVisuallyDistinctCandidate(deep_position);
2014
2015 if (!line_layout_item.GetNode()) {
2016 box = box->PrevLeafChild();
2017 if (!box)
2018 return primary_direction == TextDirection::kLtr
2019 ? PreviousVisuallyDistinctCandidate(deep_position)
2020 : NextVisuallyDistinctCandidate(deep_position);
2021 line_layout_item = box->GetLineLayoutItem();
2022 offset = box->CaretRightmostOffset();
2023 continue;
2024 }
2025
2026 offset =
2027 box->IsLeftToRightDirection()
2028 ? PreviousGraphemeBoundaryOf(line_layout_item.GetNode(), offset)
2029 : NextGraphemeBoundaryOf(line_layout_item.GetNode(), offset);
2030
2031 int caret_min_offset = box->CaretMinOffset();
2032 int caret_max_offset = box->CaretMaxOffset();
2033
2034 if (offset > caret_min_offset && offset < caret_max_offset)
2035 break;
2036
2037 if (box->IsLeftToRightDirection() ? offset < caret_min_offset
2038 : offset > caret_max_offset) {
2039 // Overshot to the left.
2040 InlineBox* prev_box = box->PrevLeafChildIgnoringLineBreak();
2041 if (!prev_box) {
2042 PositionTemplate<Strategy> position_on_left =
2043 primary_direction == TextDirection::kLtr
2044 ? PreviousVisuallyDistinctCandidate(
2045 visible_position.DeepEquivalent())
2046 : NextVisuallyDistinctCandidate(
2047 visible_position.DeepEquivalent());
2048 if (position_on_left.IsNull())
2049 return PositionTemplate<Strategy>();
2050
2051 InlineBox* box_on_left =
2052 ComputeInlineBoxPosition(position_on_left, affinity,
2053 primary_direction)
2054 .inline_box;
2055 if (box_on_left && box_on_left->Root() == box->Root())
2056 return PositionTemplate<Strategy>();
2057 return position_on_left;
2058 }
2059
2060 // Reposition at the other logical position corresponding to our
2061 // edge's visual position and go for another round.
2062 box = prev_box;
2063 line_layout_item = box->GetLineLayoutItem();
2064 offset = prev_box->CaretRightmostOffset();
2065 continue;
2066 }
2067
2068 DCHECK_EQ(offset, box->CaretLeftmostOffset());
2069
2070 unsigned char level = box->BidiLevel();
2071 InlineBox* prev_box = box->PrevLeafChild();
2072
2073 if (box->Direction() == primary_direction) {
2074 if (!prev_box) {
2075 InlineBox* logical_start = 0;
2076 if (primary_direction == TextDirection::kLtr
2077 ? box->Root().GetLogicalStartBoxWithNode(logical_start)
2078 : box->Root().GetLogicalEndBoxWithNode(logical_start)) {
2079 box = logical_start;
2080 line_layout_item = box->GetLineLayoutItem();
2081 offset = primary_direction == TextDirection::kLtr
2082 ? box->CaretMinOffset()
2083 : box->CaretMaxOffset();
2084 }
2085 break;
2086 }
2087 if (prev_box->BidiLevel() >= level)
2088 break;
2089
2090 level = prev_box->BidiLevel();
2091
2092 InlineBox* next_box = box;
2093 do {
2094 next_box = next_box->NextLeafChild();
2095 } while (next_box && next_box->BidiLevel() > level);
2096
2097 if (next_box && next_box->BidiLevel() == level)
2098 break;
2099
2100 box = prev_box;
2101 line_layout_item = box->GetLineLayoutItem();
2102 offset = box->CaretRightmostOffset();
2103 if (box->Direction() == primary_direction)
2104 break;
2105 continue;
2106 }
2107
2108 while (prev_box && !prev_box->GetLineLayoutItem().GetNode())
2109 prev_box = prev_box->PrevLeafChild();
2110
2111 if (prev_box) {
2112 box = prev_box;
2113 line_layout_item = box->GetLineLayoutItem();
2114 offset = box->CaretRightmostOffset();
2115 if (box->BidiLevel() > level) {
2116 do {
2117 prev_box = prev_box->PrevLeafChild();
2118 } while (prev_box && prev_box->BidiLevel() > level);
2119
2120 if (!prev_box || prev_box->BidiLevel() < level)
2121 continue;
2122 }
2123 } else {
2124 // Trailing edge of a secondary run. Set to the leading edge of
2125 // the entire run.
2126 while (true) {
2127 while (InlineBox* next_box = box->NextLeafChild()) {
2128 if (next_box->BidiLevel() < level)
2129 break;
2130 box = next_box;
2131 }
2132 if (box->BidiLevel() == level)
2133 break;
2134 level = box->BidiLevel();
2135 while (InlineBox* prev_box = box->PrevLeafChild()) {
2136 if (prev_box->BidiLevel() < level)
2137 break;
2138 box = prev_box;
2139 }
2140 if (box->BidiLevel() == level)
2141 break;
2142 level = box->BidiLevel();
2143 }
2144 line_layout_item = box->GetLineLayoutItem();
2145 offset = primary_direction == TextDirection::kLtr
2146 ? box->CaretMinOffset()
2147 : box->CaretMaxOffset();
2148 }
2149 break;
2150 }
2151
2152 p = PositionTemplate<Strategy>::EditingPositionOf(
2153 line_layout_item.GetNode(), offset);
2154
2155 if ((IsVisuallyEquivalentCandidate(p) &&
2156 MostForwardCaretPosition(p) != downstream_start) ||
2157 p.AtStartOfTree() || p.AtEndOfTree())
2158 return p;
2159
2160 DCHECK_NE(p, deep_position);
2161 }
2162 }
2163
2164 template <typename Strategy>
2165 VisiblePositionTemplate<Strategy> LeftPositionOfAlgorithm(
2166 const VisiblePositionTemplate<Strategy>& visible_position) {
2167 DCHECK(visible_position.IsValid()) << visible_position;
2168 const PositionTemplate<Strategy> pos =
2169 LeftVisuallyDistinctCandidate(visible_position);
2170 // TODO(yosin) Why can't we move left from the last position in a tree?
2171 if (pos.AtStartOfTree() || pos.AtEndOfTree())
2172 return VisiblePositionTemplate<Strategy>();
2173
2174 const VisiblePositionTemplate<Strategy> left = CreateVisiblePosition(pos);
2175 DCHECK_NE(left.DeepEquivalent(), visible_position.DeepEquivalent());
2176
2177 return DirectionOfEnclosingBlockOf(left.DeepEquivalent()) ==
2178 TextDirection::kLtr
2179 ? HonorEditingBoundaryAtOrBefore(left,
2180 visible_position.DeepEquivalent())
2181 : HonorEditingBoundaryAtOrAfter(left,
2182 visible_position.DeepEquivalent());
2183 }
2184
2185 VisiblePosition LeftPositionOf(const VisiblePosition& visible_position) {
2186 return LeftPositionOfAlgorithm<EditingStrategy>(visible_position);
2187 }
2188
2189 VisiblePositionInFlatTree LeftPositionOf(
2190 const VisiblePositionInFlatTree& visible_position) {
2191 return LeftPositionOfAlgorithm<EditingInFlatTreeStrategy>(visible_position);
2192 }
2193
2194 template <typename Strategy>
2195 static PositionTemplate<Strategy> RightVisuallyDistinctCandidate(
2196 const VisiblePositionTemplate<Strategy>& visible_position) {
2197 DCHECK(visible_position.IsValid()) << visible_position;
2198 const PositionTemplate<Strategy> deep_position =
2199 visible_position.DeepEquivalent();
2200 PositionTemplate<Strategy> p = deep_position;
2201 if (p.IsNull())
2202 return PositionTemplate<Strategy>();
2203
2204 const PositionTemplate<Strategy> downstream_start =
2205 MostForwardCaretPosition(p);
2206 TextDirection primary_direction = PrimaryDirectionOf(*p.AnchorNode());
2207 const TextAffinity affinity = visible_position.Affinity();
2208
2209 while (true) {
2210 InlineBoxPosition box_position =
2211 ComputeInlineBoxPosition(p, affinity, primary_direction);
2212 InlineBox* box = box_position.inline_box;
2213 int offset = box_position.offset_in_box;
2214 if (!box)
2215 return primary_direction == TextDirection::kLtr
2216 ? NextVisuallyDistinctCandidate(deep_position)
2217 : PreviousVisuallyDistinctCandidate(deep_position);
2218
2219 LayoutObject* layout_object =
2220 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2221
2222 while (true) {
2223 if ((layout_object->IsAtomicInlineLevel() || layout_object->IsBR()) &&
2224 offset == box->CaretLeftmostOffset())
2225 return box->IsLeftToRightDirection()
2226 ? NextVisuallyDistinctCandidate(deep_position)
2227 : PreviousVisuallyDistinctCandidate(deep_position);
2228
2229 if (!layout_object->GetNode()) {
2230 box = box->NextLeafChild();
2231 if (!box)
2232 return primary_direction == TextDirection::kLtr
2233 ? NextVisuallyDistinctCandidate(deep_position)
2234 : PreviousVisuallyDistinctCandidate(deep_position);
2235 layout_object =
2236 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2237 offset = box->CaretLeftmostOffset();
2238 continue;
2239 }
2240
2241 offset =
2242 box->IsLeftToRightDirection()
2243 ? NextGraphemeBoundaryOf(layout_object->GetNode(), offset)
2244 : PreviousGraphemeBoundaryOf(layout_object->GetNode(), offset);
2245
2246 int caret_min_offset = box->CaretMinOffset();
2247 int caret_max_offset = box->CaretMaxOffset();
2248
2249 if (offset > caret_min_offset && offset < caret_max_offset)
2250 break;
2251
2252 if (box->IsLeftToRightDirection() ? offset > caret_max_offset
2253 : offset < caret_min_offset) {
2254 // Overshot to the right.
2255 InlineBox* next_box = box->NextLeafChildIgnoringLineBreak();
2256 if (!next_box) {
2257 PositionTemplate<Strategy> position_on_right =
2258 primary_direction == TextDirection::kLtr
2259 ? NextVisuallyDistinctCandidate(deep_position)
2260 : PreviousVisuallyDistinctCandidate(deep_position);
2261 if (position_on_right.IsNull())
2262 return PositionTemplate<Strategy>();
2263
2264 InlineBox* box_on_right =
2265 ComputeInlineBoxPosition(position_on_right, affinity,
2266 primary_direction)
2267 .inline_box;
2268 if (box_on_right && box_on_right->Root() == box->Root())
2269 return PositionTemplate<Strategy>();
2270 return position_on_right;
2271 }
2272
2273 // Reposition at the other logical position corresponding to our
2274 // edge's visual position and go for another round.
2275 box = next_box;
2276 layout_object =
2277 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2278 offset = next_box->CaretLeftmostOffset();
2279 continue;
2280 }
2281
2282 DCHECK_EQ(offset, box->CaretRightmostOffset());
2283
2284 unsigned char level = box->BidiLevel();
2285 InlineBox* next_box = box->NextLeafChild();
2286
2287 if (box->Direction() == primary_direction) {
2288 if (!next_box) {
2289 InlineBox* logical_end = 0;
2290 if (primary_direction == TextDirection::kLtr
2291 ? box->Root().GetLogicalEndBoxWithNode(logical_end)
2292 : box->Root().GetLogicalStartBoxWithNode(logical_end)) {
2293 box = logical_end;
2294 layout_object =
2295 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2296 offset = primary_direction == TextDirection::kLtr
2297 ? box->CaretMaxOffset()
2298 : box->CaretMinOffset();
2299 }
2300 break;
2301 }
2302
2303 if (next_box->BidiLevel() >= level)
2304 break;
2305
2306 level = next_box->BidiLevel();
2307
2308 InlineBox* prev_box = box;
2309 do {
2310 prev_box = prev_box->PrevLeafChild();
2311 } while (prev_box && prev_box->BidiLevel() > level);
2312
2313 // For example, abc FED 123 ^ CBA
2314 if (prev_box && prev_box->BidiLevel() == level)
2315 break;
2316
2317 // For example, abc 123 ^ CBA or 123 ^ CBA abc
2318 box = next_box;
2319 layout_object =
2320 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2321 offset = box->CaretLeftmostOffset();
2322 if (box->Direction() == primary_direction)
2323 break;
2324 continue;
2325 }
2326
2327 while (next_box && !next_box->GetLineLayoutItem().GetNode())
2328 next_box = next_box->NextLeafChild();
2329
2330 if (next_box) {
2331 box = next_box;
2332 layout_object =
2333 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2334 offset = box->CaretLeftmostOffset();
2335
2336 if (box->BidiLevel() > level) {
2337 do {
2338 next_box = next_box->NextLeafChild();
2339 } while (next_box && next_box->BidiLevel() > level);
2340
2341 if (!next_box || next_box->BidiLevel() < level)
2342 continue;
2343 }
2344 } else {
2345 // Trailing edge of a secondary run. Set to the leading edge of the
2346 // entire run.
2347 while (true) {
2348 while (InlineBox* prev_box = box->PrevLeafChild()) {
2349 if (prev_box->BidiLevel() < level)
2350 break;
2351 box = prev_box;
2352 }
2353 if (box->BidiLevel() == level)
2354 break;
2355 level = box->BidiLevel();
2356 while (InlineBox* next_box = box->NextLeafChild()) {
2357 if (next_box->BidiLevel() < level)
2358 break;
2359 box = next_box;
2360 }
2361 if (box->BidiLevel() == level)
2362 break;
2363 level = box->BidiLevel();
2364 }
2365 layout_object =
2366 LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
2367 offset = primary_direction == TextDirection::kLtr
2368 ? box->CaretMaxOffset()
2369 : box->CaretMinOffset();
2370 }
2371 break;
2372 }
2373
2374 p = PositionTemplate<Strategy>::EditingPositionOf(layout_object->GetNode(),
2375 offset);
2376
2377 if ((IsVisuallyEquivalentCandidate(p) &&
2378 MostForwardCaretPosition(p) != downstream_start) ||
2379 p.AtStartOfTree() || p.AtEndOfTree())
2380 return p;
2381
2382 DCHECK_NE(p, deep_position);
2383 }
2384 }
2385
2386 template <typename Strategy>
2387 static VisiblePositionTemplate<Strategy> RightPositionOfAlgorithm(
2388 const VisiblePositionTemplate<Strategy>& visible_position) {
2389 DCHECK(visible_position.IsValid()) << visible_position;
2390 const PositionTemplate<Strategy> pos =
2391 RightVisuallyDistinctCandidate(visible_position);
2392 // FIXME: Why can't we move left from the last position in a tree?
2393 if (pos.AtStartOfTree() || pos.AtEndOfTree())
2394 return VisiblePositionTemplate<Strategy>();
2395
2396 const VisiblePositionTemplate<Strategy> right = CreateVisiblePosition(pos);
2397 DCHECK_NE(right.DeepEquivalent(), visible_position.DeepEquivalent());
2398
2399 return DirectionOfEnclosingBlockOf(right.DeepEquivalent()) ==
2400 TextDirection::kLtr
2401 ? HonorEditingBoundaryAtOrAfter(right,
2402 visible_position.DeepEquivalent())
2403 : HonorEditingBoundaryAtOrBefore(
2404 right, visible_position.DeepEquivalent());
2405 }
2406
2407 VisiblePosition RightPositionOf(const VisiblePosition& visible_position) {
2408 return RightPositionOfAlgorithm<EditingStrategy>(visible_position);
2409 }
2410
2411 VisiblePositionInFlatTree RightPositionOf(
2412 const VisiblePositionInFlatTree& visible_position) {
2413 return RightPositionOfAlgorithm<EditingInFlatTreeStrategy>(visible_position);
2414 }
2415
2416 template <typename Strategy>
2417 static VisiblePositionTemplate<Strategy> NextPositionOfAlgorithm( 1981 static VisiblePositionTemplate<Strategy> NextPositionOfAlgorithm(
2418 const PositionWithAffinityTemplate<Strategy>& position, 1982 const PositionWithAffinityTemplate<Strategy>& position,
2419 EditingBoundaryCrossingRule rule) { 1983 EditingBoundaryCrossingRule rule) {
2420 const VisiblePositionTemplate<Strategy> next = CreateVisiblePosition( 1984 const VisiblePositionTemplate<Strategy> next = CreateVisiblePosition(
2421 NextVisuallyDistinctCandidate(position.GetPosition()), 1985 NextVisuallyDistinctCandidate(position.GetPosition()),
2422 position.Affinity()); 1986 position.Affinity());
2423 1987
2424 switch (rule) { 1988 switch (rule) {
2425 case kCanCrossEditingBoundary: 1989 case kCanCrossEditingBoundary:
2426 return next; 1990 return next;
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2620 2184
2621 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { 2185 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) {
2622 return EnclosingIntRect(ComputeTextRectTemplate(range)); 2186 return EnclosingIntRect(ComputeTextRectTemplate(range));
2623 } 2187 }
2624 2188
2625 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { 2189 FloatRect ComputeTextFloatRect(const EphemeralRange& range) {
2626 return ComputeTextRectTemplate(range); 2190 return ComputeTextRectTemplate(range);
2627 } 2191 }
2628 2192
2629 } // namespace blink 2193 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/VisibleUnits.h ('k') | third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698