Backed out changeset 0b797601dc36 (bug 1343499) for build bustages. r=backout
authorAndrew Osmond <aosmond@mozilla.com>
Wed, 22 Mar 2017 09:19:05 -0400
changeset 387492 d9f0bdf14469ffdb47987c7eab8a6dc2fc17d18c
parent 387491 0b797601dc36ce8b3758aa9b39eaa2f20356d239
child 387559 b6a142776feedad9e7a00f66aab85310435c4348
push idunknown
push userunknown
push dateunknown
reviewersbackout
bugs1343499
milestone55.0a1
backs out0b797601dc36ce8b3758aa9b39eaa2f20356d239
Backed out changeset 0b797601dc36 (bug 1343499) for build bustages. r=backout
image/DynamicImage.cpp
image/DynamicImage.h
image/FrameTimeout.h
image/ImageMetadata.h
image/ImageOps.cpp
image/ImageOps.h
image/ImageWrapper.cpp
image/ImageWrapper.h
image/OrientedImage.cpp
image/OrientedImage.h
image/RasterImage.cpp
image/RasterImage.h
image/VectorImage.cpp
image/VectorImage.h
image/decoders/nsICODecoder.cpp
image/imgFrame.h
image/imgIContainer.idl
image/moz.build
image/test/gtest/Common.cpp
image/test/gtest/Common.h
image/test/gtest/TestDecodeToSurface.cpp
image/test/gtest/TestDecoders.cpp
image/test/gtest/green-multiple-sizes.ico
image/test/gtest/moz.build
--- a/image/DynamicImage.cpp
+++ b/image/DynamicImage.cpp
@@ -122,22 +122,16 @@ DynamicImage::GetWidth(int32_t* aWidth)
 
 NS_IMETHODIMP
 DynamicImage::GetHeight(int32_t* aHeight)
 {
   *aHeight = mDrawable->Size().height;
   return NS_OK;
 }
 
-nsresult
-DynamicImage::GetNativeSizes(nsTArray<IntSize>& aNativeSizes) const
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 NS_IMETHODIMP
 DynamicImage::GetIntrinsicSize(nsSize* aSize)
 {
   IntSize intSize(mDrawable->Size());
   *aSize = nsSize(intSize.width, intSize.height);
   return NS_OK;
 }
 
--- a/image/DynamicImage.h
+++ b/image/DynamicImage.h
@@ -26,17 +26,16 @@ public:
 
   explicit DynamicImage(gfxDrawable* aDrawable)
     : mDrawable(aDrawable)
   {
     MOZ_ASSERT(aDrawable, "Must have a gfxDrawable to wrap");
   }
 
   // Inherited methods from Image.
-  nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
   virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
   virtual size_t SizeOfSourceWithComputedFallback(
                                  MallocSizeOf aMallocSizeOf) const override;
   virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
                                      MallocSizeOf aMallocSizeOf) const override;
 
   virtual void IncrementAnimationConsumers() override;
   virtual void DecrementAnimationConsumers() override;
deleted file mode 100644
--- a/image/FrameTimeout.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_image_FrameTimeout_h
-#define mozilla_image_FrameTimeout_h
-
-#include <stdint.h>
-#include "mozilla/Assertions.h"
-
-namespace mozilla {
-namespace image {
-
-/**
- * FrameTimeout wraps a frame timeout value (measured in milliseconds) after
- * first normalizing it. This normalization is necessary because some tools
- * generate incorrect frame timeout values which we nevertheless have to
- * support. For this reason, code that deals with frame timeouts should always
- * use a FrameTimeout value rather than the raw value from the image header.
- */
-struct FrameTimeout
-{
-  /**
-   * @return a FrameTimeout of zero. This should be used only for math
-   * involving FrameTimeout values. You can't obtain a zero FrameTimeout from
-   * FromRawMilliseconds().
-   */
-  static FrameTimeout Zero() { return FrameTimeout(0); }
-
-  /// @return an infinite FrameTimeout.
-  static FrameTimeout Forever() { return FrameTimeout(-1); }
-
-  /// @return a FrameTimeout obtained by normalizing a raw timeout value.
-  static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds)
-  {
-    // Normalize all infinite timeouts to the same value.
-    if (aRawMilliseconds < 0) {
-      return FrameTimeout::Forever();
-    }
-
-    // Very small timeout values are problematic for two reasons: we don't want
-    // to burn energy redrawing animated images extremely fast, and broken tools
-    // generate these values when they actually want a "default" value, so such
-    // images won't play back right without normalization. For some context,
-    // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical
-    // behavior of IE and Opera was:
-    //   IE 6/Win:
-    //     10 - 50ms is normalized to 100ms.
-    //     >50ms is used unnormalized.
-    //   Opera 7 final/Win:
-    //     10ms is normalized to 100ms.
-    //     >10ms is used unnormalized.
-    if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10 ) {
-      return FrameTimeout(100);
-    }
-
-    // The provided timeout value is OK as-is.
-    return FrameTimeout(aRawMilliseconds);
-  }
-
-  bool operator==(const FrameTimeout& aOther) const
-  {
-    return mTimeout == aOther.mTimeout;
-  }
-
-  bool operator!=(const FrameTimeout& aOther) const { return !(*this == aOther); }
-
-  FrameTimeout operator+(const FrameTimeout& aOther)
-  {
-    if (*this == Forever() || aOther == Forever()) {
-      return Forever();
-    }
-
-    return FrameTimeout(mTimeout + aOther.mTimeout);
-  }
-
-  FrameTimeout& operator+=(const FrameTimeout& aOther)
-  {
-    *this = *this + aOther;
-    return *this;
-  }
-
-  /**
-   * @return this FrameTimeout's value in milliseconds. Illegal to call on a
-   * an infinite FrameTimeout value.
-   */
-  uint32_t AsMilliseconds() const
-  {
-    if (*this == Forever()) {
-      MOZ_ASSERT_UNREACHABLE("Calling AsMilliseconds() on an infinite FrameTimeout");
-      return 100;  // Fail to something sane.
-    }
-
-    return uint32_t(mTimeout);
-  }
-
-  /**
-   * @return this FrameTimeout value encoded so that non-negative values
-   * represent a timeout in milliseconds, and -1 represents an infinite
-   * timeout.
-   *
-   * XXX(seth): This is a backwards compatibility hack that should be removed.
-   */
-  int32_t AsEncodedValueDeprecated() const { return mTimeout; }
-
-private:
-  explicit FrameTimeout(int32_t aTimeout)
-    : mTimeout(aTimeout)
-  { }
-
-  int32_t mTimeout;
-};
-
-} // namespace image
-} // namespace mozilla
-
-#endif // mozilla_image_FrameTimeout_h
--- a/image/ImageMetadata.h
+++ b/image/ImageMetadata.h
@@ -6,21 +6,22 @@
 
 #ifndef mozilla_image_ImageMetadata_h
 #define mozilla_image_ImageMetadata_h
 
 #include <stdint.h>
 #include "mozilla/Maybe.h"
 #include "nsSize.h"
 #include "Orientation.h"
