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

Side by Side Diff: Source/core/editing/ApplyStyleCommand.cpp

Issue 67473002: Have ElementTraversal / NodeTraversal's next() methods take a reference (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase on master Created 7 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
« no previous file with comments | « Source/core/dom/shadow/ShadowRoot.cpp ('k') | Source/core/editing/BreakBlockquoteCommand.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2008, 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
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 end = endPosition(); 346 end = endPosition();
347 } 347 }
348 348
349 // Calculate loop end point. 349 // Calculate loop end point.
350 // If the end node is before the start node (can only happen if the end node is 350 // If the end node is before the start node (can only happen if the end node is
351 // an ancestor of the start node), we gather nodes up to the next sibling of the end node 351 // an ancestor of the start node), we gather nodes up to the next sibling of the end node
352 Node *beyondEnd; 352 Node *beyondEnd;
353 if (start.deprecatedNode()->isDescendantOf(end.deprecatedNode())) 353 if (start.deprecatedNode()->isDescendantOf(end.deprecatedNode()))
354 beyondEnd = NodeTraversal::nextSkippingChildren(end.deprecatedNode()); 354 beyondEnd = NodeTraversal::nextSkippingChildren(end.deprecatedNode());
355 else 355 else
356 beyondEnd = NodeTraversal::next(end.deprecatedNode()); 356 beyondEnd = NodeTraversal::next(*end.deprecatedNode());
357 357
358 start = start.upstream(); // Move upstream to ensure we do not add redundant spans. 358 start = start.upstream(); // Move upstream to ensure we do not add redundant spans.
359 Node* startNode = start.deprecatedNode(); 359 Node* startNode = start.deprecatedNode();
360 ASSERT(startNode);
360 if (startNode->isTextNode() && start.deprecatedEditingOffset() >= caretMaxOf fset(startNode)) // Move out of text node if range does not include its characte rs. 361 if (startNode->isTextNode() && start.deprecatedEditingOffset() >= caretMaxOf fset(startNode)) // Move out of text node if range does not include its characte rs.
361 startNode = NodeTraversal::next(startNode); 362 startNode = NodeTraversal::next(*startNode);
362 363
363 // Store away font size before making any changes to the document. 364 // Store away font size before making any changes to the document.
364 // This ensures that changes to one node won't effect another. 365 // This ensures that changes to one node won't effect another.
365 HashMap<Node*, float> startingFontSizes; 366 HashMap<Node*, float> startingFontSizes;
366 for (Node *node = startNode; node != beyondEnd; node = NodeTraversal::next(n ode)) 367 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(* node))
367 startingFontSizes.set(node, computedFontSize(node)); 368 startingFontSizes.set(node, computedFontSize(node));
368 369
369 // These spans were added by us. If empty after font size changes, they can be removed. 370 // These spans were added by us. If empty after font size changes, they can be removed.
370 Vector<RefPtr<HTMLElement> > unstyledSpans; 371 Vector<RefPtr<HTMLElement> > unstyledSpans;
371 372
372 Node* lastStyledNode = 0; 373 Node* lastStyledNode = 0;
373 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(n ode)) { 374 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(* node)) {
374 RefPtr<HTMLElement> element; 375 RefPtr<HTMLElement> element;
375 if (node->isHTMLElement()) { 376 if (node->isHTMLElement()) {
376 // Only work on fully selected nodes. 377 // Only work on fully selected nodes.
377 if (!nodeFullySelected(node, start, end)) 378 if (!nodeFullySelected(node, start, end))
378 continue; 379 continue;
379 element = toHTMLElement(node); 380 element = toHTMLElement(node);
380 } else if (node->isTextNode() && node->renderer() && node->parentNode() != lastStyledNode) { 381 } else if (node->isTextNode() && node->renderer() && node->parentNode() != lastStyledNode) {
381 // Last styled node was not parent node of this text node, but we wi sh to style this 382 // Last styled node was not parent node of this text node, but we wi sh to style this
382 // text node. To make this possible, add a style span to surround th is text node. 383 // text node. To make this possible, add a style span to surround th is text node.
383 RefPtr<HTMLElement> span = createStyleSpanElement(document()); 384 RefPtr<HTMLElement> span = createStyleSpanElement(document());
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 666
666 // Remove dummy style spans created by splitting text elements. 667 // Remove dummy style spans created by splitting text elements.
667 cleanupUnstyledAppleStyleSpans(startDummySpanAncestor.get()); 668 cleanupUnstyledAppleStyleSpans(startDummySpanAncestor.get());
668 if (endDummySpanAncestor != startDummySpanAncestor) 669 if (endDummySpanAncestor != startDummySpanAncestor)
669 cleanupUnstyledAppleStyleSpans(endDummySpanAncestor.get()); 670 cleanupUnstyledAppleStyleSpans(endDummySpanAncestor.get());
670 } 671 }
671 672
672 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const P osition& start, const Position& end) 673 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const P osition& start, const Position& end)
673 { 674 {
674 Node* startNode = start.deprecatedNode(); 675 Node* startNode = start.deprecatedNode();
676 ASSERT(startNode);
675 677
676 if (start.deprecatedEditingOffset() >= caretMaxOffset(start.deprecatedNode() )) { 678 if (start.deprecatedEditingOffset() >= caretMaxOffset(start.deprecatedNode() )) {
677 startNode = NodeTraversal::next(startNode); 679 startNode = NodeTraversal::next(*startNode);
678 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star tNode)) < 0) 680 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star tNode)) < 0)
679 return; 681 return;
680 } 682 }
681 683
682 Node* pastEndNode = end.deprecatedNode(); 684 Node* pastEndNode = end.deprecatedNode();
683 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode())) 685 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode()))
684 pastEndNode = NodeTraversal::nextSkippingChildren(end.deprecatedNode()); 686 pastEndNode = NodeTraversal::nextSkippingChildren(end.deprecatedNode());
685 687
686 // FIXME: Callers should perform this operation on a Range that includes the br 688 // FIXME: Callers should perform this operation on a Range that includes the br
687 // if they want style applied to the empty line. 689 // if they want style applied to the empty line.
688 if (start == end && start.deprecatedNode()->hasTagName(brTag)) 690 if (start == end && start.deprecatedNode()->hasTagName(brTag))
689 pastEndNode = NodeTraversal::next(start.deprecatedNode()); 691 pastEndNode = NodeTraversal::next(*start.deprecatedNode());
690 692
691 // Start from the highest fully selected ancestor so that we can modify the fully selected node. 693 // Start from the highest fully selected ancestor so that we can modify the fully selected node.
692 // e.g. When applying font-size: large on <font color="blue">hello</font>, w e need to include the font element in our run 694 // e.g. When applying font-size: large on <font color="blue">hello</font>, w e need to include the font element in our run
693 // to generate <font color="blue" size="4">hello</font> instead of <font col or="blue"><font size="4">hello</font></font> 695 // to generate <font color="blue" size="4">hello</font> instead of <font col or="blue"><font size="4">hello</font></font>
694 RefPtr<Range> range = Range::create(startNode->document(), start, end); 696 RefPtr<Range> range = Range::create(startNode->document(), start, end);
695 Element* editableRoot = startNode->rootEditableElement(); 697 Element* editableRoot = startNode->rootEditableElement();
696 if (startNode != editableRoot) { 698 if (startNode != editableRoot) {
697 while (editableRoot && startNode->parentNode() != editableRoot && isNode VisiblyContainedWithin(startNode->parentNode(), range.get())) 699 while (editableRoot && startNode->parentNode() != editableRoot && isNode VisiblyContainedWithin(startNode->parentNode(), range.get()))
698 startNode = startNode->parentNode(); 700 startNode = startNode->parentNode();
699 } 701 }
700 702
701 applyInlineStyleToNodeRange(style, startNode, pastEndNode); 703 applyInlineStyleToNodeRange(style, startNode, pastEndNode);
702 } 704 }
703 705
704 static bool containsNonEditableRegion(Node* node) 706 static bool containsNonEditableRegion(Node* node)
705 { 707 {
706 if (!node->rendererIsEditable()) 708 if (!node->rendererIsEditable())
707 return true; 709 return true;
708 710
709 Node* sibling = NodeTraversal::nextSkippingChildren(node); 711 Node* sibling = NodeTraversal::nextSkippingChildren(node);
710 for (Node* descendent = node->firstChild(); descendent && descendent != sibl ing; descendent = NodeTraversal::next(descendent)) { 712 for (Node* descendent = node->firstChild(); descendent && descendent != sibl ing; descendent = NodeTraversal::next(*descendent)) {
711 if (!descendent->rendererIsEditable()) 713 if (!descendent->rendererIsEditable())
712 return true; 714 return true;
713 } 715 }
714 716
715 return false; 717 return false;
716 } 718 }
717 719
718 struct InlineRunToApplyStyle { 720 struct InlineRunToApplyStyle {
719 InlineRunToApplyStyle(Node* start, Node* end, Node* pastEndNode) 721 InlineRunToApplyStyle(Node* start, Node* end, Node* pastEndNode)
720 : start(start) 722 : start(start)
(...skipping 19 matching lines...) Expand all
740 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, PassRef Ptr<Node> startNode, PassRefPtr<Node> pastEndNode) 742 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, PassRef Ptr<Node> startNode, PassRefPtr<Node> pastEndNode)
741 { 743 {
742 if (m_removeOnly) 744 if (m_removeOnly)
743 return; 745 return;
744 746
745 document().updateLayoutIgnorePendingStylesheets(); 747 document().updateLayoutIgnorePendingStylesheets();
746 748
747 Vector<InlineRunToApplyStyle> runs; 749 Vector<InlineRunToApplyStyle> runs;
748 RefPtr<Node> node = startNode; 750 RefPtr<Node> node = startNode;
749 for (RefPtr<Node> next; node && node != pastEndNode; node = next) { 751 for (RefPtr<Node> next; node && node != pastEndNode; node = next) {
750 next = NodeTraversal::next(node.get()); 752 next = NodeTraversal::next(*node);
751 753
752 if (!node->renderer() || !node->rendererIsEditable()) 754 if (!node->renderer() || !node->rendererIsEditable())
753 continue; 755 continue;
754 756
755 if (!node->rendererIsRichlyEditable() && node->isHTMLElement()) { 757 if (!node->rendererIsRichlyEditable() && node->isHTMLElement()) {
756 // This is a plaintext-only region. Only proceed if it's fully selec ted. 758 // This is a plaintext-only region. Only proceed if it's fully selec ted.
757 // pastEndNode is the node after the last fully selected node, so if it's inside node then 759 // pastEndNode is the node after the last fully selected node, so if it's inside node then
758 // node isn't fully selected. 760 // node isn't fully selected.
759 if (pastEndNode && pastEndNode->isDescendantOf(node.get())) 761 if (pastEndNode && pastEndNode->isDescendantOf(node.get()))
760 break; 762 break;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 bool ApplyStyleCommand::isStyledInlineElementToRemove(Element* element) const 823 bool ApplyStyleCommand::isStyledInlineElementToRemove(Element* element) const
822 { 824 {
823 return (m_styledInlineElement && element->hasTagName(m_styledInlineElement-> tagQName())) 825 return (m_styledInlineElement && element->hasTagName(m_styledInlineElement-> tagQName()))
824 || (m_isInlineElementToRemoveFunction && m_isInlineElementToRemoveFuncti on(element)); 826 || (m_isInlineElementToRemoveFunction && m_isInlineElementToRemoveFuncti on(element));
825 } 827 }
826 828
827 bool ApplyStyleCommand::shouldApplyInlineStyleToRun(EditingStyle* style, Node* r unStart, Node* pastEndNode) 829 bool ApplyStyleCommand::shouldApplyInlineStyleToRun(EditingStyle* style, Node* r unStart, Node* pastEndNode)
828 { 830 {
829 ASSERT(style && runStart); 831 ASSERT(style && runStart);
830 832
831 for (Node* node = runStart; node && node != pastEndNode; node = NodeTraversa l::next(node)) { 833 for (Node* node = runStart; node && node != pastEndNode; node = NodeTraversa l::next(*node)) {
832 if (node->childNodeCount()) 834 if (node->childNodeCount())
833 continue; 835 continue;
834 // We don't consider m_isInlineElementToRemoveFunction here because we n ever apply style when m_isInlineElementToRemoveFunction is specified 836 // We don't consider m_isInlineElementToRemoveFunction here because we n ever apply style when m_isInlineElementToRemoveFunction is specified
835 if (!style->styleIsPresentInComputedStyleOfNode(node)) 837 if (!style->styleIsPresentInComputedStyleOfNode(node))
836 return true; 838 return true;
837 if (m_styledInlineElement && !enclosingNodeWithTag(positionBeforeNode(no de), m_styledInlineElement->tagQName())) 839 if (m_styledInlineElement && !enclosingNodeWithTag(positionBeforeNode(no de), m_styledInlineElement->tagQName()))
838 return true; 840 return true;
839 } 841 }
840 return false; 842 return false;
841 } 843 }
842 844
843 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, RefPtr<Node>& runStart, RefPtr<Node>& runEnd, PassRefPtr<Node> pastEndNode) 845 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, RefPtr<Node>& runStart, RefPtr<Node>& runEnd, PassRefPtr<Node> pastEndNode)
844 { 846 {
845 ASSERT(runStart && runEnd); 847 ASSERT(runStart && runEnd);
846 RefPtr<Node> next = runStart; 848 RefPtr<Node> next = runStart;
847 for (RefPtr<Node> node = next; node && node->inDocument() && node != pastEnd Node; node = next) { 849 for (RefPtr<Node> node = next; node && node->inDocument() && node != pastEnd Node; node = next) {
848 if (editingIgnoresContent(node.get())) { 850 if (editingIgnoresContent(node.get())) {
849 ASSERT(!node->contains(pastEndNode.get())); 851 ASSERT(!node->contains(pastEndNode.get()));
850 next = NodeTraversal::nextSkippingChildren(node.get()); 852 next = NodeTraversal::nextSkippingChildren(node.get());
851 } else 853 } else {
852 next = NodeTraversal::next(node.get()); 854 next = NodeTraversal::next(*node);
855 }
853 if (!node->isHTMLElement()) 856 if (!node->isHTMLElement())
854 continue; 857 continue;
855 858
856 RefPtr<Node> previousSibling = node->previousSibling(); 859 RefPtr<Node> previousSibling = node->previousSibling();
857 RefPtr<Node> nextSibling = node->nextSibling(); 860 RefPtr<Node> nextSibling = node->nextSibling();
858 RefPtr<ContainerNode> parent = node->parentNode(); 861 RefPtr<ContainerNode> parent = node->parentNode();
859 removeInlineStyleFromElement(style, toHTMLElement(node), RemoveAlways); 862 removeInlineStyleFromElement(style, toHTMLElement(node), RemoveAlways);
860 if (!node->inDocument()) { 863 if (!node->inDocument()) {
861 // FIXME: We might need to update the start and the end of current s election here but need a test. 864 // FIXME: We might need to update the start and the end of current s election here but need a test.
862 if (runStart == node) 865 if (runStart == node)
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; 1104 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start;
1102 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; 1105 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end;
1103 1106
1104 RefPtr<Node> node = start.deprecatedNode(); 1107 RefPtr<Node> node = start.deprecatedNode();
1105 while (node) { 1108 while (node) {
1106 RefPtr<Node> next; 1109 RefPtr<Node> next;
1107 if (editingIgnoresContent(node.get())) { 1110 if (editingIgnoresContent(node.get())) {
1108 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate dNode())); 1111 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate dNode()));
1109 next = NodeTraversal::nextSkippingChildren(node.get()); 1112 next = NodeTraversal::nextSkippingChildren(node.get());
1110 } else { 1113 } else {
1111 next = NodeTraversal::next(node.get()); 1114 next = NodeTraversal::next(*node);
1112 } 1115 }
1113 if (node->isHTMLElement() && nodeFullySelected(node.get(), start, end)) { 1116 if (node->isHTMLElement() && nodeFullySelected(node.get(), start, end)) {
1114 RefPtr<HTMLElement> elem = toHTMLElement(node); 1117 RefPtr<HTMLElement> elem = toHTMLElement(node);
1115 RefPtr<Node> prev = NodeTraversal::previousPostOrder(elem.get()); 1118 RefPtr<Node> prev = NodeTraversal::previousPostOrder(elem.get());
1116 RefPtr<Node> next = NodeTraversal::next(elem.get()); 1119 RefPtr<Node> next = NodeTraversal::next(*elem);
1117 RefPtr<EditingStyle> styleToPushDown; 1120 RefPtr<EditingStyle> styleToPushDown;
1118 RefPtr<Node> childNode; 1121 RefPtr<Node> childNode;
1119 if (isStyledInlineElementToRemove(elem.get())) { 1122 if (isStyledInlineElementToRemove(elem.get())) {
1120 styleToPushDown = EditingStyle::create(); 1123 styleToPushDown = EditingStyle::create();
1121 childNode = elem->firstChild(); 1124 childNode = elem->firstChild();
1122 } 1125 }
1123 1126
1124 removeInlineStyleFromElement(style, elem.get(), RemoveIfNeeded, styl eToPushDown.get()); 1127 removeInlineStyleFromElement(style, elem.get(), RemoveIfNeeded, styl eToPushDown.get());
1125 if (!elem->inDocument()) { 1128 if (!elem->inDocument()) {
1126 if (s.deprecatedNode() == elem) { 1129 if (s.deprecatedNode() == elem) {
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
1543 String textToMove = nextText->data(); 1546 String textToMove = nextText->data();
1544 insertTextIntoNode(childText, childText->length(), textToMove); 1547 insertTextIntoNode(childText, childText->length(), textToMove);
1545 removeNode(next); 1548 removeNode(next);
1546 // don't move child node pointer. it may want to merge with more text no des. 1549 // don't move child node pointer. it may want to merge with more text no des.
1547 } 1550 }
1548 1551
1549 updateStartEnd(newStart, newEnd); 1552 updateStartEnd(newStart, newEnd);
1550 } 1553 }
1551 1554
1552 } 1555 }
OLDNEW
« no previous file with comments | « Source/core/dom/shadow/ShadowRoot.cpp ('k') | Source/core/editing/BreakBlockquoteCommand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698