| /* | 
 |  * Copyright (C) 2006 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef SkiaInterpolator_DEFINED | 
 | #define SkiaInterpolator_DEFINED | 
 |  | 
 | #include <cstddef> | 
 | #include <cstdint> | 
 |  | 
 | class SkiaInterpolatorBase { | 
 | public: | 
 |     enum Result { kNormal_Result, kFreezeStart_Result, kFreezeEnd_Result }; | 
 |  | 
 | protected: | 
 |     SkiaInterpolatorBase(); | 
 |     ~SkiaInterpolatorBase(); | 
 |  | 
 | public: | 
 |     void reset(int elemCount, int frameCount); | 
 |  | 
 |     /** Return the start and end time for this interpolator. | 
 |         If there are no key frames, return false. | 
 |         @param startTime If not null, returns the time (in milliseconds) of the | 
 |                          first keyframe. If there are no keyframes, this param | 
 |                          is ignored (left unchanged). | 
 |         @param endTime If not null, returns the time (in milliseconds) of the | 
 |                        last keyframe. If there are no keyframes, this parameter | 
 |                        is ignored (left unchanged). | 
 |         @return True if there are key frames, or false if there are none. | 
 |     */ | 
 |     bool getDuration(uint32_t* startTime, uint32_t* endTime) const; | 
 |  | 
 |     /** Set the whether the repeat is mirrored. | 
 |         @param mirror If true, the odd repeats interpolate from the last key | 
 |                       frame and the first. | 
 |     */ | 
 |     void setMirror(bool mirror) { | 
 |         fFlags = static_cast<uint8_t>((fFlags & ~kMirror) | (int)mirror); | 
 |     } | 
 |  | 
 |     /** Set the repeat count. The repeat count may be fractional. | 
 |         @param repeatCount Multiplies the total time by this scalar. | 
 |     */ | 
 |     void setRepeatCount(float repeatCount) { fRepeat = repeatCount; } | 
 |  | 
 |     /** Set the whether the repeat is mirrored. | 
 |         @param reset If true, the odd repeats interpolate from the last key | 
 |                      frame and the first. | 
 |     */ | 
 |     void setReset(bool reset) { fFlags = static_cast<uint8_t>((fFlags & ~kReset) | (int)reset); } | 
 |  | 
 |     Result timeToT(uint32_t time, float* T, int* index, bool* exact) const; | 
 |  | 
 | protected: | 
 |     enum Flags { kMirror = 1, kReset = 2, kHasBlend = 4 }; | 
 |     static float ComputeRelativeT(uint32_t time, uint32_t prevTime, uint32_t nextTime, | 
 |                                   const float blend[4] = nullptr); | 
 |     int16_t fFrameCount; | 
 |     uint8_t fElemCount; | 
 |     uint8_t fFlags; | 
 |     float fRepeat; | 
 |     struct SkTimeCode { | 
 |         uint32_t fTime; | 
 |         float fBlend[4]; | 
 |     }; | 
 |     SkTimeCode* fTimes;  // pointer into fStorage | 
 |     void* fStorage; | 
 | }; | 
 |  | 
 | class SkiaInterpolator : public SkiaInterpolatorBase { | 
 | public: | 
 |     SkiaInterpolator(); | 
 |     SkiaInterpolator(int elemCount, int frameCount); | 
 |  | 
 |     void reset(int elemCount, int frameCount); | 
 |  | 
 |     /** Add or replace a key frame, copying the values[] data into the | 
 |         interpolator. | 
 |         @param index    The index of this frame (frames must be ordered by time) | 
 |         @param time The millisecond time for this frame | 
 |         @param values   The array of values [elemCount] for this frame. The data | 
 |                         is copied into the interpolator. | 
 |         @param blend    A positive scalar specifying how to blend between this | 
 |                         and the next key frame. [0...1) is a cubic lag/log/lag | 
 |                         blend (slow to change at the beginning and end) | 
 |                         1 is a linear blend (default) | 
 |     */ | 
 |     bool setKeyFrame(int index, uint32_t time, const float values[], | 
 |                      const float blend[4] = nullptr); | 
 |  | 
 |     /** Return the computed values given the specified time. Return whether | 
 |         those values are the result of pinning to either the first | 
 |         (kFreezeStart) or last (kFreezeEnd), or from interpolated the two | 
 |         nearest key values (kNormal). | 
 |         @param time The time to sample (in milliseconds) | 
 |         @param (may be null) where to write the computed values. | 
 |     */ | 
 |     Result timeToValues(uint32_t time, float values[] = nullptr) const; | 
 |  | 
 | private: | 
 |     float* fValues;  // pointer into fStorage | 
 |  | 
 |     using INHERITED = SkiaInterpolatorBase; | 
 | }; | 
 |  | 
 | #endif |