-#include "FrameTimeout.h"
 
 namespace mozilla {
 namespace image {
 
+class RasterImage;
+
 // The metadata about an image that decoders accumulate as they decode.
 class ImageMetadata
 {
 public:
   ImageMetadata()
     : mLoopCount(-1)
     , mFirstFrameTimeout(FrameTimeout::Forever())
     , mHasAnimation(false)
@@ -58,23 +59,16 @@ public:
     if (!HasSize()) {
       mSize.emplace(nsIntSize(width, height));
       mOrientation.emplace(orientation);
     }
   }
   nsIntSize GetSize() const { return *mSize; }
   bool HasSize() const { return mSize.isSome(); }
 
-  void AddNativeSize(const nsIntSize& aSize)
-  {
-    mNativeSizes.AppendElement(aSize);
-  }
-
-  const nsTArray<nsIntSize>& GetNativeSizes() const { return mNativeSizes; }
-
   Orientation GetOrientation() const { return *mOrientation; }
   bool HasOrientation() const { return mOrientation.isSome(); }
 
   void SetHasAnimation() { mHasAnimation = true; }
   bool HasAnimation() const { return mHasAnimation; }
 
 private:
   /// The hotspot found on cursors, if present.
@@ -91,18 +85,15 @@ private:
 
   // The area of the image that needs to be invalidated when the animation
   // loops.
   Maybe<gfx::IntRect> mFirstFrameRefreshArea;
 
   Maybe<nsIntSize> mSize;
   Maybe<Orientation> mOrientation;
 
-  // Sizes the image can natively decode to.
-  nsTArray<nsIntSize> mNativeSizes;
-
   bool mHasAnimation : 1;
 };
 
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_ImageMetadata_h
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -9,17 +9,16 @@
 #include "ClippedImage.h"
 #include "DecodePool.h"
 #include "Decoder.h"
 #include "DecoderFactory.h"
 #include "DynamicImage.h"
 #include "FrozenImage.h"
 #include "IDecodingTask.h"
 #include "Image.h"
-#include "ImageMetadata.h"
 #include "imgIContainer.h"
 #include "mozilla/gfx/2D.h"
 #include "nsStreamUtils.h"
 #include "OrientedImage.h"
 #include "SourceBuffer.h"
 
 using namespace mozilla::gfx;
 
@@ -75,37 +74,20 @@ ImageOps::Orient(imgIContainer* aImage, 
 
 /* static */ already_AddRefed<imgIContainer>
 ImageOps::CreateFromDrawable(gfxDrawable* aDrawable)
 {
   nsCOMPtr<imgIContainer> drawableImage = new DynamicImage(aDrawable);
   return drawableImage.forget();
 }
 
-class ImageOps::ImageBufferImpl final : public ImageOps::ImageBuffer {
-public:
-  ImageBufferImpl(already_AddRefed<SourceBuffer> aSourceBuffer)
-    : mSourceBuffer(aSourceBuffer)
-  { }
-
-protected:
-  ~ImageBufferImpl() override { }
-
-  virtual already_AddRefed<SourceBuffer> GetSourceBuffer()
-  {
-    RefPtr<SourceBuffer> sourceBuffer = mSourceBuffer;
-    return sourceBuffer.forget();
-  }
-
-private:
-  RefPtr<SourceBuffer> mSourceBuffer;
-};
-
-/* static */ already_AddRefed<ImageOps::ImageBuffer>
-ImageOps::CreateImageBuffer(nsIInputStream* aInputStream)
+/* static */ already_AddRefed<gfx::SourceSurface>
+ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
+                          const nsACString& aMimeType,
+                          uint32_t aFlags)
 {
   MOZ_ASSERT(aInputStream);
 
   nsresult rv;
 
   // Prepare the input stream.
   nsCOMPtr<nsIInputStream> inputStream = aInputStream;
   if (!NS_InputStreamIsBuffered(aInputStream)) {
@@ -120,115 +102,37 @@ ImageOps::CreateImageBuffer(nsIInputStre
   // Figure out how much data we've been passed.
   uint64_t length;
   rv = inputStream->Available(&length);
   if (NS_FAILED(rv) || length > UINT32_MAX) {
     return nullptr;
   }
 
   // Write the data into a SourceBuffer.
-  RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
+  NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
   sourceBuffer->ExpectLength(length);
   rv = sourceBuffer->AppendFromInputStream(inputStream, length);
   if (NS_FAILED(rv)) {
     return nullptr;
   }
   // Make sure our sourceBuffer is marked as complete.
   if (sourceBuffer->IsComplete()) {
     NS_WARNING("The SourceBuffer was unexpectedly marked as complete. This may "
                "indicate either an OOM condition, or that imagelib was not "
                "initialized properly.");
     return nullptr;
   }
   sourceBuffer->Complete(NS_OK);
 
-  RefPtr<ImageBuffer> imageBuffer = new ImageBufferImpl(sourceBuffer.forget());
-  return imageBuffer.forget();
-}
-
-/* static */ nsresult
-ImageOps::DecodeMetadata(nsIInputStream* aInputStream,
-                         const nsACString& aMimeType,
-                         ImageMetadata& aMetadata)
-{
-  RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
-  return DecodeMetadata(buffer, aMimeType, aMetadata);
-}
-
-/* static */ nsresult
-ImageOps::DecodeMetadata(ImageBuffer* aBuffer,
-                         const nsACString& aMimeType,
-                         ImageMetadata& aMetadata)
-{
-  if (!aBuffer) {
-    return NS_ERROR_FAILURE;
-  }
-
-  RefPtr<SourceBuffer> sourceBuffer = aBuffer->GetSourceBuffer();
-  if (NS_WARN_IF(!sourceBuffer)) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Create a decoder.
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get());
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousMetadataDecoder(decoderType,
-                                                   WrapNotNull(sourceBuffer));
-  if (!decoder) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Run the decoder synchronously.
-  RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder));
-  task->Run();
-  if (!decoder->GetDecodeDone() || decoder->HasError()) {
-    return NS_ERROR_FAILURE;
-  }
-
-  aMetadata = decoder->GetImageMetadata();
-  if (aMetadata.GetNativeSizes().IsEmpty() && aMetadata.HasSize()) {
-    aMetadata.AddNativeSize(aMetadata.GetSize());
-  }
-
-  return NS_OK;
-}
-
-/* static */ already_AddRefed<gfx::SourceSurface>
-ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
-                          const nsACString& aMimeType,
-                          uint32_t aFlags,
-                          Maybe<IntSize> aSize /* = Nothing() */)
-{
-  RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
-  return DecodeToSurface(buffer, aMimeType, aFlags, aSize);
-}
-
-/* static */ already_AddRefed<gfx::SourceSurface>
-ImageOps::DecodeToSurface(ImageBuffer* aBuffer,
-                          const nsACString& aMimeType,
-                          uint32_t aFlags,
-                          Maybe<IntSize> aSize /* = Nothing() */)
-{
-  if (!aBuffer) {
-    return nullptr;
-  }
-
-  RefPtr<SourceBuffer> sourceBuffer = aBuffer->GetSourceBuffer();
-  if (NS_WARN_IF(!sourceBuffer)) {
-    return nullptr;
-  }
-
-  // Create a decoder.
-  DecoderType decoderType =
-    DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get());
-  RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType,
-                                           WrapNotNull(sourceBuffer),
-                                           aSize, ToSurfaceFlags(aFlags));
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+                                           Nothing(), ToSurfaceFlags(aFlags));
   if (!decoder) {
     return nullptr;
   }
 
   // Run the decoder synchronously.
   RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder));
   task->Run();
   if (!decoder->GetDecodeDone() || decoder->HasError()) {
--- a/image/ImageOps.h
+++ b/image/ImageOps.h
@@ -4,49 +4,35 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_image_ImageOps_h
 #define mozilla_image_ImageOps_h
 
 #include "nsCOMPtr.h"
 #include "nsRect.h"
-#include "ImageMetadata.h"
 
 class gfxDrawable;
 class imgIContainer;
 class nsIInputStream;
 
 namespace mozilla {
 
 namespace gfx {
 class SourceSurface;
 }
 
 namespace image {
 
 class Image;
 struct Orientation;
-class SourceBuffer;
 
 class ImageOps
 {
 public:
-  class ImageBuffer {
-  public:
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageOps::ImageBuffer);
-  protected:
-    friend class ImageOps;
-
-    ImageBuffer() { }
-    virtual ~ImageBuffer() { }
-
-    virtual already_AddRefed<SourceBuffer> GetSourceBuffer() = 0;
-  };
-
   /**
    * Creates a version of an existing image which does not animate and is frozen
    * at the first frame.
    *
    * @param aImage         The existing image.
    */
   static already_AddRefed<Image> Freeze(Image* aImage);
   static already_AddRefed<imgIContainer> Freeze(imgIContainer* aImage);
@@ -84,78 +70,33 @@ public:
    * Creates an image from a gfxDrawable.
    *
    * @param aDrawable      The gfxDrawable.
    */
   static already_AddRefed<imgIContainer>
   CreateFromDrawable(gfxDrawable* aDrawable);
 
   /**
-   * Create a buffer to be used with DecodeMetadata and DecodeToSurface. Reusing
-   * an ImageBuffer representing the given input stream is more efficient if one
-   * has multiple Decode* calls to make on that stream.
-   *
-   * @param aInputStream An input stream containing an encoded image.
-   * @return An image buffer derived from the input stream.
-   */
-  static already_AddRefed<ImageBuffer>
-  CreateImageBuffer(nsIInputStream* aInputStream);
-
-  /**
-   * Decodes an image's metadata from an nsIInputStream into the given
-   * structure. This function may be called off-main-thread.
-   *
-   * @param aInputStream An input stream containing an encoded image.
-   * @param aMimeType The MIME type of the image.
-   * @param aMetadata Where the image metadata is stored upon success.
-   * @return The status of the operation.
-   */
-  static nsresult
-  DecodeMetadata(nsIInputStream* aInputStream,
-                 const nsACString& aMimeType,
-                 ImageMetadata& aMetadata);
-
-  /**
-   * Same as above but takes an ImageBuffer instead of nsIInputStream.
-   */
-  static nsresult
-  DecodeMetadata(ImageBuffer* aBuffer,
-                 const nsACString& aMimeType,
-                 ImageMetadata& aMetadata);
-
-  /**
    * Decodes an image from an nsIInputStream directly into a SourceSurface,
    * without ever creating an Image or imgIContainer (which are mostly
    * main-thread-only). That means that this function may be called
    * off-main-thread.
    *
    * @param aInputStream An input stream containing an encoded image.
    * @param aMimeType The MIME type of the image.
    * @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
    * @return A SourceSurface containing the first frame of the image at its
    *         intrinsic size, or nullptr if the image cannot be decoded.
    */
   static already_AddRefed<gfx::SourceSurface>
   DecodeToSurface(nsIInputStream* aInputStream,
                   const nsACString& aMimeType,
-                  uint32_t aFlags,
-                  Maybe<gfx::IntSize> aSize = Nothing());
-
-  /**
-   * Same as above but takes an ImageBuffer instead of nsIInputStream.
-   */
-  static already_AddRefed<gfx::SourceSurface>
-  DecodeToSurface(ImageBuffer* aBuffer,
-                  const nsACString& aMimeType,
-                  uint32_t aFlags,
-                  Maybe<gfx::IntSize> aSize = Nothing());
+                  uint32_t aFlags);
 
 private:
-  class ImageBufferImpl;
-
   // This is a static utility class, so disallow instantiation.
   virtual ~ImageOps() = 0;
 };
 
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_ImageOps_h
--- a/image/ImageWrapper.cpp
+++ b/image/ImageWrapper.cpp
@@ -134,22 +134,16 @@ ImageWrapper::GetWidth(int32_t* aWidth)
 }
 
 NS_IMETHODIMP
 ImageWrapper::GetHeight(int32_t* aHeight)
 {
   return mInnerImage->GetHeight(aHeight);
 }
 
