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

mitz at apple.com mitz at apple.com
Wed Dec 22 13:19:45 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 685d89caae6ec4f4d8e60665ffe3ffc10450f8f6
Author: mitz at apple.com <mitz at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Sep 11 05:55:18 2010 +0000

    <rdar://problem/8414282> Can’t dynamically change first-letter to/from floating
    
    Reviewed by Darin Adler.
    
    WebCore:
    
    Test: fast/dynamic/first-letter-display-change.html
    
    * rendering/RenderBlock.cpp:
    (WebCore::styleForFirstLetter): Factored this helper function out.
    (WebCore::RenderBlock::updateFirstLetter): Renamed variables so that the
    “update style” and “create new” branches use the same terminology. In the
    update case, if the style change requires a new renderer, handle it.
    * rendering/RenderTextFragment.h:
    (WebCore::toRenderTextFragment): Added.
    
    LayoutTests:
    
    * fast/dynamic/first-letter-display-change-expected.checksum: Added.
    * fast/dynamic/first-letter-display-change-expected.png: Added.
    * fast/dynamic/first-letter-display-change-expected.txt: Added.
    * fast/dynamic/first-letter-display-change.html: Added.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@67281 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index cf5e202..dca4ba8 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2010-09-10  Dan Bernstein  <mitz at apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/8414282> Can’t dynamically change first-letter to/from floating
+
+        * fast/dynamic/first-letter-display-change-expected.checksum: Added.
+        * fast/dynamic/first-letter-display-change-expected.png: Added.
+        * fast/dynamic/first-letter-display-change-expected.txt: Added.
+        * fast/dynamic/first-letter-display-change.html: Added.
+
 2010-09-10  Ryosuke Niwa  <rniwa at webkit.org>
 
         Unreviewed.
