[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

rniwa at webkit.org rniwa at webkit.org
Wed Dec 22 11:57:03 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit d34b748ca323dc9f101d1e0b9d96134801d85f23
Author: rniwa at webkit.org <rniwa at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Aug 12 02:05:11 2010 +0000

    2010-08-11  Ryosuke Niwa  <rniwa at webkit.org>
    
            Reviewed by Tony Chang.
    
            Can't unbold text in div in font-weight span
            https://bugs.webkit.org/show_bug.cgi?id=26871
    
            The bug was caused by removeInlineStyle not being able to include styled inline nodes around the start.
            Solved this problem by pushing down all inline styles instead of just text-decorations.
            This approach allows removeInlineStyle to remove styled ancestors properly and generates compact markups.
    
            Test: editing/style/push-down-inline-styles.html
    
            * editing/ApplyStyleCommand.cpp:
            (WebCore::ApplyStyleCommand::removeCSSStyle): No longer removes attributes or node when mode == RemoveNone.
            (WebCore::ApplyStyleCommand::highestAncestorWithConflictingInlineStyle): Calls shouldRemoveInlineStyleFromElement
            to determine the highest ancestor whose style needs to be pushed down.
            (WebCore::ApplyStyleCommand::extractInlineStyleToPushDown): Renamed from extractTextDecorationStyle.
            Extracts all inline CSS properties specified instead of just text decorations.
            (WebCore::ApplyStyleCommand::applyInlineStyleToPushDown): Renamed from applyTextDecorationStyle.
            Applies inline styles using addInlineStyleIfNeeded or adds inline CSS values.
            (WebCore::ApplyStyleCommand::pushDownInlineStyleAroundNode): Renamed from pushDownTextDecorationStyleAroundNode.
            (WebCore::ApplyStyleCommand::removeInlineStyle): Calls pushDownTextDecorationStyleAroundNode.
            * editing/ApplyStyleCommand.h:
            * editing/DeleteSelectionCommand.cpp:
            (WebCore::DeleteSelectionCommand::mergeParagraphs): Prevents moveParagraph from preserving
            the style of an empty paragraph when merged with the previous paragraph because we don't use that style anyways.
    2010-08-11  Ryosuke Niwa  <rniwa at webkit.org>
    
            Reviewed by Tony Chang.
    
            Can't unbold text in div in font-weight span
            https://bugs.webkit.org/show_bug.cgi?id=26871
    
            Added a test to push down inline styles to the leaves of DOM tree.
    
            * editing/deleting/delete-br-011-expected.txt: Removed redundant style spans.
            * editing/execCommand/empty-span-removal-expected.txt: Removed a span without any attributes.
            * editing/style/push-down-inline-styles-expected.txt: Added.
            * editing/style/push-down-inline-styles.html: Added.
            * editing/style/script-tests/push-down-inline-styles.js: Added.
            (testSingleToggle):
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65208 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 61dce1a..57b598f 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2010-08-11  Ryosuke Niwa  <rniwa at webkit.org>
+
+        Reviewed by Tony Chang.
+
+        Can't unbold text in div in font-weight span
+        https://bugs.webkit.org/show_bug.cgi?id=26871
+
+        Added a test to push down inline styles to the leaves of DOM tree.
+
+        * editing/deleting/delete-br-011-expected.txt: Removed redundant style spans.
+        * editing/execCommand/empty-span-removal-expected.txt: Removed a span without any attributes.
+        * editing/style/push-down-inline-styles-expected.txt: Added.
+        * editing/style/push-down-inline-styles.html: Added.
+        * editing/style/script-tests/push-down-inline-styles.js: Added.
+        (testSingleToggle):
+
 2010-08-11  Shinichiro Hamaji  <hamaji at chromium.org>
 
         Chromium test_expectations update.
diff --git a/LayoutTests/editing/deleting/delete-br-011-expected.txt b/LayoutTests/editing/deleting/delete-br-011-expected.txt
index 6f7a7dc..6025b04 100644
--- a/LayoutTests/editing/deleting/delete-br-011-expected.txt
+++ b/LayoutTests/editing/deleting/delete-br-011-expected.txt
@@ -26,16 +26,7 @@ after deletion:
 | <div>
 |   class="editing"
 |   id="test"
-|   <span>
-|     class="Apple-style-span"
-|     style="font-size: medium;"
-|     <font>
-|       class="Apple-style-span"
-|       size="6"
-|       <span>
-|         class="Apple-style-span"
-|         style="font-size: 24px;"
-|         <#selection-caret>
-|         <br>
+|   <#selection-caret>
+|   <br>
 | "
 "
diff --git a/LayoutTests/editing/execCommand/empty-span-removal-expected.txt b/LayoutTests/editing/execCommand/empty-span-removal-expected.txt
index 6480bfe..6e1fa76 100644
--- a/LayoutTests/editing/execCommand/empty-span-removal-expected.txt
+++ b/LayoutTests/editing/execCommand/empty-span-removal-expected.txt
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS one bold command converted <span><span style='font-weight: bold'>test</span></span> to <span>test</span>
-PASS one bold command converted <span style='font-weight: bold'><span>test</span></span> to <span>test</span>
+PASS one bold command converted <span style='font-weight: bold'><span>test</span></span> to test
 PASS one bold command converted <span style='font-weight: bold'><span style='font-weight: bold'>test</span></span> to test
 PASS one bold command converted <span foo="bar" style='font-weight: bold'>test</span> to <span foo="bar">test</span>
 PASS two bold commands converted <span>test</span> to <span>test</span>
diff --git a/LayoutTests/editing/execCommand/script-tests/empty-span-removal.js b/LayoutTests/editing/execCommand/script-tests/empty-span-removal.js
index 7bb8d95..2e5e604 100644
--- a/LayoutTests/editing/execCommand/script-tests/empty-span-removal.js
+++ b/LayoutTests/editing/execCommand/script-tests/empty-span-removal.js
@@ -30,7 +30,7 @@ function testDoubleToggle(toggleCommand, initialContents, expectedContents)
 }
 
 testSingleToggle("bold", "<span><span style='font-weight: bold'>test</span></span>", "<span>test</span>");
