Expose multi-frame methods for SkCodecImageGenerator

This will allow Flutter to avoid some usages of SkCodec
and have consistent EXIF handling for multi-frame formats
that support EXIF.

Change-Id: I80daee9b00777d88d0a960cc0f0d76da6680e257
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302270
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Dan Field <dnfield@google.com>
diff --git a/src/codec/SkCodecImageGenerator.cpp b/src/codec/SkCodecImageGenerator.cpp
index ba02233..7a23c07 100644
--- a/src/codec/SkCodecImageGenerator.cpp
+++ b/src/codec/SkCodecImageGenerator.cpp
@@ -46,12 +46,11 @@
     return fData;
 }
 
-bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
-                                        size_t requestRowBytes, const Options&) {
-    SkPixmap dst(requestInfo, requestPixels, requestRowBytes);
+bool SkCodecImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const SkCodec::Options* options) {
+    SkPixmap dst(info, pixels, rowBytes);
 
-    auto decode = [this](const SkPixmap& pm) {
-        SkCodec::Result result = fCodec->getPixels(pm);
+    auto decode = [this, options](const SkPixmap& pm) {
+        SkCodec::Result result = fCodec->getPixels(pm, options);
         switch (result) {
             case SkCodec::kSuccess:
             case SkCodec::kIncompleteInput:
@@ -65,6 +64,11 @@
     return SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode);
 }
 
+bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
+                                        size_t requestRowBytes, const Options& options) {
+    return this->getPixels(requestInfo, requestPixels, requestRowBytes, nullptr);
+}
+
 bool SkCodecImageGenerator::onQueryYUVA8(SkYUVASizeInfo* sizeInfo,
                                          SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
                                          SkYUVColorSpace* colorSpace) const {
diff --git a/src/codec/SkCodecImageGenerator.h b/src/codec/SkCodecImageGenerator.h
index c27e77f..11664ba 100644
--- a/src/codec/SkCodecImageGenerator.h
+++ b/src/codec/SkCodecImageGenerator.h
@@ -32,16 +32,78 @@
      */
     SkISize getScaledDimensions(float desiredScale) const;
 
+    /**
+     *  Decode into the given pixels, a block of memory of size at
+     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
+     *  bytesPerPixel)
+     *
+     *  Repeated calls to this function should give the same results,
+     *  allowing the PixelRef to be immutable.
+     *
+     *  @param info A description of the format
+     *         expected by the caller.  This can simply be identical
+     *         to the info returned by getInfo().
+     *
+     *         This contract also allows the caller to specify
+     *         different output-configs, which the implementation can
+     *         decide to support or not.
+     *
+     *         A size that does not match getInfo() implies a request
+     *         to scale. If the generator cannot perform this scale,
+     *         it will return false.
+     *
+     *  @return true on success.
+     */
+    bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const SkCodec::Options* options = nullptr);
+
+    /**
+     *  Return the number of frames in the image.
+     *
+     *  May require reading through the stream.
+     */
+    int getFrameCount() { return fCodec->getFrameCount(); }
+
+    /**
+     *  Return info about a single frame.
+     *
+     *  Only supported by multi-frame images. Does not read through the stream,
+     *  so it should be called after getFrameCount() to parse any frames that
+     *  have not already been parsed.
+     */
+    bool getFrameInfo(int index, SkCodec::FrameInfo* info) const {
+        return fCodec->getFrameInfo(index, info);
+    }
+
+    /**
+     *  Return the number of times to repeat, if this image is animated. This number does not
+     *  include the first play through of each frame. For example, a repetition count of 4 means
+     *  that each frame is played 5 times and then the animation stops.
+     *
+     *  It can return kRepetitionCountInfinite, a negative number, meaning that the animation
+     *  should loop forever.
+     *
+     *  May require reading the stream to find the repetition count.
+     *
+     *  As such, future decoding calls may require a rewind.
+     *
+     *  For still (non-animated) image codecs, this will return 0.
+     */
+    int getRepetitionCount() { return fCodec->getRepetitionCount(); }
+
 protected:
     sk_sp<SkData> onRefEncodedData() override;
 
-    bool onGetPixels(
-        const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts) override;
+    bool onGetPixels(const SkImageInfo& info,
+                     void* pixels,
+                     size_t rowBytes,
+                     const Options& opts) override;
 
-    bool onQueryYUVA8(
-        SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount], SkYUVColorSpace*) const override;
+    bool onQueryYUVA8(SkYUVASizeInfo*,
+                      SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                      SkYUVColorSpace*) const override;
 
-    bool onGetYUVA8Planes(const SkYUVASizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
+    bool onGetYUVA8Planes(const SkYUVASizeInfo&,
+                          const SkYUVAIndex[SkYUVAIndex::kIndexCount],
                           void* planes[]) override;
 
 private: