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 26 matching lines...) Expand all Loading... |
37 #include "core/dom/NodeTraversal.h" | 37 #include "core/dom/NodeTraversal.h" |
38 #include "core/dom/Range.h" | 38 #include "core/dom/Range.h" |
39 #include "core/dom/Text.h" | 39 #include "core/dom/Text.h" |
40 #include "core/editing/EditingStyle.h" | 40 #include "core/editing/EditingStyle.h" |
41 #include "core/editing/HTMLInterchange.h" | 41 #include "core/editing/HTMLInterchange.h" |
42 #include "core/editing/PlainTextRange.h" | 42 #include "core/editing/PlainTextRange.h" |
43 #include "core/editing/TextIterator.h" | 43 #include "core/editing/TextIterator.h" |
44 #include "core/editing/VisibleUnits.h" | 44 #include "core/editing/VisibleUnits.h" |
45 #include "core/editing/htmlediting.h" | 45 #include "core/editing/htmlediting.h" |
46 #include "core/frame/UseCounter.h" | 46 #include "core/frame/UseCounter.h" |
| 47 #include "core/html/HTMLFontElement.h" |
| 48 #include "core/html/HTMLSpanElement.h" |
47 #include "core/rendering/RenderObject.h" | 49 #include "core/rendering/RenderObject.h" |
48 #include "core/rendering/RenderText.h" | 50 #include "core/rendering/RenderText.h" |
49 #include "platform/heap/Handle.h" | 51 #include "platform/heap/Handle.h" |
50 #include "wtf/StdLibExtras.h" | 52 #include "wtf/StdLibExtras.h" |
51 #include "wtf/text/StringBuilder.h" | 53 #include "wtf/text/StringBuilder.h" |
52 | 54 |
53 namespace blink { | 55 namespace blink { |
54 | 56 |
55 using namespace HTMLNames; | 57 using namespace HTMLNames; |
56 | 58 |
57 static String& styleSpanClassString() | 59 static String& styleSpanClassString() |
58 { | 60 { |
59 DEFINE_STATIC_LOCAL(String, styleSpanClassString, ((AppleStyleSpanClass))); | 61 DEFINE_STATIC_LOCAL(String, styleSpanClassString, ((AppleStyleSpanClass))); |
60 return styleSpanClassString; | 62 return styleSpanClassString; |
61 } | 63 } |
62 | 64 |
63 bool isLegacyAppleStyleSpan(const Node *node) | 65 bool isLegacyAppleStyleSpan(const Node* node) |
64 { | 66 { |
65 if (!node || !node->isHTMLElement()) | 67 if (!isHTMLSpanElement(node)) |
66 return false; | 68 return false; |
67 | 69 |
68 const HTMLElement& element = toHTMLElement(*node); | 70 const HTMLSpanElement& span = toHTMLSpanElement(*node); |
69 if (!isHTMLSpanElement(element) || element.getAttribute(classAttr) != styleS
panClassString()) | 71 if (span.getAttribute(classAttr) != styleSpanClassString()) |
70 return false; | 72 return false; |
71 UseCounter::count(element.document(), UseCounter::EditingAppleStyleSpanClass
); | 73 UseCounter::count(span.document(), UseCounter::EditingAppleStyleSpanClass); |
72 return true; | 74 return true; |
73 } | 75 } |
74 | 76 |
75 static bool hasNoAttributeOrOnlyStyleAttribute(const Element* element, ShouldSty
leAttributeBeEmpty shouldStyleAttributeBeEmpty) | 77 static bool hasNoAttributeOrOnlyStyleAttribute(const HTMLElement* element, Shoul
dStyleAttributeBeEmpty shouldStyleAttributeBeEmpty) |
76 { | 78 { |
77 if (!element->hasAttributes()) | 79 if (!element->hasAttributes()) |
78 return true; | 80 return true; |
79 | 81 |
80 unsigned matchedAttributes = 0; | 82 unsigned matchedAttributes = 0; |
81 if (element->getAttribute(classAttr) == styleSpanClassString()) | 83 if (element->getAttribute(classAttr) == styleSpanClassString()) |
82 matchedAttributes++; | 84 matchedAttributes++; |
83 if (element->hasAttribute(styleAttr) && (shouldStyleAttributeBeEmpty == Allo
wNonEmptyStyleAttribute | 85 if (element->hasAttribute(styleAttr) && (shouldStyleAttributeBeEmpty == Allo
wNonEmptyStyleAttribute |
84 || !element->inlineStyle() || element->inlineStyle()->isEmpty())) | 86 || !element->inlineStyle() || element->inlineStyle()->isEmpty())) |
85 matchedAttributes++; | 87 matchedAttributes++; |
86 | 88 |
87 ASSERT(matchedAttributes <= element->attributes().size()); | 89 ASSERT(matchedAttributes <= element->attributes().size()); |
88 return matchedAttributes == element->attributes().size(); | 90 return matchedAttributes == element->attributes().size(); |
89 } | 91 } |
90 | 92 |
91 bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) | 93 bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) |
92 { | 94 { |
93 if (!isHTMLSpanElement(element)) | 95 if (!isHTMLSpanElement(element)) |
94 return false; | 96 return false; |
95 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(element), AllowNonEm
ptyStyleAttribute); | 97 return hasNoAttributeOrOnlyStyleAttribute(toHTMLSpanElement(element), AllowN
onEmptyStyleAttribute); |
96 } | 98 } |
97 | 99 |
98 static inline bool isSpanWithoutAttributesOrUnstyledStyleSpan(const Node* node) | 100 static inline bool isSpanWithoutAttributesOrUnstyledStyleSpan(const Node* node) |
99 { | 101 { |
100 if (!isHTMLSpanElement(node)) | 102 if (!isHTMLSpanElement(node)) |
101 return false; | 103 return false; |
102 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(node), StyleAttribut
eShouldBeEmpty); | 104 return hasNoAttributeOrOnlyStyleAttribute(toHTMLSpanElement(node), StyleAttr
ibuteShouldBeEmpty); |
103 } | 105 } |
104 | 106 |
105 bool isEmptyFontTag(const Element* element, ShouldStyleAttributeBeEmpty shouldSt
yleAttributeBeEmpty) | 107 bool isEmptyFontTag(const Element* element, ShouldStyleAttributeBeEmpty shouldSt
yleAttributeBeEmpty) |
106 { | 108 { |
107 if (!isHTMLFontElement(element)) | 109 if (!isHTMLFontElement(element)) |
108 return false; | 110 return false; |
109 | 111 |
110 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(element), shouldStyl
eAttributeBeEmpty); | 112 return hasNoAttributeOrOnlyStyleAttribute(toHTMLFontElement(element), should
StyleAttributeBeEmpty); |
111 } | 113 } |
112 | 114 |
113 static PassRefPtrWillBeRawPtr<Element> createFontElement(Document& document) | 115 static PassRefPtrWillBeRawPtr<HTMLFontElement> createFontElement(Document& docum
ent) |
114 { | 116 { |
115 return createHTMLElement(document, fontTag); | 117 return toHTMLFontElement(createHTMLElement(document, fontTag).get()); |
116 } | 118 } |
117 | 119 |
118 PassRefPtrWillBeRawPtr<HTMLElement> createStyleSpanElement(Document& document) | 120 PassRefPtrWillBeRawPtr<HTMLSpanElement> createStyleSpanElement(Document& documen
t) |
119 { | 121 { |
120 return createHTMLElement(document, spanTag); | 122 return toHTMLSpanElement(createHTMLElement(document, spanTag).get()); |
121 } | 123 } |
122 | 124 |
123 ApplyStyleCommand::ApplyStyleCommand(Document& document, const EditingStyle* sty
le, EditAction editingAction, EPropertyLevel propertyLevel) | 125 ApplyStyleCommand::ApplyStyleCommand(Document& document, const EditingStyle* sty
le, EditAction editingAction, EPropertyLevel propertyLevel) |
124 : CompositeEditCommand(document) | 126 : CompositeEditCommand(document) |
125 , m_style(style->copy()) | 127 , m_style(style->copy()) |
126 , m_editingAction(editingAction) | 128 , m_editingAction(editingAction) |
127 , m_propertyLevel(propertyLevel) | 129 , m_propertyLevel(propertyLevel) |
128 , m_start(endingSelection().start().downstream()) | 130 , m_start(endingSelection().start().downstream()) |
129 , m_end(endingSelection().end().upstream()) | 131 , m_end(endingSelection().end().upstream()) |
130 , m_useEndingSelection(true) | 132 , m_useEndingSelection(true) |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 RefPtrWillBeRawPtr<Range> endRange = Range::create(document(), firstPosition
InNode(&scope), visibleEnd.deepEquivalent().parentAnchoredEquivalent()); | 263 RefPtrWillBeRawPtr<Range> endRange = Range::create(document(), firstPosition
InNode(&scope), visibleEnd.deepEquivalent().parentAnchoredEquivalent()); |
262 int startIndex = TextIterator::rangeLength(startRange.get(), true); | 264 int startIndex = TextIterator::rangeLength(startRange.get(), true); |
263 int endIndex = TextIterator::rangeLength(endRange.get(), true); | 265 int endIndex = TextIterator::rangeLength(endRange.get(), true); |
264 | 266 |
265 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); | 267 VisiblePosition paragraphStart(startOfParagraph(visibleStart)); |
266 VisiblePosition nextParagraphStart(endOfParagraph(paragraphStart).next()); | 268 VisiblePosition nextParagraphStart(endOfParagraph(paragraphStart).next()); |
267 VisiblePosition beyondEnd(endOfParagraph(visibleEnd).next()); | 269 VisiblePosition beyondEnd(endOfParagraph(visibleEnd).next()); |
268 while (paragraphStart.isNotNull() && paragraphStart != beyondEnd) { | 270 while (paragraphStart.isNotNull() && paragraphStart != beyondEnd) { |
269 StyleChange styleChange(style, paragraphStart.deepEquivalent()); | 271 StyleChange styleChange(style, paragraphStart.deepEquivalent()); |
270 if (styleChange.cssStyle().length() || m_removeOnly) { | 272 if (styleChange.cssStyle().length() || m_removeOnly) { |
271 RefPtrWillBeRawPtr<Node> block = enclosingBlock(paragraphStart.deepE
quivalent().deprecatedNode()); | 273 RefPtrWillBeRawPtr<Element> block = enclosingBlock(paragraphStart.de
epEquivalent().deprecatedNode()); |
272 const Position& paragraphStartToMove = paragraphStart.deepEquivalent
(); | 274 const Position& paragraphStartToMove = paragraphStart.deepEquivalent
(); |
273 if (!m_removeOnly && isEditablePosition(paragraphStartToMove)) { | 275 if (!m_removeOnly && isEditablePosition(paragraphStartToMove)) { |
274 RefPtrWillBeRawPtr<Element> newBlock = moveParagraphContentsToNe
wBlockIfNecessary(paragraphStartToMove); | 276 RefPtrWillBeRawPtr<Element> newBlock = moveParagraphContentsToNe
wBlockIfNecessary(paragraphStartToMove); |
275 if (newBlock) | 277 if (newBlock) |
276 block = newBlock; | 278 block = newBlock; |
277 } | 279 } |
278 ASSERT(!block || block->isElementNode()); | |
279 if (block && block->isHTMLElement()) { | 280 if (block && block->isHTMLElement()) { |
280 removeCSSStyle(style, toHTMLElement(block)); | 281 removeCSSStyle(style, toHTMLElement(block)); |
281 if (!m_removeOnly) | 282 if (!m_removeOnly) |
282 addBlockStyle(styleChange, toHTMLElement(block)); | 283 addBlockStyle(styleChange, toHTMLElement(block)); |
283 } | 284 } |
284 | 285 |
285 if (nextParagraphStart.isOrphan()) | 286 if (nextParagraphStart.isOrphan()) |
286 nextParagraphStart = endOfParagraph(paragraphStart).next(); | 287 nextParagraphStart = endOfParagraph(paragraphStart).next(); |
287 } | 288 } |
288 | 289 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 | 384 |
384 // These spans were added by us. If empty after font size changes, they can
be removed. | 385 // These spans were added by us. If empty after font size changes, they can
be removed. |
385 WillBeHeapVector<RefPtrWillBeMember<HTMLElement> > unstyledSpans; | 386 WillBeHeapVector<RefPtrWillBeMember<HTMLElement> > unstyledSpans; |
386 | 387 |
387 Node* lastStyledNode = 0; | 388 Node* lastStyledNode = 0; |
388 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(*
node)) { | 389 for (Node* node = startNode; node != beyondEnd; node = NodeTraversal::next(*
node)) { |
389 ASSERT(node); | 390 ASSERT(node); |
390 RefPtrWillBeRawPtr<HTMLElement> element = nullptr; | 391 RefPtrWillBeRawPtr<HTMLElement> element = nullptr; |
391 if (node->isHTMLElement()) { | 392 if (node->isHTMLElement()) { |
392 // Only work on fully selected nodes. | 393 // Only work on fully selected nodes. |
393 if (!nodeFullySelected(node, start, end)) | 394 if (!elementFullySelected(toHTMLElement(*node), start, end)) |
394 continue; | 395 continue; |
395 element = toHTMLElement(node); | 396 element = toHTMLElement(node); |
396 } else if (node->isTextNode() && node->renderer() && node->parentNode()
!= lastStyledNode) { | 397 } else if (node->isTextNode() && node->renderer() && node->parentNode()
!= lastStyledNode) { |
397 // Last styled node was not parent node of this text node, but we wi
sh to style this | 398 // Last styled node was not parent node of this text node, but we wi
sh to style this |
398 // text node. To make this possible, add a style span to surround th
is text node. | 399 // text node. To make this possible, add a style span to surround th
is text node. |
399 RefPtrWillBeRawPtr<HTMLElement> span = createStyleSpanElement(docume
nt()); | 400 RefPtrWillBeRawPtr<HTMLSpanElement> span = createStyleSpanElement(do
cument()); |
400 surroundNodeRangeWithElement(node, node, span.get()); | 401 surroundNodeRangeWithElement(node, node, span.get()); |
401 element = span.release(); | 402 element = span.release(); |
402 } else { | 403 } else { |
403 // Only handle HTML elements and text nodes. | 404 // Only handle HTML elements and text nodes. |
404 continue; | 405 continue; |
405 } | 406 } |
406 lastStyledNode = node; | 407 lastStyledNode = node; |
407 | 408 |
408 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCre
ateEmpty(element->inlineStyle()); | 409 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCre
ateEmpty(element->inlineStyle()); |
409 float currentFontSize = computedFontSize(node); | 410 float currentFontSize = computedFontSize(node); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 next = node->nextSibling(); | 452 next = node->nextSibling(); |
452 if (isSpanWithoutAttributesOrUnstyledStyleSpan(node)) | 453 if (isSpanWithoutAttributesOrUnstyledStyleSpan(node)) |
453 removeNodePreservingChildren(node); | 454 removeNodePreservingChildren(node); |
454 } | 455 } |
455 } | 456 } |
456 | 457 |
457 HTMLElement* ApplyStyleCommand::splitAncestorsWithUnicodeBidi(Node* node, bool b
efore, WritingDirection allowedDirection) | 458 HTMLElement* ApplyStyleCommand::splitAncestorsWithUnicodeBidi(Node* node, bool b
efore, WritingDirection allowedDirection) |
458 { | 459 { |
459 // We are allowed to leave the highest ancestor with unicode-bidi unsplit if
it is unicode-bidi: embed and direction: allowedDirection. | 460 // We are allowed to leave the highest ancestor with unicode-bidi unsplit if
it is unicode-bidi: embed and direction: allowedDirection. |
460 // In that case, we return the unsplit ancestor. Otherwise, we return 0. | 461 // In that case, we return the unsplit ancestor. Otherwise, we return 0. |
461 Node* block = enclosingBlock(node); | 462 Element* block = enclosingBlock(node); |
462 if (!block) | 463 if (!block) |
463 return 0; | 464 return 0; |
464 | 465 |
465 Node* highestAncestorWithUnicodeBidi = 0; | 466 ContainerNode* highestAncestorWithUnicodeBidi = 0; |
466 Node* nextHighestAncestorWithUnicodeBidi = 0; | 467 ContainerNode* nextHighestAncestorWithUnicodeBidi = 0; |
467 int highestAncestorUnicodeBidi = 0; | 468 int highestAncestorUnicodeBidi = 0; |
468 for (Node* n = node->parentNode(); n != block; n = n->parentNode()) { | 469 for (ContainerNode* n = node->parentNode(); n != block; n = n->parentNode())
{ |
469 int unicodeBidi = getIdentifierValue(CSSComputedStyleDeclaration::create
(n).get(), CSSPropertyUnicodeBidi); | 470 int unicodeBidi = getIdentifierValue(CSSComputedStyleDeclaration::create
(n).get(), CSSPropertyUnicodeBidi); |
470 if (unicodeBidi && unicodeBidi != CSSValueNormal) { | 471 if (unicodeBidi && unicodeBidi != CSSValueNormal) { |
471 highestAncestorUnicodeBidi = unicodeBidi; | 472 highestAncestorUnicodeBidi = unicodeBidi; |
472 nextHighestAncestorWithUnicodeBidi = highestAncestorWithUnicodeBidi; | 473 nextHighestAncestorWithUnicodeBidi = highestAncestorWithUnicodeBidi; |
473 highestAncestorWithUnicodeBidi = n; | 474 highestAncestorWithUnicodeBidi = n; |
474 } | 475 } |
475 } | 476 } |
476 | 477 |
477 if (!highestAncestorWithUnicodeBidi) | 478 if (!highestAncestorWithUnicodeBidi) |
478 return 0; | 479 return 0; |
(...skipping 19 matching lines...) Expand all Loading... |
498 RefPtrWillBeRawPtr<Element> parent = toElement(currentNode->parentNode()
); | 499 RefPtrWillBeRawPtr<Element> parent = toElement(currentNode->parentNode()
); |
499 if (before ? currentNode->previousSibling() : currentNode->nextSibling()
) | 500 if (before ? currentNode->previousSibling() : currentNode->nextSibling()
) |
500 splitElement(parent, before ? currentNode.get() : currentNode->nextS
ibling()); | 501 splitElement(parent, before ? currentNode.get() : currentNode->nextS
ibling()); |
501 if (parent == highestAncestorWithUnicodeBidi) | 502 if (parent == highestAncestorWithUnicodeBidi) |
502 break; | 503 break; |
503 currentNode = parent; | 504 currentNode = parent; |
504 } | 505 } |
505 return unsplitAncestor; | 506 return unsplitAncestor; |
506 } | 507 } |
507 | 508 |
508 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, Node* unsp
litAncestor) | 509 void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, HTMLElemen
t* unsplitAncestor) |
509 { | 510 { |
510 Node* block = enclosingBlock(node); | 511 Element* block = enclosingBlock(node); |
511 if (!block) | 512 if (!block) |
512 return; | 513 return; |
513 | 514 |
514 for (Node* n = node->parentNode(); n != block && n != unsplitAncestor; n = n
->parentNode()) { | 515 for (ContainerNode* n = node->parentNode(); n != block && n != unsplitAncest
or; n = n->parentNode()) { |
515 if (!n->isStyledElement()) | 516 if (!n->isStyledElement()) |
516 continue; | 517 continue; |
517 | 518 |
518 Element* element = toElement(n); | 519 Element* element = toElement(n); |
519 int unicodeBidi = getIdentifierValue(CSSComputedStyleDeclaration::create
(element).get(), CSSPropertyUnicodeBidi); | 520 int unicodeBidi = getIdentifierValue(CSSComputedStyleDeclaration::create
(element).get(), CSSPropertyUnicodeBidi); |
520 if (!unicodeBidi || unicodeBidi == CSSValueNormal) | 521 if (!unicodeBidi || unicodeBidi == CSSValueNormal) |
521 continue; | 522 continue; |
522 | 523 |
523 // FIXME: This code should really consider the mapped attribute 'dir', t
he inline style declaration, | 524 // FIXME: This code should really consider the mapped attribute 'dir', t
he inline style declaration, |
524 // and all matching style rules in order to determine how to best set th
e unicode-bidi property to 'normal'. | 525 // and all matching style rules in order to determine how to best set th
e unicode-bidi property to 'normal'. |
525 // For now, it assumes that if the 'dir' attribute is present, then remo
ving it will suffice, and | 526 // For now, it assumes that if the 'dir' attribute is present, then remo
ving it will suffice, and |
526 // otherwise it sets the property in the inline style declaration. | 527 // otherwise it sets the property in the inline style declaration. |
527 if (element->hasAttribute(dirAttr)) { | 528 if (element->hasAttribute(dirAttr)) { |
528 // FIXME: If this is a BDO element, we should probably just remove i
t if it has no | 529 // FIXME: If this is a BDO element, we should probably just remove i
t if it has no |
529 // other attributes, like we (should) do with B and I elements. | 530 // other attributes, like we (should) do with B and I elements. |
530 removeNodeAttribute(element, dirAttr); | 531 removeNodeAttribute(element, dirAttr); |
531 } else { | 532 } else { |
532 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); | 533 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); |
533 inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); | 534 inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); |
534 inlineStyle->removeProperty(CSSPropertyDirection); | 535 inlineStyle->removeProperty(CSSPropertyDirection); |
535 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); | 536 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); |
536 if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) | 537 if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) |
537 removeNodePreservingChildren(element); | 538 removeNodePreservingChildren(element); |
538 } | 539 } |
539 } | 540 } |
540 } | 541 } |
541 | 542 |
542 static Node* highestEmbeddingAncestor(Node* startNode, Node* enclosingNode) | 543 static HTMLElement* highestEmbeddingAncestor(Node* startNode, Node* enclosingNod
e) |
543 { | 544 { |
544 for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { | 545 for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { |
545 if (n->isHTMLElement() && getIdentifierValue(CSSComputedStyleDeclaration
::create(n).get(), CSSPropertyUnicodeBidi) == CSSValueEmbed) | 546 if (n->isHTMLElement() && getIdentifierValue(CSSComputedStyleDeclaration
::create(n).get(), CSSPropertyUnicodeBidi) == CSSValueEmbed) |
546 return n; | 547 return toHTMLElement(n); |
547 } | 548 } |
548 | 549 |
549 return 0; | 550 return 0; |
550 } | 551 } |
551 | 552 |
552 void ApplyStyleCommand::applyInlineStyle(EditingStyle* style) | 553 void ApplyStyleCommand::applyInlineStyle(EditingStyle* style) |
553 { | 554 { |
554 RefPtrWillBeRawPtr<ContainerNode> startDummySpanAncestor = nullptr; | 555 RefPtrWillBeRawPtr<ContainerNode> startDummySpanAncestor = nullptr; |
555 RefPtrWillBeRawPtr<ContainerNode> endDummySpanAncestor = nullptr; | 556 RefPtrWillBeRawPtr<ContainerNode> endDummySpanAncestor = nullptr; |
556 | 557 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 RefPtrWillBeRawPtr<EditingStyle> embeddingStyle = nullptr; | 609 RefPtrWillBeRawPtr<EditingStyle> embeddingStyle = nullptr; |
609 if (hasTextDirection) { | 610 if (hasTextDirection) { |
610 // Leave alone an ancestor that provides the desired single level embedd
ing, if there is one. | 611 // Leave alone an ancestor that provides the desired single level embedd
ing, if there is one. |
611 HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.
deprecatedNode(), true, textDirection); | 612 HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.
deprecatedNode(), true, textDirection); |
612 HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.depr
ecatedNode(), false, textDirection); | 613 HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.depr
ecatedNode(), false, textDirection); |
613 removeEmbeddingUpToEnclosingBlock(start.deprecatedNode(), startUnsplitAn
cestor); | 614 removeEmbeddingUpToEnclosingBlock(start.deprecatedNode(), startUnsplitAn
cestor); |
614 removeEmbeddingUpToEnclosingBlock(end.deprecatedNode(), endUnsplitAncest
or); | 615 removeEmbeddingUpToEnclosingBlock(end.deprecatedNode(), endUnsplitAncest
or); |
615 | 616 |
616 // Avoid removing the dir attribute and the unicode-bidi and direction p
roperties from the unsplit ancestors. | 617 // Avoid removing the dir attribute and the unicode-bidi and direction p
roperties from the unsplit ancestors. |
617 Position embeddingRemoveStart = removeStart; | 618 Position embeddingRemoveStart = removeStart; |
618 if (startUnsplitAncestor && nodeFullySelected(startUnsplitAncestor, remo
veStart, end)) | 619 if (startUnsplitAncestor && elementFullySelected(*startUnsplitAncestor,
removeStart, end)) |
619 embeddingRemoveStart = positionInParentAfterNode(*startUnsplitAncest
or); | 620 embeddingRemoveStart = positionInParentAfterNode(*startUnsplitAncest
or); |
620 | 621 |
621 Position embeddingRemoveEnd = end; | 622 Position embeddingRemoveEnd = end; |
622 if (endUnsplitAncestor && nodeFullySelected(endUnsplitAncestor, removeSt
art, end)) | 623 if (endUnsplitAncestor && elementFullySelected(*endUnsplitAncestor, remo
veStart, end)) |
623 embeddingRemoveEnd = positionInParentBeforeNode(*endUnsplitAncestor)
.downstream(); | 624 embeddingRemoveEnd = positionInParentBeforeNode(*endUnsplitAncestor)
.downstream(); |
624 | 625 |
625 if (embeddingRemoveEnd != removeStart || embeddingRemoveEnd != end) { | 626 if (embeddingRemoveEnd != removeStart || embeddingRemoveEnd != end) { |
626 styleWithoutEmbedding = style->copy(); | 627 styleWithoutEmbedding = style->copy(); |
627 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDirectio
n(); | 628 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDirectio
n(); |
628 | 629 |
629 if (comparePositions(embeddingRemoveStart, embeddingRemoveEnd) <= 0) | 630 if (comparePositions(embeddingRemoveStart, embeddingRemoveEnd) <= 0) |
630 removeInlineStyle(embeddingStyle.get(), embeddingRemoveStart, em
beddingRemoveEnd); | 631 removeInlineStyle(embeddingStyle.get(), embeddingRemoveStart, em
beddingRemoveEnd); |
631 } | 632 } |
632 } | 633 } |
(...skipping 16 matching lines...) Expand all Loading... |
649 } | 650 } |
650 | 651 |
651 // update document layout once before running the rest of the function | 652 // update document layout once before running the rest of the function |
652 // so that we avoid the expense of updating before each and every call | 653 // so that we avoid the expense of updating before each and every call |
653 // to check a computed style | 654 // to check a computed style |
654 document().updateLayoutIgnorePendingStylesheets(); | 655 document().updateLayoutIgnorePendingStylesheets(); |
655 | 656 |
656 RefPtrWillBeRawPtr<EditingStyle> styleToApply = style; | 657 RefPtrWillBeRawPtr<EditingStyle> styleToApply = style; |
657 if (hasTextDirection) { | 658 if (hasTextDirection) { |
658 // Avoid applying the unicode-bidi and direction properties beneath ance
stors that already have them. | 659 // Avoid applying the unicode-bidi and direction properties beneath ance
stors that already have them. |
659 Node* embeddingStartNode = highestEmbeddingAncestor(start.deprecatedNode
(), enclosingBlock(start.deprecatedNode())); | 660 HTMLElement* embeddingStartElement = highestEmbeddingAncestor(start.depr
ecatedNode(), enclosingBlock(start.deprecatedNode())); |
660 Node* embeddingEndNode = highestEmbeddingAncestor(end.deprecatedNode(),
enclosingBlock(end.deprecatedNode())); | 661 HTMLElement* embeddingEndElement = highestEmbeddingAncestor(end.deprecat
edNode(), enclosingBlock(end.deprecatedNode())); |
661 | 662 |
662 if (embeddingStartNode || embeddingEndNode) { | 663 if (embeddingStartElement || embeddingEndElement) { |
663 Position embeddingApplyStart = embeddingStartNode ? positionInParent
AfterNode(*embeddingStartNode) : start; | 664 Position embeddingApplyStart = embeddingStartElement ? positionInPar
entAfterNode(*embeddingStartElement) : start; |
664 Position embeddingApplyEnd = embeddingEndNode ? positionInParentBefo
reNode(*embeddingEndNode) : end; | 665 Position embeddingApplyEnd = embeddingEndElement ? positionInParentB
eforeNode(*embeddingEndElement) : end; |
665 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul
l()); | 666 ASSERT(embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNul
l()); |
666 | 667 |
667 if (!embeddingStyle) { | 668 if (!embeddingStyle) { |
668 styleWithoutEmbedding = style->copy(); | 669 styleWithoutEmbedding = style->copy(); |
669 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDire
ction(); | 670 embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDire
ction(); |
670 } | 671 } |
671 fixRangeAndApplyInlineStyle(embeddingStyle.get(), embeddingApplyStar
t, embeddingApplyEnd); | 672 fixRangeAndApplyInlineStyle(embeddingStyle.get(), embeddingApplyStar
t, embeddingApplyEnd); |
672 | 673 |
673 styleToApply = styleWithoutEmbedding; | 674 styleToApply = styleWithoutEmbedding; |
674 } | 675 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 visitor->trace(end); | 752 visitor->trace(end); |
752 visitor->trace(pastEndNode); | 753 visitor->trace(pastEndNode); |
753 visitor->trace(positionForStyleComputation); | 754 visitor->trace(positionForStyleComputation); |
754 visitor->trace(dummyElement); | 755 visitor->trace(dummyElement); |
755 } | 756 } |
756 | 757 |
757 RefPtrWillBeMember<Node> start; | 758 RefPtrWillBeMember<Node> start; |
758 RefPtrWillBeMember<Node> end; | 759 RefPtrWillBeMember<Node> end; |
759 RefPtrWillBeMember<Node> pastEndNode; | 760 RefPtrWillBeMember<Node> pastEndNode; |
760 Position positionForStyleComputation; | 761 Position positionForStyleComputation; |
761 RefPtrWillBeMember<Node> dummyElement; | 762 RefPtrWillBeMember<HTMLSpanElement> dummyElement; |
762 StyleChange change; | 763 StyleChange change; |
763 }; | 764 }; |
764 | 765 |
765 } // namespace blink | 766 } // namespace blink |
766 | 767 |
767 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::InlineRunToApplyStyle); | 768 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::InlineRunToApplyStyle); |
768 | 769 |
769 namespace blink { | 770 namespace blink { |
770 | 771 |
771 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, PassRef
PtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> pastEndNode) | 772 void ApplyStyleCommand::applyInlineStyleToNodeRange(EditingStyle* style, PassRef
PtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> pastEndNode) |
772 { | 773 { |
773 if (m_removeOnly) | 774 if (m_removeOnly) |
774 return; | 775 return; |
775 | 776 |
776 document().updateLayoutIgnorePendingStylesheets(); | 777 document().updateLayoutIgnorePendingStylesheets(); |
777 | 778 |
778 WillBeHeapVector<InlineRunToApplyStyle> runs; | 779 WillBeHeapVector<InlineRunToApplyStyle> runs; |
779 RefPtrWillBeRawPtr<Node> node = startNode; | 780 RefPtrWillBeRawPtr<Node> node = startNode; |
780 for (RefPtrWillBeRawPtr<Node> next; node && node != pastEndNode; node = next
) { | 781 for (RefPtrWillBeRawPtr<Node> next; node && node != pastEndNode; node = next
) { |
781 next = NodeTraversal::next(*node); | 782 next = NodeTraversal::next(*node); |
782 | 783 |
783 if (!node->renderer() || !node->hasEditableStyle()) | 784 if (!node->renderer() || !node->hasEditableStyle()) |
784 continue; | 785 continue; |
785 | 786 |
786 if (!node->rendererIsRichlyEditable() && node->isHTMLElement()) { | 787 if (!node->rendererIsRichlyEditable() && node->isHTMLElement()) { |
| 788 HTMLElement* element = toHTMLElement(node); |
787 // This is a plaintext-only region. Only proceed if it's fully selec
ted. | 789 // This is a plaintext-only region. Only proceed if it's fully selec
ted. |
788 // pastEndNode is the node after the last fully selected node, so if
it's inside node then | 790 // pastEndNode is the node after the last fully selected node, so if
it's inside node then |
789 // node isn't fully selected. | 791 // node isn't fully selected. |
790 if (pastEndNode && pastEndNode->isDescendantOf(node.get())) | 792 if (pastEndNode && pastEndNode->isDescendantOf(element)) |
791 break; | 793 break; |
792 // Add to this element's inline style and skip over its contents. | 794 // Add to this element's inline style and skip over its contents. |
793 HTMLElement* element = toHTMLElement(node); | |
794 next = NodeTraversal::nextSkippingChildren(*node); | 795 next = NodeTraversal::nextSkippingChildren(*node); |
795 if (!style->style()) | 796 if (!style->style()) |
796 continue; | 797 continue; |
797 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); | 798 RefPtrWillBeRawPtr<MutableStylePropertySet> inlineStyle = copyStyleO
rCreateEmpty(element->inlineStyle()); |
798 inlineStyle->mergeAndOverrideOnConflict(style->style()); | 799 inlineStyle->mergeAndOverrideOnConflict(style->style()); |
799 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); | 800 setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asTex
t())); |
800 continue; | 801 continue; |
801 } | 802 } |
802 | 803 |
803 if (isBlock(node.get())) | 804 if (isBlock(node.get())) |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 for (RefPtrWillBeRawPtr<Node> node = next; node && node->inDocument() && nod
e != pastEndNode; node = next) { | 883 for (RefPtrWillBeRawPtr<Node> node = next; node && node->inDocument() && nod
e != pastEndNode; node = next) { |
883 if (editingIgnoresContent(node.get())) { | 884 if (editingIgnoresContent(node.get())) { |
884 ASSERT(!node->contains(pastEndNode.get())); | 885 ASSERT(!node->contains(pastEndNode.get())); |
885 next = NodeTraversal::nextSkippingChildren(*node); | 886 next = NodeTraversal::nextSkippingChildren(*node); |
886 } else { | 887 } else { |
887 next = NodeTraversal::next(*node); | 888 next = NodeTraversal::next(*node); |
888 } | 889 } |
889 if (!node->isHTMLElement()) | 890 if (!node->isHTMLElement()) |
890 continue; | 891 continue; |
891 | 892 |
892 RefPtrWillBeRawPtr<Node> previousSibling = node->previousSibling(); | 893 HTMLElement& element = toHTMLElement(*node); |
893 RefPtrWillBeRawPtr<Node> nextSibling = node->nextSibling(); | 894 RefPtrWillBeRawPtr<Node> previousSibling = element.previousSibling(); |
894 RefPtrWillBeRawPtr<ContainerNode> parent = node->parentNode(); | 895 RefPtrWillBeRawPtr<Node> nextSibling = element.nextSibling(); |
895 removeInlineStyleFromElement(style, toHTMLElement(node), RemoveAlways); | 896 RefPtrWillBeRawPtr<ContainerNode> parent = element.parentNode(); |
896 if (!node->inDocument()) { | 897 removeInlineStyleFromElement(style, &element, RemoveAlways); |
| 898 if (!element.inDocument()) { |
897 // FIXME: We might need to update the start and the end of current s
election here but need a test. | 899 // FIXME: We might need to update the start and the end of current s
election here but need a test. |
898 if (runStart == node) | 900 if (runStart == element) |
899 runStart = previousSibling ? previousSibling->nextSibling() : pa
rent->firstChild(); | 901 runStart = previousSibling ? previousSibling->nextSibling() : pa
rent->firstChild(); |
900 if (runEnd == node) | 902 if (runEnd == element) |
901 runEnd = nextSibling ? nextSibling->previousSibling() : parent->
lastChild(); | 903 runEnd = nextSibling ? nextSibling->previousSibling() : parent->
lastChild(); |
902 } | 904 } |
903 } | 905 } |
904 } | 906 } |
905 | 907 |
906 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRe
fPtrWillBeRawPtr<HTMLElement> element, InlineStyleRemovalMode mode, EditingStyle
* extractedStyle) | 908 bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRe
fPtrWillBeRawPtr<HTMLElement> element, InlineStyleRemovalMode mode, EditingStyle
* extractedStyle) |
907 { | 909 { |
908 ASSERT(element); | 910 ASSERT(element); |
909 | 911 |
910 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node
::UserSelectAllIsAlwaysNonEditable)) | 912 if (!element->parentNode() || !element->parentNode()->isContentEditable(Node
::UserSelectAllIsAlwaysNonEditable)) |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 | 1134 |
1133 RefPtrWillBeRawPtr<Node> node = start.deprecatedNode(); | 1135 RefPtrWillBeRawPtr<Node> node = start.deprecatedNode(); |
1134 while (node) { | 1136 while (node) { |
1135 RefPtrWillBeRawPtr<Node> next = nullptr; | 1137 RefPtrWillBeRawPtr<Node> next = nullptr; |
1136 if (editingIgnoresContent(node.get())) { | 1138 if (editingIgnoresContent(node.get())) { |
1137 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate
dNode())); | 1139 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate
dNode())); |
1138 next = NodeTraversal::nextSkippingChildren(*node); | 1140 next = NodeTraversal::nextSkippingChildren(*node); |
1139 } else { | 1141 } else { |
1140 next = NodeTraversal::next(*node); | 1142 next = NodeTraversal::next(*node); |
1141 } | 1143 } |
1142 if (node->isHTMLElement() && nodeFullySelected(node.get(), start, end))
{ | 1144 if (node->isHTMLElement() && elementFullySelected(toHTMLElement(*node),
start, end)) { |
1143 RefPtrWillBeRawPtr<HTMLElement> elem = toHTMLElement(node); | 1145 RefPtrWillBeRawPtr<HTMLElement> elem = toHTMLElement(node); |
1144 RefPtrWillBeRawPtr<Node> prev = NodeTraversal::previousPostOrder(*el
em); | 1146 RefPtrWillBeRawPtr<Node> prev = NodeTraversal::previousPostOrder(*el
em); |
1145 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*elem); | 1147 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*elem); |
1146 RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = nullptr; | 1148 RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = nullptr; |
1147 RefPtrWillBeRawPtr<Node> childNode = nullptr; | 1149 RefPtrWillBeRawPtr<Node> childNode = nullptr; |
1148 if (isStyledInlineElementToRemove(elem.get())) { | 1150 if (isStyledInlineElementToRemove(elem.get())) { |
1149 styleToPushDown = EditingStyle::create(); | 1151 styleToPushDown = EditingStyle::create(); |
1150 childNode = elem->firstChild(); | 1152 childNode = elem->firstChild(); |
1151 } | 1153 } |
1152 | 1154 |
(...skipping 20 matching lines...) Expand all Loading... |
1173 } | 1175 } |
1174 } | 1176 } |
1175 if (node == end.deprecatedNode()) | 1177 if (node == end.deprecatedNode()) |
1176 break; | 1178 break; |
1177 node = next; | 1179 node = next; |
1178 } | 1180 } |
1179 | 1181 |
1180 updateStartEnd(s, e); | 1182 updateStartEnd(s, e); |
1181 } | 1183 } |
1182 | 1184 |
1183 bool ApplyStyleCommand::nodeFullySelected(Node *node, const Position &start, con
st Position &end) const | 1185 bool ApplyStyleCommand::elementFullySelected(HTMLElement& element, const Positio
n& start, const Position& end) const |
1184 { | 1186 { |
1185 ASSERT(node); | 1187 // The tree may have changed and Position::upstream() relies on an up-to-dat
e layout. |
1186 ASSERT(node->isElementNode()); | 1188 element.document().updateLayoutIgnorePendingStylesheets(); |
1187 | 1189 |
1188 // The tree may have changed and Position::upstream() relies on an up-to-dat
e layout. | 1190 return comparePositions(firstPositionInOrBeforeNode(&element), start) >= 0 |
1189 node->document().updateLayoutIgnorePendingStylesheets(); | 1191 && comparePositions(lastPositionInOrAfterNode(&element).upstream(), end)
<= 0; |
1190 | |
1191 return comparePositions(firstPositionInOrBeforeNode(node), start) >= 0 | |
1192 && comparePositions(lastPositionInOrAfterNode(node).upstream(), end) <=
0; | |
1193 } | 1192 } |
1194 | 1193 |
1195 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position&
end) | 1194 void ApplyStyleCommand::splitTextAtStart(const Position& start, const Position&
end) |
1196 { | 1195 { |
1197 ASSERT(start.containerNode()->isTextNode()); | 1196 ASSERT(start.containerNode()->isTextNode()); |
1198 | 1197 |
1199 Position newEnd; | 1198 Position newEnd; |
1200 if (end.anchorType() == Position::PositionIsOffsetInAnchor && start.containe
rNode() == end.containerNode()) | 1199 if (end.anchorType() == Position::PositionIsOffsetInAnchor && start.containe
rNode() == end.containerNode()) |
1201 newEnd = Position(end.containerText(), end.offsetInContainerNode() - sta
rt.offsetInContainerNode()); | 1200 newEnd = Position(end.containerText(), end.offsetInContainerNode() - sta
rt.offsetInContainerNode()); |
1202 else | 1201 else |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 } | 1401 } |
1403 setNodeAttribute(block, styleAttr, cssText.toAtomicString()); | 1402 setNodeAttribute(block, styleAttr, cssText.toAtomicString()); |
1404 } | 1403 } |
1405 | 1404 |
1406 void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWi
llBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EAddStyled
Element addStyledElement) | 1405 void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWi
llBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EAddStyled
Element addStyledElement) |
1407 { | 1406 { |
1408 if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->
inDocument()) | 1407 if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->
inDocument()) |
1409 return; | 1408 return; |
1410 | 1409 |
1411 RefPtrWillBeRawPtr<Node> start = passedStart; | 1410 RefPtrWillBeRawPtr<Node> start = passedStart; |
1412 RefPtrWillBeMember<Node> dummyElement = nullptr; | 1411 RefPtrWillBeMember<HTMLSpanElement> dummyElement = nullptr; |
1413 StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dum
myElement)); | 1412 StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dum
myElement)); |
1414 | 1413 |
1415 if (dummyElement) | 1414 if (dummyElement) |
1416 removeNode(dummyElement); | 1415 removeNode(dummyElement); |
1417 | 1416 |
1418 applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement); | 1417 applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement); |
1419 } | 1418 } |
1420 | 1419 |
1421 Position ApplyStyleCommand::positionToComputeInlineStyleChange(PassRefPtrWillBeR
awPtr<Node> startNode, RefPtrWillBeMember<Node>& dummyElement) | 1420 Position ApplyStyleCommand::positionToComputeInlineStyleChange(PassRefPtrWillBeR
awPtr<Node> startNode, RefPtrWillBeMember<HTMLSpanElement>& dummyElement) |
1422 { | 1421 { |
1423 // It's okay to obtain the style at the startNode because we've removed all
relevant styles from the current run. | 1422 // It's okay to obtain the style at the startNode because we've removed all
relevant styles from the current run. |
1424 if (!startNode->isElementNode()) { | 1423 if (!startNode->isElementNode()) { |
1425 dummyElement = createStyleSpanElement(document()); | 1424 dummyElement = createStyleSpanElement(document()); |
1426 insertNodeAt(dummyElement, positionBeforeNode(startNode.get())); | 1425 insertNodeAt(dummyElement, positionBeforeNode(startNode.get())); |
1427 return positionBeforeNode(dummyElement.get()); | 1426 return positionBeforeNode(dummyElement.get()); |
1428 } | 1427 } |
1429 | 1428 |
1430 return firstPositionInOrBeforeNode(startNode.get()); | 1429 return firstPositionInOrBeforeNode(startNode.get()); |
1431 } | 1430 } |
1432 | 1431 |
1433 void ApplyStyleCommand::applyInlineStyleChange(PassRefPtrWillBeRawPtr<Node> pass
edStart, PassRefPtrWillBeRawPtr<Node> passedEnd, StyleChange& styleChange, EAddS
tyledElement addStyledElement) | 1432 void ApplyStyleCommand::applyInlineStyleChange(PassRefPtrWillBeRawPtr<Node> pass
edStart, PassRefPtrWillBeRawPtr<Node> passedEnd, StyleChange& styleChange, EAddS
tyledElement addStyledElement) |
1434 { | 1433 { |
1435 RefPtrWillBeRawPtr<Node> startNode = passedStart; | 1434 RefPtrWillBeRawPtr<Node> startNode = passedStart; |
1436 RefPtrWillBeRawPtr<Node> endNode = passedEnd; | 1435 RefPtrWillBeRawPtr<Node> endNode = passedEnd; |
1437 ASSERT(startNode->inDocument()); | 1436 ASSERT(startNode->inDocument()); |
1438 ASSERT(endNode->inDocument()); | 1437 ASSERT(endNode->inDocument()); |
1439 | 1438 |
1440 // Find appropriate font and span elements top-down. | 1439 // Find appropriate font and span elements top-down. |
1441 HTMLElement* fontContainer = 0; | 1440 HTMLFontElement* fontContainer = 0; |
1442 HTMLElement* styleContainer = 0; | 1441 HTMLElement* styleContainer = 0; |
1443 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { | 1442 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { |
1444 if (isHTMLFontElement(*container)) | 1443 if (isHTMLFontElement(*container)) |
1445 fontContainer = toHTMLElement(container); | 1444 fontContainer = toHTMLFontElement(container); |
1446 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); | 1445 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); |
1447 if (container->isHTMLElement()) { | 1446 if (container->isHTMLElement()) { |
1448 HTMLElement* containerElement = toHTMLElement(container); | 1447 HTMLElement* containerElement = toHTMLElement(container); |
1449 if (isHTMLSpanElement(*containerElement) || (styleContainerIsNotSpan
&& containerElement->hasChildren())) | 1448 if (isHTMLSpanElement(*containerElement) || (styleContainerIsNotSpan
&& containerElement->hasChildren())) |
1450 styleContainer = toHTMLElement(container); | 1449 styleContainer = toHTMLElement(container); |
1451 } | 1450 } |
1452 if (!container->firstChild()) | 1451 if (!container->firstChild()) |
1453 break; | 1452 break; |
1454 startNode = container->firstChild(); | 1453 startNode = container->firstChild(); |
1455 endNode = container->lastChild(); | 1454 endNode = container->lastChild(); |
1456 } | 1455 } |
1457 | 1456 |
1458 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. | 1457 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. |
1459 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { | 1458 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { |
1460 if (fontContainer) { | 1459 if (fontContainer) { |
1461 if (styleChange.applyFontColor()) | 1460 if (styleChange.applyFontColor()) |
1462 setNodeAttribute(fontContainer, colorAttr, AtomicString(styleCha
nge.fontColor())); | 1461 setNodeAttribute(fontContainer, colorAttr, AtomicString(styleCha
nge.fontColor())); |
1463 if (styleChange.applyFontFace()) | 1462 if (styleChange.applyFontFace()) |
1464 setNodeAttribute(fontContainer, faceAttr, AtomicString(styleChan
ge.fontFace())); | 1463 setNodeAttribute(fontContainer, faceAttr, AtomicString(styleChan
ge.fontFace())); |
1465 if (styleChange.applyFontSize()) | 1464 if (styleChange.applyFontSize()) |
1466 setNodeAttribute(fontContainer, sizeAttr, AtomicString(styleChan
ge.fontSize())); | 1465 setNodeAttribute(fontContainer, sizeAttr, AtomicString(styleChan
ge.fontSize())); |
1467 } else { | 1466 } else { |
1468 RefPtrWillBeRawPtr<Element> fontElement = createFontElement(document
()); | 1467 RefPtrWillBeRawPtr<HTMLFontElement> fontElement = createFontElement(
document()); |
1469 if (styleChange.applyFontColor()) | 1468 if (styleChange.applyFontColor()) |
1470 fontElement->setAttribute(colorAttr, AtomicString(styleChange.fo
ntColor())); | 1469 fontElement->setAttribute(colorAttr, AtomicString(styleChange.fo
ntColor())); |
1471 if (styleChange.applyFontFace()) | 1470 if (styleChange.applyFontFace()) |
1472 fontElement->setAttribute(faceAttr, AtomicString(styleChange.fon
tFace())); | 1471 fontElement->setAttribute(faceAttr, AtomicString(styleChange.fon
tFace())); |
1473 if (styleChange.applyFontSize()) | 1472 if (styleChange.applyFontSize()) |
1474 fontElement->setAttribute(sizeAttr, AtomicString(styleChange.fon
tSize())); | 1473 fontElement->setAttribute(sizeAttr, AtomicString(styleChange.fon
tSize())); |
1475 surroundNodeRangeWithElement(startNode, endNode, fontElement.get()); | 1474 surroundNodeRangeWithElement(startNode, endNode, fontElement.get()); |
1476 } | 1475 } |
1477 } | 1476 } |
1478 | 1477 |
1479 if (styleChange.cssStyle().length()) { | 1478 if (styleChange.cssStyle().length()) { |
1480 if (styleContainer) { | 1479 if (styleContainer) { |
1481 if (const StylePropertySet* existingStyle = styleContainer->inlineSt
yle()) { | 1480 if (const StylePropertySet* existingStyle = styleContainer->inlineSt
yle()) { |
1482 String existingText = existingStyle->asText(); | 1481 String existingText = existingStyle->asText(); |
1483 StringBuilder cssText; | 1482 StringBuilder cssText; |
1484 cssText.append(existingText); | 1483 cssText.append(existingText); |
1485 if (!existingText.isEmpty()) | 1484 if (!existingText.isEmpty()) |
1486 cssText.append(' '); | 1485 cssText.append(' '); |
1487 cssText.append(styleChange.cssStyle()); | 1486 cssText.append(styleChange.cssStyle()); |
1488 setNodeAttribute(styleContainer, styleAttr, cssText.toAtomicStri
ng()); | 1487 setNodeAttribute(styleContainer, styleAttr, cssText.toAtomicStri
ng()); |
1489 } else { | 1488 } else { |
1490 setNodeAttribute(styleContainer, styleAttr, AtomicString(styleCh
ange.cssStyle())); | 1489 setNodeAttribute(styleContainer, styleAttr, AtomicString(styleCh
ange.cssStyle())); |
1491 } | 1490 } |
1492 } else { | 1491 } else { |
1493 RefPtrWillBeRawPtr<Element> styleElement = createStyleSpanElement(do
cument()); | 1492 RefPtrWillBeRawPtr<HTMLSpanElement> styleElement = createStyleSpanEl
ement(document()); |
1494 styleElement->setAttribute(styleAttr, AtomicString(styleChange.cssSt
yle())); | 1493 styleElement->setAttribute(styleAttr, AtomicString(styleChange.cssSt
yle())); |
1495 surroundNodeRangeWithElement(startNode, endNode, styleElement.releas
e()); | 1494 surroundNodeRangeWithElement(startNode, endNode, styleElement.releas
e()); |
1496 } | 1495 } |
1497 } | 1496 } |
1498 | 1497 |
1499 if (styleChange.applyBold()) | 1498 if (styleChange.applyBold()) |
1500 surroundNodeRangeWithElement(startNode, endNode, createHTMLElement(docum
ent(), bTag)); | 1499 surroundNodeRangeWithElement(startNode, endNode, createHTMLElement(docum
ent(), bTag)); |
1501 | 1500 |
1502 if (styleChange.applyItalic()) | 1501 if (styleChange.applyItalic()) |
1503 surroundNodeRangeWithElement(startNode, endNode, createHTMLElement(docum
ent(), iTag)); | 1502 surroundNodeRangeWithElement(startNode, endNode, createHTMLElement(docum
ent(), iTag)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1572 void ApplyStyleCommand::trace(Visitor* visitor) | 1571 void ApplyStyleCommand::trace(Visitor* visitor) |
1573 { | 1572 { |
1574 visitor->trace(m_style); | 1573 visitor->trace(m_style); |
1575 visitor->trace(m_start); | 1574 visitor->trace(m_start); |
1576 visitor->trace(m_end); | 1575 visitor->trace(m_end); |
1577 visitor->trace(m_styledInlineElement); | 1576 visitor->trace(m_styledInlineElement); |
1578 CompositeEditCommand::trace(visitor); | 1577 CompositeEditCommand::trace(visitor); |
1579 } | 1578 } |
1580 | 1579 |
1581 } | 1580 } |
OLD | NEW |