-testSingleToggle("bold", "<span style='font-weight: bold'><span>test</span></span>", "<span>test</span>");
+testSingleToggle("bold", "<span style='font-weight: bold'><span>test</span></span>", "test");
 testSingleToggle("bold", "<span style='font-weight: bold'><span style='font-weight: bold'>test</span></span>", "test");
 testSingleToggle("bold", "<span foo=\"bar\" style='font-weight: bold'>test</span>", "<span foo=\"bar\">test</span>");
 testDoubleToggle("bold", "<span>test</span>", "<span>test</span>");
diff --git a/LayoutTests/editing/style/push-down-inline-styles-expected.txt b/LayoutTests/editing/style/push-down-inline-styles-expected.txt
new file mode 100644
index 0000000..c2b198a
--- /dev/null
+++ b/LayoutTests/editing/style/push-down-inline-styles-expected.txt
@@ -0,0 +1,28 @@
+Test to make sure we push down inline styles properly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS bold converted <span style="font-weight: 900;"> <div>text</div> </span> to  <div>text</div> 
+PASS bold converted <span style="font-weight: 900;"><div>text</div></span> to <div>text</div>
+PASS bold converted <span style="font-weight: 900;"><div id="test">hello</div><div>world</div></span> to <div id="test">hello</div><div style="font-weight: 900; ">world</div>
+PASS bold converted <div style="font-weight: bold;">hello<div id="test">world</div></div> to <div><b>hello</b><div id="test">world</div></div>
+PASS bold converted <span style="font-weight: bold;">hello<span id="test">world</div></div> to <b>hello</b><span id="test">world</span>
+PASS bold converted <span style="font-style: italic; font-weight: bold;">hello<span id="test">world</div></div> to <span style="font-style: italic; "><b>hello</b><span id="test">world</span></span>
+FAIL bold converted <span style="font-weight: bold;"><div id="test">hello</div><div style="font-weight: normal;"><div>world</div>webkit</div> to <div id="test">hello</div><div style="font-weight: normal; "><div>world</div>webkit</div>, expected <div id="test">hello</div><div>world</div>webkit
+PASS italic converted <span style="font-style: italic;"><div>hello</div></span> to <div>hello</div>
+PASS italic converted <span style="font-style: italic;"><div id="test">hello</div><span style="font-style: oblique;">world</span> to <div id="test">hello</div><span style="font-style: oblique; ">world</span>
+PASS italic converted <span style="font-style: italic; font-weight: bold;"><div>hello</div></span> to <span style="font-weight: bold; "><div>hello</div></span>
+PASS italic converted <span style="font-style: italic; text-decoration: line-through;"><div>hello</div></span> to <span style="text-decoration: line-through; "><div>hello</div></span>
+PASS italic converted <span style="font-style: italic;">hello<div id="test">world</div><blockquote>webkit</blockquote></span> to <i>hello</i><div id="test">world</div><blockquote style="font-style: italic; ">webkit</blockquote>
+PASS italic converted <span style="font-style: italic;">hello <span id="test">world</span> webkit</span> to <i>hello </i><span id="test">world</span><i> webkit</i>
+PASS underline converted <span style="text-decoration: underline;"><div id="test">hello</div>world</span> to <div id="test">hello</div><u>world</u>
+PASS underline converted <span style="text-decoration: underline;"><div id="test">hello</div><blockquote>world<br>webkit</blockquote></span> to <div id="test">hello</div><blockquote style="text-decoration: underline; ">world<br>webkit</blockquote>
+PASS underline converted <span style="text-decoration: underline;">hello<div id="test">world</div>webkit</u> to <u>hello</u><div id="test">world</div><u>webkit</u>
+FAIL underline converted <div style="text-decoration: underline;"><div>hello</span></div><div id="test">webkit</div><span style="font-style: italic;">rocks</span> to <div><div style="text-decoration: underline; ">hello</div><div id="test">webkit</div><span style="font-style: italic; text-decoration: underline; ">rocks</span></div>, expected <div><div style="text-decoration: underline; ">hello</span></div><div id="test">webkit</div><u><span style="font-style: italic;">rocks</span></u></div>
+PASS underline converted <span style="text-decoration: underline;"><div style="text-decoration: line-through;">hello</div><div id="test">world</div></span> to <div style="text-decoration: line-through underline; ">hello</div><div id="test">world</div>
+PASS strikeThrough converted <span style="text-decoration: line-through;"><div id="test">hello</div><div style="text-decoration: underline;">world</div></span> to <div id="test">hello</div><div style="text-decoration: underline line-through; ">world</div>
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/style/push-down-inline-styles.html b/LayoutTests/editing/style/push-down-inline-styles.html
new file mode 100644
index 0000000..f9b80eb
--- /dev/null
+++ b/LayoutTests/editing/style/push-down-inline-styles.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/push-down-inline-styles.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/editing/style/script-tests/push-down-inline-styles.js b/LayoutTests/editing/style/script-tests/push-down-inline-styles.js
new file mode 100644
index 0000000..8a010bd
--- /dev/null
+++ b/LayoutTests/editing/style/script-tests/push-down-inline-styles.js
@@ -0,0 +1,48 @@
+description('Test to make sure we push down inline styles properly.');
+
+var testContainer = document.createElement("div");
+testContainer.contentEditable = true;
+document.body.appendChild(testContainer);
+
+function testSingleToggle(toggleCommand, initialContents, expectedContents)
+{
+    testContainer.innerHTML = initialContents;
+    if (document.getElementById('test'))
+        window.getSelection().selectAllChildren(document.getElementById('test'));
+    else
+        window.getSelection().selectAllChildren(testContainer);
+    document.execCommand('styleWithCSS', false, 'false');
+    document.execCommand(toggleCommand, false, null);
+    if (testContainer.innerHTML === expectedContents) {
+        testPassed(toggleCommand + " converted " + initialContents + " to " + expectedContents);
+    } else {
+        testFailed(toggleCommand + " converted " + initialContents + " to " + testContainer.innerHTML + ", expected " + expectedContents);
+    }
+}
+
+
+testSingleToggle("bold", '<span style="font-weight: 900;"> <div>text</div> </span>', ' <div>text</div> ');
+testSingleToggle("bold", '<span style="font-weight: 900;"><div>text</div></span>', '<div>text</div>');
+testSingleToggle("bold", '<span style="font-weight: 900;"><div id="test">hello</div><div>world</div></span>', '<div id="test">hello</div><div style="font-weight: 900; ">world</div>');
+testSingleToggle("bold", '<div style="font-weight: bold;">hello<div id="test">world</div></div>', '<div><b>hello</b><div id="test">world</div></div>');
+testSingleToggle("bold", '<span style="font-weight: bold;">hello<span id="test">world</div></div>', '<b>hello</b><span id="test">world</span>');
+testSingleToggle("bold", '<span style="font-style: italic; font-weight: bold;">hello<span id="test">world</div></div>', '<span style="font-style: italic; "><b>hello</b><span id="test">world</span></span>');
+testSingleToggle("bold", '<span style="font-weight: bold;"><div id="test">hello</div><div style="font-weight: normal;"><div>world</div>webkit</div>', '<div id="test">hello</div><div>world</div>webkit');
+testSingleToggle("italic", '<span style="font-style: italic;"><div>hello</div></span>', '<div>hello</div>');
+testSingleToggle("italic", '<span style="font-style: italic;"><div id="test">hello</div><span style="font-style: oblique;">world</span>', '<div id="test">hello</div><span style="font-style: oblique; ">world</span>');
+testSingleToggle("italic", '<span style="font-style: italic; font-weight: bold;"><div>hello</div></span>', '<span style="font-weight: bold; "><div>hello</div></span>');
+testSingleToggle("italic", '<span style="font-style: italic; text-decoration: line-through;"><div>hello</div></span>', '<span style="text-decoration: line-through; "><div>hello</div></span>');
+testSingleToggle("italic", '<span style="font-style: italic;">hello<div id="test">world</div><blockquote>webkit</blockquote></span>', '<i>hello</i><div id="test">world</div><blockquote style="font-style: italic; ">webkit</blockquote>');
+testSingleToggle("italic", '<span style="font-style: italic;">hello <span id="test">world</span> webkit</span>', '<i>hello </i><span id="test">world</span><i> webkit</i>');
+testSingleToggle("underline", '<span style="text-decoration: underline;"><div id="test">hello</div>world</span>', '<div id="test">hello</div><u>world</u>');
+testSingleToggle("underline", '<span style="text-decoration: underline;"><div id="test">hello</div><blockquote>world<br>webkit</blockquote></span>', '<div id="test">hello</div><blockquote style="text-decoration: underline; ">world<br>webkit</blockquote>');
+testSingleToggle("underline", '<span style="text-decoration: underline;">hello<div id="test">world</div>webkit</u>', '<u>hello</u><div id="test">world</div><u>webkit</u>');
+testSingleToggle("underline",
+    '<div style="text-decoration: underline;"><div>hello</span></div><div id="test">webkit</div><span style="font-style: italic;">rocks</span>',
+    '<div><div style="text-decoration: underline; ">hello</span></div><div id="test">webkit</div><u><span style="font-style: italic;">rocks</span></u></div>');
+testSingleToggle("underline", '<span style="text-decoration: underline;"><div style="text-decoration: line-through;">hello</div><div id="test">world</div></span>', '<div style="text-decoration: line-through underline; ">hello</div><div id="test">world</div>');
+testSingleToggle("strikeThrough", '<span style="text-decoration: line-through;"><div id="test">hello</div><div style="text-decoration: underline;">world</div></span>', '<div id="test">hello</div><div style="text-decoration: underline line-through; ">world</div>');
+
+document.body.removeChild(testContainer);
+
+var successfullyParsed = true;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 1a01eb4..53d3ec0 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,31 @@
+2010-08-11  Ryosuke Niwa  <rniwa at webkit.org>
+
+        Reviewed by Tony Chang.
+
+        Can't unbold text in div in font-weight span
+        https://bugs.webkit.org/show_bug.cgi?id=26871
+
+        The bug was caused by removeInlineStyle not being able to include styled inline nodes around the start.
+        Solved this problem by pushing down all inline styles instead of just text-decorations.
+        This approach allows removeInlineStyle to remove styled ancestors properly and generates compact markups.
+
+        Test: editing/style/push-down-inline-styles.html
+
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::ApplyStyleCommand::removeCSSStyle): No longer removes attributes or node when mode == RemoveNone.
+        (WebCore::ApplyStyleCommand::highestAncestorWithConflictingInlineStyle): Calls shouldRemoveInlineStyleFromElement
+        to determine the highest ancestor whose style needs to be pushed down.
+        (WebCore::ApplyStyleCommand::extractInlineStyleToPushDown): Renamed from extractTextDecorationStyle.
+        Extracts all inline CSS properties specified instead of just text decorations.
+        (WebCore::ApplyStyleCommand::applyInlineStyleToPushDown): Renamed from applyTextDecorationStyle.
+        Applies inline styles using addInlineStyleIfNeeded or adds inline CSS values.
+        (WebCore::ApplyStyleCommand::pushDownInlineStyleAroundNode): Renamed from pushDownTextDecorationStyleAroundNode.
+        (WebCore::ApplyStyleCommand::removeInlineStyle): Calls pushDownTextDecorationStyleAroundNode.
+        * editing/ApplyStyleCommand.h:
+        * editing/DeleteSelectionCommand.cpp:
+        (WebCore::DeleteSelectionCommand::mergeParagraphs): Prevents moveParagraph from preserving
+        the style of an empty paragraph when merged with the previous paragraph because we don't use that style anyways.
+
 2010-08-11  Julien Chaffraix  <jchaffraix at codeaurora.org>
 
         Reviewed by Ariya Hidayat.
