Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 if (attributes.isEmpty()) | 79 if (attributes.isEmpty()) |
| 80 return true; | 80 return true; |
| 81 | 81 |
| 82 unsigned matchedAttributes = 0; | 82 unsigned matchedAttributes = 0; |
| 83 if (element->getAttribute(classAttr) == styleSpanClassString()) | 83 if (element->getAttribute(classAttr) == styleSpanClassString()) |
| 84 matchedAttributes++; | 84 matchedAttributes++; |
| 85 if (element->hasAttribute(styleAttr) && (shouldStyleAttributeBeEmpty == Allo wNonEmptyStyleAttribute | 85 if (element->hasAttribute(styleAttr) && (shouldStyleAttributeBeEmpty == Allo wNonEmptyStyleAttribute |
| 86 || !element->inlineStyle() || element->inlineStyle()->isEmpty())) | 86 || !element->inlineStyle() || element->inlineStyle()->isEmpty())) |
| 87 matchedAttributes++; | 87 matchedAttributes++; |
| 88 | 88 |
| 89 ASSERT(matchedAttributes <= attributes.size()); | 89 DCHECK_LE(matchedAttributes, attributes.size()); |
| 90 return matchedAttributes == attributes.size(); | 90 return matchedAttributes == attributes.size(); |
| 91 } | 91 } |
| 92 | 92 |
| 93 bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) | 93 bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) |
| 94 { | 94 { |
| 95 if (!isHTMLSpanElement(element)) | 95 if (!isHTMLSpanElement(element)) |
| 96 return false; | 96 return false; |
| 97 return hasNoAttributeOrOnlyStyleAttribute(toHTMLSpanElement(element), AllowN onEmptyStyleAttribute); | 97 return hasNoAttributeOrOnlyStyleAttribute(toHTMLSpanElement(element), AllowN onEmptyStyleAttribute); |
| 98 } | 98 } |
| 99 | 99 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 163 , m_end(mostBackwardCaretPosition(endingSelection().end())) | 163 , m_end(mostBackwardCaretPosition(endingSelection().end())) |
| 164 , m_useEndingSelection(true) | 164 , m_useEndingSelection(true) |
| 165 , m_styledInlineElement(nullptr) | 165 , m_styledInlineElement(nullptr) |
| 166 , m_removeOnly(true) | 166 , m_removeOnly(true) |
| 167 , m_isInlineElementToRemoveFunction(isInlineElementToRemoveFunction) | 167 , m_isInlineElementToRemoveFunction(isInlineElementToRemoveFunction) |
| 168 { | 168 { |
| 169 } | 169 } |
| 170 | 170 |
| 171 void ApplyStyleCommand::updateStartEnd(const Position& newStart, const Position& newEnd) | 171 void ApplyStyleCommand::updateStartEnd(const Position& newStart, const Position& newEnd) |
| 172 { | 172 { |
| 173 ASSERT(comparePositions(newEnd, newStart) >= 0); | 173 DCHECK_GE(comparePositions(newEnd, newStart), 0); |
| 174 | 174 |
| 175 if (!m_useEndingSelection && (newStart != m_start || newEnd != m_end)) | 175 if (!m_useEndingSelection && (newStart != m_start || newEnd != m_end)) |
| 176 m_useEndingSelection = true; | 176 m_useEndingSelection = true; |
| 177 | 177 |
| 178 setEndingSelection(VisibleSelection(newStart, newEnd, VP_DEFAULT_AFFINITY, e ndingSelection().isDirectional())); | 178 setEndingSelection(VisibleSelection(newStart, newEnd, VP_DEFAULT_AFFINITY, e ndingSelection().isDirectional())); |
| 179 m_start = newStart; | 179 m_start = newStart; |
| 180 m_end = newEnd; | 180 m_end = newEnd; |
| 181 } | 181 } |
| 182 | 182 |
| 183 Position ApplyStyleCommand::startPosition() | 183 Position ApplyStyleCommand::startPosition() |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 352 if (isValidCaretPositionInTextNode(end)) { | 352 if (isValidCaretPositionInTextNode(end)) { |
| 353 splitTextAtEnd(start, end); | 353 splitTextAtEnd(start, end); |
| 354 start = startPosition(); | 354 start = startPosition(); |
| 355 end = endPosition(); | 355 end = endPosition(); |
| 356 } | 356 } |
| 357 | 357 |
| 358 // Calculate loop end point. | 358 // Calculate loop end point. |
| 359 // If the end node is before the start node (can only happen if the end node is | 359 // If the end node is before the start node (can only happen if the end node is |
| 360 // an ancestor of the start node), we gather nodes up to the next sibling of the end node | 360 // an ancestor of the start node), we gather nodes up to the next sibling of the end node |
| 361 Node* beyondEnd; | 361 Node* beyondEnd; |
| 362 ASSERT(start.anchorNode()); | 362 DCHECK(start.anchorNode()); |
| 363 ASSERT(end.anchorNode()); | 363 DCHECK(end.anchorNode()); |
| 364 if (start.anchorNode()->isDescendantOf(end.anchorNode())) | 364 if (start.anchorNode()->isDescendantOf(end.anchorNode())) |
| 365 beyondEnd = NodeTraversal::nextSkippingChildren(*end.anchorNode()); | 365 beyondEnd = NodeTraversal::nextSkippingChildren(*end.anchorNode()); |
| 366 else | 366 else |
| 367 beyondEnd = NodeTraversal::next(*end.anchorNode()); | 367 beyondEnd = NodeTraversal::next(*end.anchorNode()); |
| 368 | 368 |
| 369 start = mostBackwardCaretPosition(start); // Move upstream to ensure we do n ot add redundant spans. | 369 start = mostBackwardCaretPosition(start); // Move upstream to ensure we do n ot add redundant spans. |
| 370 Node* startNode = start.anchorNode(); | 370 Node* startNode = start.anchorNode(); |
| 371 ASSERT(startNode); | 371 DCHECK(startNode); |
| 372 | 372 |
| 373 // Make sure we're not already at the end or the next NodeTraversal::next() will traverse | 373 // Make sure we're not already at the end or the next NodeTraversal::next() will traverse |
| 374 // past it. | 374 // past it. |
| 375 if (startNode == beyondEnd) | 375 if (startNode == beyondEnd) |
| 376 return; | 376 return; |
| 377 | 377 |
| 378 if (startNode->isTextNode() && start.computeOffsetInContainerNode() >= caret MaxOffset(startNode)) { | 378 if (startNode->isTextNode() && start.computeOffsetInContainerNode() >= caret MaxOffset(startNode)) { |
| 379 // Move out of text node if range does not include its characters. | 379 // Move out of text node if range does not include its characters. |
| 380 startNode = NodeTraversal::next(*startNode); | 380 startNode = NodeTraversal::next(*startNode); |
| 381 if (!startNode) | 381 if (!startNode) |
| 382 return; | 382 return; |
| 383 } | 383 } |
| 384 | 384 |
| 385 // Store away font size before making any changes to the document. | 385 // Store away font size before making any changes to the document. |
| 386 // This ensures that changes to one node won't effect another. | 386 // This ensures that changes to one node won't effect another. |
| 387 HeapHashMap<Member<Node>, float> startingFontSizes; | 387 HeapHashMap<Member<Node>, float> startingFontSizes; |
| 388 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(* node)) { | 388 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(* node)) { |
| 389 ASSERT(node); | 389 DCHECK(node); |
| 390 startingFontSizes.set(node, computedFontSize(node)); | 390 startingFontSizes.set(node, computedFontSize(node)); |
| 391 } | 391 } |
| 392 | 392 |
| 393 // These spans were added by us. If empty after font size changes, they can be removed. | 393 // These spans were added by us. If empty after font size changes, they can be removed. |
| 394 HeapVector<Member<HTMLElement>> unstyledSpans; | 394 HeapVector<Member<HTMLElement>> unstyledSpans; |
| 395 | 395 |
| 396 Node* lastStyledNode = nullptr; | 396 Node* lastStyledNode = nullptr; |
| 397 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(* node)) { | 397 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(* node)) { |
| 398 ASSERT(node); | 398 DCHECK(node); |
| 399 HTMLElement* element = nullptr; | 399 HTMLElement* element = nullptr; |
| 400 if (node->isHTMLElement()) { | 400 if (node->isHTMLElement()) { |
| 401 // Only work on fully selected nodes. | 401 // Only work on fully selected nodes. |
| 402 if (!elementFullySelected(toHTMLElement(*node), start, end)) | 402 if (!elementFullySelected(toHTMLElement(*node), start, end)) |
| 403 continue; | 403 continue; |
| 404 element = toHTMLElement(node); | 404 element = toHTMLElement(node); |
| 405 } else if (node->isTextNode() && node->layoutObject() && node->parentNod e() != lastStyledNode) { | 405 } else if (node->isTextNode() && node->layoutObject() && node->parentNod e() != lastStyledNode) { |
| 406 // Last styled node was not parent node of this text node, but we wi sh to style this | 406 // Last styled node was not parent node of this text node, but we wi sh to style this |
| 407 // text node. To make this possible, add a style span to surround th is text node. | 407 // text node. To make this possible, add a style span to surround th is text node. |
| 408 HTMLSpanElement* span = HTMLSpanElement::create(document()); | 408 HTMLSpanElement* span = HTMLSpanElement::create(document()); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 696 | 696 |
| 697 EditingStyle* styleToApply = style; | 697 EditingStyle* styleToApply = style; |
| 698 if (hasTextDirection) { | 698 if (hasTextDirection) { |
| 699 // Avoid applying the unicode-bidi and direction properties beneath ance stors that already have them. | 699 // Avoid applying the unicode-bidi and direction properties beneath ance stors that already have them. |
| 700 HTMLElement* embeddingStartElement = highestEmbeddingAncestor(start.anch orNode(), enclosingBlock(start.anchorNode())); | 700 HTMLElement* embeddingStartElement = highestEmbeddingAncestor(start.anch orNode(), enclosingBlock(start.anchorNode())); |
| 701 HTMLElement* embeddingEndElement = highestEmbeddingAncestor(end.anchorNo de(), enclosingBlock(end.anchorNode())); | 701 HTMLElement* embeddingEndElement = highestEmbeddingAncestor(end.anchorNo de(), enclosingBlock(end.anchorNode())); |
| 702 | 702 |
| 703 if (embeddingStartElement || embeddingEndElement) { | 703 if (embeddingStartElement || embeddingEndElement) { |
| 704 Position embeddingApplyStart = embeddingStartElement ? positionInPar entAfterNode(*embeddingStartElement) : start; | 704 Position embeddingApplyStart = embeddingStartElement ? positionInPar entAfterNode(*embeddingStartElement) : start; |
| 705 Position embeddingApplyEnd = embeddingEndElement ? positionInParentB eforeNode(*embeddingEndElement) : end; | 705 Position embeddingApplyEnd = embeddingEndElement ? positionInParentB eforeNode(*embeddingEndElement) : end; |
| 706 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul l()); | 706 DCHECK(embeddingApplyStart.isNotNull()); |
| 707 DCHECK(embeddingApplyEnd.isNotNull()); | |
| 707 | 708 |
| 708 if (!embeddingStyle) { | 709 if (!embeddingStyle) { |
| 709 styleWithoutEmbedding = style->copy(); | 710 styleWithoutEmbedding = style->copy(); |
| 710 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDire ction(); | 711 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDire ction(); |
| 711 } | 712 } |
| 712 fixRangeAndApplyInlineStyle(embeddingStyle, embeddingApplyStart, emb eddingApplyEnd, editingState); | 713 fixRangeAndApplyInlineStyle(embeddingStyle, embeddingApplyStart, emb eddingApplyEnd, editingState); |
| 713 if (editingState->isAborted()) | 714 if (editingState->isAborted()) |
| 714 return; | 715 return; |
| 715 | 716 |
| 716 styleToApply = styleWithoutEmbedding; | 717 styleToApply = styleWithoutEmbedding; |
| 717 } | 718 } |
| 718 } | 719 } |
| 719 | 720 |
| 720 fixRangeAndApplyInlineStyle(styleToApply, start, end, editingState); | 721 fixRangeAndApplyInlineStyle(styleToApply, start, end, editingState); |
| 721 if (editingState->isAborted()) | 722 if (editingState->isAborted()) |
| 722 return; | 723 return; |
| 723 | 724 |
| 724 // Remove dummy style spans created by splitting text elements. | 725 // Remove dummy style spans created by splitting text elements. |
| 725 cleanupUnstyledAppleStyleSpans(startDummySpanAncestor, editingState); | 726 cleanupUnstyledAppleStyleSpans(startDummySpanAncestor, editingState); |
| 726 if (editingState->isAborted()) | 727 if (editingState->isAborted()) |
| 727 return; | 728 return; |
| 728 if (endDummySpanAncestor != startDummySpanAncestor) | 729 if (endDummySpanAncestor != startDummySpanAncestor) |
| 729 cleanupUnstyledAppleStyleSpans(endDummySpanAncestor, editingState); | 730 cleanupUnstyledAppleStyleSpans(endDummySpanAncestor, editingState); |
| 730 } | 731 } |
| 731 | 732 |
| 732 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const P osition& start, const Position& end, EditingState* editingState) | 733 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const P osition& start, const Position& end, EditingState* editingState) |
| 733 { | 734 { |
| 734 Node* startNode = start.anchorNode(); | 735 Node* startNode = start.anchorNode(); |
| 735 ASSERT(startNode); | 736 DCHECK(startNode); |
| 736 | 737 |
| 737 if (start.computeEditingOffset() >= caretMaxOffset(start.anchorNode())) { | 738 if (start.computeEditingOffset() >= caretMaxOffset(start.anchorNode())) { |
| 738 startNode = NodeTraversal::next(*startNode); | 739 startNode = NodeTraversal::next(*startNode); |
| 739 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star tNode)) < 0) | 740 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star tNode)) < 0) |
| 740 return; | 741 return; |
| 741 } | 742 } |
| 742 | 743 |
| 743 Node* pastEndNode = end.anchorNode(); | 744 Node* pastEndNode = end.anchorNode(); |
| 744 if (end.computeEditingOffset() >= caretMaxOffset(end.anchorNode())) | 745 if (end.computeEditingOffset() >= caretMaxOffset(end.anchorNode())) |
| 745 pastEndNode = NodeTraversal::nextSkippingChildren(*end.anchorNode()); | 746 pastEndNode = NodeTraversal::nextSkippingChildren(*end.anchorNode()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 777 } | 778 } |
| 778 | 779 |
| 779 class InlineRunToApplyStyle { | 780 class InlineRunToApplyStyle { |
| 780 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 781 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
| 781 public: | 782 public: |
| 782 InlineRunToApplyStyle(Node* start, Node* end, Node* pastEndNode) | 783 InlineRunToApplyStyle(Node* start, Node* end, Node* pastEndNode) |
| 783 : start(start) | 784 : start(start) |
| 784 , end(end) | 785 , end(end) |
| 785 , pastEndNode(pastEndNode) | 786 , pastEndNode(pastEndNode) |
| 786 { | 787 { |
| 787 ASSERT(start->parentNode() == end->parentNode()); | 788 DCHECK_EQ(start->parentNode(), end->parentNode()); |
| 788 } | 789 } |
| 789 | 790 |
| 790 bool startAndEndAreStillInDocument() | 791 bool startAndEndAreStillInDocument() |
| 791 { | 792 { |
| 792 return start && end && start->inShadowIncludingDocument() && end->inShad owIncludingDocument(); | 793 return start && end && start->inShadowIncludingDocument() && end->inShad owIncludingDocument(); |
| 793 } | 794 } |
| 794 | 795 |
| 795 DEFINE_INLINE_TRACE() | 796 DEFINE_INLINE_TRACE() |
| 796 { | 797 { |
| 797 visitor->trace(start); | 798 visitor->trace(start); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 | 862 |
| 862 Node* runStart = node; | 863 Node* runStart = node; |
| 863 Node* runEnd = node; | 864 Node* runEnd = node; |
| 864 Node* sibling = node->nextSibling(); | 865 Node* sibling = node->nextSibling(); |
| 865 while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNo de) | 866 while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNo de) |
| 866 && (!isEnclosingBlock(sibling) || isHTMLBRElement(*sibling)) | 867 && (!isEnclosingBlock(sibling) || isHTMLBRElement(*sibling)) |
| 867 && !containsNonEditableRegion(*sibling)) { | 868 && !containsNonEditableRegion(*sibling)) { |
| 868 runEnd = sibling; | 869 runEnd = sibling; |
| 869 sibling = runEnd->nextSibling(); | 870 sibling = runEnd->nextSibling(); |
| 870 } | 871 } |
| 871 ASSERT(runEnd); | 872 DCHECK(runEnd); |
| 872 next = NodeTraversal::nextSkippingChildren(*runEnd); | 873 next = NodeTraversal::nextSkippingChildren(*runEnd); |
| 873 | 874 |
| 874 Node* pastEndNode = NodeTraversal::nextSkippingChildren(*runEnd); | 875 Node* pastEndNode = NodeTraversal::nextSkippingChildren(*runEnd); |
| 875 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) | 876 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) |
| 876 continue; | 877 continue; |
| 877 | 878 |
| 878 runs.append(InlineRunToApplyStyle(runStart, runEnd, pastEndNode)); | 879 runs.append(InlineRunToApplyStyle(runStart, runEnd, pastEndNode)); |
| 879 } | 880 } |
| 880 | 881 |
| 881 for (auto& run : runs) { | 882 for (auto& run : runs) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 911 } | 912 } |
| 912 | 913 |
| 913 bool ApplyStyleCommand::isStyledInlineElementToRemove(Element* element) const | 914 bool ApplyStyleCommand::isStyledInlineElementToRemove(Element* element) const |
| 914 { | 915 { |
| 915 return (m_styledInlineElement && element->hasTagName(m_styledInlineElement-> tagQName())) | 916 return (m_styledInlineElement && element->hasTagName(m_styledInlineElement-> tagQName())) |
| 916 || (m_isInlineElementToRemoveFunction && m_isInlineElementToRemoveFuncti on(element)); | 917 || (m_isInlineElementToRemoveFunction && m_isInlineElementToRemoveFuncti on(element)); |
| 917 } | 918 } |
| 918 | 919 |
| 919 bool ApplyStyleCommand::shouldApplyInlineStyleToRun(EditingStyle* style, Node* r unStart, Node* pastEndNode) | 920 bool ApplyStyleCommand::shouldApplyInlineStyleToRun(EditingStyle* style, Node* r unStart, Node* pastEndNode) |
| 920 { | 921 { |
| 921 ASSERT(style && runStart); | 922 DCHECK(style); |
| 923 DCHECK(runStart); | |
| 922 | 924 |
| 923 for (Node* node = runStart; node && node != pastEndNode; node = NodeTraversa l::next(*node)) { | 925 for (Node* node = runStart; node && node != pastEndNode; node = NodeTraversa l::next(*node)) { |
| 924 if (node->hasChildren()) | 926 if (node->hasChildren()) |
| 925 continue; | 927 continue; |
| 926 // We don't consider m_isInlineElementToRemoveFunction here because we n ever apply style when m_isInlineElementToRemoveFunction is specified | 928 // We don't consider m_isInlineElementToRemoveFunction here because we n ever apply style when m_isInlineElementToRemoveFunction is specified |
| 927 if (!style->styleIsPresentInComputedStyleOfNode(node)) | 929 if (!style->styleIsPresentInComputedStyleOfNode(node)) |
| 928 return true; | 930 return true; |
| 929 if (m_styledInlineElement && !enclosingElementWithTag(positionBeforeNode (node), m_styledInlineElement->tagQName())) | 931 if (m_styledInlineElement && !enclosingElementWithTag(positionBeforeNode (node), m_styledInlineElement->tagQName())) |
| 930 return true; | 932 return true; |
| 931 } | 933 } |
| 932 return false; | 934 return false; |
| 933 } | 935 } |
| 934 | 936 |
| 935 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, Member<Node>& runStart, Member<Node>& runEnd, Node* pastEndNode, EditingState* editingState) | 937 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, Member<Node>& runStart, Member<Node>& runEnd, Node* pastEndNode, EditingState* editingState) |
| 936 { | 938 { |
| 937 ASSERT(runStart && runEnd); | 939 DCHECK(runStart); |
| 940 DCHECK(runEnd); | |
| 938 Node* next = runStart; | 941 Node* next = runStart; |
| 939 for (Node* node = next; node && node->inShadowIncludingDocument() && node != pastEndNode; node = next) { | 942 for (Node* node = next; node && node->inShadowIncludingDocument() && node != pastEndNode; node = next) { |
| 940 if (editingIgnoresContent(node)) { | 943 if (editingIgnoresContent(node)) { |
| 941 ASSERT(!node->contains(pastEndNode)); | 944 DCHECK(!node->contains(pastEndNode)); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< node << ' ' << pastEnd|?
| |
| 942 next = NodeTraversal::nextSkippingChildren(*node); | 945 next = NodeTraversal::nextSkippingChildren(*node); |
| 943 } else { | 946 } else { |
| 944 next = NodeTraversal::next(*node); | 947 next = NodeTraversal::next(*node); |
| 945 } | 948 } |
| 946 if (!node->isHTMLElement()) | 949 if (!node->isHTMLElement()) |
| 947 continue; | 950 continue; |
| 948 | 951 |
| 949 HTMLElement& element = toHTMLElement(*node); | 952 HTMLElement& element = toHTMLElement(*node); |
| 950 Node* previousSibling = element.previousSibling(); | 953 Node* previousSibling = element.previousSibling(); |
| 951 Node* nextSibling = element.nextSibling(); | 954 Node* nextSibling = element.nextSibling(); |
| 952 ContainerNode* parent = element.parentNode(); | 955 ContainerNode* parent = element.parentNode(); |
| 953 removeInlineStyleFromElement(style, &element, editingState, RemoveAlways ); | 956 removeInlineStyleFromElement(style, &element, editingState, RemoveAlways ); |
| 954 if (editingState->isAborted()) | 957 if (editingState->isAborted()) |
| 955 return; | 958 return; |
| 956 if (!element.inShadowIncludingDocument()) { | 959 if (!element.inShadowIncludingDocument()) { |
| 957 // FIXME: We might need to update the start and the end of current s election here but need a test. | 960 // FIXME: We might need to update the start and the end of current s election here but need a test. |
| 958 if (runStart == element) | 961 if (runStart == element) |
| 959 runStart = previousSibling ? previousSibling->nextSibling() : pa rent->firstChild(); | 962 runStart = previousSibling ? previousSibling->nextSibling() : pa rent->firstChild(); |
| 960 if (runEnd == element) | 963 if (runEnd == element) |
| 961 runEnd = nextSibling ? nextSibling->previousSibling() : parent-> lastChild(); | 964 runEnd = nextSibling ? nextSibling->previousSibling() : parent-> lastChild(); |
| 962 } | 965 } |
| 963 } | 966 } |
| 964 } | 967 } |
| 965 | 968 |
| 966 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, HTMLEl ement* element, EditingState* editingState, InlineStyleRemovalMode mode, Editing Style* extractedStyle) | 969 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, HTMLEl ement* element, EditingState* editingState, InlineStyleRemovalMode mode, Editing Style* extractedStyle) |
| 967 { | 970 { |
| 968 ASSERT(element); | 971 DCHECK(element); |
| 969 | 972 |
| 970 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node ::UserSelectAllIsAlwaysNonEditable)) | 973 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node ::UserSelectAllIsAlwaysNonEditable)) |
| 971 return false; | 974 return false; |
| 972 | 975 |
| 973 if (isStyledInlineElementToRemove(element)) { | 976 if (isStyledInlineElementToRemove(element)) { |
| 974 if (mode == RemoveNone) | 977 if (mode == RemoveNone) |
| 975 return true; | 978 return true; |
| 976 if (extractedStyle) | 979 if (extractedStyle) |
| 977 extractedStyle->mergeInlineStyleOfElement(element, EditingStyle::Ove rrideValues); | 980 extractedStyle->mergeInlineStyleOfElement(element, EditingStyle::Ove rrideValues); |
| 978 removeNodePreservingChildren(element, editingState); | 981 removeNodePreservingChildren(element, editingState); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1001 void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement* elem, EditingState* editingState) | 1004 void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement* elem, EditingState* editingState) |
| 1002 { | 1005 { |
| 1003 if (hasNoAttributeOrOnlyStyleAttribute(elem, StyleAttributeShouldBeEmpty)) | 1006 if (hasNoAttributeOrOnlyStyleAttribute(elem, StyleAttributeShouldBeEmpty)) |
| 1004 removeNodePreservingChildren(elem, editingState); | 1007 removeNodePreservingChildren(elem, editingState); |
| 1005 else | 1008 else |
| 1006 replaceElementWithSpanPreservingChildrenAndAttributes(elem); | 1009 replaceElementWithSpanPreservingChildrenAndAttributes(elem); |
| 1007 } | 1010 } |
| 1008 | 1011 |
| 1009 bool ApplyStyleCommand::removeImplicitlyStyledElement(EditingStyle* style, HTMLE lement* element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle, Edit ingState* editingState) | 1012 bool ApplyStyleCommand::removeImplicitlyStyledElement(EditingStyle* style, HTMLE lement* element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle, Edit ingState* editingState) |
| 1010 { | 1013 { |
| 1011 ASSERT(style); | 1014 DCHECK(style); |
| 1012 if (mode == RemoveNone) { | 1015 if (mode == RemoveNone) { |
| 1013 ASSERT(!extractedStyle); | 1016 DCHECK(!extractedStyle); |
| 1014 return style->conflictsWithImplicitStyleOfElement(element) || style->con flictsWithImplicitStyleOfAttributes(element); | 1017 return style->conflictsWithImplicitStyleOfElement(element) || style->con flictsWithImplicitStyleOfAttributes(element); |
| 1015 } | 1018 } |
| 1016 | 1019 |
| 1017 ASSERT(mode == RemoveIfNeeded || mode == RemoveAlways); | 1020 DCHECK(mode == RemoveIfNeeded || mode == RemoveAlways); |
| 1018 if (style->conflictsWithImplicitStyleOfElement(element, extractedStyle, mode == RemoveAlways ? EditingStyle::ExtractMatchingStyle : EditingStyle::DoNotExtra ctMatchingStyle)) { | 1021 if (style->conflictsWithImplicitStyleOfElement(element, extractedStyle, mode == RemoveAlways ? EditingStyle::ExtractMatchingStyle : EditingStyle::DoNotExtra ctMatchingStyle)) { |
| 1019 replaceWithSpanOrRemoveIfWithoutAttributes(element, editingState); | 1022 replaceWithSpanOrRemoveIfWithoutAttributes(element, editingState); |
| 1020 if (editingState->isAborted()) | 1023 if (editingState->isAborted()) |
| 1021 return false; | 1024 return false; |
| 1022 return true; | 1025 return true; |
| 1023 } | 1026 } |
| 1024 | 1027 |
| 1025 // unicode-bidi and direction are pushed down separately so don't push down with other styles | 1028 // unicode-bidi and direction are pushed down separately so don't push down with other styles |
| 1026 Vector<QualifiedName> attributes; | 1029 Vector<QualifiedName> attributes; |
| 1027 if (!style->extractConflictingImplicitStyleOfAttributes(element, extractedSt yle ? EditingStyle::PreserveWritingDirection : EditingStyle::DoNotPreserveWritin gDirection, | 1030 if (!style->extractConflictingImplicitStyleOfAttributes(element, extractedSt yle ? EditingStyle::PreserveWritingDirection : EditingStyle::DoNotPreserveWritin gDirection, |
| 1028 extractedStyle, attributes, mode == RemoveAlways ? EditingStyle::Extract MatchingStyle : EditingStyle::DoNotExtractMatchingStyle)) | 1031 extractedStyle, attributes, mode == RemoveAlways ? EditingStyle::Extract MatchingStyle : EditingStyle::DoNotExtractMatchingStyle)) |
| 1029 return false; | 1032 return false; |
| 1030 | 1033 |
| 1031 for (const auto& attribute : attributes) | 1034 for (const auto& attribute : attributes) |
| 1032 removeElementAttribute(element, attribute); | 1035 removeElementAttribute(element, attribute); |
| 1033 | 1036 |
| 1034 if (isEmptyFontTag(element) || isSpanWithoutAttributesOrUnstyledStyleSpan(el ement)) { | 1037 if (isEmptyFontTag(element) || isSpanWithoutAttributesOrUnstyledStyleSpan(el ement)) { |
| 1035 removeNodePreservingChildren(element, editingState); | 1038 removeNodePreservingChildren(element, editingState); |
| 1036 if (editingState->isAborted()) | 1039 if (editingState->isAborted()) |
| 1037 return false; | 1040 return false; |
| 1038 } | 1041 } |
| 1039 | 1042 |
| 1040 return true; | 1043 return true; |
| 1041 } | 1044 } |
| 1042 | 1045 |
| 1043 bool ApplyStyleCommand::removeCSSStyle(EditingStyle* style, HTMLElement* element , EditingState* editingState, InlineStyleRemovalMode mode, EditingStyle* extract edStyle) | 1046 bool ApplyStyleCommand::removeCSSStyle(EditingStyle* style, HTMLElement* element , EditingState* editingState, InlineStyleRemovalMode mode, EditingStyle* extract edStyle) |
| 1044 { | 1047 { |
| 1045 ASSERT(style); | 1048 DCHECK(style); |
| 1046 ASSERT(element); | 1049 DCHECK(element); |
| 1047 | 1050 |
| 1048 if (mode == RemoveNone) | 1051 if (mode == RemoveNone) |
| 1049 return style->conflictsWithInlineStyleOfElement(element); | 1052 return style->conflictsWithInlineStyleOfElement(element); |
| 1050 | 1053 |
| 1051 Vector<CSSPropertyID> properties; | 1054 Vector<CSSPropertyID> properties; |
| 1052 if (!style->conflictsWithInlineStyleOfElement(element, extractedStyle, prope rties)) | 1055 if (!style->conflictsWithInlineStyleOfElement(element, extractedStyle, prope rties)) |
| 1053 return false; | 1056 return false; |
| 1054 | 1057 |
| 1055 // FIXME: We should use a mass-removal function here but we don't have an un doable one yet. | 1058 // FIXME: We should use a mass-removal function here but we don't have an un doable one yet. |
| 1056 for (const auto& property : properties) | 1059 for (const auto& property : properties) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1077 // also stop at the unsplittable element to be consistent with other UAs | 1080 // also stop at the unsplittable element to be consistent with other UAs |
| 1078 if (n == unsplittableElement) | 1081 if (n == unsplittableElement) |
| 1079 break; | 1082 break; |
| 1080 } | 1083 } |
| 1081 | 1084 |
| 1082 return result; | 1085 return result; |
| 1083 } | 1086 } |
| 1084 | 1087 |
| 1085 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty le, EditingState* editingState) | 1088 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty le, EditingState* editingState) |
| 1086 { | 1089 { |
| 1087 ASSERT(node); | 1090 DCHECK(node); |
| 1088 | 1091 |
| 1089 node->document().updateLayoutTree(); | 1092 node->document().updateLayoutTree(); |
| 1090 | 1093 |
| 1091 if (!style || style->isEmpty() || !node->layoutObject() || isHTMLIFrameEleme nt(*node)) | 1094 if (!style || style->isEmpty() || !node->layoutObject() || isHTMLIFrameEleme nt(*node)) |
| 1092 return; | 1095 return; |
| 1093 | 1096 |
| 1094 EditingStyle* newInlineStyle = style; | 1097 EditingStyle* newInlineStyle = style; |
| 1095 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { | 1098 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { |
| 1096 newInlineStyle = style->copy(); | 1099 newInlineStyle = style->copy(); |
| 1097 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt yle::OverrideValues); | 1100 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt yle::OverrideValues); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1171 // We found the next node for the outer loop (contains targetNode) | 1174 // We found the next node for the outer loop (contains targetNode) |
| 1172 // When reached targetNode, stop the outer loop upon the completion of the current inner loop | 1175 // When reached targetNode, stop the outer loop upon the completion of the current inner loop |
| 1173 if (child == targetNode || child->contains(targetNode)) | 1176 if (child == targetNode || child->contains(targetNode)) |
| 1174 current = child; | 1177 current = child; |
| 1175 } | 1178 } |
| 1176 } | 1179 } |
| 1177 } | 1180 } |
| 1178 | 1181 |
| 1179 void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &s tart, const Position &end, EditingState* editingState) | 1182 void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &s tart, const Position &end, EditingState* editingState) |
| 1180 { | 1183 { |
| 1181 ASSERT(start.isNotNull()); | 1184 DCHECK(start.isNotNull()); |
| 1182 ASSERT(end.isNotNull()); | 1185 DCHECK(end.isNotNull()); |
| 1183 ASSERT(start.inShadowIncludingDocument()); | 1186 DCHECK(start.inShadowIncludingDocument()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< start|?
| |
| 1184 ASSERT(end.inShadowIncludingDocument()); | 1187 DCHECK(end.inShadowIncludingDocument()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< end|?
| |
| 1185 ASSERT(Position::commonAncestorTreeScope(start, end)); | 1188 DCHECK(Position::commonAncestorTreeScope(start, end)); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< start << ' ' << end|?
| |
| 1186 ASSERT(comparePositions(start, end) <= 0); | 1189 DCHECK_LE(comparePositions(start, end), 0); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< start << ' ' << end|?
Could y
| |
| 1187 // FIXME: We should assert that start/end are not in the middle of a text no de. | 1190 // FIXME: We should assert that start/end are not in the middle of a text no de. |
| 1188 | 1191 |
| 1189 Position pushDownStart = mostForwardCaretPosition(start); | 1192 Position pushDownStart = mostForwardCaretPosition(start); |
| 1190 // If the pushDownStart is at the end of a text node, then this node is not fully selected. | 1193 // If the pushDownStart is at the end of a text node, then this node is not fully selected. |
| 1191 // Move it to the next deep quivalent position to avoid removing the style f rom this node. | 1194 // Move it to the next deep quivalent position to avoid removing the style f rom this node. |
| 1192 // e.g. if pushDownStart was at Position("hello", 5) in <b>hello<div>world</ div></b>, we want Position("world", 0) instead. | 1195 // e.g. if pushDownStart was at Position("hello", 5) in <b>hello<div>world</ div></b>, we want Position("world", 0) instead. |
| 1193 Node* pushDownStartContainer = pushDownStart.computeContainerNode(); | 1196 Node* pushDownStartContainer = pushDownStart.computeContainerNode(); |
| 1194 if (pushDownStartContainer && pushDownStartContainer->isTextNode() | 1197 if (pushDownStartContainer && pushDownStartContainer->isTextNode() |
| 1195 && pushDownStart.computeOffsetInContainerNode() == pushDownStartContaine r->maxCharacterOffset()) | 1198 && pushDownStart.computeOffsetInContainerNode() == pushDownStartContaine r->maxCharacterOffset()) |
| 1196 pushDownStart = nextVisuallyDistinctCandidate(pushDownStart); | 1199 pushDownStart = nextVisuallyDistinctCandidate(pushDownStart); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1218 | 1221 |
| 1219 // Current ending selection resetting algorithm assumes |start| and |end| | 1222 // Current ending selection resetting algorithm assumes |start| and |end| |
| 1220 // are in a same DOM tree even if they are not in document. | 1223 // are in a same DOM tree even if they are not in document. |
| 1221 if (!Position::commonAncestorTreeScope(start, end)) | 1224 if (!Position::commonAncestorTreeScope(start, end)) |
| 1222 return; | 1225 return; |
| 1223 | 1226 |
| 1224 Node* node = start.anchorNode(); | 1227 Node* node = start.anchorNode(); |
| 1225 while (node) { | 1228 while (node) { |
| 1226 Node* next = nullptr; | 1229 Node* next = nullptr; |
| 1227 if (editingIgnoresContent(node)) { | 1230 if (editingIgnoresContent(node)) { |
| 1228 ASSERT(node == end.anchorNode() || !node->contains(end.anchorNode()) ); | 1231 DCHECK(node == end.anchorNode() || !node->contains(end.anchorNode()) ); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< node << ' ' << end|?
| |
| 1229 next = NodeTraversal::nextSkippingChildren(*node); | 1232 next = NodeTraversal::nextSkippingChildren(*node); |
| 1230 } else { | 1233 } else { |
| 1231 next = NodeTraversal::next(*node); | 1234 next = NodeTraversal::next(*node); |
| 1232 } | 1235 } |
| 1233 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node), start, end)) { | 1236 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node), start, end)) { |
| 1234 HTMLElement* elem = toHTMLElement(node); | 1237 HTMLElement* elem = toHTMLElement(node); |
| 1235 Node* prev = NodeTraversal::previousPostOrder(*elem); | 1238 Node* prev = NodeTraversal::previousPostOrder(*elem); |
| 1236 Node* next = NodeTraversal::next(*elem); | 1239 Node* next = NodeTraversal::next(*elem); |
| 1237 EditingStyle* styleToPushDown = nullptr; | 1240 EditingStyle* styleToPushDown = nullptr; |
| 1238 Node* childNode = nullptr; | 1241 Node* childNode = nullptr; |
| 1239 if (isStyledInlineElementToRemove(elem)) { | 1242 if (isStyledInlineElementToRemove(elem)) { |
| 1240 styleToPushDown = EditingStyle::create(); | 1243 styleToPushDown = EditingStyle::create(); |
| 1241 childNode = elem->firstChild(); | 1244 childNode = elem->firstChild(); |
| 1242 } | 1245 } |
| 1243 | 1246 |
| 1244 removeInlineStyleFromElement(style, elem, editingState, RemoveIfNeed ed, styleToPushDown); | 1247 removeInlineStyleFromElement(style, elem, editingState, RemoveIfNeed ed, styleToPushDown); |
| 1245 if (editingState->isAborted()) | 1248 if (editingState->isAborted()) |
| 1246 return; | 1249 return; |
| 1247 if (!elem->inShadowIncludingDocument()) { | 1250 if (!elem->inShadowIncludingDocument()) { |
| 1248 if (s.anchorNode() == elem) { | 1251 if (s.anchorNode() == elem) { |
| 1249 // Since elem must have been fully selected, and it is at th e start | 1252 // Since elem must have been fully selected, and it is at th e start |
| 1250 // of the selection, it is clear we can set the new s offset to 0. | 1253 // of the selection, it is clear we can set the new s offset to 0. |
| 1251 ASSERT(s.isBeforeAnchor() || s.isBeforeChildren() || s.offse tInContainerNode() <= 0); | 1254 DCHECK(s.isBeforeAnchor() || s.isBeforeChildren() || s.offse tInContainerNode() <= 0); |
|
yosin_UTC9
2016/04/14 04:35:00
How about adding |<< s|?
| |
| 1252 s = firstPositionInOrBeforeNode(next); | 1255 s = firstPositionInOrBeforeNode(next); |
| 1253 } | 1256 } |
| 1254 if (e.anchorNode() == elem) { | 1257 if (e.anchorNode() == elem) { |
| 1255 // Since elem must have been fully selected, and it is at th e end | 1258 // Since elem must have been fully selected, and it is at th e end |
| 1256 // of the selection, it is clear we can set the new e offset to | 1259 // of the selection, it is clear we can set the new e offset to |
| 1257 // the max range offset of prev. | 1260 // the max range offset of prev. |
| 1258 ASSERT(s.isAfterAnchor() || !offsetIsBeforeLastNodeOffset(s. offsetInContainerNode(), s.computeContainerNode())); | 1261 DCHECK(s.isAfterAnchor() || !offsetIsBeforeLastNodeOffset(s. offsetInContainerNode(), s.computeContainerNode())); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< s|?
| |
| 1259 e = lastPositionInOrAfterNode(prev); | 1262 e = lastPositionInOrAfterNode(prev); |
| 1260 } | 1263 } |
| 1261 } | 1264 } |
| 1262 | 1265 |
| 1263 if (styleToPushDown) { | 1266 if (styleToPushDown) { |
| 1264 for (; childNode; childNode = childNode->nextSibling()) { | 1267 for (; childNode; childNode = childNode->nextSibling()) { |
| 1265 applyInlineStyleToPushDown(childNode, styleToPushDown, editi ngState); | 1268 applyInlineStyleToPushDown(childNode, styleToPushDown, editi ngState); |
| 1266 if (editingState->isAborted()) | 1269 if (editingState->isAborted()) |
| 1267 return; | 1270 return; |
| 1268 } | 1271 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1280 { | 1283 { |
| 1281 // The tree may have changed and Position::upstream() relies on an up-to-dat e layout. | 1284 // The tree may have changed and Position::upstream() relies on an up-to-dat e layout. |
| 1282 element.document().updateLayoutIgnorePendingStylesheets(); | 1285 element.document().updateLayoutIgnorePendingStylesheets(); |
| 1283 | 1286 |
| 1284 return comparePositions(firstPositionInOrBeforeNode(&element), start) >= 0 | 1287 return comparePositions(firstPositionInOrBeforeNode(&element), start) >= 0 |
| 1285 && comparePositions(mostBackwardCaretPosition(lastPositionInOrAfterNode( &element)), end) <= 0; | 1288 && comparePositions(mostBackwardCaretPosition(lastPositionInOrAfterNode( &element)), end) <= 0; |
| 1286 } | 1289 } |
| 1287 | 1290 |
| 1288 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position& end) | 1291 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position& end) |
| 1289 { | 1292 { |
| 1290 ASSERT(start.computeContainerNode()->isTextNode()); | 1293 DCHECK(start.computeContainerNode()->isTextNode()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< s|?
| |
| 1291 | 1294 |
| 1292 Position newEnd; | 1295 Position newEnd; |
| 1293 if (end.isOffsetInAnchor() && start.computeContainerNode() == end.computeCon tainerNode()) | 1296 if (end.isOffsetInAnchor() && start.computeContainerNode() == end.computeCon tainerNode()) |
| 1294 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode( ) - start.offsetInContainerNode()); | 1297 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode( ) - start.offsetInContainerNode()); |
| 1295 else | 1298 else |
| 1296 newEnd = end; | 1299 newEnd = end; |
| 1297 | 1300 |
| 1298 Text* text = toText(start.computeContainerNode()); | 1301 Text* text = toText(start.computeContainerNode()); |
| 1299 splitTextNode(text, start.offsetInContainerNode()); | 1302 splitTextNode(text, start.offsetInContainerNode()); |
| 1300 updateStartEnd(firstPositionInNode(text), newEnd); | 1303 updateStartEnd(firstPositionInNode(text), newEnd); |
| 1301 } | 1304 } |
| 1302 | 1305 |
| 1303 void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en d) | 1306 void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en d) |
| 1304 { | 1307 { |
| 1305 ASSERT(end.computeContainerNode()->isTextNode()); | 1308 DCHECK(end.computeContainerNode()->isTextNode()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< end|?
| |
| 1306 | 1309 |
| 1307 bool shouldUpdateStart = start.isOffsetInAnchor() && start.computeContainerN ode() == end.computeContainerNode(); | 1310 bool shouldUpdateStart = start.isOffsetInAnchor() && start.computeContainerN ode() == end.computeContainerNode(); |
| 1308 Text* text = toText(end.anchorNode()); | 1311 Text* text = toText(end.anchorNode()); |
| 1309 splitTextNode(text, end.offsetInContainerNode()); | 1312 splitTextNode(text, end.offsetInContainerNode()); |
| 1310 | 1313 |
| 1311 Node* prevNode = text->previousSibling(); | 1314 Node* prevNode = text->previousSibling(); |
| 1312 if (!prevNode || !prevNode->isTextNode()) | 1315 if (!prevNode || !prevNode->isTextNode()) |
| 1313 return; | 1316 return; |
| 1314 | 1317 |
| 1315 Position newStart = shouldUpdateStart ? Position(toText(prevNode), start.off setInContainerNode()) : start; | 1318 Position newStart = shouldUpdateStart ? Position(toText(prevNode), start.off setInContainerNode()) : start; |
| 1316 updateStartEnd(newStart, lastPositionInNode(prevNode)); | 1319 updateStartEnd(newStart, lastPositionInNode(prevNode)); |
| 1317 } | 1320 } |
| 1318 | 1321 |
| 1319 void ApplyStyleCommand::splitTextElementAtStart(const Position& start, const Pos ition& end) | 1322 void ApplyStyleCommand::splitTextElementAtStart(const Position& start, const Pos ition& end) |
| 1320 { | 1323 { |
| 1321 ASSERT(start.computeContainerNode()->isTextNode()); | 1324 DCHECK(start.computeContainerNode()->isTextNode()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< start|?
| |
| 1322 | 1325 |
| 1323 Position newEnd; | 1326 Position newEnd; |
| 1324 if (start.computeContainerNode() == end.computeContainerNode()) | 1327 if (start.computeContainerNode() == end.computeContainerNode()) |
| 1325 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode( ) - start.offsetInContainerNode()); | 1328 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode( ) - start.offsetInContainerNode()); |
| 1326 else | 1329 else |
| 1327 newEnd = end; | 1330 newEnd = end; |
| 1328 | 1331 |
| 1329 splitTextNodeContainingElement(toText(start.computeContainerNode()), start.o ffsetInContainerNode()); | 1332 splitTextNodeContainingElement(toText(start.computeContainerNode()), start.o ffsetInContainerNode()); |
| 1330 updateStartEnd(positionBeforeNode(start.computeContainerNode()), newEnd); | 1333 updateStartEnd(positionBeforeNode(start.computeContainerNode()), newEnd); |
| 1331 } | 1334 } |
| 1332 | 1335 |
| 1333 void ApplyStyleCommand::splitTextElementAtEnd(const Position& start, const Posit ion& end) | 1336 void ApplyStyleCommand::splitTextElementAtEnd(const Position& start, const Posit ion& end) |
| 1334 { | 1337 { |
| 1335 ASSERT(end.computeContainerNode()->isTextNode()); | 1338 DCHECK(end.computeContainerNode()->isTextNode()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< end|?
| |
| 1336 | 1339 |
| 1337 bool shouldUpdateStart = start.computeContainerNode() == end.computeContaine rNode(); | 1340 bool shouldUpdateStart = start.computeContainerNode() == end.computeContaine rNode(); |
| 1338 splitTextNodeContainingElement(toText(end.computeContainerNode()), end.offse tInContainerNode()); | 1341 splitTextNodeContainingElement(toText(end.computeContainerNode()), end.offse tInContainerNode()); |
| 1339 | 1342 |
| 1340 Node* parentElement = end.computeContainerNode()->parentNode(); | 1343 Node* parentElement = end.computeContainerNode()->parentNode(); |
| 1341 if (!parentElement || !parentElement->previousSibling()) | 1344 if (!parentElement || !parentElement->previousSibling()) |
| 1342 return; | 1345 return; |
| 1343 Node* firstTextNode = parentElement->previousSibling()->lastChild(); | 1346 Node* firstTextNode = parentElement->previousSibling()->lastChild(); |
| 1344 if (!firstTextNode || !firstTextNode->isTextNode()) | 1347 if (!firstTextNode || !firstTextNode->isTextNode()) |
| 1345 return; | 1348 return; |
| 1346 | 1349 |
| 1347 Position newStart = shouldUpdateStart ? Position(toText(firstTextNode), star t.offsetInContainerNode()) : start; | 1350 Position newStart = shouldUpdateStart ? Position(toText(firstTextNode), star t.offsetInContainerNode()) : start; |
| 1348 updateStartEnd(newStart, positionAfterNode(firstTextNode)); | 1351 updateStartEnd(newStart, positionAfterNode(firstTextNode)); |
| 1349 } | 1352 } |
| 1350 | 1353 |
| 1351 bool ApplyStyleCommand::shouldSplitTextElement(Element* element, EditingStyle* s tyle) | 1354 bool ApplyStyleCommand::shouldSplitTextElement(Element* element, EditingStyle* s tyle) |
| 1352 { | 1355 { |
| 1353 if (!element || !element->isHTMLElement()) | 1356 if (!element || !element->isHTMLElement()) |
| 1354 return false; | 1357 return false; |
| 1355 | 1358 |
| 1356 return shouldRemoveInlineStyleFromElement(style, toHTMLElement(element)); | 1359 return shouldRemoveInlineStyleFromElement(style, toHTMLElement(element)); |
| 1357 } | 1360 } |
| 1358 | 1361 |
| 1359 bool ApplyStyleCommand::isValidCaretPositionInTextNode(const Position& position) | 1362 bool ApplyStyleCommand::isValidCaretPositionInTextNode(const Position& position) |
| 1360 { | 1363 { |
| 1361 ASSERT(position.isNotNull()); | 1364 DCHECK(position.isNotNull()); |
| 1362 | 1365 |
| 1363 Node* node = position.computeContainerNode(); | 1366 Node* node = position.computeContainerNode(); |
| 1364 if (!position.isOffsetInAnchor() || !node->isTextNode()) | 1367 if (!position.isOffsetInAnchor() || !node->isTextNode()) |
| 1365 return false; | 1368 return false; |
| 1366 int offsetInText = position.offsetInContainerNode(); | 1369 int offsetInText = position.offsetInContainerNode(); |
| 1367 return offsetInText > caretMinOffset(node) && offsetInText < caretMaxOffset( node); | 1370 return offsetInText > caretMinOffset(node) && offsetInText < caretMaxOffset( node); |
| 1368 } | 1371 } |
| 1369 | 1372 |
| 1370 bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end, EditingState* editingState) | 1373 bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end, EditingState* editingState) |
| 1371 { | 1374 { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1385 | 1388 |
| 1386 if (!startNode->isElementNode()) | 1389 if (!startNode->isElementNode()) |
| 1387 return false; | 1390 return false; |
| 1388 | 1391 |
| 1389 Node* previousSibling = startNode->previousSibling(); | 1392 Node* previousSibling = startNode->previousSibling(); |
| 1390 | 1393 |
| 1391 if (previousSibling && areIdenticalElements(*startNode, *previousSibling)) { | 1394 if (previousSibling && areIdenticalElements(*startNode, *previousSibling)) { |
| 1392 Element* previousElement = toElement(previousSibling); | 1395 Element* previousElement = toElement(previousSibling); |
| 1393 Element* element = toElement(startNode); | 1396 Element* element = toElement(startNode); |
| 1394 Node* startChild = element->firstChild(); | 1397 Node* startChild = element->firstChild(); |
| 1395 ASSERT(startChild); | 1398 DCHECK(startChild); |
| 1396 mergeIdenticalElements(previousElement, element, editingState); | 1399 mergeIdenticalElements(previousElement, element, editingState); |
| 1397 if (editingState->isAborted()) | 1400 if (editingState->isAborted()) |
| 1398 return false; | 1401 return false; |
| 1399 | 1402 |
| 1400 int startOffsetAdjustment = startChild->nodeIndex(); | 1403 int startOffsetAdjustment = startChild->nodeIndex(); |
| 1401 int endOffsetAdjustment = startNode == end.anchorNode() ? startOffsetAdj ustment : 0; | 1404 int endOffsetAdjustment = startNode == end.anchorNode() ? startOffsetAdj ustment : 0; |
| 1402 updateStartEnd(Position(startNode, startOffsetAdjustment), | 1405 updateStartEnd(Position(startNode, startOffsetAdjustment), |
| 1403 Position(end.anchorNode(), end.computeEditingOffset() + endOffsetAdj ustment)); | 1406 Position(end.anchorNode(), end.computeEditingOffset() + endOffsetAdj ustment)); |
| 1404 return true; | 1407 return true; |
| 1405 } | 1408 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1440 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC ontainerNode()) : start, | 1443 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC ontainerNode()) : start, |
| 1441 Position(nextElement, endOffset)); | 1444 Position(nextElement, endOffset)); |
| 1442 return true; | 1445 return true; |
| 1443 } | 1446 } |
| 1444 | 1447 |
| 1445 return false; | 1448 return false; |
| 1446 } | 1449 } |
| 1447 | 1450 |
| 1448 void ApplyStyleCommand::surroundNodeRangeWithElement(Node* passedStartNode, Node * endNode, Element* elementToInsert, EditingState* editingState) | 1451 void ApplyStyleCommand::surroundNodeRangeWithElement(Node* passedStartNode, Node * endNode, Element* elementToInsert, EditingState* editingState) |
| 1449 { | 1452 { |
| 1450 ASSERT(passedStartNode); | 1453 DCHECK(passedStartNode); |
| 1451 ASSERT(endNode); | 1454 DCHECK(endNode); |
| 1452 ASSERT(elementToInsert); | 1455 DCHECK(elementToInsert); |
| 1453 Node* node = passedStartNode; | 1456 Node* node = passedStartNode; |
| 1454 Element* element = elementToInsert; | 1457 Element* element = elementToInsert; |
| 1455 | 1458 |
| 1456 insertNodeBefore(element, node, editingState); | 1459 insertNodeBefore(element, node, editingState); |
| 1457 if (editingState->isAborted()) | 1460 if (editingState->isAborted()) |
| 1458 return; | 1461 return; |
| 1459 | 1462 |
| 1460 while (node) { | 1463 while (node) { |
| 1461 Node* next = node->nextSibling(); | 1464 Node* next = node->nextSibling(); |
| 1462 if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) { | 1465 if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1545 return positionBeforeNode(dummyElement); | 1548 return positionBeforeNode(dummyElement); |
| 1546 } | 1549 } |
| 1547 | 1550 |
| 1548 return firstPositionInOrBeforeNode(startNode); | 1551 return firstPositionInOrBeforeNode(startNode); |
| 1549 } | 1552 } |
| 1550 | 1553 |
| 1551 void ApplyStyleCommand::applyInlineStyleChange(Node* passedStart, Node* passedEn d, StyleChange& styleChange, EAddStyledElement addStyledElement, EditingState* e ditingState) | 1554 void ApplyStyleCommand::applyInlineStyleChange(Node* passedStart, Node* passedEn d, StyleChange& styleChange, EAddStyledElement addStyledElement, EditingState* e ditingState) |
| 1552 { | 1555 { |
| 1553 Node* startNode = passedStart; | 1556 Node* startNode = passedStart; |
| 1554 Node* endNode = passedEnd; | 1557 Node* endNode = passedEnd; |
| 1555 ASSERT(startNode->inShadowIncludingDocument()); | 1558 DCHECK(startNode->inShadowIncludingDocument()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< startNode|?
| |
| 1556 ASSERT(endNode->inShadowIncludingDocument()); | 1559 DCHECK(endNode->inShadowIncludingDocument()); |
|
yosin_UTC9
2016/04/14 04:35:01
How about adding |<< endNode|?
| |
| 1557 | 1560 |
| 1558 // Find appropriate font and span elements top-down. | 1561 // Find appropriate font and span elements top-down. |
| 1559 HTMLFontElement* fontContainer = nullptr; | 1562 HTMLFontElement* fontContainer = nullptr; |
| 1560 HTMLElement* styleContainer = nullptr; | 1563 HTMLElement* styleContainer = nullptr; |
| 1561 for (Node* container = startNode; container && startNode == endNode; contain er = container->firstChild()) { | 1564 for (Node* container = startNode; container && startNode == endNode; contain er = container->firstChild()) { |
| 1562 if (isHTMLFontElement(*container)) | 1565 if (isHTMLFontElement(*container)) |
| 1563 fontContainer = toHTMLFontElement(container); | 1566 fontContainer = toHTMLFontElement(container); |
| 1564 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); | 1567 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); |
| 1565 if (container->isHTMLElement()) { | 1568 if (container->isHTMLElement()) { |
| 1566 HTMLElement* containerElement = toHTMLElement(container); | 1569 HTMLElement* containerElement = toHTMLElement(container); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1662 return 0; | 1665 return 0; |
| 1663 | 1666 |
| 1664 CSSComputedStyleDeclaration* style = CSSComputedStyleDeclaration::create(nod e); | 1667 CSSComputedStyleDeclaration* style = CSSComputedStyleDeclaration::create(nod e); |
| 1665 if (!style) | 1668 if (!style) |
| 1666 return 0; | 1669 return 0; |
| 1667 | 1670 |
| 1668 CSSPrimitiveValue* value = toCSSPrimitiveValue(style->getPropertyCSSValue(CS SPropertyFontSize)); | 1671 CSSPrimitiveValue* value = toCSSPrimitiveValue(style->getPropertyCSSValue(CS SPropertyFontSize)); |
| 1669 if (!value) | 1672 if (!value) |
| 1670 return 0; | 1673 return 0; |
| 1671 | 1674 |
| 1672 ASSERT(value->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::Pixels) ; | 1675 DCHECK(value->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::Pixels) ; |
|
yosin_UTC9
2016/04/14 04:35:01
Could you add |TODO(yosin): We should have printer
| |
| 1673 return value->getFloatValue(); | 1676 return value->getFloatValue(); |
| 1674 } | 1677 } |
| 1675 | 1678 |
| 1676 void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position& start, const Position& end) | 1679 void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position& start, const Position& end) |
| 1677 { | 1680 { |
| 1678 if (!node) | 1681 if (!node) |
| 1679 return; | 1682 return; |
| 1680 | 1683 |
| 1681 Position newStart = start; | 1684 Position newStart = start; |
| 1682 Position newEnd = end; | 1685 Position newEnd = end; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1713 DEFINE_TRACE(ApplyStyleCommand) | 1716 DEFINE_TRACE(ApplyStyleCommand) |
| 1714 { | 1717 { |
| 1715 visitor->trace(m_style); | 1718 visitor->trace(m_style); |
| 1716 visitor->trace(m_start); | 1719 visitor->trace(m_start); |
| 1717 visitor->trace(m_end); | 1720 visitor->trace(m_end); |
| 1718 visitor->trace(m_styledInlineElement); | 1721 visitor->trace(m_styledInlineElement); |
| 1719 CompositeEditCommand::trace(visitor); | 1722 CompositeEditCommand::trace(visitor); |
| 1720 } | 1723 } |
| 1721 | 1724 |
| 1722 } // namespace blink | 1725 } // namespace blink |
| OLD | NEW |