-nsresult
-ImageWrapper::GetNativeSizes(nsTArray<IntSize>& aNativeSizes) const
-{
-  return mInnerImage->GetNativeSizes(aNativeSizes);
-}
-
 NS_IMETHODIMP
 ImageWrapper::GetIntrinsicSize(nsSize* aSize)
 {
   return mInnerImage->GetIntrinsicSize(aSize);
 }
 
 NS_IMETHODIMP
 ImageWrapper::GetIntrinsicRatio(nsSize* aSize)
--- a/image/ImageWrapper.h
+++ b/image/ImageWrapper.h
@@ -17,17 +17,16 @@ namespace image {
  */
 class ImageWrapper : public Image
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGICONTAINER
 
   // Inherited methods from Image.
-  nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
   virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
 
   virtual size_t
     SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const override;
   virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
                                      MallocSizeOf aMallocSizeOf) const override;
 
   virtual void IncrementAnimationConsumers() override;
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -41,32 +41,16 @@ OrientedImage::GetHeight(int32_t* aHeigh
 {
   if (mOrientation.SwapsWidthAndHeight()) {
     return InnerImage()->GetWidth(aHeight);
   } else {
     return InnerImage()->GetHeight(aHeight);
   }
 }
 
-nsresult
-OrientedImage::GetNativeSizes(nsTArray<IntSize>& aNativeSizes) const
-{
-  nsresult rv = InnerImage()->GetNativeSizes(aNativeSizes);
-
-  if (mOrientation.SwapsWidthAndHeight()) {
-    auto i = aNativeSizes.Length();
-    while (i > 0) {
-      --i;
-      swap(aNativeSizes[i].width, aNativeSizes[i].height);
-    }
-  }
-
-  return rv;
-}
-
 NS_IMETHODIMP
 OrientedImage::GetIntrinsicSize(nsSize* aSize)
 {
   nsresult rv = InnerImage()->GetIntrinsicSize(aSize);
 
   if (mOrientation.SwapsWidthAndHeight()) {
     swap(aSize->width, aSize->height);
   }
--- a/image/OrientedImage.h
+++ b/image/OrientedImage.h
@@ -25,17 +25,16 @@ class OrientedImage : public ImageWrappe
 {
   typedef gfx::SourceSurface SourceSurface;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD GetWidth(int32_t* aWidth) override;
   NS_IMETHOD GetHeight(int32_t* aHeight) override;
-  nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
   NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override;
   NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
   NS_IMETHOD_(already_AddRefed<SourceSurface>)
     GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
   NS_IMETHOD_(already_AddRefed<SourceSurface>)
     GetFrameAtSize(const gfx::IntSize& aSize,
                    uint32_t aWhichFrame,
                    uint32_t aFlags) override;
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -216,34 +216,16 @@ RasterImage::GetHeight(int32_t* aHeight)
     return NS_ERROR_FAILURE;
   }
 
   *aHeight = mSize.height;
   return NS_OK;
 }
 
 //******************************************************************************
-nsresult
-RasterImage::GetNativeSizes(nsTArray<IntSize>& aNativeSizes) const
-{
-  if (mError) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (mNativeSizes.IsEmpty()) {
-    aNativeSizes.Clear();
-    aNativeSizes.AppendElement(mSize);
-  } else {
-    aNativeSizes = mNativeSizes;
-  }
-
-  return NS_OK;
-}
-
-//******************************************************************************
 NS_IMETHODIMP
 RasterImage::GetIntrinsicSize(nsSize* aSize)
 {
   if (mError) {
     return NS_ERROR_FAILURE;
   }
 
   *aSize = nsSize(nsPresContext::CSSPixelsToAppUnits(mSize.width),
@@ -716,17 +698,16 @@ RasterImage::SetMetadata(const ImageMeta
                  "This should not happen!");
       DoError();
       return true;
     }
 
     // Set the size and flag that we have it.
     mSize = size;
     mOrientation = orientation;
-    mNativeSizes = aMetadata.GetNativeSizes();
     mHasSize = true;
   }
 
   if (mHasSize && aMetadata.HasAnimation() && !mAnimationState) {
     // We're becoming animated, so initialize animation stuff.
     mAnimationState.emplace(mAnimationMode);
     mFrameAnimator = MakeUnique<FrameAnimator>(this, mSize);
 
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -155,17 +155,16 @@ public:
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(RasterImage)
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPROPERTIES
   NS_DECL_IMGICONTAINER
 #ifdef DEBUG
   NS_DECL_IMGICONTAINERDEBUG
 #endif
 
-  nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
   virtual nsresult StartAnimation() override;
   virtual nsresult StopAnimation() override;
 
   // Methods inherited from Image
   virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override;
 
   virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
     const override;
@@ -376,17 +375,16 @@ private:
    *
    * RecoverFromInvalidFrames discards all existing frames and redecodes using
    * the provided @aSize and @aFlags.
    */
   void RecoverFromInvalidFrames(const nsIntSize& aSize, uint32_t aFlags);
 
 private: // data
   nsIntSize                  mSize;
-  nsTArray<nsIntSize>        mNativeSizes;
   Orientation                mOrientation;
 
   /// If this has a value, we're waiting for SetSize() to send the load event.
   Maybe<Progress>            mLoadProgress;
 
   nsCOMPtr<nsIProperties>   mProperties;
 
   /// If this image is animated, a FrameAnimator which manages its animation.
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -516,23 +516,16 @@ VectorImage::GetWidth(int32_t* aWidth)
     *aWidth = 0;
     return NS_ERROR_FAILURE;
   }
   *aWidth = rootElemWidth;
   return NS_OK;
 }
 
 //******************************************************************************
