1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <SkAnimatedImage.h> 20 #include <SkCanvas.h> 21 #include <SkColorFilter.h> 22 #include <SkDrawable.h> 23 #include <SkEncodedImageFormat.h> 24 #include <SkPicture.h> 25 #include <cutils/compiler.h> 26 #include <utils/Macros.h> 27 #include <utils/RefBase.h> 28 #include <utils/Timers.h> 29 30 #include <future> 31 #include <mutex> 32 33 namespace android { 34 35 class OnAnimationEndListener { 36 public: ~OnAnimationEndListener()37 virtual ~OnAnimationEndListener() {} 38 39 virtual void onAnimationEnd() = 0; 40 }; 41 42 /** 43 * Native component of android.graphics.drawable.AnimatedImageDrawables.java. 44 * This class can be drawn into Canvas.h and maintains the state needed to drive 45 * the animation from the RenderThread. 46 */ 47 class AnimatedImageDrawable : public SkDrawable { 48 public: 49 // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the 50 // Snapshots. 51 AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed, 52 SkEncodedImageFormat format); 53 54 /** 55 * This updates the internal time and returns true if the image needs 56 * to be redrawn this frame. 57 * 58 * This is called on RenderThread, while the UI thread is locked. 59 * 60 * @param outDelay Nanoseconds in the future when the following frame 61 * will need to be drawn. 0 if not running. 62 */ 63 bool isDirty(nsecs_t* outDelay); 64 getStagingAlpha()65 int getStagingAlpha() const { return mStagingProperties.mAlpha; } setStagingAlpha(int alpha)66 void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; } setStagingColorFilter(sk_sp<SkColorFilter> filter)67 void setStagingColorFilter(sk_sp<SkColorFilter> filter) { 68 mStagingProperties.mColorFilter = filter; 69 } setStagingMirrored(bool mirrored)70 void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; } setStagingBounds(const SkRect & bounds)71 void setStagingBounds(const SkRect& bounds) { mStagingProperties.mBounds = bounds; } 72 void syncProperties(); 73 74 SkRect onGetBounds() override; 75 76 // Draw to software canvas, and return time to next draw. 77 // 0 means the animation is not running. 78 // -1 means the animation advanced to the final frame. 79 int drawStaging(SkCanvas* canvas); 80 81 // Returns true if the animation was started; false otherwise (e.g. it was 82 // already running) 83 bool start(); 84 // Returns true if the animation was stopped; false otherwise (e.g. it was 85 // already stopped) 86 bool stop(); 87 bool isRunning(); getRepetitionCount()88 int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); } setRepetitionCount(int count)89 void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); } 90 setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener)91 void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) { 92 mEndListener = std::move(listener); 93 } 94 95 struct Snapshot { 96 sk_sp<SkPicture> mPic; 97 int mDurationMS; 98 99 Snapshot() = default; 100 101 Snapshot(Snapshot&&) = default; 102 Snapshot& operator=(Snapshot&&) = default; 103 104 PREVENT_COPY_AND_ASSIGN(Snapshot); 105 }; 106 107 // These are only called on AnimatedImageThread. 108 Snapshot decodeNextFrame(); 109 Snapshot reset(); 110 byteSize()111 size_t byteSize() const { return sizeof(*this) + mBytesUsed; } 112 113 protected: 114 void onDraw(SkCanvas* canvas) override; 115 116 private: 117 sk_sp<SkAnimatedImage> mSkAnimatedImage; 118 const size_t mBytesUsed; 119 const SkEncodedImageFormat mFormat; 120 121 bool mRunning = false; 122 bool mStarting = false; 123 124 // A snapshot of the current frame to draw. 125 Snapshot mSnapshot; 126 127 std::future<Snapshot> mNextSnapshot; 128 129 bool nextSnapshotReady() const; 130 131 // When to switch from mSnapshot to mNextSnapshot. 132 nsecs_t mTimeToShowNextSnapshot = 0; 133 134 // The current time for the drawable itself. 135 nsecs_t mCurrentTime = 0; 136 137 // The wall clock of the last time we called isDirty. 138 nsecs_t mLastWallTime = 0; 139 140 // Locked when assigning snapshots and times. Operations while this is held 141 // should be short. 142 std::mutex mSwapLock; 143 144 // Locked when mSkAnimatedImage is being updated or drawn. 145 std::mutex mImageLock; 146 147 struct Properties { 148 int mAlpha = SK_AlphaOPAQUE; 149 sk_sp<SkColorFilter> mColorFilter; 150 bool mMirrored = false; 151 SkRect mBounds; 152 153 Properties() = default; 154 Properties(Properties&) = default; 155 Properties& operator=(Properties&) = default; 156 }; 157 158 Properties mStagingProperties; 159 Properties mProperties; 160 161 std::unique_ptr<OnAnimationEndListener> mEndListener; 162 163 int adjustFrameDuration(int); 164 int currentFrameDuration(); 165 }; 166 167 } // namespace android 168