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