Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkAnimatedImage_DEFINED
      9 #define SkAnimatedImage_DEFINED
     10 
     11 #include "SkBitmap.h"
     12 #include "SkCodecAnimation.h"
     13 #include "SkDrawable.h"
     14 #include "SkMatrix.h"
     15 #include "SkRect.h"
     16 
     17 class SkAndroidCodec;
     18 class SkPicture;
     19 
     20 /**
     21  *  Thread unsafe drawable for drawing animated images (e.g. GIF).
     22  */
     23 class SK_API SkAnimatedImage : public SkDrawable {
     24 public:
     25     /**
     26      *  Create an SkAnimatedImage from the SkAndroidCodec.
     27      *
     28      *  Returns null on failure to allocate pixels. On success, this will
     29      *  decode the first frame.
     30      *
     31      *  @param info Width and height may require scaling.
     32      *  @param cropRect Rectangle to crop to after scaling.
     33      *  @param postProcess Picture to apply after scaling and cropping.
     34      */
     35     static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>,
     36             const SkImageInfo& info, SkIRect cropRect, sk_sp<SkPicture> postProcess);
     37 
     38     /**
     39      *  Create an SkAnimatedImage from the SkAndroidCodec.
     40      *
     41      *  Returns null on failure to allocate pixels. On success, this will
     42      *  decode the first frame.
     43      *
     44      *  @param scaledSize Size to draw the image, possibly requiring scaling.
     45      *  @param cropRect Rectangle to crop to after scaling.
     46      *  @param postProcess Picture to apply after scaling and cropping.
     47      */
     48     static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>,
     49             SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess);
     50 
     51     /**
     52      *  Simpler version that uses the default size, no cropping, and no postProcess.
     53      */
     54     static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>);
     55 
     56     ~SkAnimatedImage() override;
     57 
     58     /**
     59      *  Reset the animation to the beginning.
     60      */
     61     void reset();
     62 
     63     /**
     64      *  Whether the animation completed.
     65      *
     66      *  Returns true after all repetitions are complete, or an error stops the
     67      *  animation. Gets reset to false if the animation is restarted.
     68      */
     69     bool isFinished() const { return fFinished; }
     70 
     71     /**
     72      * Returned by decodeNextFrame and currentFrameDuration if the animation
     73      * is not running.
     74      */
     75     static constexpr int kFinished = -1;
     76 
     77     /**
     78      *  Decode the next frame.
     79      *
     80      *  If the animation is on the last frame or has hit an error, returns
     81      *  kFinished.
     82      */
     83     int decodeNextFrame();
     84 
     85     /**
     86      *  How long to display the current frame.
     87      *
     88      *  Useful for the first frame, for which decodeNextFrame is called
     89      *  internally.
     90      */
     91     int currentFrameDuration() {
     92         return fCurrentFrameDuration;
     93     }
     94 
     95     /**
     96      *  Change the repetition count.
     97      *
     98      *  By default, the image will repeat the number of times indicated in the
     99      *  encoded data.
    100      *
    101      *  Use SkCodec::kRepetitionCountInfinite for infinite, and 0 to show all
    102      *  frames once and then stop.
    103      */
    104     void setRepetitionCount(int count);
    105 
    106     /**
    107      *  Return the currently set repetition count.
    108      */
    109     int getRepetitionCount() const {
    110         return fRepetitionCount;
    111     }
    112 
    113 protected:
    114     SkRect onGetBounds() override;
    115     void onDraw(SkCanvas*) override;
    116 
    117 private:
    118     struct Frame {
    119         SkBitmap fBitmap;
    120         int      fIndex;
    121         SkCodecAnimation::DisposalMethod fDisposalMethod;
    122 
    123         // init() may have to create a new SkPixelRef, if the
    124         // current one is already in use by another owner (e.g.
    125         // an SkPicture). This determines whether to copy the
    126         // existing one to the new one.
    127         enum class OnInit {
    128             // Restore the image from the old SkPixelRef to the
    129             // new one.
    130             kRestoreIfNecessary,
    131             // No need to restore.
    132             kNoRestore,
    133         };
    134 
    135         Frame();
    136         bool init(const SkImageInfo& info, OnInit);
    137         bool copyTo(Frame*) const;
    138     };
    139 
    140     std::unique_ptr<SkAndroidCodec> fCodec;
    141     const SkISize                   fScaledSize;
    142     const SkImageInfo               fDecodeInfo;
    143     const SkIRect                   fCropRect;
    144     const sk_sp<SkPicture>          fPostProcess;
    145     const int                       fFrameCount;
    146     const bool                      fSimple;     // no crop, scale, or postprocess
    147     SkMatrix                        fMatrix;     // used only if !fSimple
    148 
    149     bool                            fFinished;
    150     int                             fCurrentFrameDuration;
    151     Frame                           fDisplayFrame;
    152     Frame                           fDecodingFrame;
    153     Frame                           fRestoreFrame;
    154     int                             fRepetitionCount;
    155     int                             fRepetitionsCompleted;
    156 
    157     SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, SkISize scaledSize,
    158             SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess);
    159     SkAnimatedImage(std::unique_ptr<SkAndroidCodec>);
    160 
    161     int computeNextFrame(int current, bool* animationEnded);
    162     double finish();
    163 
    164     typedef SkDrawable INHERITED;
    165 };
    166 
    167 #endif // SkAnimatedImage_DEFINED
    168