hwui's own impl for interpolator

Bug: 184822190
Test: make
Change-Id: Ib041ad8207417ea5dfa09b50412234e5cf7daf80
diff --git a/libs/hwui/SkiaInterpolator.h b/libs/hwui/SkiaInterpolator.h
new file mode 100644
index 0000000..c03f502
--- /dev/null
+++ b/libs/hwui/SkiaInterpolator.h
@@ -0,0 +1,119 @@
+/*
+ * 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 "include/private/SkTo.h"
+
+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 = SkToU8((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 = SkToU8((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;
+#ifdef SK_DEBUG
+    SkTimeCode (*fTimesArray)[10];
+#endif
+};
+
+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