Add animation support to SkWebpCodec

TBR=reed@google.com
(No change to the public API, but changed a header file)

SkWebpCodec:
- Implement onGetFrameCount, onGetFrameInfo, and onGetRepetitionCount
- Respect the alpha reported by libwebp. Although the spec states that
  it is only a hint, the libwebp encoder uses it properly. Respecting
  allows us to draw opaque images faster and decode them to 565. This
  also matches other SkCodecs (and Chromium).
- onGetPixels:
  - Decode the frame requested, recursively decoding required frame if
    necessary
  - When blending with a prior frame, use SkRasterPipeline

SkCodec:
- Move check for negative index to getFrameInfo
- Reset the colorXform if one is not needed

SkCodecAnimation:
- Add new blend enum, for WebP's (and APNG's) non-blending option

SkFrameHolder:
- New base classes for frames and the owner of the frames, allowing
  code sharing between SkWebpCodec and SkGifCodec (particularly for
  determining whether a frame has alpha and what frame it depends on)
- When moving items from SkGIFFrameContext, use Skia conventions (i.e.
  int instead of unsigned)
- Rename "delay time" to "duration", to match e.g. SkFrameInfo::
  fDuration

SkGifImageReader:
- Move pieces to SkFrameHolder, and adapt to changes made in the
  process
- Make setAlphaAndRequiredFrame (now on the base class SkFrameHolder)
  more general to support webp, and add support for frames that do not
  blend
- Change SkGIFFrameContext from a struct to a class, to match how we
  use the distinction elsewhere (i.e. struct is a small object with
  public fields)
- Rework hasTransparentPixel (now hasTransparency, since it returns true
  in some cases where there is not a transparent pixel) to better fit
  with the modified setAlphaAndRequiredFrame. Also be more consistent
  when there is no transparent pixel but no color map.
- Simplify an if condition that was previously simplified in 2d61e717
  but accidentally got reverted in a4db9be6

CodecAnimTest:
- Test new animated webp files
- Rearrange the test to more cleanly print alpha type mismatches for
  the first frame

resources:
- webp-animated.webp
  - animated webp from Chromium
- blendBG.webp
  - new webp file using bits of webp-animated-semitransparent4.webp
    from Chromium
  - tests required frame and alpha when using the non-blending mode
  - frames have the following properties:
    - Frame 0: no alpha, fills screen
    - Frame 1: alpha, fills screen
    - Frame 2: no alpha, fills screen
    - Frame 3: alpha, fills screen, blendBG
    - Frame 4: no alpha, fills screen, blendBG
    - Frame 5: alpha, blendBG
    - Frame 6: covers 4, has alpha, blendBG
  - also used to test decoding to 565 if the new frame data has alpha
    but blends onto an opaque frame

DM.cpp:
- Test animated images to non-native 8888 and unpremul

DMSrcSink.cpp:
- Do not test non-native 8888 decodes to f16 dst
- Test unpremul decodes to f16
- Copy a frame of an animated image prior to drawing, since in unpremul
  mode, the DM code will premultiply first.

