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

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

Issue 1756763002: 2016-03-02T18:53:01 LayoutPosition Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2016-04-25T19:02:18 Created 4 years, 8 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, 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
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
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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 "core/editing/Position.h" 26 #include "core/editing/Position.h"
27 27
28 #include "core/dom/Text.h"
28 #include "core/dom/shadow/ElementShadow.h" 29 #include "core/dom/shadow/ElementShadow.h"
29 #include "core/editing/EditingUtilities.h" 30 #include "core/editing/EditingUtilities.h"
30 #include "core/editing/TextAffinity.h" 31 #include "core/editing/TextAffinity.h"
31 #include "wtf/text/CString.h" 32 #include "wtf/text/CString.h"
32 #include <stdio.h>
33 #include <ostream> // NOLINT 33 #include <ostream> // NOLINT
34 34
35 namespace blink { 35 namespace blink {
36 36
37 #if DCHECK_IS_ON() 37 #if DCHECK_IS_ON()
38 static bool canBeAnchorNode(Node* node) 38 static bool canBeAnchorNode(Node* node)
39 { 39 {
40 return !node || !node->isPseudoElement(); 40 return !node || !node->isPseudoElement();
41 } 41 }
42 #endif 42 #endif
(...skipping 24 matching lines...) Expand all
67 DCHECK_GE(offset, 1); 67 DCHECK_GE(offset, 1);
68 return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::AfterAncho r); 68 return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::AfterAncho r);
69 } 69 }
70 70
71 template <typename Strategy> 71 template <typename Strategy>
72 PositionTemplate<Strategy>::PositionTemplate(Node* anchorNode, PositionAnchorTyp e anchorType) 72 PositionTemplate<Strategy>::PositionTemplate(Node* anchorNode, PositionAnchorTyp e anchorType)
73 : m_anchorNode(anchorNode) 73 : m_anchorNode(anchorNode)
74 , m_offset(0) 74 , m_offset(0)
75 , m_anchorType(anchorType) 75 , m_anchorType(anchorType)
76 { 76 {
77 if (!m_anchorNode) { 77 DCHECK(m_anchorNode);
78 m_anchorType = PositionAnchorType::OffsetInAnchor; 78 DCHECK_NE(m_anchorType, PositionAnchorType::OffsetInAnchor);
79 return;
80 }
81 if (m_anchorNode->isTextNode()) { 79 if (m_anchorNode->isTextNode()) {
82 DCHECK(m_anchorType == PositionAnchorType::BeforeAnchor || m_anchorType == PositionAnchorType::AfterAnchor); 80 DCHECK(isBeforeAnchor() || isAfterAnchor()) << m_anchorType;
83 return; 81 return;
84 } 82 }
85 if (m_anchorNode->isDocumentNode()) { 83 if (m_anchorNode->isDocumentNode()) {
86 // Since |RangeBoundaryPoint| can't represent before/after Document, we 84 // Since |RangeBoundaryPoint| can't represent before/after Document, we
87 // should not use them. 85 // should not use them.
88 DCHECK(isBeforeChildren() || isAfterChildren()) << m_anchorType; 86 DCHECK(isBeforeChildren() || isAfterChildren()) << m_anchorType;
89 return; 87 return;
90 } 88 }
89
91 #if DCHECK_IS_ON() 90 #if DCHECK_IS_ON()
92 DCHECK(canBeAnchorNode(m_anchorNode.get())); 91 DCHECK(canBeAnchorNode(m_anchorNode.get()));
93 #endif 92 #endif
94 DCHECK_NE(m_anchorType, PositionAnchorType::OffsetInAnchor); 93 DCHECK_NE(m_anchorType, PositionAnchorType::OffsetInAnchor);
95 } 94 }
96 95
97 template <typename Strategy> 96 template <typename Strategy>
98 PositionTemplate<Strategy>::PositionTemplate(Node* anchorNode, int offset) 97 PositionTemplate<Strategy>::PositionTemplate(Node* anchorNode, int offset)
99 : m_anchorNode(anchorNode) 98 : m_anchorNode(anchorNode)
100 , m_offset(offset) 99 , m_offset(offset)
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 if (isNull()) 385 if (isNull())
387 return true; 386 return true;
388 // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of 387 // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of
389 // DOM tree version. 388 // DOM tree version.
390 return !Strategy::parent(*anchorNode()) && m_offset >= EditingStrategy::last OffsetForEditing(anchorNode()); 389 return !Strategy::parent(*anchorNode()) && m_offset >= EditingStrategy::last OffsetForEditing(anchorNode());
391 } 390 }
392 391
393 template <typename Strategy> 392 template <typename Strategy>
394 void PositionTemplate<Strategy>::debugPosition(const char* msg) const 393 void PositionTemplate<Strategy>::debugPosition(const char* msg) const
395 { 394 {
396 static const char* const anchorTypes[] = { 395 VLOG(0) << msg << ' ' << *this;
397 "OffsetInAnchor",
398 "BeforeAnchor",
399 "AfterAnchor",
400 "BeforeChildren",
401 "AfterChildren",
402 "Invalid",
403 };
404
405 if (isNull()) {
406 fprintf(stderr, "Position [%s]: null\n", msg);
407 return;
408 }
409
410 const char* anchorType = anchorTypes[std::min(static_cast<size_t>(m_anchorTy pe), WTF_ARRAY_LENGTH(anchorTypes) - 1)];
411 if (m_anchorNode->isTextNode()) {
412 fprintf(stderr, "Position [%s]: %s [%p] %s, (%s) at %d\n", msg, anchorNo de()->nodeName().utf8().data(), anchorNode(), anchorType, m_anchorNode->nodeValu e().utf8().data(), m_offset);
413 return;
414 }
415
416 fprintf(stderr, "Position [%s]: %s [%p] %s at %d\n", msg, anchorNode()->node Name().utf8().data(), anchorNode(), anchorType, m_offset);
417 } 396 }
418 397
419 PositionInFlatTree toPositionInFlatTree(const Position& pos) 398 PositionInFlatTree toPositionInFlatTree(const Position& pos)
420 { 399 {
421 if (pos.isNull()) 400 if (pos.isNull())
422 return PositionInFlatTree(); 401 return PositionInFlatTree();
423 402
424 if (pos.isOffsetInAnchor()) { 403 if (pos.isOffsetInAnchor()) {
425 Node* anchor = pos.anchorNode(); 404 Node* anchor = pos.anchorNode();
426 if (anchor->offsetInCharacters()) 405 if (anchor->offsetInCharacters())
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 // |child| is null when the position is at the end of the children. 466 // |child| is null when the position is at the end of the children.
488 // <div>foo|</div> 467 // <div>foo|</div>
489 return Position(anchorNode, PositionAnchorType::AfterChildren); 468 return Position(anchorNode, PositionAnchorType::AfterChildren);
490 } 469 }
491 default: 470 default:
492 ASSERT_NOT_REACHED(); 471 ASSERT_NOT_REACHED();
493 return Position(); 472 return Position();
494 } 473 }
495 } 474 }
496 475
476 // |normalize()| returns an equivalent position with |BeforeNode| position, or
477 // |OffsetInAnchor| for |Text| node if possible, otherwise |normalize()| returns
478 // - |AfterAnchor| if anchor node has no next siblings.
479 // - |BeforeChildren| if anchor node has no children.
480 // |normalized()| never return |AfterChildren| position.
481 template <typename Strategy>
482 PositionTemplate<Strategy> PositionTemplate<Strategy>::normalize(const PositionT emplate<Strategy>& position)
483 {
484 if (position.isNull())
485 return PositionTemplate<Strategy>();
486 Node* const anchorNode = position.anchorNode();
487 switch (position.anchorType()) {
488 case PositionAnchorType::AfterAnchor:
489 if (Node* nextSibling = Strategy::nextSibling(*anchorNode))
490 return normalize(beforeNode(nextSibling));
491 if (anchorNode->isTextNode())
492 return PositionTemplate<Strategy>(anchorNode, toText(anchorNode)->le ngth());
493 return position;
494 case PositionAnchorType::AfterChildren:
495 ASSERT(!anchorNode->isTextNode());
496 if (Node* lastChild = Strategy::lastChild(*anchorNode))
497 return normalize(afterNode(lastChild));
498 return firstPositionInNode(anchorNode);
499 case PositionAnchorType::BeforeAnchor:
500 if (anchorNode->isTextNode())
501 return PositionTemplate<Strategy>(anchorNode, 0);
502 return position;
503 case PositionAnchorType::BeforeChildren:
504 ASSERT(!anchorNode->isTextNode());
505 if (Node* firstChild = Strategy::firstChild(*anchorNode))
506 return normalize(beforeNode(firstChild));
507 return position;
508 case PositionAnchorType::OffsetInAnchor: {
509 const int offsetInContainer = position.offsetInContainerNode();
510 if (anchorNode->isTextNode()) {
511 const Text& textNode = *toText(anchorNode);
512 if (offsetInContainer < static_cast<int>(textNode.length()))
513 return position;
514 return normalize(afterNode(anchorNode));
515 }
516 if (Node* child = Strategy::childAt(*anchorNode, offsetInContainer))
517 return normalize(beforeNode(child));
518 if (Node* lastChild = Strategy::lastChild(*anchorNode))
519 return normalize(afterNode(lastChild));
520 return firstPositionInNode(anchorNode);
521 }
522 }
523 ASSERT_NOT_REACHED();
524 return PositionTemplate<Strategy>();
525 }
526
497 #ifndef NDEBUG 527 #ifndef NDEBUG
498 528
499 template <typename Strategy> 529 template <typename Strategy>
500 void PositionTemplate<Strategy>::formatForDebugger(char* buffer, unsigned length ) const 530 void PositionTemplate<Strategy>::formatForDebugger(char* buffer, unsigned length ) const
501 { 531 {
502 StringBuilder result; 532 StringBuilder result;
503 533
504 if (isNull()) { 534 if (isNull()) {
505 result.appendLiteral("<null>"); 535 result.appendLiteral("<null>");
506 } else { 536 } else {
507 char s[1024]; 537 char s[1024];
508 result.appendLiteral("offset "); 538 result.appendLiteral("offset ");
509 result.appendNumber(m_offset); 539 result.appendNumber(m_offset);
510 result.appendLiteral(" of "); 540 result.appendLiteral(" of ");
511 anchorNode()->formatForDebugger(s, sizeof(s)); 541 anchorNode()->formatForDebugger(s, sizeof(s));
512 result.append(s); 542 result.append(s);
513 } 543 }
514 544
515 strncpy(buffer, result.toString().utf8().data(), length - 1); 545 strncpy(buffer, result.toString().utf8().data(), length - 1);
516 } 546 }
517 547
518 template <typename Strategy> 548 template <typename Strategy>
519 void PositionTemplate<Strategy>::showAnchorTypeAndOffset() const
520 {
521 switch (anchorType()) {
522 case PositionAnchorType::OffsetInAnchor:
523 fputs("offset", stderr);
524 break;
525 case PositionAnchorType::BeforeChildren:
526 fputs("beforeChildren", stderr);
527 break;
528 case PositionAnchorType::AfterChildren:
529 fputs("afterChildren", stderr);
530 break;
531 case PositionAnchorType::BeforeAnchor:
532 fputs("before", stderr);
533 break;
534 case PositionAnchorType::AfterAnchor:
535 fputs("after", stderr);
536 break;
537 }
538 fprintf(stderr, ", offset:%d\n", m_offset);
539 }
540
541 template <typename Strategy>
542 void PositionTemplate<Strategy>::showTreeForThis() const 549 void PositionTemplate<Strategy>::showTreeForThis() const
543 { 550 {
544 if (!anchorNode()) 551 if (!anchorNode())
545 return; 552 return;
546 anchorNode()->showTreeForThis(); 553 anchorNode()->showTreeForThis();
547 showAnchorTypeAndOffset(); 554 VLOG(0) << *this;
548 } 555 }
549 556
550 template <typename Strategy> 557 template <typename Strategy>
551 void PositionTemplate<Strategy>::showTreeForThisInFlatTree() const 558 void PositionTemplate<Strategy>::showTreeForThisInFlatTree() const
552 { 559 {
553 if (!anchorNode()) 560 if (!anchorNode())
554 return; 561 return;
555 anchorNode()->showTreeForThisInFlatTree(); 562 anchorNode()->showTreeForThisInFlatTree();
556 showAnchorTypeAndOffset(); 563 VLOG(0) << *this;
557 } 564 }
558 565
559 #endif 566 #endif
560 567
561 template <typename PositionType> 568 template <typename PositionType>
562 static std::ostream& printPosition(std::ostream& ostream, const PositionType& po sition) 569 static std::ostream& printPosition(std::ostream& ostream, const PositionType& po sition)
563 { 570 {
564 if (position.isNull()) 571 if (position.isNull())
565 return ostream << "null"; 572 return ostream << "null";
566 ostream << position.anchorNode() << "@"; 573 ostream << position.anchorNode() << "@";
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 618
612 void showTree(const blink::Position* pos) 619 void showTree(const blink::Position* pos)
613 { 620 {
614 if (pos) 621 if (pos)
615 pos->showTreeForThis(); 622 pos->showTreeForThis();
616 else 623 else
617 fprintf(stderr, "Cannot showTree for (nil)\n"); 624 fprintf(stderr, "Cannot showTree for (nil)\n");
618 } 625 }
619 626
620 #endif 627 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/Position.h ('k') | third_party/WebKit/Source/core/editing/PositionTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698