11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkInterpolator_DEFINED
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkInterpolator_DEFINED
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalar.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkInterpolatorBase : SkNoncopyable {
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum Result {
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kNormal_Result,
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kFreezeStart_Result,
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kFreezeEnd_Result
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected:
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkInterpolatorBase();
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ~SkInterpolatorBase();
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void    reset(int elemCount, int frameCount);
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return the start and end time for this interpolator.
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        If there are no key frames, return false.
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param startTime If not null, returns the time (in milliseconds) of the
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         first keyframe. If there are no keyframes, this param
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         is ignored (left unchanged).
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param endTime If not null, returns the time (in milliseconds) of the
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                       last keyframe. If there are no keyframes, this parameter
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                       is ignored (left unchanged).
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @return True if there are key frames, or false if there are none.
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    getDuration(SkMSec* startTime, SkMSec* endTime) const;
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Set the whether the repeat is mirrored.
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param mirror If true, the odd repeats interpolate from the last key
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                      frame and the first.
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void setMirror(bool mirror) {
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror);
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Set the repeat count. The repeat count may be fractional.
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param repeatCount Multiplies the total time by this scalar.
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void    setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; }
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Set the whether the repeat is mirrored.
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param reset If true, the odd repeats interpolate from the last key
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                     frame and the first.
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void setReset(bool reset) {
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fFlags = SkToU8((fFlags & ~kReset) | (int)reset);
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Result  timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const;
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected:
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum Flags {
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kMirror = 1,
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kReset = 2,
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kHasBlend = 4
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime,
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                             SkMSec nextTime, const SkScalar blend[4] = NULL);
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int16_t fFrameCount;
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint8_t fElemCount;
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint8_t fFlags;
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar fRepeat;
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    struct SkTimeCode {
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMSec  fTime;
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar fBlend[4];
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTimeCode* fTimes;     // pointer into fStorage
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void* fStorage;
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTimeCode(* fTimesArray)[10];
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkInterpolator : public SkInterpolatorBase {
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkInterpolator();
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkInterpolator(int elemCount, int frameCount);
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void    reset(int elemCount, int frameCount);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Add or replace a key frame, copying the values[] data into the
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        interpolator.
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param index    The index of this frame (frames must be ordered by time)
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param time The millisecond time for this frame
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param values   The array of values [elemCount] for this frame. The data
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        is copied into the interpolator.
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param blend    A positive scalar specifying how to blend between this
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        and the next key frame. [0...1) is a cubic lag/log/lag
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        blend (slow to change at the beginning and end)
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        1 is a linear blend (default)
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool setKeyFrame(int index, SkMSec time, const SkScalar values[],
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                     const SkScalar blend[4] = NULL);
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Return the computed values given the specified time. Return whether
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        those values are the result of pinning to either the first
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        (kFreezeStart) or last (kFreezeEnd), or from interpolated the two
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        nearest key values (kNormal).
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param time The time to sample (in milliseconds)
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        @param (may be null) where to write the computed values.
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Result timeToValues(SkMSec time, SkScalar values[] = NULL) const;
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(static void UnitTest();)
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar* fValues;  // pointer into fStorage
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar(* fScalarsArray)[10];
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef SkInterpolatorBase INHERITED;
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Given all the parameters are [0...1], apply the cubic specified by (0,0)
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1].
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                           SkScalar cx, SkScalar cy);
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
133