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
;
68 int previous_frames
= 0, state_frames
, new_frames
;
73 previous_frames
= state
->frame
- previous
->frame
;
77 state
->next
= newState
;
78 new_frames
= newState
->frame
- state
->frame
;
79 if (state
->function
== CF_SCHANGE
)
81 state_frames
= state
->frame
- previous
->frame
;
84 if (previous
->function
== CF_SCHANGE
)
85 m0
= (3 * previous
->spline
.a
+ 2 * previous
->spline
.b
+ previous
->spline
.c
) * state_frames
/ previous_frames
;
87 if (previous
->function
== CF_CHANGE
|| previous
->function
== CF_SWEEP
)
88 m0
= state_tangent(start
, previous
->frame
, T_BEFORE
) * state_frames
;
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
);
94 if (newState
->function
== CF_CHANGE
|| newState
->function
== CF_SWEEP
)
95 m1
= state_tangent(previous
, state
->frame
, T_AFTER
) * state_frames
;
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
)
108 p1
= newState
->value
;
109 if (state
->function
== CF_SCHANGE
)
112 if (state
->function
== CF_CHANGE
|| state
->function
== CF_SWEEP
)
113 m0
= state_tangent(start
, state
->frame
, T_BEFORE
) * new_frames
;
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
)
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
)
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
;
191 return a
->cX
+ a
->r
* cos(angle
);
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
;
207 if (modification
->frame
== frame
)
209 return (modification
->function
!= CF_JUMP
);
212 float state_tangent(state_t
* modification
, U16 frame
, int tangent
)
214 float deltaFrame
= 0.1;
218 return (state_value(modification
, frame
) - state_value(modification
, frame
- deltaFrame
)) / deltaFrame
;
220 return (state_value(modification
, frame
+ deltaFrame
) - state_value(modification
, frame
)) / deltaFrame
;
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
;
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
)
249 return modification
->value
;
252 float fraction
= (frame
- previous
->frame
) / (float)(modification
->frame
- previous
->frame
);
253 return interpolateScalar(previous
->value
, modification
->value
, fraction
, modification
->interpolation
);
257 float fraction
= (frame
- previous
->frame
) / (float)(modification
->frame
- previous
->frame
);
258 fraction
= interpolateScalar(0, 1, fraction
, modification
->interpolation
);
259 return calculateSpline(modification
, fraction
);
263 float fraction
= (frame
- previous
->frame
) / (float)(modification
->frame
- previous
->frame
);
264 fraction
= interpolateScalar(0, 1, fraction
, modification
->interpolation
);
265 return calculateSweep(modification
, fraction
);
268 return previous
->value
;
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
;
285 void filterState_free(filterState_t
*change
)
288 filterState_free(change
->next
);
293 void filterState_init(filterState_t
* change
)
295 memset(change
, 0, sizeof(filterState_t
));
298 void filterState_append(filterState_t
* first
, filterState_t
* newChange
)
302 if (!first
->value
|| !newChange
->value
)
303 first
->next
= newChange
;
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
++)
311 if (newChange
->value
->filter
[i
]->type
!= first
->value
->filter
[i
]->type
)
314 mergedCount
= mergedCount
+ first
->value
->num
- common
+ newChange
->value
->num
- common
;
320 list1
= (char*)malloc(1);
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
]);
332 list2
= (char*)malloc(1);
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
);
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
)
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
);
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");
366 GRADIENT
* g
= (GRADIENT
*) malloc(sizeof(GRADIENT
));
367 g
->ratios
= rfx_calloc(16*sizeof(U8
));
368 g
->rgba
= rfx_calloc(16*sizeof(RGBA
));
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
);
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
));
391 g
->ratios
[0] = g
->ratios
[1] / 2;
392 g
->rgba
[0] = g
->rgba
[1];
397 g
->ratios
[pos
] = (255 + g
->ratios
[g
->num
- 1]) / 2;
398 g
->rgba
[pos
] = g
->rgba
[pos
- 1];
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);
408 void insertOptimalNode(GRADIENT
* g
)
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
];
422 next_gap
= 255 - g
->ratios
[g
->num
-1];
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
)
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
);
451 if (g1
->num
< g2
->num
)
453 copyGradient(&g
, g1
);
454 growGradient(&g
, g2
->num
);
455 GRADIENT
* result
= interpolateNodes(&g
, g2
, fraction
, inter
);
461 return interpolateNodes(g1
, g2
, fraction
, inter
);
464 FILTER
* copyFilter(FILTER
* original
)
468 FILTER
* copy
= swf_NewFilter(original
->type
);
469 switch (original
->type
)
471 case FILTERTYPE_BLUR
:
472 memcpy(copy
, original
, sizeof(FILTER_BLUR
));
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
);
484 case FILTERTYPE_DROPSHADOW
:
485 memcpy(copy
, original
, sizeof(FILTER_DROPSHADOW
));
487 case FILTERTYPE_BEVEL
:
488 memcpy(copy
, original
, sizeof(FILTER_BEVEL
));
490 default: syntaxerror("Internal error: unsupported filterype, cannot 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
;
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
);
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
;
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
);
546 if (f2
== noDropshadow
)
547 matchDropshadowFlags(f
, f1
);
550 matchDropshadowFlags(f
, f2
);
552 matchDropshadowFlags(f
, f1
);
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
;
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
);
589 matchBevelFlags(f
, f2
);
593 matchBevelFlags(f
, f1
);
596 matchBevelFlags(f
, f2
);
598 matchBevelFlags(f
, f1
);
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
;
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
);
638 if (f2
== noGradientGlow
)
639 matchGradientGlowFlags(f
, f1
);
642 matchGradientGlowFlags(f
, f2
);
644 matchGradientGlowFlags(f
, f1
);
648 FILTER
* interpolateFilter(FILTER
* filter1
,FILTER
* filter2
, float ratio
, interpolation_t
* inter
)
650 if(!filter1
&& !filter2
)
655 filter_type
= filter2
->type
;
658 filter_type
= filter1
->type
;
660 if(filter2
->type
!= filter1
->type
)
661 syntaxerror("can't interpolate between %s and %s filters yet", filtername
[filter1
->type
], filtername
[filter2
->type
]);
663 filter_type
= filter1
->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
);
676 syntaxerror("Filtertype %s not supported yet.\n", filtername
[filter1
->type
]);
681 FILTERLIST
* copyFilterList(FILTERLIST
* original
)
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
]);
693 FILTER
* noFilter(int type
)
697 case FILTERTYPE_BLUR
:
698 return (FILTER
*)noBlur
;
700 case FILTERTYPE_BEVEL
:
701 return (FILTER
*)noBevel
;
703 case FILTERTYPE_DROPSHADOW
:
704 return (FILTER
*)noDropshadow
;
706 case FILTERTYPE_GRADIENTGLOW
:
707 return (FILTER
*)noGradientGlow
;
710 syntaxerror("Internal error: unsupported filtertype, cannot match filterlists");
715 FILTERLIST
* interpolateFilterList(FILTERLIST
* list1
, FILTERLIST
* list2
, float ratio
, interpolation_t
* inter
)
717 if (!list1
&& !list2
)
719 FILTERLIST start
, target
, dummy
;
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
];
737 target
.filter
[j
] = noFilter(list1
->filter
[i
]->type
);
739 start
.filter
[j
] = noFilter(list2
->filter
[i
]->type
);
740 target
.filter
[j
] = list2
->filter
[i
];
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
);
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
];
760 FILTERLIST
* mixedList
= (FILTERLIST
*)malloc(sizeof(FILTERLIST
));
762 for (i
= 0; i
< j
; i
++)
763 mixedList
->filter
[i
] = interpolateFilter(start
.filter
[i
], target
.filter
[i
], ratio
, inter
);
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
;
777 if (modification
->frame
== frame
)
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
;
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
)
805 return copyFilterList(modification
->value
);
808 float fraction
= (frame
- previous
->frame
) / (float)(modification
->frame
- previous
->frame
);
809 return interpolateFilterList(previous
->value
, modification
->value
, fraction
, modification
->interpolation
);
812 return copyFilterList(previous
->value
);
818 history_t
* history_new()
820 history_t
* newHistory
= (history_t
*)malloc(sizeof(history_t
));
821 history_init(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
);
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
);
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
);
894 return acos(dX
/ radius
);
896 return 2 * M_PI
- acos(dX
/ radius
);
899 return M_PI
- acos(-dX
/ radius
);
901 return M_PI
+ acos(-dX
/ radius
);
904 static float getDeltaAngle(float angle1
, float angle2
, int clockwise
)
909 return angle2
- angle1
;
911 return angle2
- angle1
- 2 * M_PI
;
916 return 2 * M_PI
- angle1
+ angle2
;
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
;
927 past
->lastFrame
= frame
;
928 state_t
* change
= dict_lookup(past
->states
, "x");
929 if (change
) //should always be true
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
939 change
= change
->next
;
940 lastY
= change
->value
;
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);
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
));
963 if (dY
== 0) //horizontal
965 c1X
= c2X
= (lastX
+ x
) / 2;
966 c1Y
= y
+sqrt(r
* r
- (c1X
- x
) * (c1X
- x
));
971 c1X
= sqrt((r
* r
- (dX
* dX
+ dY
* dY
) / 4) / (1 + dX
* dX
/ dY
/ dY
));
973 c1Y
= -dX
/ dY
* c1X
;
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
))
991 angle1
= getAngle(lastX
- c2X
, lastY
- c2Y
);
992 angle2
= getAngle(x
- c2X
, y
- c2Y
);
993 delta_angle
= getDeltaAngle(angle1
, angle2
, clockwise
);
997 change
= dict_lookup(past
->states
, "x");
998 state_t
* nextX
= state_new(frame
, CF_SWEEP
, x
, inter
);
1000 nextX
->arc
.angle
= angle1
;
1001 nextX
->arc
.delta_angle
= delta_angle
;
1002 nextX
->arc
.cX
= centerX
;
1003 nextX
->arc
.cY
= centerY
;
1005 state_append(change
, nextX
);
1006 change
= dict_lookup(past
->states
, "y");
1007 state_t
* nextY
= state_new(frame
, CF_SWEEP
, y
, inter
);
1009 nextY
->arc
.angle
= angle1
;
1010 nextY
->arc
.delta_angle
= delta_angle
;
1011 nextY
->arc
.cX
= centerX
;
1012 nextY
->arc
.cY
= centerY
;
1014 state_append(change
, nextY
);
1017 syntaxerror("Internal error: changing parameter y in sweep, which is unknown for the instance.");
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
);
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");
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
)
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
);
1068 while (dx
== 0 && dy
== 0 && onFrame
< past
->lastFrame
);
1069 if (onFrame
== past
->lastFrame
)
1070 nextState
->params
.pathAngle
= 0;
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
);
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
);
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
)
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);
1138 while (dx
== 0 && dy
== 0 && frame
> past
->firstFrame
);
1139 if (frame
== past
->firstFrame
)
1142 pathAngle
= getAngle(dx
, dy
) / M_PI
* 180;
1143 return angle
+ flags
->params
.instanceAngle
+ pathAngle
- flags
->params
.pathAngle
;
1148 syntaxerror("no history found to get a value for parameter rotate.\n");
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");
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");