1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkInterpolator_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkInterpolator_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalar.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkInterpolatorBase : SkNoncopyable {
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum Result {
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kNormal_Result,
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kFreezeStart_Result,
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kFreezeEnd_Result
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkInterpolatorBase();
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkInterpolatorBase();
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    reset(int elemCount, int frameCount);
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the start and end time for this interpolator.
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If there are no key frames, return false.
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param startTime If not null, returns the time (in milliseconds) of the
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                         first keyframe. If there are no keyframes, this param
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                         is ignored (left unchanged).
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param endTime If not null, returns the time (in milliseconds) of the
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       last keyframe. If there are no keyframes, this parameter
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       is ignored (left unchanged).
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return True if there are key frames, or false if there are none.
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    getDuration(SkMSec* startTime, SkMSec* endTime) const;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the whether the repeat is mirrored.
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param mirror If true, the odd repeats interpolate from the last key
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                      frame and the first.
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setMirror(bool mirror) {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror);
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the repeat count. The repeat count may be fractional.
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param repeatCount Multiplies the total time by this scalar.
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; }
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the whether the repeat is mirrored.
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param reset If true, the odd repeats interpolate from the last key
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     frame and the first.
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setReset(bool reset) {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFlags = SkToU8((fFlags & ~kReset) | (int)reset);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Result  timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum Flags {
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kMirror = 1,
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kReset = 2,
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kHasBlend = 4
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime,
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SkMSec nextTime, const SkScalar blend[4] = NULL);
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int16_t fFrameCount;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t fElemCount;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t fFlags;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar fRepeat;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    struct SkTimeCode {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkMSec  fTime;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar fBlend[4];
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTimeCode* fTimes;     // pointer into fStorage
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void* fStorage;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTimeCode(* fTimesArray)[10];
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkInterpolator : public SkInterpolatorBase {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkInterpolator();
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkInterpolator(int elemCount, int frameCount);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    reset(int elemCount, int frameCount);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add or replace a key frame, copying the values[] data into the
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        interpolator.
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param index    The index of this frame (frames must be ordered by time)
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param time The millisecond time for this frame
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param values   The array of values [elemCount] for this frame. The data
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        is copied into the interpolator.
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param blend    A positive scalar specifying how to blend between this
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        and the next key frame. [0...1) is a cubic lag/log/lag
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        blend (slow to change at the beginning and end)
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        1 is a linear blend (default)
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool setKeyFrame(int index, SkMSec time, const SkScalar values[],
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     const SkScalar blend[4] = NULL);
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the computed values given the specified time. Return whether
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        those values are the result of pinning to either the first
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (kFreezeStart) or last (kFreezeEnd), or from interpolated the two
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        nearest key values (kNormal).
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param time The time to sample (in milliseconds)
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param (may be null) where to write the computed values.
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Result timeToValues(SkMSec time, SkScalar values[] = NULL) const;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar* fValues;  // pointer into fStorage
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar(* fScalarsArray)[10];
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkInterpolatorBase INHERITED;
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Given all the parameters are [0...1], apply the cubic specified by (0,0)
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1].
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkScalar cx, SkScalar cy);
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
131