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 */
24 #include "swfc-history.h"
26 change_t* change_new(U16 frame, int function, float value, interpolation_t* inter)
28 change_t* newChange = (change_t*)malloc(sizeof(change_t));
29 change_init(newChange);
30 newChange->frame = frame;
31 newChange->function = function;
32 newChange->value = value;
33 newChange->interpolation = inter;
37 void change_free(change_t *change)
40 change_free(change->next);
44 void change_init(change_t* change)
46 memset(change, 0, sizeof(change_t));
49 void change_append(change_t* first, change_t* newChange)
51 change_t* previous = 0;
52 change_t* start = first;
60 first->next = newChange;
61 if (first->function == CF_QCHANGE)
65 if (previous->function == CF_QCHANGE)
66 m0 = (3 * previous->spline.a + 2 * previous->spline.b + previous->spline.c);
68 if (previous->function == CF_CHANGE)
69 m0 = (change_value(start, previous->frame) - change_value(start, previous->frame - 1)) * (first->frame - previous->frame);
71 m0 = (first->value - previous->value);
72 if (newChange->function == CF_QCHANGE)
73 m1 = 0.5 * (newChange->value - previous->value);
75 if (newChange->function == CF_CHANGE)
76 m1 = (change_value(previous, first->frame + 1) - change_value(previous, first->frame)) * (first->frame - previous->frame);
78 m1 = (first->value - previous->value);
79 first->spline.a = 2 * p0 + m0 - 2 * p1 + m1;
80 first->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1;
84 if (newChange->function == CF_QCHANGE)
87 p1 = newChange->value;
88 if (first->function == CF_QCHANGE)
91 if (first->function == CF_CHANGE)
92 m0 = (change_value(start, first->frame) - change_value(start, first->frame - 1)) * (first->frame - previous->frame);
94 m0 = (newChange->value - first->value);
95 m1 = (newChange->value - first->value);
96 newChange->spline.a = 2 * p0 + m0 - 2 * p1 + m1;
97 newChange->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1;
98 newChange->spline.c = m0;
99 newChange->spline.d = p0;
103 float calculateSpline(change_t* modification, float fraction)
105 spline_t s = modification->spline;
106 return (((s.a * fraction) + s.b) * fraction + s.c) * fraction + s.d;
109 float interpolateScalar(float p1, float p2, float fraction, interpolation_t* inter)
112 return linear(fraction, p1, p2 - p1);
113 switch (inter->function)
115 case IF_LINEAR: return linear(fraction, p1, p2 - p1);
116 case IF_QUAD_IN: return quadIn(fraction, p1, p2 - p1);
117 case IF_QUAD_OUT: return quadOut(fraction, p1, p2 - p1);
118 case IF_QUAD_IN_OUT: return quadInOut(fraction, p1, p2 - p1);
119 case IF_CUBIC_IN: return cubicIn(fraction, p1, p2 - p1);
120 case IF_CUBIC_OUT: return cubicOut(fraction, p1, p2 - p1);
121 case IF_CUBIC_IN_OUT: return cubicInOut(fraction, p1, p2 - p1);
122 case IF_QUART_IN: return quartIn(fraction, p1, p2 - p1);
123 case IF_QUART_OUT: return quartOut(fraction, p1, p2 - p1);
124 case IF_QUART_IN_OUT: return quartInOut(fraction, p1, p2 - p1);
125 case IF_QUINT_IN: return quintIn(fraction, p1, p2 - p1);
126 case IF_QUINT_OUT: return quintOut(fraction, p1, p2 - p1);
127 case IF_QUINT_IN_OUT: return quintInOut(fraction, p1, p2 - p1);
128 case IF_CIRCLE_IN: return circleIn(fraction, p1, p2 - p1);
129 case IF_CIRCLE_OUT: return circleOut(fraction, p1, p2 - p1);
130 case IF_CIRCLE_IN_OUT: return circleInOut(fraction, p1, p2 - p1);
131 case IF_EXPONENTIAL_IN: return exponentialIn(fraction, p1, p2 - p1);
132 case IF_EXPONENTIAL_OUT: return exponentialOut(fraction, p1, p2 - p1);
133 case IF_EXPONENTIAL_IN_OUT: return exponentialInOut(fraction, p1, p2 - p1);
134 case IF_SINE_IN: return sineIn(fraction, p1, p2 - p1);
135 case IF_SINE_OUT: return sineOut(fraction, p1, p2 - p1);
136 case IF_SINE_IN_OUT: return sineInOut(fraction, p1, p2 - p1);
137 case IF_ELASTIC_IN: return elasticIn(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
138 case IF_ELASTIC_OUT: return elasticOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
139 case IF_ELASTIC_IN_OUT: return elasticInOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
140 case IF_BACK_IN: return backIn(fraction, p1, p2 - p1, inter->speed);
141 case IF_BACK_OUT: return backOut(fraction, p1, p2 - p1, inter->speed);
142 case IF_BACK_IN_OUT: return backInOut(fraction, p1, p2 - p1, inter->speed);
143 case IF_BOUNCE_IN: return bounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
144 case IF_BOUNCE_OUT: return bounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
145 case IF_BOUNCE_IN_OUT: return bounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
146 case IF_FAST_BOUNCE_IN: return fastBounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
147 case IF_FAST_BOUNCE_OUT: return fastBounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
148 case IF_FAST_BOUNCE_IN_OUT: return fastBounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
149 default: return linear(fraction, p1, p2 - p1);
153 int change_differs(change_t* modification, U16 frame)
155 change_t* previous = modification;
156 while (modification && modification->frame < frame)
158 previous = modification;
159 modification = modification->next;
163 if (modification->frame == frame)
165 return (modification->function != CF_JUMP);
168 float change_value(change_t* modification, U16 frame)
170 change_t* previous = modification;
171 while (modification && modification->frame < frame)
173 previous = modification;
174 modification = modification->next;
177 return previous->value;
178 if (modification->frame == frame)
182 previous = modification;
183 modification = modification->next;
185 while (modification && modification->frame == frame);
186 return previous->value;
188 switch (modification->function)
191 return modification->value;
194 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
195 return interpolateScalar(previous->value, modification->value, fraction, modification->interpolation);
199 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
200 return calculateSpline(modification, fraction);
203 return previous->value;
209 changeFilter_t* changeFilter_new(U16 frame, int function, FILTERLIST* value, interpolation_t* inter)
211 changeFilter_t* newChange = (changeFilter_t*)malloc(sizeof(changeFilter_t));
212 changeFilter_init(newChange);
213 newChange->frame = frame;
214 newChange->function = function;
215 newChange->value = value;
216 newChange->interpolation = inter;
220 void changeFilter_free(changeFilter_t *change)
223 changeFilter_free(change->next);
228 void changeFilter_init(changeFilter_t* change)
230 memset(change, 0, sizeof(changeFilter_t));
233 void changeFilter_append(changeFilter_t* first, changeFilter_t* newChange)
237 if (!first->value || !newChange->value)
238 first->next = newChange;
241 int i, mergedCount = 0;
242 int common = first->value->num < newChange->value->num ? first->value->num : newChange->value->num;
243 for (i = 0; i < common; i++)
246 if (newChange->value->filter[i]->type != first->value->filter[i]->type)
249 mergedCount = mergedCount + first->value->num - common + newChange->value->num - common;
255 list1 = (char*)malloc(1);
257 for (i = 0; i < first->value->num; i++)
259 newList = (char*)malloc(strlen(list1) + strlen(filtername[first->value->filter[i]->type]) + 2);
260 newList = strcat(strcat(list1, "+"), filtername[first->value->filter[i]->type]);
264 list2 = (char*)malloc(1);
266 for (i = 0; i < newChange->value->num; i++)
268 newList = (char*)malloc(strlen(list1) + strlen(filtername[newChange->value->filter[i]->type]) + 2);
269 newList = strcat(strcat(list2, "+"), filtername[newChange->value->filter[i]->type]);
273 syntaxerror("filterlists %s and %s cannot be interpolated.", list1, list2);
275 first->next = newChange;
279 RGBA interpolateColor(RGBA c1, RGBA c2, float ratio, interpolation_t* inter)
282 c.r = interpolateScalar(c1.r, c2.r, ratio, inter);
283 c.g = interpolateScalar(c1.g, c2.g, ratio, inter);
284 c.b = interpolateScalar(c1.b, c2.b, ratio, inter);
285 c.a = interpolateScalar(c1.a, c2.a, ratio, inter);
289 GRADIENT* interpolateNodes(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
291 if (g1->num != g2->num)
292 syntaxerror("Internal error: gradients are not equal in size");
295 GRADIENT* g = (GRADIENT*) malloc(sizeof(GRADIENT));
296 g->ratios = rfx_calloc(16*sizeof(U8));
297 g->rgba = rfx_calloc(16*sizeof(RGBA));
299 for (i = 0; i < g->num; i++)
301 g->ratios[i] = interpolateScalar(g1->ratios[i], g2->ratios[i], fraction, inter);
302 g->rgba[i] = interpolateColor(g1->rgba[i], g2->rgba[i], fraction, inter);
307 void copyGradient(GRADIENT* dest, GRADIENT* source)
309 dest->num = source->num;
310 memcpy(dest->ratios, source->ratios, source->num * sizeof(U8));
311 memcpy(dest->rgba, source->rgba, source->num * sizeof(RGBA));
314 void insertNode(GRADIENT* g, int pos)
316 memmove(&g->ratios[pos + 1], &g->ratios[pos], (g->num - pos) * sizeof(U8));
317 memmove(&g->rgba[pos + 1], &g->rgba[pos], (g->num - pos) * sizeof(RGBA));
320 g->ratios[0] = g->ratios[1] / 2;
321 g->rgba[0] = g->rgba[1];
326 g->ratios[pos] = (255 + g->ratios[g->num - 1]) / 2;
327 g->rgba[pos] = g->rgba[pos - 1];
331 g->ratios[pos] = (g->ratios[pos - 1] + g->ratios[pos + 1]) / 2;
332 g->rgba[pos] = interpolateColor(g->rgba[pos - 1], g->rgba[pos + 1], 0.5, 0);
337 void insertOptimalNode(GRADIENT* g)
341 int gap = g->ratios[0];
342 for (i = 0; i < g->num - 1; i++)
344 next_gap = g->ratios[i + 1] - g->ratios[i];
351 next_gap = 255 - g->ratios[g->num -1];
357 void growGradient(GRADIENT* start, int size)
359 while (start->num < size)
360 insertOptimalNode(start);
363 GRADIENT* interpolateGradient(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
367 g.ratios = rfx_calloc(16*sizeof(U8));
368 g.rgba = rfx_calloc(16*sizeof(RGBA));
370 if (g1->num > g2->num)
372 copyGradient(&g, g2);
373 growGradient(&g, g1->num);
374 GRADIENT* result = interpolateNodes(g1, &g, fraction, inter);
380 if (g1->num < g2->num)
382 copyGradient(&g, g1);
383 growGradient(&g, g2->num);
384 GRADIENT* result = interpolateNodes(&g, g2, fraction, inter);
390 return interpolateNodes(g1, g2, fraction, inter);
393 FILTER* copyFilter(FILTER* original)
397 FILTER* copy = swf_NewFilter(original->type);
398 switch (original->type)
400 case FILTERTYPE_BLUR:
401 memcpy(copy, original, sizeof(FILTER_BLUR));
403 case FILTERTYPE_GRADIENTGLOW:
405 memcpy(copy, original, sizeof(FILTER_GRADIENTGLOW));
406 FILTER_GRADIENTGLOW* ggcopy = (FILTER_GRADIENTGLOW*)copy;
407 ggcopy->gradient = (GRADIENT*)malloc(sizeof(GRADIENT));
408 ggcopy->gradient->ratios = (U8*)malloc(16 * sizeof(U8));
409 ggcopy->gradient->rgba = (RGBA*)malloc(16 * sizeof(RGBA));
410 copyGradient(ggcopy->gradient, ((FILTER_GRADIENTGLOW*)original)->gradient);
413 case FILTERTYPE_DROPSHADOW:
414 memcpy(copy, original, sizeof(FILTER_DROPSHADOW));
416 case FILTERTYPE_BEVEL:
417 memcpy(copy, original, sizeof(FILTER_BEVEL));
419 default: syntaxerror("Internal error: unsupported filterype, cannot copy");
424 FILTER* interpolateBlur(FILTER* filter1, FILTER* filter2, float ratio, interpolation_t* inter)
426 FILTER_BLUR*f1 = (FILTER_BLUR*)filter1;
427 FILTER_BLUR*f2 = (FILTER_BLUR*)filter2;
432 if(f1->blurx == f2->blurx && f1->blury == f2->blury)
433 return copyFilter(filter1);
434 FILTER_BLUR*f = (FILTER_BLUR*)swf_NewFilter(FILTERTYPE_BLUR);
435 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
436 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
437 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
441 void matchDropshadowFlags(FILTER_DROPSHADOW* unset, FILTER_DROPSHADOW* target)
443 unset->innershadow = target->innershadow;
444 unset->knockout = target->knockout;
445 unset->composite = target->composite;
448 FILTER* interpolateDropshadow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
450 FILTER_DROPSHADOW*f1 = (FILTER_DROPSHADOW*)filter1;
451 FILTER_DROPSHADOW*f2 = (FILTER_DROPSHADOW*)filter2;
456 if(!memcmp(&f1->color,&f2->color,sizeof(RGBA)) && f1->strength == f2->strength &&
457 f1->blurx == f2->blurx && f1->blury == f2->blury &&
458 f1->angle == f2->angle && f1->distance == f2->distance)
459 return copyFilter(filter1);
460 FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)swf_NewFilter(FILTERTYPE_DROPSHADOW);
461 memcpy(f, f1, sizeof(FILTER_DROPSHADOW));
462 f->color = interpolateColor(f1->color, f2->color, ratio, inter);
463 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
464 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
465 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
466 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
467 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
468 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
469 if (f1 == noDropshadow)
471 if (f2 != noDropshadow)
472 matchDropshadowFlags(f, f2);
475 if (f2 == noDropshadow)
476 matchDropshadowFlags(f, f1);
479 matchDropshadowFlags(f, f2);
481 matchDropshadowFlags(f, f1);
485 void matchBevelFlags(FILTER_BEVEL* unset, FILTER_BEVEL* target)
487 unset->innershadow = target->innershadow;
488 unset->knockout = target->knockout;
489 unset->composite = target->composite;
490 unset->ontop = target->ontop;
493 FILTER* interpolateBevel(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
495 FILTER_BEVEL*f1 = (FILTER_BEVEL*)filter1;
496 FILTER_BEVEL*f2 = (FILTER_BEVEL*)filter2;
501 if(!memcmp(&f1->shadow,&f2->shadow,sizeof(RGBA)) &&
502 !memcmp(&f1->highlight,&f2->highlight,sizeof(RGBA)) &&
503 f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
504 return copyFilter(filter1);
505 FILTER_BEVEL*f = (FILTER_BEVEL*)swf_NewFilter(FILTERTYPE_BEVEL);
506 memcpy(f, f1, sizeof(FILTER_BEVEL));
507 f->shadow = interpolateColor(f1->shadow, f2->shadow, ratio, inter);
508 f->highlight = interpolateColor(f1->highlight, f2->highlight, ratio, inter);
509 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
510 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
511 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
512 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
513 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
514 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
518 matchBevelFlags(f, f2);
522 matchBevelFlags(f, f1);
525 matchBevelFlags(f, f2);
527 matchBevelFlags(f, f1);
531 void matchGradientGlowFlags(FILTER_GRADIENTGLOW* unset, FILTER_GRADIENTGLOW* target)
533 unset->innershadow = target->innershadow;
534 unset->knockout = target->knockout;
535 unset->composite = target->composite;
536 unset->ontop = target->ontop;
539 FILTER* interpolateGradientGlow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
541 FILTER_GRADIENTGLOW*f1 = (FILTER_GRADIENTGLOW*)filter1;
542 FILTER_GRADIENTGLOW*f2 = (FILTER_GRADIENTGLOW*)filter2;
547 if(f1->gradient->num == f2->gradient->num &&
548 !memcmp(&f1->gradient->ratios,&f2->gradient->ratios,f1->gradient->num * sizeof(U8)) &&
549 !memcmp(&f1->gradient->rgba,&f2->gradient->rgba,f1->gradient->num * sizeof(RGBA)) &&
550 f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
551 return copyFilter(filter1);
552 FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW);
553 memcpy(f, f1, sizeof(FILTER_GRADIENTGLOW));
554 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
555 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
556 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
557 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
558 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
559 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
560 f->gradient= interpolateGradient(f1->gradient, f2->gradient, ratio, inter);
561 if (f1 == noGradientGlow)
563 if (f2 != noGradientGlow)
564 matchGradientGlowFlags(f, f2);
567 if (f2 == noGradientGlow)
568 matchGradientGlowFlags(f, f1);
571 matchGradientGlowFlags(f, f2);
573 matchGradientGlowFlags(f, f1);
577 FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
579 if(!filter1 && !filter2)
584 filter_type = filter2->type;
587 filter_type = filter1->type;
589 if(filter2->type != filter1->type)
590 syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]);
592 filter_type = filter1->type;
596 case FILTERTYPE_BLUR:
597 return interpolateBlur(filter1, filter2, ratio, inter);
598 case FILTERTYPE_BEVEL:
599 return interpolateBevel(filter1, filter2, ratio, inter);
600 case FILTERTYPE_DROPSHADOW:
601 return interpolateDropshadow(filter1, filter2, ratio, inter);
602 case FILTERTYPE_GRADIENTGLOW:
603 return interpolateGradientGlow(filter1, filter2, ratio, inter);
605 syntaxerror("Filtertype %s not supported yet.\n", filtername[filter1->type]);
610 FILTERLIST* copyFilterList(FILTERLIST* original)
615 FILTERLIST* copy = (FILTERLIST*)malloc(sizeof(FILTERLIST));
616 copy->num = original->num;
617 for (i = 0; i < copy->num; i++)
618 copy->filter[i] = copyFilter(original->filter[i]);
622 FILTER* noFilter(int type)
626 case FILTERTYPE_BLUR:
627 return (FILTER*)noBlur;
629 case FILTERTYPE_BEVEL:
630 return (FILTER*)noBevel;
632 case FILTERTYPE_DROPSHADOW:
633 return (FILTER*)noDropshadow;
635 case FILTERTYPE_GRADIENTGLOW:
636 return (FILTER*)noGradientGlow;
639 syntaxerror("Internal error: unsupported filtertype, cannot match filterlists");
644 FILTERLIST* interpolateFilterList(FILTERLIST* list1, FILTERLIST* list2, float ratio, interpolation_t* inter)
646 if (!list1 && !list2)
648 FILTERLIST start, target, dummy;
655 int common = list1->num < list2->num ? list1->num : list2->num;
656 for (i = 0; i < common; i++)
658 start.filter[j] = list1->filter[i];
659 if (list2->filter[i]->type == list1->filter[i]->type)
661 target.filter[j] = list2->filter[i];
666 target.filter[j] = noFilter(list1->filter[i]->type);
668 start.filter[j] = noFilter(list2->filter[i]->type);
669 target.filter[j] = list2->filter[i];
673 if (list1->num > common)
674 for (i = common; i < list1->num; i++)
676 start.filter[j] = list1->filter[i];
677 target.filter[j] = noFilter(list1->filter[i]->type);
680 if (list2->num > common)
681 for (i = common; i < list2->num; i++)
683 start.filter[j] = noFilter(list2->filter[i]->type);
684 target.filter[j] = list2->filter[i];
689 FILTERLIST* mixedList = (FILTERLIST*)malloc(sizeof(FILTERLIST));
691 for (i = 0; i < j; i++)
692 mixedList->filter[i] = interpolateFilter(start.filter[i], target.filter[i], ratio, inter);
696 int changeFilter_differs(changeFilter_t* modification, U16 frame)
698 changeFilter_t* previous = modification;
699 while (modification && modification->frame < frame)
701 previous = modification;
702 modification = modification->next;
706 if (modification->frame == frame)
708 return (modification->function != CF_JUMP);
711 FILTERLIST* changeFilter_value(changeFilter_t* modification, U16 frame)
713 changeFilter_t* previous = modification;
714 while (modification && modification->frame < frame)
716 previous = modification;
717 modification = modification->next;
720 return copyFilterList(previous->value);
721 if (modification->frame == frame)
725 previous = modification;
726 modification = modification->next;
728 while (modification && modification->frame == frame);
729 return copyFilterList(previous->value);
731 switch (modification->function)
734 return copyFilterList(modification->value);
737 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
738 return interpolateFilterList(previous->value, modification->value, fraction, modification->interpolation);
741 return copyFilterList(previous->value);
747 history_t* history_new()
749 history_t* newHistory = (history_t*)malloc(sizeof(history_t));
750 history_init(newHistory);
754 void history_free(history_t* past)
756 change_free(dictionary_lookup(past->changes, "x"));
757 change_free(dictionary_lookup(past->changes, "y"));
758 change_free(dictionary_lookup(past->changes, "scalex"));
759 change_free(dictionary_lookup(past->changes, "scaley"));
760 change_free(dictionary_lookup(past->changes, "cxform.r0"));
761 change_free(dictionary_lookup(past->changes, "cxform.g0"));
762 change_free(dictionary_lookup(past->changes, "cxform.b0"));
763 change_free(dictionary_lookup(past->changes, "cxform.a0"));
764 change_free(dictionary_lookup(past->changes, "cxform.r1"));
765 change_free(dictionary_lookup(past->changes, "cxform.g1"));
766 change_free(dictionary_lookup(past->changes, "cxform.b1"));
767 change_free(dictionary_lookup(past->changes, "cxform.a1"));
768 change_free(dictionary_lookup(past->changes, "rotate"));
769 change_free(dictionary_lookup(past->changes, "shear"));
770 change_free(dictionary_lookup(past->changes, "pivot.x"));
771 change_free(dictionary_lookup(past->changes, "pivot.y"));
772 change_free(dictionary_lookup(past->changes, "pin.x"));
773 change_free(dictionary_lookup(past->changes, "pin.y"));
774 change_free(dictionary_lookup(past->changes, "blendmode"));
775 changeFilter_free(dictionary_lookup(past->changes, "filter"));
776 dictionary_destroy(past->changes);
780 void history_init(history_t* past)
782 past->changes = (dictionary_t*)malloc(sizeof(dictionary_t));
783 dictionary_init(past->changes);
786 void history_begin(history_t* past, char* parameter, U16 frame, TAG* tag, float value)
788 change_t* first = change_new(frame, CF_PUT, value, 0);
789 past->firstTag = tag;
790 past->firstFrame = frame;
791 dictionary_put2(past->changes, parameter, first);
794 void history_beginFilter(history_t* past, U16 frame, TAG* tag, FILTERLIST* value)
796 changeFilter_t* first = changeFilter_new(frame, CF_PUT, value, 0);
797 past->firstTag = tag;
798 past->firstFrame = frame;
799 dictionary_put2(past->changes, "filter", first);
802 void history_remember(history_t* past, char* parameter, U16 frame, int function, float value, interpolation_t* inter)
804 change_t* first = dictionary_lookup(past->changes, parameter);
805 if (first) //should always be true
807 change_t* next = change_new(frame, function, value, inter);
808 change_append(first, next);
812 void history_rememberFilter(history_t* past, U16 frame, int function, FILTERLIST* value, interpolation_t* inter)
814 changeFilter_t* first = dictionary_lookup(past->changes, "filter");
815 if (first) //should always be true
817 changeFilter_t* next = changeFilter_new(frame, function, value, inter);
818 changeFilter_append(first, next);
822 int history_change(history_t* past, U16 frame, char* parameter)
824 change_t* first = dictionary_lookup(past->changes, parameter);
825 if (first) //should always be true.
826 return change_differs(first, frame);
827 printf("no history found for parameter %s\n", parameter);
831 float history_value(history_t* past, U16 frame, char* parameter)
833 change_t* first = dictionary_lookup(past->changes, parameter);
834 if (first) //should always be true.
835 return change_value(first, frame);
836 printf("no history found for parameter %s\n", parameter);
840 int history_changeFilter(history_t* past, U16 frame)
842 changeFilter_t* first = dictionary_lookup(past->changes, "filter");
843 if (first) //should always be true.
844 return changeFilter_differs(first, frame);
845 printf("no history found for parameter filter\n");
849 FILTERLIST* history_valueFilter(history_t* past, U16 frame)
851 changeFilter_t* first = dictionary_lookup(past->changes, "filter");
852 if (first) //should always be true.
853 return changeFilter_value(first, frame);
854 printf("no history found for parameter filter\n");