Bug 1251804 - Use the ImageContainer's size and not the intrinsic size when computing the transform in nsDisplayImage::ConfigureLayer. r=tn
authorSeth Fowler <mark.seth.fowler@gmail.com>
Mon, 07 Mar 2016 17:06:04 -0800
changeset 338022 b485a37494452b6cedacd95f0aa673d48ef449b5
parent 338021 6312f4020b6d91372c9b4f69e5fa1c02bc1148ef
child 338023 9314f8ddff7830e1cb4beb5450cb6ad2875bcdd2
push id12405
push usercku@mozilla.com
push dateTue, 08 Mar 2016 03:35:29 +0000
reviewerstn
bugs1251804
milestone47.0a1
Bug 1251804 - Use the ImageContainer's size and not the intrinsic size when computing the transform in nsDisplayImage::ConfigureLayer. r=tn
layout/base/nsDisplayList.cpp
layout/generic/nsImageFrame.cpp
layout/xul/nsImageBoxFrame.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2794,20 +2794,30 @@ nsDisplayBackgroundImage::ConfigureLayer
   }
 
   // XXX(seth): Right now we ignore aParameters.Scale() and
   // aParameters.Offset(), because FrameLayerBuilder already applies
   // aParameters.Scale() via the layer's post-transform, and
   // aParameters.Offset() is always zero.
   MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
 
+  // It's possible (for example, due to downscale-during-decode) that the
+  // ImageContainer this ImageLayer is holding has a different size from the
+  // intrinsic size of the image. For this reason we compute the transform using
+  // the ImageContainer's size rather than the image's intrinsic size.
+  // XXX(seth): In reality, since the size of the ImageContainer may change
+  // asynchronously, this is not enough. Bug 1183378 will provide a more
+  // complete fix, but this solution is safe in more cases than simply relying
+  // on the intrinsic size.
+  IntSize containerSize = aLayer->GetContainer()->GetCurrentSize();
+
   const LayoutDevicePoint p = mImageLayerDestRect.TopLeft();
   Matrix transform = Matrix::Translation(p.x, p.y);
-  transform.PreScale(mImageLayerDestRect.width / imageWidth,
-                     mImageLayerDestRect.height / imageHeight);
+  transform.PreScale(mImageLayerDestRect.width / containerSize.width,
+                     mImageLayerDestRect.height / containerSize.height);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
 }
 
 void
 nsDisplayBackgroundImage::HitTest(nsDisplayListBuilder* aBuilder,
                                   const nsRect& aRect,
                                   HitTestState* aState,
                                   nsTArray<nsIFrame*> *aOutFrames)
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1698,20 +1698,30 @@ nsDisplayImage::ConfigureLayer(ImageLaye
     LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
 
   // XXX(seth): Right now we ignore aParameters.Scale() and
   // aParameters.Offset(), because FrameLayerBuilder already applies
   // aParameters.Scale() via the layer's post-transform, and
   // aParameters.Offset() is always zero.
   MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
 
+  // It's possible (for example, due to downscale-during-decode) that the
+  // ImageContainer this ImageLayer is holding has a different size from the
+  // intrinsic size of the image. For this reason we compute the transform using
+  // the ImageContainer's size rather than the image's intrinsic size.
+  // XXX(seth): In reality, since the size of the ImageContainer may change
+  // asynchronously, this is not enough. Bug 1183378 will provide a more
+  // complete fix, but this solution is safe in more cases than simply relying
+  // on the intrinsic size.
+  IntSize containerSize = aLayer->GetContainer()->GetCurrentSize();
+
   const LayoutDevicePoint p = destRect.TopLeft();
   Matrix transform = Matrix::Translation(p.x, p.y);
-  transform.PreScale(destRect.Width() / imageWidth,
-                     destRect.Height() / imageHeight);
+  transform.PreScale(destRect.Width() / containerSize.width,
+                     destRect.Height() / containerSize.height);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
 }
 
 DrawResult
 nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
                          const nsRect& aDirtyRect, imgIContainer* aImage,
                          uint32_t aFlags)
 {
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -475,20 +475,30 @@ nsDisplayXULImage::ConfigureLayer(ImageL
   }
 
   // XXX(seth): Right now we ignore aParameters.Scale() and
   // aParameters.Offset(), because FrameLayerBuilder already applies
   // aParameters.Scale() via the layer's post-transform, and
   // aParameters.Offset() is always zero.
   MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
 
+  // It's possible (for example, due to downscale-during-decode) that the
+  // ImageContainer this ImageLayer is holding has a different size from the
+  // intrinsic size of the image. For this reason we compute the transform using
+  // the ImageContainer's size rather than the image's intrinsic size.
+  // XXX(seth): In reality, since the size of the ImageContainer may change
+  // asynchronously, this is not enough. Bug 1183378 will provide a more
+  // complete fix, but this solution is safe in more cases than simply relying
+  // on the intrinsic size.
+  IntSize containerSize = aLayer->GetContainer()->GetCurrentSize();
+
   const LayoutDevicePoint p = destRect.TopLeft();
   Matrix transform = Matrix::Translation(p.x, p.y);
-  transform.PreScale(destRect.Width() / imageWidth,
-                     destRect.Height() / imageHeight);
+  transform.PreScale(destRect.Width() / containerSize.width,
+                     destRect.Height() / containerSize.height);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
 }
 
 bool
 nsDisplayXULImage::CanOptimizeToImageLayer(LayerManager* aManager,
                                            nsDisplayListBuilder* aBuilder)
 {
   uint32_t flags = aBuilder->ShouldSyncDecodeImages()