blob: 18203d05d062de985040474fed92e5bf066e8033 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkInterpolator_DEFINED
11#define SkInterpolator_DEFINED
12
13#include "SkScalar.h"
14
15class SkInterpolatorBase : SkNoncopyable {
16public:
17 enum Result {
18 kNormal_Result,
19 kFreezeStart_Result,
20 kFreezeEnd_Result
21 };
22protected:
23 SkInterpolatorBase();
24 ~SkInterpolatorBase();
25public:
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
64protected:
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
87class SkInterpolator : public SkInterpolatorBase {
88public:
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
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116private:
117 SkScalar* fValues; // pointer into fStorage
118#ifdef SK_DEBUG
119 SkScalar(* fScalarsArray)[10];
120#endif
121 typedef SkInterpolatorBase INHERITED;
122};
123
124/** Given all the parameters are [0...1], apply the cubic specified by (0,0)
125 (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1].
126*/
127SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,
128 SkScalar cx, SkScalar cy);
129
130#endif