diff --git a/WebCore/editing/ApplyStyleCommand.cpp b/WebCore/editing/ApplyStyleCommand.cpp
index a9d1509..f9e827b 100644
--- a/WebCore/editing/ApplyStyleCommand.cpp
+++ b/WebCore/editing/ApplyStyleCommand.cpp
@@ -1311,6 +1311,9 @@ bool ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLEl
         }
     }
 
+    if (mode == RemoveNone)
+        return removed;
+
     // No need to serialize <foo style=""> if we just removed the last css property
     if (decl->isEmpty())
         removeNodeAttribute(elem, styleAttr);
@@ -1321,24 +1324,17 @@ bool ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLEl
     return removed;
 }
 
-static bool hasTextDecorationProperty(Node *node)
+HTMLElement* ApplyStyleCommand::highestAncestorWithConflictingInlineStyle(CSSMutableStyleDeclaration* style, Node* node)
 {
-    if (!node->isElementNode())
-        return false;
-
-    RefPtr<CSSValue> value = computedStyle(node)->getPropertyCSSValue(CSSPropertyTextDecoration, DoNotUpdateLayout);
-    return value && !equalIgnoringCase(value->cssText(), "none");
-}
+    if (!node)
+        return 0;
 
-static Node* highestAncestorWithTextDecoration(Node *node)
-{
-    ASSERT(node);
-    Node* result = 0;
+    HTMLElement* result = 0;
     Node* unsplittableElement = unsplittableElementForPosition(Position(node, 0));
 
     for (Node *n = node; n; n = n->parentNode()) {
-        if (hasTextDecorationProperty(n))
-            result = n;
+        if (n->isHTMLElement() && shouldRemoveInlineStyleFromElement(style, static_cast<HTMLElement*>(n)))
+            result = static_cast<HTMLElement*>(n);
         // Should stop at the editable root (cannot cross editing boundary) and
         // also stop at the unsplittable element to be consistent with other UAs
         if (n == unsplittableElement)
@@ -1348,7 +1344,7 @@ static Node* highestAncestorWithTextDecoration(Node *node)
     return result;
 }
 
-PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractTextDecorationStyle(Node* node)
+PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractInlineStyleToPushDown(Node* node, const Vector<int>& properties)
 {
     ASSERT(node);
     ASSERT(node->isElementNode());
@@ -1362,72 +1358,108 @@ PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractTextDecorationS
     if (!style)
         return 0;
 
-    int properties[1] = { CSSPropertyTextDecoration };
-    RefPtr<CSSMutableStyleDeclaration> textDecorationStyle = style->copyPropertiesInSet(properties, 1);
+    style = style->copyPropertiesInSet(properties.data(), properties.size());
+
+    for (size_t i = 0; i < properties.size(); i++) {
+        RefPtr<CSSValue> property = style->getPropertyCSSValue(properties[i]);
+        if (property)
+            removeCSSProperty(element, static_cast<CSSPropertyID>(properties[i]));
+    }
 
-    RefPtr<CSSValue> property = style->getPropertyCSSValue(CSSPropertyTextDecoration);
-    if (property && !equalIgnoringCase(property->cssText(), "none"))
-        removeCSSProperty(element, CSSPropertyTextDecoration);
+    if (element->inlineStyleDecl() && element->inlineStyleDecl()->isEmpty())
+        removeNodeAttribute(element, styleAttr);
 
-    return textDecorationStyle.release();
+    if (isSpanWithoutAttributesOrUnstyleStyleSpan(element))
+        removeNodePreservingChildren(element);
+
+    return style.release();
 }
 
-void ApplyStyleCommand::applyTextDecorationStyle(Node *node, CSSMutableStyleDeclaration *style)
+void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, CSSMutableStyleDeclaration* style)
 {
     ASSERT(node);
 
-    if (!style || style->cssText().isEmpty())
+    if (!style || !style->length() || !node->renderer())
         return;
 
-    StyleChange styleChange(style, Position(node, 0));
-    if (styleChange.cssStyle().length()) {
-        if (node->isTextNode()) {
-            RefPtr<HTMLElement> styleSpan = createStyleSpanElement(document());
-            surroundNodeRangeWithElement(node, node, styleSpan.get());
-            node = styleSpan.get();
-        }
+    // Since addInlineStyleIfNeeded can't add styles to block-flow render objects, add style attribute instead.
+    // FIXME: applyInlineStyleToRange should be used here instead.
+    if ((node->renderer()->isBlockFlow() || node->childNodeCount()) && node->isHTMLElement()) {
+        HTMLElement* element = static_cast<HTMLElement*>(node);
+        CSSMutableStyleDeclaration* existingInlineStyle = element->inlineStyleDecl();
+
+        // Avoid overriding existing styles of node
+        if (existingInlineStyle) {
+            RefPtr<CSSMutableStyleDeclaration> newInlineStyle = existingInlineStyle->copy();
+            CSSMutableStyleDeclaration::const_iterator end = style->end();
+            for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
+                ExceptionCode ec;
+                if (!existingInlineStyle->getPropertyCSSValue(it->id()))
+                    newInlineStyle->setProperty(it->id(), it->value()->cssText(), it->isImportant(), ec);
+
+                // text-decorations adds up
+                if (it->id() == CSSPropertyTextDecoration) {
+                    ASSERT(it->value()->isValueList());
+                    RefPtr<CSSValue> textDecoration = newInlineStyle->getPropertyCSSValue(CSSPropertyTextDecoration);
+                    if (textDecoration) {
+                        ASSERT(textDecoration->isValueList());
+                        CSSValueList* textDecorationOfInlineStyle = static_cast<CSSValueList*>(textDecoration.get());
+                        CSSValueList* textDecorationOfStyleApplied = static_cast<CSSValueList*>(it->value());
+
+                        DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline)));
+                        DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough)));
+                        
+                        if (textDecorationOfStyleApplied->hasValue(underline.get()) && !textDecorationOfInlineStyle->hasValue(underline.get()))
+                            textDecorationOfInlineStyle->append(underline.get());
+
+                        if (textDecorationOfStyleApplied->hasValue(lineThrough.get()) && !textDecorationOfInlineStyle->hasValue(lineThrough.get()))
+                            textDecorationOfInlineStyle->append(lineThrough.get());
+                    }
+                }
+            }
 
