Bug 825720 - Don't use GetRootLayoutFrame to calculate the size of SVG images. r=joe
authorSeth Fowler <seth@mozilla.com>
Thu, 10 Jan 2013 19:38:34 -0800
changeset 122486 42a50bccf86ed209f8f01b8e673cb686c9981688
parent 122485 cd7341caf9f0fc2b04437e0822d01535ffb6aa14
child 122487 1641778f1619a5306ad2d84aec9bbe5a3a2a6124
push id24342
push userryanvm@gmail.com
push dateThu, 21 Feb 2013 13:05:06 +0000
treeherdermozilla-central@702d2814efbf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs825720
milestone22.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 825720 - Don't use GetRootLayoutFrame to calculate the size of SVG images. r=joe
image/public/imgIContainer.idl
image/src/RasterImage.cpp
image/src/VectorImage.cpp
layout/base/nsLayoutUtils.cpp
layout/generic/nsImageFrame.cpp
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -36,46 +36,60 @@ class TimeStamp;
 [ptr] native gfxASurface(gfxASurface);
 native gfxImageFormat(gfxASurface::gfxImageFormat);
 [ptr] native gfxContext(gfxContext);
 [ref] native gfxMatrix(gfxMatrix);
 [ref] native gfxRect(gfxRect);
 native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
 [ref] native nsIntRect(nsIntRect);
 [ref] native nsIntSize(nsIntSize);
+native nsSize(nsSize);
 [ptr] native nsIFrame(nsIFrame);
 [ptr] native ImageContainer(mozilla::layers::ImageContainer);
 [ptr] native LayerManager(mozilla::layers::LayerManager);
 [ref] native TimeStamp(mozilla::TimeStamp);
 
 
 /**
  * imgIContainer is the interface that represents an image. It allows
  * access to frames as Thebes surfaces, and permits users to extract subregions
  * as other imgIContainers. It also allows drawing of images on to Thebes
  * contexts.
  *
  * Internally, imgIContainer also manages animation of images.
  */
-[scriptable, builtinclass, uuid(c7e8eed7-2be9-40b0-be7c-b682097f5b28)]
+[scriptable, builtinclass, uuid(a9a6835f-ca7e-4c80-8892-962c959fcd27)]
 interface imgIContainer : nsISupports
 {
   /**
    * The width of the container rectangle.  In the case of any error,
    * zero is returned, and an exception will be thrown.
    */
   readonly attribute int32_t width;
 
   /**
    * The height of the container rectangle.  In the case of any error,
    * zero is returned, and an exception will be thrown.
    */
   readonly attribute int32_t height;
 
   /**
+   * The intrinsic size of this image in appunits. If the image has no intrinsic
+   * size in a dimension, -1 will be returned for that dimension. In the case of
+   * any error, an exception will be thrown.
+   */
+  [noscript] readonly attribute nsSize intrinsicSize;
+
+  /**
+   * The (dimensionless) intrinsic ratio of this image. In the case of any error,
+   * an exception will be thrown.
+   */
+  [noscript] readonly attribute nsSize intrinsicRatio;
+
+  /**
     * Enumerated values for the 'type' attribute (below).
     */
   const unsigned short TYPE_RASTER = 0;
   const unsigned short TYPE_VECTOR = 1;
 
   /**
    * The type of this image (one of the TYPE_* values above).
    */
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -12,16 +12,17 @@
 #include "RasterImage.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsAutoPtr.h"
 #include "nsStringStream.h"
 #include "prenv.h"
 #include "ImageContainer.h"
 #include "Layers.h"
+#include "nsPresContext.h"
 
 #include "nsPNGDecoder.h"
 #include "nsGIFDecoder2.h"
 #include "nsJPEGDecoder.h"
 #include "nsBMPDecoder.h"
 #include "nsICODecoder.h"
 #include "nsIconDecoder.h"
 
@@ -766,16 +767,41 @@ RasterImage::GetHeight(int32_t *aHeight)
   if (mError) {
     *aHeight = 0;
     return NS_ERROR_FAILURE;
   }
 
   *aHeight = mSize.height;
   return NS_OK;
 }
