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 | */ |
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 | */ |
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 | */ |
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 | |