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