Bug 885009. Handle clip-all-descendants cases with rounded corners. r=mats
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 26 Jul 2013 13:36:05 +1200
changeset 140131 366608750a6e9fbd16893250d675f4cfd5266b0c
parent 140130 6b4ff981027f3232bf23cd598fa848d57b064b48
child 140132 44c751cee3b144b888f489e245ef475f3db1e97c
push id25016
push userryanvm@gmail.com
push dateSat, 27 Jul 2013 02:25:56 +0000
treeherdermozilla-central@fb48c7d58b8b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs885009
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 885009. Handle clip-all-descendants cases with rounded corners. r=mats
layout/base/DisplayListClipState.cpp
layout/base/DisplayListClipState.h
layout/generic/crashtests/885009-1.html
layout/generic/crashtests/crashtests.list
layout/generic/nsGfxScrollFrame.cpp
--- a/layout/base/DisplayListClipState.cpp
+++ b/layout/base/DisplayListClipState.cpp
@@ -48,19 +48,24 @@ DisplayListClipState::ClipContainingBloc
     aClipOnStack.IntersectWith(*mClipContainingBlockDescendants);
   }
   mClipContainingBlockDescendants = &aClipOnStack;
   mCurrentCombinedClip = nullptr;
 }
 
 void
 DisplayListClipState::ClipContentDescendants(const nsRect& aRect,
+                                             const nscoord* aRadii,
                                              DisplayItemClip& aClipOnStack)
 {
-  aClipOnStack.SetTo(aRect);
+  if (aRadii) {
+    aClipOnStack.SetTo(aRect, aRadii);
+  } else {
+    aClipOnStack.SetTo(aRect);
+  }
   if (mClipContentDescendants) {
     aClipOnStack.IntersectWith(*mClipContentDescendants);
   }
   mClipContentDescendants = &aClipOnStack;
   mCurrentCombinedClip = nullptr;
 }
 
 void
--- a/layout/base/DisplayListClipState.h
+++ b/layout/base/DisplayListClipState.h
@@ -74,16 +74,17 @@ private:
    * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
    * the result, stored in aClipOnStack.
    */
   void ClipContainingBlockDescendants(const nsRect& aRect,
                                       const nscoord* aRadii,
                                       DisplayItemClip& aClipOnStack);
 
   void ClipContentDescendants(const nsRect& aRect,
+                              const nscoord* aRadii,
                               DisplayItemClip& aClipOnStack);
 
   /**
    * Clips containing-block descendants to the frame's content-box,
    * taking border-radius into account.
    * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
    * we assume display items will not draw outside the content rect, so
    * clipping is only required if there is a border-radius. This is an
@@ -145,30 +146,31 @@ public:
   }
 
   /**
    * Intersects the given clip rect (with optional aRadii) with the current
    * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
    * the result, stored in aClipOnStack.
    */
   void ClipContainingBlockDescendants(const nsRect& aRect,
-                                      const nscoord* aRadii)
+                                      const nscoord* aRadii = nullptr)
   {
     NS_ASSERTION(!mRestored, "Already restored!");
     NS_ASSERTION(!mClipUsed, "mClip already used");
     mClipUsed = true;
     mState.ClipContainingBlockDescendants(aRect, aRadii, mClip);
   }
 
-  void ClipContentDescendants(const nsRect& aRect)
+  void ClipContentDescendants(const nsRect& aRect,
+                              const nscoord* aRadii = nullptr)
   {
     NS_ASSERTION(!mRestored, "Already restored!");
     NS_ASSERTION(!mClipUsed, "mClip already used");
     mClipUsed = true;
-    mState.ClipContentDescendants(aRect, mClip);
+    mState.ClipContentDescendants(aRect, aRadii, mClip);
   }
 
   /**
    * Clips containing-block descendants to the frame's content-box,
    * taking border-radius into account.
    * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
    * we assume display items will not draw outside the content rect, so
    * clipping is only required if there is a border-radius. This is an
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/885009-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+</head>
+<body style="display: -moz-inline-stack; overflow: scroll; border-style: solid; border-radius: 4px;"></body>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -492,8 +492,9 @@ asserts(4) load 847209.html # bug 847368
 test-pref(layout.css.flexbox.enabled,true) load 847211-1.html
 load 849603.html
 test-pref(layout.css.flexbox.enabled,true) load 851396-1.html
 test-pref(layout.css.flexbox.enabled,true) load 854263-1.html
 test-pref(layout.css.flexbox.enabled,true) load 862947-1.html
 needs-focus pref(accessibility.browsewithcaret,true) load 868906.html
 test-pref(layout.css.flexbox.enabled,true) load 866547-1.html
 asserts(1-4) test-pref(layout.css.flexbox.enabled,true) load 876074-1.html # bug 876749
+load 885009-1.html
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2246,28 +2246,23 @@ nsGfxScrollFrameInner::BuildDisplayList(
       nsRect clip = displayPort + aBuilder->ToReferenceFrame(mOuter);
       if (mClipAllDescendants) {
         clipState.ClipContentDescendants(clip);
       } else {
         clipState.ClipContainingBlockDescendants(clip, nullptr);
       }
     } else {
       nsRect clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
+      nscoord radii[8];
+      bool haveRadii = mOuter->GetPaddingBoxBorderRadii(radii);
       // Our override of GetBorderRadii ensures we never have a radius at
       // the corners where we have a scrollbar.
       if (mClipAllDescendants) {
-#ifdef DEBUG
-        nscoord radii[8];
-#endif
-        NS_ASSERTION(!mOuter->GetPaddingBoxBorderRadii(radii),
-                     "Roots with radii not supported");
-        clipState.ClipContentDescendants(clip);
+        clipState.ClipContentDescendants(clip, haveRadii ? radii : nullptr);
       } else {
-        nscoord radii[8];
-        bool haveRadii = mOuter->GetPaddingBoxBorderRadii(radii);
         clipState.ClipContainingBlockDescendants(clip, haveRadii ? radii : nullptr);
       }
     }
 
     mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, aLists);
   }
 
   // Since making new layers is expensive, only use nsDisplayScrollLayer