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

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

Issue 24278008: [oilpan] Handlify Nodes in htmlediting (Closed) Base URL: svn://svn.chromium.org/blink/branches/oilpan
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 int startIndex = TextIterator::rangeLength(startRange, true); 258 int startIndex = TextIterator::rangeLength(startRange, true);
259 int endIndex = TextIterator::rangeLength(endRange, true); 259 int endIndex = TextIterator::rangeLength(endRange, true);
260 260
261 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); 261 VisiblePosition paragraphStart(startOfParagraph(visibleStart));
262 VisiblePosition nextParagraphStart(endOfParagraph(paragraphStart).next()); 262 VisiblePosition nextParagraphStart(endOfParagraph(paragraphStart).next());
263 VisiblePosition beyondEnd(endOfParagraph(visibleEnd).next()); 263 VisiblePosition beyondEnd(endOfParagraph(visibleEnd).next());
264 while (paragraphStart.isNotNull() && paragraphStart != beyondEnd) { 264 while (paragraphStart.isNotNull() && paragraphStart != beyondEnd) {
265 HandleScope scope; 265 HandleScope scope;
266 StyleChange styleChange(style, paragraphStart.deepEquivalent()); 266 StyleChange styleChange(style, paragraphStart.deepEquivalent());
267 if (styleChange.cssStyle().length() || m_removeOnly) { 267 if (styleChange.cssStyle().length() || m_removeOnly) {
268 Handle<Node> block = enclosingBlock(paragraphStart.deepEquivalent(). deprecatedNode().handle().raw()); 268 Handle<Node> block = enclosingBlock(paragraphStart.deepEquivalent(). deprecatedNode());
269 if (!m_removeOnly) { 269 if (!m_removeOnly) {
270 Handle<Node> newBlock = moveParagraphContentsToNewBlockIfNecessa ry(paragraphStart.deepEquivalent()); 270 Handle<Node> newBlock = moveParagraphContentsToNewBlockIfNecessa ry(paragraphStart.deepEquivalent());
271 if (newBlock) 271 if (newBlock)
272 block = newBlock; 272 block = newBlock;
273 } 273 }
274 ASSERT(!block || block->isHTMLElement()); 274 ASSERT(!block || block->isHTMLElement());
275 if (block && block->isHTMLElement()) { 275 if (block && block->isHTMLElement()) {
276 removeCSSStyle(style, toHTMLElement(block)); 276 removeCSSStyle(style, toHTMLElement(block));
277 if (!m_removeOnly) 277 if (!m_removeOnly)
278 addBlockStyle(styleChange, toHTMLElement(block)); 278 addBlockStyle(styleChange, toHTMLElement(block));
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 Handle<Node> beyondEnd; 352 Handle<Node> beyondEnd;
353 if (start.deprecatedNode()->isDescendantOf(end.deprecatedNode().handle().raw ())) 353 if (start.deprecatedNode()->isDescendantOf(end.deprecatedNode().handle().raw ()))
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 Handle<Node> startNode = start.deprecatedNode(); 359 Handle<Node> startNode = start.deprecatedNode();
360 if (startNode->isTextNode() && start.deprecatedEditingOffset() >= caretMaxOf fset(startNode.raw())) // Move out of text node if range does not include its ch aracters. 360 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); 361 startNode = NodeTraversal::next(startNode);
362 362
363 // Store away font size before making any changes to the document. 363 // Store away font size before making any changes to the document.
364 // This ensures that changes to one node won't effect another. 364 // This ensures that changes to one node won't effect another.
365 CollectionRoot<HashMap<Member<Node>, float> > startingFontSizes; 365 CollectionRoot<HashMap<Member<Node>, float> > startingFontSizes;
366 for (Handle<Node> node = startNode; node != beyondEnd; node = NodeTraversal: :next(node)) { 366 for (Handle<Node> node = startNode; node != beyondEnd; node = NodeTraversal: :next(node)) {
367 HandleScope scope; 367 HandleScope scope;
368 startingFontSizes->set(node, computedFontSize(node)); 368 startingFontSizes->set(node, computedFontSize(node));
369 } 369 }
370 370
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 if (isSpanWithoutAttributesOrUnstyledStyleSpan(node)) 445 if (isSpanWithoutAttributesOrUnstyledStyleSpan(node))
446 removeNodePreservingChildren(node); 446 removeNodePreservingChildren(node);
447 node = next; 447 node = next;
448 } 448 }
449 } 449 }
450 450
451 Result<HTMLElement> ApplyStyleCommand::splitAncestorsWithUnicodeBidi(const Handl e<Node>& node, bool before, WritingDirection allowedDirection) 451 Result<HTMLElement> ApplyStyleCommand::splitAncestorsWithUnicodeBidi(const Handl e<Node>& node, bool before, WritingDirection allowedDirection)
452 { 452 {
453 // We are allowed to leave the highest ancestor with unicode-bidi unsplit if it is unicode-bidi: embed and direction: allowedDirection. 453 // We are allowed to leave the highest ancestor with unicode-bidi unsplit if it is unicode-bidi: embed and direction: allowedDirection.
454 // In that case, we return the unsplit ancestor. Otherwise, we return 0. 454 // In that case, we return the unsplit ancestor. Otherwise, we return 0.
455 Handle<Node> block = enclosingBlock(node.raw()); 455 Handle<Node> block = enclosingBlock(node);
456 if (!block) 456 if (!block)
457 return nullptr; 457 return nullptr;
458 458
459 Handle<Node> highestAncestorWithUnicodeBidi; 459 Handle<Node> highestAncestorWithUnicodeBidi;
460 Handle<Node> nextHighestAncestorWithUnicodeBidi; 460 Handle<Node> nextHighestAncestorWithUnicodeBidi;
461 int highestAncestorUnicodeBidi = 0; 461 int highestAncestorUnicodeBidi = 0;
462 for (Handle<Node> n = node->parentNode(); n != block; n = n->parentNode()) { 462 for (Handle<Node> n = node->parentNode(); n != block; n = n->parentNode()) {
463 HandleScope scope; 463 HandleScope scope;
464 Handle<CSSStyleDeclaration> styleDeclaration = CSSComputedStyleDeclarati on::create(n); 464 Handle<CSSStyleDeclaration> styleDeclaration = CSSComputedStyleDeclarati on::create(n);
465 int unicodeBidi = getIdentifierValue(styleDeclaration, CSSPropertyUnicod eBidi); 465 int unicodeBidi = getIdentifierValue(styleDeclaration, CSSPropertyUnicod eBidi);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 splitElement(parent, before ? currentNode : currentNode->nextSibling ().handle()); 497 splitElement(parent, before ? currentNode : currentNode->nextSibling ().handle());
498 if (parent == highestAncestorWithUnicodeBidi) 498 if (parent == highestAncestorWithUnicodeBidi)
499 break; 499 break;
500 currentNode = parent; 500 currentNode = parent;
501 } 501 }
502 return unsplitAncestor; 502 return unsplitAncestor;
503 } 503 }
504 504
505 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(const Handle<Node>& no de, const Handle<Node>& unsplitAncestor) 505 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(const Handle<Node>& no de, const Handle<Node>& unsplitAncestor)
506 { 506 {
507 Handle<Node> block = enclosingBlock(node.raw()); 507 Handle<Node> block = enclosingBlock(node);
508 if (!block) 508 if (!block)
509 return; 509 return;
510 510
511 Handle<Node> parent; 511 Handle<Node> parent;
512 for (Handle<Node> n = node->parentNode(); n != block && n != unsplitAncestor ; n = parent) { 512 for (Handle<Node> n = node->parentNode(); n != block && n != unsplitAncestor ; n = parent) {
513 HandleScope scope; 513 HandleScope scope;
514 parent = n->parentNode(); 514 parent = n->parentNode();
515 if (!n->isStyledElement()) 515 if (!n->isStyledElement())
516 continue; 516 continue;
517 517
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 } 652 }
653 653
654 // update document layout once before running the rest of the function 654 // update document layout once before running the rest of the function
655 // so that we avoid the expense of updating before each and every call 655 // so that we avoid the expense of updating before each and every call
656 // to check a computed style 656 // to check a computed style
657 document()->updateLayoutIgnorePendingStylesheets(); 657 document()->updateLayoutIgnorePendingStylesheets();
658 658
659 RefPtr<EditingStyle> styleToApply = style; 659 RefPtr<EditingStyle> styleToApply = style;
660 if (hasTextDirection) { 660 if (hasTextDirection) {
661 // Avoid applying the unicode-bidi and direction properties beneath ance stors that already have them. 661 // Avoid applying the unicode-bidi and direction properties beneath ance stors that already have them.
662 Handle<Node> embeddingStartNode = highestEmbeddingAncestor(start.depreca tedNode(), enclosingBlock(start.deprecatedNode().handle().raw())); 662 Handle<Node> embeddingStartNode = highestEmbeddingAncestor(start.depreca tedNode(), enclosingBlock(start.deprecatedNode()));
663 Handle<Node> embeddingEndNode = highestEmbeddingAncestor(end.deprecatedN ode(), enclosingBlock(end.deprecatedNode().handle().raw())); 663 Handle<Node> embeddingEndNode = highestEmbeddingAncestor(end.deprecatedN ode(), enclosingBlock(end.deprecatedNode()));
664 664
665 if (embeddingStartNode || embeddingEndNode) { 665 if (embeddingStartNode || embeddingEndNode) {
666 Position embeddingApplyStart = embeddingStartNode ? positionInParent AfterNode(embeddingStartNode) : start; 666 Position embeddingApplyStart = embeddingStartNode ? positionInParent AfterNode(embeddingStartNode) : start;
667 Position embeddingApplyEnd = embeddingEndNode ? positionInParentBefo reNode(embeddingEndNode) : end; 667 Position embeddingApplyEnd = embeddingEndNode ? positionInParentBefo reNode(embeddingEndNode) : end;
668 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul l()); 668 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul l());
669 669
670 if (!embeddingStyle) { 670 if (!embeddingStyle) {
671 styleWithoutEmbedding = style->copy(); 671 styleWithoutEmbedding = style->copy();
672 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDire ction(); 672 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDire ction();
673 } 673 }
674 fixRangeAndApplyInlineStyle(embeddingStyle.get(), embeddingApplyStar t, embeddingApplyEnd); 674 fixRangeAndApplyInlineStyle(embeddingStyle.get(), embeddingApplyStar t, embeddingApplyEnd);
675 675
676 styleToApply = styleWithoutEmbedding; 676 styleToApply = styleWithoutEmbedding;
677 } 677 }
678 } 678 }
679 679
680 fixRangeAndApplyInlineStyle(styleToApply.get(), start, end); 680 fixRangeAndApplyInlineStyle(styleToApply.get(), start, end);
681 681
682 // Remove dummy style spans created by splitting text elements. 682 // Remove dummy style spans created by splitting text elements.
683 cleanupUnstyledAppleStyleSpans(startDummySpanAncestor); 683 cleanupUnstyledAppleStyleSpans(startDummySpanAncestor);
684 if (endDummySpanAncestor != startDummySpanAncestor) 684 if (endDummySpanAncestor != startDummySpanAncestor)
685 cleanupUnstyledAppleStyleSpans(endDummySpanAncestor); 685 cleanupUnstyledAppleStyleSpans(endDummySpanAncestor);
686 } 686 }
687 687
688 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const P osition& start, const Position& end) 688 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const P osition& start, const Position& end)
689 { 689 {
690 Handle<Node> startNode = start.deprecatedNode(); 690 Handle<Node> startNode = start.deprecatedNode();
691 691
692 if (start.deprecatedEditingOffset() >= caretMaxOffset(start.deprecatedNode() .handle().raw())) { 692 if (start.deprecatedEditingOffset() >= caretMaxOffset(start.deprecatedNode() )) {
693 startNode = NodeTraversal::next(startNode); 693 startNode = NodeTraversal::next(startNode);
694 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star tNode.raw())) < 0) 694 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star tNode)) < 0)
695 return; 695 return;
696 } 696 }
697 697
698 Handle<Node> pastEndNode = end.deprecatedNode(); 698 Handle<Node> pastEndNode = end.deprecatedNode();
699 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode().han dle().raw())) 699 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode()))
700 pastEndNode = NodeTraversal::nextSkippingChildren(end.deprecatedNode()); 700 pastEndNode = NodeTraversal::nextSkippingChildren(end.deprecatedNode());
701 701
702 // FIXME: Callers should perform this operation on a Range that includes the br 702 // FIXME: Callers should perform this operation on a Range that includes the br
703 // if they want style applied to the empty line. 703 // if they want style applied to the empty line.
704 if (start == end && start.deprecatedNode()->hasTagName(brTag)) 704 if (start == end && start.deprecatedNode()->hasTagName(brTag))
705 pastEndNode = NodeTraversal::next(start.deprecatedNode()); 705 pastEndNode = NodeTraversal::next(start.deprecatedNode());
706 706
707 // Start from the highest fully selected ancestor so that we can modify the fully selected node. 707 // Start from the highest fully selected ancestor so that we can modify the fully selected node.
708 // e.g. When applying font-size: large on <font color="blue">hello</font>, w e need to include the font element in our run 708 // e.g. When applying font-size: large on <font color="blue">hello</font>, w e need to include the font element in our run
709 // to generate <font color="blue" size="4">hello</font> instead of <font col or="blue"><font size="4">hello</font></font> 709 // to generate <font color="blue" size="4">hello</font> instead of <font col or="blue"><font size="4">hello</font></font>
710 Handle<Range> range = Range::create(startNode->document(), start, end); 710 Handle<Range> range = Range::create(startNode->document(), start, end);
711 Handle<Element> editableRoot = startNode->rootEditableElement(); 711 Handle<Element> editableRoot = startNode->rootEditableElement();
712 if (startNode != editableRoot) { 712 if (startNode != editableRoot) {
713 while (1) { 713 while (1) {
714 HandleScope scope; 714 HandleScope scope;
715 if (!editableRoot || startNode->parentNode() == editableRoot || !isN odeVisiblyContainedWithin(startNode->parentNode().handle().raw(), range)) 715 if (!editableRoot || startNode->parentNode() == editableRoot || !isN odeVisiblyContainedWithin(startNode->parentNode(), range))
716 break; 716 break;
717 startNode = startNode->parentNode(); 717 startNode = startNode->parentNode();
718 } 718 }
719 } 719 }
720 720
721 applyInlineStyleToNodeRange(style, startNode, pastEndNode); 721 applyInlineStyleToNodeRange(style, startNode, pastEndNode);
722 } 722 }
723 723
724 static bool containsNonEditableRegion(const Handle<Node>& node) 724 static bool containsNonEditableRegion(const Handle<Node>& node)
725 { 725 {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 break; 782 break;
783 // Add to this element's inline style and skip over its contents. 783 // Add to this element's inline style and skip over its contents.
784 Handle<HTMLElement> element = toHTMLElement(node); 784 Handle<HTMLElement> element = toHTMLElement(node);
785 Handle<StylePropertySet> inlineStyle = copyStyleOrCreateEmpty(elemen t->inlineStyle()); 785 Handle<StylePropertySet> inlineStyle = copyStyleOrCreateEmpty(elemen t->inlineStyle());
786 inlineStyle->mergeAndOverrideOnConflict(style->style()); 786 inlineStyle->mergeAndOverrideOnConflict(style->style());
787 setNodeAttribute(element, styleAttr, inlineStyle->asText()); 787 setNodeAttribute(element, styleAttr, inlineStyle->asText());
788 next = NodeTraversal::nextSkippingChildren(node); 788 next = NodeTraversal::nextSkippingChildren(node);
789 continue; 789 continue;
790 } 790 }
791 791
792 if (isBlock(node.raw())) 792 if (isBlock(node))
793 continue; 793 continue;
794 794
795 if (node->childNodeCount()) { 795 if (node->childNodeCount()) {
796 if (node->contains(pastEndNode) || containsNonEditableRegion(node) | | !node->parentNode()->rendererIsEditable()) 796 if (node->contains(pastEndNode) || containsNonEditableRegion(node) | | !node->parentNode()->rendererIsEditable())
797 continue; 797 continue;
798 if (editingIgnoresContent(node.raw())) { 798 if (editingIgnoresContent(node)) {
799 next = NodeTraversal::nextSkippingChildren(node); 799 next = NodeTraversal::nextSkippingChildren(node);
800 continue; 800 continue;
801 } 801 }
802 } 802 }
803 803
804 Handle<Node> runStart = node; 804 Handle<Node> runStart = node;
805 Handle<Node> runEnd = node; 805 Handle<Node> runEnd = node;
806 Handle<Node> sibling = node->nextSibling(); 806 Handle<Node> sibling = node->nextSibling();
807 while (1) { 807 while (1) {
808 HandleScope scope; 808 HandleScope scope;
809 if (!sibling || sibling == pastEndNode || sibling->contains(pastEndN ode) 809 if (!sibling || sibling == pastEndNode || sibling->contains(pastEndN ode)
810 || (isBlock(sibling.raw()) && !sibling->hasTagName(brTag)) 810 || (isBlock(sibling) && !sibling->hasTagName(brTag))
811 || containsNonEditableRegion(sibling)) 811 || containsNonEditableRegion(sibling))
812 break; 812 break;
813 runEnd = sibling; 813 runEnd = sibling;
814 sibling = runEnd->nextSibling(); 814 sibling = runEnd->nextSibling();
815 } 815 }
816 next = NodeTraversal::nextSkippingChildren(runEnd); 816 next = NodeTraversal::nextSkippingChildren(runEnd);
817 817
818 Handle<Node> pastEndNode = NodeTraversal::nextSkippingChildren(runEnd); 818 Handle<Node> pastEndNode = NodeTraversal::nextSkippingChildren(runEnd);
819 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) 819 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode))
820 continue; 820 continue;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 } 867 }
868 return false; 868 return false;
869 } 869 }
870 870
871 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, Persistent<Node>& runStart, Persistent<Node>& runEnd, const Handle<Node>& pastE ndNode) 871 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, Persistent<Node>& runStart, Persistent<Node>& runEnd, const Handle<Node>& pastE ndNode)
872 { 872 {
873 ASSERT(runStart && runEnd); 873 ASSERT(runStart && runEnd);
874 Handle<Node> next = runStart; 874 Handle<Node> next = runStart;
875 for (Handle<Node> node = next; node && node->inDocument() && node != pastEnd Node; node = next) { 875 for (Handle<Node> node = next; node && node->inDocument() && node != pastEnd Node; node = next) {
876 HandleScope scope; 876 HandleScope scope;
877 if (editingIgnoresContent(node.raw())) { 877 if (editingIgnoresContent(node)) {
878 ASSERT(!node->contains(pastEndNode)); 878 ASSERT(!node->contains(pastEndNode));
879 next = NodeTraversal::nextSkippingChildren(node); 879 next = NodeTraversal::nextSkippingChildren(node);
880 } else 880 } else
881 next = NodeTraversal::next(node); 881 next = NodeTraversal::next(node);
882 if (!node->isHTMLElement()) 882 if (!node->isHTMLElement())
883 continue; 883 continue;
884 884
885 Handle<Node> previousSibling = node->previousSibling(); 885 Handle<Node> previousSibling = node->previousSibling();
886 Handle<Node> nextSibling = node->nextSibling(); 886 Handle<Node> nextSibling = node->nextSibling();
887 Handle<ContainerNode> parent = node->parentNode(); 887 Handle<ContainerNode> parent = node->parentNode();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 991
992 return true; 992 return true;
993 } 993 }
994 994
995 Result<HTMLElement> ApplyStyleCommand::highestAncestorWithConflictingInlineStyle (EditingStyle* style, const Handle<Node>& node) 995 Result<HTMLElement> ApplyStyleCommand::highestAncestorWithConflictingInlineStyle (EditingStyle* style, const Handle<Node>& node)
996 { 996 {
997 if (!node) 997 if (!node)
998 return nullptr; 998 return nullptr;
999 999
1000 Handle<HTMLElement> result; 1000 Handle<HTMLElement> result;
1001 Handle<Node> unsplittableElement = unsplittableElementForPosition(firstPosit ionInOrBeforeNode(node.raw())); 1001 Handle<Node> unsplittableElement = unsplittableElementForPosition(firstPosit ionInOrBeforeNode(node));
1002 1002
1003 for (Handle<Node> n = node; n; n = n->parentNode()) { 1003 for (Handle<Node> n = node; n; n = n->parentNode()) {
1004 HandleScope scope; 1004 HandleScope scope;
1005 if (n->isHTMLElement() && shouldRemoveInlineStyleFromElement(style, toHT MLElement(n))) 1005 if (n->isHTMLElement() && shouldRemoveInlineStyleFromElement(style, toHT MLElement(n)))
1006 result = toHTMLElement(n); 1006 result = toHTMLElement(n);
1007 // Should stop at the editable root (cannot cross editing boundary) and 1007 // Should stop at the editable root (cannot cross editing boundary) and
1008 // also stop at the unsplittable element to be consistent with other UAs 1008 // also stop at the unsplittable element to be consistent with other UAs
1009 if (n == unsplittableElement) 1009 if (n == unsplittableElement)
1010 break; 1010 break;
1011 } 1011 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 // are removed from the document during the work of this function. 1129 // are removed from the document during the work of this function.
1130 // If pushDownInlineStyleAroundNode has pruned start.deprecatedNode() or end .deprecatedNode(), 1130 // If pushDownInlineStyleAroundNode has pruned start.deprecatedNode() or end .deprecatedNode(),
1131 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround Node won't prune. 1131 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround Node won't prune.
1132 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; 1132 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start;
1133 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; 1133 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end;
1134 1134
1135 Handle<Node> node = start.deprecatedNode(); 1135 Handle<Node> node = start.deprecatedNode();
1136 while (node) { 1136 while (node) {
1137 HandleScope scope; 1137 HandleScope scope;
1138 Handle<Node> next; 1138 Handle<Node> next;
1139 if (editingIgnoresContent(node.raw())) { 1139 if (editingIgnoresContent(node)) {
1140 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate dNode())); 1140 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate dNode()));
1141 next = NodeTraversal::nextSkippingChildren(node); 1141 next = NodeTraversal::nextSkippingChildren(node);
1142 } else 1142 } else
1143 next = NodeTraversal::next(node); 1143 next = NodeTraversal::next(node);
1144 if (node->isHTMLElement() && nodeFullySelected(node, start, end)) { 1144 if (node->isHTMLElement() && nodeFullySelected(node, start, end)) {
1145 Handle<HTMLElement> elem = toHTMLElement(node); 1145 Handle<HTMLElement> elem = toHTMLElement(node);
1146 Handle<Node> prevNode = NodeTraversal::previousPostOrder(elem); 1146 Handle<Node> prevNode = NodeTraversal::previousPostOrder(elem);
1147 Handle<Node> nextNode = NodeTraversal::next(elem); 1147 Handle<Node> nextNode = NodeTraversal::next(elem);
1148 RefPtr<EditingStyle> styleToPushDown; 1148 RefPtr<EditingStyle> styleToPushDown;
1149 Handle<Node> childNode; 1149 Handle<Node> childNode;
1150 if (isStyledInlineElementToRemove(elem)) { 1150 if (isStyledInlineElementToRemove(elem)) {
1151 styleToPushDown = EditingStyle::create(); 1151 styleToPushDown = EditingStyle::create();
1152 childNode = elem->firstChild(); 1152 childNode = elem->firstChild();
1153 } 1153 }
1154 1154
1155 removeInlineStyleFromElement(style, elem, RemoveIfNeeded, styleToPus hDown.get()); 1155 removeInlineStyleFromElement(style, elem, RemoveIfNeeded, styleToPus hDown.get());
1156 if (!elem->inDocument()) { 1156 if (!elem->inDocument()) {
1157 if (s.deprecatedNode() == elem) { 1157 if (s.deprecatedNode() == elem) {
1158 // Since elem must have been fully selected, and it is at th e start 1158 // Since elem must have been fully selected, and it is at th e start
1159 // of the selection, it is clear we can set the new s offset to 0. 1159 // of the selection, it is clear we can set the new s offset to 0.
1160 ASSERT(s.anchorType() == Position::PositionIsBeforeAnchor || s.offsetInContainerNode() <= 0); 1160 ASSERT(s.anchorType() == Position::PositionIsBeforeAnchor || s.offsetInContainerNode() <= 0);
1161 s = firstPositionInOrBeforeNode(nextNode.raw()); 1161 s = firstPositionInOrBeforeNode(nextNode);
1162 } 1162 }
1163 if (e.deprecatedNode() == elem) { 1163 if (e.deprecatedNode() == elem) {
1164 // Since elem must have been fully selected, and it is at th e end 1164 // Since elem must have been fully selected, and it is at th e end
1165 // of the selection, it is clear we can set the new e offset to 1165 // of the selection, it is clear we can set the new e offset to
1166 // the max range offset of prevNode. 1166 // the max range offset of prevNode.
1167 ASSERT(s.anchorType() == Position::PositionIsAfterAnchor || !offsetIsBeforeLastNodeOffset(s.offsetInContainerNode(), s.containerNode())); 1167 ASSERT(s.anchorType() == Position::PositionIsAfterAnchor || !offsetIsBeforeLastNodeOffset(s.offsetInContainerNode(), s.containerNode()));
1168 e = lastPositionInOrAfterNode(prevNode.raw()); 1168 e = lastPositionInOrAfterNode(prevNode);
1169 } 1169 }
1170 } 1170 }
1171 1171
1172 if (styleToPushDown) { 1172 if (styleToPushDown) {
1173 for (; childNode; childNode = childNode->nextSibling()) 1173 for (; childNode; childNode = childNode->nextSibling())
1174 applyInlineStyleToPushDown(childNode, styleToPushDown.get()) ; 1174 applyInlineStyleToPushDown(childNode, styleToPushDown.get()) ;
1175 } 1175 }
1176 } 1176 }
1177 if (node == end.deprecatedNode()) 1177 if (node == end.deprecatedNode())
1178 break; 1178 break;
1179 node = next; 1179 node = next;
1180 } 1180 }
1181 1181
1182 updateStartEnd(s, e); 1182 updateStartEnd(s, e);
1183 } 1183 }
1184 1184
1185 bool ApplyStyleCommand::nodeFullySelected(const Handle<Node>& node, const Positi on &start, const Position &end) const 1185 bool ApplyStyleCommand::nodeFullySelected(const Handle<Node>& node, const Positi on &start, const Position &end) const
1186 { 1186 {
1187 ASSERT(node); 1187 ASSERT(node);
1188 ASSERT(node->isElementNode()); 1188 ASSERT(node->isElementNode());
1189 1189
1190 // The tree may have changed and Position::upstream() relies on an up-to-dat e layout. 1190 // The tree may have changed and Position::upstream() relies on an up-to-dat e layout.
1191 node->document()->updateLayoutIgnorePendingStylesheets(); 1191 node->document()->updateLayoutIgnorePendingStylesheets();
1192 1192
1193 return comparePositions(firstPositionInOrBeforeNode(node.raw()), start) >= 0 1193 return comparePositions(firstPositionInOrBeforeNode(node), start) >= 0
1194 && comparePositions(lastPositionInOrAfterNode(node.raw()).upstream(), en d) <= 0; 1194 && comparePositions(lastPositionInOrAfterNode(node).upstream(), end) <= 0;
1195 } 1195 }
1196 1196
1197 bool ApplyStyleCommand::nodeFullyUnselected(const Handle<Node>& node, const Posi tion &start, const Position &end) const 1197 bool ApplyStyleCommand::nodeFullyUnselected(const Handle<Node>& node, const Posi tion &start, const Position &end) const
1198 { 1198 {
1199 ASSERT(node); 1199 ASSERT(node);
1200 ASSERT(node->isElementNode()); 1200 ASSERT(node->isElementNode());
1201 1201
1202 bool isFullyBeforeStart = comparePositions(lastPositionInOrAfterNode(node.ra w()).upstream(), start) < 0; 1202 bool isFullyBeforeStart = comparePositions(lastPositionInOrAfterNode(node).u pstream(), start) < 0;
1203 bool isFullyAfterEnd = comparePositions(firstPositionInOrBeforeNode(node.raw ()), end) > 0; 1203 bool isFullyAfterEnd = comparePositions(firstPositionInOrBeforeNode(node), e nd) > 0;
1204 1204
1205 return isFullyBeforeStart || isFullyAfterEnd; 1205 return isFullyBeforeStart || isFullyAfterEnd;
1206 } 1206 }
1207 1207
1208 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position& end) 1208 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position& end)
1209 { 1209 {
1210 ASSERT(start.containerNode()->isTextNode()); 1210 ASSERT(start.containerNode()->isTextNode());
1211 1211
1212 Position newEnd; 1212 Position newEnd;
1213 if (end.anchorType() == Position::PositionIsOffsetInAnchor && start.containe rNode() == end.containerNode()) 1213 if (end.anchorType() == Position::PositionIsOffsetInAnchor && start.containe rNode() == end.containerNode())
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1271 bool ApplyStyleCommand::shouldSplitTextElement(const Handle<Element>& element, E ditingStyle* style) 1271 bool ApplyStyleCommand::shouldSplitTextElement(const Handle<Element>& element, E ditingStyle* style)
1272 { 1272 {
1273 if (!element || !element->isHTMLElement()) 1273 if (!element || !element->isHTMLElement())
1274 return false; 1274 return false;
1275 1275
1276 return shouldRemoveInlineStyleFromElement(style, toHTMLElement(element)); 1276 return shouldRemoveInlineStyleFromElement(style, toHTMLElement(element));
1277 } 1277 }
1278 1278
1279 bool ApplyStyleCommand::isValidCaretPositionInTextNode(const Position& position) 1279 bool ApplyStyleCommand::isValidCaretPositionInTextNode(const Position& position)
1280 { 1280 {
1281 Node* node = position.containerNode().handle().raw(); 1281 Handle<Node> node = position.containerNode();
1282 if (position.anchorType() != Position::PositionIsOffsetInAnchor || !node->is TextNode()) 1282 if (position.anchorType() != Position::PositionIsOffsetInAnchor || !node->is TextNode())
1283 return false; 1283 return false;
1284 int offsetInText = position.offsetInContainerNode(); 1284 int offsetInText = position.offsetInContainerNode();
1285 return offsetInText > caretMinOffset(node) && offsetInText < caretMaxOffset( node); 1285 return offsetInText > caretMinOffset(node) && offsetInText < caretMaxOffset( node);
1286 } 1286 }
1287 1287
1288 bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end) 1288 bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end)
1289 { 1289 {
1290 Node* startNode = start.containerNode().handle().raw(); 1290 Handle<Node> startNode = start.containerNode();
1291 int startOffset = start.computeOffsetInContainerNode(); 1291 int startOffset = start.computeOffsetInContainerNode();
1292 if (startOffset) 1292 if (startOffset)
1293 return false; 1293 return false;
1294 1294
1295 if (isAtomicNode(startNode)) { 1295 if (isAtomicNode(startNode)) {
1296 // note: prior siblings could be unrendered elements. it's silly to miss the 1296 // note: prior siblings could be unrendered elements. it's silly to miss the
1297 // merge opportunity just for that. 1297 // merge opportunity just for that.
1298 if (startNode->previousSibling()) 1298 if (startNode->previousSibling())
1299 return false; 1299 return false;
1300 1300
1301 startNode = startNode->parentNode().handle().raw(); 1301 startNode = startNode->parentNode();
1302 startOffset = 0; 1302 startOffset = 0;
1303 } 1303 }
1304 1304
1305 if (!startNode->isElementNode()) 1305 if (!startNode->isElementNode())
1306 return false; 1306 return false;
1307 1307
1308 Handle<Node> previousSibling = startNode->previousSibling(); 1308 Handle<Node> previousSibling = startNode->previousSibling();
1309 1309
1310 if (previousSibling && areIdenticalElements(startNode, previousSibling.raw() )) { 1310 if (previousSibling && areIdenticalElements(startNode, previousSibling)) {
1311 Handle<Element> previousElement = toElement(previousSibling); 1311 Handle<Element> previousElement = toElement(previousSibling);
1312 Handle<Element> element = adoptRawResult(toElement(startNode)); 1312 Handle<Element> element = toElement(startNode);
1313 Handle<Node> startChild = element->firstChild(); 1313 Handle<Node> startChild = element->firstChild();
1314 ASSERT(startChild); 1314 ASSERT(startChild);
1315 mergeIdenticalElements(previousElement, element); 1315 mergeIdenticalElements(previousElement, element);
1316 1316
1317 int startOffsetAdjustment = startChild->nodeIndex(); 1317 int startOffsetAdjustment = startChild->nodeIndex();
1318 int endOffsetAdjustment = startNode == end.deprecatedNode() ? startOffse tAdjustment : 0; 1318 int endOffsetAdjustment = startNode == end.deprecatedNode() ? startOffse tAdjustment : 0;
1319 updateStartEnd(Position(adoptRawResult(startNode), startOffsetAdjustment , Position::PositionIsOffsetInAnchor), 1319 updateStartEnd(Position(startNode, startOffsetAdjustment, Position::Posi tionIsOffsetInAnchor),
1320 Position(end.deprecatedNode(), end.deprecatedEditingOffse t() + endOffsetAdjustment, Position::PositionIsOffsetInAnchor)); 1320 Position(end.deprecatedNode(), end.deprecatedEditingOffse t() + endOffsetAdjustment, Position::PositionIsOffsetInAnchor));
1321 return true; 1321 return true;
1322 } 1322 }
1323 1323
1324 return false; 1324 return false;
1325 } 1325 }
1326 1326
1327 bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const Position& end) 1327 bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const Position& end)
1328 { 1328 {
1329 Handle<Node> endNode = end.containerNode(); 1329 Handle<Node> endNode = end.containerNode();
1330 int endOffset = end.computeOffsetInContainerNode(); 1330 int endOffset = end.computeOffsetInContainerNode();
1331 1331
1332 if (isAtomicNode(endNode.raw())) { 1332 if (isAtomicNode(endNode)) {
1333 if (offsetIsBeforeLastNodeOffset(endOffset, endNode)) 1333 if (offsetIsBeforeLastNodeOffset(endOffset, endNode))
1334 return false; 1334 return false;
1335 1335
1336 unsigned parentLastOffset = end.deprecatedNode()->parentNode()->childNod es()->length() - 1; 1336 unsigned parentLastOffset = end.deprecatedNode()->parentNode()->childNod es()->length() - 1;
1337 if (end.deprecatedNode()->nextSibling()) 1337 if (end.deprecatedNode()->nextSibling())
1338 return false; 1338 return false;
1339 1339
1340 endNode = end.deprecatedNode()->parentNode(); 1340 endNode = end.deprecatedNode()->parentNode();
1341 endOffset = parentLastOffset; 1341 endOffset = parentLastOffset;
1342 } 1342 }
1343 1343
1344 if (!endNode->isElementNode() || endNode->hasTagName(brTag)) 1344 if (!endNode->isElementNode() || endNode->hasTagName(brTag))
1345 return false; 1345 return false;
1346 1346
1347 Handle<Node> nextSibling = endNode->nextSibling(); 1347 Handle<Node> nextSibling = endNode->nextSibling();
1348 if (nextSibling && areIdenticalElements(endNode.raw(), nextSibling.raw())) { 1348 if (nextSibling && areIdenticalElements(endNode, nextSibling)) {
1349 Handle<Element> nextElement = toElement(nextSibling); 1349 Handle<Element> nextElement = toElement(nextSibling);
1350 Handle<Element> element = adoptRawResult(toElement(endNode.raw())); 1350 Handle<Element> element = toElement(endNode);
1351 Handle<Node> nextChild = nextElement->firstChild(); 1351 Handle<Node> nextChild = nextElement->firstChild();
1352 1352
1353 mergeIdenticalElements(element, nextElement); 1353 mergeIdenticalElements(element, nextElement);
1354 1354
1355 bool shouldUpdateStart = start.containerNode() == endNode; 1355 bool shouldUpdateStart = start.containerNode() == endNode;
1356 int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childN odes()->length(); 1356 int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childN odes()->length();
1357 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC ontainerNode(), Position::PositionIsOffsetInAnchor) : start, 1357 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC ontainerNode(), Position::PositionIsOffsetInAnchor) : start,
1358 Position(nextElement, endOffset, Position::PositionIsOffsetInAnchor) ); 1358 Position(nextElement, endOffset, Position::PositionIsOffsetInAnchor) );
1359 return true; 1359 return true;
1360 } 1360 }
(...skipping 19 matching lines...) Expand all
1380 appendNode(node, element); 1380 appendNode(node, element);
1381 } 1381 }
1382 if (node.raw() == endNode) 1382 if (node.raw() == endNode)
1383 break; 1383 break;
1384 node = next; 1384 node = next;
1385 } 1385 }
1386 1386
1387 Handle<Node> nextSibling = element->nextSibling(); 1387 Handle<Node> nextSibling = element->nextSibling();
1388 Handle<Node> previousSibling = element->previousSibling(); 1388 Handle<Node> previousSibling = element->previousSibling();
1389 if (nextSibling && nextSibling->isElementNode() && nextSibling->rendererIsEd itable() 1389 if (nextSibling && nextSibling->isElementNode() && nextSibling->rendererIsEd itable()
1390 && areIdenticalElements(element.raw(), toElement(nextSibling).handle().r aw())) 1390 && areIdenticalElements(element, toElement(nextSibling)))
1391 mergeIdenticalElements(element, toElement(nextSibling)); 1391 mergeIdenticalElements(element, toElement(nextSibling));
1392 1392
1393 if (previousSibling && previousSibling->isElementNode() && previousSibling-> rendererIsEditable()) { 1393 if (previousSibling && previousSibling->isElementNode() && previousSibling-> rendererIsEditable()) {
1394 Handle<Node> mergedElement = previousSibling->nextSibling(); 1394 Handle<Node> mergedElement = previousSibling->nextSibling();
1395 if (mergedElement->isElementNode() && mergedElement->rendererIsEditable( ) 1395 if (mergedElement->isElementNode() && mergedElement->rendererIsEditable( )
1396 && areIdenticalElements(toElement(previousSibling).handle().raw(), t oElement(mergedElement).handle().raw())) 1396 && areIdenticalElements(toElement(previousSibling), toElement(merged Element)))
1397 mergeIdenticalElements(toElement(previousSibling), toElement(mergedE lement)); 1397 mergeIdenticalElements(toElement(previousSibling), toElement(mergedE lement));
1398 } 1398 }
1399 1399
1400 // FIXME: We should probably call updateStartEnd if the start or end was in the node 1400 // FIXME: We should probably call updateStartEnd if the start or end was in the node
1401 // range so that the endingSelection() is canonicalized. See the comments a t the end of 1401 // range so that the endingSelection() is canonicalized. See the comments a t the end of
1402 // VisibleSelection::validate(). 1402 // VisibleSelection::validate().
1403 } 1403 }
1404 1404
1405 void ApplyStyleCommand::addBlockStyle(const StyleChange& styleChange, const Hand le<HTMLElement>& block) 1405 void ApplyStyleCommand::addBlockStyle(const StyleChange& styleChange, const Hand le<HTMLElement>& block)
1406 { 1406 {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 Position ApplyStyleCommand::positionToComputeInlineStyleChange(const Handle<Node >& startNode, Persistent<Node>& dummyElement) 1438 Position ApplyStyleCommand::positionToComputeInlineStyleChange(const Handle<Node >& startNode, Persistent<Node>& dummyElement)
1439 { 1439 {
1440 // It's okay to obtain the style at the startNode because we've removed all relevant styles from the current run. 1440 // It's okay to obtain the style at the startNode because we've removed all relevant styles from the current run.
1441 Position positionForStyleComparison; 1441 Position positionForStyleComparison;
1442 if (!startNode->isElementNode()) { 1442 if (!startNode->isElementNode()) {
1443 dummyElement = createStyleSpanElement(document()); 1443 dummyElement = createStyleSpanElement(document());
1444 insertNodeAt(dummyElement, positionBeforeNode(startNode)); 1444 insertNodeAt(dummyElement, positionBeforeNode(startNode));
1445 return positionBeforeNode(dummyElement); 1445 return positionBeforeNode(dummyElement);
1446 } 1446 }
1447 1447
1448 return firstPositionInOrBeforeNode(startNode.raw()); 1448 return firstPositionInOrBeforeNode(startNode);
1449 } 1449 }
1450 1450
1451 void ApplyStyleCommand::applyInlineStyleChange(const Handle<Node>& passedStart, const Handle<Node>& passedEnd, StyleChange& styleChange, EAddStyledElement addSt yledElement) 1451 void ApplyStyleCommand::applyInlineStyleChange(const Handle<Node>& passedStart, const Handle<Node>& passedEnd, StyleChange& styleChange, EAddStyledElement addSt yledElement)
1452 { 1452 {
1453 Handle<Node> startNode = passedStart; 1453 Handle<Node> startNode = passedStart;
1454 Handle<Node> endNode = passedEnd; 1454 Handle<Node> endNode = passedEnd;
1455 ASSERT(startNode->inDocument()); 1455 ASSERT(startNode->inDocument());
1456 ASSERT(endNode->inDocument()); 1456 ASSERT(endNode->inDocument());
1457 1457
1458 // Find appropriate font and span elements top-down. 1458 // Find appropriate font and span elements top-down.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1579 String textToMove = nextText->data(); 1579 String textToMove = nextText->data();
1580 insertTextIntoNode(childText, childText->length(), textToMove); 1580 insertTextIntoNode(childText, childText->length(), textToMove);
1581 removeNode(next); 1581 removeNode(next);
1582 // don't move child node pointer. it may want to merge with more text no des. 1582 // don't move child node pointer. it may want to merge with more text no des.
1583 } 1583 }
1584 1584
1585 updateStartEnd(newStart, newEnd); 1585 updateStartEnd(newStart, newEnd);
1586 } 1586 }
1587 1587
1588 } 1588 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698