1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9 #ifndef SkInterpolator_DEFINED 10 #define SkInterpolator_DEFINED 11 12 #include "include/core/SkScalar.h" 13 #include "include/private/SkNoncopyable.h" 14 #include "include/private/SkTo.h" 15 16 class SK_API SkInterpolatorBase : SkNoncopyable { 17 public: 18 enum Result { 19 kNormal_Result, 20 kFreezeStart_Result, 21 kFreezeEnd_Result 22 }; 23 protected: 24 SkInterpolatorBase(); 25 ~SkInterpolatorBase(); 26 public: 27 void reset(int elemCount, int frameCount); 28 29 /** Return the start and end time for this interpolator. 30 If there are no key frames, return false. 31 @param startTime If not null, returns the time (in milliseconds) of the 32 first keyframe. If there are no keyframes, this param 33 is ignored (left unchanged). 34 @param endTime If not null, returns the time (in milliseconds) of the 35 last keyframe. If there are no keyframes, this parameter 36 is ignored (left unchanged). 37 @return True if there are key frames, or false if there are none. 38 */ 39 bool getDuration(SkMSec* startTime, SkMSec* endTime) const; 40 41 42 /** Set the whether the repeat is mirrored. 43 @param mirror If true, the odd repeats interpolate from the last key 44 frame and the first. 45 */ setMirror(bool mirror)46 void setMirror(bool mirror) { 47 fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror); 48 } 49 50 /** Set the repeat count. The repeat count may be fractional. 51 @param repeatCount Multiplies the total time by this scalar. 52 */ setRepeatCount(SkScalar repeatCount)53 void setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; } 54 55 /** Set the whether the repeat is mirrored. 56 @param reset If true, the odd repeats interpolate from the last key 57 frame and the first. 58 */ setReset(bool reset)59 void setReset(bool reset) { 60 fFlags = SkToU8((fFlags & ~kReset) | (int)reset); 61 } 62 63 Result timeToT(SkMSec time, SkScalar* T, int* index, bool* exact) const; 64 65 protected: 66 enum Flags { 67 kMirror = 1, 68 kReset = 2, 69 kHasBlend = 4 70 }; 71 static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime, 72 const SkScalar blend[4] = nullptr); 73 int16_t fFrameCount; 74 uint8_t fElemCount; 75 uint8_t fFlags; 76 SkScalar fRepeat; 77 struct SkTimeCode { 78 SkMSec fTime; 79 SkScalar fBlend[4]; 80 }; 81 SkTimeCode* fTimes; // pointer into fStorage 82 void* fStorage; 83 #ifdef SK_DEBUG 84 SkTimeCode(* fTimesArray)[10]; 85 #endif 86 }; 87 88 class SK_API SkInterpolator : public SkInterpolatorBase { 89 public: 90 SkInterpolator(); 91 SkInterpolator(int elemCount, int frameCount); 92 void reset(int elemCount, int frameCount); 93 94 /** Add or replace a key frame, copying the values[] data into the 95 interpolator. 96 @param index The index of this frame (frames must be ordered by time) 97 @param time The millisecond time for this frame 98 @param values The array of values [elemCount] for this frame. The data 99 is copied into the interpolator. 100 @param blend A positive scalar specifying how to blend between this 101 and the next key frame. [0...1) is a cubic lag/log/lag 102 blend (slow to change at the beginning and end) 103 1 is a linear blend (default) 104 */ 105 bool setKeyFrame(int index, SkMSec time, const SkScalar values[], 106 const SkScalar blend[4] = nullptr); 107 108 /** Return the computed values given the specified time. Return whether 109 those values are the result of pinning to either the first 110 (kFreezeStart) or last (kFreezeEnd), or from interpolated the two 111 nearest key values (kNormal). 112 @param time The time to sample (in milliseconds) 113 @param (may be null) where to write the computed values. 114 */ 115 Result timeToValues(SkMSec time, SkScalar values[] = nullptr) const; 116 117 private: 118 SkScalar* fValues; // pointer into fStorage 119 #ifdef SK_DEBUG 120 SkScalar(* fScalarsArray)[10]; 121 #endif 122 typedef SkInterpolatorBase INHERITED; 123 }; 124 125 /** Interpolate a cubic curve, typically to provide an ease-in ease-out transition. 126 All the parameters are in the range of [0...1]. 127 The input value is treated as the x-coordinate of the cubic. 128 The output value is the y-coordinate on the cubic at the x-coordinate. 129 130 @param value The x-coordinate pinned between [0..1]. 131 @param bx,by,cx,cy The cubic control points where the cubic is specified 132 as (0,0) (bx,by) (cx,cy) (1,1) 133 @return the corresponding y-coordinate value, from [0..1]. 134 */ 135 SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by, 136 SkScalar cx, SkScalar cy); 137 138 #endif 139