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 scaledSize Size to draw the image, possibly requiring 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             SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess);
37 
38     /**
39      *  Simpler version that uses the default size, no cropping, and no postProcess.
40      */
41     static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>);
42 
43     ~SkAnimatedImage() override;
44 
45     /**
46      *  Reset the animation to the beginning.
47      */
48     void reset();
49 
50     /**
51      *  Whether the animation completed.
52      *
53      *  Returns true after all repetitions are complete, or an error stops the
54      *  animation. Gets reset to false if the animation is restarted.
55      */
isFinished()56     bool isFinished() const { return fFinished; }
57 
58     /**
59      * Returned by decodeNextFrame and currentFrameDuration if the animation
60      * is not running.
61      */
62     static constexpr int kFinished = -1;
63 
64     /**
65      *  Decode the next frame.
66      *
67      *  If the animation is on the last frame or has hit an error, returns
68      *  kFinished.
69      */
70     int decodeNextFrame();
71 
72     /**
73      *  How long to display the current frame.
74      *
75      *  Useful for the first frame, for which decodeNextFrame is called
76      *  internally.
77      */
currentFrameDuration()78     int currentFrameDuration() {
79         return fCurrentFrameDuration;
80     }
81 
82     /**
83      *  Change the repetition count.
84      *
85      *  By default, the image will repeat the number of times indicated in the
86      *  encoded data.
87      *
88      *  Use SkCodec::kRepetitionCountInfinite for infinite, and 0 to show all
89      *  frames once and then stop.
90      */
91     void setRepetitionCount(int count);
92 
93     /**
94      *  Return the currently set repetition count.
95      */
getRepetitionCount()96     int getRepetitionCount() const {
97         return fRepetitionCount;
98     }
99 
100 protected:
101     SkRect onGetBounds() override;
102     void onDraw(SkCanvas*) override;
103 
104 private:
105     struct Frame {
106         SkBitmap fBitmap;
107         int      fIndex;
108         SkCodecAnimation::DisposalMethod fDisposalMethod;
109 
110         // init() may have to create a new SkPixelRef, if the
111         // current one is already in use by another owner (e.g.
112         // an SkPicture). This determines whether to copy the
113         // existing one to the new one.
114         enum class OnInit {
115             // Restore the image from the old SkPixelRef to the
116             // new one.
117             kRestoreIfNecessary,
118             // No need to restore.
119             kNoRestore,
120         };
121 
122         Frame();
123         bool init(const SkImageInfo& info, OnInit);
124         bool copyTo(Frame*) const;
125     };
126 
127     std::unique_ptr<SkAndroidCodec> fCodec;
128     const SkISize                   fScaledSize;
129     const SkImageInfo               fDecodeInfo;
130     const SkIRect                   fCropRect;
131     const sk_sp<SkPicture>          fPostProcess;
132     const int                       fFrameCount;
133     const bool                      fSimple;     // no crop, scale, or postprocess
134     SkMatrix                        fMatrix;     // used only if !fSimple
135 
136     bool                            fFinished;
137     int                             fCurrentFrameDuration;
138     Frame                           fDisplayFrame;
139     Frame                           fDecodingFrame;
140     Frame                           fRestoreFrame;
141     int                             fRepetitionCount;
142     int                             fRepetitionsCompleted;
143 
144     SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, SkISize scaledSize,
145             SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess);
146     SkAnimatedImage(std::unique_ptr<SkAndroidCodec>);
147 
148     int computeNextFrame(int current, bool* animationEnded);
149     double finish();
150 
151     typedef SkDrawable INHERITED;
152 };
153 
154 #endif // SkAnimatedImage_DEFINED
155