Bug: skia: 3315
Change-Id: I4e55ae2ee5bc095b37a743bdcfac644be603b980
Reviewed-on: https://skia-review.googlesource.com/16707
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
diff --git a/src/codec/SkFrameHolder.h b/src/codec/SkFrameHolder.h
new file mode 100644
index 0000000..e92b40f
--- /dev/null
+++ b/src/codec/SkFrameHolder.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFrameHolder_DEFINED
+#define SkFrameHolder_DEFINED
+
+#include "SkTypes.h"
+#include "SkCodecAnimation.h"
+
+/**
+ *  Base class for a single frame of an animated image.
+ *
+ *  Separate from SkCodec::FrameInfo, which is a pared down
+ *  interface that only contains the info the client needs.
+ */
+class SkFrame : public SkNoncopyable {
+public:
+    SkFrame(int id)
+        : fId(id)
+        , fHasAlpha(false)
+        , fRequiredFrame(kUninitialized)
+        , fDisposalMethod(SkCodecAnimation::Keep_DisposalMethod)
+        , fDuration(0)
+        , fBlend(SkCodecAnimation::Blend::kPriorFrame)
+    {
+        fRect.setEmpty();
+    }
+
+    virtual ~SkFrame() {}
+
+    /**
+     *  0-based index of the frame in the image sequence.
+     */
+    int frameId() const { return fId; }
+
+    /**
+     *  Whether this frame reports alpha.
+     *
+     *  This only considers the rectangle of this frame, and
+     *  considers it to have alpha even if it is opaque once
+     *  blended with the frame behind it.
+     */
+    bool reportsAlpha() const {
+        return this->onReportsAlpha();
+    }
+
+    /**
+     *  Cached value representing whether the frame has alpha,
+     *  after compositing with the prior frame.
+     */
+    bool hasAlpha() const { return fHasAlpha; }
+
+    /**
+     *  Cache whether the finished frame has alpha.
+     */
+    void setHasAlpha(bool alpha) { fHasAlpha = alpha; }
+
+    /**
+     *  Whether enough of the frame has been read to determine
+     *  fRequiredFrame and fHasAlpha.
+     */
+    bool reachedStartOfData() const { return fRequiredFrame != kUninitialized; }
+
+    /**
+     *  The frame this one depends on.
+     *
+     *  Must not be called until fRequiredFrame has been set properly.
+     */
+    int getRequiredFrame() const {
+        SkASSERT(this->reachedStartOfData());
+        return fRequiredFrame;
+    }
+
+    /**
+     *  Set the frame that this frame depends on.
+     */
+    void setRequiredFrame(int req) { fRequiredFrame = req; }
+
+    /**
+     *  Set the rectangle that is updated by this frame.
+     */
+    void setXYWH(int x, int y, int width, int height) {
+        fRect.setXYWH(x, y, width, height);
+    }
+
+    /**
+     *  The rectangle that is updated by this frame.
+     */
+    SkIRect frameRect() const { return fRect; }
+
+    int xOffset() const { return fRect.x(); }
+    int yOffset() const { return fRect.y(); }
+    int width()   const { return fRect.width(); }
+    int height()  const { return fRect.height(); }
+
+    SkCodecAnimation::DisposalMethod getDisposalMethod() const {
+        return fDisposalMethod;
+    }
+
+    void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
+        fDisposalMethod = disposalMethod;
+    }
+
+    /**
+     * Set the duration (in ms) to show this frame.
+     */
+    void setDuration(int duration) {
+        fDuration = duration;
+    }
+
+    /**
+     *  Duration in ms to show this frame.
+     */
+    int getDuration() const {
+        return fDuration;
+    }
+
+    void setBlend(SkCodecAnimation::Blend blend) {
+        fBlend = blend;
+    }
+
+    SkCodecAnimation::Blend getBlend() const {
+        return fBlend;
+    }
+
+protected:
+    virtual bool onReportsAlpha() const = 0;
+
+private:
+    static constexpr int kUninitialized = -2;
+
+    const int                           fId;
+    bool                                fHasAlpha;
+    int                                 fRequiredFrame;
+    SkIRect                             fRect;
+    SkCodecAnimation::DisposalMethod    fDisposalMethod;
+    int                                 fDuration;
+    SkCodecAnimation::Blend             fBlend;
+};
+
+/**
+ *  Base class for an object which holds the SkFrames of an
+ *  image sequence.
+ */
+class SkFrameHolder : public SkNoncopyable {
+public:
+    SkFrameHolder()
+        : fScreenWidth(0)
+        , fScreenHeight(0)
+    {}
+
+    virtual ~SkFrameHolder() {}
+
+    /**
+     *  Size of the image. Each frame will be contained in
+     *  these dimensions (possibly after clipping).
+     */
+    int screenWidth() const { return fScreenWidth; }
+    int screenHeight() const { return fScreenHeight; }
+
+    /**
+     *  Compute the opacity and required frame, based on
+     *  whether the frame reportsAlpha and how it blends
+     *  with prior frames.
+     */
+    void setAlphaAndRequiredFrame(SkFrame*);
+
+    /**
+     *  Return the frame with frameId i.
+     */
+    const SkFrame* getFrame(int i) const {
+        return this->onGetFrame(i);
+    }
+
+protected:
+    int fScreenWidth;
+    int fScreenHeight;
+
+    virtual const SkFrame* onGetFrame(int i) const = 0;
+};
+
+#endif // SkFrameHolder_DEFINED