• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cutils/compiler.h>
20 #include <utils/Macros.h>
21 #include <utils/RefBase.h>
22 #include <utils/Timers.h>
23 
24 #include <SkAnimatedImage.h>
25 #include <SkCanvas.h>
26 #include <SkColorFilter.h>
27 #include <SkDrawable.h>
28 #include <SkPicture.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 
53     /**
54      * This updates the internal time and returns true if the image needs
55      * to be redrawn this frame.
56      *
57      * This is called on RenderThread, while the UI thread is locked.
58      *
59      * @param outDelay Nanoseconds in the future when the following frame
60      *      will need to be drawn. 0 if not running.
61      */
62     bool isDirty(nsecs_t* outDelay);
63 
getStagingAlpha()64     int getStagingAlpha() const { return mStagingProperties.mAlpha; }
setStagingAlpha(int alpha)65     void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; }
setStagingColorFilter(sk_sp<SkColorFilter> filter)66     void setStagingColorFilter(sk_sp<SkColorFilter> filter) {
67         mStagingProperties.mColorFilter = filter;
68     }
setStagingMirrored(bool mirrored)69     void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; }
setStagingBounds(const SkRect & bounds)70     void setStagingBounds(const SkRect& bounds) { mStagingProperties.mBounds = bounds; }
71     void syncProperties();
72 
73     SkRect onGetBounds() override;
74 
75     // Draw to software canvas, and return time to next draw.
76     // 0 means the animation is not running.
77     // -1 means the animation advanced to the final frame.
78     int drawStaging(SkCanvas* canvas);
79 
80     // Returns true if the animation was started; false otherwise (e.g. it was
81     // already running)
82     bool start();
83     // Returns true if the animation was stopped; false otherwise (e.g. it was
84     // already stopped)
85     bool stop();
86     bool isRunning();
getRepetitionCount()87     int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); }
setRepetitionCount(int count)88     void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); }
89 
setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener)90     void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) {
91         mEndListener = std::move(listener);
92     }
93 
94     struct Snapshot {
95         sk_sp<SkPicture> mPic;
96         int mDurationMS;
97 
98         Snapshot() = default;
99 
100         Snapshot(Snapshot&&) = default;
101         Snapshot& operator=(Snapshot&&) = default;
102 
103         PREVENT_COPY_AND_ASSIGN(Snapshot);
104     };
105 
106     // These are only called on AnimatedImageThread.
107     Snapshot decodeNextFrame();
108     Snapshot reset();
109 
byteSize()110     size_t byteSize() const { return sizeof(*this) + mBytesUsed; }
111 
112 protected:
113     void onDraw(SkCanvas* canvas) override;
114 
115 private:
116     sk_sp<SkAnimatedImage> mSkAnimatedImage;
117     const size_t mBytesUsed;
118 
119     bool mRunning = false;
120     bool mStarting = false;
121 
122     // A snapshot of the current frame to draw.
123     Snapshot mSnapshot;
124 
125     std::future<Snapshot> mNextSnapshot;
126 
127     bool nextSnapshotReady() const;
128 
129     // When to switch from mSnapshot to mNextSnapshot.
130     nsecs_t mTimeToShowNextSnapshot = 0;
131 
132     // The current time for the drawable itself.
133     nsecs_t mCurrentTime = 0;
134 
135     // The wall clock of the last time we called isDirty.
136     nsecs_t mLastWallTime = 0;
137 
138     // Locked when assigning snapshots and times. Operations while this is held
139     // should be short.
140     std::mutex mSwapLock;
141 
142     // Locked when mSkAnimatedImage is being updated or drawn.
143     std::mutex mImageLock;
144 
145     struct Properties {
146         int mAlpha = SK_AlphaOPAQUE;
147         sk_sp<SkColorFilter> mColorFilter;
148         bool mMirrored = false;
149         SkRect mBounds;
150 
151         Properties() = default;
152         Properties(Properties&) = default;
153         Properties& operator=(Properties&) = default;
154     };
155 
156     Properties mStagingProperties;
157     Properties mProperties;
158 
159     std::unique_ptr<OnAnimationEndListener> mEndListener;
160 };
161 
162 }  // namespace android
163