diff --git a/LayoutTests/fast/dynamic/first-letter-display-change-expected.checksum b/LayoutTests/fast/dynamic/first-letter-display-change-expected.checksum
new file mode 100644
index 0000000..048cc48
--- /dev/null
+++ b/LayoutTests/fast/dynamic/first-letter-display-change-expected.checksum
@@ -0,0 +1 @@
+cfc8dcb729284e0b5680cf5827f1a4c8
\ No newline at end of file
diff --git a/LayoutTests/fast/dynamic/first-letter-display-change-expected.png b/LayoutTests/fast/dynamic/first-letter-display-change-expected.png
new file mode 100644
index 0000000..1a7bf86
Binary files /dev/null and b/LayoutTests/fast/dynamic/first-letter-display-change-expected.png differ
diff --git a/LayoutTests/fast/dynamic/first-letter-display-change-expected.txt b/LayoutTests/fast/dynamic/first-letter-display-change-expected.txt
new file mode 100644
index 0000000..436408b
--- /dev/null
+++ b/LayoutTests/fast/dynamic/first-letter-display-change-expected.txt
@@ -0,0 +1,11 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x16
+        RenderInline (generated) at (0,0) size 16x16 [color=#0000FF]
+          RenderText {#text} at (0,0) size 16x16
+            text run at (0,0) width 16: "L"
+        RenderText {#text} at (16,0) size 400x16
+          text run at (16,0) width 400: "orem ipsum dolor sit amet"
diff --git a/LayoutTests/fast/dynamic/first-letter-display-change.html b/LayoutTests/fast/dynamic/first-letter-display-change.html
new file mode 100644
index 0000000..3d6cfb7
--- /dev/null
+++ b/LayoutTests/fast/dynamic/first-letter-display-change.html
@@ -0,0 +1,10 @@
+<style>
+    .a:first-letter { float: right; font-size: 2em; }
+    .b:first-letter { color: blue; }
+</style>
+<div id="target" style="font-family: ahem;" class="a">Lorem ipsum dolor sit amet</div>
+<script>
+    var target = document.getElementById("target");
+    target.offsetTop;
+    target.className = "b";
+</script>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 44d1d12..afa54bf 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,19 @@
+2010-09-10  Dan Bernstein  <mitz at apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/8414282> Can’t dynamically change first-letter to/from floating
+
+        Test: fast/dynamic/first-letter-display-change.html
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::styleForFirstLetter): Factored this helper function out.
+        (WebCore::RenderBlock::updateFirstLetter): Renamed variables so that the
+        “update style” and “create new” branches use the same terminology. In the
+        update case, if the style change requires a new renderer, handle it.
+        * rendering/RenderTextFragment.h:
+        (WebCore::toRenderTextFragment): Added.
+
 2010-09-10  Sam Weinig  <sam at webkit.org>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index 87ef3e9..cfa86cf 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -5093,6 +5093,16 @@ RenderBlock* RenderBlock::firstLineBlock() const
     return firstLineBlock;
 }
 
+static RenderStyle* styleForFirstLetter(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer)
+{
+    RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER, firstLetterContainer->firstLineStyle());
+    // Force inline display (except for floating first-letters).
+    pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
+    // CSS2 says first-letter can't be positioned.
+    pseudoStyle->setPosition(StaticPosition);
+    return pseudoStyle;
+}
+
 void RenderBlock::updateFirstLetter()
 {
     if (!document()->usesFirstLetterRules())
@@ -5142,84 +5152,110 @@ void RenderBlock::updateFirstLetter()
     if (!currChild)
         return;
 
-    RenderObject* firstLetterContainer = currChild->parent();
-
     // If the child already has style, then it has already been created, so we just want
     // to update it.
-    if (firstLetterContainer->style()->styleType() == FIRST_LETTER) {
-        RenderStyle* pseudo = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
-                                                                     firstLetterContainer->parent()->firstLineStyle());
-        firstLetterContainer->setStyle(pseudo);
-        for (RenderObject* genChild = firstLetterContainer->firstChild(); genChild; genChild = genChild->nextSibling()) {
+    if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
+        RenderObject* firstLetter = currChild->parent();
+        RenderObject* firstLetterContainer = firstLetter->parent();
+        RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
+
+        if (Node::diff(firstLetter->style(), pseudoStyle) == Node::Detach) {
+            // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
+            RenderObject* newFirstLetter;
+            if (pseudoStyle->display() == INLINE)
+                newFirstLetter = new (renderArena()) RenderInline(document());
+            else
+                newFirstLetter = new (renderArena()) RenderBlock(document());
+            newFirstLetter->setStyle(pseudoStyle);
+
+            // Move the first letter into the new renderer.
+            view()->disableLayoutState();
+            while (RenderObject* child = firstLetter->firstChild()) {
+                if (child->isText())
+                    toRenderText(child)->dirtyLineBoxes(true);
+                firstLetter->removeChild(child);
+                newFirstLetter->addChild(child, 0);
+            }
+            RenderTextFragment* remainingText = toRenderTextFragment(firstLetter->nextSibling());
+            ASSERT(remainingText->node()->renderer() == remainingText);
+            // Replace the old renderer with the new one.
+            remainingText->setFirstLetter(newFirstLetter);
+            firstLetter->destroy();
+            firstLetter = newFirstLetter;
+            firstLetterContainer->addChild(firstLetter, remainingText);
+            view()->enableLayoutState();
+        } else
+            firstLetter->setStyle(pseudoStyle);
+
+        for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
             if (genChild->isText()) 
-                genChild->setStyle(pseudo);
+                genChild->setStyle(pseudoStyle);
         }
+
         return;
     }
 
+    if (!currChild->isText() || currChild->isBR())
+        return;
+
     // If the child does not already have style, we create it here.
-    if (currChild->isText() && !currChild->isBR() && currChild->parent()->style()->styleType() != FIRST_LETTER) {
-        // Our layout state is not valid for the repaints we are going to trigger by
-        // adding and removing children of firstLetterContainer.
-        view()->disableLayoutState();
+    RenderObject* firstLetterContainer = currChild->parent();
 
-        RenderText* textObj = toRenderText(currChild);
-        
-        // Create our pseudo style now that we have our firstLetterContainer determined.
-        RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
-                                                                          firstLetterContainer->firstLineStyle());
+    // Our layout state is not valid for the repaints we are going to trigger by
+    // adding and removing children of firstLetterContainer.
+    view()->disableLayoutState();
 
