Bug 1119774 (Part 2) - Add RequestDecodeForSize to imgIContainer. r=tn a=lmandel
authorSeth Fowler <seth@mozilla.com>
Sun, 18 Jan 2015 14:02:13 -0800
changeset 249817 ef05e787c57932c8104ff1de604e9e7751af3cef
parent 249816 3bec811ec5b321d3c0cdb967330f476f1e94fd55
child 249818 debf99339d3c2c9933956532841ac7eee6a51f08
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, lmandel
bugs1119774
milestone37.0a2
Bug 1119774 (Part 2) - Add RequestDecodeForSize to imgIContainer. r=tn a=lmandel
image/public/imgIContainer.idl
image/src/DynamicImage.cpp
image/src/ImageWrapper.cpp
image/src/RasterImage.cpp
image/src/VectorImage.cpp
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -64,17 +64,17 @@ native nsIntSizeByVal(nsIntSize);
 
 /**
  * imgIContainer is the interface that represents an image. It allows
  * access to frames as Thebes surfaces. It also allows drawing of images
  * onto Thebes contexts.
  *
  * Internally, imgIContainer also manages animation of images.
  */
-[scriptable, builtinclass, uuid(14ea6fa5-183e-4409-ac88-110bd2e05292)]
+[scriptable, builtinclass, uuid(4adb4c92-284d-4f5a-85e7-e924ec57510f)]
 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;
 
@@ -340,22 +340,38 @@ interface imgIContainer : nsISupports
    * the image will at some point fire off decode notifications. Calling draw()
    * or getFrame() triggers the same mechanism internally. Thus, if you want to
    * be sure that the image will be decoded but don't want to access it until
    * then, you must call requestDecode().
    */
   void requestDecode();
 
   /*
-   * This is equivalent to requestDecode() but it also decodes some of the
-   * image.
+   * This is equivalent to requestDecode() but it also synchronously decodes
+   * images that can be decoded "quickly" according to some heuristic.
    */
   [noscript] void startDecoding();
 
   /*
+   * This method is equivalent to requestDecode(), but enables the caller to
+   * provide more detailed information about the decode request.
+   *
+   * @param aSize The size to which the image should be scaled while decoding,
+   *              if possible. If the image cannot be scaled to this size while
+   *              being decoded, it will be decoded at its intrinsic size.
+   * @param aFlags Flags of the FLAG_* variety. Only the decode flags
+   *               (FLAG_DECODE_*) and FLAG_SYNC_DECODE (which will
+   *               synchronously decode images that can be decoded "quickly",
+   *               just like startDecoding() does) are accepted; others will be
+   *               ignored.
+   */
+  [noscript] void requestDecodeForSize([const] in nsIntSize aSize,
+                                       in uint32_t aFlags);
+
+  /*
    * Returns true if no more decoding can be performed on this image. Images
    * with errors return true since they cannot be decoded any further. Note that
    * because decoded images may be discarded, isDecoded() may return false even
    * if it has returned true in the past.
    */
   [noscript, notxpcom, nostdcall] bool isDecoded();
 
   /**
--- a/image/src/DynamicImage.cpp
+++ b/image/src/DynamicImage.cpp
@@ -250,16 +250,22 @@ DynamicImage::RequestDecode()
 }
 
 NS_IMETHODIMP
 DynamicImage::StartDecoding()
 {
   return NS_OK;
 }
 
+NS_IMETHODIMP
+DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
+{
+  return NS_OK;
+}
+
 bool
 DynamicImage::IsDecoded()
 {
   return true;
 }
 
 NS_IMETHODIMP
 DynamicImage::LockImage()
--- a/image/src/ImageWrapper.cpp
+++ b/image/src/ImageWrapper.cpp
@@ -219,16 +219,22 @@ ImageWrapper::RequestDecode()
 }
 
 NS_IMETHODIMP
 ImageWrapper::StartDecoding()
 {
   return mInnerImage->StartDecoding();
 }
 
+NS_IMETHODIMP
+ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
+{
+  return mInnerImage->RequestDecodeForSize(aSize, aFlags);
+}
+
 bool
 ImageWrapper::IsDecoded()
 {
   return mInnerImage->IsDecoded();
 }
 
 NS_IMETHODIMP
 ImageWrapper::LockImage()
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -310,17 +310,17 @@ RasterImage::Init(const char* aMimeType,
     return NS_ERROR_FAILURE;
 
   NS_ENSURE_ARG_POINTER(aMimeType);
 
   // We must be non-discardable and non-decode-on-draw for
   // transient images.
   MOZ_ASSERT(!(aFlags & INIT_FLAG_TRANSIENT) ||
                (!(aFlags & INIT_FLAG_DISCARDABLE) &&
-                !(aFlags & INIT_FLAG_DECODE_ON_DRAW),
+                !(aFlags & INIT_FLAG_DECODE_ON_DRAW) &&
                 !(aFlags & INIT_FLAG_DOWNSCALE_DURING_DECODE)),
              "Illegal init flags for transient image");
 
   // Store initialization data
   mSourceDataMimeType.Assign(aMimeType);
   mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE);
   mDecodeOnDraw = !!(aFlags & INIT_FLAG_DECODE_ON_DRAW);
   mTransient = !!(aFlags & INIT_FLAG_TRANSIENT);
@@ -1359,59 +1359,60 @@ RasterImage::WantDecodedFrames(uint32_t 
   Decode(DecodeStrategy::ASYNC, aFlags);
 }
 
 //******************************************************************************
 /* void requestDecode() */
 NS_IMETHODIMP
 RasterImage::RequestDecode()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mError) {
-    return NS_ERROR_FAILURE;
-  }
-  if (!mHasSize) {
-    mWantFullDecode = true;
-    return NS_OK;
-  }
-
-  // Look up the first frame of the image, which will implicitly start decoding
-  // if it's not available right now.
-  // XXX(seth): Passing false for aShouldSyncNotify here has the effect of
-  // decoding asynchronously, but that's not obvious from the argument name.
-  // This API needs to be reworked.
-  LookupFrame(0, mSize, DECODE_FLAGS_DEFAULT, /* aShouldSyncNotify = */ false);
-
-  return NS_OK;
+  return RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
 }
 
 /* void startDecode() */
 NS_IMETHODIMP
 RasterImage::StartDecoding()
 {
   if (!NS_IsMainThread()) {
     return NS_DispatchToMainThread(
       NS_NewRunnableMethod(this, &RasterImage::StartDecoding));
   }
 
+  return RequestDecodeForSize(mSize, FLAG_SYNC_DECODE);
+}
+
+NS_IMETHODIMP
+RasterImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
   if (mError) {
     return NS_ERROR_FAILURE;
   }
