fix crashes reported by Debian Cylab Mayhem Team
[swftools.git] / src / swfc-interpolation.c
blobf543bd2e8ec1df686b052e596d9a1212539bddd4
1 /* swfc- Compiles swf code (.sc) files into .swf files.
3 Part of the swftools package.
5 Copyright (c) 2007 Huub Schaeks <huub@h-schaeks.speedlinq.nl>
6 Copyright (c) 2007 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 #include <stdlib.h>
23 #include <math.h>
24 #include <memory.h>
25 #include "swfc-interpolation.h"
27 static inline float poly(float fraction, float start, float delta, float slope, int degree)
29 return delta * ((1 - slope) * pow(fraction, degree) + slope * fraction) + start;
32 float linear(float fraction, float start, float delta)
34 return poly(fraction, start, delta, 0, 1);
37 float quadIn(float fraction, float start, float delta, float slope)
39 return poly(fraction, start, delta, slope, 2);
42 float quadOut(float fraction, float start, float delta, float slope)
44 return quadIn(1 - fraction, start + delta, -delta, slope);
47 float quadInOut(float fraction, float start, float delta, float slope)
49 if (fraction < 0.5)
50 return quadIn(2 * fraction, start, delta / 2, slope);
51 return quadOut(2 * fraction - 1, start + delta / 2, delta / 2, slope);
54 float cubicIn(float fraction, float start, float delta, float slope)
56 return poly(fraction, start, delta, slope, 3);
59 float cubicOut(float fraction, float start, float delta, float slope)
61 return cubicIn(1 - fraction, start + delta, -delta, slope);
64 float cubicInOut(float fraction, float start, float delta, float slope)
66 if (fraction < 0.5)
67 return cubicIn(2 * fraction, start, delta / 2, slope);
68 return cubicOut(2 * fraction - 1, start + delta / 2, delta / 2, slope);
71 float quartIn(float fraction, float start, float delta, float slope)
73 return poly(fraction, start, delta, slope, 4);
76 float quartOut(float fraction, float start, float delta, float slope)
78 return quartIn(1 - fraction, start + delta, -delta, slope);
81 float quartInOut(float fraction, float start, float delta, float slope)
83 if (fraction < 0.5)
84 return quartIn(2 * fraction, start, delta / 2, slope);
85 return quartOut(2 * fraction - 1, start + delta / 2, delta / 2, slope);
88 float quintIn(float fraction, float start, float delta, float slope)
90 return poly(fraction, start, delta, slope, 5);
93 float quintOut(float fraction, float start, float delta, float slope)
95 return quintIn(1 - fraction, start + delta, -delta, slope);
98 float quintInOut(float fraction, float start, float delta, float slope)
100 if (fraction < 0.5)
101 return quintIn(2 * fraction, start, delta / 2, slope);
102 return quintOut(2 * fraction - 1, start + delta / 2, delta / 2, slope);
105 float circleIn(float fraction, float start, float delta, float slope)
107 return delta * (1 - sqrt(1 - (1 - 2 * slope) * fraction * fraction - 2 * slope * fraction)) + start;
110 float circleOut(float fraction, float start, float delta, float slope)
112 return circleIn(1 - fraction, start + delta, -delta, slope);
115 float circleInOut(float fraction, float start, float delta, float slope)
117 if (fraction < 0.5)
118 return circleIn(2 * fraction, start, delta / 2, slope);
119 return circleOut(2 * fraction - 1, start + delta / 2, delta / 2, slope);
122 float exponentialIn(float fraction, float start, float delta)
124 if (fraction == 0)
125 return start;
126 return delta * pow(2, 10 * (fraction - 1)) + start;
129 float exponentialOut(float fraction, float start, float delta)
131 return exponentialIn(1 - fraction, start + delta, -delta);
134 float exponentialInOut(float fraction, float start, float delta)
136 if (fraction < 0.5)
137 return exponentialIn(2 * fraction, start, delta / 2);
138 return exponentialOut(2 * fraction - 1, start + delta / 2, delta / 2);
141 float sineIn(float fraction, float start, float delta)
143 return delta * (1 - cos(fraction * M_PI/2)) + start;
146 float sineOut(float fraction, float start, float delta)
148 return sineIn(1 - fraction, start + delta, -delta);
151 float sineInOut(float fraction, float start, float delta)
153 if (fraction < 0.5)
154 return sineIn(2 * fraction, start, delta / 2);
155 return sineOut(2 * fraction - 1, start + delta / 2, delta / 2);
158 float elasticIn(float fraction, float start, float delta, float amplitude, int bounces, float damping)
160 if (fraction == 0 || delta == 0)
161 return start;
162 if (fraction == 1)
163 return start + delta;
164 if (amplitude < fabs(delta))
165 amplitude = delta;
166 float period = 1 / (bounces + 0.25);
167 return amplitude * pow(2, damping * (fraction - 1)) * sin(fraction * (2 * M_PI) / period) + start;
170 float elasticOut(float fraction, float start, float delta, float amplitude, int bounces, float damping)
172 return elasticIn(1 - fraction, start + delta, -delta, amplitude, bounces, damping);
175 float elasticInOut(float fraction, float start, float delta, float amplitude, int bounces, float damping)
177 if (fraction < 0.5)
178 return elasticIn(2 * fraction, start, delta / 2, amplitude, bounces, damping);
179 return elasticOut(2 * fraction - 1, start + delta / 2, delta / 2, amplitude, bounces, damping);
182 float backIn(float fraction, float start, float delta, float speed)
184 return delta * fraction * fraction * ((speed + 1) * fraction - speed) + start;
187 float backOut(float fraction, float start, float delta, float speed)
189 return backIn(1 - fraction, start + delta, -delta, speed);
192 float backInOut(float fraction, float start, float delta, float speed)
194 if (fraction < 0.5)
195 return backIn(2 * fraction, start, delta / 2, speed);
196 return backOut(2 * fraction - 1, start + delta / 2, delta / 2, speed);
199 /* when applied to movement bounceIn the object 'hits the floor' bounces times
200 * (after leaving the floor first) before gently reaching the final position at the top of the final bounce
201 * Each bounce takes growth times a long as the previous, except for the last one which lasts only half
202 * that time. The heights of the intermediate bounces are determined by the damping parameter.
203 * Set damping to 0 for an undamped movement.*/
205 float bounceIn(float fraction, float start, float delta, int bounces, float growth, float damping)
207 if (fraction == 0 || delta == 0)
208 return start;
209 if (fraction == 1)
210 return start + delta;
211 float w0;
212 if (growth == 1.0)
213 w0 = 1 / (bounces + 0.5);
214 else
216 float gN = pow(growth, bounces);
217 w0 = 1 / ((gN - 1) / (growth - 1) + gN / 2 );
219 float bounceStart = 0;
220 int i;
221 float w = w0;
222 for (i = 0; i <= bounces; i++)
224 float bounceEnd = bounceStart + w;
225 if (fraction >= bounceStart && fraction < bounceEnd)
227 float half = (bounceEnd + bounceStart) / 2;
228 float top = delta / pow(2, damping * ((bounces - i)));
229 fraction -= half;
230 fraction /= (w / 2);
231 return (1 - fraction * fraction) * top + start;
233 bounceStart = bounceEnd;
234 w = w * growth;
236 return w;
239 /* bounceOut is a time-reversed bounceIn; therefore each bounce takes 1/growth times as long as
240 * the previous, which I think fits the idea when applied to movement */
242 float bounceOut(float fraction, float start, float delta, int bounces, float growth, float damping)
244 return bounceIn(1 - fraction, start + delta, -delta, bounces, growth, damping);
247 /* since bounceIn and bounceOut are combined, if growth > 1 then the bounce-times will increase in
248 * the first half and decrease in the second half */
250 float bounceInOut(float fraction, float start, float delta, int bounces, float growth, float damping)
252 if (fraction < 0.5)
253 return bounceIn(2 * fraction, start, delta / 2, bounces, growth, damping);
254 return bounceOut(2 * fraction - 1, start + delta / 2, delta / 2, bounces, growth, damping);
256 /* fastBounce(In/Out) doesn't end or start in a horizontal slope (= gentle end or start) as
257 * bounce(In/Out) do which means fastBounceInOut doesn't have the 'delay' in the middle */
258 float fastBounceIn(float fraction, float start, float delta, int bounces, float growth, float damping)
260 if (fraction == 0 || delta == 0)
261 return start;
262 if (fraction == 1)
263 return start + delta;
264 float w0;
265 if (growth == 1.0)
266 w0 = 1 / (bounces + 0.25); /* in general (bounces + 1 / (2 * f)) */
267 else
269 float gN = pow(growth, bounces);
270 w0 = 1 / ((gN - 1) / (growth - 1) + gN / 4 /* in general: gN / (2 * f) */ );
272 float bounceStart = 0;
273 int i;
274 float w = w0;
275 for (i = 0; i <= bounces; i++)
277 float bounceEnd = bounceStart + w;
278 if (fraction >= bounceStart && fraction < bounceEnd)
280 float half = (bounceEnd + bounceStart) / 2;
281 float top = delta / 0.75/* in general: (1 - (1 / f) * (1 / f)) */ / pow(2, damping * ((bounces - i)));
282 fraction -= half;
283 fraction /= (w / 2);
284 return (1 - fraction * fraction) * top + start;
286 bounceStart = bounceEnd;
287 w = w * growth;
289 return 0;
292 float fastBounceOut(float fraction, float start, float delta, int bounces, float growth, float damping)
294 return fastBounceIn(1 - fraction, start + delta, -delta, bounces, growth, damping);
297 float fastBounceInOut(float fraction, float start, float delta, int bounces, float growth, float damping)
299 if (fraction < 0.5)
300 return fastBounceIn(2 * fraction, start, delta / 2, bounces, growth, damping);
301 return fastBounceOut(2 * fraction - 1, start + delta / 2, delta / 2, bounces, growth, damping);