[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75

simon.fraser at apple.com simon.fraser at apple.com
Thu Oct 29 20:35:01 UTC 2009


The following commit has been merged in the webkit-1.1 branch:
commit dcacba1e4fec78a0cbd9f62f8ea6c2361c14265a
Author: simon.fraser at apple.com <simon.fraser at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Sep 28 16:14:18 2009 +0000

    2009-09-25  Simon Fraser  <simon.fraser at apple.com>
    
            Reviewed by Darin Adler.
    
            ASSERTION FAILED: !repaintContainer || repaintContainer == this
            https://bugs.webkit.org/show_bug.cgi?id=29755
    
            It's possible for RenderObject::container() to return an object that is higher
            in the hierarchy than the repaintContainer that is being used to repaint an
            object. For example, this can happen when running an accelerated opacity
            transition on an element with a position:absolute parent, and a position:absolute child.
    
            In this case we need to detect when RenderObject::container() will skip over
            repaintContainer, and in that case adjust the coords to shift into repaintContainer's space.
    
            Test: compositing/repaint/opacity-between-absolute.html
    
            * rendering/RenderBox.cpp:
            (WebCore::RenderBox::mapLocalToContainer):
            (WebCore::RenderBox::computeRectForRepaint):
            * rendering/RenderInline.cpp:
            (WebCore::RenderInline::computeRectForRepaint):
            * rendering/RenderObject.cpp:
            (WebCore::RenderObject::container):
            * rendering/RenderObject.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48816 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 008b8da..7fce347 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -77,6 +77,20 @@
 
         Reviewed by Darin Adler.
 
+        ASSERTION FAILED: !repaintContainer || repaintContainer == this
+        https://bugs.webkit.org/show_bug.cgi?id=29755
+        
+        Testcase with an opacity-fading element between two absolutely positioned elements.
+
+        * compositing/repaint/opacity-between-absolute.html: Added.
+        * platform/mac/compositing/repaint/opacity-between-absolute-expected.checksum: Added.
+        * platform/mac/compositing/repaint/opacity-between-absolute-expected.png: Added.
+        * platform/mac/compositing/repaint/opacity-between-absolute-expected.txt: Added.
+
+2009-09-25  Simon Fraser  <simon.fraser at apple.com>
+
+        Reviewed by Darin Adler.
+
         Crash with hardware accelerated rotation of a PDF image in a data URL
         <rdar://problem/7250378>
         
diff --git a/LayoutTests/compositing/repaint/opacity-between-absolute.html b/LayoutTests/compositing/repaint/opacity-between-absolute.html
new file mode 100644
index 0000000..20033cb
--- /dev/null
+++ b/LayoutTests/compositing/repaint/opacity-between-absolute.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+
+<html lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Opacity between absolutes</title>
+  <style type="text/css" media="screen">
+    .container {
+      position: relative;
+      height: 200px;
+      width: 200px;
+      border: 1px solid black;
+      -webkit-transform: translateZ(0);
+      -webkit-transform-style: preserve-3d;
+    }
+
+    .fader {
+      height: 50px;
+      width: 50px;
+      margin: 20px;
+      border: 1px solid black;
+      -webkit-transition: opacity 100s;
+    }
+    
+    .container:hover .fader {
+      opacity: 0.5;
+    }
+
+    .inner {
+      position: absolute;
+      left: 100px;
+      top: 100px;
+      height: 80px;
+      width: 80px;
+      background-color: gray;
+    }
+    
+    .inner:hover {
+      background-color: orange;
+    }
+  </style>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController)
+      layoutTestController.waitUntilDone();
+
+    function runTest()
+    {
+      // Kick off an opacity fade to make .fader into a compositing layer
+      var container = document.querySelectorAll('.fader')[0];
+      container.style.opacity = 0.99;
+      window.setTimeout(function() {
+        // Now test redraw on .inner
+        var inner = document.querySelectorAll('.inner')[0];
+        inner.style.backgroundColor = 'green';
+        if (window.layoutTestController)
+          layoutTestController.notifyDone();
+      }, 0);
+    }
+
+    window.addEventListener('load', runTest, false)
+  </script>
+</head>
+<body>
+<p>This test should not assert, and you should see a fully green square.</p>
+<div class="container">
+  <div class="fader">
+    <div class="inner">
+    </div>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.checksum b/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.checksum
new file mode 100644
index 0000000..2cc5165
--- /dev/null
+++ b/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.checksum
@@ -0,0 +1 @@
+df3e21ebea67173cc9205bf8482cebab
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.png b/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.png
new file mode 100644
index 0000000..4a81de8
Binary files /dev/null and b/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.png differ
diff --git a/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.txt b/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.txt
new file mode 100644
index 0000000..c34e41d
--- /dev/null
+++ b/LayoutTests/platform/mac/compositing/repaint/opacity-between-absolute-expected.txt
@@ -0,0 +1,14 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x260
+  RenderBlock {HTML} at (0,0) size 800x260
+    RenderBody {BODY} at (8,16) size 784x236
+      RenderBlock {P} at (0,0) size 784x18
+        RenderText {#text} at (0,0) size 423x18
+          text run at (0,0) width 423: "This test should not assert, and you should see a fully green square."
+layer at (8,50) size 202x202
+  RenderBlock (relative positioned) {DIV} at (0,34) size 202x202 [border: (1px solid #000000)]
+layer at (29,71) size 52x52
+  RenderBlock {DIV} at (21,21) size 52x52 [border: (1px solid #000000)]
+layer at (109,151) size 80x80
+  RenderBlock (positioned) {DIV} at (101,101) size 80x80 [bgcolor=#008000]
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 76a724f..1590b32 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -665,6 +665,32 @@
 
         Reviewed by Darin Adler.
 
+        ASSERTION FAILED: !repaintContainer || repaintContainer == this
+        https://bugs.webkit.org/show_bug.cgi?id=29755
+        
+        It's possible for RenderObject::container() to return an object that is higher
+        in the hierarchy than the repaintContainer that is being used to repaint an
+        object. For example, this can happen when running an accelerated opacity
+        transition on an element with a position:absolute parent, and a position:absolute child.
+        
+        In this case we need to detect when RenderObject::container() will skip over
+        repaintContainer, and in that case adjust the coords to shift into repaintContainer's space.
+
+        Test: compositing/repaint/opacity-between-absolute.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::mapLocalToContainer):
+        (WebCore::RenderBox::computeRectForRepaint):
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::computeRectForRepaint):
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::container):
+        * rendering/RenderObject.h:
+
+2009-09-25  Simon Fraser  <simon.fraser at apple.com>
+
+        Reviewed by Darin Adler.
+
         Crash with hardware accelerated rotation of a PDF image in a data URL
         <rdar://problem/7250378>
         
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
index dd58ed1..c8d3037 100644
--- a/WebCore/rendering/RenderBox.cpp
+++ b/WebCore/rendering/RenderBox.cpp
@@ -941,7 +941,8 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool
     if (style()->position() == FixedPosition)
         fixed = true;
 
-    RenderObject* o = container();
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
     if (!o)
         return;
 
@@ -959,6 +960,14 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool
     } else
         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
 
+    if (containerSkipped) {
+        // There can't be a transfrom between repaintContainer and o, because transforms create containers, so it should be safe
+        // to just subtract the delta between the repaintContainer and o.
+        IntSize repaintContainerOffset = repaintContainer->offsetFromContainer(o);
+        transformState.move(-repaintContainerOffset.width(), -repaintContainerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+        return;
+    }
+    
     o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);
 }
 
@@ -1131,7 +1140,8 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In
     if (repaintContainer == this)
         return;
 
-    RenderObject* o = container();
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
     if (!o)
         return;
 
@@ -1188,6 +1198,13 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In
             return;
     } else
         rect.setLocation(topLeft);
