xref: /aosp_15_r20/frameworks/base/libs/hwui/SkiaInterpolator.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2006 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #ifndef SkiaInterpolator_DEFINED
18*d57664e9SAndroid Build Coastguard Worker #define SkiaInterpolator_DEFINED
19*d57664e9SAndroid Build Coastguard Worker 
20*d57664e9SAndroid Build Coastguard Worker #include <cstddef>
21*d57664e9SAndroid Build Coastguard Worker #include <cstdint>
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker class SkiaInterpolatorBase {
24*d57664e9SAndroid Build Coastguard Worker public:
25*d57664e9SAndroid Build Coastguard Worker     enum Result { kNormal_Result, kFreezeStart_Result, kFreezeEnd_Result };
26*d57664e9SAndroid Build Coastguard Worker 
27*d57664e9SAndroid Build Coastguard Worker protected:
28*d57664e9SAndroid Build Coastguard Worker     SkiaInterpolatorBase();
29*d57664e9SAndroid Build Coastguard Worker     ~SkiaInterpolatorBase();
30*d57664e9SAndroid Build Coastguard Worker 
31*d57664e9SAndroid Build Coastguard Worker public:
32*d57664e9SAndroid Build Coastguard Worker     void reset(int elemCount, int frameCount);
33*d57664e9SAndroid Build Coastguard Worker 
34*d57664e9SAndroid Build Coastguard Worker     /** Return the start and end time for this interpolator.
35*d57664e9SAndroid Build Coastguard Worker         If there are no key frames, return false.
36*d57664e9SAndroid Build Coastguard Worker         @param startTime If not null, returns the time (in milliseconds) of the
37*d57664e9SAndroid Build Coastguard Worker                          first keyframe. If there are no keyframes, this param
38*d57664e9SAndroid Build Coastguard Worker                          is ignored (left unchanged).
39*d57664e9SAndroid Build Coastguard Worker         @param endTime If not null, returns the time (in milliseconds) of the
40*d57664e9SAndroid Build Coastguard Worker                        last keyframe. If there are no keyframes, this parameter
41*d57664e9SAndroid Build Coastguard Worker                        is ignored (left unchanged).
42*d57664e9SAndroid Build Coastguard Worker         @return True if there are key frames, or false if there are none.
43*d57664e9SAndroid Build Coastguard Worker     */
44*d57664e9SAndroid Build Coastguard Worker     bool getDuration(uint32_t* startTime, uint32_t* endTime) const;
45*d57664e9SAndroid Build Coastguard Worker 
46*d57664e9SAndroid Build Coastguard Worker     /** Set the whether the repeat is mirrored.
47*d57664e9SAndroid Build Coastguard Worker         @param mirror If true, the odd repeats interpolate from the last key
48*d57664e9SAndroid Build Coastguard Worker                       frame and the first.
49*d57664e9SAndroid Build Coastguard Worker     */
setMirror(bool mirror)50*d57664e9SAndroid Build Coastguard Worker     void setMirror(bool mirror) {
51*d57664e9SAndroid Build Coastguard Worker         fFlags = static_cast<uint8_t>((fFlags & ~kMirror) | (int)mirror);
52*d57664e9SAndroid Build Coastguard Worker     }
53*d57664e9SAndroid Build Coastguard Worker 
54*d57664e9SAndroid Build Coastguard Worker     /** Set the repeat count. The repeat count may be fractional.
55*d57664e9SAndroid Build Coastguard Worker         @param repeatCount Multiplies the total time by this scalar.
56*d57664e9SAndroid Build Coastguard Worker     */
setRepeatCount(float repeatCount)57*d57664e9SAndroid Build Coastguard Worker     void setRepeatCount(float repeatCount) { fRepeat = repeatCount; }
58*d57664e9SAndroid Build Coastguard Worker 
59*d57664e9SAndroid Build Coastguard Worker     /** Set the whether the repeat is mirrored.
60*d57664e9SAndroid Build Coastguard Worker         @param reset If true, the odd repeats interpolate from the last key
61*d57664e9SAndroid Build Coastguard Worker                      frame and the first.
62*d57664e9SAndroid Build Coastguard Worker     */
setReset(bool reset)63*d57664e9SAndroid Build Coastguard Worker     void setReset(bool reset) { fFlags = static_cast<uint8_t>((fFlags & ~kReset) | (int)reset); }
64*d57664e9SAndroid Build Coastguard Worker 
65*d57664e9SAndroid Build Coastguard Worker     Result timeToT(uint32_t time, float* T, int* index, bool* exact) const;
66*d57664e9SAndroid Build Coastguard Worker 
67*d57664e9SAndroid Build Coastguard Worker protected:
68*d57664e9SAndroid Build Coastguard Worker     enum Flags { kMirror = 1, kReset = 2, kHasBlend = 4 };
69*d57664e9SAndroid Build Coastguard Worker     static float ComputeRelativeT(uint32_t time, uint32_t prevTime, uint32_t nextTime,
70*d57664e9SAndroid Build Coastguard Worker                                   const float blend[4] = nullptr);
71*d57664e9SAndroid Build Coastguard Worker     struct SkTimeCode {
72*d57664e9SAndroid Build Coastguard Worker         uint32_t fTime;
73*d57664e9SAndroid Build Coastguard Worker         float fBlend[4];
74*d57664e9SAndroid Build Coastguard Worker     };
75*d57664e9SAndroid Build Coastguard Worker     static int binarySearch(const SkTimeCode* arr, int count, uint32_t target);
76*d57664e9SAndroid Build Coastguard Worker 
77*d57664e9SAndroid Build Coastguard Worker     int16_t fFrameCount;
78*d57664e9SAndroid Build Coastguard Worker     uint8_t fElemCount;
79*d57664e9SAndroid Build Coastguard Worker     uint8_t fFlags;
80*d57664e9SAndroid Build Coastguard Worker     float fRepeat;
81*d57664e9SAndroid Build Coastguard Worker     SkTimeCode* fTimes;  // pointer into fStorage
82*d57664e9SAndroid Build Coastguard Worker     void* fStorage;
83*d57664e9SAndroid Build Coastguard Worker };
84*d57664e9SAndroid Build Coastguard Worker 
85*d57664e9SAndroid Build Coastguard Worker class SkiaInterpolator : public SkiaInterpolatorBase {
86*d57664e9SAndroid Build Coastguard Worker public:
87*d57664e9SAndroid Build Coastguard Worker     SkiaInterpolator();
88*d57664e9SAndroid Build Coastguard Worker     SkiaInterpolator(int elemCount, int frameCount);
89*d57664e9SAndroid Build Coastguard Worker 
90*d57664e9SAndroid Build Coastguard Worker     void reset(int elemCount, int frameCount);
91*d57664e9SAndroid Build Coastguard Worker 
92*d57664e9SAndroid Build Coastguard Worker     /** Add or replace a key frame, copying the values[] data into the
93*d57664e9SAndroid Build Coastguard Worker         interpolator.
94*d57664e9SAndroid Build Coastguard Worker         @param index    The index of this frame (frames must be ordered by time)
95*d57664e9SAndroid Build Coastguard Worker         @param time The millisecond time for this frame
96*d57664e9SAndroid Build Coastguard Worker         @param values   The array of values [elemCount] for this frame. The data
97*d57664e9SAndroid Build Coastguard Worker                         is copied into the interpolator.
98*d57664e9SAndroid Build Coastguard Worker         @param blend    A positive scalar specifying how to blend between this
99*d57664e9SAndroid Build Coastguard Worker                         and the next key frame. [0...1) is a cubic lag/log/lag
100*d57664e9SAndroid Build Coastguard Worker                         blend (slow to change at the beginning and end)
101*d57664e9SAndroid Build Coastguard Worker                         1 is a linear blend (default)
102*d57664e9SAndroid Build Coastguard Worker     */
103*d57664e9SAndroid Build Coastguard Worker     bool setKeyFrame(int index, uint32_t time, const float values[],
104*d57664e9SAndroid Build Coastguard Worker                      const float blend[4] = nullptr);
105*d57664e9SAndroid Build Coastguard Worker 
106*d57664e9SAndroid Build Coastguard Worker     /** Return the computed values given the specified time. Return whether
107*d57664e9SAndroid Build Coastguard Worker         those values are the result of pinning to either the first
108*d57664e9SAndroid Build Coastguard Worker         (kFreezeStart) or last (kFreezeEnd), or from interpolated the two
109*d57664e9SAndroid Build Coastguard Worker         nearest key values (kNormal).
110*d57664e9SAndroid Build Coastguard Worker         @param time The time to sample (in milliseconds)
111*d57664e9SAndroid Build Coastguard Worker         @param (may be null) where to write the computed values.
112*d57664e9SAndroid Build Coastguard Worker     */
113*d57664e9SAndroid Build Coastguard Worker     Result timeToValues(uint32_t time, float values[] = nullptr) const;
114*d57664e9SAndroid Build Coastguard Worker 
115*d57664e9SAndroid Build Coastguard Worker private:
116*d57664e9SAndroid Build Coastguard Worker     float* fValues;  // pointer into fStorage
117*d57664e9SAndroid Build Coastguard Worker 
118*d57664e9SAndroid Build Coastguard Worker     using INHERITED = SkiaInterpolatorBase;
119*d57664e9SAndroid Build Coastguard Worker };
120*d57664e9SAndroid Build Coastguard Worker 
121*d57664e9SAndroid Build Coastguard Worker #endif
122