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"
33 state_t* state_new(U16 frame, int function, float value, interpolation_t* inter)
35 state_t* newState = (state_t*)malloc(sizeof(state_t));
37 newState->frame = frame;
38 newState->function = function;
39 newState->value = value;
40 newState->interpolation = inter;
44 void state_free(state_t* state)
47 state_free(state->next);
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)
63 void state_append(state_t* state, state_t* newState)
65 state_t* previous = 0;
66 state_t* start = state;
74 state->next = newState;
75 if (state->function == CF_SCHANGE)
79 if (previous->function == CF_SCHANGE)
80 m0 = (3 * previous->spline.a + 2 * previous->spline.b + previous->spline.c);
82 if (previous->function == CF_CHANGE || previous->function == CF_SWEEP)
83 m0 = state_tangent(start, previous->frame, T_BEFORE) * (state->frame - previous->frame);
85 m0 = (state->value - previous->value);
86 if (newState->function == CF_SCHANGE)
87 m1 = 0.5 * (newState->value - previous->value)/* * (state->frame - previous->frame) / (newState->frame - state->frame)*/;
89 if (newState->function == CF_CHANGE || newState->function == CF_SWEEP)
90 m1 = state_tangent(previous, state->frame, T_AFTER) * (state->frame - previous->frame);
92 m1 = (newState->value - state->value);
93 state->spline.a = 2 * p0 + m0 - 2 * p1 + m1;
94 state->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1;
97 // printf("p0: %f, p1: %f, m0: %f, m1: %f.\n", p0, p1, m0, m1);
98 // printf("a: %f, b: %f, c: %f, d: %f.\n", state->spline.a, state->spline.b, state->spline.c, state->spline.d);
100 if (newState->function == CF_SCHANGE)
103 p1 = newState->value;
104 if (state->function == CF_SCHANGE)
107 if (state->function == CF_CHANGE || state->function == CF_SWEEP)
108 m0 = state_tangent(start, state->frame, T_BEFORE) * (state->frame - previous->frame);
110 m0 = (newState->value - state->value);
111 m1 = (newState->value - state->value);
112 newState->spline.a = 2 * p0 + m0 - 2 * p1 + m1;
113 newState->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1;
114 newState->spline.c = m0;
115 newState->spline.d = p0;
119 void state_insert(state_t* state, state_t* newState)
121 while (state->next && state->next->frame < newState->frame)
123 newState->next = state->next;
124 state->next = newState;
125 // if this is going to be used to insert CF_SCHANGE states it will have to be extended
126 // as in state_append above. I know this is not necessary right now, so I'll be lazy.
129 float calculateSpline(state_t* modification, float fraction)
131 spline_t s = modification->spline;
132 return (((s.a * fraction) + s.b) * fraction + s.c) * fraction + s.d;
135 float interpolateScalar(float p1, float p2, float fraction, interpolation_t* inter)
138 return linear(fraction, p1, p2 - p1);
139 switch (inter->function)
141 case IF_LINEAR: return linear(fraction, p1, p2 - p1);
142 case IF_QUAD_IN: return quadIn(fraction, p1, p2 - p1, inter->slope);
143 case IF_QUAD_OUT: return quadOut(fraction, p1, p2 - p1, inter->slope);
144 case IF_QUAD_IN_OUT: return quadInOut(fraction, p1, p2 - p1, inter->slope);
145 case IF_CUBIC_IN: return cubicIn(fraction, p1, p2 - p1, inter->slope);
146 case IF_CUBIC_OUT: return cubicOut(fraction, p1, p2 - p1, inter->slope);
147 case IF_CUBIC_IN_OUT: return cubicInOut(fraction, p1, p2 - p1, inter->slope);
148 case IF_QUART_IN: return quartIn(fraction, p1, p2 - p1, inter->slope);
149 case IF_QUART_OUT: return quartOut(fraction, p1, p2 - p1, inter->slope);
150 case IF_QUART_IN_OUT: return quartInOut(fraction, p1, p2 - p1, inter->slope);
151 case IF_QUINT_IN: return quintIn(fraction, p1, p2 - p1, inter->slope);
152 case IF_QUINT_OUT: return quintOut(fraction, p1, p2 - p1, inter->slope);
153 case IF_QUINT_IN_OUT: return quintInOut(fraction, p1, p2 - p1, inter->slope);
154 case IF_CIRCLE_IN: return circleIn(fraction, p1, p2 - p1, inter->slope);
155 case IF_CIRCLE_OUT: return circleOut(fraction, p1, p2 - p1, inter->slope);
156 case IF_CIRCLE_IN_OUT: return circleInOut(fraction, p1, p2 - p1, inter->slope);
157 case IF_EXPONENTIAL_IN: return exponentialIn(fraction, p1, p2 - p1);
158 case IF_EXPONENTIAL_OUT: return exponentialOut(fraction, p1, p2 - p1);
159 case IF_EXPONENTIAL_IN_OUT: return exponentialInOut(fraction, p1, p2 - p1);
160 case IF_SINE_IN: return sineIn(fraction, p1, p2 - p1);
161 case IF_SINE_OUT: return sineOut(fraction, p1, p2 - p1);
162 case IF_SINE_IN_OUT: return sineInOut(fraction, p1, p2 - p1);
163 case IF_ELASTIC_IN: return elasticIn(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
164 case IF_ELASTIC_OUT: return elasticOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
165 case IF_ELASTIC_IN_OUT: return elasticInOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
166 case IF_BACK_IN: return backIn(fraction, p1, p2 - p1, inter->speed);
167 case IF_BACK_OUT: return backOut(fraction, p1, p2 - p1, inter->speed);
168 case IF_BACK_IN_OUT: return backInOut(fraction, p1, p2 - p1, inter->speed);
169 case IF_BOUNCE_IN: return bounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
170 case IF_BOUNCE_OUT: return bounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
171 case IF_BOUNCE_IN_OUT: return bounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
172 case IF_FAST_BOUNCE_IN: return fastBounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
173 case IF_FAST_BOUNCE_OUT: return fastBounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
174 case IF_FAST_BOUNCE_IN_OUT: return fastBounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
175 default: return linear(fraction, p1, p2 - p1);
179 float calculateSweep(state_t* modification, float fraction)
181 arc_t* a = &(modification->arc);
182 float angle = a->angle + fraction * a->delta_angle;
184 return a->cX + a->r * cos(angle);
186 return a->cY + a->r * sin(angle);
190 int state_differs(state_t* modification, U16 frame)
192 state_t* previous = modification;
193 while (modification && modification->frame < frame)
195 previous = modification;
196 modification = modification->next;
200 if (modification->frame == frame)
202 return (modification->function != CF_JUMP);
205 float state_tangent(state_t* modification, U16 frame, int tangent)
207 float deltaFrame = 0.1;
211 return (state_value(modification, frame) - state_value(modification, frame - deltaFrame)) / deltaFrame;
213 return (state_value(modification, frame + deltaFrame) - state_value(modification, frame)) / deltaFrame;
215 return (state_value(modification, frame + deltaFrame) - state_value(modification, frame - deltaFrame)) / (2 * deltaFrame);
219 float state_value(state_t* modification, float frame)
221 state_t* previous = modification;
222 while (modification && modification->frame < frame)
224 previous = modification;
225 modification = modification->next;
228 return previous->value;
229 if (modification->frame == frame)
233 previous = modification;
234 modification = modification->next;
236 while (modification && modification->frame == frame);
237 return previous->value;
239 switch (modification->function)
242 return modification->value;
245 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
246 return interpolateScalar(previous->value, modification->value, fraction, modification->interpolation);
250 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
251 fraction = interpolateScalar(0, 1, fraction, modification->interpolation);
252 return calculateSpline(modification, fraction);
256 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
257 fraction = interpolateScalar(0, 1, fraction, modification->interpolation);
258 return calculateSweep(modification, fraction);
261 return previous->value;
267 filterState_t* filterState_new(U16 frame, int function, FILTERLIST* value, interpolation_t* inter)
269 filterState_t* newChange = (filterState_t*)malloc(sizeof(filterState_t));
270 filterState_init(newChange);
271 newChange->frame = frame;
272 newChange->function = function;
273 newChange->value = value;
274 newChange->interpolation = inter;
278 void filterState_free(filterState_t *change)
281 filterState_free(change->next);
286 void filterState_init(filterState_t* change)
288 memset(change, 0, sizeof(filterState_t));
291 void filterState_append(filterState_t* first, filterState_t* newChange)
295 if (!first->value || !newChange->value)
296 first->next = newChange;
299 int i, mergedCount = 0;
300 int common = first->value->num < newChange->value->num ? first->value->num : newChange->value->num;
301 for (i = 0; i < common; i++)
304 if (newChange->value->filter[i]->type != first->value->filter[i]->type)
307 mergedCount = mergedCount + first->value->num - common + newChange->value->num - common;
313 list1 = (char*)malloc(1);
315 for (i = 0; i < first->value->num; i++)
317 newList = (char*)malloc(strlen(list1) + strlen(filtername[first->value->filter[i]->type]) + 2);
318 newList = strcat(strcat(list1, "+"), filtername[first->value->filter[i]->type]);
322 list2 = (char*)malloc(1);
324 for (i = 0; i < newChange->value->num; i++)
326 newList = (char*)malloc(strlen(list1) + strlen(filtername[newChange->value->filter[i]->type]) + 2);
327 newList = strcat(strcat(list2, "+"), filtername[newChange->value->filter[i]->type]);
331 syntaxerror("filterlists %s and %s cannot be interpolated.", list1, list2);
333 first->next = newChange;
337 RGBA interpolateColor(RGBA c1, RGBA c2, float ratio, interpolation_t* inter)
340 c.r = interpolateScalar(c1.r, c2.r, ratio, inter);
341 c.g = interpolateScalar(c1.g, c2.g, ratio, inter);
342 c.b = interpolateScalar(c1.b, c2.b, ratio, inter);
343 c.a = interpolateScalar(c1.a, c2.a, ratio, inter);
347 GRADIENT* interpolateNodes(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
349 if (g1->num != g2->num)
350 syntaxerror("Internal error: gradients are not equal in size");
353 GRADIENT* g = (GRADIENT*) malloc(sizeof(GRADIENT));
354 g->ratios = rfx_calloc(16*sizeof(U8));
355 g->rgba = rfx_calloc(16*sizeof(RGBA));
357 for (i = 0; i < g->num; i++)
359 g->ratios[i] = interpolateScalar(g1->ratios[i], g2->ratios[i], fraction, inter);
360 g->rgba[i] = interpolateColor(g1->rgba[i], g2->rgba[i], fraction, inter);
365 void copyGradient(GRADIENT* dest, GRADIENT* source)
367 dest->num = source->num;
368 memcpy(dest->ratios, source->ratios, source->num * sizeof(U8));
369 memcpy(dest->rgba, source->rgba, source->num * sizeof(RGBA));
372 void insertNode(GRADIENT* g, int pos)
374 memmove(&g->ratios[pos + 1], &g->ratios[pos], (g->num - pos) * sizeof(U8));
375 memmove(&g->rgba[pos + 1], &g->rgba[pos], (g->num - pos) * sizeof(RGBA));
378 g->ratios[0] = g->ratios[1] / 2;
379 g->rgba[0] = g->rgba[1];
384 g->ratios[pos] = (255 + g->ratios[g->num - 1]) / 2;
385 g->rgba[pos] = g->rgba[pos - 1];
389 g->ratios[pos] = (g->ratios[pos - 1] + g->ratios[pos + 1]) / 2;
390 g->rgba[pos] = interpolateColor(g->rgba[pos - 1], g->rgba[pos + 1], 0.5, 0);
395 void insertOptimalNode(GRADIENT* g)
399 int gap = g->ratios[0];
400 for (i = 0; i < g->num - 1; i++)
402 next_gap = g->ratios[i + 1] - g->ratios[i];
409 next_gap = 255 - g->ratios[g->num -1];
415 void growGradient(GRADIENT* start, int size)
417 while (start->num < size)
418 insertOptimalNode(start);
421 GRADIENT* interpolateGradient(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
425 g.ratios = rfx_calloc(16*sizeof(U8));
426 g.rgba = rfx_calloc(16*sizeof(RGBA));
428 if (g1->num > g2->num)
430 copyGradient(&g, g2);
431 growGradient(&g, g1->num);
432 GRADIENT* result = interpolateNodes(g1, &g, fraction, inter);
438 if (g1->num < g2->num)
440 copyGradient(&g, g1);
441 growGradient(&g, g2->num);
442 GRADIENT* result = interpolateNodes(&g, g2, fraction, inter);
448 return interpolateNodes(g1, g2, fraction, inter);
451 FILTER* copyFilter(FILTER* original)
455 FILTER* copy = swf_NewFilter(original->type);
456 switch (original->type)
458 case FILTERTYPE_BLUR:
459 memcpy(copy, original, sizeof(FILTER_BLUR));
461 case FILTERTYPE_GRADIENTGLOW:
463 memcpy(copy, original, sizeof(FILTER_GRADIENTGLOW));
464 FILTER_GRADIENTGLOW* ggcopy = (FILTER_GRADIENTGLOW*)copy;
465 ggcopy->gradient = (GRADIENT*)malloc(sizeof(GRADIENT));
466 ggcopy->gradient->ratios = (U8*)malloc(16 * sizeof(U8));
467 ggcopy->gradient->rgba = (RGBA*)malloc(16 * sizeof(RGBA));
468 copyGradient(ggcopy->gradient, ((FILTER_GRADIENTGLOW*)original)->gradient);
471 case FILTERTYPE_DROPSHADOW:
472 memcpy(copy, original, sizeof(FILTER_DROPSHADOW));
474 case FILTERTYPE_BEVEL:
475 memcpy(copy, original, sizeof(FILTER_BEVEL));
477 default: syntaxerror("Internal error: unsupported filterype, cannot copy");
482 FILTER* interpolateBlur(FILTER* filter1, FILTER* filter2, float ratio, interpolation_t* inter)
484 FILTER_BLUR*f1 = (FILTER_BLUR*)filter1;
485 FILTER_BLUR*f2 = (FILTER_BLUR*)filter2;
490 if(f1->blurx == f2->blurx && f1->blury == f2->blury)
491 return copyFilter(filter1);
492 FILTER_BLUR*f = (FILTER_BLUR*)swf_NewFilter(FILTERTYPE_BLUR);
493 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
494 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
495 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
499 void matchDropshadowFlags(FILTER_DROPSHADOW* unset, FILTER_DROPSHADOW* target)
501 unset->innershadow = target->innershadow;
502 unset->knockout = target->knockout;
503 unset->composite = target->composite;
506 FILTER* interpolateDropshadow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
508 FILTER_DROPSHADOW*f1 = (FILTER_DROPSHADOW*)filter1;
509 FILTER_DROPSHADOW*f2 = (FILTER_DROPSHADOW*)filter2;
514 if(!memcmp(&f1->color,&f2->color,sizeof(RGBA)) && f1->strength == f2->strength &&
515 f1->blurx == f2->blurx && f1->blury == f2->blury &&
516 f1->angle == f2->angle && f1->distance == f2->distance)
517 return copyFilter(filter1);
518 FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)swf_NewFilter(FILTERTYPE_DROPSHADOW);
519 memcpy(f, f1, sizeof(FILTER_DROPSHADOW));
520 f->color = interpolateColor(f1->color, f2->color, ratio, inter);
521 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
522 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
523 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
524 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
525 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
526 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
527 if (f1 == noDropshadow)
529 if (f2 != noDropshadow)
530 matchDropshadowFlags(f, f2);
533 if (f2 == noDropshadow)
534 matchDropshadowFlags(f, f1);
537 matchDropshadowFlags(f, f2);
539 matchDropshadowFlags(f, f1);
543 void matchBevelFlags(FILTER_BEVEL* unset, FILTER_BEVEL* target)
545 unset->innershadow = target->innershadow;
546 unset->knockout = target->knockout;
547 unset->composite = target->composite;
548 unset->ontop = target->ontop;
551 FILTER* interpolateBevel(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
553 FILTER_BEVEL*f1 = (FILTER_BEVEL*)filter1;
554 FILTER_BEVEL*f2 = (FILTER_BEVEL*)filter2;
559 if(!memcmp(&f1->shadow,&f2->shadow,sizeof(RGBA)) &&
560 !memcmp(&f1->highlight,&f2->highlight,sizeof(RGBA)) &&
561 f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
562 return copyFilter(filter1);
563 FILTER_BEVEL*f = (FILTER_BEVEL*)swf_NewFilter(FILTERTYPE_BEVEL);
564 memcpy(f, f1, sizeof(FILTER_BEVEL));
565 f->shadow = interpolateColor(f1->shadow, f2->shadow, ratio, inter);
566 f->highlight = interpolateColor(f1->highlight, f2->highlight, ratio, inter);
567 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
568 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
569 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
570 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
571 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
572 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
576 matchBevelFlags(f, f2);
580 matchBevelFlags(f, f1);
583 matchBevelFlags(f, f2);
585 matchBevelFlags(f, f1);
589 void matchGradientGlowFlags(FILTER_GRADIENTGLOW* unset, FILTER_GRADIENTGLOW* target)
591 unset->innershadow = target->innershadow;
592 unset->knockout = target->knockout;
593 unset->composite = target->composite;
594 unset->ontop = target->ontop;
597 FILTER* interpolateGradientGlow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
599 FILTER_GRADIENTGLOW*f1 = (FILTER_GRADIENTGLOW*)filter1;
600 FILTER_GRADIENTGLOW*f2 = (FILTER_GRADIENTGLOW*)filter2;
605 if(f1->gradient->num == f2->gradient->num &&
606 !memcmp(&f1->gradient->ratios,&f2->gradient->ratios,f1->gradient->num * sizeof(U8)) &&
607 !memcmp(&f1->gradient->rgba,&f2->gradient->rgba,f1->gradient->num * sizeof(RGBA)) &&
608 f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
609 return copyFilter(filter1);
610 FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW);
611 memcpy(f, f1, sizeof(FILTER_GRADIENTGLOW));
612 f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter);
613 f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter);
614 f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter);
615 f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter);
616 f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter);
617 f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter);
618 f->gradient= interpolateGradient(f1->gradient, f2->gradient, ratio, inter);
619 if (f1 == noGradientGlow)
621 if (f2 != noGradientGlow)
622 matchGradientGlowFlags(f, f2);
625 if (f2 == noGradientGlow)
626 matchGradientGlowFlags(f, f1);
629 matchGradientGlowFlags(f, f2);
631 matchGradientGlowFlags(f, f1);
635 FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
637 if(!filter1 && !filter2)
642 filter_type = filter2->type;
645 filter_type = filter1->type;
647 if(filter2->type != filter1->type)
648 syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]);
650 filter_type = filter1->type;
654 case FILTERTYPE_BLUR:
655 return interpolateBlur(filter1, filter2, ratio, inter);
656 case FILTERTYPE_BEVEL:
657 return interpolateBevel(filter1, filter2, ratio, inter);
658 case FILTERTYPE_DROPSHADOW:
659 return interpolateDropshadow(filter1, filter2, ratio, inter);
660 case FILTERTYPE_GRADIENTGLOW:
661 return interpolateGradientGlow(filter1, filter2, ratio, inter);
663 syntaxerror("Filtertype %s not supported yet.\n", filtername[filter1->type]);
668 FILTERLIST* copyFilterList(FILTERLIST* original)
673 FILTERLIST* copy = (FILTERLIST*)malloc(sizeof(FILTERLIST));
674 copy->num = original->num;
675 for (i = 0; i < copy->num; i++)
676 copy->filter[i] = copyFilter(original->filter[i]);
680 FILTER* noFilter(int type)
684 case FILTERTYPE_BLUR:
685 return (FILTER*)noBlur;
687 case FILTERTYPE_BEVEL:
688 return (FILTER*)noBevel;
690 case FILTERTYPE_DROPSHADOW:
691 return (FILTER*)noDropshadow;
693 case FILTERTYPE_GRADIENTGLOW:
694 return (FILTER*)noGradientGlow;
697 syntaxerror("Internal error: unsupported filtertype, cannot match filterlists");
702 FILTERLIST* interpolateFilterList(FILTERLIST* list1, FILTERLIST* list2, float ratio, interpolation_t* inter)
704 if (!list1 && !list2)
706 FILTERLIST start, target, dummy;
713 int common = list1->num < list2->num ? list1->num : list2->num;
714 for (i = 0; i < common; i++)
716 start.filter[j] = list1->filter[i];
717 if (list2->filter[i]->type == list1->filter[i]->type)
719 target.filter[j] = list2->filter[i];
724 target.filter[j] = noFilter(list1->filter[i]->type);
726 start.filter[j] = noFilter(list2->filter[i]->type);
727 target.filter[j] = list2->filter[i];
731 if (list1->num > common)
732 for (i = common; i < list1->num; i++)
734 start.filter[j] = list1->filter[i];
735 target.filter[j] = noFilter(list1->filter[i]->type);
738 if (list2->num > common)
739 for (i = common; i < list2->num; i++)
741 start.filter[j] = noFilter(list2->filter[i]->type);
742 target.filter[j] = list2->filter[i];
747 FILTERLIST* mixedList = (FILTERLIST*)malloc(sizeof(FILTERLIST));
749 for (i = 0; i < j; i++)
750 mixedList->filter[i] = interpolateFilter(start.filter[i], target.filter[i], ratio, inter);
754 int filterState_differs(filterState_t* modification, U16 frame)
756 filterState_t* previous = modification;
757 while (modification && modification->frame < frame)
759 previous = modification;
760 modification = modification->next;
764 if (modification->frame == frame)
766 return (modification->function != CF_JUMP);
769 FILTERLIST* filterState_value(filterState_t* modification, U16 frame)
771 filterState_t* previous = modification;
772 while (modification && modification->frame < frame)
774 previous = modification;
775 modification = modification->next;
778 return copyFilterList(previous->value);
779 if (modification->frame == frame)
783 previous = modification;
784 modification = modification->next;
786 while (modification && modification->frame == frame);
787 return copyFilterList(previous->value);
789 switch (modification->function)
792 return copyFilterList(modification->value);
795 float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame);
796 return interpolateFilterList(previous->value, modification->value, fraction, modification->interpolation);
799 return copyFilterList(previous->value);
805 history_t* history_new()
807 history_t* newHistory = (history_t*)malloc(sizeof(history_t));
808 history_init(newHistory);
812 void history_free(history_t* past)
814 state_free(dictionary_lookup(past->states, "x"));
815 state_free(dictionary_lookup(past->states, "y"));
816 state_free(dictionary_lookup(past->states, "scalex"));
817 state_free(dictionary_lookup(past->states, "scaley"));
818 state_free(dictionary_lookup(past->states, "cxform.r0"));
819 state_free(dictionary_lookup(past->states, "cxform.g0"));
820 state_free(dictionary_lookup(past->states, "cxform.b0"));
821 state_free(dictionary_lookup(past->states, "cxform.a0"));
822 state_free(dictionary_lookup(past->states, "cxform.r1"));
823 state_free(dictionary_lookup(past->states, "cxform.g1"));
824 state_free(dictionary_lookup(past->states, "cxform.b1"));
825 state_free(dictionary_lookup(past->states, "cxform.a1"));
826 state_free(dictionary_lookup(past->states, "rotate"));
827 state_free(dictionary_lookup(past->states, "shear"));
828 state_free(dictionary_lookup(past->states, "pivot.x"));
829 state_free(dictionary_lookup(past->states, "pivot.y"));
830 state_free(dictionary_lookup(past->states, "pin.x"));
831 state_free(dictionary_lookup(past->states, "pin.y"));
832 state_free(dictionary_lookup(past->states, "blendmode"));
833 state_free(dictionary_lookup(past->states, "flags"));
834 filterState_free(dictionary_lookup(past->states, "filter"));
835 dictionary_destroy(past->states);
839 void history_init(history_t* past)
841 past->states = (dictionary_t*)malloc(sizeof(dictionary_t));
842 dictionary_init(past->states);
845 void history_begin(history_t* past, char* parameter, U16 frame, TAG* tag, float value)
847 state_t* first = state_new(frame, CF_PUT, value, 0);
848 past->firstTag = tag;
849 past->firstFrame = frame;
850 dictionary_put2(past->states, parameter, first);
853 void history_beginFilter(history_t* past, U16 frame, TAG* tag, FILTERLIST* value)
855 filterState_t* first = filterState_new(frame, CF_PUT, value, 0);
856 past->firstTag = tag;
857 past->firstFrame = frame;
858 dictionary_put2(past->states, "filter", first);
861 void history_remember(history_t* past, char* parameter, U16 frame, int function, float value, interpolation_t* inter)
863 past->lastFrame = frame;
864 state_t* state = dictionary_lookup(past->states, parameter);
865 if (state) //should always be true
867 state_t* next = state_new(frame, function, value, inter);
868 state_append(state, next);
871 syntaxerror("Internal error: changing parameter %s, which is unknown for the instance.", parameter);
874 static float getAngle(float dX, float dY)
876 float radius = sqrt(dX * dX + dY * dY);
881 return acos(dX / radius);
883 return 2 * M_PI - acos(dX / radius);
886 return M_PI - acos(-dX / radius);
888 return M_PI + acos(-dX / radius);
891 static float getDeltaAngle(float angle1, float angle2, int clockwise)
896 return angle2 - angle1;
898 return angle2 - angle1 - 2 * M_PI;
903 return 2 * M_PI - angle1 + angle2;
905 return angle2 - angle1;
909 void history_rememberSweep(history_t* past, U16 frame, float x, float y, float r, int clockwise, int short_arc, interpolation_t* inter)
911 float lastX, lastY, dX, dY;
914 past->lastFrame = frame;
915 state_t* change = dictionary_lookup(past->states, "x");
916 if (change) //should always be true
919 change = change->next;
920 lastFrame = change->frame;
921 lastX = change->value;
922 change = dictionary_lookup(past->states, "y");
923 if (change) //should always be true
926 change = change->next;
927 lastY = change->value;
930 if (dX == 0 && dY == 0)
931 syntaxerror("sweep not possible: startpoint and endpoint must not be equal");
932 if ((dX) * (dX) + (dY) * (dY) > 4 * r * r)
933 syntaxerror("sweep not possible: radius is to small");
934 if (change->frame > lastFrame)
936 lastFrame = change->frame;
937 history_remember(past, "x", lastFrame, CF_JUMP, lastX, 0);
940 if (change->frame < lastFrame)
941 history_remember(past, "y", lastFrame, CF_JUMP, lastY, 0);
942 float c1X, c1Y, c2X, c2Y;
943 if (dX == 0) //vertical
945 c1Y = c2Y = (lastY + y) / 2;
946 c1X = x + sqrt(r * r - (c1Y - y) * (c1Y - y));
950 if (dY == 0) //horizontal
952 c1X = c2X = (lastX + x) / 2;
953 c1Y = y +sqrt(r * r - (c1X - x) * (c1X - x));
958 c1X = sqrt((r * r - (dX * dX + dY * dY) / 4) / (1 + dX * dX / dY / dY));
960 c1Y = -dX / dY * c1X;
962 c1X += (x + lastX) / 2;
963 c2X += (x + lastX) / 2;
964 c1Y += (y + lastY) / 2;
965 c2Y += (y + lastY) / 2;
967 float angle1, angle2, delta_angle, centerX, centerY;
968 angle1 = getAngle(lastX - c1X, lastY - c1Y);
969 angle2 = getAngle(x - c1X, y - c1Y);
970 delta_angle = getDeltaAngle(angle1, angle2, clockwise);
971 if ((short_arc && fabs(delta_angle) <= M_PI) || (! short_arc && fabs(delta_angle) >= M_PI))
978 angle1 = getAngle(lastX - c2X, lastY - c2Y);
979 angle2 = getAngle(x - c2X, y - c2Y);
980 delta_angle = getDeltaAngle(angle1, angle2, clockwise);
984 change = dictionary_lookup(past->states, "x");
985 state_t* nextX = state_new(frame, CF_SWEEP, x, inter);
987 nextX->arc.angle = angle1;
988 nextX->arc.delta_angle = delta_angle;
989 nextX->arc.cX = centerX;
990 nextX->arc.cY = centerY;
992 state_append(change, nextX);
993 change = dictionary_lookup(past->states, "y");
994 state_t* nextY = state_new(frame, CF_SWEEP, y, inter);
996 nextY->arc.angle = angle1;
997 nextY->arc.delta_angle = delta_angle;
998 nextY->arc.cX = centerX;
999 nextY->arc.cY = centerY;
1001 state_append(change, nextY);
1004 syntaxerror("Internal error: changing parameter y in sweep, which is unknown for the instance.");
1007 syntaxerror("Internal error: changing parameter x in sweep, which is unknown for the instance.");
1010 void history_rememberFilter(history_t* past, U16 frame, int function, FILTERLIST* value, interpolation_t* inter)
1012 past->lastFrame = frame;
1013 filterState_t* first = dictionary_lookup(past->states, "filter");
1014 if (first) //should always be true
1016 filterState_t* next = filterState_new(frame, function, value, inter);
1017 filterState_append(first, next);
1020 syntaxerror("Internal error: changing a filter not set for the instance.");
1023 void history_processFlags(history_t* past)
1024 // to be called after completely recording this history, before calculating any values.
1026 state_t* flagState = dictionary_lookup(past->states, "flags");
1028 U16 nextFlags, toggledFlags, currentFlags = (U16)flagState->value;
1029 while (flagState->next)
1031 nextState = flagState->next;
1032 nextFlags = (U16)nextState->value;
1033 toggledFlags = currentFlags ^ nextFlags;
1034 if (toggledFlags & IF_FIXED_ALIGNMENT)
1035 { // the IF_FIXED_ALIGNMENT bit will change in the next state
1036 if (nextFlags & IF_FIXED_ALIGNMENT)
1037 { // the IF_FIXED_ALIGNMENT bit will be set
1038 int onFrame = nextState->frame;
1039 state_t* rotations = dictionary_lookup(past->states, "rotate");
1040 nextState->params.instanceAngle = state_value(rotations, onFrame);
1041 state_t* resetRotate = state_new(onFrame, CF_JUMP, 0, 0);
1042 state_insert(rotations, resetRotate);
1043 if (onFrame == past->firstFrame)
1049 x = dictionary_lookup(past->states, "x");
1050 dx = state_tangent(x, onFrame, T_SYMMETRIC);
1051 y = dictionary_lookup(past->states, "y");
1052 dy = state_tangent(y, onFrame, T_SYMMETRIC);
1055 while (dx == 0 && dy == 0 && onFrame < past->lastFrame);
1056 if (onFrame == past->lastFrame)
1057 nextState->params.pathAngle = 0;
1059 nextState->params.pathAngle = getAngle(dx, dy) / M_PI * 180;
1061 else // the IF_FIXED_ALIGNMENT bit will be reset
1063 int offFrame = nextState->frame;
1064 state_t* rotations = dictionary_lookup(past->states, "rotate");
1065 state_t* setRotate = state_new(offFrame, CF_JUMP, flagState->params.instanceAngle + state_value(rotations, offFrame), 0);
1066 state_insert(rotations, setRotate);
1069 else // the IF_FIXED_ALIGNMENT bit will not change but some processing may be
1070 // required just the same
1072 if (nextFlags & IF_FIXED_ALIGNMENT)
1074 nextState->params.instanceAngle = flagState->params.instanceAngle;
1075 nextState->params.pathAngle = flagState->params.pathAngle;
1078 // and so on for all the other bits.
1079 flagState = nextState;
1080 currentFlags = nextFlags;
1084 int history_change(history_t* past, U16 frame, char* parameter)
1086 state_t* first = dictionary_lookup(past->states, parameter);
1087 if (first) //should always be true.
1088 return state_differs(first, frame);
1089 syntaxerror("no history found to predict changes for parameter %s.\n", parameter);
1093 float history_value(history_t* past, U16 frame, char* parameter)
1095 state_t* state = dictionary_lookup(past->states, parameter);
1096 if (state) //should always be true.
1097 return state_value(state, frame);
1098 syntaxerror("no history found to get a value for parameter %s.\n", parameter);
1102 float history_rotateValue(history_t* past, U16 frame)
1104 state_t* rotations = dictionary_lookup(past->states, "rotate");
1105 if (rotations) //should always be true.
1107 float angle = state_value(rotations, frame);
1108 state_t* flags = dictionary_lookup(past->states, "flags");
1109 U16 currentflags = state_value(flags, frame);
1110 if (currentflags & IF_FIXED_ALIGNMENT)
1112 flags = state_at(flags, frame);
1113 if (frame == past->firstFrame)
1116 float dx, dy, pathAngle;
1119 x = dictionary_lookup(past->states, "x");
1120 dx = state_value(x, frame) - state_value(x, frame - 1);
1121 y = dictionary_lookup(past->states, "y");
1122 dy = state_value(y, frame) - state_value(y, frame - 1);
1125 while (dx == 0 && dy == 0 && frame > past->firstFrame);
1126 if (frame == past->firstFrame)
1129 pathAngle = getAngle(dx, dy) / M_PI * 180;
1130 return angle + flags->params.instanceAngle + pathAngle - flags->params.pathAngle;
1135 syntaxerror("no history found to get a value for parameter rotate.\n");
1139 int history_changeFilter(history_t* past, U16 frame)
1141 filterState_t* first = dictionary_lookup(past->states, "filter");
1142 if (first) //should always be true.
1143 return filterState_differs(first, frame);
1144 syntaxerror("no history found to predict changes for parameter filter.\n");
1148 FILTERLIST* history_filterValue(history_t* past, U16 frame)
1150 filterState_t* first = dictionary_lookup(past->states, "filter");
1151 if (first) //should always be true.
1152 return filterState_value(first, frame);
1153 syntaxerror("no history found to get a value for parameter filter.\n");