-        if (!node->isElementNode())
-            return;
+            setNodeAttribute(element, styleAttr, newInlineStyle->cssText());
+        } else
+            setNodeAttribute(element, styleAttr, style->cssText());
 
-        HTMLElement *element = static_cast<HTMLElement *>(node);
-        String cssText = styleChange.cssStyle();
-        CSSMutableStyleDeclaration *decl = element->inlineStyleDecl();
-        if (decl)
-            cssText += decl->cssText();
-        setNodeAttribute(element, styleAttr, cssText);
+        return;
     }
 
-    if (styleChange.applyUnderline())
-        surroundNodeRangeWithElement(node, node, createHTMLElement(document(), uTag));
+    if (node->renderer()->isText() && static_cast<RenderText*>(node->renderer())->isAllCollapsibleWhitespace())
+        return;
 
-    if (styleChange.applyLineThrough())
-        surroundNodeRangeWithElement(node, node, createHTMLElement(document(), sTag));    
+    // FIXME: addInlineStyleIfNeeded may override the style of node
+    addInlineStyleIfNeeded(style, node, node);
 }
 
-void ApplyStyleCommand::pushDownTextDecorationStyleAroundNode(Node* targetNode)
+void ApplyStyleCommand::pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration* style, Node* targetNode)
 {
-    ASSERT(targetNode);
-    Node* highestAncestor = highestAncestorWithTextDecoration(targetNode);
+    HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(style, targetNode);
     if (!highestAncestor)
         return;
 
+    Vector<int> properties;
+    CSSMutableStyleDeclaration::const_iterator end = style->end();
+    for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it)
+        properties.append(it->id());
+
     // The outer loop is traversing the tree vertically from highestAncestor to targetNode
     Node* current = highestAncestor;
     while (current != targetNode) {
         ASSERT(current);
+        ASSERT(current->isHTMLElement());
         ASSERT(current->contains(targetNode));
-        RefPtr<CSSMutableStyleDeclaration> decoration = extractTextDecorationStyle(current);
+        Node* child = current->firstChild();
+        RefPtr<CSSMutableStyleDeclaration> styleToPushDown = extractInlineStyleToPushDown(current, properties);
 
         // The inner loop will go through children on each level
-        Node* child = current->firstChild();
         while (child) {
             Node* nextChild = child->nextSibling();
 
             // Apply text decoration to all nodes containing targetNode and their siblings but NOT to targetNode
             if (child != targetNode)
-                applyTextDecorationStyle(child, decoration.get());
-            
+                applyInlineStyleToPushDown(child, styleToPushDown.get());
+
             // We found the next node for the outer loop (contains targetNode)
             // When reached targetNode, stop the outer loop upon the completion of the current inner loop
             if (child == targetNode || child->contains(targetNode))
@@ -1447,14 +1479,15 @@ void ApplyStyleCommand::removeInlineStyle(PassRefPtr<CSSMutableStyleDeclaration>
     ASSERT(comparePositions(start, end) <= 0);
     
     RefPtr<CSSValue> textDecorationSpecialProperty = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
-
     if (textDecorationSpecialProperty) {
-        pushDownTextDecorationStyleAroundNode(start.downstream().node());
-        pushDownTextDecorationStyleAroundNode(end.upstream().node());
         style = style->copy();
         style->setProperty(CSSPropertyTextDecoration, textDecorationSpecialProperty->cssText(), style->getPropertyPriority(CSSPropertyWebkitTextDecorationsInEffect));
     }
 
+    RefPtr<Node> pushDownEnd = end.upstream().node();
+    pushDownInlineStyleAroundNode(style.get(), start.downstream().node());
+    pushDownInlineStyleAroundNode(style.get(), pushDownEnd.get());
+
     // The s and e variables store the positions used to set the ending selection after style removal
     // takes place. This will help callers to recognize when either the start node or the end node
     // are removed from the document during the work of this function.
diff --git a/WebCore/editing/ApplyStyleCommand.h b/WebCore/editing/ApplyStyleCommand.h
index 86c24da..f4ecc7c 100644
--- a/WebCore/editing/ApplyStyleCommand.h
+++ b/WebCore/editing/ApplyStyleCommand.h
@@ -78,12 +78,13 @@ private:
     bool removeHTMLFontStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements);
     bool removeHTMLBidiEmbeddingStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements);
     bool removeCSSStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements);