+
+    if (containerSkipped) {
+        // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
+        IntSize containerOffset = repaintContainer->offsetFromContainer(o);
+        rect.move(-containerOffset);
+        return;
+    }
     
     o->computeRectForRepaint(repaintContainer, rect, fixed);
 }
diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp
index 07b28cc..a5e973e 100644
--- a/WebCore/rendering/RenderInline.cpp
+++ b/WebCore/rendering/RenderInline.cpp
@@ -652,7 +652,8 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer,
     if (repaintContainer == this)
         return;
 
-    RenderObject* o = container();
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
     if (!o)
         return;
 
@@ -693,6 +694,13 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer,
             return;
     } else
         rect.setLocation(topLeft);
+
+    if (containerSkipped) {
+        // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
+        IntSize containerOffset = repaintContainer->offsetFromContainer(o);
+        rect.move(-containerOffset);
+        return;
+    }
     
     o->computeRectForRepaint(repaintContainer, rect, fixed);
 }
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 1d5ed0c..b7f59e1 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -1788,8 +1788,11 @@ bool RenderObject::hasOutlineAnnotation() const
     return node() && node()->isLink() && document()->printing();
 }
 
-RenderObject* RenderObject::container() const
+RenderObject* RenderObject::container(RenderBoxModelObject* repaintContainer, bool* repaintContainerSkipped) const
 {
+    if (repaintContainerSkipped)
+        *repaintContainerSkipped = false;
+
     // This method is extremely similar to containingBlock(), but with a few notable
     // exceptions.
     // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
@@ -1814,14 +1817,20 @@ RenderObject* RenderObject::container() const
         // we'll just return 0).
         // FIXME: The definition of view() has changed to not crawl up the render tree.  It might
         // be safe now to use it.
-        while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock()))
+        while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock())) {
+            if (repaintContainerSkipped && o == repaintContainer)
+                *repaintContainerSkipped = true;
             o = o->parent();
+        }
     } else if (pos == AbsolutePosition) {
         // Same goes here.  We technically just want our containing block, but
         // we may not have one if we're part of an uninstalled subtree.  We'll
         // climb as high as we can though.
-        while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock()))
+        while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) {
+            if (repaintContainerSkipped && o == repaintContainer)
+                *repaintContainerSkipped = true;
             o = o->parent();
+        }
     }
 
     return o;
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index 34f2b8b..367eaa6 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -403,11 +403,11 @@ public:
     bool hasOutlineAnnotation() const;
     bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); }
 
-   /**
-     * returns the object containing this one. can be different from parent for
-     * positioned elements
-     */
-    RenderObject* container() const;
+    // Returns the object containing this one. Can be different from parent for positioned elements.
+    // If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped
+    // is true if the renderer returned is an ancestor of repaintContainer.
+    RenderObject* container(RenderBoxModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const;
+
     virtual RenderObject* hoverAncestor() const { return parent(); }
 
     // IE Extension that can be called on any RenderObject.  See the implementation for the details.

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list