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