fix crashes reported by Debian Cylab Mayhem Team
[swftools.git] / src / swfc-history.c
blobd3c0ff67672f156970f556f21aae9674c93a5470
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 <memory.h>
24 #include "swfc-history.h"
26 enum
28 T_BEFORE,
29 T_AFTER,
30 T_SYMMETRIC
33 state_t* state_new(U16 frame, int function, float value, interpolation_t* inter)
35 state_t* newState = (state_t*)malloc(sizeof(state_t));
36 state_init(newState);
37 newState->frame = frame;
38 newState->function = function;
39 newState->value = value;
40 newState->interpolation = inter;
41 return newState;
44 void state_free(state_t* state)
46 if (state->next)
47 state_free(state->next);
48 free(state);
51 void state_init(state_t* state)
53 memset(state, 0, sizeof(state_t));
56 state_t* state_at(state_t* state, U16 frame)
58 while (state->next && state->next->frame < frame)
59 state = state->next;
60 return state;
63 void state_append(state_t* state, state_t* newState)
65 state_t* previous = 0;
66 state_t* start = state;
67 float p0, p1, m0, m1;
68 int previous_frames = 0, state_frames, new_frames;
70 while (state->next)
72 if (previous)
73 previous_frames = state->frame - previous->frame;
74 previous = state;
75 state = state->next;
77 state->next = newState;
78 new_frames = newState->frame - state->frame;
79 if (state->function == CF_SCHANGE)
81 state_frames = state->frame - previous->frame;
82 p0 = previous->value;
83 p1 = state->value;
84 if (previous->function == CF_SCHANGE)
85 m0 = (3 * previous->spline.a + 2 * previous->spline.b + previous->spline.c) * state_frames / previous_frames ;
86 else
87 if (previous->function == CF_CHANGE || previous->function == CF_SWEEP)
88 m0 = state_tangent(start, previous->frame, T_BEFORE) * state_frames;
89 else
90 m0 = (state->value - previous->value);
91 if (newState->function == CF_SCHANGE)
92 m1 = /*0.5 * */(newState->value - previous->value) * state_frames / (new_frames + state_frames);
93 else
94 if (newState->function == CF_CHANGE || newState->function == CF_SWEEP)
95 m1 = state_tangent(previous, state->frame, T_AFTER) * state_frames;
96 else
97 m1 = (newState->value - state->value);
98 state->spline.a = 2 * p0 + m0 - 2 * p1 + m1;
99 state->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1;
100 state->spline.c = m0;
101 state->spline.d = p0;
102 // printf("p0: %f, p1: %f, m0: %f, m1: %f.\n", p0, p1, m0, m1);
103 // printf("a: %f, b: %f, c: %f, d: %f.\n", state->spline.a, state->spline.b, state->spline.c, state->spline.d);
105 if (newState->function == CF_SCHANGE)
107 p0 = state->value;
108 p1 = newState->value;
109 if (state->function == CF_SCHANGE)
110 m0 = m1;
111 else
112 if (state->function == CF_CHANGE || state->function == CF_SWEEP)
113 m0 = state_tangent(start, state->frame, T_BEFORE) * new_frames;
114 else
115 m0 = (newState->value - state->value);
116 m1 = (newState->value - state->value);
117 newState->spline.a = 2 * p0 + m0 - 2 * p1 + m1;
118 newState->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1;
119 newState->spline.c = m0;
120 newState->spline.d = p0;
121 // printf("p0: %f, p1: %f, m0: %f, m1: %f.\n", p0, p1, m0, m1);
122 // printf("a: %f, b: %f, c: %f, d: %f.\n", newState->spline.a, newState->spline.b, newState->spline.c, newState->spline.d);
126 void state_insert(state_t* state, state_t* newState)
128 while (state->next && state->next->frame < newState->frame)
129 state = state->next;
130 newState->next = state->next;
131 state->next = newState;
132 // if this is going to be used to insert CF_SCHANGE states it will have to be extended
133 // as in state_append above. I know this is not necessary right now, so I'll be lazy.
136 float calculateSpline(state_t* modification, float fraction)
138 spline_t s = modification->spline;
139 return (((s.a * fraction) + s.b) * fraction + s.c) * fraction + s.d;
142 float interpolateScalar(float p1, float p2, float fraction, interpolation_t* inter)
144 if (!inter)
145 return linear(fraction, p1, p2 - p1);
146 switch (inter->function)
148 case IF_LINEAR: return linear(fraction, p1, p2 - p1);
149 case IF_QUAD_IN: return quadIn(fraction, p1, p2 - p1, inter->slope);
150 case IF_QUAD_OUT: return quadOut(fraction, p1, p2 - p1, inter->slope);
151 case IF_QUAD_IN_OUT: return quadInOut(fraction, p1, p2 - p1, inter->slope);
152 case IF_CUBIC_IN: return cubicIn(fraction, p1, p2 - p1, inter->slope);
153 case IF_CUBIC_OUT: return cubicOut(fraction, p1, p2 - p1, inter->slope);
154 case IF_CUBIC_IN_OUT: return cubicInOut(fraction, p1, p2 - p1, inter->slope);
155 case IF_QUART_IN: return quartIn(fraction, p1, p2 - p1, inter->slope);
156 case IF_QUART_OUT: return quartOut(fraction, p1, p2 - p1, inter->slope);
157 case IF_QUART_IN_OUT: return quartInOut(fraction, p1, p2 - p1, inter->slope);
158 case IF_QUINT_IN: return quintIn(fraction, p1, p2 - p1, inter->slope);
159 case IF_QUINT_OUT: return quintOut(fraction, p1, p2 - p1, inter->slope);
160 case IF_QUINT_IN_OUT: return quintInOut(fraction, p1, p2 - p1, inter->slope);
161 case IF_CIRCLE_IN: return circleIn(fraction, p1, p2 - p1, inter->slope);
162 case IF_CIRCLE_OUT: return circleOut(fraction, p1, p2 - p1, inter->slope);
163 case IF_CIRCLE_IN_OUT: return circleInOut(fraction, p1, p2 - p1, inter->slope);
164 case IF_EXPONENTIAL_IN: return exponentialIn(fraction, p1, p2 - p1);
165 case IF_EXPONENTIAL_OUT: return exponentialOut(fraction, p1, p2 - p1);
166 case IF_EXPONENTIAL_IN_OUT: return exponentialInOut(fraction, p1, p2 - p1);
167 case IF_SINE_IN: return sineIn(fraction, p1, p2 - p1);
168 case IF_SINE_OUT: return sineOut(fraction, p1, p2 - p1);
169 case IF_SINE_IN_OUT: return sineInOut(fraction, p1, p2 - p1);
170 case IF_ELASTIC_IN: return elasticIn(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
171 case IF_ELASTIC_OUT: return elasticOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
172 case IF_ELASTIC_IN_OUT: return elasticInOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
173 case IF_BACK_IN: return backIn(fraction, p1, p2 - p1, inter->speed);
174 case IF_BACK_OUT: return backOut(fraction, p1, p2 - p1, inter->speed);
175 case IF_BACK_IN_OUT: return backInOut(fraction, p1, p2 - p1, inter->speed);
176 case IF_BOUNCE_IN: return bounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
177 case IF_BOUNCE_OUT: return bounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
178 case IF_BOUNCE_IN_OUT: return bounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
179 case IF_FAST_BOUNCE_IN: return fastBounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
180 case IF_FAST_BOUNCE_OUT: return fastBounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
181 case IF_FAST_BOUNCE_IN_OUT: return fastBounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
182 default: return linear(fraction, p1, p2 - p1);
186 float calculateSweep(state_t* modification, float fraction)
188 arc_t* a = &(modification->arc);
189 float angle = a->angle + fraction * a->delta_angle;
190 if (a->X)
191 return a->cX + a->r * cos(angle);
192 else
193 return a->cY + a->r * sin(angle);
197 int state_differs(state_t* modification, U16 frame)
199 state_t* previous = modification;
200 while (modification && modification->frame < frame)
202 previous = modification;
203 modification = modification->next;
205 if (!modification)
206 return 0;
207 if (modification->frame == frame)
208 return 1;
209 return (modification->function != CF_JUMP);
212 float state_tangent(state_t* modification, U16 frame, int tangent)
214 float deltaFrame = 0.1;
215 switch (tangent)
217 case T_BEFORE:
218 return (state_value(modification, frame) - state_value(modification, frame - deltaFrame)) / deltaFrame;
219 case T_AFTER:
220 return (state_value(modification, frame + deltaFrame) - state_value(modification, frame)) / deltaFrame;
221 default:
222 return (state_value(modification, frame + deltaFrame) - state_value(modification, frame - deltaFrame)) / (2 * deltaFrame);
226 float state_value(state_t* modification, float frame)
228 state_t* previous = modification;
229 while (modification && modification->frame < frame)
231 previous = modification;
232 modification = modification->next;
234 if (!modification)
235 return previous->value;
236 if (modification->frame == frame)
240 previous = modification;
241 modification = modification->next;
243 while (modification && modification->frame == frame);
244 return previous->value;
246 switch (modification->function)
248 case CF_PUT:
249 return modification->value;
250 case CF_CHANGE:
252 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
253 return interpolateScalar(previous->value, modification->value, fraction, modification->interpolation);
255 case CF_SCHANGE:
257 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
258 fraction = interpolateScalar(0, 1, fraction, modification->interpolation);
259 return calculateSpline(modification, fraction);
261 case CF_SWEEP:
263 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
264 fraction = interpolateScalar(0, 1, fraction, modification->interpolation);
265 return calculateSweep(modification, fraction);
267 case CF_JUMP:
268 return previous->value;
269 default:
270 return 0;
274 filterState_t* filterState_new(U16 frame, int function, FILTERLIST* value, interpolation_t* inter)
276 filterState_t* newChange = (filterState_t*)malloc(sizeof(filterState_t));
277 filterState_init(newChange);
278 newChange->frame = frame;
279 newChange->function = function;
280 newChange->value = value;
281 newChange->interpolation = inter;
282 return newChange;
285 void filterState_free(filterState_t *change)
287 if (change->next)
288 filterState_free(change->next);
289 free(change->value);
290 free(change);
293 void filterState_init(filterState_t* change)
295 memset(change, 0, sizeof(filterState_t));
298 void filterState_append(filterState_t* first, filterState_t* newChange)
300 while (first->next)
301 first = first->next;
302 if (!first->value || !newChange->value)
303 first->next = newChange;
304 else
306 int i, mergedCount = 0;
307 int common = first->value->num < newChange->value->num ? first->value->num : newChange->value->num;
308 for (i = 0; i < common; i++)
310 mergedCount++;
311 if (newChange->value->filter[i]->type != first->value->filter[i]->type)
312 mergedCount++;
314 mergedCount = mergedCount + first->value->num - common + newChange->value->num - common;
315 if (mergedCount > 8)
317 char* list1;
318 char* list2;
319 char* newList;
320 list1 = (char*)malloc(1);
321 *list1 = '\0';
322 for (i = 0; i < first->value->num; i++)
324 char*filter = filtername[first->value->filter[i]->type];
325 newList = (char*)malloc(strlen(list1) + strlen(filter) + 2);
326 strcpy(newList, list1);
327 strcat(newList, "+");
328 strcat(newList, filtername[first->value->filter[i]->type]);
329 free(list1);
330 list1 = newList;
332 list2 = (char*)malloc(1);
333 *list2 = '\0';
334 for (i = 0; i < newChange->value->num; i++)
336 char*filter = filtername[newChange->value->filter[i]->type];
337 newList = (char*)malloc(strlen(list2) + strlen(filter) + 2);
338 strcpy(newList, list2);
339 strcat(newList, "+");
340 strcat(newList, filter);
341 free(list2);
342 list2 = newList;
344 syntaxerror("filterlists %s and %s cannot be interpolated.", list1, list2);
346 first->next = newChange;
350 RGBA interpolateColor(RGBA c1, RGBA c2, float ratio, interpolation_t* inter)
352 RGBA c;
353 c.r = interpolateScalar(c1.r, c2.r, ratio, inter);
354 c.g = interpolateScalar(c1.g, c2.g, ratio, inter);
355 c.b = interpolateScalar(c1.b, c2.b, ratio, inter);
356 c.a = interpolateScalar(c1.a, c2.a, ratio, inter);
357 return c;
360 GRADIENT* interpolateNodes(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
362 if (g1->num != g2->num)
363 syntaxerror("Internal error: gradients are not equal in size");
365 int i;
366 GRADIENT* g = (GRADIENT*) malloc(sizeof(GRADIENT));
367 g->ratios = rfx_calloc(16*sizeof(U8));
368 g->rgba = rfx_calloc(16*sizeof(RGBA));
369 g->num = g1->num;
370 for (i = 0; i < g->num; i++)
372 g->ratios[i] = interpolateScalar(g1->ratios[i], g2->ratios[i], fraction, inter);
373 g->rgba[i] = interpolateColor(g1->rgba[i], g2->rgba[i], fraction, inter);
375 return g;
378 void copyGradient(GRADIENT* dest, GRADIENT* source)
380 dest->num = source->num;
381 memcpy(dest->ratios, source->ratios, source->num * sizeof(U8));
382 memcpy(dest->rgba, source->rgba, source->num * sizeof(RGBA));
385 void insertNode(GRADIENT* g, int pos)
387 memmove(&g->ratios[pos + 1], &g->ratios[pos], (g->num - pos) * sizeof(U8));
388 memmove(&g->rgba[pos + 1], &g->rgba[pos], (g->num - pos) * sizeof(RGBA));
389 if (pos == 0)
391 g->ratios[0] = g->ratios[1] / 2;
392 g->rgba[0] = g->rgba[1];
394 else
395 if (pos == g->num)
397 g->ratios[pos] = (255 + g->ratios[g->num - 1]) / 2;
398 g->rgba[pos] = g->rgba[pos - 1];
400 else
402 g->ratios[pos] = (g->ratios[pos - 1] + g->ratios[pos + 1]) / 2;
403 g->rgba[pos] = interpolateColor(g->rgba[pos - 1], g->rgba[pos + 1], 0.5, 0);
405 g->num++;
408 void insertOptimalNode(GRADIENT* g)
410 int i, next_gap;
411 int pos = 0;
412 int gap = g->ratios[0];
413 for (i = 0; i < g->num - 1; i++)
415 next_gap = g->ratios[i + 1] - g->ratios[i];
416 if (next_gap > gap)
418 gap = next_gap;
419 pos = i + 1;
422 next_gap = 255 - g->ratios[g->num -1];
423 if (next_gap > gap)
424 pos = g->num;
425 insertNode(g, pos);
428 void growGradient(GRADIENT* start, int size)
430 while (start->num < size)
431 insertOptimalNode(start);
434 GRADIENT* interpolateGradient(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
436 int i;
437 GRADIENT g;
438 g.ratios = rfx_calloc(16*sizeof(U8));
439 g.rgba = rfx_calloc(16*sizeof(RGBA));
441 if (g1->num > g2->num)
443 copyGradient(&g, g2);
444 growGradient(&g, g1->num);
445 GRADIENT* result = interpolateNodes(g1, &g, fraction, inter);
446 rfx_free(g.rgba);
447 rfx_free(g.ratios);
448 return result;
450 else
451 if (g1->num < g2->num)
453 copyGradient(&g, g1);
454 growGradient(&g, g2->num);
455 GRADIENT* result = interpolateNodes(&g, g2, fraction, inter);
456 rfx_free(g.rgba);
457 rfx_free(g.ratios);
458 return result;
460 else
461 return interpolateNodes(g1, g2, fraction, inter);
464 FILTER* copyFilter(FILTER* original)
466 if (!original)
467 return original;
468 FILTER* copy = swf_NewFilter(original->type);
469 switch (original->type)
471 case FILTERTYPE_BLUR:
472 memcpy(copy, original, sizeof(FILTER_BLUR));
473 break;
474 case FILTERTYPE_GRADIENTGLOW:
476 memcpy(copy, original, sizeof(FILTER_GRADIENTGLOW));
477 FILTER_GRADIENTGLOW* ggcopy = (FILTER_GRADIENTGLOW*)copy;
478 ggcopy->gradient = (GRADIENT*)malloc(sizeof(GRADIENT));
479 ggcopy->gradient->ratios = (U8*)malloc(16 * sizeof(U8));
480 ggcopy->gradient->rgba = (RGBA*)malloc(16 * sizeof(RGBA));
481 copyGradient(ggcopy->gradient, ((FILTER_GRADIENTGLOW*)original)->gradient);
483 break;
484 case FILTERTYPE_DROPSHADOW:
485 memcpy(copy, original, sizeof(FILTER_DROPSHADOW));
486 break;
487 case FILTERTYPE_BEVEL:
488 memcpy(copy, original, sizeof(FILTER_BEVEL));
489 break;
490 default: syntaxerror("Internal error: unsupported filterype, cannot copy");
492 return copy;
495 FILTER* interpolateBlur(FILTER* filter1, FILTER* filter2, float ratio, interpolation_t* inter)
497 FILTER_BLUR*f1 = (FILTER_BLUR*)filter1;
498 FILTER_BLUR*f2 = (FILTER_BLUR*)filter2;
499 if (!f1)
500 f1 = noBlur;
501 if (!f2)
502 f2 = noBlur;
503 if(f1->blurx == f2->blurx && f1->blury == f2->blury)
504 return copyFilter(filter1);
505 FILTER_BLUR*f = (FILTER_BLUR*)swf_NewFilter(FILTERTYPE_BLUR);
506 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
507 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
508 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
509 return (FILTER*)f;
512 void matchDropshadowFlags(FILTER_DROPSHADOW* unset, FILTER_DROPSHADOW* target)
514 unset->innershadow = target->innershadow;
515 unset->knockout = target->knockout;
516 unset->composite = target->composite;
519 FILTER* interpolateDropshadow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
521 FILTER_DROPSHADOW*f1 = (FILTER_DROPSHADOW*)filter1;
522 FILTER_DROPSHADOW*f2 = (FILTER_DROPSHADOW*)filter2;
523 if (!f1)
524 f1 = noDropshadow;
525 if (!f2)
526 f2 = noDropshadow;
527 if(!memcmp(&f1->color,&f2->color,sizeof(RGBA)) && f1->strength == f2->strength &&
528 f1->blurx == f2->blurx && f1->blury == f2->blury &&
529 f1->angle == f2->angle && f1->distance == f2->distance)
530 return copyFilter(filter1);
531 FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)swf_NewFilter(FILTERTYPE_DROPSHADOW);
532 memcpy(f, f1, sizeof(FILTER_DROPSHADOW));
533 f->color = interpolateColor(f1->color, f2->color, ratio, inter);
534 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
535 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
536 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
537 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
538 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
539 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
540 if (f1 == noDropshadow)
542 if (f2 != noDropshadow)
543 matchDropshadowFlags(f, f2);
545 else
546 if (f2 == noDropshadow)
547 matchDropshadowFlags(f, f1);
548 else
549 if (ratio > 0.5)
550 matchDropshadowFlags(f, f2);
551 else
552 matchDropshadowFlags(f, f1);
553 return (FILTER*)f;
556 void matchBevelFlags(FILTER_BEVEL* unset, FILTER_BEVEL* target)
558 unset->innershadow = target->innershadow;
559 unset->knockout = target->knockout;
560 unset->composite = target->composite;
561 unset->ontop = target->ontop;
564 FILTER* interpolateBevel(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
566 FILTER_BEVEL*f1 = (FILTER_BEVEL*)filter1;
567 FILTER_BEVEL*f2 = (FILTER_BEVEL*)filter2;
568 if (!f1)
569 f1 = noBevel;
570 if (!f2)
571 f2 = noBevel;
572 if(!memcmp(&f1->shadow,&f2->shadow,sizeof(RGBA)) &&
573 !memcmp(&f1->highlight,&f2->highlight,sizeof(RGBA)) &&
574 f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
575 return copyFilter(filter1);
576 FILTER_BEVEL*f = (FILTER_BEVEL*)swf_NewFilter(FILTERTYPE_BEVEL);
577 memcpy(f, f1, sizeof(FILTER_BEVEL));
578 f->shadow = interpolateColor(f1->shadow, f2->shadow, ratio, inter);
579 f->highlight = interpolateColor(f1->highlight, f2->highlight, ratio, inter);
580 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
581 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
582 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
583 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
584 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
585 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
586 if (f1 == noBevel)
588 if (f2 != noBevel)
589 matchBevelFlags(f, f2);
591 else
592 if (f2 == noBevel)
593 matchBevelFlags(f, f1);
594 else
595 if (ratio > 0.5)
596 matchBevelFlags(f, f2);
597 else
598 matchBevelFlags(f, f1);
599 return (FILTER*)f;
602 void matchGradientGlowFlags(FILTER_GRADIENTGLOW* unset, FILTER_GRADIENTGLOW* target)
604 unset->innershadow = target->innershadow;
605 unset->knockout = target->knockout;
606 unset->composite = target->composite;
607 unset->ontop = target->ontop;
610 FILTER* interpolateGradientGlow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
612 FILTER_GRADIENTGLOW*f1 = (FILTER_GRADIENTGLOW*)filter1;
613 FILTER_GRADIENTGLOW*f2 = (FILTER_GRADIENTGLOW*)filter2;
614 if (!f1)
615 f1 = noGradientGlow;
616 if (!f2)
617 f2 = noGradientGlow;
618 if(f1->gradient->num == f2->gradient->num &&
619 !memcmp(&f1->gradient->ratios,&f2->gradient->ratios,f1->gradient->num * sizeof(U8)) &&
620 !memcmp(&f1->gradient->rgba,&f2->gradient->rgba,f1->gradient->num * sizeof(RGBA)) &&
621 f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
622 return copyFilter(filter1);
623 FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW);
624 memcpy(f, f1, sizeof(FILTER_GRADIENTGLOW));
625 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
626 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
627 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
628 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
629 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
630 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
631 f->gradient= interpolateGradient(f1->gradient, f2->gradient, ratio, inter);
632 if (f1 == noGradientGlow)
634 if (f2 != noGradientGlow)
635 matchGradientGlowFlags(f, f2);
637 else
638 if (f2 == noGradientGlow)
639 matchGradientGlowFlags(f, f1);
640 else
641 if (ratio > 0.5)
642 matchGradientGlowFlags(f, f2);
643 else
644 matchGradientGlowFlags(f, f1);
645 return (FILTER*)f;
648 FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
650 if(!filter1 && !filter2)
651 return 0;
653 int filter_type;
654 if (!filter1)
655 filter_type = filter2->type;
656 else
657 if (!filter2)
658 filter_type = filter1->type;
659 else
660 if(filter2->type != filter1->type)
661 syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]);
662 else
663 filter_type = filter1->type;
665 switch (filter_type)
667 case FILTERTYPE_BLUR:
668 return interpolateBlur(filter1, filter2, ratio, inter);
669 case FILTERTYPE_BEVEL:
670 return interpolateBevel(filter1, filter2, ratio, inter);
671 case FILTERTYPE_DROPSHADOW:
672 return interpolateDropshadow(filter1, filter2, ratio, inter);
673 case FILTERTYPE_GRADIENTGLOW:
674 return interpolateGradientGlow(filter1, filter2, ratio, inter);
675 default:
676 syntaxerror("Filtertype %s not supported yet.\n", filtername[filter1->type]);
678 return 0;
681 FILTERLIST* copyFilterList(FILTERLIST* original)
683 if (!original)
684 return original;
685 int i;
686 FILTERLIST* copy = (FILTERLIST*)malloc(sizeof(FILTERLIST));
687 copy->num = original->num;
688 for (i = 0; i < copy->num; i++)
689 copy->filter[i] = copyFilter(original->filter[i]);
690 return copy;
693 FILTER* noFilter(int type)
695 switch (type)
697 case FILTERTYPE_BLUR:
698 return (FILTER*)noBlur;
699 break;
700 case FILTERTYPE_BEVEL:
701 return (FILTER*)noBevel;
702 break;
703 case FILTERTYPE_DROPSHADOW:
704 return (FILTER*)noDropshadow;
705 break;
706 case FILTERTYPE_GRADIENTGLOW:
707 return (FILTER*)noGradientGlow;
708 break;
709 default:
710 syntaxerror("Internal error: unsupported filtertype, cannot match filterlists");
712 return 0;
715 FILTERLIST* interpolateFilterList(FILTERLIST* list1, FILTERLIST* list2, float ratio, interpolation_t* inter)
717 if (!list1 && !list2)
718 return list1;
719 FILTERLIST start, target, dummy;
720 dummy.num = 0;
721 if (!list1)
722 list1 = &dummy;
723 if (!list2)
724 list2 = &dummy;
725 int i, j = 0;
726 int common = list1->num < list2->num ? list1->num : list2->num;
727 for (i = 0; i < common; i++)
729 start.filter[j] = list1->filter[i];
730 if (list2->filter[i]->type == list1->filter[i]->type)
732 target.filter[j] = list2->filter[i];
733 j++;
735 else
737 target.filter[j] = noFilter(list1->filter[i]->type);
738 j++;
739 start.filter[j] = noFilter(list2->filter[i]->type);
740 target.filter[j] = list2->filter[i];
741 j++;
744 if (list1->num > common)
745 for (i = common; i < list1->num; i++)
747 start.filter[j] = list1->filter[i];
748 target.filter[j] = noFilter(list1->filter[i]->type);
749 j++;
751 if (list2->num > common)
752 for (i = common; i < list2->num; i++)
754 start.filter[j] = noFilter(list2->filter[i]->type);
755 target.filter[j] = list2->filter[i];
756 j++;
758 start.num = j;
759 target.num = j;
760 FILTERLIST* mixedList = (FILTERLIST*)malloc(sizeof(FILTERLIST));
761 mixedList->num = j;
762 for (i = 0; i < j; i++)
763 mixedList->filter[i] = interpolateFilter(start.filter[i], target.filter[i], ratio, inter);
764 return mixedList;
767 int filterState_differs(filterState_t* modification, U16 frame)
769 filterState_t* previous = modification;
770 while (modification && modification->frame < frame)
772 previous = modification;
773 modification = modification->next;
775 if (!modification)
776 return 0;
777 if (modification->frame == frame)
778 return 1;
779 return (modification->function != CF_JUMP);
782 FILTERLIST* filterState_value(filterState_t* modification, U16 frame)
784 filterState_t* previous = modification;
785 while (modification && modification->frame < frame)
787 previous = modification;
788 modification = modification->next;
790 if (!modification)
791 return copyFilterList(previous->value);
792 if (modification->frame == frame)
796 previous = modification;
797 modification = modification->next;
799 while (modification && modification->frame == frame);
800 return copyFilterList(previous->value);
802 switch (modification->function)
804 case CF_PUT:
805 return copyFilterList(modification->value);
806 case CF_CHANGE:
808 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
809 return interpolateFilterList(previous->value, modification->value, fraction, modification->interpolation);
811 case CF_JUMP:
812 return copyFilterList(previous->value);
813 default:
814 return 0;
818 history_t* history_new()
820 history_t* newHistory = (history_t*)malloc(sizeof(history_t));
821 history_init(newHistory);
822 return newHistory;
825 void history_free(history_t* past)
827 state_free(dict_lookup(past->states, "x"));
828 state_free(dict_lookup(past->states, "y"));
829 state_free(dict_lookup(past->states, "scalex"));
830 state_free(dict_lookup(past->states, "scaley"));
831 state_free(dict_lookup(past->states, "cxform.r0"));
832 state_free(dict_lookup(past->states, "cxform.g0"));
833 state_free(dict_lookup(past->states, "cxform.b0"));
834 state_free(dict_lookup(past->states, "cxform.a0"));
835 state_free(dict_lookup(past->states, "cxform.r1"));
836 state_free(dict_lookup(past->states, "cxform.g1"));
837 state_free(dict_lookup(past->states, "cxform.b1"));
838 state_free(dict_lookup(past->states, "cxform.a1"));
839 state_free(dict_lookup(past->states, "rotate"));
840 state_free(dict_lookup(past->states, "shear"));
841 state_free(dict_lookup(past->states, "pivot.x"));
842 state_free(dict_lookup(past->states, "pivot.y"));
843 state_free(dict_lookup(past->states, "pin.x"));
844 state_free(dict_lookup(past->states, "pin.y"));
845 state_free(dict_lookup(past->states, "blendmode"));
846 state_free(dict_lookup(past->states, "flags"));
847 filterState_free(dict_lookup(past->states, "filter"));
848 dict_destroy(past->states);
849 free(past);
852 void history_init(history_t* past)
854 past->states = (dict_t*)malloc(sizeof(dict_t));
855 dict_init(past->states, 16);
858 void history_begin(history_t* past, char* parameter, U16 frame, TAG* tag, float value)
860 state_t* first = state_new(frame, CF_PUT, value, 0);
861 past->firstTag = tag;
862 past->firstFrame = frame;
863 dict_put2(past->states, parameter, first);
866 void history_beginFilter(history_t* past, U16 frame, TAG* tag, FILTERLIST* value)
868 filterState_t* first = filterState_new(frame, CF_PUT, value, 0);
869 past->firstTag = tag;
870 past->firstFrame = frame;
871 dict_put2(past->states, "filter", first);
874 void history_remember(history_t* past, char* parameter, U16 frame, int function, float value, interpolation_t* inter)
876 past->lastFrame = frame;
877 state_t* state = dict_lookup(past->states, parameter);
878 if (state) //should always be true
880 state_t* next = state_new(frame, function, value, inter);
881 state_append(state, next);
883 else
884 syntaxerror("Internal error: changing parameter %s, which is unknown for the instance.", parameter);
887 static float getAngle(float dX, float dY)
889 float radius = sqrt(dX * dX + dY * dY);
890 if (radius == 0)
891 return 0.0;
892 if (dX >= 0)
893 if (dY > 0)
894 return acos(dX / radius);
895 else
896 return 2 * M_PI - acos(dX / radius);
897 else
898 if (dY > 0)
899 return M_PI - acos(-dX / radius);
900 else
901 return M_PI + acos(-dX / radius);
904 static float getDeltaAngle(float angle1, float angle2, int clockwise)
906 if (!clockwise)
908 if (angle1 > angle2)
909 return angle2 - angle1;
910 else
911 return angle2 - angle1 - 2 * M_PI;
913 else
915 if (angle1 > angle2)
916 return 2 * M_PI - angle1 + angle2;
917 else
918 return angle2 - angle1;
922 void history_rememberSweep(history_t* past, U16 frame, float x, float y, float r, int clockwise, int short_arc, interpolation_t* inter)
924 float lastX, lastY, dX, dY;
925 U16 lastFrame;
927 past->lastFrame = frame;
928 state_t* change = dict_lookup(past->states, "x");
929 if (change) //should always be true
931 while (change->next)
932 change = change->next;
933 lastFrame = change->frame;
934 lastX = change->value;
935 change = dict_lookup(past->states, "y");
936 if (change) //should always be true
938 while (change->next)
939 change = change->next;
940 lastY = change->value;
941 dX = x - lastX;
942 dY = y - lastY;
943 if (dX == 0 && dY == 0)
944 syntaxerror("sweep not possible: startpoint and endpoint must not be equal");
945 if ((dX) * (dX) + (dY) * (dY) > 4 * r * r)
946 syntaxerror("sweep not possible: radius is to small");
947 if (change->frame > lastFrame)
949 lastFrame = change->frame;
950 history_remember(past, "x", lastFrame, CF_JUMP, lastX, 0);
952 else
953 if (change->frame < lastFrame)
954 history_remember(past, "y", lastFrame, CF_JUMP, lastY, 0);
955 float c1X, c1Y, c2X, c2Y;
956 if (dX == 0) //vertical
958 c1Y = c2Y = (lastY + y) / 2;
959 c1X = x + sqrt(r * r - (c1Y - y) * (c1Y - y));
960 c2X = 2 * x -c1X;
962 else
963 if (dY == 0) //horizontal
965 c1X = c2X = (lastX + x) / 2;
966 c1Y = y +sqrt(r * r - (c1X - x) * (c1X - x));
967 c2Y = 2 * y -c1Y;
969 else
971 c1X = sqrt((r * r - (dX * dX + dY * dY) / 4) / (1 + dX * dX / dY / dY));
972 c2X = -c1X;
973 c1Y = -dX / dY * c1X;
974 c2Y = -c1Y;
975 c1X += (x + lastX) / 2;
976 c2X += (x + lastX) / 2;
977 c1Y += (y + lastY) / 2;
978 c2Y += (y + lastY) / 2;
980 float angle1, angle2, delta_angle, centerX, centerY;
981 angle1 = getAngle(lastX - c1X, lastY - c1Y);
982 angle2 = getAngle(x - c1X, y - c1Y);
983 delta_angle = getDeltaAngle(angle1, angle2, clockwise);
984 if ((short_arc && fabs(delta_angle) <= M_PI) || (! short_arc && fabs(delta_angle) >= M_PI))
986 centerX = c1X;
987 centerY = c1Y;
989 else
991 angle1 = getAngle(lastX - c2X, lastY - c2Y);
992 angle2 = getAngle(x - c2X, y - c2Y);
993 delta_angle = getDeltaAngle(angle1, angle2, clockwise);
994 centerX = c2X;
995 centerY = c2Y;
997 change = dict_lookup(past->states, "x");
998 state_t* nextX = state_new(frame, CF_SWEEP, x, inter);
999 nextX->arc.r = r;
1000 nextX->arc.angle = angle1;
1001 nextX->arc.delta_angle = delta_angle;
1002 nextX->arc.cX = centerX;
1003 nextX->arc.cY = centerY;
1004 nextX->arc.X = 1;
1005 state_append(change, nextX);
1006 change = dict_lookup(past->states, "y");
1007 state_t* nextY = state_new(frame, CF_SWEEP, y, inter);
1008 nextY->arc.r = r;
1009 nextY->arc.angle = angle1;
1010 nextY->arc.delta_angle = delta_angle;
1011 nextY->arc.cX = centerX;
1012 nextY->arc.cY = centerY;
1013 nextY->arc.X = 0;
1014 state_append(change, nextY);
1016 else
1017 syntaxerror("Internal error: changing parameter y in sweep, which is unknown for the instance.");
1019 else
1020 syntaxerror("Internal error: changing parameter x in sweep, which is unknown for the instance.");
1023 void history_rememberFilter(history_t* past, U16 frame, int function, FILTERLIST* value, interpolation_t* inter)
1025 past->lastFrame = frame;
1026 filterState_t* first = dict_lookup(past->states, "filter");
1027 if (first) //should always be true
1029 filterState_t* next = filterState_new(frame, function, value, inter);
1030 filterState_append(first, next);
1032 else
1033 syntaxerror("Internal error: changing a filter not set for the instance.");
1036 void history_processFlags(history_t* past)
1037 // to be called after completely recording this history, before calculating any values.
1039 state_t* flagState = dict_lookup(past->states, "flags");
1040 state_t* nextState;
1041 U16 nextFlags, toggledFlags, currentFlags = (U16)flagState->value;
1042 while (flagState->next)
1044 nextState = flagState->next;
1045 nextFlags = (U16)nextState->value;
1046 toggledFlags = currentFlags ^ nextFlags;
1047 if (toggledFlags & IF_FIXED_ALIGNMENT)
1048 { // the IF_FIXED_ALIGNMENT bit will change in the next state
1049 if (nextFlags & IF_FIXED_ALIGNMENT)
1050 { // the IF_FIXED_ALIGNMENT bit will be set
1051 int onFrame = nextState->frame;
1052 state_t* rotations = dict_lookup(past->states, "rotate");
1053 nextState->params.instanceAngle = state_value(rotations, onFrame);
1054 state_t* resetRotate = state_new(onFrame, CF_JUMP, 0, 0);
1055 state_insert(rotations, resetRotate);
1056 if (onFrame == past->firstFrame)
1057 onFrame++;
1058 state_t *x, *y;
1059 float dx, dy;
1062 x = dict_lookup(past->states, "x");
1063 dx = state_tangent(x, onFrame, T_SYMMETRIC);
1064 y = dict_lookup(past->states, "y");
1065 dy = state_tangent(y, onFrame, T_SYMMETRIC);
1066 onFrame++;
1068 while (dx == 0 && dy == 0 && onFrame < past->lastFrame);
1069 if (onFrame == past->lastFrame)
1070 nextState->params.pathAngle = 0;
1071 else
1072 nextState->params.pathAngle = getAngle(dx, dy) / M_PI * 180;
1074 else // the IF_FIXED_ALIGNMENT bit will be reset
1076 int offFrame = nextState->frame;
1077 state_t* rotations = dict_lookup(past->states, "rotate");
1078 state_t* setRotate = state_new(offFrame, CF_JUMP, flagState->params.instanceAngle + state_value(rotations, offFrame), 0);
1079 state_insert(rotations, setRotate);
1082 else // the IF_FIXED_ALIGNMENT bit will not change but some processing may be
1083 // required just the same
1085 if (nextFlags & IF_FIXED_ALIGNMENT)
1087 nextState->params.instanceAngle = flagState->params.instanceAngle;
1088 nextState->params.pathAngle = flagState->params.pathAngle;
1091 // and so on for all the other bits.
1092 flagState = nextState;
1093 currentFlags = nextFlags;
1097 int history_change(history_t* past, U16 frame, char* parameter)
1099 state_t* first = dict_lookup(past->states, parameter);
1100 if (first) //should always be true.
1101 return state_differs(first, frame);
1102 syntaxerror("no history found to predict changes for parameter %s.\n", parameter);
1103 return 0;
1106 float history_value(history_t* past, U16 frame, char* parameter)
1108 state_t* state = dict_lookup(past->states, parameter);
1109 if (state) //should always be true.
1110 return state_value(state, frame);
1111 syntaxerror("no history found to get a value for parameter %s.\n", parameter);
1112 return 0;
1115 float history_rotateValue(history_t* past, U16 frame)
1117 state_t* rotations = dict_lookup(past->states, "rotate");
1118 if (rotations) //should always be true.
1120 float angle = state_value(rotations, frame);
1121 state_t* flags = dict_lookup(past->states, "flags");
1122 U16 currentflags = state_value(flags, frame);
1123 if (currentflags & IF_FIXED_ALIGNMENT)
1125 flags = state_at(flags, frame);
1126 if (frame == past->firstFrame)
1127 frame++;
1128 state_t *x, *y;
1129 float dx, dy, pathAngle;
1132 x = dict_lookup(past->states, "x");
1133 dx = state_value(x, frame) - state_value(x, frame - 1);
1134 y = dict_lookup(past->states, "y");
1135 dy = state_value(y, frame) - state_value(y, frame - 1);
1136 frame--;
1138 while (dx == 0 && dy == 0 && frame > past->firstFrame);
1139 if (frame == past->firstFrame)
1140 pathAngle = 0;
1141 else
1142 pathAngle = getAngle(dx, dy) / M_PI * 180;
1143 return angle + flags->params.instanceAngle + pathAngle - flags->params.pathAngle;
1145 else
1146 return angle;
1148 syntaxerror("no history found to get a value for parameter rotate.\n");
1149 return 0;
1152 int history_changeFilter(history_t* past, U16 frame)
1154 filterState_t* first = dict_lookup(past->states, "filter");
1155 if (first) //should always be true.
1156 return filterState_differs(first, frame);
1157 syntaxerror("no history found to predict changes for parameter filter.\n");
1158 return 0;
1161 FILTERLIST* history_filterValue(history_t* past, U16 frame)
1163 filterState_t* first = dict_lookup(past->states, "filter");
1164 if (first) //should always be true.
1165 return filterState_value(first, frame);
1166 syntaxerror("no history found to get a value for parameter filter.\n");
1167 return 0;