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      */
isFinished()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      */
currentFrameDuration()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      */
getRepetitionCount()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