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 newList
= (char*)malloc(strlen(list1
) + strlen(filtername
[first
->value
->filter
[i
]->type
]) + 2);
325 strcpy(newList
, strcat(strcat(list1
, "+"), filtername
[first
->value
->filter
[i
]->type
]));
329 list2
= (char*)malloc(1);
331 for (i
= 0; i
< newChange
->value
->num
; i
++)
333 newList
= (char*)malloc(strlen(list1
) + strlen(filtername
[newChange
->value
->filter
[i
]->type
]) + 2);
334 strcpy(newList
, strcat(strcat(list2
, "+"), filtername
[newChange
->value
->filter
[i
]->type
]));
338 syntaxerror("filterlists %s and %s cannot be interpolated.", list1
, list2
);
340 first
->next
= newChange
;
344 RGBA
interpolateColor(RGBA c1
, RGBA c2
, float ratio
, interpolation_t
* inter
)
347 c
.r
= interpolateScalar(c1
.r
, c2
.r
, ratio
, inter
);
348 c
.g
= interpolateScalar(c1
.g
, c2
.g
, ratio
, inter
);
349 c
.b
= interpolateScalar(c1
.b
, c2
.b
, ratio
, inter
);
350 c
.a
= interpolateScalar(c1
.a
, c2
.a
, ratio
, inter
);
354 GRADIENT
* interpolateNodes(GRADIENT
* g1
, GRADIENT
* g2
, float fraction
, interpolation_t
* inter
)
356 if (g1
->num
!= g2
->num
)
357 syntaxerror("Internal error: gradients are not equal in size");
360 GRADIENT
* g
= (GRADIENT
*) malloc(sizeof(GRADIENT
));
361 g
->ratios
= rfx_calloc(16*sizeof(U8
));
362 g
->rgba
= rfx_calloc(16*sizeof(RGBA
));
364 for (i
= 0; i
< g
->num
; i
++)
366 g
->ratios
[i
] = interpolateScalar(g1
->ratios
[i
], g2
->ratios
[i
], fraction
, inter
);
367 g
->rgba
[i
] = interpolateColor(g1
->rgba
[i
], g2
->rgba
[i
], fraction
, inter
);
372 void copyGradient(GRADIENT
* dest
, GRADIENT
* source
)
374 dest
->num
= source
->num
;
375 memcpy(dest
->ratios
, source
->ratios
, source
->num
* sizeof(U8
));
376 memcpy(dest
->rgba
, source
->rgba
, source
->num
* sizeof(RGBA
));
379 void insertNode(GRADIENT
* g
, int pos
)
381 memmove(&g
->ratios
[pos
+ 1], &g
->ratios
[pos
], (g
->num
- pos
) * sizeof(U8
));
382 memmove(&g
->rgba
[pos
+ 1], &g
->rgba
[pos
], (g
->num
- pos
) * sizeof(RGBA
));
385 g
->ratios
[0] = g
->ratios
[1] / 2;
386 g
->rgba
[0] = g
->rgba
[1];
391 g
->ratios
[pos
] = (255 + g
->ratios
[g
->num
- 1]) / 2;
392 g
->rgba
[pos
] = g
->rgba
[pos
- 1];
396 g
->ratios
[pos
] = (g
->ratios
[pos
- 1] + g
->ratios
[pos
+ 1]) / 2;
397 g
->rgba
[pos
] = interpolateColor(g
->rgba
[pos
- 1], g
->rgba
[pos
+ 1], 0.5, 0);
402 void insertOptimalNode(GRADIENT
* g
)
406 int gap
= g
->ratios
[0];
407 for (i
= 0; i
< g
->num
- 1; i
++)
409 next_gap
= g
->ratios
[i
+ 1] - g
->ratios
[i
];
416 next_gap
= 255 - g
->ratios
[g
->num
-1];
422 void growGradient(GRADIENT
* start
, int size
)
424 while (start
->num
< size
)
425 insertOptimalNode(start
);
428 GRADIENT
* interpolateGradient(GRADIENT
* g1
, GRADIENT
* g2
, float fraction
, interpolation_t
* inter
)
432 g
.ratios
= rfx_calloc(16*sizeof(U8
));
433 g
.rgba
= rfx_calloc(16*sizeof(RGBA
));
435 if (g1
->num
> g2
->num
)
437 copyGradient(&g
, g2
);
438 growGradient(&g
, g1
->num
);
439 GRADIENT
* result
= interpolateNodes(g1
, &g
, fraction
, inter
);
445 if (g1
->num
< g2
->num
)
447 copyGradient(&g
, g1
);
448 growGradient(&g
, g2
->num
);
449 GRADIENT
* result
= interpolateNodes(&g
, g2
, fraction
, inter
);
455 return interpolateNodes(g1
, g2
, fraction
, inter
);
458 FILTER
* copyFilter(FILTER
* original
)
462 FILTER
* copy
= swf_NewFilter(original
->type
);
463 switch (original
->type
)
465 case FILTERTYPE_BLUR
:
466 memcpy(copy
, original
, sizeof(FILTER_BLUR
));
468 case FILTERTYPE_GRADIENTGLOW
:
470 memcpy(copy
, original
, sizeof(FILTER_GRADIENTGLOW
));
471 FILTER_GRADIENTGLOW
* ggcopy
= (FILTER_GRADIENTGLOW
*)copy
;
472 ggcopy
->gradient
= (GRADIENT
*)malloc(sizeof(GRADIENT
));
473 ggcopy
->gradient
->ratios
= (U8
*)malloc(16 * sizeof(U8
));
474 ggcopy
->gradient
->rgba
= (RGBA
*)malloc(16 * sizeof(RGBA
));
475 copyGradient(ggcopy
->gradient
, ((FILTER_GRADIENTGLOW
*)original
)->gradient
);
478 case FILTERTYPE_DROPSHADOW
:
479 memcpy(copy
, original
, sizeof(FILTER_DROPSHADOW
));
481 case FILTERTYPE_BEVEL
:
482 memcpy(copy
, original
, sizeof(FILTER_BEVEL
));
484 default: syntaxerror("Internal error: unsupported filterype, cannot copy");
489 FILTER
* interpolateBlur(FILTER
* filter1
, FILTER
* filter2
, float ratio
, interpolation_t
* inter
)
491 FILTER_BLUR
*f1
= (FILTER_BLUR
*)filter1
;
492 FILTER_BLUR
*f2
= (FILTER_BLUR
*)filter2
;
497 if(f1
->blurx
== f2
->blurx
&& f1
->blury
== f2
->blury
)
498 return copyFilter(filter1
);
499 FILTER_BLUR
*f
= (FILTER_BLUR
*)swf_NewFilter(FILTERTYPE_BLUR
);
500 f
->blurx
= interpolateScalar(f1
->blurx
, (f2
->blurx
), ratio
, inter
);
501 f
->blury
= interpolateScalar(f1
->blury
, (f2
->blury
), ratio
, inter
);
502 f
->passes
= interpolateScalar(f1
->passes
, (f2
->passes
), ratio
, inter
);
506 void matchDropshadowFlags(FILTER_DROPSHADOW
* unset
, FILTER_DROPSHADOW
* target
)
508 unset
->innershadow
= target
->innershadow
;
509 unset
->knockout
= target
->knockout
;
510 unset
->composite
= target
->composite
;
513 FILTER
* interpolateDropshadow(FILTER
* filter1
,FILTER
* filter2
, float ratio
, interpolation_t
* inter
)
515 FILTER_DROPSHADOW
*f1
= (FILTER_DROPSHADOW
*)filter1
;
516 FILTER_DROPSHADOW
*f2
= (FILTER_DROPSHADOW
*)filter2
;
521 if(!memcmp(&f1
->color
,&f2
->color
,sizeof(RGBA
)) && f1
->strength
== f2
->strength
&&
522 f1
->blurx
== f2
->blurx
&& f1
->blury
== f2
->blury
&&
523 f1
->angle
== f2
->angle
&& f1
->distance
== f2
->distance
)
524 return copyFilter(filter1
);
525 FILTER_DROPSHADOW
*f
= (FILTER_DROPSHADOW
*)swf_NewFilter(FILTERTYPE_DROPSHADOW
);
526 memcpy(f
, f1
, sizeof(FILTER_DROPSHADOW
));
527 f
->color
= interpolateColor(f1
->color
, f2
->color
, ratio
, inter
);
528 f
->blurx
= interpolateScalar(f1
->blurx
, (f2
->blurx
), ratio
, inter
);
529 f
->blury
= interpolateScalar(f1
->blury
, (f2
->blury
), ratio
, inter
);
530 f
->passes
= interpolateScalar(f1
->passes
, (f2
->passes
), ratio
, inter
);
531 f
->angle
= interpolateScalar(f1
->angle
, (f2
->angle
), ratio
, inter
);
532 f
->distance
= interpolateScalar(f1
->distance
, (f2
->distance
), ratio
, inter
);
533 f
->strength
= interpolateScalar(f1
->strength
, (f2
->strength
), ratio
, inter
);
534 if (f1
== noDropshadow
)
536 if (f2
!= noDropshadow
)
537 matchDropshadowFlags(f
, f2
);
540 if (f2
== noDropshadow
)
541 matchDropshadowFlags(f
, f1
);
544 matchDropshadowFlags(f
, f2
);
546 matchDropshadowFlags(f
, f1
);
550 void matchBevelFlags(FILTER_BEVEL
* unset
, FILTER_BEVEL
* target
)
552 unset
->innershadow
= target
->innershadow
;
553 unset
->knockout
= target
->knockout
;
554 unset
->composite
= target
->composite
;
555 unset
->ontop
= target
->ontop
;
558 FILTER
* interpolateBevel(FILTER
* filter1
,FILTER
* filter2
, float ratio
, interpolation_t
* inter
)
560 FILTER_BEVEL
*f1
= (FILTER_BEVEL
*)filter1
;
561 FILTER_BEVEL
*f2
= (FILTER_BEVEL
*)filter2
;
566 if(!memcmp(&f1
->shadow
,&f2
->shadow
,sizeof(RGBA
)) &&
567 !memcmp(&f1
->highlight
,&f2
->highlight
,sizeof(RGBA
)) &&
568 f1
->blurx
== f2
->blurx
&& f1
->blury
== f2
->blury
&& f1
->angle
== f2
->angle
&& f1
->strength
== f2
->strength
&& f1
->distance
== f2
->distance
)
569 return copyFilter(filter1
);
570 FILTER_BEVEL
*f
= (FILTER_BEVEL
*)swf_NewFilter(FILTERTYPE_BEVEL
);
571 memcpy(f
, f1
, sizeof(FILTER_BEVEL
));
572 f
->shadow
= interpolateColor(f1
->shadow
, f2
->shadow
, ratio
, inter
);
573 f
->highlight
= interpolateColor(f1
->highlight
, f2
->highlight
, ratio
, inter
);
574 f
->blurx
= interpolateScalar(f1
->blurx
, (f2
->blurx
), ratio
, inter
);
575 f
->blury
= interpolateScalar(f1
->blury
, (f2
->blury
), ratio
, inter
);
576 f
->passes
= interpolateScalar(f1
->passes
, (f2
->passes
), ratio
, inter
);
577 f
->angle
= interpolateScalar(f1
->angle
, (f2
->angle
), ratio
, inter
);
578 f
->distance
= interpolateScalar(f1
->distance
, (f2
->distance
), ratio
, inter
);
579 f
->strength
= interpolateScalar(f1
->strength
, (f2
->strength
), ratio
, inter
);
583 matchBevelFlags(f
, f2
);
587 matchBevelFlags(f
, f1
);
590 matchBevelFlags(f
, f2
);
592 matchBevelFlags(f
, f1
);
596 void matchGradientGlowFlags(FILTER_GRADIENTGLOW
* unset
, FILTER_GRADIENTGLOW
* target
)
598 unset
->innershadow
= target
->innershadow
;
599 unset
->knockout
= target
->knockout
;
600 unset
->composite
= target
->composite
;
601 unset
->ontop
= target
->ontop
;
604 FILTER
* interpolateGradientGlow(FILTER
* filter1
,FILTER
* filter2
, float ratio
, interpolation_t
* inter
)
606 FILTER_GRADIENTGLOW
*f1
= (FILTER_GRADIENTGLOW
*)filter1
;
607 FILTER_GRADIENTGLOW
*f2
= (FILTER_GRADIENTGLOW
*)filter2
;
612 if(f1
->gradient
->num
== f2
->gradient
->num
&&
613 !memcmp(&f1
->gradient
->ratios
,&f2
->gradient
->ratios
,f1
->gradient
->num
* sizeof(U8
)) &&
614 !memcmp(&f1
->gradient
->rgba
,&f2
->gradient
->rgba
,f1
->gradient
->num
* sizeof(RGBA
)) &&
615 f1
->blurx
== f2
->blurx
&& f1
->blury
== f2
->blury
&& f1
->angle
== f2
->angle
&& f1
->strength
== f2
->strength
&& f1
->distance
== f2
->distance
)
616 return copyFilter(filter1
);
617 FILTER_GRADIENTGLOW
*f
= (FILTER_GRADIENTGLOW
*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW
);
618 memcpy(f
, f1
, sizeof(FILTER_GRADIENTGLOW
));
619 f
->blurx
= interpolateScalar(f1
->blurx
, (f2
->blurx
), ratio
, inter
);
620 f
->blury
= interpolateScalar(f1
->blury
, (f2
->blury
), ratio
, inter
);
621 f
->passes
= interpolateScalar(f1
->passes
, (f2
->passes
), ratio
, inter
);
622 f
->angle
= interpolateScalar(f1
->angle
, (f2
->angle
), ratio
, inter
);
623 f
->distance
= interpolateScalar(f1
->distance
, (f2
->distance
), ratio
, inter
);
624 f
->strength
= interpolateScalar(f1
->strength
, (f2
->strength
), ratio
, inter
);
625 f
->gradient
= interpolateGradient(f1
->gradient
, f2
->gradient
, ratio
, inter
);
626 if (f1
== noGradientGlow
)
628 if (f2
!= noGradientGlow
)
629 matchGradientGlowFlags(f
, f2
);
632 if (f2
== noGradientGlow
)
633 matchGradientGlowFlags(f
, f1
);
636 matchGradientGlowFlags(f
, f2
);
638 matchGradientGlowFlags(f
, f1
);
642 FILTER
* interpolateFilter(FILTER
* filter1
,FILTER
* filter2
, float ratio
, interpolation_t
* inter
)
644 if(!filter1
&& !filter2
)
649 filter_type
= filter2
->type
;
652 filter_type
= filter1
->type
;
654 if(filter2
->type
!= filter1
->type
)
655 syntaxerror("can't interpolate between %s and %s filters yet", filtername
[filter1
->type
], filtername
[filter2
->type
]);
657 filter_type
= filter1
->type
;
661 case FILTERTYPE_BLUR
:
662 return interpolateBlur(filter1
, filter2
, ratio
, inter
);
663 case FILTERTYPE_BEVEL
:
664 return interpolateBevel(filter1
, filter2
, ratio
, inter
);
665 case FILTERTYPE_DROPSHADOW
:
666 return interpolateDropshadow(filter1
, filter2
, ratio
, inter
);
667 case FILTERTYPE_GRADIENTGLOW
:
668 return interpolateGradientGlow(filter1
, filter2
, ratio
, inter
);
670 syntaxerror("Filtertype %s not supported yet.\n", filtername
[filter1
->type
]);
675 FILTERLIST
* copyFilterList(FILTERLIST
* original
)
680 FILTERLIST
* copy
= (FILTERLIST
*)malloc(sizeof(FILTERLIST
));
681 copy
->num
= original
->num
;
682 for (i
= 0; i
< copy
->num
; i
++)
683 copy
->filter
[i
] = copyFilter(original
->filter
[i
]);
687 FILTER
* noFilter(int type
)
691 case FILTERTYPE_BLUR
:
692 return (FILTER
*)noBlur
;
694 case FILTERTYPE_BEVEL
:
695 return (FILTER
*)noBevel
;
697 case FILTERTYPE_DROPSHADOW
:
698 return (FILTER
*)noDropshadow
;
700 case FILTERTYPE_GRADIENTGLOW
:
701 return (FILTER
*)noGradientGlow
;
704 syntaxerror("Internal error: unsupported filtertype, cannot match filterlists");
709 FILTERLIST
* interpolateFilterList(FILTERLIST
* list1
, FILTERLIST
* list2
, float ratio
, interpolation_t
* inter
)
711 if (!list1
&& !list2
)
713 FILTERLIST start
, target
, dummy
;
720 int common
= list1
->num
< list2
->num
? list1
->num
: list2
->num
;
721 for (i
= 0; i
< common
; i
++)
723 start
.filter
[j
] = list1
->filter
[i
];
724 if (list2
->filter
[i
]->type
== list1
->filter
[i
]->type
)
726 target
.filter
[j
] = list2
->filter
[i
];
731 target
.filter
[j
] = noFilter(list1
->filter
[i
]->type
);
733 start
.filter
[j
] = noFilter(list2
->filter
[i
]->type
);
734 target
.filter
[j
] = list2
->filter
[i
];
738 if (list1
->num
> common
)
739 for (i
= common
; i
< list1
->num
; i
++)
741 start
.filter
[j
] = list1
->filter
[i
];
742 target
.filter
[j
] = noFilter(list1
->filter
[i
]->type
);
745 if (list2
->num
> common
)
746 for (i
= common
; i
< list2
->num
; i
++)
748 start
.filter
[j
] = noFilter(list2
->filter
[i
]->type
);
749 target
.filter
[j
] = list2
->filter
[i
];
754 FILTERLIST
* mixedList
= (FILTERLIST
*)malloc(sizeof(FILTERLIST
));
756 for (i
= 0; i
< j
; i
++)
757 mixedList
->filter
[i
] = interpolateFilter(start
.filter
[i
], target
.filter
[i
], ratio
, inter
);
761 int filterState_differs(filterState_t
* modification
, U16 frame
)
763 filterState_t
* previous
= modification
;
764 while (modification
&& modification
->frame
< frame
)
766 previous
= modification
;
767 modification
= modification
->next
;
771 if (modification
->frame
== frame
)
773 return (modification
->function
!= CF_JUMP
);
776 FILTERLIST
* filterState_value(filterState_t
* modification
, U16 frame
)
778 filterState_t
* previous
= modification
;
779 while (modification
&& modification
->frame
< frame
)
781 previous
= modification
;
782 modification
= modification
->next
;
785 return copyFilterList(previous
->value
);
786 if (modification
->frame
== frame
)
790 previous
= modification
;
791 modification
= modification
->next
;
793 while (modification
&& modification
->frame
== frame
);
794 return copyFilterList(previous
->value
);
796 switch (modification
->function
)
799 return copyFilterList(modification
->value
);
802 float fraction
= (frame
- previous
->frame
) / (float)(modification
->frame
- previous
->frame
);
803 return interpolateFilterList(previous
->value
, modification
->value
, fraction
, modification
->interpolation
);
806 return copyFilterList(previous
->value
);
812 history_t
* history_new()
814 history_t
* newHistory
= (history_t
*)malloc(sizeof(history_t
));
815 history_init(newHistory
);
819 void history_free(history_t
* past
)
821 state_free(dict_lookup(past
->states
, "x"));
822 state_free(dict_lookup(past
->states
, "y"));
823 state_free(dict_lookup(past
->states
, "scalex"));
824 state_free(dict_lookup(past
->states
, "scaley"));
825 state_free(dict_lookup(past
->states
, "cxform.r0"));
826 state_free(dict_lookup(past
->states
, "cxform.g0"));
827 state_free(dict_lookup(past
->states
, "cxform.b0"));
828 state_free(dict_lookup(past
->states
, "cxform.a0"));
829 state_free(dict_lookup(past
->states
, "cxform.r1"));
830 state_free(dict_lookup(past
->states
, "cxform.g1"));
831 state_free(dict_lookup(past
->states
, "cxform.b1"));
832 state_free(dict_lookup(past
->states
, "cxform.a1"));
833 state_free(dict_lookup(past
->states
, "rotate"));
834 state_free(dict_lookup(past
->states
, "shear"));
835 state_free(dict_lookup(past
->states
, "pivot.x"));
836 state_free(dict_lookup(past
->states
, "pivot.y"));
837 state_free(dict_lookup(past
->states
, "pin.x"));
838 state_free(dict_lookup(past
->states
, "pin.y"));
839 state_free(dict_lookup(past
->states
, "blendmode"));
840 state_free(dict_lookup(past
->states
, "flags"));
841 filterState_free(dict_lookup(past
->states
, "filter"));
842 dict_destroy(past
->states
);
846 void history_init(history_t
* past
)
848 past
->states
= (dict_t
*)malloc(sizeof(dict_t
));
849 dict_init(past
->states
, 16);
852 void history_begin(history_t
* past
, char* parameter
, U16 frame
, TAG
* tag
, float value
)
854 state_t
* first
= state_new(frame
, CF_PUT
, value
, 0);
855 past
->firstTag
= tag
;
856 past
->firstFrame
= frame
;
857 dict_put2(past
->states
, parameter
, first
);
860 void history_beginFilter(history_t
* past
, U16 frame
, TAG
* tag
, FILTERLIST
* value
)
862 filterState_t
* first
= filterState_new(frame
, CF_PUT
, value
, 0);
863 past
->firstTag
= tag
;
864 past
->firstFrame
= frame
;
865 dict_put2(past
->states
, "filter", first
);
868 void history_remember(history_t
* past
, char* parameter
, U16 frame
, int function
, float value
, interpolation_t
* inter
)
870 past
->lastFrame
= frame
;
871 state_t
* state
= dict_lookup(past
->states
, parameter
);
872 if (state
) //should always be true
874 state_t
* next
= state_new(frame
, function
, value
, inter
);
875 state_append(state
, next
);
878 syntaxerror("Internal error: changing parameter %s, which is unknown for the instance.", parameter
);
881 static float getAngle(float dX
, float dY
)
883 float radius
= sqrt(dX
* dX
+ dY
* dY
);
888 return acos(dX
/ radius
);
890 return 2 * M_PI
- acos(dX
/ radius
);
893 return M_PI
- acos(-dX
/ radius
);
895 return M_PI
+ acos(-dX
/ radius
);
898 static float getDeltaAngle(float angle1
, float angle2
, int clockwise
)
903 return angle2
- angle1
;
905 return angle2
- angle1
- 2 * M_PI
;
910 return 2 * M_PI
- angle1
+ angle2
;
912 return angle2
- angle1
;
916 void history_rememberSweep(history_t
* past
, U16 frame
, float x
, float y
, float r
, int clockwise
, int short_arc
, interpolation_t
* inter
)
918 float lastX
, lastY
, dX
, dY
;
921 past
->lastFrame
= frame
;
922 state_t
* change
= dict_lookup(past
->states
, "x");
923 if (change
) //should always be true
926 change
= change
->next
;
927 lastFrame
= change
->frame
;
928 lastX
= change
->value
;
929 change
= dict_lookup(past
->states
, "y");
930 if (change
) //should always be true
933 change
= change
->next
;
934 lastY
= change
->value
;
937 if (dX
== 0 && dY
== 0)
938 syntaxerror("sweep not possible: startpoint and endpoint must not be equal");
939 if ((dX
) * (dX
) + (dY
) * (dY
) > 4 * r
* r
)
940 syntaxerror("sweep not possible: radius is to small");
941 if (change
->frame
> lastFrame
)
943 lastFrame
= change
->frame
;
944 history_remember(past
, "x", lastFrame
, CF_JUMP
, lastX
, 0);
947 if (change
->frame
< lastFrame
)
948 history_remember(past
, "y", lastFrame
, CF_JUMP
, lastY
, 0);
949 float c1X
, c1Y
, c2X
, c2Y
;
950 if (dX
== 0) //vertical
952 c1Y
= c2Y
= (lastY
+ y
) / 2;
953 c1X
= x
+ sqrt(r
* r
- (c1Y
- y
) * (c1Y
- y
));
957 if (dY
== 0) //horizontal
959 c1X
= c2X
= (lastX
+ x
) / 2;
960 c1Y
= y
+sqrt(r
* r
- (c1X
- x
) * (c1X
- x
));
965 c1X
= sqrt((r
* r
- (dX
* dX
+ dY
* dY
) / 4) / (1 + dX
* dX
/ dY
/ dY
));
967 c1Y
= -dX
/ dY
* c1X
;
969 c1X
+= (x
+ lastX
) / 2;
970 c2X
+= (x
+ lastX
) / 2;
971 c1Y
+= (y
+ lastY
) / 2;
972 c2Y
+= (y
+ lastY
) / 2;
974 float angle1
, angle2
, delta_angle
, centerX
, centerY
;
975 angle1
= getAngle(lastX
- c1X
, lastY
- c1Y
);
976 angle2
= getAngle(x
- c1X
, y
- c1Y
);
977 delta_angle
= getDeltaAngle(angle1
, angle2
, clockwise
);
978 if ((short_arc
&& fabs(delta_angle
) <= M_PI
) || (! short_arc
&& fabs(delta_angle
) >= M_PI
))
985 angle1
= getAngle(lastX
- c2X
, lastY
- c2Y
);
986 angle2
= getAngle(x
- c2X
, y
- c2Y
);
987 delta_angle
= getDeltaAngle(angle1
, angle2
, clockwise
);
991 change
= dict_lookup(past
->states
, "x");
992 state_t
* nextX
= state_new(frame
, CF_SWEEP
, x
, inter
);
994 nextX
->arc
.angle
= angle1
;
995 nextX
->arc
.delta_angle
= delta_angle
;
996 nextX
->arc
.cX
= centerX
;
997 nextX
->arc
.cY
= centerY
;
999 state_append(change
, nextX
);
1000 change
= dict_lookup(past
->states
, "y");
1001 state_t
* nextY
= state_new(frame
, CF_SWEEP
, y
, inter
);
1003 nextY
->arc
.angle
= angle1
;
1004 nextY
->arc
.delta_angle
= delta_angle
;
1005 nextY
->arc
.cX
= centerX
;
1006 nextY
->arc
.cY
= centerY
;
1008 state_append(change
, nextY
);
1011 syntaxerror("Internal error: changing parameter y in sweep, which is unknown for the instance.");
1014 syntaxerror("Internal error: changing parameter x in sweep, which is unknown for the instance.");
1017 void history_rememberFilter(history_t
* past
, U16 frame
, int function
, FILTERLIST
* value
, interpolation_t
* inter
)
1019 past
->lastFrame
= frame
;
1020 filterState_t
* first
= dict_lookup(past
->states
, "filter");
1021 if (first
) //should always be true
1023 filterState_t
* next
= filterState_new(frame
, function
, value
, inter
);
1024 filterState_append(first
, next
);
1027 syntaxerror("Internal error: changing a filter not set for the instance.");
1030 void history_processFlags(history_t
* past
)
1031 // to be called after completely recording this history, before calculating any values.
1033 state_t
* flagState
= dict_lookup(past
->states
, "flags");
1035 U16 nextFlags
, toggledFlags
, currentFlags
= (U16
)flagState
->value
;
1036 while (flagState
->next
)
1038 nextState
= flagState
->next
;
1039 nextFlags
= (U16
)nextState
->value
;
1040 toggledFlags
= currentFlags
^ nextFlags
;
1041 if (toggledFlags
& IF_FIXED_ALIGNMENT
)
1042 { // the IF_FIXED_ALIGNMENT bit will change in the next state
1043 if (nextFlags
& IF_FIXED_ALIGNMENT
)
1044 { // the IF_FIXED_ALIGNMENT bit will be set
1045 int onFrame
= nextState
->frame
;
1046 state_t
* rotations
= dict_lookup(past
->states
, "rotate");
1047 nextState
->params
.instanceAngle
= state_value(rotations
, onFrame
);
1048 state_t
* resetRotate
= state_new(onFrame
, CF_JUMP
, 0, 0);
1049 state_insert(rotations
, resetRotate
);
1050 if (onFrame
== past
->firstFrame
)
1056 x
= dict_lookup(past
->states
, "x");
1057 dx
= state_tangent(x
, onFrame
, T_SYMMETRIC
);
1058 y
= dict_lookup(past
->states
, "y");
1059 dy
= state_tangent(y
, onFrame
, T_SYMMETRIC
);
1062 while (dx
== 0 && dy
== 0 && onFrame
< past
->lastFrame
);
1063 if (onFrame
== past
->lastFrame
)
1064 nextState
->params
.pathAngle
= 0;
1066 nextState
->params
.pathAngle
= getAngle(dx
, dy
) / M_PI
* 180;
1068 else // the IF_FIXED_ALIGNMENT bit will be reset
1070 int offFrame
= nextState
->frame
;
1071 state_t
* rotations
= dict_lookup(past
->states
, "rotate");
1072 state_t
* setRotate
= state_new(offFrame
, CF_JUMP
, flagState
->params
.instanceAngle
+ state_value(rotations
, offFrame
), 0);
1073 state_insert(rotations
, setRotate
);
1076 else // the IF_FIXED_ALIGNMENT bit will not change but some processing may be
1077 // required just the same
1079 if (nextFlags
& IF_FIXED_ALIGNMENT
)
1081 nextState
->params
.instanceAngle
= flagState
->params
.instanceAngle
;
1082 nextState
->params
.pathAngle
= flagState
->params
.pathAngle
;
1085 // and so on for all the other bits.
1086 flagState
= nextState
;
1087 currentFlags
= nextFlags
;
1091 int history_change(history_t
* past
, U16 frame
, char* parameter
)
1093 state_t
* first
= dict_lookup(past
->states
, parameter
);
1094 if (first
) //should always be true.
1095 return state_differs(first
, frame
);
1096 syntaxerror("no history found to predict changes for parameter %s.\n", parameter
);
1100 float history_value(history_t
* past
, U16 frame
, char* parameter
)
1102 state_t
* state
= dict_lookup(past
->states
, parameter
);
1103 if (state
) //should always be true.
1104 return state_value(state
, frame
);
1105 syntaxerror("no history found to get a value for parameter %s.\n", parameter
);
1109 float history_rotateValue(history_t
* past
, U16 frame
)
1111 state_t
* rotations
= dict_lookup(past
->states
, "rotate");
1112 if (rotations
) //should always be true.
1114 float angle
= state_value(rotations
, frame
);
1115 state_t
* flags
= dict_lookup(past
->states
, "flags");
1116 U16 currentflags
= state_value(flags
, frame
);
1117 if (currentflags
& IF_FIXED_ALIGNMENT
)
1119 flags
= state_at(flags
, frame
);
1120 if (frame
== past
->firstFrame
)
1123 float dx
, dy
, pathAngle
;
1126 x
= dict_lookup(past
->states
, "x");
1127 dx
= state_value(x
, frame
) - state_value(x
, frame
- 1);
1128 y
= dict_lookup(past
->states
, "y");
1129 dy
= state_value(y
, frame
) - state_value(y
, frame
- 1);
1132 while (dx
== 0 && dy
== 0 && frame
> past
->firstFrame
);
1133 if (frame
== past
->firstFrame
)
1136 pathAngle
= getAngle(dx
, dy
) / M_PI
* 180;
1137 return angle
+ flags
->params
.instanceAngle
+ pathAngle
- flags
->params
.pathAngle
;
1142 syntaxerror("no history found to get a value for parameter rotate.\n");
1146 int history_changeFilter(history_t
* past
, U16 frame
)
1148 filterState_t
* first
= dict_lookup(past
->states
, "filter");
1149 if (first
) //should always be true.
1150 return filterState_differs(first
, frame
);
1151 syntaxerror("no history found to predict changes for parameter filter.\n");
1155 FILTERLIST
* history_filterValue(history_t
* past
, U16 frame
)
1157 filterState_t
* first
= dict_lookup(past
->states
, "filter");
1158 if (first
) //should always be true.
1159 return filterState_value(first
, frame
);
1160 syntaxerror("no history found to get a value for parameter filter.\n");