| 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(propertyLevel) | 133 , m_propertyLevel(propertyLevel) |
| 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, EditAction editingAction) | 143 ApplyStyleCommand::ApplyStyleCommand(RawPtr<Element> element, bool removeOnly, E
ditAction editingAction) |
| 144 : CompositeEditCommand(element->document()) | 144 : CompositeEditCommand(element->document()) |
| 145 , m_style(EditingStyle::create()) | 145 , m_style(EditingStyle::create()) |
| 146 , m_editingAction(editingAction) | 146 , m_editingAction(editingAction) |
| 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() | 199 void ApplyStyleCommand::doApply() |
| 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()); | 206 applyBlockStyle(blockStyle.get()); |
| 207 // Apply any remaining styles to the inline elements. | 207 // Apply any remaining styles to the inline elements. |
| 208 if (!m_style->isEmpty() || m_styledInlineElement || m_isInlineElementToR
emoveFunction) { | 208 if (!m_style->isEmpty() || m_styledInlineElement || m_isInlineElementToR
emoveFunction) { |
| 209 applyRelativeFontStyleChange(m_style.get()); | 209 applyRelativeFontStyleChange(m_style.get()); |
| 210 applyInlineStyle(m_style.get()); | 210 applyInlineStyle(m_style.get()); |
| 211 } | 211 } |
| 212 break; | 212 break; |
| 213 } | 213 } |
| 214 case ForceBlockProperties: | 214 case ForceBlockProperties: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 242 VisiblePosition visibleStart = createVisiblePosition(start); | 242 VisiblePosition visibleStart = createVisiblePosition(start); |
| 243 VisiblePosition visibleEnd = createVisiblePosition(end); | 243 VisiblePosition visibleEnd = createVisiblePosition(end); |
| 244 | 244 |
| 245 if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull()
|| visibleEnd.isOrphan()) | 245 if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull()
|| visibleEnd.isOrphan()) |
| 246 return; | 246 return; |
| 247 | 247 |
| 248 // Save and restore the selection endpoints using their indices in the docum
ent, since | 248 // Save and restore the selection endpoints using their indices in the docum
ent, since |
| 249 // addBlockStyleIfNeeded may moveParagraphs, which can remove these endpoint
s. | 249 // addBlockStyleIfNeeded may moveParagraphs, which can remove these endpoint
s. |
| 250 // Calculate start and end indices from the start of the tree that they're i
n. | 250 // Calculate start and end indices from the start of the tree that they're i
n. |
| 251 Node& scope = NodeTraversal::highestAncestorOrSelf(*visibleStart.deepEquival
ent().anchorNode()); | 251 Node& scope = NodeTraversal::highestAncestorOrSelf(*visibleStart.deepEquival
ent().anchorNode()); |
| 252 RefPtrWillBeRawPtr<Range> startRange = Range::create(document(), firstPositi
onInNode(&scope), visibleStart.deepEquivalent().parentAnchoredEquivalent()); | 252 RawPtr<Range> startRange = Range::create(document(), firstPositionInNode(&sc
ope), visibleStart.deepEquivalent().parentAnchoredEquivalent()); |
| 253 RefPtrWillBeRawPtr<Range> endRange = Range::create(document(), firstPosition
InNode(&scope), visibleEnd.deepEquivalent().parentAnchoredEquivalent()); | 253 RawPtr<Range> endRange = Range::create(document(), firstPositionInNode(&scop
e), visibleEnd.deepEquivalent().parentAnchoredEquivalent()); |
| 254 int startIndex = TextIterator::rangeLength(startRange->startPosition(), star
tRange->endPosition(), true); | 254 int startIndex = TextIterator::rangeLength(startRange->startPosition(), star
tRange->endPosition(), true); |
| 255 int endIndex = TextIterator::rangeLength(endRange->startPosition(), endRange
->endPosition(), true); | 255 int endIndex = TextIterator::rangeLength(endRange->startPosition(), endRange
->endPosition(), true); |
| 256 | 256 |
| 257 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); | 257 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); |
| 258 VisiblePosition nextParagraphStart(nextPositionOf(endOfParagraph(paragraphSt
art))); | 258 VisiblePosition nextParagraphStart(nextPositionOf(endOfParagraph(paragraphSt
art))); |
| 259 VisiblePosition beyondEnd(nextPositionOf(endOfParagraph(visibleEnd))); | 259 VisiblePosition beyondEnd(nextPositionOf(endOfParagraph(visibleEnd))); |
| 260 while (paragraphStart.isNotNull() && paragraphStart.deepEquivalent() != beyo
ndEnd.deepEquivalent()) { | 260 while (paragraphStart.isNotNull() && paragraphStart.deepEquivalent() != beyo
ndEnd.deepEquivalent()) { |
| 261 StyleChange styleChange(style, paragraphStart.deepEquivalent()); | 261 StyleChange styleChange(style, paragraphStart.deepEquivalent()); |
| 262 if (styleChange.cssStyle().length() || m_removeOnly) { | 262 if (styleChange.cssStyle().length() || m_removeOnly) { |
| 263 RefPtrWillBeRawPtr<Element> block = enclosingBlock(paragraphStart.de
epEquivalent().anchorNode()); | 263 RawPtr<Element> block = enclosingBlock(paragraphStart.deepEquivalent
().anchorNode()); |
| 264 const Position& paragraphStartToMove = paragraphStart.deepEquivalent
(); | 264 const Position& paragraphStartToMove = paragraphStart.deepEquivalent
(); |
| 265 if (!m_removeOnly && isEditablePosition(paragraphStartToMove)) { | 265 if (!m_removeOnly && isEditablePosition(paragraphStartToMove)) { |
| 266 RefPtrWillBeRawPtr<HTMLElement> newBlock = moveParagraphContents
ToNewBlockIfNecessary(paragraphStartToMove); | 266 RawPtr<HTMLElement> newBlock = moveParagraphContentsToNewBlockIf
Necessary(paragraphStartToMove); |
| 267 if (newBlock) | 267 if (newBlock) |
| 268 block = newBlock; | 268 block = newBlock; |
| 269 } | 269 } |
| 270 if (block && block->isHTMLElement()) { | 270 if (block && block->isHTMLElement()) { |
| 271 removeCSSStyle(style, toHTMLElement(block)); | 271 removeCSSStyle(style, toHTMLElement(block)); |
| 272 if (!m_removeOnly) | 272 if (!m_removeOnly) |
| 273 addBlockStyle(styleChange, toHTMLElement(block)); | 273 addBlockStyle(styleChange, toHTMLElement(block)); |
| 274 } | 274 } |
| 275 | 275 |
| 276 if (nextParagraphStart.isOrphan()) | 276 if (nextParagraphStart.isOrphan()) |
| 277 nextParagraphStart = nextPositionOf(endOfParagraph(paragraphStar
t)); | 277 nextParagraphStart = nextPositionOf(endOfParagraph(paragraphStar
t)); |
| 278 } | 278 } |
| 279 | 279 |
| 280 paragraphStart = nextParagraphStart; | 280 paragraphStart = nextParagraphStart; |
| 281 nextParagraphStart = nextPositionOf(endOfParagraph(paragraphStart)); | 281 nextParagraphStart = nextPositionOf(endOfParagraph(paragraphStart)); |
| 282 } | 282 } |
| 283 | 283 |
| 284 EphemeralRange startEphemeralRange = PlainTextRange(startIndex).createRangeF
orSelection(toContainerNode(scope)); | 284 EphemeralRange startEphemeralRange = PlainTextRange(startIndex).createRangeF
orSelection(toContainerNode(scope)); |
| 285 if (startEphemeralRange.isNull()) | 285 if (startEphemeralRange.isNull()) |
| 286 return; | 286 return; |
| 287 EphemeralRange endEphemeralRange = PlainTextRange(endIndex).createRangeForSe
lection(toContainerNode(scope)); | 287 EphemeralRange endEphemeralRange = PlainTextRange(endIndex).createRangeForSe
lection(toContainerNode(scope)); |
| 288 if (endEphemeralRange.isNull()) | 288 if (endEphemeralRange.isNull()) |
| 289 return; | 289 return; |
| 290 updateStartEnd(startEphemeralRange.startPosition(), endEphemeralRange.startP
osition()); | 290 updateStartEnd(startEphemeralRange.startPosition(), endEphemeralRange.startP
osition()); |
| 291 } | 291 } |
| 292 | 292 |
| 293 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyStyleOrCreateEmpty(co
nst StylePropertySet* style) | 293 static RawPtr<MutableStylePropertySet> copyStyleOrCreateEmpty(const StylePropert
ySet* style) |
| 294 { | 294 { |
| 295 if (!style) | 295 if (!style) |
| 296 return MutableStylePropertySet::create(HTMLQuirksMode); | 296 return MutableStylePropertySet::create(HTMLQuirksMode); |
| 297 return style->mutableCopy(); | 297 return style->mutableCopy(); |
| 298 } | 298 } |
| 299 | 299 |
| 300 void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style) | 300 void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style) |
| 301 { | 301 { |
| 302 static const float MinimumFontSize = 0.1f; | 302 static const float MinimumFontSize = 0.1f; |
| 303 | 303 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 | 366 |
| 367 if (startNode->isTextNode() && start.computeOffsetInContainerNode() >= caret
MaxOffset(startNode)) { | 367 if (startNode->isTextNode() && start.computeOffsetInContainerNode() >= caret
MaxOffset(startNode)) { |
| 368 // Move out of text node if range does not include its characters. | 368 // Move out of text node if range does not include its characters. |
| 369 startNode = NodeTraversal::next(*startNode); | 369 startNode = NodeTraversal::next(*startNode); |
| 370 if (!startNode) | 370 if (!startNode) |
| 371 return; | 371 return; |
| 372 } | 372 } |
| 373 | 373 |
| 374 // Store away font size before making any changes to the document. | 374 // Store away font size before making any changes to the document. |
| 375 // This ensures that changes to one node won't effect another. | 375 // This ensures that changes to one node won't effect another. |
| 376 WillBeHeapHashMap<RawPtrWillBeMember<Node>, float> startingFontSizes; | 376 HeapHashMap<Member<Node>, float> startingFontSizes; |
| 377 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(*
node)) { | 377 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(*
node)) { |
| 378 ASSERT(node); | 378 ASSERT(node); |
| 379 startingFontSizes.set(node, computedFontSize(node)); | 379 startingFontSizes.set(node, computedFontSize(node)); |
| 380 } | 380 } |
| 381 | 381 |
| 382 // These spans were added by us. If empty after font size changes, they can
be removed. | 382 // These spans were added by us. If empty after font size changes, they can
be removed. |
| 383 WillBeHeapVector<RefPtrWillBeMember<HTMLElement>> unstyledSpans; | 383 HeapVector<Member<HTMLElement>> unstyledSpans; |
| 384 | 384 |
| 385 Node* lastStyledNode = nullptr; | 385 Node* lastStyledNode = nullptr; |
| 386 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(*
node)) { | 386 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(*
node)) { |
| 387 ASSERT(node); | 387 ASSERT(node); |
| 388 RefPtrWillBeRawPtr<HTMLElement> element = nullptr; | 388 RawPtr<HTMLElement> element = nullptr; |
| 389 if (node->isHTMLElement()) { | 389 if (node->isHTMLElement()) { |
| 390 // Only work on fully selected nodes. | 390 // Only work on fully selected nodes. |
| 391 if (!elementFullySelected(toHTMLElement(*node), start, end)) | 391 if (!elementFullySelected(toHTMLElement(*node), start, end)) |
| 392 continue; | 392 continue; |
| 393 element = toHTMLElement(node); | 393 element = toHTMLElement(node); |
| 394 } else if (node->isTextNode() && node->layoutObject() && node->parentNod
e() != lastStyledNode) { | 394 } else if (node->isTextNode() && node->layoutObject() && node->parentNod
e() != lastStyledNode) { |
| 395 // Last styled node was not parent node of this text node, but we wi
sh to style this | 395 // Last styled node was not parent node of this text node, but we wi
sh to style this |
| 396 // text node. To make this possible, add a style span to surround th
is text node. | 396 // text node. To make this possible, add a style span to surround th
is text node. |
| 397 RefPtrWillBeRawPtr<HTMLSpanElement> span = HTMLSpanElement::create(d
ocument()); | 397 RawPtr<HTMLSpanElement> span = HTMLSpanElement::create(document()); |
| 398 surroundNodeRangeWithElement(node, node, span.get()); | 398 surroundNodeRangeWithElement(node, node, span.get()); |
| 399 element = span.release(); | 399 element = span.release(); |
| 400 } else { | 400 } else { |
| 401 // Only handle HTML elements and text nodes. | 401 // Only handle HTML elements and text nodes. |
| 402 continue; | 402 continue; |
| 403 } | 403 } |
| 404 lastStyledNode = node; | 404 lastStyledNode = node; |
| 405 | 405 |
| 406 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCre
ateEmpty(element->inlineStyle()); | 406 RawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty(ele
ment->inlineStyle()); |
| 407 float currentFontSize = computedFontSize(node); | 407 float currentFontSize = computedFontSize(node); |
| 408 float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node)
+ style->fontSizeDelta()); | 408 float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node)
+ style->fontSizeDelta()); |
| 409 RefPtrWillBeRawPtr<CSSValue> value = inlineStyle->getPropertyCSSValue(CS
SPropertyFontSize); | 409 RawPtr<CSSValue> value = inlineStyle->getPropertyCSSValue(CSSPropertyFon
tSize); |
| 410 if (value) { | 410 if (value) { |
| 411 element->removeInlineStyleProperty(CSSPropertyFontSize); | 411 element->removeInlineStyleProperty(CSSPropertyFontSize); |
| 412 currentFontSize = computedFontSize(node); | 412 currentFontSize = computedFontSize(node); |
| 413 } | 413 } |
| 414 if (currentFontSize != desiredFontSize) { | 414 if (currentFontSize != desiredFontSize) { |
| 415 inlineStyle->setProperty(CSSPropertyFontSize, cssValuePool().createV
alue(desiredFontSize, CSSPrimitiveValue::UnitType::Pixels), false); | 415 inlineStyle->setProperty(CSSPropertyFontSize, cssValuePool().createV
alue(desiredFontSize, CSSPrimitiveValue::UnitType::Pixels), false); |
| 416 setNodeAttribute(element.get(), styleAttr, AtomicString(inlineStyle-
>asText())); | 416 setNodeAttribute(element.get(), styleAttr, AtomicString(inlineStyle-
>asText())); |
| 417 } | 417 } |
| 418 if (inlineStyle->isEmpty()) { | 418 if (inlineStyle->isEmpty()) { |
| 419 removeElementAttribute(element.get(), styleAttr); | 419 removeElementAttribute(element.get(), styleAttr); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 && EditingStyle::create(highestAncestorWithUnicodeBidi, EditingStyle::Al
lProperties)->textDirection(highestAncestorDirection) | 483 && EditingStyle::create(highestAncestorWithUnicodeBidi, EditingStyle::Al
lProperties)->textDirection(highestAncestorDirection) |
| 484 && highestAncestorDirection == allowedDirection) { | 484 && highestAncestorDirection == allowedDirection) { |
| 485 if (!nextHighestAncestorWithUnicodeBidi) | 485 if (!nextHighestAncestorWithUnicodeBidi) |
| 486 return toHTMLElement(highestAncestorWithUnicodeBidi); | 486 return toHTMLElement(highestAncestorWithUnicodeBidi); |
| 487 | 487 |
| 488 unsplitAncestor = toHTMLElement(highestAncestorWithUnicodeBidi); | 488 unsplitAncestor = toHTMLElement(highestAncestorWithUnicodeBidi); |
| 489 highestAncestorWithUnicodeBidi = nextHighestAncestorWithUnicodeBidi; | 489 highestAncestorWithUnicodeBidi = nextHighestAncestorWithUnicodeBidi; |
| 490 } | 490 } |
| 491 | 491 |
| 492 // Split every ancestor through highest ancestor with embedding. | 492 // Split every ancestor through highest ancestor with embedding. |
| 493 RefPtrWillBeRawPtr<Node> currentNode = node; | 493 RawPtr<Node> currentNode = node; |
| 494 while (currentNode) { | 494 while (currentNode) { |
| 495 RefPtrWillBeRawPtr<Element> parent = toElement(currentNode->parentNode()
); | 495 RawPtr<Element> parent = toElement(currentNode->parentNode()); |
| 496 if (before ? currentNode->previousSibling() : currentNode->nextSibling()
) | 496 if (before ? currentNode->previousSibling() : currentNode->nextSibling()
) |
| 497 splitElement(parent, before ? currentNode.get() : currentNode->nextS
ibling()); | 497 splitElement(parent, before ? currentNode.get() : currentNode->nextS
ibling()); |
| 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(Node* node, HTMLElemen
t* unsplitAncestor) | 505 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, HTMLElemen
t* unsplitAncestor) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 519 | 519 |
| 520 // FIXME: This code should really consider the mapped attribute 'dir', t
he inline style declaration, | 520 // FIXME: This code should really consider the mapped attribute 'dir', t
he inline style declaration, |
| 521 // and all matching style rules in order to determine how to best set th
e unicode-bidi property to 'normal'. | 521 // and all matching style rules in order to determine how to best set th
e unicode-bidi property to 'normal'. |
| 522 // For now, it assumes that if the 'dir' attribute is present, then remo
ving it will suffice, and | 522 // For now, it assumes that if the 'dir' attribute is present, then remo
ving it will suffice, and |
| 523 // otherwise it sets the property in the inline style declaration. | 523 // otherwise it sets the property in the inline style declaration. |
| 524 if (element->hasAttribute(dirAttr)) { | 524 if (element->hasAttribute(dirAttr)) { |
| 525 // FIXME: If this is a BDO element, we should probably just remove i
t if it has no | 525 // FIXME: If this is a BDO element, we should probably just remove i
t if it has no |
| 526 // other attributes, like we (should) do with B and I elements. | 526 // other attributes, like we (should) do with B and I elements. |
| 527 removeElementAttribute(element, dirAttr); | 527 removeElementAttribute(element, dirAttr); |
| 528 } else { | 528 } else { |
| 529 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); | 529 RawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty
(element->inlineStyle()); |
| 530 inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); | 530 inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); |
| 531 inlineStyle->removeProperty(CSSPropertyDirection); | 531 inlineStyle->removeProperty(CSSPropertyDirection); |
| 532 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); | 532 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); |
| 533 if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) | 533 if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) |
| 534 removeNodePreservingChildren(element); | 534 removeNodePreservingChildren(element); |
| 535 } | 535 } |
| 536 } | 536 } |
| 537 } | 537 } |
| 538 | 538 |
| 539 static HTMLElement* highestEmbeddingAncestor(Node* startNode, Node* enclosingNod
e) | 539 static HTMLElement* highestEmbeddingAncestor(Node* startNode, Node* enclosingNod
e) |
| 540 { | 540 { |
| 541 for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { | 541 for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { |
| 542 if (n->isHTMLElement() | 542 if (n->isHTMLElement() |
| 543 && EditingStyle::isEmbedOrIsolate(getIdentifierValue(CSSComputedStyl
eDeclaration::create(n).get(), CSSPropertyUnicodeBidi))) { | 543 && EditingStyle::isEmbedOrIsolate(getIdentifierValue(CSSComputedStyl
eDeclaration::create(n).get(), CSSPropertyUnicodeBidi))) { |
| 544 return toHTMLElement(n); | 544 return toHTMLElement(n); |
| 545 } | 545 } |
| 546 } | 546 } |
| 547 | 547 |
| 548 return 0; | 548 return 0; |
| 549 } | 549 } |
| 550 | 550 |
| 551 void ApplyStyleCommand::applyInlineStyle(EditingStyle* style) | 551 void ApplyStyleCommand::applyInlineStyle(EditingStyle* style) |
| 552 { | 552 { |
| 553 RefPtrWillBeRawPtr<ContainerNode> startDummySpanAncestor = nullptr; | 553 RawPtr<ContainerNode> startDummySpanAncestor = nullptr; |
| 554 RefPtrWillBeRawPtr<ContainerNode> endDummySpanAncestor = nullptr; | 554 RawPtr<ContainerNode> endDummySpanAncestor = nullptr; |
| 555 | 555 |
| 556 // update document layout once before removing styles | 556 // update document layout once before removing styles |
| 557 // so that we avoid the expense of updating before each and every call | 557 // so that we avoid the expense of updating before each and every call |
| 558 // to check a computed style | 558 // to check a computed style |
| 559 document().updateLayoutIgnorePendingStylesheets(); | 559 document().updateLayoutIgnorePendingStylesheets(); |
| 560 | 560 |
| 561 // adjust to the positions we want to use for applying style | 561 // adjust to the positions we want to use for applying style |
| 562 Position start = startPosition(); | 562 Position start = startPosition(); |
| 563 Position end = endPosition(); | 563 Position end = endPosition(); |
| 564 | 564 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 } | 600 } |
| 601 | 601 |
| 602 // Remove style from the selection. | 602 // Remove style from the selection. |
| 603 // Use the upstream position of the start for removing style. | 603 // Use the upstream position of the start for removing style. |
| 604 // This will ensure we remove all traces of the relevant styles from the sel
ection | 604 // This will ensure we remove all traces of the relevant styles from the sel
ection |
| 605 // and prevent us from adding redundant ones, as described in: | 605 // and prevent us from adding redundant ones, as described in: |
| 606 // <rdar://problem/3724344> Bolding and unbolding creates extraneous tags | 606 // <rdar://problem/3724344> Bolding and unbolding creates extraneous tags |
| 607 Position removeStart = mostBackwardCaretPosition(start); | 607 Position removeStart = mostBackwardCaretPosition(start); |
| 608 WritingDirection textDirection = NaturalWritingDirection; | 608 WritingDirection textDirection = NaturalWritingDirection; |
| 609 bool hasTextDirection = style->textDirection(textDirection); | 609 bool hasTextDirection = style->textDirection(textDirection); |
| 610 RefPtrWillBeRawPtr<EditingStyle> styleWithoutEmbedding = nullptr; | 610 RawPtr<EditingStyle> styleWithoutEmbedding = nullptr; |
| 611 RefPtrWillBeRawPtr<EditingStyle> embeddingStyle = nullptr; | 611 RawPtr<EditingStyle> embeddingStyle = nullptr; |
| 612 if (hasTextDirection) { | 612 if (hasTextDirection) { |
| 613 // Leave alone an ancestor that provides the desired single level embedd
ing, if there is one. | 613 // Leave alone an ancestor that provides the desired single level embedd
ing, if there is one. |
| 614 HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.
anchorNode(), true, textDirection); | 614 HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.
anchorNode(), true, textDirection); |
| 615 HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.anch
orNode(), false, textDirection); | 615 HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.anch
orNode(), false, textDirection); |
| 616 removeEmbeddingUpToEnclosingBlock(start.anchorNode(), startUnsplitAncest
or); | 616 removeEmbeddingUpToEnclosingBlock(start.anchorNode(), startUnsplitAncest
or); |
| 617 removeEmbeddingUpToEnclosingBlock(end.anchorNode(), endUnsplitAncestor); | 617 removeEmbeddingUpToEnclosingBlock(end.anchorNode(), endUnsplitAncestor); |
| 618 | 618 |
| 619 // Avoid removing the dir attribute and the unicode-bidi and direction p
roperties from the unsplit ancestors. | 619 // Avoid removing the dir attribute and the unicode-bidi and direction p
roperties from the unsplit ancestors. |
| 620 Position embeddingRemoveStart = removeStart; | 620 Position embeddingRemoveStart = removeStart; |
| 621 if (startUnsplitAncestor && elementFullySelected(*startUnsplitAncestor,
removeStart, end)) | 621 if (startUnsplitAncestor && elementFullySelected(*startUnsplitAncestor,
removeStart, end)) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 649 mergeEndWithNextIfIdentical(start, end); | 649 mergeEndWithNextIfIdentical(start, end); |
| 650 start = startPosition(); | 650 start = startPosition(); |
| 651 end = endPosition(); | 651 end = endPosition(); |
| 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 RefPtrWillBeRawPtr<EditingStyle> styleToApply = style; | 659 RawPtr<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 HTMLElement* embeddingStartElement = highestEmbeddingAncestor(start.anch
orNode(), enclosingBlock(start.anchorNode())); | 662 HTMLElement* embeddingStartElement = highestEmbeddingAncestor(start.anch
orNode(), enclosingBlock(start.anchorNode())); |
| 663 HTMLElement* embeddingEndElement = highestEmbeddingAncestor(end.anchorNo
de(), enclosingBlock(end.anchorNode())); | 663 HTMLElement* embeddingEndElement = highestEmbeddingAncestor(end.anchorNo
de(), enclosingBlock(end.anchorNode())); |
| 664 | 664 |
| 665 if (embeddingStartElement || embeddingEndElement) { | 665 if (embeddingStartElement || embeddingEndElement) { |
| 666 Position embeddingApplyStart = embeddingStartElement ? positionInPar
entAfterNode(*embeddingStartElement) : start; | 666 Position embeddingApplyStart = embeddingStartElement ? positionInPar
entAfterNode(*embeddingStartElement) : start; |
| 667 Position embeddingApplyEnd = embeddingEndElement ? positionInParentB
eforeNode(*embeddingEndElement) : end; | 667 Position embeddingApplyEnd = embeddingEndElement ? positionInParentB
eforeNode(*embeddingEndElement) : end; |
| 668 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul
l()); | 668 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul
l()); |
| 669 | 669 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 pastEndNode = NodeTraversal::nextSkippingChildren(*end.anchorNode()); | 701 pastEndNode = NodeTraversal::nextSkippingChildren(*end.anchorNode()); |
| 702 | 702 |
| 703 // FIXME: Callers should perform this operation on a Range that includes the
br | 703 // FIXME: Callers should perform this operation on a Range that includes the
br |
| 704 // if they want style applied to the empty line. | 704 // if they want style applied to the empty line. |
| 705 if (start == end && isHTMLBRElement(*start.anchorNode())) | 705 if (start == end && isHTMLBRElement(*start.anchorNode())) |
| 706 pastEndNode = NodeTraversal::next(*start.anchorNode()); | 706 pastEndNode = NodeTraversal::next(*start.anchorNode()); |
| 707 | 707 |
| 708 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. | 708 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. |
| 709 // 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 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run |
| 710 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> | 710 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> |
| 711 RefPtrWillBeRawPtr<Range> range = Range::create(startNode->document(), start
, end); | 711 RawPtr<Range> range = Range::create(startNode->document(), start, end); |
| 712 Element* editableRoot = startNode->rootEditableElement(); | 712 Element* editableRoot = startNode->rootEditableElement(); |
| 713 if (startNode != editableRoot) { | 713 if (startNode != editableRoot) { |
| 714 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(*startNode->parentNode(), *range)) | 714 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(*startNode->parentNode(), *range)) |
| 715 startNode = startNode->parentNode(); | 715 startNode = startNode->parentNode(); |
| 716 } | 716 } |
| 717 | 717 |
| 718 applyInlineStyleToNodeRange(style, startNode, pastEndNode); | 718 applyInlineStyleToNodeRange(style, startNode, pastEndNode); |
| 719 } | 719 } |
| 720 | 720 |
| 721 static bool containsNonEditableRegion(Node& node) | 721 static bool containsNonEditableRegion(Node& node) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 750 | 750 |
| 751 DEFINE_INLINE_TRACE() | 751 DEFINE_INLINE_TRACE() |
| 752 { | 752 { |
| 753 visitor->trace(start); | 753 visitor->trace(start); |
| 754 visitor->trace(end); | 754 visitor->trace(end); |
| 755 visitor->trace(pastEndNode); | 755 visitor->trace(pastEndNode); |
| 756 visitor->trace(positionForStyleComputation); | 756 visitor->trace(positionForStyleComputation); |
| 757 visitor->trace(dummyElement); | 757 visitor->trace(dummyElement); |
| 758 } | 758 } |
| 759 | 759 |
| 760 RefPtrWillBeMember<Node> start; | 760 Member<Node> start; |
| 761 RefPtrWillBeMember<Node> end; | 761 Member<Node> end; |
| 762 RefPtrWillBeMember<Node> pastEndNode; | 762 Member<Node> pastEndNode; |
| 763 Position positionForStyleComputation; | 763 Position positionForStyleComputation; |
| 764 RefPtrWillBeMember<HTMLSpanElement> dummyElement; | 764 Member<HTMLSpanElement> dummyElement; |
| 765 StyleChange change; | 765 StyleChange change; |
| 766 }; | 766 }; |
| 767 | 767 |
| 768 } // namespace blink | 768 } // namespace blink |
| 769 | 769 |
| 770 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::InlineRunToApplyStyle); | 770 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::InlineRunToApplyStyle); |
| 771 | 771 |
| 772 namespace blink { | 772 namespace blink { |
| 773 | 773 |
| 774 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, PassRef
PtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> pastEndNode) | 774 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, RawPtr<
Node> startNode, RawPtr<Node> pastEndNode) |
| 775 { | 775 { |
| 776 if (m_removeOnly) | 776 if (m_removeOnly) |
| 777 return; | 777 return; |
| 778 | 778 |
| 779 document().updateLayoutIgnorePendingStylesheets(); | 779 document().updateLayoutIgnorePendingStylesheets(); |
| 780 | 780 |
| 781 WillBeHeapVector<InlineRunToApplyStyle> runs; | 781 HeapVector<InlineRunToApplyStyle> runs; |
| 782 RefPtrWillBeRawPtr<Node> node = startNode; | 782 RawPtr<Node> node = startNode; |
| 783 for (RefPtrWillBeRawPtr<Node> next; node && node != pastEndNode; node = next
) { | 783 for (RawPtr<Node> next; node && node != pastEndNode; node = next) { |
| 784 next = NodeTraversal::next(*node); | 784 next = NodeTraversal::next(*node); |
| 785 | 785 |
| 786 if (!node->layoutObject() || !node->hasEditableStyle()) | 786 if (!node->layoutObject() || !node->hasEditableStyle()) |
| 787 continue; | 787 continue; |
| 788 | 788 |
| 789 if (!node->layoutObjectIsRichlyEditable() && node->isHTMLElement()) { | 789 if (!node->layoutObjectIsRichlyEditable() && node->isHTMLElement()) { |
| 790 HTMLElement* element = toHTMLElement(node); | 790 HTMLElement* element = toHTMLElement(node); |
| 791 // This is a plaintext-only region. Only proceed if it's fully selec
ted. | 791 // This is a plaintext-only region. Only proceed if it's fully selec
ted. |
| 792 // pastEndNode is the node after the last fully selected node, so if
it's inside node then | 792 // pastEndNode is the node after the last fully selected node, so if
it's inside node then |
| 793 // node isn't fully selected. | 793 // node isn't fully selected. |
| 794 if (pastEndNode && pastEndNode->isDescendantOf(element)) | 794 if (pastEndNode && pastEndNode->isDescendantOf(element)) |
| 795 break; | 795 break; |
| 796 // Add to this element's inline style and skip over its contents. | 796 // Add to this element's inline style and skip over its contents. |
| 797 next = NodeTraversal::nextSkippingChildren(*node); | 797 next = NodeTraversal::nextSkippingChildren(*node); |
| 798 if (!style->style()) | 798 if (!style->style()) |
| 799 continue; | 799 continue; |
| 800 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); | 800 RawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty
(element->inlineStyle()); |
| 801 inlineStyle->mergeAndOverrideOnConflict(style->style()); | 801 inlineStyle->mergeAndOverrideOnConflict(style->style()); |
| 802 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); | 802 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); |
| 803 continue; | 803 continue; |
| 804 } | 804 } |
| 805 | 805 |
| 806 if (isEnclosingBlock(node.get())) | 806 if (isEnclosingBlock(node.get())) |
| 807 continue; | 807 continue; |
| 808 | 808 |
| 809 if (node->hasChildren()) { | 809 if (node->hasChildren()) { |
| 810 if (node->contains(pastEndNode.get()) || containsNonEditableRegion(*
node) || !node->parentNode()->hasEditableStyle()) | 810 if (node->contains(pastEndNode.get()) || containsNonEditableRegion(*
node) || !node->parentNode()->hasEditableStyle()) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 continue; | 870 continue; |
| 871 // We don't consider m_isInlineElementToRemoveFunction here because we n
ever apply style when m_isInlineElementToRemoveFunction is specified | 871 // We don't consider m_isInlineElementToRemoveFunction here because we n
ever apply style when m_isInlineElementToRemoveFunction is specified |
| 872 if (!style->styleIsPresentInComputedStyleOfNode(node)) | 872 if (!style->styleIsPresentInComputedStyleOfNode(node)) |
| 873 return true; | 873 return true; |
| 874 if (m_styledInlineElement && !enclosingElementWithTag(positionBeforeNode
(node), m_styledInlineElement->tagQName())) | 874 if (m_styledInlineElement && !enclosingElementWithTag(positionBeforeNode
(node), m_styledInlineElement->tagQName())) |
| 875 return true; | 875 return true; |
| 876 } | 876 } |
| 877 return false; | 877 return false; |
| 878 } | 878 } |
| 879 | 879 |
| 880 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style,
RefPtrWillBeMember<Node>& runStart, RefPtrWillBeMember<Node>& runEnd, PassRefPt
rWillBeRawPtr<Node> pastEndNode) | 880 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style,
Member<Node>& runStart, Member<Node>& runEnd, RawPtr<Node> pastEndNode) |
| 881 { | 881 { |
| 882 ASSERT(runStart && runEnd); | 882 ASSERT(runStart && runEnd); |
| 883 RefPtrWillBeRawPtr<Node> next = runStart; | 883 RawPtr<Node> next = runStart; |
| 884 for (RefPtrWillBeRawPtr<Node> node = next; node && node->inDocument() && nod
e != pastEndNode; node = next) { | 884 for (RawPtr<Node> node = next; node && node->inDocument() && node != pastEnd
Node; node = next) { |
| 885 if (editingIgnoresContent(node.get())) { | 885 if (editingIgnoresContent(node.get())) { |
| 886 ASSERT(!node->contains(pastEndNode.get())); | 886 ASSERT(!node->contains(pastEndNode.get())); |
| 887 next = NodeTraversal::nextSkippingChildren(*node); | 887 next = NodeTraversal::nextSkippingChildren(*node); |
| 888 } else { | 888 } else { |
| 889 next = NodeTraversal::next(*node); | 889 next = NodeTraversal::next(*node); |
| 890 } | 890 } |
| 891 if (!node->isHTMLElement()) | 891 if (!node->isHTMLElement()) |
| 892 continue; | 892 continue; |
| 893 | 893 |
| 894 HTMLElement& element = toHTMLElement(*node); | 894 HTMLElement& element = toHTMLElement(*node); |
| 895 RefPtrWillBeRawPtr<Node> previousSibling = element.previousSibling(); | 895 RawPtr<Node> previousSibling = element.previousSibling(); |
| 896 RefPtrWillBeRawPtr<Node> nextSibling = element.nextSibling(); | 896 RawPtr<Node> nextSibling = element.nextSibling(); |
| 897 RefPtrWillBeRawPtr<ContainerNode> parent = element.parentNode(); | 897 RawPtr<ContainerNode> parent = element.parentNode(); |
| 898 removeInlineStyleFromElement(style, &element, RemoveAlways); | 898 removeInlineStyleFromElement(style, &element, RemoveAlways); |
| 899 if (!element.inDocument()) { | 899 if (!element.inDocument()) { |
| 900 // FIXME: We might need to update the start and the end of current s
election here but need a test. | 900 // FIXME: We might need to update the start and the end of current s
election here but need a test. |
| 901 if (runStart == element) | 901 if (runStart == element) |
| 902 runStart = previousSibling ? previousSibling->nextSibling() : pa
rent->firstChild(); | 902 runStart = previousSibling ? previousSibling->nextSibling() : pa
rent->firstChild(); |
| 903 if (runEnd == element) | 903 if (runEnd == element) |
| 904 runEnd = nextSibling ? nextSibling->previousSibling() : parent->
lastChild(); | 904 runEnd = nextSibling ? nextSibling->previousSibling() : parent->
lastChild(); |
| 905 } | 905 } |
| 906 } | 906 } |
| 907 } | 907 } |
| 908 | 908 |
| 909 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRe
fPtrWillBeRawPtr<HTMLElement> element, InlineStyleRemovalMode mode, EditingStyle
* extractedStyle) | 909 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, RawPtr
<HTMLElement> element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle
) |
| 910 { | 910 { |
| 911 ASSERT(element); | 911 ASSERT(element); |
| 912 | 912 |
| 913 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node
::UserSelectAllIsAlwaysNonEditable)) | 913 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node
::UserSelectAllIsAlwaysNonEditable)) |
| 914 return false; | 914 return false; |
| 915 | 915 |
| 916 if (isStyledInlineElementToRemove(element.get())) { | 916 if (isStyledInlineElementToRemove(element.get())) { |
| 917 if (mode == RemoveNone) | 917 if (mode == RemoveNone) |
| 918 return true; | 918 return true; |
| 919 if (extractedStyle) | 919 if (extractedStyle) |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 | 1018 |
| 1019 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
le) | 1019 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
le) |
| 1020 { | 1020 { |
| 1021 ASSERT(node); | 1021 ASSERT(node); |
| 1022 | 1022 |
| 1023 node->document().updateLayoutTreeIfNeeded(); | 1023 node->document().updateLayoutTreeIfNeeded(); |
| 1024 | 1024 |
| 1025 if (!style || style->isEmpty() || !node->layoutObject() || isHTMLIFrameEleme
nt(*node)) | 1025 if (!style || style->isEmpty() || !node->layoutObject() || isHTMLIFrameEleme
nt(*node)) |
| 1026 return; | 1026 return; |
| 1027 | 1027 |
| 1028 RefPtrWillBeRawPtr<EditingStyle> newInlineStyle = style; | 1028 RawPtr<EditingStyle> newInlineStyle = style; |
| 1029 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { | 1029 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { |
| 1030 newInlineStyle = style->copy(); | 1030 newInlineStyle = style->copy(); |
| 1031 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt
yle::OverrideValues); | 1031 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt
yle::OverrideValues); |
| 1032 } | 1032 } |
| 1033 | 1033 |
| 1034 // Since addInlineStyleIfNeeded can't add styles to block-flow layout object
s, add style attribute instead. | 1034 // Since addInlineStyleIfNeeded can't add styles to block-flow layout object
s, add style attribute instead. |
| 1035 // FIXME: applyInlineStyleToRange should be used here instead. | 1035 // FIXME: applyInlineStyleToRange should be used here instead. |
| 1036 if ((node->layoutObject()->isLayoutBlockFlow() || node->hasChildren()) && no
de->isHTMLElement()) { | 1036 if ((node->layoutObject()->isLayoutBlockFlow() || node->hasChildren()) && no
de->isHTMLElement()) { |
| 1037 setNodeAttribute(toHTMLElement(node), styleAttr, AtomicString(newInlineS
tyle->style()->asText())); | 1037 setNodeAttribute(toHTMLElement(node), styleAttr, AtomicString(newInlineS
tyle->style()->asText())); |
| 1038 return; | 1038 return; |
| 1039 } | 1039 } |
| 1040 | 1040 |
| 1041 if (node->layoutObject()->isText() && toLayoutText(node->layoutObject())->is
AllCollapsibleWhitespace()) | 1041 if (node->layoutObject()->isText() && toLayoutText(node->layoutObject())->is
AllCollapsibleWhitespace()) |
| 1042 return; | 1042 return; |
| 1043 | 1043 |
| 1044 // We can't wrap node with the styled element here because new styled elemen
t will never be removed if we did. | 1044 // We can't wrap node with the styled element here because new styled elemen
t will never be removed if we did. |
| 1045 // If we modified the child pointer in pushDownInlineStyleAroundNode to poin
t to new style element | 1045 // If we modified the child pointer in pushDownInlineStyleAroundNode to poin
t to new style element |
| 1046 // then we fall into an infinite loop where we keep removing and adding styl
ed element wrapping node. | 1046 // then we fall into an infinite loop where we keep removing and adding styl
ed element wrapping node. |
| 1047 addInlineStyleIfNeeded(newInlineStyle.get(), node, node, DoNotAddStyledEleme
nt); | 1047 addInlineStyleIfNeeded(newInlineStyle.get(), node, node, DoNotAddStyledEleme
nt); |
| 1048 } | 1048 } |
| 1049 | 1049 |
| 1050 void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
targetNode) | 1050 void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
targetNode) |
| 1051 { | 1051 { |
| 1052 HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(sty
le, targetNode); | 1052 HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(sty
le, targetNode); |
| 1053 if (!highestAncestor) | 1053 if (!highestAncestor) |
| 1054 return; | 1054 return; |
| 1055 | 1055 |
| 1056 // The outer loop is traversing the tree vertically from highestAncestor to
targetNode | 1056 // The outer loop is traversing the tree vertically from highestAncestor to
targetNode |
| 1057 RefPtrWillBeRawPtr<Node> current = highestAncestor; | 1057 RawPtr<Node> current = highestAncestor; |
| 1058 // Along the way, styled elements that contain targetNode are removed and ac
cumulated into elementsToPushDown. | 1058 // Along the way, styled elements that contain targetNode are removed and ac
cumulated into elementsToPushDown. |
| 1059 // Each child of the removed element, exclusing ancestors of targetNode, is
then wrapped by clones of elements in elementsToPushDown. | 1059 // Each child of the removed element, exclusing ancestors of targetNode, is
then wrapped by clones of elements in elementsToPushDown. |
| 1060 WillBeHeapVector<RefPtrWillBeMember<Element>> elementsToPushDown; | 1060 HeapVector<Member<Element>> elementsToPushDown; |
| 1061 while (current && current != targetNode && current->contains(targetNode)) { | 1061 while (current && current != targetNode && current->contains(targetNode)) { |
| 1062 NodeVector currentChildren; | 1062 NodeVector currentChildren; |
| 1063 getChildNodes(toContainerNode(*current), currentChildren); | 1063 getChildNodes(toContainerNode(*current), currentChildren); |
| 1064 RefPtrWillBeRawPtr<Element> styledElement = nullptr; | 1064 RawPtr<Element> styledElement = nullptr; |
| 1065 if (current->isStyledElement() && isStyledInlineElementToRemove(toElemen
t(current))) { | 1065 if (current->isStyledElement() && isStyledInlineElementToRemove(toElemen
t(current))) { |
| 1066 styledElement = toElement(current); | 1066 styledElement = toElement(current); |
| 1067 elementsToPushDown.append(styledElement); | 1067 elementsToPushDown.append(styledElement); |
| 1068 } | 1068 } |
| 1069 | 1069 |
| 1070 RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = EditingStyle::create(
); | 1070 RawPtr<EditingStyle> styleToPushDown = EditingStyle::create(); |
| 1071 if (current->isHTMLElement()) | 1071 if (current->isHTMLElement()) |
| 1072 removeInlineStyleFromElement(style, toHTMLElement(current), RemoveIf
Needed, styleToPushDown.get()); | 1072 removeInlineStyleFromElement(style, toHTMLElement(current), RemoveIf
Needed, styleToPushDown.get()); |
| 1073 | 1073 |
| 1074 // The inner loop will go through children on each level | 1074 // The inner loop will go through children on each level |
| 1075 // FIXME: we should aggregate inline child elements together so that we
don't wrap each child separately. | 1075 // FIXME: we should aggregate inline child elements together so that we
don't wrap each child separately. |
| 1076 for (const auto& currentChild : currentChildren) { | 1076 for (const auto& currentChild : currentChildren) { |
| 1077 Node* child = currentChild.get(); | 1077 Node* child = currentChild.get(); |
| 1078 if (!child->parentNode()) | 1078 if (!child->parentNode()) |
| 1079 continue; | 1079 continue; |
| 1080 if (!child->contains(targetNode) && elementsToPushDown.size()) { | 1080 if (!child->contains(targetNode) && elementsToPushDown.size()) { |
| 1081 for (const auto& element : elementsToPushDown) { | 1081 for (const auto& element : elementsToPushDown) { |
| 1082 RefPtrWillBeRawPtr<Element> wrapper = element->cloneElementW
ithoutChildren(); | 1082 RawPtr<Element> wrapper = element->cloneElementWithoutChildr
en(); |
| 1083 wrapper->removeAttribute(styleAttr); | 1083 wrapper->removeAttribute(styleAttr); |
| 1084 // Delete id attribute from the second element because the s
ame id cannot be used for more than one element | 1084 // Delete id attribute from the second element because the s
ame id cannot be used for more than one element |
| 1085 element->removeAttribute(HTMLNames::idAttr); | 1085 element->removeAttribute(HTMLNames::idAttr); |
| 1086 if (isHTMLAnchorElement(element)) | 1086 if (isHTMLAnchorElement(element)) |
| 1087 element->removeAttribute(HTMLNames::nameAttr); | 1087 element->removeAttribute(HTMLNames::nameAttr); |
| 1088 surroundNodeRangeWithElement(child, child, wrapper); | 1088 surroundNodeRangeWithElement(child, child, wrapper); |
| 1089 } | 1089 } |
| 1090 } | 1090 } |
| 1091 | 1091 |
| 1092 // Apply style to all nodes containing targetNode and their siblings
but NOT to targetNode | 1092 // Apply style to all nodes containing targetNode and their siblings
but NOT to targetNode |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 // If pushDownInlineStyleAroundNode has pruned start.anchorNode() or end.anc
horNode(), | 1136 // If pushDownInlineStyleAroundNode has pruned start.anchorNode() or end.anc
horNode(), |
| 1137 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround
Node won't prune. | 1137 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround
Node won't prune. |
| 1138 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; | 1138 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; |
| 1139 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; | 1139 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; |
| 1140 | 1140 |
| 1141 // Current ending selection resetting algorithm assumes |start| and |end| | 1141 // Current ending selection resetting algorithm assumes |start| and |end| |
| 1142 // are in a same DOM tree even if they are not in document. | 1142 // are in a same DOM tree even if they are not in document. |
| 1143 if (!Position::commonAncestorTreeScope(start, end)) | 1143 if (!Position::commonAncestorTreeScope(start, end)) |
| 1144 return; | 1144 return; |
| 1145 | 1145 |
| 1146 RefPtrWillBeRawPtr<Node> node = start.anchorNode(); | 1146 RawPtr<Node> node = start.anchorNode(); |
| 1147 while (node) { | 1147 while (node) { |
| 1148 RefPtrWillBeRawPtr<Node> next = nullptr; | 1148 RawPtr<Node> next = nullptr; |
| 1149 if (editingIgnoresContent(node.get())) { | 1149 if (editingIgnoresContent(node.get())) { |
| 1150 ASSERT(node == end.anchorNode() || !node->contains(end.anchorNode())
); | 1150 ASSERT(node == end.anchorNode() || !node->contains(end.anchorNode())
); |
| 1151 next = NodeTraversal::nextSkippingChildren(*node); | 1151 next = NodeTraversal::nextSkippingChildren(*node); |
| 1152 } else { | 1152 } else { |
| 1153 next = NodeTraversal::next(*node); | 1153 next = NodeTraversal::next(*node); |
| 1154 } | 1154 } |
| 1155 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node),
start, end)) { | 1155 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node),
start, end)) { |
| 1156 RefPtrWillBeRawPtr<HTMLElement> elem = toHTMLElement(node); | 1156 RawPtr<HTMLElement> elem = toHTMLElement(node); |
| 1157 RefPtrWillBeRawPtr<Node> prev = NodeTraversal::previousPostOrder(*el
em); | 1157 RawPtr<Node> prev = NodeTraversal::previousPostOrder(*elem); |
| 1158 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*elem); | 1158 RawPtr<Node> next = NodeTraversal::next(*elem); |
| 1159 RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = nullptr; | 1159 RawPtr<EditingStyle> styleToPushDown = nullptr; |
| 1160 RefPtrWillBeRawPtr<Node> childNode = nullptr; | 1160 RawPtr<Node> childNode = nullptr; |
| 1161 if (isStyledInlineElementToRemove(elem.get())) { | 1161 if (isStyledInlineElementToRemove(elem.get())) { |
| 1162 styleToPushDown = EditingStyle::create(); | 1162 styleToPushDown = EditingStyle::create(); |
| 1163 childNode = elem->firstChild(); | 1163 childNode = elem->firstChild(); |
| 1164 } | 1164 } |
| 1165 | 1165 |
| 1166 removeInlineStyleFromElement(style, elem.get(), RemoveIfNeeded, styl
eToPushDown.get()); | 1166 removeInlineStyleFromElement(style, elem.get(), RemoveIfNeeded, styl
eToPushDown.get()); |
| 1167 if (!elem->inDocument()) { | 1167 if (!elem->inDocument()) { |
| 1168 if (s.anchorNode() == elem) { | 1168 if (s.anchorNode() == elem) { |
| 1169 // Since elem must have been fully selected, and it is at th
e start | 1169 // Since elem must have been fully selected, and it is at th
e start |
| 1170 // of the selection, it is clear we can set the new s offset
to 0. | 1170 // of the selection, it is clear we can set the new s offset
to 0. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position&
end) | 1205 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position&
end) |
| 1206 { | 1206 { |
| 1207 ASSERT(start.computeContainerNode()->isTextNode()); | 1207 ASSERT(start.computeContainerNode()->isTextNode()); |
| 1208 | 1208 |
| 1209 Position newEnd; | 1209 Position newEnd; |
| 1210 if (end.isOffsetInAnchor() && start.computeContainerNode() == end.computeCon
tainerNode()) | 1210 if (end.isOffsetInAnchor() && start.computeContainerNode() == end.computeCon
tainerNode()) |
| 1211 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode(
) - start.offsetInContainerNode()); | 1211 newEnd = Position(end.computeContainerNode(), end.offsetInContainerNode(
) - start.offsetInContainerNode()); |
| 1212 else | 1212 else |
| 1213 newEnd = end; | 1213 newEnd = end; |
| 1214 | 1214 |
| 1215 RefPtrWillBeRawPtr<Text> text = toText(start.computeContainerNode()); | 1215 RawPtr<Text> text = toText(start.computeContainerNode()); |
| 1216 splitTextNode(text, start.offsetInContainerNode()); | 1216 splitTextNode(text, start.offsetInContainerNode()); |
| 1217 updateStartEnd(firstPositionInNode(text.get()), newEnd); | 1217 updateStartEnd(firstPositionInNode(text.get()), newEnd); |
| 1218 } | 1218 } |
| 1219 | 1219 |
| 1220 void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en
d) | 1220 void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en
d) |
| 1221 { | 1221 { |
| 1222 ASSERT(end.computeContainerNode()->isTextNode()); | 1222 ASSERT(end.computeContainerNode()->isTextNode()); |
| 1223 | 1223 |
| 1224 bool shouldUpdateStart = start.isOffsetInAnchor() && start.computeContainerN
ode() == end.computeContainerNode(); | 1224 bool shouldUpdateStart = start.isOffsetInAnchor() && start.computeContainerN
ode() == end.computeContainerNode(); |
| 1225 Text* text = toText(end.anchorNode()); | 1225 Text* text = toText(end.anchorNode()); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 bool shouldUpdateStart = start.computeContainerNode() == endNode; | 1351 bool shouldUpdateStart = start.computeContainerNode() == endNode; |
| 1352 int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childN
odes()->length(); | 1352 int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childN
odes()->length(); |
| 1353 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC
ontainerNode()) : start, | 1353 updateStartEnd(shouldUpdateStart ? Position(nextElement, start.offsetInC
ontainerNode()) : start, |
| 1354 Position(nextElement, endOffset)); | 1354 Position(nextElement, endOffset)); |
| 1355 return true; | 1355 return true; |
| 1356 } | 1356 } |
| 1357 | 1357 |
| 1358 return false; | 1358 return false; |
| 1359 } | 1359 } |
| 1360 | 1360 |
| 1361 void ApplyStyleCommand::surroundNodeRangeWithElement(PassRefPtrWillBeRawPtr<Node
> passedStartNode, PassRefPtrWillBeRawPtr<Node> endNode, PassRefPtrWillBeRawPtr<
Element> elementToInsert) | 1361 void ApplyStyleCommand::surroundNodeRangeWithElement(RawPtr<Node> passedStartNod
e, RawPtr<Node> endNode, RawPtr<Element> elementToInsert) |
| 1362 { | 1362 { |
| 1363 ASSERT(passedStartNode); | 1363 ASSERT(passedStartNode); |
| 1364 ASSERT(endNode); | 1364 ASSERT(endNode); |
| 1365 ASSERT(elementToInsert); | 1365 ASSERT(elementToInsert); |
| 1366 RefPtrWillBeRawPtr<Node> node = passedStartNode; | 1366 RawPtr<Node> node = passedStartNode; |
| 1367 RefPtrWillBeRawPtr<Element> element = elementToInsert; | 1367 RawPtr<Element> element = elementToInsert; |
| 1368 | 1368 |
| 1369 insertNodeBefore(element, node); | 1369 insertNodeBefore(element, node); |
| 1370 | 1370 |
| 1371 while (node) { | 1371 while (node) { |
| 1372 RefPtrWillBeRawPtr<Node> next = node->nextSibling(); | 1372 RawPtr<Node> next = node->nextSibling(); |
| 1373 if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) { | 1373 if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) { |
| 1374 removeNode(node); | 1374 removeNode(node); |
| 1375 appendNode(node, element); | 1375 appendNode(node, element); |
| 1376 } | 1376 } |
| 1377 if (node == endNode) | 1377 if (node == endNode) |
| 1378 break; | 1378 break; |
| 1379 node = next; | 1379 node = next; |
| 1380 } | 1380 } |
| 1381 | 1381 |
| 1382 RefPtrWillBeRawPtr<Node> nextSibling = element->nextSibling(); | 1382 RawPtr<Node> nextSibling = element->nextSibling(); |
| 1383 RefPtrWillBeRawPtr<Node> previousSibling = element->previousSibling(); | 1383 RawPtr<Node> previousSibling = element->previousSibling(); |
| 1384 if (nextSibling && nextSibling->isElementNode() && nextSibling->hasEditableS
tyle() | 1384 if (nextSibling && nextSibling->isElementNode() && nextSibling->hasEditableS
tyle() |
| 1385 && areIdenticalElements(*element, toElement(*nextSibling))) | 1385 && areIdenticalElements(*element, toElement(*nextSibling))) |
| 1386 mergeIdenticalElements(element.get(), toElement(nextSibling)); | 1386 mergeIdenticalElements(element.get(), toElement(nextSibling)); |
| 1387 | 1387 |
| 1388 if (previousSibling && previousSibling->isElementNode() && previousSibling->
hasEditableStyle()) { | 1388 if (previousSibling && previousSibling->isElementNode() && previousSibling->
hasEditableStyle()) { |
| 1389 Node* mergedElement = previousSibling->nextSibling(); | 1389 Node* mergedElement = previousSibling->nextSibling(); |
| 1390 if (mergedElement->isElementNode() && mergedElement->hasEditableStyle() | 1390 if (mergedElement->isElementNode() && mergedElement->hasEditableStyle() |
| 1391 && areIdenticalElements(toElement(*previousSibling), toElement(*merg
edElement))) | 1391 && areIdenticalElements(toElement(*previousSibling), toElement(*merg
edElement))) |
| 1392 mergeIdenticalElements(toElement(previousSibling), toElement(mergedE
lement)); | 1392 mergeIdenticalElements(toElement(previousSibling), toElement(mergedE
lement)); |
| 1393 } | 1393 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1408 StringBuilder cssText; | 1408 StringBuilder cssText; |
| 1409 cssText.append(cssStyle); | 1409 cssText.append(cssStyle); |
| 1410 if (const StylePropertySet* decl = block->inlineStyle()) { | 1410 if (const StylePropertySet* decl = block->inlineStyle()) { |
| 1411 if (!cssStyle.isEmpty()) | 1411 if (!cssStyle.isEmpty()) |
| 1412 cssText.append(' '); | 1412 cssText.append(' '); |
| 1413 cssText.append(decl->asText()); | 1413 cssText.append(decl->asText()); |
| 1414 } | 1414 } |
| 1415 setNodeAttribute(block, styleAttr, cssText.toAtomicString()); | 1415 setNodeAttribute(block, styleAttr, cssText.toAtomicString()); |
| 1416 } | 1416 } |
| 1417 | 1417 |
| 1418 void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWi
llBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EAddStyled
Element addStyledElement) | 1418 void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, RawPtr<Node>
passedStart, RawPtr<Node> passedEnd, EAddStyledElement addStyledElement) |
| 1419 { | 1419 { |
| 1420 if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->
inDocument()) | 1420 if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->
inDocument()) |
| 1421 return; | 1421 return; |
| 1422 | 1422 |
| 1423 RefPtrWillBeRawPtr<Node> start = passedStart; | 1423 RawPtr<Node> start = passedStart; |
| 1424 RefPtrWillBeMember<HTMLSpanElement> dummyElement = nullptr; | 1424 Member<HTMLSpanElement> dummyElement = nullptr; |
| 1425 StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dum
myElement)); | 1425 StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dum
myElement)); |
| 1426 | 1426 |
| 1427 if (dummyElement) | 1427 if (dummyElement) |
| 1428 removeNode(dummyElement); | 1428 removeNode(dummyElement); |
| 1429 | 1429 |
| 1430 applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement); | 1430 applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement); |
| 1431 } | 1431 } |
| 1432 | 1432 |
| 1433 Position ApplyStyleCommand::positionToComputeInlineStyleChange(PassRefPtrWillBeR
awPtr<Node> startNode, RefPtrWillBeMember<HTMLSpanElement>& dummyElement) | 1433 Position ApplyStyleCommand::positionToComputeInlineStyleChange(RawPtr<Node> star
tNode, Member<HTMLSpanElement>& dummyElement) |
| 1434 { | 1434 { |
| 1435 // It's okay to obtain the style at the startNode because we've removed all
relevant styles from the current run. | 1435 // It's okay to obtain the style at the startNode because we've removed all
relevant styles from the current run. |
| 1436 if (!startNode->isElementNode()) { | 1436 if (!startNode->isElementNode()) { |
| 1437 dummyElement = HTMLSpanElement::create(document()); | 1437 dummyElement = HTMLSpanElement::create(document()); |
| 1438 insertNodeAt(dummyElement, positionBeforeNode(startNode.get())); | 1438 insertNodeAt(dummyElement, positionBeforeNode(startNode.get())); |
| 1439 return positionBeforeNode(dummyElement.get()); | 1439 return positionBeforeNode(dummyElement.get()); |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 return firstPositionInOrBeforeNode(startNode.get()); | 1442 return firstPositionInOrBeforeNode(startNode.get()); |
| 1443 } | 1443 } |
| 1444 | 1444 |
| 1445 void ApplyStyleCommand::applyInlineStyleChange(PassRefPtrWillBeRawPtr<Node> pass
edStart, PassRefPtrWillBeRawPtr<Node> passedEnd, StyleChange& styleChange, EAddS
tyledElement addStyledElement) | 1445 void ApplyStyleCommand::applyInlineStyleChange(RawPtr<Node> passedStart, RawPtr<
Node> passedEnd, StyleChange& styleChange, EAddStyledElement addStyledElement) |
| 1446 { | 1446 { |
| 1447 RefPtrWillBeRawPtr<Node> startNode = passedStart; | 1447 RawPtr<Node> startNode = passedStart; |
| 1448 RefPtrWillBeRawPtr<Node> endNode = passedEnd; | 1448 RawPtr<Node> endNode = passedEnd; |
| 1449 ASSERT(startNode->inDocument()); | 1449 ASSERT(startNode->inDocument()); |
| 1450 ASSERT(endNode->inDocument()); | 1450 ASSERT(endNode->inDocument()); |
| 1451 | 1451 |
| 1452 // Find appropriate font and span elements top-down. | 1452 // Find appropriate font and span elements top-down. |
| 1453 HTMLFontElement* fontContainer = nullptr; | 1453 HTMLFontElement* fontContainer = nullptr; |
| 1454 HTMLElement* styleContainer = nullptr; | 1454 HTMLElement* styleContainer = nullptr; |
| 1455 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { | 1455 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { |
| 1456 if (isHTMLFontElement(*container)) | 1456 if (isHTMLFontElement(*container)) |
| 1457 fontContainer = toHTMLFontElement(container); | 1457 fontContainer = toHTMLFontElement(container); |
| 1458 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); | 1458 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1470 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. | 1470 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. |
| 1471 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { | 1471 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { |
| 1472 if (fontContainer) { | 1472 if (fontContainer) { |
| 1473 if (styleChange.applyFontColor()) | 1473 if (styleChange.applyFontColor()) |
| 1474 setNodeAttribute(fontContainer, colorAttr, AtomicString(styleCha
nge.fontColor())); | 1474 setNodeAttribute(fontContainer, colorAttr, AtomicString(styleCha
nge.fontColor())); |
| 1475 if (styleChange.applyFontFace()) | 1475 if (styleChange.applyFontFace()) |
| 1476 setNodeAttribute(fontContainer, faceAttr, AtomicString(styleChan
ge.fontFace())); | 1476 setNodeAttribute(fontContainer, faceAttr, AtomicString(styleChan
ge.fontFace())); |
| 1477 if (styleChange.applyFontSize()) | 1477 if (styleChange.applyFontSize()) |
| 1478 setNodeAttribute(fontContainer, sizeAttr, AtomicString(styleChan
ge.fontSize())); | 1478 setNodeAttribute(fontContainer, sizeAttr, AtomicString(styleChan
ge.fontSize())); |
| 1479 } else { | 1479 } else { |
| 1480 RefPtrWillBeRawPtr<HTMLFontElement> fontElement = HTMLFontElement::c
reate(document()); | 1480 RawPtr<HTMLFontElement> fontElement = HTMLFontElement::create(docume
nt()); |
| 1481 if (styleChange.applyFontColor()) | 1481 if (styleChange.applyFontColor()) |
| 1482 fontElement->setAttribute(colorAttr, AtomicString(styleChange.fo
ntColor())); | 1482 fontElement->setAttribute(colorAttr, AtomicString(styleChange.fo
ntColor())); |
| 1483 if (styleChange.applyFontFace()) | 1483 if (styleChange.applyFontFace()) |
| 1484 fontElement->setAttribute(faceAttr, AtomicString(styleChange.fon
tFace())); | 1484 fontElement->setAttribute(faceAttr, AtomicString(styleChange.fon
tFace())); |
| 1485 if (styleChange.applyFontSize()) | 1485 if (styleChange.applyFontSize()) |
| 1486 fontElement->setAttribute(sizeAttr, AtomicString(styleChange.fon
tSize())); | 1486 fontElement->setAttribute(sizeAttr, AtomicString(styleChange.fon
tSize())); |
| 1487 surroundNodeRangeWithElement(startNode, endNode, fontElement.get()); | 1487 surroundNodeRangeWithElement(startNode, endNode, fontElement.get()); |
| 1488 } | 1488 } |
| 1489 } | 1489 } |
| 1490 | 1490 |
| 1491 if (styleChange.cssStyle().length()) { | 1491 if (styleChange.cssStyle().length()) { |
| 1492 if (styleContainer) { | 1492 if (styleContainer) { |
| 1493 if (const StylePropertySet* existingStyle = styleContainer->inlineSt
yle()) { | 1493 if (const StylePropertySet* existingStyle = styleContainer->inlineSt
yle()) { |
| 1494 String existingText = existingStyle->asText(); | 1494 String existingText = existingStyle->asText(); |
| 1495 StringBuilder cssText; | 1495 StringBuilder cssText; |
| 1496 cssText.append(existingText); | 1496 cssText.append(existingText); |
| 1497 if (!existingText.isEmpty()) | 1497 if (!existingText.isEmpty()) |
| 1498 cssText.append(' '); | 1498 cssText.append(' '); |
| 1499 cssText.append(styleChange.cssStyle()); | 1499 cssText.append(styleChange.cssStyle()); |
| 1500 setNodeAttribute(styleContainer, styleAttr, cssText.toAtomicStri
ng()); | 1500 setNodeAttribute(styleContainer, styleAttr, cssText.toAtomicStri
ng()); |
| 1501 } else { | 1501 } else { |
| 1502 setNodeAttribute(styleContainer, styleAttr, AtomicString(styleCh
ange.cssStyle())); | 1502 setNodeAttribute(styleContainer, styleAttr, AtomicString(styleCh
ange.cssStyle())); |
| 1503 } | 1503 } |
| 1504 } else { | 1504 } else { |
| 1505 RefPtrWillBeRawPtr<HTMLSpanElement> styleElement = HTMLSpanElement::
create(document()); | 1505 RawPtr<HTMLSpanElement> styleElement = HTMLSpanElement::create(docum
ent()); |
| 1506 styleElement->setAttribute(styleAttr, AtomicString(styleChange.cssSt
yle())); | 1506 styleElement->setAttribute(styleAttr, AtomicString(styleChange.cssSt
yle())); |
| 1507 surroundNodeRangeWithElement(startNode, endNode, styleElement.releas
e()); | 1507 surroundNodeRangeWithElement(startNode, endNode, styleElement.releas
e()); |
| 1508 } | 1508 } |
| 1509 } | 1509 } |
| 1510 | 1510 |
| 1511 if (styleChange.applyBold()) | 1511 if (styleChange.applyBold()) |
| 1512 surroundNodeRangeWithElement(startNode, endNode, HTMLElement::create(bTa
g, document())); | 1512 surroundNodeRangeWithElement(startNode, endNode, HTMLElement::create(bTa
g, document())); |
| 1513 | 1513 |
| 1514 if (styleChange.applyItalic()) | 1514 if (styleChange.applyItalic()) |
| 1515 surroundNodeRangeWithElement(startNode, endNode, HTMLElement::create(iTa
g, document())); | 1515 surroundNodeRangeWithElement(startNode, endNode, HTMLElement::create(iTa
g, document())); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1527 | 1527 |
| 1528 if (m_styledInlineElement && addStyledElement == AddStyledElement) | 1528 if (m_styledInlineElement && addStyledElement == AddStyledElement) |
| 1529 surroundNodeRangeWithElement(startNode, endNode, m_styledInlineElement->
cloneElementWithoutChildren()); | 1529 surroundNodeRangeWithElement(startNode, endNode, m_styledInlineElement->
cloneElementWithoutChildren()); |
| 1530 } | 1530 } |
| 1531 | 1531 |
| 1532 float ApplyStyleCommand::computedFontSize(Node* node) | 1532 float ApplyStyleCommand::computedFontSize(Node* node) |
| 1533 { | 1533 { |
| 1534 if (!node) | 1534 if (!node) |
| 1535 return 0; | 1535 return 0; |
| 1536 | 1536 |
| 1537 RefPtrWillBeRawPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDecl
aration::create(node); | 1537 RawPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::cre
ate(node); |
| 1538 if (!style) | 1538 if (!style) |
| 1539 return 0; | 1539 return 0; |
| 1540 | 1540 |
| 1541 RefPtrWillBeRawPtr<CSSPrimitiveValue> value = static_pointer_cast<CSSPrimiti
veValue>(style->getPropertyCSSValue(CSSPropertyFontSize)); | 1541 RawPtr<CSSPrimitiveValue> value = static_pointer_cast<CSSPrimitiveValue>(sty
le->getPropertyCSSValue(CSSPropertyFontSize)); |
| 1542 if (!value) | 1542 if (!value) |
| 1543 return 0; | 1543 return 0; |
| 1544 | 1544 |
| 1545 ASSERT(value->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::Pixels)
; | 1545 ASSERT(value->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::Pixels)
; |
| 1546 return value->getFloatValue(); | 1546 return value->getFloatValue(); |
| 1547 } | 1547 } |
| 1548 | 1548 |
| 1549 void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position&
start, const Position& end) | 1549 void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position&
start, const Position& end) |
| 1550 { | 1550 { |
| 1551 if (!node) | 1551 if (!node) |
| 1552 return; | 1552 return; |
| 1553 | 1553 |
| 1554 Position newStart = start; | 1554 Position newStart = start; |
| 1555 Position newEnd = end; | 1555 Position newEnd = end; |
| 1556 | 1556 |
| 1557 WillBeHeapVector<RefPtrWillBeMember<Text>> textNodes; | 1557 HeapVector<Member<Text>> textNodes; |
| 1558 for (Node* curr = node->firstChild(); curr; curr = curr->nextSibling()) { | 1558 for (Node* curr = node->firstChild(); curr; curr = curr->nextSibling()) { |
| 1559 if (!curr->isTextNode()) | 1559 if (!curr->isTextNode()) |
| 1560 continue; | 1560 continue; |
| 1561 | 1561 |
| 1562 textNodes.append(toText(curr)); | 1562 textNodes.append(toText(curr)); |
| 1563 } | 1563 } |
| 1564 | 1564 |
| 1565 for (const auto& textNode : textNodes) { | 1565 for (const auto& textNode : textNodes) { |
| 1566 Text* childText = textNode.get(); | 1566 Text* childText = textNode.get(); |
| 1567 Node* next = childText->nextSibling(); | 1567 Node* next = childText->nextSibling(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1585 DEFINE_TRACE(ApplyStyleCommand) | 1585 DEFINE_TRACE(ApplyStyleCommand) |
| 1586 { | 1586 { |
| 1587 visitor->trace(m_style); | 1587 visitor->trace(m_style); |
| 1588 visitor->trace(m_start); | 1588 visitor->trace(m_start); |
| 1589 visitor->trace(m_end); | 1589 visitor->trace(m_end); |
| 1590 visitor->trace(m_styledInlineElement); | 1590 visitor->trace(m_styledInlineElement); |
| 1591 CompositeEditCommand::trace(visitor); | 1591 CompositeEditCommand::trace(visitor); |
| 1592 } | 1592 } |
| 1593 | 1593 |
| 1594 } // namespace blink | 1594 } // namespace blink |
| OLD | NEW |