1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkInterpolator_DEFINED 18 #define SkInterpolator_DEFINED 19 20 #include "SkScalar.h" 21 22 class SkInterpolatorBase : SkNoncopyable { 23 public: 24 enum Result { 25 kNormal_Result, 26 kFreezeStart_Result, 27 kFreezeEnd_Result 28 }; 29 protected: 30 SkInterpolatorBase(); 31 ~SkInterpolatorBase(); 32 public: 33 void reset(int elemCount, int frameCount); 34 35 /** Return the start and end time for this interpolator. 36 If there are no key frames, return false. 37 @param startTime If not null, returns the time (in milliseconds) of the 38 first keyframe. If there are no keyframes, this param 39 is ignored (left unchanged). 40 @param endTime If not null, returns the time (in milliseconds) of the 41 last keyframe. If there are no keyframes, this parameter 42 is ignored (left unchanged). 43 @return True if there are key frames, or false if there are none. 44 */ 45 bool getDuration(SkMSec* startTime, SkMSec* endTime) const; 46 47 48 /** Set the whether the repeat is mirrored. 49 @param mirror If true, the odd repeats interpolate from the last key 50 frame and the first. 51 */ 52 void setMirror(bool mirror) { 53 fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror); 54 } 55 56 /** Set the repeat count. The repeat count may be fractional. 57 @param repeatCount Multiplies the total time by this scalar. 58 */ 59 void setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; } 60 61 /** Set the whether the repeat is mirrored. 62 @param reset If true, the odd repeats interpolate from the last key 63 frame and the first. 64 */ 65 void setReset(bool reset) { 66 fFlags = SkToU8((fFlags & ~kReset) | (int)reset); 67 } 68 69 Result timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const; 70 71 protected: 72 enum Flags { 73 kMirror = 1, 74 kReset = 2, 75 kHasBlend = 4 76 }; 77 static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime, 78 SkMSec nextTime, const SkScalar blend[4] = NULL); 79 int16_t fFrameCount; 80 uint8_t fElemCount; 81 uint8_t fFlags; 82 SkScalar fRepeat; 83 struct SkTimeCode { 84 SkMSec fTime; 85 SkScalar fBlend[4]; 86 }; 87 SkTimeCode* fTimes; // pointer into fStorage 88 void* fStorage; 89 #ifdef SK_DEBUG 90 SkTimeCode(* fTimesArray)[10]; 91 #endif 92 }; 93 94 class SkInterpolator : public SkInterpolatorBase { 95 public: 96 SkInterpolator(); 97 SkInterpolator(int elemCount, int frameCount); 98 void reset(int elemCount, int frameCount); 99 100 /** Add or replace a key frame, copying the values[] data into the 101 interpolator. 102 @param index The index of this frame (frames must be ordered by time) 103 @param time The millisecond time for this frame 104 @param values The array of values [elemCount] for this frame. The data 105 is copied into the interpolator. 106 @param blend A positive scalar specifying how to blend between this 107 and the next key frame. [0...1) is a cubic lag/log/lag 108 blend (slow to change at the beginning and end) 109 1 is a linear blend (default) 110 */ 111 bool setKeyFrame(int index, SkMSec time, const SkScalar values[], 112 const SkScalar blend[4] = NULL); 113 114 /** Return the computed values given the specified time. Return whether 115 those values are the result of pinning to either the first 116 (kFreezeStart) or last (kFreezeEnd), or from interpolated the two 117 nearest key values (kNormal). 118 @param time The time to sample (in milliseconds) 119 @param (may be null) where to write the computed values. 120 */ 121 Result timeToValues(SkMSec time, SkScalar values[] = NULL) const; 122 123 SkDEBUGCODE(static void UnitTest();) 124 private: 125 SkScalar* fValues; // pointer into fStorage 126 #ifdef SK_DEBUG 127 SkScalar(* fScalarsArray)[10]; 128 #endif 129 typedef SkInterpolatorBase INHERITED; 130 }; 131 132 /** Given all the parameters are [0...1], apply the cubic specified by (0,0) 133 (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1]. 134 */ 135 SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by, 136 SkScalar cx, SkScalar cy); 137 138 #endif 139 140