aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/graphics/SkInterpolator.h
blob: c224c8cd66d000f4fd313ae1d85cda582caf8475 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef SkInterpolator_DEFINED
#define SkInterpolator_DEFINED

#include "SkMath.h"

class SkInterpolatorBase {
public:
	enum Result {
		kNormal_Result,
		kFreezeStart_Result,
		kFreezeEnd_Result
	};
	static SkScalar Blend(SkScalar t, SkScalar blend);
protected:
	SkInterpolatorBase();
	~SkInterpolatorBase();
public:
	void	reset(int elemCount, int frameCount);

	/**	Return the start and end time for this interpolator.
		If there are no key frames, return false.
		@param	startTime	If no nil, returns the time (in milliseconds) of the
							first keyframe. If there are no keyframes, this parameter
							is ignored (left unchanged).
		@param	endTime		If no nil, returns the time (in milliseconds) of the
							last keyframe. If there are no keyframes, this parameter
							is ignored (left unchanged).
		@return	True if there are key frames, or false if there are none.
	*/
	bool	getDuration(SkMSec* startTime, SkMSec* endTime) const;


	/**	Set the whether the repeat is mirrored.
		@param If true, the odd repeats interpolate from the last key frame and the first.
	*/
	void	setMirror(bool mirror) { fFlags = SkToU8(fFlags & ~kMirror | (int) mirror); }

	/**	Set the repeat count. The repeat count may be fractional.
		@param repeatCount Multiplies the total time by this scalar.
	*/
	void	setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; }

	/**	Set the whether the repeat is mirrored.
		@param If true, the odd repeats interpolate from the last key frame and the first.
	*/
	void	setReset(bool reset) { fFlags = SkToU8(fFlags & ~kReset | (int) reset); }

	Result	timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const;
protected:
	enum Flags {
		kMirror = 1,
		kReset = 2
	};
	static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime, SkScalar blend);
	S16 fFrameCount;
	U8 fElemCount;
	U8 fFlags;
	SkScalar fRepeat;
	struct SkTimeCode {
		SkMSec fTime;
		SkScalar fBlend;
	};
	SkTimeCode* fTimes;		// pointer into fStorage
	void* fStorage;
#ifdef SK_DEBUG
	SkTimeCode(* fTimesArray)[10];
#endif
};

class SkInterpolator : public SkInterpolatorBase {
public:
	SkInterpolator();
	SkInterpolator(int elemCount, int frameCount);
	void	reset(int elemCount, int frameCount);

	/**	Add or replace a key frame, copying the values[] data into the interpolator.
		@param index	The index of this frame (frames must be ordered by time)
		@param time	The millisecond time for this frame
		@param values	The array of values [elemCount] for this frame. The data is copied
						into the interpolator.
		@param blend	A positive scalar specifying how to blend between this and the next key frame.
						[0...1) is a cubic lag/log/lag blend (slow to change at the beginning and end)
						1 is a linear blend (default)
	*/
	bool	setKeyFrame(int index, SkMSec time, const SkScalar values[], SkScalar blend = SK_Scalar1);
	Result timeToValues(SkMSec time, SkScalar values[]) const;
	SkDEBUGCODE(static void UnitTest();)
private:
	SkScalar* fValues; 	// pointer into fStorage
#ifdef SK_DEBUG
	SkScalar(* fScalarsArray)[10];
#endif
	typedef SkInterpolatorBase INHERITED;
};


#endif