Use SkAndroidCodec in SkAnimatedImage

Bug: b/63909536
Bug: b/63908092

SkAnimatedImage is designed around a specific Android use case, so move
it into the android folders.

Make SkAnimatedImage hold an SkAndroidCodec (instead of an SkCodec).
Expose fCodec so that SkAnimatedImage can animate by using the internal
SkCodec.

Update the sample to use SkAndroidCodec.

Allow webp to decode a scaled down animation. For RestoreBG frames,
adjust the frameRect (which is erased) to account for the scaling. Add
a test to verify that we decode a webp with a RestoreBG frame
successfully. Disable scaling for later frames in other formats (GIF,
for now), since the code for erasing a RestoreBG frame is currently
unaware of the sampling.

Change-Id: I5dd2b86138f2c7f6adcd08dce1bd49040f7dc224
Reviewed-on: https://skia-review.googlesource.com/94621
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp
index b09c925..f707f1e 100644
--- a/tests/CodecAnimTest.cpp
+++ b/tests/CodecAnimTest.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkAndroidCodec.h"
 #include "SkBitmap.h"
 #include "SkCodec.h"
 #include "SkCommonFlags.h"
@@ -386,3 +387,52 @@
         }
     }
 }
+
+// Verify that a webp image can be animated scaled down. This image has a
+// kRestoreBG frame, so it is an interesting image to test. After decoding that
+// frame, we have to erase its rectangle. The rectangle has to be adjusted
+// based on the scaled size.
+DEF_TEST(AndroidCodec_animated, r) {
+    if (GetResourcePath().isEmpty()) {
+        return;
+    }
+
+    const char* file = "images/required.webp";
+    sk_sp<SkData> data(GetResourceAsData(file));
+    if (!data) {
+        ERRORF(r, "Missing %s", file);
+        return;
+    }
+
+    auto codec = SkAndroidCodec::MakeFromCodec(SkCodec::MakeFromData(std::move(data)));
+    if (!codec) {
+        ERRORF(r, "Failed to decode %s", file);
+        return;
+    }
+
+    auto info = codec->getInfo().makeAlphaType(kPremul_SkAlphaType);
+
+    for (int sampleSize : { 8, 32, 100 }) {
+        auto dimensions = codec->codec()->getScaledDimensions(1.0f / sampleSize);
+        info = info.makeWH(dimensions.width(), dimensions.height());
+        SkBitmap bm;
+        bm.allocPixels(info);
+
+        SkCodec::Options options;
+        for (int i = 0; i < codec->codec()->getFrameCount(); ++i) {
+            SkCodec::FrameInfo frameInfo;
+            REPORTER_ASSERT(r, codec->codec()->getFrameInfo(i, &frameInfo));
+            if (5 == i) {
+                REPORTER_ASSERT(r, frameInfo.fDisposalMethod
+                        == SkCodecAnimation::DisposalMethod::kRestoreBGColor);
+            }
+            options.fFrameIndex = i;
+            options.fPriorFrame = i - 1;
+            info = info.makeAlphaType(frameInfo.fAlphaType);
+
+            const auto result = codec->codec()->getPixels(info, bm.getPixels(), bm.rowBytes(),
+                                                          &options);
+            REPORTER_ASSERT(r, result == SkCodec::kSuccess);
+        }
+    }
+}