+
   if (!mHasSize) {
     mWantFullDecode = true;
     return NS_OK;
   }
 
+  // Fall back to our intrinsic size if we don't support
+  // downscale-during-decode.
+  nsIntSize targetSize = mDownscaleDuringDecode ? aSize : mSize;
+
+  // Sync decode small images if requested.
+  bool shouldSyncDecodeSmallImages = aFlags & FLAG_SYNC_DECODE;
+
   // Look up the first frame of the image, which will implicitly start decoding
   // if it's not available right now.
   // XXX(seth): Passing true for aShouldSyncNotify here has the effect of
-  // synchronously decoding small images, but that's not obvious from the
-  // argument name. This API needs to be reworked.
-  LookupFrame(0, mSize, DECODE_FLAGS_DEFAULT, /* aShouldSyncNotify = */ true);
+  // synchronously decoding small images, while passing false has the effect of
+  // decoding asynchronously, but that's not obvious from the argument name.
+  // This API needs to be reworked.
+  LookupFrame(0, targetSize, DecodeFlags(aFlags),
+              /* aShouldSyncNotify = */ shouldSyncDecodeSmallImages);
 
   return NS_OK;
 }
 
 bool
 RasterImage::IsDecoded()
 {
   // XXX(seth): We need to get rid of this; it's not reliable.
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -894,16 +894,25 @@ VectorImage::RequestDecode()
 
 NS_IMETHODIMP
 VectorImage::StartDecoding()
 {
   // Nothing to do for SVG images
   return NS_OK;
 }
 
+NS_IMETHODIMP
+VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
+{
+  // Nothing to do for SVG images, though in theory we could rasterize to the
+  // provided size ahead of time if we supported off-main-thread SVG
+  // rasterization...
+  return NS_OK;
+}
+
 bool
 VectorImage::IsDecoded()
 {
   return mIsFullyLoaded || mError;
 }
 
 //******************************************************************************
 /* void lockImage() */