+ 
+//******************************************************************************
+/* [noscript] readonly attribute nsSize intrinsicSize; */
+NS_IMETHODIMP
+RasterImage::GetIntrinsicSize(nsSize* aSize)
+{
+  if (mError)
+    return NS_ERROR_FAILURE;
+
+  *aSize = nsSize(nsPresContext::CSSPixelsToAppUnits(mSize.width),
+                  nsPresContext::CSSPixelsToAppUnits(mSize.height));
+  return NS_OK;
+}
+
+//******************************************************************************
+/* [noscript] readonly attribute nsSize intrinsicRatio; */
+NS_IMETHODIMP
+RasterImage::GetIntrinsicRatio(nsSize* aRatio)
+{
+  if (mError)
+    return NS_ERROR_FAILURE;
+
+  *aRatio = nsSize(mSize.width, mSize.height);
+  return NS_OK;
+}
 
 //******************************************************************************
 /* unsigned short GetType(); */
 NS_IMETHODIMP
 RasterImage::GetType(uint16_t *aType)
 {
   NS_ENSURE_ARG_POINTER(aType);
 
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -481,16 +481,48 @@ VectorImage::GetHeight(int32_t* aHeight)
     *aHeight = 0;
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 //******************************************************************************
+/* [noscript] readonly attribute nsSize intrinsicSize; */
+NS_IMETHODIMP
+VectorImage::GetIntrinsicSize(nsSize* aSize)
+{
+  nsIFrame* rootFrame = GetRootLayoutFrame();
+  if (!rootFrame)
+    return NS_ERROR_FAILURE;
+
+  *aSize = nsSize(-1, -1);
+  nsIFrame::IntrinsicSize rfSize = rootFrame->GetIntrinsicSize();
+  if (rfSize.width.GetUnit() == eStyleUnit_Coord)
+    aSize->width = rfSize.width.GetCoordValue();
+  if (rfSize.height.GetUnit() == eStyleUnit_Coord)
+    aSize->height = rfSize.height.GetCoordValue();
+
+  return NS_OK;
+}
+
+//******************************************************************************
+/* [noscript] readonly attribute nsSize intrinsicRatio; */
+NS_IMETHODIMP
+VectorImage::GetIntrinsicRatio(nsSize* aRatio)
+{
+  nsIFrame* rootFrame = GetRootLayoutFrame();
+  if (!rootFrame)
+    return NS_ERROR_FAILURE;
+
+  *aRatio = rootFrame->GetIntrinsicRatio();
+  return NS_OK;
+}
+
+//******************************************************************************
 /* readonly attribute unsigned short type; */
 NS_IMETHODIMP
 VectorImage::GetType(uint16_t* aType)
 {
   NS_ENSURE_ARG_POINTER(aType);
 
   *aType = GetType();
   return NS_OK;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4123,28 +4123,21 @@ nsLayoutUtils::DrawSingleImage(nsRenderi
 nsLayoutUtils::ComputeSizeForDrawing(imgIContainer *aImage,
                                      nsIntSize&     aImageSize, /*outparam*/
                                      nsSize&        aIntrinsicRatio, /*outparam*/
                                      bool&          aGotWidth,  /*outparam*/
                                      bool&          aGotHeight  /*outparam*/)
 {
   aGotWidth  = NS_SUCCEEDED(aImage->GetWidth(&aImageSize.width));
   aGotHeight = NS_SUCCEEDED(aImage->GetHeight(&aImageSize.height));
-
-  if (aGotWidth && aGotHeight) {
-    aIntrinsicRatio = nsSize(aImageSize.width, aImageSize.height);
-    return;
-  }
-
-  // If we failed to get width or height, we either have a vector image and
-  // should return its intrinsic ratio, or we hit an error (say, because the
-  // image failed to load or couldn't be decoded) and should return zero size.
-  if (nsIFrame* rootFrame = aImage->GetRootLayoutFrame()) {
-    aIntrinsicRatio = rootFrame->GetIntrinsicRatio();
-  } else {
+  bool gotRatio = NS_SUCCEEDED(aImage->GetIntrinsicRatio(&aIntrinsicRatio));
+
+  if (!(aGotWidth && aGotHeight) && !gotRatio) {
+    // We hit an error (say, because the image failed to load or couldn't be
+    // decoded) and should return zero size.
     aGotWidth = aGotHeight = true;
     aImageSize = nsIntSize(0, 0);
     aIntrinsicRatio = nsSize(0, 0);
   }
 }
 
 
 /* static */ nsresult
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -282,59 +282,51 @@ nsImageFrame::Init(nsIContent*      aCon
 bool
 nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage)
 {
   NS_PRECONDITION(aImage, "null image");
   if (!aImage)
     return false;
 
   nsIFrame::IntrinsicSize oldIntrinsicSize = mIntrinsicSize;
+  mIntrinsicSize = nsIFrame::IntrinsicSize();
 
-  nsIFrame* rootFrame = aImage->GetRootLayoutFrame();
-  if (rootFrame) {
-    // Set intrinsic size to match that of aImage's rootFrame.
-    mIntrinsicSize = rootFrame->GetIntrinsicSize();
+  // Set intrinsic size to match aImage's reported intrinsic width & height.
+  nsSize intrinsicSize;
+  if (NS_SUCCEEDED(aImage->GetIntrinsicSize(&intrinsicSize))) {
+    // If the image has no intrinsic width, intrinsicSize.width will be -1, and
+    // we can leave mIntrinsicSize.width at its default value of eStyleUnit_None.
+    // Otherwise we use intrinsicSize.width. Height works the same way.
+    if (intrinsicSize.width != -1)
+      mIntrinsicSize.width.SetCoordValue(intrinsicSize.width);
+    if (intrinsicSize.height != -1)
+      mIntrinsicSize.height.SetCoordValue(intrinsicSize.height);
   } else {
-    // Set intrinsic size to match aImage's reported width & height.
-    nsIntSize imageSizeInPx;
-    if (NS_FAILED(aImage->GetWidth(&imageSizeInPx.width)) ||
-        NS_FAILED(aImage->GetHeight(&imageSizeInPx.height))) {
-      imageSizeInPx.SizeTo(0, 0);
-    }
-    mIntrinsicSize.width.SetCoordValue(
-      nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.width));
-    mIntrinsicSize.height.SetCoordValue(
-      nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.height));
+    // Failure means that the image hasn't loaded enough to report a result. We
+    // treat this case as if the image's intrinsic size was 0x0.
+    mIntrinsicSize.width.SetCoordValue(0);
+    mIntrinsicSize.height.SetCoordValue(0);
   }
 
   return mIntrinsicSize != oldIntrinsicSize;
 }
 
 bool
 nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage)
 {
   NS_PRECONDITION(aImage, "null image");
 
   if (!aImage)
     return false;
 
   nsSize oldIntrinsicRatio = mIntrinsicRatio;
 
-  nsIFrame* rootFrame = aImage->GetRootLayoutFrame();
-  if (rootFrame) {
-    // Set intrinsic ratio to match that of aImage's rootFrame.
-    mIntrinsicRatio = rootFrame->GetIntrinsicRatio();
-  } else {
-    NS_ABORT_IF_FALSE(mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
-                      mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord,
-                      "since aImage doesn't have a rootFrame, our intrinsic "
-                      "dimensions must have coord units (not percent units)");
-    mIntrinsicRatio.width = mIntrinsicSize.width.GetCoordValue();
-    mIntrinsicRatio.height = mIntrinsicSize.height.GetCoordValue();
-  }
+  // Set intrinsic ratio to match aImage's reported intrinsic ratio.
+  if (NS_FAILED(aImage->GetIntrinsicRatio(&mIntrinsicRatio)))
+    mIntrinsicRatio.SizeTo(0, 0);
 
   return mIntrinsicRatio != oldIntrinsicRatio;
 }
 
 bool
 nsImageFrame::GetSourceToDestTransform(nsTransform2D& aTransform)
 {
   // Set the translation components.