Bug 641770. Apply correct clip rect to a layerized image. r=tnikkel
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 01 Apr 2011 10:33:46 +1300
changeset 64533 c96c353c9d5e37441fded130cfce0668e1569101
parent 64532 2622ae93dfe8b568a8bbcbd3016a43d28eccd9a5
child 64534 7dceef1d4e6670968c204d1a89300c8d1efc34c9
push idunknown
push userunknown
push dateunknown
reviewerstnikkel
bugs641770
milestone2.2a1pre
Bug 641770. Apply correct clip rect to a layerized image. r=tnikkel
layout/base/FrameLayerBuilder.cpp
layout/reftests/bugs/641770-1-ref.html
layout/reftests/bugs/641770-1.html
layout/reftests/bugs/reftest.list
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -277,16 +277,20 @@ protected:
      */
     PRPackedBool mForceTransparentSurface;
 
     /**
      * Stores the pointer to the nsDisplayImage if we want to
      * convert this to an ImageLayer.
      */
     nsDisplayImage* mImage;
+    /**
+     * Stores the clip that we need to apply to the image.
+     */
+    FrameLayerBuilder::Clip mImageClip;
   };
 
   /**
    * Grab the next recyclable ThebesLayer, or create one if there are no
    * more recyclable ThebesLayers. Does any necessary invalidation of
    * a recycled ThebesLayer, and sets up the transform on the ThebesLayer
    * to account for scrolling.
    */
@@ -912,17 +916,17 @@ ContainerState::FindOpaqueBackgroundColo
       FindOpaqueColorCovering(mBuilder, candidate->mLayer, rect);
   }
   return NS_RGBA(0,0,0,0);
 }
 
 nsRefPtr<ImageContainer>
 ContainerState::ThebesLayerData::CanOptimizeImageLayer(LayerManager* aManager)
 {
-  if (!mImage) {
+  if (!mImage || !mImageClip.mRoundedClipRects.IsEmpty()) {
     return nsnull;
   }
 
   return mImage->GetContainer(aManager);
 }
 
 void
 ContainerState::PopThebesLayerData()
@@ -937,16 +941,25 @@ ContainerState::PopThebesLayerData()
 
   if (data->mIsSolidColorInVisibleRegion || imageContainer) {
     NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
                  "Can't be a solid color as well as an image!");
     if (imageContainer) {
       nsRefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer();
       imageLayer->SetContainer(imageContainer);
       data->mImage->ConfigureLayer(imageLayer);
+      NS_ASSERTION(data->mImageClip.mRoundedClipRects.IsEmpty(),
+                   "How did we get rounded clip rects here?");
+      if (data->mImageClip.mHaveClipRect) {
+        nsPresContext* presContext = mContainerFrame->PresContext();
+        nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
+        nsIntRect clip = data->mImageClip.mClipRect.ToNearestPixels(appUnitsPerDevPixel);
+        imageLayer->IntersectClipRect(
+          data->mImageClip.mClipRect.ToNearestPixels(appUnitsPerDevPixel));
+      }
       layer = imageLayer;
     } else {
       nsRefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer();
       colorLayer->SetColor(data->mSolidColor);
 
       // Copy transform
       colorLayer->SetTransform(data->mLayer->GetTransform());
       
@@ -1113,16 +1126,17 @@ ContainerState::ThebesLayerData::Accumul
     mDrawRegion.SimplifyOutward(4);
   }
 
   /* Mark as available for conversion to image layer if this is a nsDisplayImage and
    * we are the first visible item in the ThebesLayerData object.
    */
   if (aItem->GetType() == nsDisplayItem::TYPE_IMAGE && mVisibleRegion.IsEmpty()) {
     mImage = static_cast<nsDisplayImage*>(aItem);
+    mImageClip = aClip;
   } else {
     mImage = nsnull;
   }
   
   PRBool forceTransparentSurface = PR_FALSE;
   nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &forceTransparentSurface);
   if (!opaque.IsEmpty()) {
     nsRegionRectIterator iter(opaque);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/641770-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div style="position:absolute; background:green; width:1500px; height:1500px;"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/641770-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<img style="position:fixed; width:1500px;" src="repeatable-diagonal-gradient.png">
+<div style="position:absolute; background:green; width:1500px; height:1500px;"></div>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1618,9 +1618,10 @@ fails-if(Android) == 625409-1.html 62540
 == 631352-1.html 631352-1-ref.html
 fails-if(Android) == 632423-1.html 632423-1-ref.html
 skip-if(Android) fails-if(winWidget) == 632781-verybig.html 632781-ref.html # large canvas elements are not drawn on Windows, see bug 633936
 == 632781-normalsize.html 632781-ref.html
 fails-if(Android) == 634232-1.html 634232-1-ref.html
 fails-if(Android) == 635302-1.html 635302-1-ref.html
 HTTP(..) == 635639-1.html 635639-1-ref.html
 HTTP(..) == 635639-2.html 635639-2-ref.html
+== 641770-1.html 641770-1-ref.html
 == 641856-1.html 641856-1-ref.html