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