-nsresult
-VectorImage::GetNativeSizes(nsTArray<IntSize>& aNativeSizes) const
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-//******************************************************************************
 NS_IMETHODIMP_(void)
 VectorImage::RequestRefresh(const TimeStamp& aTime)
 {
   if (HadRecentRefresh(aTime)) {
     return;
   }
 
   PendingAnimationTracker* tracker =
--- a/image/VectorImage.h
+++ b/image/VectorImage.h
@@ -29,17 +29,16 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_IMGICONTAINER
 
   // (no public constructor - use ImageFactory)
 
   // Methods inherited from Image
-  nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
   virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
     const override;
   virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
                                      MallocSizeOf aMallocSizeOf) const override;
 
   virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
                                         nsISupports* aContext,
                                         nsIInputStream* aInStr,
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -237,18 +237,16 @@ nsICODecoder::ReadDirEntry(const char* a
     mBiggestResourceColorDepth = e.mBitCount;
     mBiggestResourceHotSpot = IntSize(e.mXHotspot, e.mYHotspot);
 
     if (!desiredSize) {
       mDirEntry = e;
     }
   }
 
-  mImageMetadata.AddNativeSize(entrySize);
-
   if (desiredSize) {
     // Calculate the delta between this resource's size and the desired size, so
     // we can see if it is better than our current-best option.  In the case of
     // several equally-good resources, we use the last one. "Better" in this
     // case is determined by |delta|, a measure of the difference in size
     // between the entry we've found and the desired size. We will choose the
     // smallest resource that is greater than or equal to the desired size (i.e.
     // we assume it's better to downscale a larger icon than to upscale a
--- a/image/imgFrame.h
+++ b/image/imgFrame.h
@@ -6,17 +6,16 @@
 
 #ifndef mozilla_image_imgFrame_h
 #define mozilla_image_imgFrame_h
 
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Move.h"
-#include "FrameTimeout.h"
 #include "gfxDrawable.h"
 #include "imgIContainer.h"
 #include "MainThreadUtils.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace image {
 
@@ -43,16 +42,116 @@ enum class DisposalMethod : int8_t {
 };
 
 enum class Opacity : uint8_t {
   FULLY_OPAQUE,
   SOME_TRANSPARENCY
 };
 
 /**
+ * FrameTimeout wraps a frame timeout value (measured in milliseconds) after
+ * first normalizing it. This normalization is necessary because some tools
+ * generate incorrect frame timeout values which we nevertheless have to
+ * support. For this reason, code that deals with frame timeouts should always
+ * use a FrameTimeout value rather than the raw value from the image header.
+ */
+struct FrameTimeout
+{
+  /**
+   * @return a FrameTimeout of zero. This should be used only for math
+   * involving FrameTimeout values. You can't obtain a zero FrameTimeout from
+   * FromRawMilliseconds().
+   */
+  static FrameTimeout Zero() { return FrameTimeout(0); }
+
+  /// @return an infinite FrameTimeout.
+  static FrameTimeout Forever() { return FrameTimeout(-1); }
+
+  /// @return a FrameTimeout obtained by normalizing a raw timeout value.
+  static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds)
+  {
+    // Normalize all infinite timeouts to the same value.
+    if (aRawMilliseconds < 0) {
+      return FrameTimeout::Forever();
+    }
+
+    // Very small timeout values are problematic for two reasons: we don't want
+    // to burn energy redrawing animated images extremely fast, and broken tools
+    // generate these values when they actually want a "default" value, so such
+    // images won't play back right without normalization. For some context,
+    // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical
+    // behavior of IE and Opera was:
+    //   IE 6/Win:
+    //     10 - 50ms is normalized to 100ms.
+    //     >50ms is used unnormalized.
+    //   Opera 7 final/Win:
+    //     10ms is normalized to 100ms.
+    //     >10ms is used unnormalized.
+    if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10 ) {
+      return FrameTimeout(100);
+    }
+
+    // The provided timeout value is OK as-is.
+    return FrameTimeout(aRawMilliseconds);
+  }
+
+  bool operator==(const FrameTimeout& aOther) const
+  {
+    return mTimeout == aOther.mTimeout;
+  }
+
+  bool operator!=(const FrameTimeout& aOther) const { return !(*this == aOther); }
+
+  FrameTimeout operator+(const FrameTimeout& aOther)
+  {
+    if (*this == Forever() || aOther == Forever()) {
+      return Forever();
+    }
+
+    return FrameTimeout(mTimeout + aOther.mTimeout);
+  }
+
+  FrameTimeout& operator+=(const FrameTimeout& aOther)
+  {
+    *this = *this + aOther;
+    return *this;
+  }
+
+  /**
+   * @return this FrameTimeout's value in milliseconds. Illegal to call on a
+   * an infinite FrameTimeout value.
+   */
+  uint32_t AsMilliseconds() const
+  {
+    if (*this == Forever()) {
+      MOZ_ASSERT_UNREACHABLE("Calling AsMilliseconds() on an infinite FrameTimeout");
+      return 100;  // Fail to something sane.
+    }
+
+    return uint32_t(mTimeout);
+  }
+
+  /**
+   * @return this FrameTimeout value encoded so that non-negative values
+   * represent a timeout in milliseconds, and -1 represents an infinite
+   * timeout.
+   *
+   * XXX(seth): This is a backwards compatibility hack that should be removed.
+   */
+  int32_t AsEncodedValueDeprecated() const { return mTimeout; }
+
+private:
+  explicit FrameTimeout(int32_t aTimeout)
+    : mTimeout(aTimeout)
+  { }
+
+  int32_t mTimeout;
+};
+
+/**
  * AnimationData contains all of the information necessary for using an imgFrame
  * as part of an animation.
  *
  * It includes pointers to the raw image data of the underlying imgFrame, but
  * does not own that data. A RawAccessFrameRef for the underlying imgFrame must
  * outlive the AnimationData for it to remain valid.
  */
 struct AnimationData
