| 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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 , m_propertyLevel(PropertyDefault) | 133 , m_propertyLevel(PropertyDefault) |
| 134 , m_start(start) | 134 , m_start(start) |
| 135 , m_end(end) | 135 , m_end(end) |
| 136 , m_useEndingSelection(false) | 136 , m_useEndingSelection(false) |
| 137 , m_styledInlineElement(nullptr) | 137 , m_styledInlineElement(nullptr) |
| 138 , m_removeOnly(false) | 138 , m_removeOnly(false) |
| 139 , m_isInlineElementToRemoveFunction(0) | 139 , m_isInlineElementToRemoveFunction(0) |
| 140 { | 140 { |
| 141 } | 141 } |
| 142 | 142 |
| 143 ApplyStyleCommand::ApplyStyleCommand(PassRefPtrWillBeRawPtr<Element> element, bo
ol removeOnly) | 143 ApplyStyleCommand::ApplyStyleCommand(RawPtr<Element> element, bool removeOnly) |
| 144 : CompositeEditCommand(element->document()) | 144 : CompositeEditCommand(element->document()) |
| 145 , m_style(EditingStyle::create()) | 145 , m_style(EditingStyle::create()) |
| 146 , m_editingAction(EditActionChangeAttributes) | 146 , m_editingAction(EditActionChangeAttributes) |
| 147 , m_propertyLevel(PropertyDefault) | 147 , m_propertyLevel(PropertyDefault) |
| 148 , m_start(mostForwardCaretPosition(endingSelection().start())) | 148 , m_start(mostForwardCaretPosition(endingSelection().start())) |
| 149 , m_end(mostBackwardCaretPosition(endingSelection().end())) | 149 , m_end(mostBackwardCaretPosition(endingSelection().end())) |
| 150 , m_useEndingSelection(true) | 150 , m_useEndingSelection(true) |
| 151 , m_styledInlineElement(element) | 151 , m_styledInlineElement(element) |
| 152 , m_removeOnly(removeOnly) | 152 , m_removeOnly(removeOnly) |
| 153 , m_isInlineElementToRemoveFunction(0) | 153 , m_isInlineElementToRemoveFunction(0) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 return endingSelection().end(); | 194 return endingSelection().end(); |
| 195 | 195 |
| 196 return m_end; | 196 return m_end; |
| 197 } | 197 } |
| 198 | 198 |
| 199 void ApplyStyleCommand::doApply(EditingState* editingState) | 199 void ApplyStyleCommand::doApply(EditingState* editingState) |
| 200 { | 200 { |
| 201 switch (m_propertyLevel) { | 201 switch (m_propertyLevel) { |
| 202 case PropertyDefault: { | 202 case PropertyDefault: { |
| 203 // Apply the block-centric properties of the style. | 203 // Apply the block-centric properties of the style. |
| 204 RefPtrWillBeRawPtr<EditingStyle> blockStyle = m_style->extractAndRemoveB
lockProperties(); | 204 RawPtr<EditingStyle> blockStyle = m_style->extractAndRemoveBlockProperti
es(); |
| 205 if (!blockStyle->isEmpty()) { | 205 if (!blockStyle->isEmpty()) { |
| 206 applyBlockStyle(blockStyle.get(), editingState); | 206 applyBlockStyle(blockStyle.get(), editingState); |
| 207 if (editingState->isAborted()) | 207 if (editingState->isAborted()) |
| 208 return; | 208 return; |
| 209 } | 209 } |
| 210 // Apply any remaining styles to the inline elements. | 210 // Apply any remaining styles to the inline elements. |
| 211 if (!m_style->isEmpty() || m_styledInlineElement || m_isInlineElementToR
emoveFunction) { | 211 if (!m_style->isEmpty() || m_styledInlineElement || m_isInlineElementToR
emoveFunction) { |
| 212 applyRelativeFontStyleChange(m_style.get(), editingState); | 212 applyRelativeFontStyleChange(m_style.get(), editingState); |
| 213 if (editingState->isAborted()) | 213 if (editingState->isAborted()) |
| 214 return; | 214 return; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 VisiblePosition visibleStart = createVisiblePosition(start); | 249 VisiblePosition visibleStart = createVisiblePosition(start); |
| 250 VisiblePosition visibleEnd = createVisiblePosition(end); | 250 VisiblePosition visibleEnd = createVisiblePosition(end); |
| 251 | 251 |
| 252 if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull()
|| visibleEnd.isOrphan()) | 252 if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull()
|| visibleEnd.isOrphan()) |
| 253 return; | 253 return; |
| 254 | 254 |
| 255 // Save and restore the selection endpoints using their indices in the docum
ent, since | 255 // Save and restore the selection endpoints using their indices in the docum
ent, since |
| 256 // addBlockStyleIfNeeded may moveParagraphs, which can remove these endpoint
s. | 256 // addBlockStyleIfNeeded may moveParagraphs, which can remove these endpoint
s. |
| 257 // Calculate start and end indices from the start of the tree that they're i
n. | 257 // Calculate start and end indices from the start of the tree that they're i
n. |
| 258 Node& scope = NodeTraversal::highestAncestorOrSelf(*visibleStart.deepEquival
ent().anchorNode()); | 258 Node& scope = NodeTraversal::highestAncestorOrSelf(*visibleStart.deepEquival
ent().anchorNode()); |
| 259 RefPtrWillBeRawPtr<Range> startRange = Range::create(document(), firstPositi
onInNode(&scope), visibleStart.deepEquivalent().parentAnchoredEquivalent()); | 259 RawPtr<Range> startRange = Range::create(document(), firstPositionInNode(&sc
ope), visibleStart.deepEquivalent().parentAnchoredEquivalent()); |
| 260 RefPtrWillBeRawPtr<Range> endRange = Range::create(document(), firstPosition
InNode(&scope), visibleEnd.deepEquivalent().parentAnchoredEquivalent()); | 260 RawPtr<Range> endRange = Range::create(document(), firstPositionInNode(&scop
e), visibleEnd.deepEquivalent().parentAnchoredEquivalent()); |
| 261 int startIndex = TextIterator::rangeLength(startRange->startPosition(), star
tRange->endPosition(), true); | 261 int startIndex = TextIterator::rangeLength(startRange->startPosition(), star
tRange->endPosition(), true); |
| 262 int endIndex = TextIterator::rangeLength(endRange->startPosition(), endRange
->endPosition(), true); | 262 int endIndex = TextIterator::rangeLength(endRange->startPosition(), endRange
->endPosition(), true); |
| 263 | 263 |
| 264 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); | 264 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); |
| 265 VisiblePosition nextParagraphStart(nextPositionOf(endOfParagraph(paragraphSt
art))); | 265 VisiblePosition nextParagraphStart(nextPositionOf(endOfParagraph(paragraphSt
art))); |
| 266 VisiblePosition beyondEnd(nextPositionOf(endOfParagraph(visibleEnd))); | 266 VisiblePosition beyondEnd(nextPositionOf(endOfParagraph(visibleEnd))); |
| 267 while (paragraphStart.isNotNull() && paragraphStart.deepEquivalent() != beyo
ndEnd.deepEquivalent()) { | 267 while (paragraphStart.isNotNull() && paragraphStart.deepEquivalent() != beyo
ndEnd.deepEquivalent()) { |
| 268 StyleChange styleChange(style, paragraphStart.deepEquivalent()); | 268 StyleChange styleChange(style, paragraphStart.deepEquivalent()); |
| 269 if (styleChange.cssStyle().length() || m_removeOnly) { | 269 if (styleChange.cssStyle().length() || m_removeOnly) { |
| 270 RefPtrWillBeRawPtr<Element> block = enclosingBlock(paragraphStart.de
epEquivalent().anchorNode()); | 270 RawPtr<Element> block = enclosingBlock(paragraphStart.deepEquivalent
().anchorNode()); |
| 271 const Position& paragraphStartToMove = paragraphStart.deepEquivalent
(); | 271 const Position& paragraphStartToMove = paragraphStart.deepEquivalent
(); |
| 272 if (!m_removeOnly && isEditablePosition(paragraphStartToMove)) { | 272 if (!m_removeOnly && isEditablePosition(paragraphStartToMove)) { |
| 273 RefPtrWillBeRawPtr<HTMLElement> newBlock = moveParagraphContents
ToNewBlockIfNecessary(paragraphStartToMove, editingState); | 273 RawPtr<HTMLElement> newBlock = moveParagraphContentsToNewBlockIf
Necessary(paragraphStartToMove, editingState); |
| 274 if (editingState->isAborted()) | 274 if (editingState->isAborted()) |
| 275 return; | 275 return; |
| 276 if (newBlock) | 276 if (newBlock) |
| 277 block = newBlock; | 277 block = newBlock; |
| 278 } | 278 } |
| 279 if (block && block->isHTMLElement()) { | 279 if (block && block->isHTMLElement()) { |
| 280 removeCSSStyle(style, toHTMLElement(block), editingState); | 280 removeCSSStyle(style, toHTMLElement(block), editingState); |
| 281 if (editingState->isAborted()) | 281 if (editingState->isAborted()) |
| 282 return; | 282 return; |
| 283 if (!m_removeOnly) | 283 if (!m_removeOnly) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 294 | 294 |
| 295 EphemeralRange startEphemeralRange = PlainTextRange(startIndex).createRangeF
orSelection(toContainerNode(scope)); | 295 EphemeralRange startEphemeralRange = PlainTextRange(startIndex).createRangeF
orSelection(toContainerNode(scope)); |
| 296 if (startEphemeralRange.isNull()) | 296 if (startEphemeralRange.isNull()) |
| 297 return; | 297 return; |
| 298 EphemeralRange endEphemeralRange = PlainTextRange(endIndex).createRangeForSe
lection(toContainerNode(scope)); | 298 EphemeralRange endEphemeralRange = PlainTextRange(endIndex).createRangeForSe
lection(toContainerNode(scope)); |
| 299 if (endEphemeralRange.isNull()) | 299 if (endEphemeralRange.isNull()) |
| 300 return; | 300 return; |
| 301 updateStartEnd(startEphemeralRange.startPosition(), endEphemeralRange.startP
osition()); | 301 updateStartEnd(startEphemeralRange.startPosition(), endEphemeralRange.startP
osition()); |
| 302 } | 302 } |
| 303 | 303 |
| 304 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyStyleOrCreateEmpty(co
nst StylePropertySet* style) | 304 static RawPtr<MutableStylePropertySet> copyStyleOrCreateEmpty(const StylePropert
ySet* style) |
| 305 { | 305 { |
| 306 if (!style) | 306 if (!style) |
| 307 return MutableStylePropertySet::create(HTMLQuirksMode); | 307 return MutableStylePropertySet::create(HTMLQuirksMode); |
| 308 return style->mutableCopy(); | 308 return style->mutableCopy(); |
| 309 } | 309 } |
| 310 | 310 |
| 311 void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style, Editin
gState* editingState) | 311 void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style, Editin
gState* editingState) |
| 312 { | 312 { |
| 313 static const float MinimumFontSize = 0.1f; | 313 static const float MinimumFontSize = 0.1f; |
| 314 | 314 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 WillBeHeapHashMap<RawPtrWillBeMember<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 ASSERT(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 WillBeHeapVector<RefPtrWillBeMember<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 ASSERT(node); |
| 399 RefPtrWillBeRawPtr<HTMLElement> element = nullptr; | 399 RawPtr<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 RefPtrWillBeRawPtr<HTMLSpanElement> span = HTMLSpanElement::create(d
ocument()); | 408 RawPtr<HTMLSpanElement> span = HTMLSpanElement::create(document()); |
| 409 surroundNodeRangeWithElement(node, node, span.get(), editingState); | 409 surroundNodeRangeWithElement(node, node, span.get(), editingState); |
| 410 if (editingState->isAborted()) | 410 if (editingState->isAborted()) |
| 411 return; | 411 return; |
| 412 element = span.release(); | 412 element = span.release(); |
| 413 } else { | 413 } else { |
| 414 // Only handle HTML elements and text nodes. | 414 // Only handle HTML elements and text nodes. |
| 415 continue; | 415 continue; |
| 416 } | 416 } |
| 417 lastStyledNode = node; | 417 lastStyledNode = node; |
| 418 | 418 |
| 419 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCre
ateEmpty(element->inlineStyle()); | 419 RawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty(ele
ment->inlineStyle()); |
| 420 float currentFontSize = computedFontSize(node); | 420 float currentFontSize = computedFontSize(node); |
| 421 float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node)
+ style->fontSizeDelta()); | 421 float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node)
+ style->fontSizeDelta()); |
| 422 RefPtrWillBeRawPtr<CSSValue> value = inlineStyle->getPropertyCSSValue(CS
SPropertyFontSize); | 422 RawPtr<CSSValue> value = inlineStyle->getPropertyCSSValue(CSSPropertyFon
tSize); |
| 423 if (value) { | 423 if (value) { |
| 424 element->removeInlineStyleProperty(CSSPropertyFontSize); | 424 element->removeInlineStyleProperty(CSSPropertyFontSize); |
| 425 currentFontSize = computedFontSize(node); | 425 currentFontSize = computedFontSize(node); |
| 426 } | 426 } |
| 427 if (currentFontSize != desiredFontSize) { | 427 if (currentFontSize != desiredFontSize) { |
| 428 inlineStyle->setProperty(CSSPropertyFontSize, cssValuePool().createV
alue(desiredFontSize, CSSPrimitiveValue::UnitType::Pixels), false); | 428 inlineStyle->setProperty(CSSPropertyFontSize, cssValuePool().createV
alue(desiredFontSize, CSSPrimitiveValue::UnitType::Pixels), false); |
| 429 setNodeAttribute(element.get(), styleAttr, AtomicString(inlineStyle-
>asText())); | 429 setNodeAttribute(element.get(), styleAttr, AtomicString(inlineStyle-
>asText())); |
| 430 } | 430 } |
| 431 if (inlineStyle->isEmpty()) { | 431 if (inlineStyle->isEmpty()) { |
| 432 removeElementAttribute(element.get(), styleAttr); | 432 removeElementAttribute(element.get(), styleAttr); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 && EditingStyle::create(highestAncestorWithUnicodeBidi, EditingStyle::Al
lProperties)->textDirection(highestAncestorDirection) | 502 && EditingStyle::create(highestAncestorWithUnicodeBidi, EditingStyle::Al
lProperties)->textDirection(highestAncestorDirection) |
| 503 && highestAncestorDirection == allowedDirection) { | 503 && highestAncestorDirection == allowedDirection) { |
| 504 if (!nextHighestAncestorWithUnicodeBidi) | 504 if (!nextHighestAncestorWithUnicodeBidi) |
| 505 return toHTMLElement(highestAncestorWithUnicodeBidi); | 505 return toHTMLElement(highestAncestorWithUnicodeBidi); |
| 506 | 506 |
| 507 unsplitAncestor = toHTMLElement(highestAncestorWithUnicodeBidi); | 507 unsplitAncestor = toHTMLElement(highestAncestorWithUnicodeBidi); |
| 508 highestAncestorWithUnicodeBidi = nextHighestAncestorWithUnicodeBidi; | 508 highestAncestorWithUnicodeBidi = nextHighestAncestorWithUnicodeBidi; |
| 509 } | 509 } |
| 510 | 510 |
| 511 // Split every ancestor through highest ancestor with embedding. | 511 // Split every ancestor through highest ancestor with embedding. |
| 512 RefPtrWillBeRawPtr<Node> currentNode = node; | 512 RawPtr<Node> currentNode = node; |
| 513 while (currentNode) { | 513 while (currentNode) { |
| 514 RefPtrWillBeRawPtr<Element> parent = toElement(currentNode->parentNode()
); | 514 RawPtr<Element> parent = toElement(currentNode->parentNode()); |
| 515 if (before ? currentNode->previousSibling() : currentNode->nextSibling()
) | 515 if (before ? currentNode->previousSibling() : currentNode->nextSibling()
) |
| 516 splitElement(parent, before ? currentNode.get() : currentNode->nextS
ibling()); | 516 splitElement(parent, before ? currentNode.get() : currentNode->nextS
ibling()); |
| 517 if (parent == highestAncestorWithUnicodeBidi) | 517 if (parent == highestAncestorWithUnicodeBidi) |
| 518 break; | 518 break; |
| 519 currentNode = parent; | 519 currentNode = parent; |
| 520 } | 520 } |
| 521 return unsplitAncestor; | 521 return unsplitAncestor; |
| 522 } | 522 } |
| 523 | 523 |
| 524 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, HTMLElemen
t* unsplitAncestor, EditingState* editingState) | 524 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, HTMLElemen
t* unsplitAncestor, EditingState* editingState) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 538 | 538 |
| 539 // FIXME: This code should really consider the mapped attribute 'dir', t
he inline style declaration, | 539 // FIXME: This code should really consider the mapped attribute 'dir', t
he inline style declaration, |
| 540 // and all matching style rules in order to determine how to best set th
e unicode-bidi property to 'normal'. | 540 // and all matching style rules in order to determine how to best set th
e unicode-bidi property to 'normal'. |
| 541 // For now, it assumes that if the 'dir' attribute is present, then remo
ving it will suffice, and | 541 // For now, it assumes that if the 'dir' attribute is present, then remo
ving it will suffice, and |
| 542 // otherwise it sets the property in the inline style declaration. | 542 // otherwise it sets the property in the inline style declaration. |
| 543 if (element->hasAttribute(dirAttr)) { | 543 if (element->hasAttribute(dirAttr)) { |
| 544 // FIXME: If this is a BDO element, we should probably just remove i
t if it has no | 544 // FIXME: If this is a BDO element, we should probably just remove i
t if it has no |
| 545 // other attributes, like we (should) do with B and I elements. | 545 // other attributes, like we (should) do with B and I elements. |
| 546 removeElementAttribute(element, dirAttr); | 546 removeElementAttribute(element, dirAttr); |
| 547 } else { | 547 } else { |
| 548 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); | 548 RawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty
(element->inlineStyle()); |
| 549 inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); | 549 inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); |
| 550 inlineStyle->removeProperty(CSSPropertyDirection); | 550 inlineStyle->removeProperty(CSSPropertyDirection); |
| 551 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); | 551 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); |
| 552 if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) { | 552 if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) { |
| 553 removeNodePreservingChildren(element, editingState); | 553 removeNodePreservingChildren(element, editingState); |
| 554 if (editingState->isAborted()) | 554 if (editingState->isAborted()) |
| 555 return; | 555 return; |
| 556 } | 556 } |
| 557 } | 557 } |
| 558 } | 558 } |
| 559 } | 559 } |
| 560 | 560 |
| 561 static HTMLElement* highestEmbeddingAncestor(Node* startNode, Node* enclosingNod
e) | 561 static HTMLElement* highestEmbeddingAncestor(Node* startNode, Node* enclosingNod
e) |
| 562 { | 562 { |
| 563 for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { | 563 for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { |
| 564 if (n->isHTMLElement() | 564 if (n->isHTMLElement() |
| 565 && EditingStyle::isEmbedOrIsolate(getIdentifierValue(CSSComputedStyl
eDeclaration::create(n).get(), CSSPropertyUnicodeBidi))) { | 565 && EditingStyle::isEmbedOrIsolate(getIdentifierValue(CSSComputedStyl
eDeclaration::create(n).get(), CSSPropertyUnicodeBidi))) { |
| 566 return toHTMLElement(n); | 566 return toHTMLElement(n); |
| 567 } | 567 } |
| 568 } | 568 } |
| 569 | 569 |
| 570 return 0; | 570 return 0; |
| 571 } | 571 } |
| 572 | 572 |
| 573 void ApplyStyleCommand::applyInlineStyle(EditingStyle* style, EditingState* edit
ingState) | 573 void ApplyStyleCommand::applyInlineStyle(EditingStyle* style, EditingState* edit
ingState) |
| 574 { | 574 { |
| 575 RefPtrWillBeRawPtr<ContainerNode> startDummySpanAncestor = nullptr; | 575 RawPtr<ContainerNode> startDummySpanAncestor = nullptr; |
| 576 RefPtrWillBeRawPtr<ContainerNode> endDummySpanAncestor = nullptr; | 576 RawPtr<ContainerNode> endDummySpanAncestor = nullptr; |
| 577 | 577 |
| 578 // update document layout once before removing styles | 578 // update document layout once before removing styles |
| 579 // so that we avoid the expense of updating before each and every call | 579 // so that we avoid the expense of updating before each and every call |
| 580 // to check a computed style | 580 // to check a computed style |
| 581 document().updateLayoutIgnorePendingStylesheets(); | 581 document().updateLayoutIgnorePendingStylesheets(); |
| 582 | 582 |
| 583 // adjust to the positions we want to use for applying style | 583 // adjust to the positions we want to use for applying style |
| 584 Position start = startPosition(); | 584 Position start = startPosition(); |
| 585 Position end = endPosition(); | 585 Position end = endPosition(); |
| 586 | 586 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 } | 622 } |
| 623 | 623 |
| 624 // Remove style from the selection. | 624 // Remove style from the selection. |
| 625 // Use the upstream position of the start for removing style. | 625 // Use the upstream position of the start for removing style. |
| 626 // This will ensure we remove all traces of the relevant styles from the sel
ection | 626 // This will ensure we remove all traces of the relevant styles from the sel
ection |
| 627 // and prevent us from adding redundant ones, as described in: | 627 // and prevent us from adding redundant ones, as described in: |
| 628 // <rdar://problem/3724344> Bolding and unbolding creates extraneous tags | 628 // <rdar://problem/3724344> Bolding and unbolding creates extraneous tags |
| 629 Position removeStart = mostBackwardCaretPosition(start); | 629 Position removeStart = mostBackwardCaretPosition(start); |
| 630 WritingDirection textDirection = NaturalWritingDirection; | 630 WritingDirection textDirection = NaturalWritingDirection; |
| 631 bool hasTextDirection = style->textDirection(textDirection); | 631 bool hasTextDirection = style->textDirection(textDirection); |
| 632 RefPtrWillBeRawPtr<EditingStyle> styleWithoutEmbedding = nullptr; | 632 RawPtr<EditingStyle> styleWithoutEmbedding = nullptr; |
| 633 RefPtrWillBeRawPtr<EditingStyle> embeddingStyle = nullptr; | 633 RawPtr<EditingStyle> embeddingStyle = nullptr; |
| 634 if (hasTextDirection) { | 634 if (hasTextDirection) { |
| 635 // Leave alone an ancestor that provides the desired single level embedd
ing, if there is one. | 635 // Leave alone an ancestor that provides the desired single level embedd
ing, if there is one. |
| 636 HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.
anchorNode(), true, textDirection); | 636 HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.
anchorNode(), true, textDirection); |
| 637 HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.anch
orNode(), false, textDirection); | 637 HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.anch
orNode(), false, textDirection); |
| 638 removeEmbeddingUpToEnclosingBlock(start.anchorNode(), startUnsplitAncest
or, editingState); | 638 removeEmbeddingUpToEnclosingBlock(start.anchorNode(), startUnsplitAncest
or, editingState); |
| 639 if (editingState->isAborted()) | 639 if (editingState->isAborted()) |
| 640 return; | 640 return; |
| 641 removeEmbeddingUpToEnclosingBlock(end.anchorNode(), endUnsplitAncestor,
editingState); | 641 removeEmbeddingUpToEnclosingBlock(end.anchorNode(), endUnsplitAncestor,
editingState); |
| 642 if (editingState->isAborted()) | 642 if (editingState->isAborted()) |
| 643 return; | 643 return; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 return; | 687 return; |
| 688 start = startPosition(); | 688 start = startPosition(); |
| 689 end = endPosition(); | 689 end = endPosition(); |
| 690 } | 690 } |
| 691 | 691 |
| 692 // update document layout once before running the rest of the function | 692 // update document layout once before running the rest of the function |
| 693 // so that we avoid the expense of updating before each and every call | 693 // so that we avoid the expense of updating before each and every call |
| 694 // to check a computed style | 694 // to check a computed style |
| 695 document().updateLayoutIgnorePendingStylesheets(); | 695 document().updateLayoutIgnorePendingStylesheets(); |
| 696 | 696 |
| 697 RefPtrWillBeRawPtr<EditingStyle> styleToApply = style; | 697 RawPtr<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 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul
l()); |
| 707 | 707 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 pastEndNode = NodeTraversal::nextSkippingChildren(*end.anchorNode()); | 745 pastEndNode = NodeTraversal::nextSkippingChildren(*end.anchorNode()); |
| 746 | 746 |
| 747 // FIXME: Callers should perform this operation on a Range that includes the
br | 747 // FIXME: Callers should perform this operation on a Range that includes the
br |
| 748 // if they want style applied to the empty line. | 748 // if they want style applied to the empty line. |
| 749 if (start == end && isHTMLBRElement(*start.anchorNode())) | 749 if (start == end && isHTMLBRElement(*start.anchorNode())) |
| 750 pastEndNode = NodeTraversal::next(*start.anchorNode()); | 750 pastEndNode = NodeTraversal::next(*start.anchorNode()); |
| 751 | 751 |
| 752 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. | 752 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. |
| 753 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run | 753 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run |
| 754 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> | 754 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> |
| 755 RefPtrWillBeRawPtr<Range> range = Range::create(startNode->document(), start
, end); | 755 RawPtr<Range> range = Range::create(startNode->document(), start, end); |
| 756 Element* editableRoot = startNode->rootEditableElement(); | 756 Element* editableRoot = startNode->rootEditableElement(); |
| 757 if (startNode != editableRoot) { | 757 if (startNode != editableRoot) { |
| 758 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(*startNode->parentNode(), *range)) | 758 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(*startNode->parentNode(), *range)) |
| 759 startNode = startNode->parentNode(); | 759 startNode = startNode->parentNode(); |
| 760 } | 760 } |
| 761 | 761 |
| 762 applyInlineStyleToNodeRange(style, startNode, pastEndNode, editingState); | 762 applyInlineStyleToNodeRange(style, startNode, pastEndNode, editingState); |
| 763 } | 763 } |
| 764 | 764 |
| 765 static bool containsNonEditableRegion(Node& node) | 765 static bool containsNonEditableRegion(Node& node) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 794 | 794 |
| 795 DEFINE_INLINE_TRACE() | 795 DEFINE_INLINE_TRACE() |
| 796 { | 796 { |
| 797 visitor->trace(start); | 797 visitor->trace(start); |
| 798 visitor->trace(end); | 798 visitor->trace(end); |
| 799 visitor->trace(pastEndNode); | 799 visitor->trace(pastEndNode); |
| 800 visitor->trace(positionForStyleComputation); | 800 visitor->trace(positionForStyleComputation); |
| 801 visitor->trace(dummyElement); | 801 visitor->trace(dummyElement); |
| 802 } | 802 } |
| 803 | 803 |
| 804 RefPtrWillBeMember<Node> start; | 804 Member<Node> start; |
| 805 RefPtrWillBeMember<Node> end; | 805 Member<Node> end; |
| 806 RefPtrWillBeMember<Node> pastEndNode; | 806 Member<Node> pastEndNode; |
| 807 Position positionForStyleComputation; | 807 Position positionForStyleComputation; |
| 808 RefPtrWillBeMember<HTMLSpanElement> dummyElement; | 808 Member<HTMLSpanElement> dummyElement; |
| 809 StyleChange change; | 809 StyleChange change; |
| 810 }; | 810 }; |
| 811 | 811 |
| 812 } // namespace blink | 812 } // namespace blink |
| 813 | 813 |
| 814 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::InlineRunToApplyStyle); | 814 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::InlineRunToApplyStyle); |
| 815 | 815 |
| 816 namespace blink { | 816 namespace blink { |
| 817 | 817 |
| 818 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, PassRef
PtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> pastEndNode, Editi
ngState* editingState) | 818 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, RawPtr<
Node> startNode, RawPtr<Node> pastEndNode, EditingState* editingState) |
| 819 { | 819 { |
| 820 if (m_removeOnly) | 820 if (m_removeOnly) |
| 821 return; | 821 return; |
| 822 | 822 |
| 823 document().updateLayoutIgnorePendingStylesheets(); | 823 document().updateLayoutIgnorePendingStylesheets(); |
| 824 | 824 |
| 825 WillBeHeapVector<InlineRunToApplyStyle> runs; | 825 HeapVector<InlineRunToApplyStyle> runs; |
| 826 RefPtrWillBeRawPtr<Node> node = startNode; | 826 RawPtr<Node> node = startNode; |
| 827 for (RefPtrWillBeRawPtr<Node> next; node && node != pastEndNode; node = next
) { | 827 for (RawPtr<Node> next; node && node != pastEndNode; node = next) { |
| 828 next = NodeTraversal::next(*node); | 828 next = NodeTraversal::next(*node); |
| 829 | 829 |
| 830 if (!node->layoutObject() || !node->hasEditableStyle()) | 830 if (!node->layoutObject() || !node->hasEditableStyle()) |
| 831 continue; | 831 continue; |
| 832 | 832 |
| 833 if (!node->layoutObjectIsRichlyEditable() && node->isHTMLElement()) { | 833 if (!node->layoutObjectIsRichlyEditable() && node->isHTMLElement()) { |
| 834 HTMLElement* element = toHTMLElement(node); | 834 HTMLElement* element = toHTMLElement(node); |
| 835 // This is a plaintext-only region. Only proceed if it's fully selec
ted. | 835 // This is a plaintext-only region. Only proceed if it's fully selec
ted. |
| 836 // pastEndNode is the node after the last fully selected node, so if
it's inside node then | 836 // pastEndNode is the node after the last fully selected node, so if
it's inside node then |
| 837 // node isn't fully selected. | 837 // node isn't fully selected. |
| 838 if (pastEndNode && pastEndNode->isDescendantOf(element)) | 838 if (pastEndNode && pastEndNode->isDescendantOf(element)) |
| 839 break; | 839 break; |
| 840 // Add to this element's inline style and skip over its contents. | 840 // Add to this element's inline style and skip over its contents. |
| 841 next = NodeTraversal::nextSkippingChildren(*node); | 841 next = NodeTraversal::nextSkippingChildren(*node); |
| 842 if (!style->style()) | 842 if (!style->style()) |
| 843 continue; | 843 continue; |
| 844 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); | 844 RawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty
(element->inlineStyle()); |
| 845 inlineStyle->mergeAndOverrideOnConflict(style->style()); | 845 inlineStyle->mergeAndOverrideOnConflict(style->style()); |
| 846 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); | 846 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); |
| 847 continue; | 847 continue; |
| 848 } | 848 } |
| 849 | 849 |
| 850 if (isEnclosingBlock(node.get())) | 850 if (isEnclosingBlock(node.get())) |
| 851 continue; | 851 continue; |
| 852 | 852 |
| 853 if (node->hasChildren()) { | 853 if (node->hasChildren()) { |
| 854 if (node->contains(pastEndNode.get()) || containsNonEditableRegion(*
node) || !node->parentNode()->hasEditableStyle()) | 854 if (node->contains(pastEndNode.get()) || containsNonEditableRegion(*
node) || !node->parentNode()->hasEditableStyle()) |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 continue; | 925 continue; |
| 926 // We don't consider m_isInlineElementToRemoveFunction here because we n
ever apply style when m_isInlineElementToRemoveFunction is specified | 926 // We don't consider m_isInlineElementToRemoveFunction here because we n
ever apply style when m_isInlineElementToRemoveFunction is specified |
| 927 if (!style->styleIsPresentInComputedStyleOfNode(node)) | 927 if (!style->styleIsPresentInComputedStyleOfNode(node)) |
| 928 return true; | 928 return true; |
| 929 if (m_styledInlineElement && !enclosingElementWithTag(positionBeforeNode
(node), m_styledInlineElement->tagQName())) | 929 if (m_styledInlineElement && !enclosingElementWithTag(positionBeforeNode
(node), m_styledInlineElement->tagQName())) |
| 930 return true; | 930 return true; |
| 931 } | 931 } |
| 932 return false; | 932 return false; |
| 933 } | 933 } |
| 934 | 934 |
| 935 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style,
RefPtrWillBeMember<Node>& runStart, RefPtrWillBeMember<Node>& runEnd, PassRefPt
rWillBeRawPtr<Node> pastEndNode, EditingState* editingState) | 935 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style,
Member<Node>& runStart, Member<Node>& runEnd, RawPtr<Node> pastEndNode, Editing
State* editingState) |
| 936 { | 936 { |
| 937 ASSERT(runStart && runEnd); | 937 ASSERT(runStart && runEnd); |
| 938 RefPtrWillBeRawPtr<Node> next = runStart; | 938 RawPtr<Node> next = runStart; |
| 939 for (RefPtrWillBeRawPtr<Node> node = next; node && node->inDocument() && nod
e != pastEndNode; node = next) { | 939 for (RawPtr<Node> node = next; node && node->inDocument() && node != pastEnd
Node; node = next) { |
| 940 if (editingIgnoresContent(node.get())) { | 940 if (editingIgnoresContent(node.get())) { |
| 941 ASSERT(!node->contains(pastEndNode.get())); | 941 ASSERT(!node->contains(pastEndNode.get())); |
| 942 next = NodeTraversal::nextSkippingChildren(*node); | 942 next = NodeTraversal::nextSkippingChildren(*node); |
| 943 } else { | 943 } else { |
| 944 next = NodeTraversal::next(*node); | 944 next = NodeTraversal::next(*node); |
| 945 } | 945 } |
| 946 if (!node->isHTMLElement()) | 946 if (!node->isHTMLElement()) |
| 947 continue; | 947 continue; |
| 948 | 948 |
| 949 HTMLElement& element = toHTMLElement(*node); | 949 HTMLElement& element = toHTMLElement(*node); |
| 950 RefPtrWillBeRawPtr<Node> previousSibling = element.previousSibling(); | 950 RawPtr<Node> previousSibling = element.previousSibling(); |
| 951 RefPtrWillBeRawPtr<Node> nextSibling = element.nextSibling(); | 951 RawPtr<Node> nextSibling = element.nextSibling(); |
| 952 RefPtrWillBeRawPtr<ContainerNode> parent = element.parentNode(); | 952 RawPtr<ContainerNode> parent = element.parentNode(); |
| 953 removeInlineStyleFromElement(style, &element, editingState, RemoveAlways
); | 953 removeInlineStyleFromElement(style, &element, editingState, RemoveAlways
); |
| 954 if (editingState->isAborted()) | 954 if (editingState->isAborted()) |
| 955 return; | 955 return; |
| 956 if (!element.inDocument()) { | 956 if (!element.inDocument()) { |
| 957 // FIXME: We might need to update the start and the end of current s
election here but need a test. | 957 // FIXME: We might need to update the start and the end of current s
election here but need a test. |
| 958 if (runStart == element) | 958 if (runStart == element) |
| 959 runStart = previousSibling ? previousSibling->nextSibling() : pa
rent->firstChild(); | 959 runStart = previousSibling ? previousSibling->nextSibling() : pa
rent->firstChild(); |
| 960 if (runEnd == element) | 960 if (runEnd == element) |
| 961 runEnd = nextSibling ? nextSibling->previousSibling() : parent->
lastChild(); | 961 runEnd = nextSibling ? nextSibling->previousSibling() : parent->
lastChild(); |
| 962 } | 962 } |
| 963 } | 963 } |
| 964 } | 964 } |
| 965 | 965 |
| 966 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRe
fPtrWillBeRawPtr<HTMLElement> element, EditingState* editingState, InlineStyleRe
movalMode mode, EditingStyle* extractedStyle) | 966 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, RawPtr
<HTMLElement> element, EditingState* editingState, InlineStyleRemovalMode mode,
EditingStyle* extractedStyle) |
| 967 { | 967 { |
| 968 ASSERT(element); | 968 ASSERT(element); |
| 969 | 969 |
| 970 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node
::UserSelectAllIsAlwaysNonEditable)) | 970 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node
::UserSelectAllIsAlwaysNonEditable)) |
| 971 return false; | 971 return false; |
| 972 | 972 |
| 973 if (isStyledInlineElementToRemove(element.get())) { | 973 if (isStyledInlineElementToRemove(element.get())) { |
| 974 if (mode == RemoveNone) | 974 if (mode == RemoveNone) |
| 975 return true; | 975 return true; |
| 976 if (extractedStyle) | 976 if (extractedStyle) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 | 1084 |
| 1085 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
le, EditingState* editingState) | 1085 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
le, EditingState* editingState) |
| 1086 { | 1086 { |
| 1087 ASSERT(node); | 1087 ASSERT(node); |
| 1088 | 1088 |
| 1089 node->document().updateLayoutTree(); | 1089 node->document().updateLayoutTree(); |
| 1090 | 1090 |
| 1091 if (!style || style->isEmpty() || !node->layoutObject() || isHTMLIFrameEleme
nt(*node)) | 1091 if (!style || style->isEmpty() || !node->layoutObject() || isHTMLIFrameEleme
nt(*node)) |
| 1092 return; | 1092 return; |
| 1093 | 1093 |
| 1094 RefPtrWillBeRawPtr<EditingStyle> newInlineStyle = style; | 1094 RawPtr<EditingStyle> newInlineStyle = style; |
| 1095 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { | 1095 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { |
| 1096 newInlineStyle = style->copy(); | 1096 newInlineStyle = style->copy(); |
| 1097 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt
yle::OverrideValues); | 1097 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt
yle::OverrideValues); |
| 1098 } | 1098 } |
| 1099 | 1099 |
| 1100 // Since addInlineStyleIfNeeded can't add styles to block-flow layout object
s, add style attribute instead. | 1100 // Since addInlineStyleIfNeeded can't add styles to block-flow layout object
s, add style attribute instead. |
| 1101 // FIXME: applyInlineStyleToRange should be used here instead. | 1101 // FIXME: applyInlineStyleToRange should be used here instead. |
| 1102 if ((node->layoutObject()->isLayoutBlockFlow() || node->hasChildren()) && no
de->isHTMLElement()) { | 1102 if ((node->layoutObject()->isLayoutBlockFlow() || node->hasChildren()) && no
de->isHTMLElement()) { |
| 1103 setNodeAttribute(toHTMLElement(node), styleAttr, AtomicString(newInlineS
tyle->style()->asText())); | 1103 setNodeAttribute(toHTMLElement(node), styleAttr, AtomicString(newInlineS
tyle->style()->asText())); |
| 1104 return; | 1104 return; |
| 1105 } | 1105 } |
| 1106 | 1106 |
| 1107 if (node->layoutObject()->isText() && toLayoutText(node->layoutObject())->is
AllCollapsibleWhitespace()) | 1107 if (node->layoutObject()->isText() && toLayoutText(node->layoutObject())->is
AllCollapsibleWhitespace()) |
| 1108 return; | 1108 return; |
| 1109 | 1109 |
| 1110 // We can't wrap node with the styled element here because new styled elemen
t will never be removed if we did. | 1110 // We can't wrap node with the styled element here because new styled elemen
t will never be removed if we did. |
| 1111 // If we modified the child pointer in pushDownInlineStyleAroundNode to poin
t to new style element | 1111 // If we modified the child pointer in pushDownInlineStyleAroundNode to poin
t to new style element |
| 1112 // then we fall into an infinite loop where we keep removing and adding styl
ed element wrapping node. | 1112 // then we fall into an infinite loop where we keep removing and adding styl
ed element wrapping node. |
| 1113 addInlineStyleIfNeeded(newInlineStyle.get(), node, node, editingState); | 1113 addInlineStyleIfNeeded(newInlineStyle.get(), node, node, editingState); |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
targetNode, EditingState* editingState) | 1116 void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
targetNode, EditingState* editingState) |
| 1117 { | 1117 { |
| 1118 HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(sty
le, targetNode); | 1118 HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(sty
le, targetNode); |
| 1119 if (!highestAncestor) | 1119 if (!highestAncestor) |
| 1120 return; | 1120 return; |
| 1121 | 1121 |
| 1122 // The outer loop is traversing the tree vertically from highestAncestor to
targetNode | 1122 // The outer loop is traversing the tree vertically from highestAncestor to
targetNode |
| 1123 RefPtrWillBeRawPtr<Node> current = highestAncestor; | 1123 RawPtr<Node> current = highestAncestor; |
| 1124 // Along the way, styled elements that contain targetNode are removed and ac
cumulated into elementsToPushDown. | 1124 // Along the way, styled elements that contain targetNode are removed and ac
cumulated into elementsToPushDown. |
| 1125 // Each child of the removed element, exclusing ancestors of targetNode, is
then wrapped by clones of elements in elementsToPushDown. | 1125 // Each child of the removed element, exclusing ancestors of targetNode, is
then wrapped by clones of elements in elementsToPushDown. |
| 1126 WillBeHeapVector<RefPtrWillBeMember<Element>> elementsToPushDown; | 1126 HeapVector<Member<Element>> elementsToPushDown; |
| 1127 while (current && current != targetNode && current->contains(targetNode)) { | 1127 while (current && current != targetNode && current->contains(targetNode)) { |
| 1128 NodeVector currentChildren; | 1128 NodeVector currentChildren; |
| 1129 getChildNodes(toContainerNode(*current), currentChildren); | 1129 getChildNodes(toContainerNode(*current), currentChildren); |
| 1130 RefPtrWillBeRawPtr<Element> styledElement = nullptr; | 1130 RawPtr<Element> styledElement = nullptr; |
| 1131 if (current->isStyledElement() && isStyledInlineElementToRemove(toElemen
t(current))) { | 1131 if (current->isStyledElement() && isStyledInlineElementToRemove(toElemen
t(current))) { |
| 1132 styledElement = toElement(current); | 1132 styledElement = toElement(current); |
| 1133 elementsToPushDown.append(styledElement); | 1133 elementsToPushDown.append(styledElement); |
| 1134 } | 1134 } |
| 1135 | 1135 |
| 1136 RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = EditingStyle::create(
); | 1136 RawPtr<EditingStyle> styleToPushDown = EditingStyle::create(); |
| 1137 if (current->isHTMLElement()) { | 1137 if (current->isHTMLElement()) { |
| 1138 removeInlineStyleFromElement(style, toHTMLElement(current), editingS
tate, RemoveIfNeeded, styleToPushDown.get()); | 1138 removeInlineStyleFromElement(style, toHTMLElement(current), editingS
tate, RemoveIfNeeded, styleToPushDown.get()); |
| 1139 if (editingState->isAborted()) | 1139 if (editingState->isAborted()) |
| 1140 return; | 1140 return; |
| 1141 } | 1141 } |
| 1142 | 1142 |
| 1143 // The inner loop will go through children on each level | 1143 // The inner loop will go through children on each level |
| 1144 // FIXME: we should aggregate inline child elements together so that we
don't wrap each child separately. | 1144 // FIXME: we should aggregate inline child elements together so that we
don't wrap each child separately. |
| 1145 for (const auto& currentChild : currentChildren) { | 1145 for (const auto& currentChild : currentChildren) { |
| 1146 Node* child = currentChild.get(); | 1146 Node* child = currentChild.get(); |
| 1147 if (!child->parentNode()) | 1147 if (!child->parentNode()) |
| 1148 continue; | 1148 continue; |
| 1149 if (!child->contains(targetNode) && elementsToPushDown.size()) { | 1149 if (!child->contains(targetNode) && elementsToPushDown.size()) { |
| 1150 for (const auto& element : elementsToPushDown) { | 1150 for (const auto& element : elementsToPushDown) { |
| 1151 RefPtrWillBeRawPtr<Element> wrapper = element->cloneElementW
ithoutChildren(); | 1151 RawPtr<Element> wrapper = element->cloneElementWithoutChildr
en(); |
| 1152 wrapper->removeAttribute(styleAttr); | 1152 wrapper->removeAttribute(styleAttr); |
| 1153 // Delete id attribute from the second element because the s
ame id cannot be used for more than one element | 1153 // Delete id attribute from the second element because the s
ame id cannot be used for more than one element |
| 1154 element->removeAttribute(HTMLNames::idAttr); | 1154 element->removeAttribute(HTMLNames::idAttr); |
| 1155 if (isHTMLAnchorElement(element)) | 1155 if (isHTMLAnchorElement(element)) |
| 1156 element->removeAttribute(HTMLNames::nameAttr); | 1156 element->removeAttribute(HTMLNames::nameAttr); |
| 1157 surroundNodeRangeWithElement(child, child, wrapper, editingS
tate); | 1157 surroundNodeRangeWithElement(child, child, wrapper, editingS
tate); |
| 1158 if (editingState->isAborted()) | 1158 if (editingState->isAborted()) |
| 1159 return; | 1159 return; |
| 1160 } | 1160 } |
| 1161 } | 1161 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 // If pushDownInlineStyleAroundNode has pruned start.anchorNode() or end.anc
horNode(), | 1214 // If pushDownInlineStyleAroundNode has pruned start.anchorNode() or end.anc
horNode(), |
| 1215 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround
Node won't prune. | 1215 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround
Node won't prune. |
| 1216 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; | 1216 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; |
| 1217 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; | 1217 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; |
| 1218 | 1218 |
| 1219 // Current ending selection resetting algorithm assumes |start| and |end| | 1219 // Current ending selection resetting algorithm assumes |start| and |end| |
| 1220 // are in a same DOM tree even if they are not in document. | 1220 // are in a same DOM tree even if they are not in document. |
| 1221 if (!Position::commonAncestorTreeScope(start, end)) | 1221 if (!Position::commonAncestorTreeScope(start, end)) |
| 1222 return; | 1222 return; |
| 1223 | 1223 |
| 1224 RefPtrWillBeRawPtr<Node> node = start.anchorNode(); | 1224 RawPtr<Node> node = start.anchorNode(); |
| 1225 while (node) { | 1225 while (node) { |
| 1226 RefPtrWillBeRawPtr<Node> next = nullptr; | 1226 RawPtr<Node> next = nullptr; |
| 1227 if (editingIgnoresContent(node.get())) { | 1227 if (editingIgnoresContent(node.get())) { |
| 1228 ASSERT(node == end.anchorNode() || !node->contains(end.anchorNode())
); | 1228 ASSERT(node == end.anchorNode() || !node->contains(end.anchorNode())
); |
| 1229 next = NodeTraversal::nextSkippingChildren(*node); | 1229 next = NodeTraversal::nextSkippingChildren(*node); |
| 1230 } else { | 1230 } else { |
| 1231 next = NodeTraversal::next(*node); | 1231 next = NodeTraversal::next(*node); |
| 1232 } | 1232 } |
| 1233 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node),
start, end)) { | 1233 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node),
start, end)) { |
| 1234 RefPtrWillBeRawPtr<HTMLElement> elem = toHTMLElement(node); | 1234 RawPtr<HTMLElement> elem = toHTMLElement(node); |
| 1235 RefPtrWillBeRawPtr<Node> prev = NodeTraversal::previousPostOrder(*el
em); | 1235 RawPtr<Node> prev = NodeTraversal::previousPostOrder(*elem); |
| 1236 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*elem); | 1236 RawPtr<Node> next = NodeTraversal::next(*elem); |
| 1237 RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = nullptr; | 1237 RawPtr<EditingStyle> styleToPushDown = nullptr; |
| 1238 RefPtrWillBeRawPtr<Node> childNode = nullptr; | 1238 RawPtr<Node> childNode = nullptr; |
| 1239 if (isStyledInlineElementToRemove(elem.get())) { | 1239 if (isStyledInlineElementToRemove(elem.get())) { |
| 1240 styleToPushDown = EditingStyle::create(); | 1240 styleToPushDown = EditingStyle::create(); |
| 1241 childNode = elem->firstChild(); | 1241 childNode = elem->firstChild(); |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 removeInlineStyleFromElement(style, elem.get(), editingState, Remove
IfNeeded, styleToPushDown.get()); | 1244 removeInlineStyleFromElement(style, elem.get(), editingState, Remove
IfNeeded, styleToPushDown.get()); |
| 1245 if (editingState->isAborted()) | 1245 if (editingState->isAborted()) |
| 1246 return; | 1246 return; |
| 1247 if (!elem->inDocument()) { | 1247 if (!elem->inDocument()) { |
| 1248 if (s.anchorNode() == elem) { | 1248 if (s.anchorNode() == elem) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position&
end) | 1288 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position&
end) |
| 1289 { | 1289 { |
| 1290 ASSERT(start.computeContainerNode()->isTextNode()); | 1290 ASSERT(start.computeContainerNode()->isTextNode()); |
| 1291 | 1291 |
| 1292 Position newEnd; | 1292 Position newEnd; |
| 1293 if (end.isOffsetInAnchor() && start.computeContainerNode() == end.computeCon
tainerNode()) | 1293 if (end.isOffsetInAnchor() && start.computeContainerNode() == end.computeCon
tainerNode()) |
| 1294 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode(
) - start.offsetInContainerNode()); | 1294 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode(
) - start.offsetInContainerNode()); |
| 1295 else | 1295 else |
| 1296 newEnd = end; | 1296 newEnd = end; |
| 1297 | 1297 |
| 1298 RefPtrWillBeRawPtr<Text> text = toText(start.computeContainerNode()); | 1298 RawPtr<Text> text = toText(start.computeContainerNode()); |
| 1299 splitTextNode(text, start.offsetInContainerNode()); | 1299 splitTextNode(text, start.offsetInContainerNode()); |
| 1300 updateStartEnd(firstPositionInNode(text.get()), newEnd); | 1300 updateStartEnd(firstPositionInNode(text.get()), newEnd); |
| 1301 } | 1301 } |
| 1302 | 1302 |
| 1303 void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en
d) | 1303 void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en
d) |
| 1304 { | 1304 { |
| 1305 ASSERT(end.computeContainerNode()->isTextNode()); | 1305 ASSERT(end.computeContainerNode()->isTextNode()); |
| 1306 | 1306 |
| 1307 bool shouldUpdateStart = start.isOffsetInAnchor() && start.computeContainerN
ode() == end.computeContainerNode(); | 1307 bool shouldUpdateStart = start.isOffsetInAnchor() && start.computeContainerN
ode() == end.computeContainerNode(); |
| 1308 Text* text = toText(end.anchorNode()); | 1308 Text* text = toText(end.anchorNode()); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 bool shouldUpdateStart = start.computeContainerNode() == endNode; | 1438 bool shouldUpdateStart = start.computeContainerNode() == endNode; |
| 1439 int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childN
odes()->length(); | 1439 int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childN
odes()->length(); |
| 1440 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC
ontainerNode()) : start, | 1440 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC
ontainerNode()) : start, |
| 1441 Position(nextElement, endOffset)); | 1441 Position(nextElement, endOffset)); |
| 1442 return true; | 1442 return true; |
| 1443 } | 1443 } |
| 1444 | 1444 |
| 1445 return false; | 1445 return false; |
| 1446 } | 1446 } |
| 1447 | 1447 |
| 1448 void ApplyStyleCommand::surroundNodeRangeWithElement(PassRefPtrWillBeRawPtr<Node
> passedStartNode, PassRefPtrWillBeRawPtr<Node> endNode, PassRefPtrWillBeRawPtr<
Element> elementToInsert, EditingState* editingState) | 1448 void ApplyStyleCommand::surroundNodeRangeWithElement(RawPtr<Node> passedStartNod
e, RawPtr<Node> endNode, RawPtr<Element> elementToInsert, EditingState* editingS
tate) |
| 1449 { | 1449 { |
| 1450 ASSERT(passedStartNode); | 1450 ASSERT(passedStartNode); |
| 1451 ASSERT(endNode); | 1451 ASSERT(endNode); |
| 1452 ASSERT(elementToInsert); | 1452 ASSERT(elementToInsert); |
| 1453 RefPtrWillBeRawPtr<Node> node = passedStartNode; | 1453 RawPtr<Node> node = passedStartNode; |
| 1454 RefPtrWillBeRawPtr<Element> element = elementToInsert; | 1454 RawPtr<Element> element = elementToInsert; |
| 1455 | 1455 |
| 1456 insertNodeBefore(element, node, editingState); | 1456 insertNodeBefore(element, node, editingState); |
| 1457 if (editingState->isAborted()) | 1457 if (editingState->isAborted()) |
| 1458 return; | 1458 return; |
| 1459 | 1459 |
| 1460 while (node) { | 1460 while (node) { |
| 1461 RefPtrWillBeRawPtr<Node> next = node->nextSibling(); | 1461 RawPtr<Node> next = node->nextSibling(); |
| 1462 if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) { | 1462 if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) { |
| 1463 removeNode(node, editingState); | 1463 removeNode(node, editingState); |
| 1464 if (editingState->isAborted()) | 1464 if (editingState->isAborted()) |
| 1465 return; | 1465 return; |
| 1466 appendNode(node, element, editingState); | 1466 appendNode(node, element, editingState); |
| 1467 if (editingState->isAborted()) | 1467 if (editingState->isAborted()) |
| 1468 return; | 1468 return; |
| 1469 } | 1469 } |
| 1470 if (node == endNode) | 1470 if (node == endNode) |
| 1471 break; | 1471 break; |
| 1472 node = next; | 1472 node = next; |
| 1473 } | 1473 } |
| 1474 | 1474 |
| 1475 RefPtrWillBeRawPtr<Node> nextSibling = element->nextSibling(); | 1475 RawPtr<Node> nextSibling = element->nextSibling(); |
| 1476 RefPtrWillBeRawPtr<Node> previousSibling = element->previousSibling(); | 1476 RawPtr<Node> previousSibling = element->previousSibling(); |
| 1477 if (nextSibling && nextSibling->isElementNode() && nextSibling->hasEditableS
tyle() | 1477 if (nextSibling && nextSibling->isElementNode() && nextSibling->hasEditableS
tyle() |
| 1478 && areIdenticalElements(*element, toElement(*nextSibling))) { | 1478 && areIdenticalElements(*element, toElement(*nextSibling))) { |
| 1479 mergeIdenticalElements(element.get(), toElement(nextSibling), editingSta
te); | 1479 mergeIdenticalElements(element.get(), toElement(nextSibling), editingSta
te); |
| 1480 if (editingState->isAborted()) | 1480 if (editingState->isAborted()) |
| 1481 return; | 1481 return; |
| 1482 } | 1482 } |
| 1483 | 1483 |
| 1484 if (previousSibling && previousSibling->isElementNode() && previousSibling->
hasEditableStyle()) { | 1484 if (previousSibling && previousSibling->isElementNode() && previousSibling->
hasEditableStyle()) { |
| 1485 Node* mergedElement = previousSibling->nextSibling(); | 1485 Node* mergedElement = previousSibling->nextSibling(); |
| 1486 if (mergedElement->isElementNode() && mergedElement->hasEditableStyle() | 1486 if (mergedElement->isElementNode() && mergedElement->hasEditableStyle() |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1507 StringBuilder cssText; | 1507 StringBuilder cssText; |
| 1508 cssText.append(cssStyle); | 1508 cssText.append(cssStyle); |
| 1509 if (const StylePropertySet* decl = block->inlineStyle()) { | 1509 if (const StylePropertySet* decl = block->inlineStyle()) { |
| 1510 if (!cssStyle.isEmpty()) | 1510 if (!cssStyle.isEmpty()) |
| 1511 cssText.append(' '); | 1511 cssText.append(' '); |
| 1512 cssText.append(decl->asText()); | 1512 cssText.append(decl->asText()); |
| 1513 } | 1513 } |
| 1514 setNodeAttribute(block, styleAttr, cssText.toAtomicString()); | 1514 setNodeAttribute(block, styleAttr, cssText.toAtomicString()); |
| 1515 } | 1515 } |
| 1516 | 1516 |
| 1517 void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWi
llBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EditingSta
te* editingState) | 1517 void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, RawPtr<Node>
passedStart, RawPtr<Node> passedEnd, EditingState* editingState) |
| 1518 { | 1518 { |
| 1519 if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->
inDocument()) | 1519 if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->
inDocument()) |
| 1520 return; | 1520 return; |
| 1521 | 1521 |
| 1522 RefPtrWillBeRawPtr<Node> start = passedStart; | 1522 RawPtr<Node> start = passedStart; |
| 1523 RefPtrWillBeMember<HTMLSpanElement> dummyElement = nullptr; | 1523 Member<HTMLSpanElement> dummyElement = nullptr; |
| 1524 StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dum
myElement, editingState)); | 1524 StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dum
myElement, editingState)); |
| 1525 if (editingState->isAborted()) | 1525 if (editingState->isAborted()) |
| 1526 return; | 1526 return; |
| 1527 | 1527 |
| 1528 if (dummyElement) { | 1528 if (dummyElement) { |
| 1529 removeNode(dummyElement, editingState); | 1529 removeNode(dummyElement, editingState); |
| 1530 if (editingState->isAborted()) | 1530 if (editingState->isAborted()) |
| 1531 return; | 1531 return; |
| 1532 } | 1532 } |
| 1533 | 1533 |
| 1534 applyInlineStyleChange(start, passedEnd, styleChange, DoNotAddStyledElement,
editingState); | 1534 applyInlineStyleChange(start, passedEnd, styleChange, DoNotAddStyledElement,
editingState); |
| 1535 } | 1535 } |
| 1536 | 1536 |
| 1537 Position ApplyStyleCommand::positionToComputeInlineStyleChange(PassRefPtrWillBeR
awPtr<Node> startNode, RefPtrWillBeMember<HTMLSpanElement>& dummyElement, Editin
gState* editingState) | 1537 Position ApplyStyleCommand::positionToComputeInlineStyleChange(RawPtr<Node> star
tNode, Member<HTMLSpanElement>& dummyElement, EditingState* editingState) |
| 1538 { | 1538 { |
| 1539 // It's okay to obtain the style at the startNode because we've removed all
relevant styles from the current run. | 1539 // It's okay to obtain the style at the startNode because we've removed all
relevant styles from the current run. |
| 1540 if (!startNode->isElementNode()) { | 1540 if (!startNode->isElementNode()) { |
| 1541 dummyElement = HTMLSpanElement::create(document()); | 1541 dummyElement = HTMLSpanElement::create(document()); |
| 1542 insertNodeAt(dummyElement, positionBeforeNode(startNode.get()), editingS
tate); | 1542 insertNodeAt(dummyElement, positionBeforeNode(startNode.get()), editingS
tate); |
| 1543 if (editingState->isAborted()) | 1543 if (editingState->isAborted()) |
| 1544 return Position(); | 1544 return Position(); |
| 1545 return positionBeforeNode(dummyElement.get()); | 1545 return positionBeforeNode(dummyElement.get()); |
| 1546 } | 1546 } |
| 1547 | 1547 |
| 1548 return firstPositionInOrBeforeNode(startNode.get()); | 1548 return firstPositionInOrBeforeNode(startNode.get()); |
| 1549 } | 1549 } |
| 1550 | 1550 |
| 1551 void ApplyStyleCommand::applyInlineStyleChange(PassRefPtrWillBeRawPtr<Node> pass
edStart, PassRefPtrWillBeRawPtr<Node> passedEnd, StyleChange& styleChange, EAddS
tyledElement addStyledElement, EditingState* editingState) | 1551 void ApplyStyleCommand::applyInlineStyleChange(RawPtr<Node> passedStart, RawPtr<
Node> passedEnd, StyleChange& styleChange, EAddStyledElement addStyledElement, E
ditingState* editingState) |
| 1552 { | 1552 { |
| 1553 RefPtrWillBeRawPtr<Node> startNode = passedStart; | 1553 RawPtr<Node> startNode = passedStart; |
| 1554 RefPtrWillBeRawPtr<Node> endNode = passedEnd; | 1554 RawPtr<Node> endNode = passedEnd; |
| 1555 ASSERT(startNode->inDocument()); | 1555 ASSERT(startNode->inDocument()); |
| 1556 ASSERT(endNode->inDocument()); | 1556 ASSERT(endNode->inDocument()); |
| 1557 | 1557 |
| 1558 // Find appropriate font and span elements top-down. | 1558 // Find appropriate font and span elements top-down. |
| 1559 HTMLFontElement* fontContainer = nullptr; | 1559 HTMLFontElement* fontContainer = nullptr; |
| 1560 HTMLElement* styleContainer = nullptr; | 1560 HTMLElement* styleContainer = nullptr; |
| 1561 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { | 1561 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { |
| 1562 if (isHTMLFontElement(*container)) | 1562 if (isHTMLFontElement(*container)) |
| 1563 fontContainer = toHTMLFontElement(container); | 1563 fontContainer = toHTMLFontElement(container); |
| 1564 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); | 1564 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1576 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. | 1576 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. |
| 1577 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { | 1577 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { |
| 1578 if (fontContainer) { | 1578 if (fontContainer) { |
| 1579 if (styleChange.applyFontColor()) | 1579 if (styleChange.applyFontColor()) |
| 1580 setNodeAttribute(fontContainer, colorAttr, AtomicString(styleCha
nge.fontColor())); | 1580 setNodeAttribute(fontContainer, colorAttr, AtomicString(styleCha
nge.fontColor())); |
| 1581 if (styleChange.applyFontFace()) | 1581 if (styleChange.applyFontFace()) |
| 1582 setNodeAttribute(fontContainer, faceAttr, AtomicString(styleChan
ge.fontFace())); | 1582 setNodeAttribute(fontContainer, faceAttr, AtomicString(styleChan
ge.fontFace())); |
| 1583 if (styleChange.applyFontSize()) | 1583 if (styleChange.applyFontSize()) |
| 1584 setNodeAttribute(fontContainer, sizeAttr, AtomicString(styleChan
ge.fontSize())); | 1584 setNodeAttribute(fontContainer, sizeAttr, AtomicString(styleChan
ge.fontSize())); |
| 1585 } else { | 1585 } else { |
| 1586 RefPtrWillBeRawPtr<HTMLFontElement> fontElement = HTMLFontElement::c
reate(document()); | 1586 RawPtr<HTMLFontElement> fontElement = HTMLFontElement::create(docume
nt()); |
| 1587 if (styleChange.applyFontColor()) | 1587 if (styleChange.applyFontColor()) |
| 1588 fontElement->setAttribute(colorAttr, AtomicString(styleChange.fo
ntColor())); | 1588 fontElement->setAttribute(colorAttr, AtomicString(styleChange.fo
ntColor())); |
| 1589 if (styleChange.applyFontFace()) | 1589 if (styleChange.applyFontFace()) |
| 1590 fontElement->setAttribute(faceAttr, AtomicString(styleChange.fon
tFace())); | 1590 fontElement->setAttribute(faceAttr, AtomicString(styleChange.fon
tFace())); |
| 1591 if (styleChange.applyFontSize()) | 1591 if (styleChange.applyFontSize()) |
| 1592 fontElement->setAttribute(sizeAttr, AtomicString(styleChange.fon
tSize())); | 1592 fontElement->setAttribute(sizeAttr, AtomicString(styleChange.fon
tSize())); |
| 1593 surroundNodeRangeWithElement(startNode, endNode, fontElement.get(),
editingState); | 1593 surroundNodeRangeWithElement(startNode, endNode, fontElement.get(),
editingState); |
| 1594 if (editingState->isAborted()) | 1594 if (editingState->isAborted()) |
| 1595 return; | 1595 return; |
| 1596 } | 1596 } |
| 1597 } | 1597 } |
| 1598 | 1598 |
| 1599 if (styleChange.cssStyle().length()) { | 1599 if (styleChange.cssStyle().length()) { |
| 1600 if (styleContainer) { | 1600 if (styleContainer) { |
| 1601 if (const StylePropertySet* existingStyle = styleContainer->inlineSt
yle()) { | 1601 if (const StylePropertySet* existingStyle = styleContainer->inlineSt
yle()) { |
| 1602 String existingText = existingStyle->asText(); | 1602 String existingText = existingStyle->asText(); |
| 1603 StringBuilder cssText; | 1603 StringBuilder cssText; |
| 1604 cssText.append(existingText); | 1604 cssText.append(existingText); |
| 1605 if (!existingText.isEmpty()) | 1605 if (!existingText.isEmpty()) |
| 1606 cssText.append(' '); | 1606 cssText.append(' '); |
| 1607 cssText.append(styleChange.cssStyle()); | 1607 cssText.append(styleChange.cssStyle()); |
| 1608 setNodeAttribute(styleContainer, styleAttr, cssText.toAtomicStri
ng()); | 1608 setNodeAttribute(styleContainer, styleAttr, cssText.toAtomicStri
ng()); |
| 1609 } else { | 1609 } else { |
| 1610 setNodeAttribute(styleContainer, styleAttr, AtomicString(styleCh
ange.cssStyle())); | 1610 setNodeAttribute(styleContainer, styleAttr, AtomicString(styleCh
ange.cssStyle())); |
| 1611 } | 1611 } |
| 1612 } else { | 1612 } else { |
| 1613 RefPtrWillBeRawPtr<HTMLSpanElement> styleElement = HTMLSpanElement::
create(document()); | 1613 RawPtr<HTMLSpanElement> styleElement = HTMLSpanElement::create(docum
ent()); |
| 1614 styleElement->setAttribute(styleAttr, AtomicString(styleChange.cssSt
yle())); | 1614 styleElement->setAttribute(styleAttr, AtomicString(styleChange.cssSt
yle())); |
| 1615 surroundNodeRangeWithElement(startNode, endNode, styleElement.releas
e(), editingState); | 1615 surroundNodeRangeWithElement(startNode, endNode, styleElement.releas
e(), editingState); |
| 1616 if (editingState->isAborted()) | 1616 if (editingState->isAborted()) |
| 1617 return; | 1617 return; |
| 1618 } | 1618 } |
| 1619 } | 1619 } |
| 1620 | 1620 |
| 1621 if (styleChange.applyBold()) { | 1621 if (styleChange.applyBold()) { |
| 1622 surroundNodeRangeWithElement(startNode, endNode, HTMLElement::create(bTa
g, document()), editingState); | 1622 surroundNodeRangeWithElement(startNode, endNode, HTMLElement::create(bTa
g, document()), editingState); |
| 1623 if (editingState->isAborted()) | 1623 if (editingState->isAborted()) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1654 | 1654 |
| 1655 if (m_styledInlineElement && addStyledElement == AddStyledElement) | 1655 if (m_styledInlineElement && addStyledElement == AddStyledElement) |
| 1656 surroundNodeRangeWithElement(startNode, endNode, m_styledInlineElement->
cloneElementWithoutChildren(), editingState); | 1656 surroundNodeRangeWithElement(startNode, endNode, m_styledInlineElement->
cloneElementWithoutChildren(), editingState); |
| 1657 } | 1657 } |
| 1658 | 1658 |
| 1659 float ApplyStyleCommand::computedFontSize(Node* node) | 1659 float ApplyStyleCommand::computedFontSize(Node* node) |
| 1660 { | 1660 { |
| 1661 if (!node) | 1661 if (!node) |
| 1662 return 0; | 1662 return 0; |
| 1663 | 1663 |
| 1664 RefPtrWillBeRawPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDecl
aration::create(node); | 1664 RawPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::cre
ate(node); |
| 1665 if (!style) | 1665 if (!style) |
| 1666 return 0; | 1666 return 0; |
| 1667 | 1667 |
| 1668 RefPtrWillBeRawPtr<CSSPrimitiveValue> value = static_pointer_cast<CSSPrimiti
veValue>(style->getPropertyCSSValue(CSSPropertyFontSize)); | 1668 RawPtr<CSSPrimitiveValue> value = static_pointer_cast<CSSPrimitiveValue>(sty
le->getPropertyCSSValue(CSSPropertyFontSize)); |
| 1669 if (!value) | 1669 if (!value) |
| 1670 return 0; | 1670 return 0; |
| 1671 | 1671 |
| 1672 ASSERT(value->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::Pixels)
; | 1672 ASSERT(value->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::Pixels)
; |
| 1673 return value->getFloatValue(); | 1673 return value->getFloatValue(); |
| 1674 } | 1674 } |
| 1675 | 1675 |
| 1676 void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position&
start, const Position& end) | 1676 void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position&
start, const Position& end) |
| 1677 { | 1677 { |
| 1678 if (!node) | 1678 if (!node) |
| 1679 return; | 1679 return; |
| 1680 | 1680 |
| 1681 Position newStart = start; | 1681 Position newStart = start; |
| 1682 Position newEnd = end; | 1682 Position newEnd = end; |
| 1683 | 1683 |
| 1684 WillBeHeapVector<RefPtrWillBeMember<Text>> textNodes; | 1684 HeapVector<Member<Text>> textNodes; |
| 1685 for (Node* curr = node->firstChild(); curr; curr = curr->nextSibling()) { | 1685 for (Node* curr = node->firstChild(); curr; curr = curr->nextSibling()) { |
| 1686 if (!curr->isTextNode()) | 1686 if (!curr->isTextNode()) |
| 1687 continue; | 1687 continue; |
| 1688 | 1688 |
| 1689 textNodes.append(toText(curr)); | 1689 textNodes.append(toText(curr)); |
| 1690 } | 1690 } |
| 1691 | 1691 |
| 1692 for (const auto& textNode : textNodes) { | 1692 for (const auto& textNode : textNodes) { |
| 1693 Text* childText = textNode.get(); | 1693 Text* childText = textNode.get(); |
| 1694 Node* next = childText->nextSibling(); | 1694 Node* next = childText->nextSibling(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1713 DEFINE_TRACE(ApplyStyleCommand) | 1713 DEFINE_TRACE(ApplyStyleCommand) |
| 1714 { | 1714 { |
| 1715 visitor->trace(m_style); | 1715 visitor->trace(m_style); |
| 1716 visitor->trace(m_start); | 1716 visitor->trace(m_start); |
| 1717 visitor->trace(m_end); | 1717 visitor->trace(m_end); |
| 1718 visitor->trace(m_styledInlineElement); | 1718 visitor->trace(m_styledInlineElement); |
| 1719 CompositeEditCommand::trace(visitor); | 1719 CompositeEditCommand::trace(visitor); |
| 1720 } | 1720 } |
| 1721 | 1721 |
| 1722 } // namespace blink | 1722 } // namespace blink |
| OLD | NEW |