Bug 601894 - Compare covered rects when computing whether a transform display list item is opaque / uniform. r=roc, a=betaN
authorMarkus Stange <mstange@themasta.com>
Sat, 27 Nov 2010 00:31:08 +0100
changeset 58321 6aad676f008c2647ef32d474aa0a44d4480bdfa4
parent 58320 64188998417c19a5764d89aab9f56d1c70effe07
child 58322 4d4065d46e80674cb32d5a3a2ca35114e64f4997
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersroc, betaN
bugs601894
milestone2.0b8pre
Bug 601894 - Compare covered rects when computing whether a transform display list item is opaque / uniform. r=roc, a=betaN
layout/base/nsDisplayList.cpp
layout/reftests/transform/601894-1.html
layout/reftests/transform/601894-2.html
layout/reftests/transform/601894-ref.html
layout/reftests/transform/reftest.list
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1980,46 +1980,58 @@ void nsDisplayTransform::HitTest(nsDispl
  * by the reference point.
  */
 nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder)
 {
   return mFrame->GetVisualOverflowRect() + ToReferenceFrame();
 }
 
 /* The transform is opaque iff the transform consists solely of scales and
- * transforms and if the underlying content is opaque.  Thus if the transform
+ * translations and if the underlying content is opaque.  Thus if the transform
  * is of the form
  *
  * |a c e|
  * |b d f|
  * |0 0 1|
  *
  * We need b and c to be zero.
+ *
+ * We also need to check whether the underlying opaque content completely fills
+ * our visible rect. We use UntransformRect which expands to the axis-aligned
+ * bounding rect, but that's OK since if
+ * mStoredList.GetVisibleRect().Contains(untransformedVisible), then it
+ * certainly contains the actual (non-axis-aligned) untransformed rect.
  */
 PRBool nsDisplayTransform::IsOpaque(nsDisplayListBuilder *aBuilder,
                                     PRBool* aForceTransparentSurface)
 {
   if (aForceTransparentSurface) {
     *aForceTransparentSurface = PR_FALSE;
   }
   const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
+  nsRect untransformedVisible =
+    UntransformRect(mVisibleRect, mFrame, ToReferenceFrame());
   return disp->mTransform.GetMainMatrixEntry(1) == 0.0f &&
     disp->mTransform.GetMainMatrixEntry(2) == 0.0f &&
+    mStoredList.GetVisibleRect().Contains(untransformedVisible) &&
     mStoredList.IsOpaque(aBuilder);
 }
 
 /* The transform is uniform if it fills the entire bounding rect and the
  * wrapped list is uniform.  See IsOpaque for discussion of why this
  * works.
  */
 PRBool nsDisplayTransform::IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor)
 {
   const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
+  nsRect untransformedVisible =
+    UntransformRect(mVisibleRect, mFrame, ToReferenceFrame());
   return disp->mTransform.GetMainMatrixEntry(1) == 0.0f &&
     disp->mTransform.GetMainMatrixEntry(2) == 0.0f &&
+    mStoredList.GetVisibleRect().Contains(untransformedVisible) &&
     mStoredList.IsUniform(aBuilder, aColor);
 }
 
 /* If UNIFIED_CONTINUATIONS is defined, we can merge two display lists that
  * share the same underlying content.  Otherwise, doing so results in graphical
  * glitches.
  */
 #ifndef UNIFIED_CONTINUATIONS
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform/601894-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+  <body style="background: -moz-linear-gradient(lime, lime) fixed; overflow: hidden;">
+    <div style="position: absolute; left: 21.0138px; top: 507.24px; z-index: 17567; -moz-transform: scale(8);">
+      <div style="height: 128px; left: -64px; position: absolute; top: -64px; visibility: visible; width: 128px;"></div>
+    </div>
+    <div style="position: absolute; left: 640.572px; top: 386.574px; -moz-transform: scale(1); z-index: -157863;">
+      <div style="position: absolute; top: -64px; left: -64px; width: 128px; height: 128px; visibility: visible;"></div>
+    </div>
+    <div style="position: absolute; left: 568.346px; top: 582.669px; -moz-transform: scale(1); z-index: -62592;">
+      <div style="position: absolute; top: -64px; left: -64px; width: 128px; height: 128px; visibility: visible;"></div>
+    </div>
+    <div style="position: absolute; left: 573.27px; top: 168.861px; -moz-transform: scale(1); z-index: -137632;">
+      <div style="position: absolute; top: -64px; left: -64px; width: 128px; height: 128px; visibility: visible;"></div>
+    </div>
+    <div style="position: absolute; left: 519.063px; top: 182.9px; -moz-transform: scale(1); z-index: -50558;">
+      <div style="position: absolute; top: -64px; left: -64px; width: 128px; height: 128px; visibility: visible;"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform/601894-2.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+  <body style="background: -moz-linear-gradient(lime, lime) fixed;">
+    <div style="position: absolute; left: 0; top: 0; -moz-transform: scale(1)">
+      <div style="position: absolute; width: 200px; height: 200px;"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform/601894-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body style="background: lime;">
--- a/layout/reftests/transform/reftest.list
+++ b/layout/reftests/transform/reftest.list
@@ -100,8 +100,11 @@ fails-if(d2d) == abspos-1d.html abspos-1
 == scale-1a.html scale-1-ref.html
 == scale-1b.html scale-1-ref.html
 == scale-percent-1.html scale-percent-1-ref.html
 # Some simple checks that it obeys selector operations
 == descendant-1.html descendant-1-ref.html
 == propagate-inherit-boolean.html propagate-inherit-boolean-ref.html
 # Ensure you can't move outside an iframe
 == iframe-1.html iframe-1-ref.html
+# Bugs
+== 601894-1.html 601894-ref.html
+== 601894-2.html 601894-ref.html