+    HTMLElement* highestAncestorWithConflictingInlineStyle(CSSMutableStyleDeclaration*, Node*);
+    PassRefPtr<CSSMutableStyleDeclaration> extractInlineStyleToPushDown(Node*, const Vector<int>&);
+    void applyInlineStyleToPushDown(Node*, CSSMutableStyleDeclaration *style);
+    void pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration*, Node*);
     void removeInlineStyle(PassRefPtr<CSSMutableStyleDeclaration>, const Position& start, const Position& end);
     bool nodeFullySelected(Node*, const Position& start, const Position& end) const;
     bool nodeFullyUnselected(Node*, const Position& start, const Position& end) const;
-    PassRefPtr<CSSMutableStyleDeclaration> extractTextDecorationStyle(Node*);
-    void applyTextDecorationStyle(Node*, CSSMutableStyleDeclaration *style);
-    void pushDownTextDecorationStyleAroundNode(Node*);
 
     // style-application helpers
     void applyBlockStyle(CSSMutableStyleDeclaration*);
diff --git a/WebCore/editing/DeleteSelectionCommand.cpp b/WebCore/editing/DeleteSelectionCommand.cpp
index c37b0fc..5e025eb 100644
--- a/WebCore/editing/DeleteSelectionCommand.cpp
+++ b/WebCore/editing/DeleteSelectionCommand.cpp
@@ -630,7 +630,8 @@ void DeleteSelectionCommand::mergeParagraphs()
     // moveParagraphs will insert placeholders if it removes blocks that would require their use, don't let block
     // removals that it does cause the insertion of *another* placeholder.
     bool needPlaceholder = m_needPlaceholder;
-    moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination);
+    bool paragraphToMergeIsEmpty = (startOfParagraphToMove == endOfParagraphToMove);
+    moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination, false, !paragraphToMergeIsEmpty);
     m_needPlaceholder = needPlaceholder;
     // The endingPosition was likely clobbered by the move, so recompute it (moveParagraph selects the moved paragraph).
     m_endingPosition = endingSelection().start();

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list