-        // Force inline display (except for floating first-letters)
-        pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
-        pseudoStyle->setPosition(StaticPosition); // CSS2 says first-letter can't be positioned.
-        
-        RenderObject* firstLetter = 0;
-        if (pseudoStyle->display() == INLINE)
-            firstLetter = new (renderArena()) RenderInline(document());
-        else
-            firstLetter = new (renderArena()) RenderBlock(document());
-        firstLetter->setStyle(pseudoStyle);
-        firstLetterContainer->addChild(firstLetter, currChild);
-        
-        // The original string is going to be either a generated content string or a DOM node's
-        // string.  We want the original string before it got transformed in case first-letter has
-        // no text-transform or a different text-transform applied to it.
-        RefPtr<StringImpl> oldText = textObj->originalText();
-        ASSERT(oldText);
-        
-        if (oldText && oldText->length() > 0) {
-            unsigned int length = 0;
-            
-            // account for leading spaces and punctuation
-            while (length < oldText->length() && (isSpaceOrNewline((*oldText)[length]) || Unicode::isPunct((*oldText)[length])))
-                length++;
-            
-            // account for first letter
+    RenderText* textObj = toRenderText(currChild);
+
+    // Create our pseudo style now that we have our firstLetterContainer determined.
+    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
+
+    RenderObject* firstLetter = 0;
+    if (pseudoStyle->display() == INLINE)
+        firstLetter = new (renderArena()) RenderInline(document());
+    else
+        firstLetter = new (renderArena()) RenderBlock(document());
+    firstLetter->setStyle(pseudoStyle);
+    firstLetterContainer->addChild(firstLetter, currChild);
+
+    // The original string is going to be either a generated content string or a DOM node's
+    // string.  We want the original string before it got transformed in case first-letter has
+    // no text-transform or a different text-transform applied to it.
+    RefPtr<StringImpl> oldText = textObj->originalText();
+    ASSERT(oldText);
+
+    if (oldText && oldText->length() > 0) {
+        unsigned length = 0;
+
+        // account for leading spaces and punctuation
+        while (length < oldText->length() && (isSpaceOrNewline((*oldText)[length]) || Unicode::isPunct((*oldText)[length])))
             length++;
-            
-            // construct text fragment for the text after the first letter
-            // NOTE: this might empty
-            RenderTextFragment* remainingText = 
-                new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
-            remainingText->setStyle(textObj->style());
-            if (remainingText->node())
-                remainingText->node()->setRenderer(remainingText);
-            
-            RenderObject* nextObj = textObj->nextSibling();
-            firstLetterContainer->removeChild(textObj);
-            firstLetterContainer->addChild(remainingText, nextObj);
-            remainingText->setFirstLetter(firstLetter);
-            
-            // construct text fragment for the first letter
-            RenderTextFragment* letter = 
-                new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
-            letter->setStyle(pseudoStyle);
-            firstLetter->addChild(letter);
 
-            textObj->destroy();
-        }
-        view()->enableLayoutState();
+        // account for first letter
+        length++;
+
+        // construct text fragment for the text after the first letter
+        // NOTE: this might empty
+        RenderTextFragment* remainingText = 
+            new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
+        remainingText->setStyle(textObj->style());
+        if (remainingText->node())
+            remainingText->node()->setRenderer(remainingText);
+
+        RenderObject* nextObj = textObj->nextSibling();
+        firstLetterContainer->removeChild(textObj);
+        firstLetterContainer->addChild(remainingText, nextObj);
+        remainingText->setFirstLetter(firstLetter);
+        
+        // construct text fragment for the first letter
+        RenderTextFragment* letter = 
+            new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
+        letter->setStyle(pseudoStyle);
+        firstLetter->addChild(letter);
+
+        textObj->destroy();
     }
+    view()->enableLayoutState();
 }
 
 // Helper methods for obtaining the last line, computing line counts and heights for line counts
diff --git a/WebCore/rendering/RenderTextFragment.h b/WebCore/rendering/RenderTextFragment.h
index e351436..e023042 100644
--- a/WebCore/rendering/RenderTextFragment.h
+++ b/WebCore/rendering/RenderTextFragment.h
@@ -59,6 +59,21 @@ private:
     RenderObject* m_firstLetter;
 };
 
+inline RenderTextFragment* toRenderTextFragment(RenderObject* object)
+{ 
+    ASSERT(!object || toRenderText(object)->isTextFragment());
+    return static_cast<RenderTextFragment*>(object);
+}
+
+inline const RenderTextFragment* toRenderTextFragment(const RenderObject* object)
+{ 
+    ASSERT(!object || toRenderText(object)->isTextFragment());
+    return static_cast<const RenderTextFragment*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextFragment(const RenderTextFragment*);
+
 } // namespace WebCore
 
 #endif // RenderTextFragment_h

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list