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