--- a/image/imgIContainer.idl
+++ b/image/imgIContainer.idl
@@ -85,20 +85,16 @@ interface imgIContainer : nsISupports
   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;
 
-  %{C++
-  virtual nsresult GetNativeSizes(nsTArray<nsIntSize>& aNativeSizes) const = 0;
-  %}
-
   /**
    * 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;
 
   /**
--- a/image/moz.build
+++ b/image/moz.build
@@ -32,20 +32,18 @@ XPIDL_SOURCES += [
     'imgITools.idl',
     'nsIIconURI.idl',
 ]
 
 XPIDL_MODULE = 'imglib2'
 
 EXPORTS += [
     'DrawResult.h',
-    'FrameTimeout.h',
     'ImageCacheKey.h',
     'ImageLogging.h',
-    'ImageMetadata.h',
     'ImageOps.h',
     'ImageRegion.h',
     'imgLoader.h',
     'imgRequest.h',
     'imgRequestProxy.h',
     'IProgressObserver.h',
     'Orientation.h',
     'SurfaceCacheUtils.h',
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -674,16 +674,10 @@ ImageTestCase DownscaledTransparentICOWi
                        TEST_CASE_IS_TRANSPARENT | TEST_CASE_IGNORE_OUTPUT);
 }
 
 ImageTestCase TruncatedSmallGIFTestCase()
 {
   return ImageTestCase("green-1x1-truncated.gif", "image/gif", IntSize(1, 1));
 }
 
-ImageTestCase GreenMultipleSizesICOTestCase()
-{
-  return ImageTestCase("green-multiple-sizes.ico", "image/x-icon",
-                       IntSize(256, 256));
-}
-
 } // namespace image
 } // namespace mozilla
--- a/image/test/gtest/Common.h
+++ b/image/test/gtest/Common.h
@@ -409,14 +409,12 @@ ImageTestCase DownscaledGIFTestCase();
 ImageTestCase DownscaledJPGTestCase();
 ImageTestCase DownscaledBMPTestCase();
 ImageTestCase DownscaledICOTestCase();
 ImageTestCase DownscaledIconTestCase();
 ImageTestCase DownscaledTransparentICOWithANDMaskTestCase();
 
 ImageTestCase TruncatedSmallGIFTestCase();
 
-ImageTestCase GreenMultipleSizesICOTestCase();
-
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_test_gtest_Common_h
--- a/image/test/gtest/TestDecodeToSurface.cpp
+++ b/image/test/gtest/TestDecodeToSurface.cpp
@@ -22,93 +22,67 @@ using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
 class DecodeToSurfaceRunnable : public Runnable
 {
 public:
   DecodeToSurfaceRunnable(RefPtr<SourceSurface>& aSurface,
                           nsIInputStream* aInputStream,
-                          ImageOps::ImageBuffer* aImageBuffer,
                           const ImageTestCase& aTestCase)
     : mSurface(aSurface)
     , mInputStream(aInputStream)
-    , mImageBuffer(aImageBuffer)
     , mTestCase(aTestCase)
   { }
 
   NS_IMETHOD Run() override
   {
     Go();
     return NS_OK;
   }
 
   void Go()
   {
-    Maybe<IntSize> outputSize;
-    if (mTestCase.mOutputSize != mTestCase.mSize) {
-      outputSize.emplace(mTestCase.mOutputSize);
-    }
-
-    if (mImageBuffer) {
-      mSurface =
-        ImageOps::DecodeToSurface(mImageBuffer,
-                                  nsDependentCString(mTestCase.mMimeType),
-                                  imgIContainer::DECODE_FLAGS_DEFAULT,
-                                  outputSize);
-    } else {
-      mSurface =
-        ImageOps::DecodeToSurface(mInputStream,
-                                  nsDependentCString(mTestCase.mMimeType),
-                                  imgIContainer::DECODE_FLAGS_DEFAULT,
-                                  outputSize);
-    }
+    mSurface =
+      ImageOps::DecodeToSurface(mInputStream,
+                                nsDependentCString(mTestCase.mMimeType),
+                                imgIContainer::DECODE_FLAGS_DEFAULT);
     ASSERT_TRUE(mSurface != nullptr);
 
     EXPECT_TRUE(mSurface->IsDataSourceSurface());
     EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
                 mSurface->GetFormat() == SurfaceFormat::B8G8R8A8);
-
-    if (outputSize) {
-      EXPECT_EQ(*outputSize, mSurface->GetSize());
-    } else {
-      EXPECT_EQ(mTestCase.mSize, mSurface->GetSize());
-    }
+    EXPECT_EQ(mTestCase.mSize, mSurface->GetSize());
 
     EXPECT_TRUE(IsSolidColor(mSurface, BGRAColor::Green(),
                              mTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0));
   }
 
 private:
   RefPtr<SourceSurface>& mSurface;
   nsCOMPtr<nsIInputStream> mInputStream;
-  RefPtr<ImageOps::ImageBuffer> mImageBuffer;
   ImageTestCase mTestCase;
 };
 
 static void
-RunDecodeToSurface(const ImageTestCase& aTestCase,
-                   ImageOps::ImageBuffer* aImageBuffer = nullptr)
+RunDecodeToSurface(const ImageTestCase& aTestCase)
 {
-  nsCOMPtr<nsIInputStream> inputStream;
-  if (!aImageBuffer) {
-    inputStream = LoadFile(aTestCase.mPath);
-    ASSERT_TRUE(inputStream != nullptr);
-  }
+  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
+  ASSERT_TRUE(inputStream != nullptr);
 
   nsCOMPtr<nsIThread> thread;
   nsresult rv =
     NS_NewNamedThread("DecodeToSurface", getter_AddRefs(thread), nullptr);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   // We run the DecodeToSurface tests off-main-thread to ensure that
   // DecodeToSurface doesn't require any main-thread-only code.
   RefPtr<SourceSurface> surface;
   nsCOMPtr<nsIRunnable> runnable =
-    new DecodeToSurfaceRunnable(surface, inputStream, aImageBuffer, aTestCase);
+    new DecodeToSurfaceRunnable(surface, inputStream, aTestCase);
   thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC);
 
   thread->Shutdown();
 
   // Explicitly release the SourceSurface on the main thread.
   surface = nullptr;
 }
 
@@ -143,48 +117,8 @@ TEST_F(ImageDecodeToSurface, Corrupt)
   ASSERT_TRUE(inputStream != nullptr);
 
   RefPtr<SourceSurface> surface =
     ImageOps::DecodeToSurface(inputStream,
                               nsDependentCString(testCase.mMimeType),
                               imgIContainer::DECODE_FLAGS_DEFAULT);
   EXPECT_TRUE(surface == nullptr);
 }
-
-TEST_F(ImageDecodeToSurface, ICOMultipleSizes)
-{
-  ImageTestCase testCase = GreenMultipleSizesICOTestCase();
-
-  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
-  ASSERT_TRUE(inputStream != nullptr);
-
-  RefPtr<ImageOps::ImageBuffer> buffer =
-    ImageOps::CreateImageBuffer(inputStream);
-  ASSERT_TRUE(buffer != nullptr);
-
-  ImageMetadata metadata;
-  nsresult rv = ImageOps::DecodeMetadata(buffer,
-                                         nsDependentCString(testCase.mMimeType),
-                                         metadata);
-  EXPECT_TRUE(NS_SUCCEEDED(rv));
-  ASSERT_TRUE(metadata.HasSize());
-  EXPECT_EQ(testCase.mSize, metadata.GetSize());
-
-  const nsTArray<IntSize>& nativeSizes = metadata.GetNativeSizes();
-  ASSERT_EQ(6, nativeSizes.Length());
-
-  IntSize expectedSizes[] = {
-    IntSize(16, 16),
-    IntSize(32, 32),
-    IntSize(64, 64),
-    IntSize(128, 128),
-    IntSize(256, 256),
-    IntSize(256, 128),
-  };
-
-  for (int i = 0; i < 6; ++i) {
-    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
-
-    // Request decoding at native size
-    testCase.mOutputSize = nativeSizes[i];
-    RunDecodeToSurface(testCase, buffer);
-  }
-}
--- a/image/test/gtest/TestDecoders.cpp
+++ b/image/test/gtest/TestDecoders.cpp
@@ -667,92 +667,8 @@ TEST_F(ImageDecoders, AnimatedGIFWithExt
   EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1)));
   EXPECT_TRUE(bool(result.Surface()));
 }
 
 TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk)
 {
   CheckDecoderSingleChunk(TruncatedSmallGIFTestCase());
 }
-
-TEST_F(ImageDecoders, MultipleSizesICOSingleChunk)
-{
-  ImageTestCase testCase = GreenMultipleSizesICOTestCase();
-
-  // Create an image.
-  RefPtr<Image> image =
-    ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType));
-  ASSERT_TRUE(!image->HasError());
-
-  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
-  ASSERT_TRUE(inputStream);
-
-  // Figure out how much data we have.
-  uint64_t length;
-  nsresult rv = inputStream->Available(&length);
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
-  // Write the data into the image.
-  rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
-                                   static_cast<uint32_t>(length));
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
-  // Let the image know we've sent all the data.
-  rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
-  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
-  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
-
-  // Use GetFrame() to force a sync decode of the image.
-  RefPtr<SourceSurface> surface =
-    image->GetFrame(imgIContainer::FRAME_CURRENT,
-                    imgIContainer::FLAG_SYNC_DECODE);
-
-  // Ensure that the image's metadata meets our expectations.
-  IntSize imageSize(0, 0);
-  rv = image->GetWidth(&imageSize.width);
-  EXPECT_TRUE(NS_SUCCEEDED(rv));
-  rv = image->GetHeight(&imageSize.height);
-  EXPECT_TRUE(NS_SUCCEEDED(rv));
-
-  EXPECT_EQ(testCase.mSize.width, imageSize.width);
-  EXPECT_EQ(testCase.mSize.height, imageSize.height);
-
-  nsTArray<IntSize> nativeSizes;
-  rv = image->GetNativeSizes(nativeSizes);
-  EXPECT_TRUE(NS_SUCCEEDED(rv));
-  ASSERT_EQ(6, nativeSizes.Length());
-
-  IntSize expectedSizes[] = {
-    IntSize(16, 16),
-    IntSize(32, 32),
-    IntSize(64, 64),
-    IntSize(128, 128),
-    IntSize(256, 256),
-    IntSize(256, 128)
-  };
-
-  for (int i = 0; i < 6; ++i) {
-    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
-  }
-
-  RefPtr<Image> image90 =
-    ImageOps::Orient(image, Orientation(Angle::D90, Flip::Unflipped));
-  rv = image90->GetNativeSizes(nativeSizes);
-  EXPECT_TRUE(NS_SUCCEEDED(rv));
-  ASSERT_EQ(6, nativeSizes.Length());
-
-  for (int i = 0; i < 5; ++i) {
-    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
-  }
-  EXPECT_EQ(IntSize(128, 256), nativeSizes[5]);
-
-  RefPtr<Image> image180 =
-    ImageOps::Orient(image, Orientation(Angle::D180, Flip::Unflipped));
-  rv = image180->GetNativeSizes(nativeSizes);
-  EXPECT_TRUE(NS_SUCCEEDED(rv));
-  ASSERT_EQ(6, nativeSizes.Length());
-
-  for (int i = 0; i < 6; ++i) {
-    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
-  }
-}
deleted file mode 100644
index b9463d0c897117204b2edacfa6cbfc4f5f61d771..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/image/test/gtest/moz.build
+++ b/image/test/gtest/moz.build
@@ -42,17 +42,16 @@ TEST_HARNESS_FILES.gtest += [
     'downscaled.ico',
     'downscaled.icon',
     'downscaled.jpg',
     'downscaled.png',
     'first-frame-green.gif',
     'first-frame-green.png',
     'first-frame-padding.gif',
     'green-1x1-truncated.gif',
-    'green-multiple-sizes.ico',
     'green.bmp',
     'green.gif',
     'green.ico',
     'green.icon',
     'green.jpg',
     'green.png',
     'invalid-truncated-metadata.bmp',
     'no-frame-delay.gif',