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

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

Issue 1404423005: Make most{Backward,Forward}CaretPosition() to handle first-letter pseudo element (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2015-11-02T14:06:55 Created 5 years, 1 month 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 reserv ed. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 11 matching lines...) Expand all
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/editing/VisibleUnits.h" 27 #include "core/editing/VisibleUnits.h"
28 28
29 #include "core/HTMLNames.h" 29 #include "core/HTMLNames.h"
30 #include "core/dom/Document.h" 30 #include "core/dom/Document.h"
31 #include "core/dom/Element.h" 31 #include "core/dom/Element.h"
32 #include "core/dom/FirstLetterPseudoElement.h"
32 #include "core/dom/NodeTraversal.h" 33 #include "core/dom/NodeTraversal.h"
33 #include "core/dom/Text.h" 34 #include "core/dom/Text.h"
34 #include "core/editing/EditingUtilities.h" 35 #include "core/editing/EditingUtilities.h"
35 #include "core/editing/FrameSelection.h" 36 #include "core/editing/FrameSelection.h"
36 #include "core/editing/Position.h" 37 #include "core/editing/Position.h"
37 #include "core/editing/PositionIterator.h" 38 #include "core/editing/PositionIterator.h"
38 #include "core/editing/RenderedPosition.h" 39 #include "core/editing/RenderedPosition.h"
39 #include "core/editing/TextAffinity.h" 40 #include "core/editing/TextAffinity.h"
40 #include "core/editing/VisiblePosition.h" 41 #include "core/editing/VisiblePosition.h"
41 #include "core/editing/iterators/BackwardsCharacterIterator.h" 42 #include "core/editing/iterators/BackwardsCharacterIterator.h"
42 #include "core/editing/iterators/CharacterIterator.h" 43 #include "core/editing/iterators/CharacterIterator.h"
43 #include "core/editing/iterators/SimplifiedBackwardsTextIterator.h" 44 #include "core/editing/iterators/SimplifiedBackwardsTextIterator.h"
44 #include "core/editing/iterators/TextIterator.h" 45 #include "core/editing/iterators/TextIterator.h"
45 #include "core/frame/LocalFrame.h" 46 #include "core/frame/LocalFrame.h"
46 #include "core/frame/Settings.h" 47 #include "core/frame/Settings.h"
47 #include "core/html/HTMLBRElement.h" 48 #include "core/html/HTMLBRElement.h"
48 #include "core/html/HTMLTextFormControlElement.h" 49 #include "core/html/HTMLTextFormControlElement.h"
49 #include "core/layout/HitTestRequest.h" 50 #include "core/layout/HitTestRequest.h"
50 #include "core/layout/HitTestResult.h" 51 #include "core/layout/HitTestResult.h"
51 #include "core/layout/LayoutBlockFlow.h" 52 #include "core/layout/LayoutBlockFlow.h"
52 #include "core/layout/LayoutInline.h" 53 #include "core/layout/LayoutInline.h"
53 #include "core/layout/LayoutObject.h" 54 #include "core/layout/LayoutObject.h"
55 #include "core/layout/LayoutTextFragment.h"
54 #include "core/layout/LayoutView.h" 56 #include "core/layout/LayoutView.h"
55 #include "core/layout/line/InlineIterator.h" 57 #include "core/layout/line/InlineIterator.h"
56 #include "core/layout/line/InlineTextBox.h" 58 #include "core/layout/line/InlineTextBox.h"
57 #include "core/paint/PaintLayer.h" 59 #include "core/paint/PaintLayer.h"
58 #include "platform/Logging.h" 60 #include "platform/Logging.h"
59 #include "platform/RuntimeEnabledFeatures.h" 61 #include "platform/RuntimeEnabledFeatures.h"
60 #include "platform/heap/Handle.h" 62 #include "platform/heap/Handle.h"
61 #include "platform/text/TextBoundaries.h" 63 #include "platform/text/TextBoundaries.h"
62 64
63 namespace blink { 65 namespace blink {
(...skipping 2078 matching lines...) Expand 10 before | Expand all | Expand 10 after
2142 { 2144 {
2143 HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | H itTestRequest::Active | HitTestRequest::IgnoreClipping; 2145 HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | H itTestRequest::Active | HitTestRequest::IgnoreClipping;
2144 HitTestResult result(request, contentsPoint); 2146 HitTestResult result(request, contentsPoint);
2145 frame->document()->layoutView()->hitTest(result); 2147 frame->document()->layoutView()->hitTest(result);
2146 2148
2147 if (Node* node = result.innerNode()) 2149 if (Node* node = result.innerNode())
2148 return frame->selection().selection().visiblePositionRespectingEditingBo undary(result.localPoint(), node); 2150 return frame->selection().selection().visiblePositionRespectingEditingBo undary(result.localPoint(), node);
2149 return VisiblePosition(); 2151 return VisiblePosition();
2150 } 2152 }
2151 2153
2154 // TODO(yosin): We should use |associatedLayoutObjectOf()| in "VisibleUnits.cpp"
2155 // where it takes |LayoutObject| from |Position|.
2156 static LayoutObject* associatedLayoutObjectOf(const Node& node, int offsetInNode )
2157 {
2158 ASSERT(offsetInNode >= 0);
2159 LayoutObject* layoutObject = node.layoutObject();
2160 if (!node.isTextNode() || !layoutObject || !toLayoutText(layoutObject)->isTe xtFragment())
2161 return layoutObject;
2162 LayoutTextFragment* layoutTextFragment = toLayoutTextFragment(layoutObject);
2163 if (layoutTextFragment->isRemainingTextLayoutObject()) {
2164 if (static_cast<unsigned>(offsetInNode) >= layoutTextFragment->start())
2165 return layoutObject;
2166 LayoutObject* firstLetterLayoutObject = layoutTextFragment->firstLetterP seudoElement()->layoutObject();
2167 if (!firstLetterLayoutObject)
2168 return nullptr;
2169 // TODO(yosin): We're not sure when |firstLetterLayoutObject| has
2170 // multiple child layout object.
2171 ASSERT(firstLetterLayoutObject->slowFirstChild() == firstLetterLayoutObj ect->slowLastChild());
2172 return firstLetterLayoutObject->slowFirstChild();
2173 }
2174 // TODO(yosin): We should rename |LayoutTextFramge::length()| instead of
2175 // |end()|, once |LayoutTextFramge| has it. See http://crbug.com/545789
2176 ASSERT(static_cast<unsigned>(offsetInNode) <= layoutTextFragment->start() + layoutTextFragment->fragmentLength());
2177 return layoutTextFragment;
2178 }
2179
2152 template <typename Strategy> 2180 template <typename Strategy>
2153 static bool inRenderedText(const PositionTemplate<Strategy>& position) 2181 static bool inRenderedText(const PositionTemplate<Strategy>& position)
2154 { 2182 {
2155 Node* const anchorNode = position.anchorNode(); 2183 Node* const anchorNode = position.anchorNode();
2156 if (!anchorNode || !anchorNode->isTextNode()) 2184 if (!anchorNode || !anchorNode->isTextNode())
2157 return false; 2185 return false;
2158 2186
yoichio 2015/11/05 04:00:15 Could you use |Text* const anchorText = toText(anc
yosin_UTC9 2015/11/05 04:22:47 No, since it is used only one place, L2188, introd
2159 LayoutObject* layoutObject = anchorNode->layoutObject(); 2187 const int offsetInNode = position.computeEditingOffset();
2188 LayoutObject* layoutObject = associatedLayoutObjectOf(*anchorNode, offsetInN ode);
2160 if (!layoutObject) 2189 if (!layoutObject)
2161 return false; 2190 return false;
2162 2191
2163 const int offsetInNode = position.computeEditingOffset();
2164 LayoutText* textLayoutObject = toLayoutText(layoutObject); 2192 LayoutText* textLayoutObject = toLayoutText(layoutObject);
2193 const int textOffset = offsetInNode - textLayoutObject->textStartOffset();
2165 for (InlineTextBox *box = textLayoutObject->firstTextBox(); box; box = box-> nextTextBox()) { 2194 for (InlineTextBox *box = textLayoutObject->firstTextBox(); box; box = box-> nextTextBox()) {
2166 if (offsetInNode < static_cast<int>(box->start()) && !textLayoutObject-> containsReversedText()) { 2195 if (textOffset < static_cast<int>(box->start()) && !textLayoutObject->co ntainsReversedText()) {
2167 // The offset we're looking for is before this node 2196 // The offset we're looking for is before this node
2168 // this means the offset must be in content that is 2197 // this means the offset must be in content that is
2169 // not laid out. Return false. 2198 // not laid out. Return false.
2170 return false; 2199 return false;
2171 } 2200 }
2172 if (box->containsCaretOffset(offsetInNode)) { 2201 if (box->containsCaretOffset(textOffset)) {
2173 // Return false for offsets inside composed characters. 2202 // Return false for offsets inside composed characters.
2174 return offsetInNode == 0 || offsetInNode == textLayoutObject->nextOf fset(textLayoutObject->previousOffset(offsetInNode)); 2203 return textOffset == 0 || textOffset == textLayoutObject->nextOffset (textLayoutObject->previousOffset(textOffset));
2175 } 2204 }
2176 } 2205 }
2177 2206
2178 return false; 2207 return false;
2179 } 2208 }
2180 2209
2181 static Node* nextRenderedEditable(Node* node) 2210 static Node* nextRenderedEditable(Node* node)
2182 { 2211 {
2183 for (node = nextAtomicLeafNode(*node); node; node = nextAtomicLeafNode(*node )) { 2212 for (node = nextAtomicLeafNode(*node); node; node = nextAtomicLeafNode(*node )) {
2184 LayoutObject* layoutObject = node->layoutObject(); 2213 LayoutObject* layoutObject = node->layoutObject();
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
2399 } 2428 }
2400 lastNode = currentNode; 2429 lastNode = currentNode;
2401 } 2430 }
2402 2431
2403 // If we've moved to a position that is visually distinct, return the la st saved position. There 2432 // If we've moved to a position that is visually distinct, return the la st saved position. There
2404 // is code below that terminates early if we're *about* to move to a vis ually distinct position. 2433 // is code below that terminates early if we're *about* to move to a vis ually distinct position.
2405 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary) 2434 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary)
2406 return lastVisible.deprecatedComputePosition(); 2435 return lastVisible.deprecatedComputePosition();
2407 2436
2408 // skip position in non-laid out or invisible node 2437 // skip position in non-laid out or invisible node
2409 LayoutObject* layoutObject = currentNode->layoutObject(); 2438 LayoutObject* layoutObject = associatedLayoutObjectOf(*currentNode, curr entPos.offsetInLeafNode());
2410 if (!layoutObject || layoutObject->style()->visibility() != VISIBLE) 2439 if (!layoutObject || layoutObject->style()->visibility() != VISIBLE)
2411 continue; 2440 continue;
2412 2441
2413 if (rule == CanCrossEditingBoundary && boundaryCrossed) { 2442 if (rule == CanCrossEditingBoundary && boundaryCrossed) {
2414 lastVisible = currentPos; 2443 lastVisible = currentPos;
2415 break; 2444 break;
2416 } 2445 }
2417 2446
2418 // track last visible streamer position 2447 // track last visible streamer position
2419 if (isStreamer<Strategy>(currentPos)) 2448 if (isStreamer<Strategy>(currentPos))
2420 lastVisible = currentPos; 2449 lastVisible = currentPos;
2421 2450
2422 // Don't move past a position that is visually distinct. We could rely on code above to terminate and 2451 // Don't move past a position that is visually distinct. We could rely on code above to terminate and
2423 // return lastVisible on the next iteration, but we terminate early to a void doing a nodeIndex() call. 2452 // return lastVisible on the next iteration, but we terminate early to a void doing a nodeIndex() call.
2424 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.at StartOfNode()) 2453 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.at StartOfNode())
2425 return lastVisible.deprecatedComputePosition(); 2454 return lastVisible.deprecatedComputePosition();
2426 2455
2427 // Return position after tables and nodes which have content that can be ignored. 2456 // Return position after tables and nodes which have content that can be ignored.
2428 if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableE lement(currentNode)) { 2457 if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableE lement(currentNode)) {
2429 if (currentPos.atEndOfNode()) 2458 if (currentPos.atEndOfNode())
2430 return PositionTemplate<Strategy>::afterNode(currentNode); 2459 return PositionTemplate<Strategy>::afterNode(currentNode);
2431 continue; 2460 continue;
2432 } 2461 }
2433 2462
2434 // return current position if it is in laid out text 2463 // return current position if it is in laid out text
2435 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox() ) { 2464 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox() ) {
2465 LayoutText* const textLayoutObject = toLayoutText(layoutObject);
2466 const unsigned textStartOffset = textLayoutObject->textStartOffset() ;
2436 if (currentNode != startNode) { 2467 if (currentNode != startNode) {
2437 // This assertion fires in layout tests in the case-transform.ht ml test because 2468 // This assertion fires in layout tests in the case-transform.ht ml test because
2438 // of a mix-up between offsets in the text in the DOM tree with text in the 2469 // of a mix-up between offsets in the text in the DOM tree with text in the
2439 // layout tree which can have a different length due to case tra nsformation. 2470 // layout tree which can have a different length due to case tra nsformation.
2440 // Until we resolve that, disable this so we can run the layout tests! 2471 // Until we resolve that, disable this so we can run the layout tests!
2441 // ASSERT(currentOffset >= layoutObject->caretMaxOffset()); 2472 // ASSERT(currentOffset >= layoutObject->caretMaxOffset());
2442 return PositionTemplate<Strategy>(currentNode, layoutObject->car etMaxOffset()); 2473 return PositionTemplate<Strategy>(currentNode, layoutObject->car etMaxOffset() + textStartOffset);
2443 } 2474 }
2444 2475
2445 unsigned textOffset = currentPos.offsetInLeafNode(); 2476 // Map offset in DOM node to offset in InlineBox.
2446 LayoutText* textLayoutObject = toLayoutText(layoutObject); 2477 ASSERT(currentPos.offsetInLeafNode() >= static_cast<int>(textStartOf fset));
2478 const unsigned textOffset = currentPos.offsetInLeafNode() - textStar tOffset;
2447 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox(); 2479 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox();
2448 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) { 2480 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
2481 if (textOffset == box->start()) {
2482 if (textLayoutObject->isTextFragment() && toLayoutTextFragme nt(layoutObject)->isRemainingTextLayoutObject()) {
2483 // |currentPos| is at start of remaining text of
2484 // |Text| node with :first-letter.
2485 ASSERT(currentPos.offsetInLeafNode() >= 1);
2486 LayoutObject* firstLetterLayoutObject = toLayoutTextFrag ment(layoutObject)->firstLetterPseudoElement()->layoutObject();
2487 if (firstLetterLayoutObject && firstLetterLayoutObject-> style()->visibility() == VISIBLE)
2488 return currentPos.computePosition();
2489 }
2490 continue;
2491 }
2449 if (textOffset <= box->start() + box->len()) { 2492 if (textOffset <= box->start() + box->len()) {
2450 if (textOffset > box->start()) 2493 if (textOffset > box->start())
2451 return currentPos.computePosition(); 2494 return currentPos.computePosition();
2452 continue; 2495 continue;
2453 } 2496 }
2454 2497
2455 if (box == lastTextBox || textOffset != box->start() + box->len( ) + 1) 2498 if (box == lastTextBox || textOffset != box->start() + box->len( ) + 1)
2456 continue; 2499 continue;
2457 2500
2458 // The text continues on the next line only if the last text box is not on this line and 2501 // The text continues on the next line only if the last text box is not on this line and
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2536 // Do not move to a visually distinct position. 2579 // Do not move to a visually distinct position.
2537 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary) 2580 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary)
2538 return lastVisible.deprecatedComputePosition(); 2581 return lastVisible.deprecatedComputePosition();
2539 // Do not move past a visually disinct position. 2582 // Do not move past a visually disinct position.
2540 // Note: The first position after the last in a node whose ends are visu ally distinct 2583 // Note: The first position after the last in a node whose ends are visu ally distinct
2541 // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1]. 2584 // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
2542 if (boundary && Strategy::parent(*boundary) == currentNode) 2585 if (boundary && Strategy::parent(*boundary) == currentNode)
2543 return lastVisible.deprecatedComputePosition(); 2586 return lastVisible.deprecatedComputePosition();
2544 2587
2545 // skip position in non-laid out or invisible node 2588 // skip position in non-laid out or invisible node
2546 LayoutObject* layoutObject = currentNode->layoutObject(); 2589 LayoutObject* layoutObject = associatedLayoutObjectOf(*currentNode, curr entPos.offsetInLeafNode());
2547 if (!layoutObject || layoutObject->style()->visibility() != VISIBLE) 2590 if (!layoutObject || layoutObject->style()->visibility() != VISIBLE)
2548 continue; 2591 continue;
2549 2592
2550 if (rule == CanCrossEditingBoundary && boundaryCrossed) { 2593 if (rule == CanCrossEditingBoundary && boundaryCrossed) {
2551 lastVisible = currentPos; 2594 lastVisible = currentPos;
2552 break; 2595 break;
2553 } 2596 }
2554 2597
2555 // track last visible streamer position 2598 // track last visible streamer position
2556 if (isStreamer<Strategy>(currentPos)) 2599 if (isStreamer<Strategy>(currentPos))
2557 lastVisible = currentPos; 2600 lastVisible = currentPos;
2558 2601
2559 // Return position before tables and nodes which have content that can b e ignored. 2602 // Return position before tables and nodes which have content that can b e ignored.
2560 if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableE lement(currentNode)) { 2603 if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableE lement(currentNode)) {
2561 if (currentPos.offsetInLeafNode() <= layoutObject->caretMinOffset()) 2604 if (currentPos.offsetInLeafNode() <= layoutObject->caretMinOffset())
2562 return PositionTemplate<Strategy>::editingPositionOf(currentNode , layoutObject->caretMinOffset()); 2605 return PositionTemplate<Strategy>::editingPositionOf(currentNode , layoutObject->caretMinOffset());
2563 continue; 2606 continue;
2564 } 2607 }
2565 2608
2566 // return current position if it is in laid out text 2609 // return current position if it is in laid out text
2567 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox() ) { 2610 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox() ) {
2611 LayoutText* const textLayoutObject = toLayoutText(layoutObject);
2612 const unsigned textStartOffset = textLayoutObject->textStartOffset() ;
2568 if (currentNode != startNode) { 2613 if (currentNode != startNode) {
2569 ASSERT(currentPos.atStartOfNode()); 2614 ASSERT(currentPos.atStartOfNode());
2570 return PositionTemplate<Strategy>(currentNode, layoutObject->car etMinOffset()); 2615 return PositionTemplate<Strategy>(currentNode, layoutObject->car etMinOffset() + textStartOffset);
2571 } 2616 }
2572 2617
2573 unsigned textOffset = currentPos.offsetInLeafNode(); 2618 // Map offset in DOM node to offset in InlineBox.
2574 LayoutText* textLayoutObject = toLayoutText(layoutObject); 2619 ASSERT(currentPos.offsetInLeafNode() >= static_cast<int>(textStartOf fset));
2620 const unsigned textOffset = currentPos.offsetInLeafNode() - textStar tOffset;
2575 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox(); 2621 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox();
2576 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) { 2622 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
2577 if (textOffset <= box->end()) { 2623 if (textOffset <= box->end()) {
2578 if (textOffset >= box->start()) 2624 if (textOffset >= box->start())
2579 return currentPos.computePosition(); 2625 return currentPos.computePosition();
2580 continue; 2626 continue;
2581 } 2627 }
2582 2628
2583 if (box == lastTextBox || textOffset != box->start() + box->len( )) 2629 if (box == lastTextBox || textOffset != box->start() + box->len( ))
2584 continue; 2630 continue;
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
3252 { 3298 {
3253 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); 3299 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule);
3254 } 3300 }
3255 3301
3256 VisiblePositionInComposedTree previousPositionOf(const VisiblePositionInComposed Tree& visiblePosition, EditingBoundaryCrossingRule rule) 3302 VisiblePositionInComposedTree previousPositionOf(const VisiblePositionInComposed Tree& visiblePosition, EditingBoundaryCrossingRule rule)
3257 { 3303 {
3258 return previousPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePos ition, rule); 3304 return previousPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePos ition, rule);
3259 } 3305 }
3260 3306
3261 } // namespace blink 3307 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698