--- /dev/null
+/* swfc- Compiles swf code (.sc) files into .swf files.
+
+ Part of the swftools package.
+
+ Copyright (c) 2007 Huub Schaeks <huub@h-schaeks.speedlinq.nl>
+ Copyright (c) 2007 Matthias Kramm <kramm@quiss.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <stdlib.h>
+#include <memory.h>
+#include "history.h"
+
+change_t* change_new(U16 frame, int function, float value, interpolation_t* inter)
+{
+ change_t* newChange = (change_t*)malloc(sizeof(change_t));
+ change_init(newChange);
+ newChange->frame = frame;
+ newChange->function = function;
+ newChange->value = value;
+ newChange->interpolation = inter;
+ return newChange;
+}
+
+void change_free(change_t *change)
+{
+ if (change->next)
+ change_free(change->next);
+ free(change);
+}
+
+void change_init(change_t* change)
+{
+ memset(change, 0, sizeof(change_t));
+}
+
+void change_append(change_t* first, change_t* newChange)
+{
+ while (first->next)
+ first = first->next;
+ first->next = newChange;
+}
+
+float interpolateParameter(float p1, float p2, float fraction, interpolation_t* inter)
+{
+ if (!inter)
+ return linear(fraction, p1, p2 - p1);
+ switch (inter->function)
+ {
+ case IF_LINEAR: return linear(fraction, p1, p2 - p1);
+ case IF_QUAD_IN: return quadIn(fraction, p1, p2 - p1);
+ case IF_QUAD_OUT: return quadOut(fraction, p1, p2 - p1);
+ case IF_QUAD_IN_OUT: return quadInOut(fraction, p1, p2 - p1);
+ case IF_CUBIC_IN: return cubicIn(fraction, p1, p2 - p1);
+ case IF_CUBIC_OUT: return cubicOut(fraction, p1, p2 - p1);
+ case IF_CUBIC_IN_OUT: return cubicInOut(fraction, p1, p2 - p1);
+ case IF_QUART_IN: return quartIn(fraction, p1, p2 - p1);
+ case IF_QUART_OUT: return quartOut(fraction, p1, p2 - p1);
+ case IF_QUART_IN_OUT: return quartInOut(fraction, p1, p2 - p1);
+ case IF_QUINT_IN: return quintIn(fraction, p1, p2 - p1);
+ case IF_QUINT_OUT: return quintOut(fraction, p1, p2 - p1);
+ case IF_QUINT_IN_OUT: return quintInOut(fraction, p1, p2 - p1);
+ case IF_CIRCLE_IN: return circleIn(fraction, p1, p2 - p1);
+ case IF_CIRCLE_OUT: return circleOut(fraction, p1, p2 - p1);
+ case IF_CIRCLE_IN_OUT: return circleInOut(fraction, p1, p2 - p1);
+ case IF_EXPONENTIAL_IN: return exponentialIn(fraction, p1, p2 - p1);
+ case IF_EXPONENTIAL_OUT: return exponentialOut(fraction, p1, p2 - p1);
+ case IF_EXPONENTIAL_IN_OUT: return exponentialInOut(fraction, p1, p2 - p1);
+ case IF_SINE_IN: return sineIn(fraction, p1, p2 - p1);
+ case IF_SINE_OUT: return sineOut(fraction, p1, p2 - p1);
+ case IF_SINE_IN_OUT: return sineInOut(fraction, p1, p2 - p1);
+ case IF_ELASTIC_IN: return elasticIn(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
+ case IF_ELASTIC_OUT: return elasticOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
+ case IF_ELASTIC_IN_OUT: return elasticInOut(fraction, p1, p2 - p1, inter->amplitude, inter->bounces, inter->damping);
+ case IF_BACK_IN: return backIn(fraction, p1, p2 - p1, inter->speed);
+ case IF_BACK_OUT: return backOut(fraction, p1, p2 - p1, inter->speed);
+ case IF_BACK_IN_OUT: return backInOut(fraction, p1, p2 - p1, inter->speed);
+ case IF_BOUNCE_IN: return bounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
+ case IF_BOUNCE_OUT: return bounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
+ case IF_BOUNCE_IN_OUT: return bounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
+ case IF_FAST_BOUNCE_IN: return fastBounceIn(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
+ case IF_FAST_BOUNCE_OUT: return fastBounceOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
+ case IF_FAST_BOUNCE_IN_OUT: return fastBounceInOut(fraction, p1, p2 - p1, inter->bounces, inter->growth, inter->damping);
+ default: return linear(fraction, p1, p2 - p1);
+ }
+}
+
+float change_value(change_t* first, U16 frame)
+{
+ change_t* previous = first;
+ while (first && first->frame < frame)
+ {
+ previous = first;
+ first = first->next;
+ }
+ if (!first)
+ return previous->value;
+ if (first->frame == frame)
+ {
+ float result;
+ do
+ {
+ result = first->value;
+ first = first->next;
+ }
+ while (first && first->frame == frame);
+ return result;
+ }
+ switch (first->function)
+ {
+ case CF_PUT:
+ return first->value;
+ case CF_CHANGE:
+ {
+ float fraction = (frame - previous->frame) / (float)(first->frame - previous->frame);
+ return interpolateParameter(previous->value, first->value, fraction, first->interpolation);
+ }
+ case CF_JUMP:
+ return previous->value;
+ default:
+ return 0;
+ }
+}
+
+changeFilter_t* changeFilter_new(U16 frame, int function, FILTER* value, interpolation_t* inter)
+{
+ changeFilter_t* newChange = (changeFilter_t*)malloc(sizeof(changeFilter_t));
+ changeFilter_init(newChange);
+ newChange->frame = frame;
+ newChange->function = function;
+ newChange->value = value;
+ newChange->interpolation = inter;
+ return newChange;
+}
+
+void changeFilter_free(changeFilter_t *change)
+{
+ if (change->next)
+ changeFilter_free(change->next);
+ free(change);
+}
+
+void changeFilter_init(changeFilter_t* change)
+{
+ memset(change, 0, sizeof(changeFilter_t));
+}
+
+void changeFilter_append(changeFilter_t* first, changeFilter_t* newChange)
+{
+ while (first->next)
+ first = first->next;
+ first->next = newChange;
+}
+
+RGBA interpolateColor(RGBA c1, RGBA c2, float ratio, interpolation_t* inter)
+{
+ RGBA c;
+ c.r = c1.r * (1-ratio) + c2.r * ratio;
+ c.g = c1.g * (1-ratio) + c2.g * ratio;
+ c.b = c1.b * (1-ratio) + c2.b * ratio;
+ c.a = c1.a * (1-ratio) + c2.a * ratio;
+ return c;
+}
+
+FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter)
+{
+ if(!filter1 && !filter2)
+ return 0;
+ if(!filter1)
+ return interpolateFilter(filter2,filter1,1-ratio, inter);
+
+ if(filter2 && filter2->type != filter1->type)
+ syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]);
+
+ if(filter1->type == FILTERTYPE_BLUR)
+ {
+ FILTER_BLUR*f1 = (FILTER_BLUR*)filter1;
+ FILTER_BLUR*f2 = (FILTER_BLUR*)filter2;
+ if(f2 && f1->blurx == f2->blurx && f1->blury == f2->blury)
+ return 0;
+ FILTER_BLUR*f = (FILTER_BLUR*)swf_NewFilter(FILTERTYPE_BLUR);
+ f->blurx= (f1->blurx)*(1-ratio) + (f2?f2->blurx:0)*ratio;
+ f->blury= (f1->blury)*(1-ratio) + (f2?f2->blury:0)*ratio;
+ f->passes= (f1->passes)*(1-ratio) + (f2?f2->passes:0)*ratio;
+ return (FILTER*)f;
+ }
+ else
+ if (filter1->type == FILTERTYPE_DROPSHADOW)
+ {
+ FILTER_DROPSHADOW*f1 = (FILTER_DROPSHADOW*)filter1;
+ FILTER_DROPSHADOW*f2 = (FILTER_DROPSHADOW*)filter2;
+ if(f2 && !memcmp(&f1->color,&f2->color,sizeof(RGBA)) && f1->strength == f2->strength &&
+ f1->blurx == f2->blurx && f1->blury == f2->blury &&
+ f1->angle == f2->angle && f1->distance == f2->distance)
+ return 0;
+ FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)swf_NewFilter(FILTERTYPE_DROPSHADOW);
+ memcpy(f, f1, sizeof(FILTER_DROPSHADOW));
+ f->color = interpolateColor(f1->color, f2->color, ratio, inter);
+ f->blurx= (f1->blurx)*(1-ratio) + (f2?f2->blurx:0)*ratio;
+ f->blury= (f1->blury)*(1-ratio) + (f2?f2->blury:0)*ratio;
+ f->passes= (f1->passes)*(1-ratio) + (f2?f2->passes:0)*ratio;
+ f->angle= (f1->angle)*(1-ratio) + (f2?f2->angle:0)*ratio;
+ f->distance= (f1->distance)*(1-ratio) + (f2?f2->distance:0)*ratio;
+ f->strength= (f1->strength)*(1-ratio) + (f2?f2->strength:0)*ratio;
+ return (FILTER*)f;
+ }
+ else
+ if (filter1->type == FILTERTYPE_BEVEL)
+ {
+ FILTER_BEVEL*f1 = (FILTER_BEVEL*)filter1;
+ FILTER_BEVEL*f2 = (FILTER_BEVEL*)filter2;
+ if(f2 && !memcmp(&f1->shadow,&f2->shadow,sizeof(RGBA)) &&
+ !memcmp(&f1->highlight,&f2->highlight,sizeof(RGBA)) &&
+ f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
+ return 0;
+ FILTER_BEVEL*f = (FILTER_BEVEL*)swf_NewFilter(FILTERTYPE_BEVEL);
+ memcpy(f, f1, sizeof(FILTER_BEVEL));
+ f->shadow = interpolateColor(f1->shadow, f2->shadow, ratio, inter);
+ f->highlight = interpolateColor(f1->highlight, f2->highlight, ratio, inter);
+ f->blurx= (f1->blurx)*(1-ratio) + (f2?f2->blurx:0)*ratio;
+ f->blury= (f1->blury)*(1-ratio) + (f2?f2->blury:0)*ratio;
+ f->passes= (f1->passes)*(1-ratio) + (f2?f2->passes:0)*ratio;
+ f->angle= (f1->angle)*(1-ratio) + (f2?f2->angle:0)*ratio;
+ f->distance= (f1->distance)*(1-ratio) + (f2?f2->distance:0)*ratio;
+ f->strength= (f1->strength)*(1-ratio) + (f2?f2->strength:0)*ratio;
+ return (FILTER*)f;
+ } /*else if (filter1->type == FILTERTYPE_GRADIENTGLOW) {
+ FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW);
+ // can't interpolate gradients
+ memcpy(f, filter1, sizeof(FILTER_GRADIENTGLOW));
+ return (FILTER*)f;
+ }*/ else
+ syntaxerror("can't interpolate %s filters yet", filtername[filter1->type]);
+ return 0;
+}
+
+FILTER* copyFilter(FILTER* original)
+{
+ if (!original)
+ return original;
+ FILTER* copy = swf_NewFilter(original->type);
+ switch (original->type)
+ {
+ case FILTERTYPE_BLUR:
+ memcpy(copy, original, sizeof(FILTER_BLUR));
+ break;
+ case FILTERTYPE_GRADIENTGLOW:
+ memcpy(copy, original, sizeof(FILTER_GRADIENTGLOW));
+ break;
+ case FILTERTYPE_DROPSHADOW:
+ memcpy(copy, original, sizeof(FILTER_DROPSHADOW));
+ break;
+ case FILTERTYPE_BEVEL:
+ memcpy(copy, original, sizeof(FILTER_BEVEL));
+ break;
+ default: printf("unsupported filterype");
+ }
+ return copy;
+}
+
+FILTER* changeFilter_value(changeFilter_t* first, U16 frame)
+{
+ changeFilter_t* previous = first;
+ while (first && first->frame < frame)
+ {
+ previous = first;
+ first = first->next;
+ }
+ if (!first)
+ return copyFilter(previous->value);
+ if (first->frame == frame)
+ {
+ FILTER* result;
+ do
+ {
+ result = first->value;
+ first = first->next;
+ }
+ while (first && first->frame == frame);
+ return copyFilter(result);
+ }
+ switch (first->function)
+ {
+ case CF_PUT:
+ return copyFilter(first->value);
+ case CF_CHANGE:
+ {
+ float fraction = (frame - previous->frame) / (float)(first->frame - previous->frame);
+ return interpolateFilter(previous->value, first->value, fraction, first->interpolation);
+ }
+ case CF_JUMP:
+ return copyFilter(previous->value);
+ default:
+ return 0;
+ }
+}
+
+history_t* history_new()
+{
+ history_t* newHistory = (history_t*)malloc(sizeof(history_t));
+ history_init(newHistory);
+ return newHistory;
+}
+
+void history_free(history_t* past)
+{
+ change_free(dictionary_lookup(past->changes, "x"));
+ change_free(dictionary_lookup(past->changes, "y"));
+ change_free(dictionary_lookup(past->changes, "scalex"));
+ change_free(dictionary_lookup(past->changes, "scaley"));
+ change_free(dictionary_lookup(past->changes, "cxform.r0"));
+ change_free(dictionary_lookup(past->changes, "cxform.g0"));
+ change_free(dictionary_lookup(past->changes, "cxform.b0"));
+ change_free(dictionary_lookup(past->changes, "cxform.a0"));
+ change_free(dictionary_lookup(past->changes, "cxform.r1"));
+ change_free(dictionary_lookup(past->changes, "cxform.g1"));
+ change_free(dictionary_lookup(past->changes, "cxform.b1"));
+ change_free(dictionary_lookup(past->changes, "cxform.a1"));
+ change_free(dictionary_lookup(past->changes, "rotate"));
+ change_free(dictionary_lookup(past->changes, "shear"));
+ change_free(dictionary_lookup(past->changes, "pivot.x"));
+ change_free(dictionary_lookup(past->changes, "pivot.y"));
+ change_free(dictionary_lookup(past->changes, "pin.x"));
+ change_free(dictionary_lookup(past->changes, "pin.y"));
+ change_free(dictionary_lookup(past->changes, "blendmode"));
+ changeFilter_free(dictionary_lookup(past->changes, "filter"));
+ dictionary_destroy(past->changes);
+ free(past);
+}
+
+void history_init(history_t* past)
+{
+ past->changes = (dictionary_t*)malloc(sizeof(dictionary_t));
+ dictionary_init(past->changes);
+}
+
+void history_begin(history_t* past, char* parameter, U16 frame, TAG* tag, float value)
+{
+ change_t* first = change_new(frame, CF_PUT, value, 0);
+ past->firstTag = tag;
+ past->firstFrame = frame;
+ dictionary_put2(past->changes, parameter, first);
+}
+
+void history_beginFilter(history_t* past, U16 frame, TAG* tag, FILTER* value)
+{
+ changeFilter_t* first = changeFilter_new(frame, CF_PUT, value, 0);
+ past->firstTag = tag;
+ past->firstFrame = frame;
+ dictionary_put2(past->changes, "filter", first);
+}
+
+void history_remember(history_t* past, char* parameter, U16 frame, int function, float value, interpolation_t* inter)
+{
+ change_t* first = dictionary_lookup(past->changes, parameter);
+ if (first) //should always be true
+ {
+ change_t* next = change_new(frame, function, value, inter);
+ change_append(first, next);
+ }
+}
+
+void history_rememberFilter(history_t* past, U16 frame, int function, FILTER* value, interpolation_t* inter)
+{
+ changeFilter_t* first = dictionary_lookup(past->changes, "filter");
+ if (first) //should always be true
+ {
+ changeFilter_t* next = changeFilter_new(frame, function, value, inter);
+ changeFilter_append(first, next);
+ }
+}
+
+float history_value(history_t* past, U16 frame, char* parameter)
+{
+ change_t* first = dictionary_lookup(past->changes, parameter);
+ if (first) //should always be true.
+ return change_value(first, frame);
+ printf("no history found for parameter %s\n", parameter);
+ return 0;
+}
+
+FILTER* history_valueFilter(history_t* past, U16 frame)
+{
+ changeFilter_t* first = dictionary_lookup(past->changes, "filter");
+ if (first) //should always be true.
+ return changeFilter_value(first, frame);
+ printf("no history found for parameter filter\n");
+ return 0;
+}
--- /dev/null
+/* swfc- Compiles swf code (.sc) files into .swf files.
+
+ Part of the swftools package.
+
+ Copyright (c) 2007 Huub Schaeks <huub@h-schaeks.speedlinq.nl>
+ Copyright (c) 2007 Matthias Kramm <kramm@quiss.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <stdlib.h>
+#include <math.h>
+#include <memory.h>
+#include "interpolation.h"
+
+static inline float poly(float fraction, float start, float delta, int degree)
+{
+ return delta * pow(fraction, degree) + start;
+}
+
+float linear(float fraction, float start, float delta)
+{
+ return poly(fraction, start, delta, 1);
+}
+
+float quadIn(float fraction, float start, float delta)
+{
+ return poly(fraction, start, delta, 2);
+}
+
+float quadOut(float fraction, float start, float delta)
+{
+ return quadIn(1 - fraction, start + delta, -delta);
+}
+
+float quadInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return quadIn(2 * fraction, start, delta / 2);
+ return quadOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float cubicIn(float fraction, float start, float delta)
+{
+ return poly(fraction, start, delta, 3);
+}
+
+float cubicOut(float fraction, float start, float delta)
+{
+ return cubicIn(1 - fraction, start + delta, -delta);
+}
+
+float cubicInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return cubicIn(2 * fraction, start, delta / 2);
+ return cubicOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float quartIn(float fraction, float start, float delta)
+{
+ return poly(fraction, start, delta, 4);
+}
+
+float quartOut(float fraction, float start, float delta)
+{
+ return quartIn(1 - fraction, start + delta, -delta);
+}
+
+float quartInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return quartIn(2 * fraction, start, delta / 2);
+ return quartOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float quintIn(float fraction, float start, float delta)
+{
+ return poly(fraction, start, delta, 5);
+}
+
+float quintOut(float fraction, float start, float delta)
+{
+ return quintIn(1 - fraction, start + delta, -delta);
+}
+
+float quintInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return quintIn(2 * fraction, start, delta / 2);
+ return quintOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float circleIn(float fraction, float start, float delta)
+{
+ return delta * (1 - sqrt(1 - fraction * fraction)) + start;
+}
+
+float circleOut(float fraction, float start, float delta)
+{
+ return circleIn(1 - fraction, start + delta, -delta);
+}
+
+float circleInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return circleIn(2 * fraction, start, delta / 2);
+ return circleOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float exponentialIn(float fraction, float start, float delta)
+{
+ if (fraction == 0)
+ return start;
+ return delta * pow(2, 10 * (fraction - 1)) + start;
+}
+
+float exponentialOut(float fraction, float start, float delta)
+{
+ return exponentialIn(1 - fraction, start + delta, -delta);
+}
+
+float exponentialInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return exponentialIn(2 * fraction, start, delta / 2);
+ return exponentialOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float sineIn(float fraction, float start, float delta)
+{
+ return delta * (1 - cos(fraction * PI/2)) + start;
+}
+
+float sineOut(float fraction, float start, float delta)
+{
+ return sineIn(1 - fraction, start + delta, -delta);
+}
+
+float sineInOut(float fraction, float start, float delta)
+{
+ if (fraction < 0.5)
+ return sineIn(2 * fraction, start, delta / 2);
+ return sineOut(2 * fraction - 1, start + delta / 2, delta / 2);
+}
+
+float elasticIn(float fraction, float start, float delta, float amplitude, int bounces, float damping)
+{
+ if (fraction == 0 || delta == 0)
+ return start;
+ if (fraction == 1)
+ return start + delta;
+ if (amplitude < fabs(delta))
+ amplitude = delta;
+ float period = 1 / (bounces + 0.25);
+// float s = asin(delta / amplitude) - 2 * PI / period;
+ return amplitude * pow(2, damping * (fraction - 1)) * sin(fraction * (2 * PI) / period /*+ fraction * s*/) + start;
+}
+
+float elasticOut(float fraction, float start, float delta, float amplitude, int bounces, float damping)
+{
+ return elasticIn(1 - fraction, start + delta, -delta, amplitude, bounces, damping);
+}
+
+float elasticInOut(float fraction, float start, float delta, float amplitude, int bounces, float damping)
+{
+ if (fraction < 0.5)
+ return elasticIn(2 * fraction, start, delta / 2, amplitude, bounces, damping);
+ return elasticOut(2 * fraction - 1, start + delta / 2, delta / 2, amplitude, bounces, damping);
+}
+
+float backIn(float fraction, float start, float delta, float speed)
+{
+ return delta * fraction * fraction * ((speed + 1) * fraction - speed) + start;
+}
+
+float backOut(float fraction, float start, float delta, float speed)
+{
+ return backIn(1 - fraction, start + delta, -delta, speed);
+}
+
+float backInOut(float fraction, float start, float delta, float speed)
+{
+ if (fraction < 0.5)
+ return backIn(2 * fraction, start, delta / 2, speed);
+ return backOut(2 * fraction - 1, start + delta / 2, delta / 2, speed);
+}
+
+/* when applied to movement bounceIn the object 'hits the floor' bounces times
+ * (after leaving the floor first) before gently reaching the final position at the top of the final bounce
+ * Each bounce takes growth times a long as the previous, except for the last one which lasts only half
+ * that time. The heights of the intermediate bounces are determined by the damping parameter.
+ * Set damping to 0 for an undamped movement.*/
+
+float bounceIn(float fraction, float start, float delta, int bounces, float growth, float damping)
+{
+ if (fraction == 0 || delta == 0)
+ return start;
+ if (fraction == 1)
+ return start + delta;
+ float w0;
+ if (growth == 1.0)
+ w0 = 1 / (bounces + 0.5);
+ else
+ {
+ float gN = pow(growth, bounces);
+ w0 = 1 / ((gN - 1) / (growth - 1) + gN / 2 );
+ }
+ float bounceStart = 0;
+ int i;
+ float w = w0;
+ for (i = 0; i <= bounces; i++)
+ {
+ float bounceEnd = bounceStart + w;
+ if (fraction >= bounceStart && fraction < bounceEnd)
+ {
+ float half = (bounceEnd + bounceStart) / 2;
+ float top = delta / pow(2, damping * ((bounces - i)));
+ fraction -= half;
+ fraction /= (w / 2);
+ return (1 - fraction * fraction) * top + start;
+ }
+ bounceStart = bounceEnd;
+ w = w * growth;
+ }
+}
+
+/* bounceOut is a time-reversed bounceIn; therefore each bounce takes 1/growth times as long as
+ * the previous, which I think fits the idea when applied to movement */
+
+float bounceOut(float fraction, float start, float delta, int bounces, float growth, float damping)
+{
+ return bounceIn(1 - fraction, start + delta, -delta, bounces, growth, damping);
+}
+
+/* since bounceIn and bounceOut are combined, if growth > 1 then the bounce-times will increase in
+ * the first half and decrease in the second half */
+
+float bounceInOut(float fraction, float start, float delta, int bounces, float growth, float damping)
+{
+ if (fraction < 0.5)
+ return bounceIn(2 * fraction, start, delta / 2, bounces, growth, damping);
+ return bounceOut(2 * fraction - 1, start + delta / 2, delta / 2, bounces, growth, damping);
+}
+/* fastBounce(In/Out) doesn't end or start in a horizontal slope (= gentle end or start) as
+ * bounce(In/Out) do which means fastBounceInOut doesn't have the 'delay' in the middle */
+float fastBounceIn(float fraction, float start, float delta, int bounces, float growth, float damping)
+{
+ if (fraction == 0 || delta == 0)
+ return start;
+ if (fraction == 1)
+ return start + delta;
+ float w0;
+ if (growth == 1.0)
+ w0 = 1 / (bounces + 0.25); /* in general (bounces + 1 / (2 * f)) */
+ else
+ {
+ float gN = pow(growth, bounces);
+ w0 = 1 / ((gN - 1) / (growth - 1) + gN / 4 /* in general: gN / (2 * f) */ );
+ }
+ float bounceStart = 0;
+ int i;
+ float w = w0;
+ for (i = 0; i <= bounces; i++)
+ {
+ float bounceEnd = bounceStart + w;
+ if (fraction >= bounceStart && fraction < bounceEnd)
+ {
+ float half = (bounceEnd + bounceStart) / 2;
+ float top = delta / 0.75/* in general: (1 - (1 / f) * (1 / f)) */ / pow(2, damping * ((bounces - i)));
+ fraction -= half;
+ fraction /= (w / 2);
+ return (1 - fraction * fraction) * top + start;
+ }
+ bounceStart = bounceEnd;
+ w = w * growth;
+ }
+}
+
+float fastBounceOut(float fraction, float start, float delta, int bounces, float growth, float damping)
+{
+ return fastBounceIn(1 - fraction, start + delta, -delta, bounces, growth, damping);
+}
+
+float fastBounceInOut(float fraction, float start, float delta, int bounces, float growth, float damping)
+{
+ if (fraction < 0.5)
+ return fastBounceIn(2 * fraction, start, delta / 2, bounces, growth, damping);
+ return fastBounceOut(2 * fraction - 1, start + delta / 2, delta / 2, bounces, growth, damping);
+}
#include "../lib/wav.h"
#include "parser.h"
#include "../lib/png.h"
+#include "../lib/interpolation.h"
+#include "../lib/history.h"
//#define DEBUG
-
-static char * filename = 0;
static char * outputname = "output.swf";
static int verbose = 2;
static int optimize = 0;
static char*text;
static int textlen;
static int type;
-static int line;
-static int column;
-
-static void syntaxerror(char*format, ...)
-{
- char buf[1024];
- va_list arglist;
- va_start(arglist, format);
- vsprintf(buf, format, arglist);
- va_end(arglist);
- fprintf(stderr, "\"%s\", line %d column %d: error- %s\n", filename, line, column, buf);
- exit(1);
-}
-
-static void warning(char*format, ...)
-{
- char buf[1024];
- va_list arglist;
- va_start(arglist, format);
- vsprintf(buf, format, arglist);
- va_end(arglist);
- fprintf(stderr, "\"%s\", line %d column %d: warning- %s\n", filename, line, column, buf);
-}
static void readToken()
{
static dictionary_t outlines;
static dictionary_t gradients;
static dictionary_t filters;
+static dictionary_t interpolations;
static char idmap[65536];
static TAG*tag = 0; //current tag
static dictionary_t instances;
static dictionary_t fonts;
static dictionary_t sounds;
+static dictionary_t fontUsage;
typedef struct _parameters {
int x,y;
SPOINT pin;
U8 blendmode; //not interpolated
FILTER*filter;
+ U16 set; // bits indicating wether a parameter was set in the c_placement function
} parameters_t;
typedef struct _character {
parameters_t parameters;
TAG* lastTag; //last tag which set the object
U16 lastFrame; //frame lastTag is in
+ history_t* history;
} instance_t;
typedef struct _outline {
FILLSTYLE fs;
} texture_t;
+char* interpolationFunctions[] = {"linear", \
+ "quadIn", "quadOut", "quadInOut", \
+ "cubicIn", "cubicOut", "cubicInOut", \
+ "quartIn", "quartOut", "quartInOut", \
+ "quintIn", "quintOut", "quintInOut", \
+ "circleIn", "circleOut", "circleInOut", \
+ "exponentialIn", "exponentialOut", "exponentialInOut", \
+ "sineIn", "sineOut", "sineInOut", \
+ "elasticIn", "elasticOut", "elasticInOut", \
+ "backIn", "backOut", "backInOut", \
+ "bounceIn", "bounceOut", "bounceInOut", \
+ "fastBounceIn", "fastBounceOut", "fastBounceInOut"};
+
+typedef struct _fontData {
+ char *glyphs;
+ int notUsed, needsAll;
+} fontData;
+
+void addFontData(char *name)
+{
+ fontData* newFont;
+ newFont = (fontData *)malloc(sizeof(fontData));
+ memset(newFont, 0, sizeof(fontData));
+ newFont->notUsed = 1;
+ dictionary_put2(&fontUsage, name, newFont);
+}
+
+void freeFontData(fontData* font)
+{
+ free(font->glyphs);
+ free(font);
+}
+
+fontData *getFontData(char *name)
+{
+ return (fontData *)dictionary_lookup(&fontUsage, name);
+}
+
static void character_init(character_t*c)
{
memset(c, 0, sizeof(character_t));
}
+
static character_t* character_new()
{
character_t*c;
character_init(c);
return c;
}
+
static void instance_init(instance_t*i)
{
memset(i, 0, sizeof(instance_t));
+ i->history = history_new();
}
+
+static void instance_free(instance_t* i)
+{
+ history_free(i->history);
+ free(i);
+}
+
static instance_t* instance_new()
{
instance_t*c;
return c;
}
+static void free_instance(void* i)
+{
+ instance_free((instance_t*)i);
+}
+
+static void free_font(void* f)
+{
+ swf_FontFree((SWFFONT*)f);
+}
+
+static void free_fontData(void* fd)
+{
+ freeFontData((fontData*)fd);
+}
+
+static void gradient_free(GRADIENT* grad)
+{
+ free(grad->ratios);
+ free(grad->rgba);
+ free(grad);
+}
+
+static void free_gradient(void* grad)
+{
+ gradient_free((GRADIENT*) grad);
+}
+
+static void outline_free(outline_t* o)
+{
+ free(o->shape->data);
+ free(o->shape);
+ free(o);
+}
+
+static void free_outline(void* o)
+{
+ outline_free((outline_t*)o);
+}
+
+static void freeDictionaries()
+{
+ dictionary_free_all(&instances, free_instance);
+ dictionary_free_all(&characters, free);
+ dictionary_free_all(&images, free);
+ dictionary_free_all(&textures, free);
+ dictionary_free_all(&outlines, free_outline);
+ dictionary_free_all(&gradients, free_gradient);
+ dictionary_free_all(&filters, free);
+ dictionary_free_all(&fonts, free_font);
+ dictionary_free_all(&sounds, free);
+ dictionary_free_all(&fontUsage, free_fontData);
+ dictionary_free_all(&interpolations, free);
+}
+
static void incrementid()
{
while(idmap[++id]) {
static void s_addcharacter(char*name, U16 id, TAG*ctag, SRECT r)
{
+ if(dictionary_lookup(&characters, name))
+ syntaxerror("character %s defined twice", name);
character_t* c = character_new();
c->definingTag = ctag;
c->id = id;
c->size = r;
- if(dictionary_lookup(&characters, name))
- syntaxerror("character %s defined twice", name);
dictionary_put2(&characters, name, c);
tag = swf_InsertTag(tag, ST_NAMECHARACTER);
}
static void s_addimage(char*name, U16 id, TAG*ctag, SRECT r)
{
+ if(dictionary_lookup(&images, name))
+ syntaxerror("image %s defined twice", name);
+
character_t* c = character_new();
c->definingTag = ctag;
c->id = id;
c->size = r;
-
- if(dictionary_lookup(&images, name))
- syntaxerror("image %s defined twice", name);
dictionary_put2(&images, name, c);
}
static instance_t* s_addinstance(char*name, character_t*c, U16 depth)
{
+ if(dictionary_lookup(&instances, name))
+ syntaxerror("object %s defined twice", name);
instance_t* i = instance_new();
i->character = c;
i->depth = depth;
//swf_GetMatrix(0, &i->matrix);
- if(dictionary_lookup(&instances, name))
- syntaxerror("object %s defined twice", name);
dictionary_put2(&instances, name, i);
return i;
}
* \r0 sy/ \y/
*/
- sx = p->scalex*cos(p->rotate/360*2*3.14159265358979);
- r1 = -p->scalex*sin(p->rotate/360*2*3.14159265358979)+sx*p->shear;
- r0 = p->scaley*sin(p->rotate/360*2*3.14159265358979);
- sy = p->scaley*cos(p->rotate/360*2*3.14159265358979)+r0*p->shear;
+ sx = p->scalex*cos(p->rotate/360*2*PI);
+ r1 = -p->scalex*sin(p->rotate/360*2*PI)+sx*p->shear;
+ r0 = p->scaley*sin(p->rotate/360*2*PI);
+ sy = p->scaley*cos(p->rotate/360*2*PI)+r0*p->shear;
m->sx = (int)(sx*65536+0.5);
m->r1 = (int)(r1*65536+0.5);
return m;
}
+void builtInInterpolations()
+{
+ interpolation_t* new;
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_LINEAR;
+ dictionary_put2(&interpolations, "linear", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUAD_IN;
+ dictionary_put2(&interpolations, "quadIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUAD_OUT;
+ dictionary_put2(&interpolations, "quadOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUAD_IN_OUT;
+ dictionary_put2(&interpolations, "quadInOut", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_CUBIC_IN;
+ dictionary_put2(&interpolations, "cubicIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_CUBIC_OUT;
+ dictionary_put2(&interpolations, "cubicOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_CUBIC_IN_OUT;
+ dictionary_put2(&interpolations, "cubicInOut", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUART_IN;
+ dictionary_put2(&interpolations, "quartIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUART_OUT;
+ dictionary_put2(&interpolations, "quartOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUART_IN_OUT;
+ dictionary_put2(&interpolations, "quartInOut", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUINT_IN;
+ dictionary_put2(&interpolations, "quintIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUINT_OUT;
+ dictionary_put2(&interpolations, "quintOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_QUINT_IN_OUT;
+ dictionary_put2(&interpolations, "quintInOut", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_CIRCLE_IN;
+ dictionary_put2(&interpolations, "circleIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_CIRCLE_OUT;
+ dictionary_put2(&interpolations, "circleOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_CIRCLE_IN_OUT;
+ dictionary_put2(&interpolations, "circleInOut", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_EXPONENTIAL_IN;
+ dictionary_put2(&interpolations, "exponentialIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_EXPONENTIAL_OUT;
+ dictionary_put2(&interpolations, "exponentialOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_EXPONENTIAL_IN_OUT;
+ dictionary_put2(&interpolations, "exponentialInOut", new);
+
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_SINE_IN;
+ dictionary_put2(&interpolations, "sineIn", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_SINE_OUT;
+ dictionary_put2(&interpolations, "sineOut", new);
+ new = (interpolation_t*)malloc(sizeof(interpolation_t));
+ new->function = IF_SINE_IN_OUT;
+ dictionary_put2(&interpolations, "sineInOut", new);
+}
+
void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA background)
{
- SWF*swf = (SWF*)malloc(sizeof(SWF));
-
if(stackpos)
- syntaxerror(".swf blocks can't be nested");
+ syntaxerror(".swf blocks can't be nested");
+ if(stackpos==sizeof(stack)/sizeof(stack[0]))
+ syntaxerror("too many levels of recursion");
+
+ SWF*swf = (SWF*)malloc(sizeof(SWF));
memset(swf, 0, sizeof(swf));
swf->fileVersion = version;
swf->firstTag = tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
swf->compressed = compress;
swf_SetRGB(tag,&background);
-
- if(stackpos==sizeof(stack)/sizeof(stack[0]))
- syntaxerror("too many levels of recursion");
dictionary_init(&characters);
dictionary_init(&images);
dictionary_init(&instances);
dictionary_init(&fonts);
dictionary_init(&sounds);
+ dictionary_init(&interpolations);
+ builtInInterpolations();
+ cleanUp = &freeDictionaries;
memset(&stack[stackpos], 0, sizeof(stack[0]));
stack[stackpos].type = 0;
return save;
}
+static void readParameters(history_t* history, parameters_t* p, int frame)
+{
+ p->x = history_value(history, frame, "x");
+ p->y = history_value(history, frame, "y");
+ p->scalex = history_value(history, frame, "scalex");
+ p->scaley = history_value(history, frame, "scaley");
+ p->cxform.r0 = history_value(history, frame, "cxform.r0");
+ p->cxform.g0 = history_value(history, frame, "cxform.g0");
+ p->cxform.b0 = history_value(history, frame, "cxform.b0");
+ p->cxform.a0 = history_value(history, frame, "cxform.a0");
+ p->cxform.r1 = history_value(history, frame, "cxform.r1");
+ p->cxform.g1 = history_value(history, frame, "cxform.g1");
+ p->cxform.b1 = history_value(history, frame, "cxform.b1");
+ p->cxform.a1 = history_value(history, frame, "cxform.a1");
+ p->rotate = history_value(history, frame, "rotate");
+ p->shear = history_value(history, frame, "shear");
+ p->pivot.x = history_value(history, frame, "pivot.x");
+ p->pivot.y = history_value(history, frame, "pivot.y");
+ p->pin.x = history_value(history, frame, "pin.x");
+ p->pin.y = history_value(history, frame, "pin.y");
+ p->blendmode = history_value(history, frame, "blendmode");
+ p->filter = history_valueFilter(history, frame);
+}
+
+void setPlacement(TAG*tag, U16 id, U16 depth, MATRIX m, char*name, parameters_t*p, char move)
+{
+ SWFPLACEOBJECT po;
+ FILTERLIST flist;
+ swf_GetPlaceObject(NULL, &po);
+ po.id = id;
+ po.depth = depth;
+ po.matrix = m;
+ po.cxform = p->cxform;
+ po.name = name;
+ po.move = move;
+ if(move)
+ po.id = 0;
+ if(p->blendmode) {
+ po.blendmode = p->blendmode;
+ }
+ if(p->filter) {
+ flist.num = 1;
+ flist.filter[0] = p->filter;
+ po.filters = &flist;
+ }
+ swf_SetPlaceObject(tag, &po);
+}
+
+static void writeInstance(instance_t* i)
+{
+ parameters_t p;
+ MATRIX m;
+ int frame = i->history->firstFrame;
+ TAG* tag = i->history->firstTag;
+ while (frame < currentframe)
+ {
+ frame++;
+ readParameters(i->history, &p, frame);
+ while (tag->id != ST_SHOWFRAME)
+ tag = tag->next;
+ m = s_instancepos(i->character->size, &p);
+
+ if(p.blendmode || p.filter)
+ tag = swf_InsertTag(tag, ST_PLACEOBJECT3);
+ else
+ tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+ setPlacement(tag, 0, i->depth, m, 0, &p, 1);
+ if (p.filter)
+ free(p.filter);
+ }
+}
+
+void dumpSWF(SWF*swf)
+{
+ TAG* tag = swf->firstTag;
+ printf("vvvvvvvvvvvvvvvvvvvvv\n");
+ while(tag) {
+ printf("%8d %s\n", tag->len, swf_TagGetName(tag));
+ tag = tag->next;
+ }
+ printf("^^^^^^^^^^^^^^^^^^^^^\n");
+}
+
static void s_endSprite()
{
SRECT r = currentrect;
tag = removeFromTo(stack[stackpos].cut, tag);
stackpos--;
-
+ instance_t *i;
+ stringarray_t* index =dictionary_index(&instances);
+ int num = 0;
+ char* name = stringarray_at(index, num);
+ while (name)
+ {
+ i = dictionary_lookup(&instances, name);
+ writeInstance(i);
+ num++;
+ name = stringarray_at(index, num);
+ }
+
+ tag = swf_InsertTag(tag, ST_SHOWFRAME);
+ tag = swf_InsertTag(tag, ST_END);
+
+ tag = stack[stackpos].tag;
+ swf_FoldSprite(tag);
+ if(tag->next != 0)
+ syntaxerror("internal error(7)");
/* TODO: before clearing, prepend "<spritename>." to names and
copy into old instances dict */
- dictionary_clear(&instances);
+ dictionary_free_all(&instances, free_instance);
currentframe = stack[stackpos].oldframe;
currentrect = stack[stackpos].oldrect;
currentdepth = stack[stackpos].olddepth;
instances = stack[stackpos].oldinstances;
- tag = swf_InsertTag(tag, ST_SHOWFRAME);
- tag = swf_InsertTag(tag, ST_END);
-
- tag = stack[stackpos].tag;
- swf_FoldSprite(tag);
- if(tag->next != 0)
- syntaxerror("internal error(7)");
-
s_addcharacter(stack[stackpos].name, stack[stackpos].id, stack[stackpos].tag, r);
free(stack[stackpos].name);
}
SWF* swf;
char*filename;
+ instance_t *i;
+ stringarray_t* index =dictionary_index(&instances);
+ int num = 0;
+ char* name = stringarray_at(index, num);
+ while (name)
+ {
+ i = dictionary_lookup(&instances, name);
+ writeInstance(i);
+ num++;
+ name = stringarray_at(index, num);
+ }
+
if(stack[stackpos].cut)
tag = removeFromTo(stack[stackpos].cut, tag);
{if(swf_WriteSWF(fi, swf)<0) syntaxerror("WriteSWF() failed.\n");}
close(fi);
-
- dictionary_clear(&instances);
- dictionary_clear(&characters);
- dictionary_clear(&images);
- dictionary_clear(&textures);
- dictionary_clear(&outlines);
- dictionary_clear(&gradients); // mem leak
- dictionary_clear(&filters);
- dictionary_clear(&fonts);
- dictionary_clear(&sounds);
+
+ freeDictionaries();
swf_FreeTags(swf);
free(swf);
MATRIX rot,m;
double ccos,csin;
swf_GetMatrix(0, &rot);
- ccos = cos(-gradient->rotate*2*3.14159265358979/360);
- csin = sin(-gradient->rotate*2*3.14159265358979/360);
+ ccos = cos(-gradient->rotate*2*PI/360);
+ csin = sin(-gradient->rotate*2*PI/360);
rot.sx = ccos*65536;
rot.r1 = -csin*65536;
rot.r0 = csin*65536;
tag = swf_InsertTag(tag, ST_DEFINEBITSLOSSLESS);
swf_SetU16(tag, imageID);
swf_SetLosslessImage(tag, data, width, height);
+ free(data);
r.xmin = 0;
r.ymin = 0;
void s_texture(char*name, char*object, int x, int y, float scalex, float scaley, float rotate, float shear)
{
+ if(dictionary_lookup(&textures, name))
+ syntaxerror("texture %s defined twice", name);
gradient_t* gradient = dictionary_lookup(&gradients, object);
character_t* bitmap = dictionary_lookup(&images, object);
texture_t* texture = (texture_t*)rfx_calloc(sizeof(texture_t));
fs->m.sy *= 20;
}
-
- if(dictionary_lookup(&textures, name))
- syntaxerror("texture %s defined twice", name);
dictionary_put2(&textures, name, texture);
}
-void dumpSWF(SWF*swf)
-{
- TAG* tag = swf->firstTag;
- printf("vvvvvvvvvvvvvvvvvvvvv\n");
- while(tag) {
- printf("%8d %s\n", tag->len, swf_TagGetName(tag));
- tag = tag->next;
- }
- printf("^^^^^^^^^^^^^^^^^^^^^\n");
-}
-
-void s_font(char*name, char*filename)
+void s_font(char*name, char*filename, char *glyphs)
{
+ if(dictionary_lookup(&fonts, name))
+ syntaxerror("font %s defined twice", name);
+
SWFFONT* font;
- font = swf_LoadFont(filename);
+ font = swf_LoadFont(filename, glyphs);
if(font == 0) {
warning("Couldn't open font file \"%s\"", filename);
swf_SetString(tag, name);
incrementid();
- if(dictionary_lookup(&fonts, name))
- syntaxerror("font %s defined twice", name);
dictionary_put2(&fonts, name, font);
}
struct MP3 mp3;
sound_t* sound;
U16*samples = NULL;
- unsigned numsamples;
+ unsigned numsamples = 1;
unsigned blocksize = 1152;
int is_mp3 = 0;
- if(wav_read(&wav, filename)) {
+ if(dictionary_lookup(&sounds, name))
+ syntaxerror("sound %s defined twice", name);
+
+ if(wav_read(&wav, filename))
+ {
int t;
- wav_convert2mono(&wav, &wav2, 44100);
- samples = (U16*)wav2.data;
- numsamples = wav2.size/2;
- free(wav.data);
+ wav_convert2mono(&wav, &wav2, 44100);
+ samples = (U16*)wav2.data;
+ numsamples = wav2.size/2;
+ free(wav.data);
#ifdef WORDS_BIGENDIAN
/* swap bytes */
- for(t=0;t<numsamples;t++) {
- samples[t] = (samples[t]>>8)&0xff | (samples[t]<<8)&0xff00;
- }
+ for(t=0;t<numsamples;t++)
+ samples[t] = (samples[t]>>8)&0xff | (samples[t]<<8)&0xff00;
#endif
- } else if(mp3_read(&mp3, filename)) {
- fprintf(stderr, "\"%s\" seems to work as a MP3 file...\n", filename);
- blocksize = 1;
- is_mp3 = 1;
}
else
- {
- warning("Couldn't read WAV/MP3 file \"%s\"", filename);
- samples = 0;
- numsamples = 0;
- }
+ if(mp3_read(&mp3, filename))
+ {
+ fprintf(stderr, "\"%s\" seems to work as a MP3 file...\n", filename);
+ blocksize = 1;
+ is_mp3 = 1;
+ }
+ else
+ {
+ warning("Couldn't read WAV/MP3 file \"%s\"", filename);
+ samples = 0;
+ numsamples = 0;
+ }
if(numsamples%blocksize != 0)
{
// apply padding, so that block is a multiple of blocksize
- int numblocks = (numsamples+blocksize-1)/blocksize;
- int numsamples2;
- U16* samples2;
- numsamples2 = numblocks * blocksize;
- samples2 = malloc(sizeof(U16)*numsamples2);
- memcpy(samples2, samples, numsamples*sizeof(U16));
- memset(&samples2[numsamples], 0, sizeof(U16)*(numsamples2 - numsamples));
- numsamples = numsamples2;
- samples = samples2;
+ int numblocks = (numsamples+blocksize-1)/blocksize;
+ int numsamples2;
+ U16* samples2;
+ numsamples2 = numblocks * blocksize;
+ samples2 = malloc(sizeof(U16)*numsamples2);
+ memcpy(samples2, samples, numsamples*sizeof(U16));
+ memset(&samples2[numsamples], 0, sizeof(U16)*(numsamples2 - numsamples));
+ numsamples = numsamples2;
+ free(samples);
+ samples = samples2;
}
tag = swf_InsertTag(tag, ST_DEFINESOUND);
mp3.SampRate,
mp3.Channels,
mp3.NumFrames);
- mp3_clear(&mp3);
+ mp3_clear(&mp3);
}
else
- {
swf_SetSoundDefine(tag, samples, numsamples);
- }
tag = swf_InsertTag(tag, ST_NAMECHARACTER);
swf_SetU16(tag, id);
sound->tag = tag;
sound->id = id;
- if(dictionary_lookup(&sounds, name))
- syntaxerror("sound %s defined twice", name);
dictionary_put2(&sounds, name, sound);
incrementid();
- if(samples)
- free(samples);
+ if (samples)
+ free(samples);
}
static char* gradient_getToken(const char**p)
memset(&gradient, 0, sizeof(GRADIENT));
gradient.ratios = rfx_calloc(16*sizeof(U8));
gradient.rgba = rfx_calloc(16*sizeof(RGBA));
- while(*p) {
- char*posstr,*colorstr;
- int pos;
- RGBA color;
- posstr = gradient_getToken(&p);
- if(!*posstr)
- break;
- pos = (int)(parsePercent(posstr)*255.0);
- if(pos == lastpos)
- pos++;
- if(!*p) syntaxerror("Error in shape data: Color expected after %s", posstr);
- colorstr = gradient_getToken(&p);
- color = parseColor(colorstr);
- if(gradient.num == 16) {
- warning("gradient record too big- max size is 16, rest ignored");
- break;
+
+ while(*p)
+ {
+ char*posstr,*colorstr;
+ int pos;
+ RGBA color;
+ posstr = gradient_getToken(&p);
+ if(!*posstr)
+ {
+ free(posstr);
+ break;
+ }
+ pos = (int)(parsePercent(posstr)*255.0);
+ if(pos == lastpos)
+ pos++;
+ if(!*p)
+ {
+ rfx_free(gradient.ratios);
+ rfx_free(gradient.rgba);
+ free(posstr);
+ syntaxerror("Error in shape data: Color expected after %s", posstr);
+ }
+ colorstr = gradient_getToken(&p);
+ color = parseColor(colorstr);
+ if(gradient.num == 16)
+ {
+ warning("gradient record too big- max size is 16, rest ignored");
+ break;
+ }
+ gradient.ratios[gradient.num] = pos;
+ gradient.rgba[gradient.num] = color;
+ gradient.num++;
+ free(posstr);
+ free(colorstr);
+ lastpos = pos;
}
- gradient.ratios[gradient.num] = pos;
- gradient.rgba[gradient.num] = color;
- gradient.num++;
- free(posstr);
- free(colorstr);
- lastpos = pos;
- }
return gradient;
}
gradient->radial = radial;
gradient->rotate = rotate;
- if(dictionary_lookup(&gradients, name))
- syntaxerror("gradient %s defined twice", name);
dictionary_put2(&gradients, name, gradient);
}
float angle, float distance, float strength, char innershadow,
char knockout, char composite, char ontop, int passes)
{
+ if(dictionary_lookup(&filters, name))
+ syntaxerror("filter %s defined twice", name);
+
gradient_t* g = dictionary_lookup(&gradients, gradient);
composite = 1;
filter->ontop = ontop;
filter->passes = passes;
- if(dictionary_lookup(&filters, name))
- syntaxerror("filter %s defined twice", name);
dictionary_put2(&filters, name, filter);
}
void s_dropshadow(char*name, RGBA color, double blurx, double blury, double angle, double distance, double strength, char innershadow, char knockout, char composite, int passes)
{
+ if(dictionary_lookup(&filters, name))
+ syntaxerror("filter %s defined twice", name);
+
composite = 1;
FILTER_DROPSHADOW* filter = rfx_calloc(sizeof(FILTER_DROPSHADOW));
filter->type = FILTERTYPE_DROPSHADOW;
filter->composite = composite;
filter->passes = passes;
- if(dictionary_lookup(&filters, name))
- syntaxerror("filter %s defined twice", name);
dictionary_put2(&filters, name, filter);
}
void s_bevel(char*name, RGBA shadow, RGBA highlight, double blurx, double blury, double angle, double distance, double strength, char innershadow, char knockout, char composite, char ontop, int passes)
{
+ if(dictionary_lookup(&filters, name))
+ syntaxerror("filter %s defined twice", name);
+
composite = 1;
FILTER_BEVEL* filter = rfx_calloc(sizeof(FILTER_BEVEL));
filter->type = FILTERTYPE_BEVEL;
filter->ontop = ontop;
filter->passes = passes;
- if(dictionary_lookup(&filters, name))
- syntaxerror("filter %s defined twice", name);
dictionary_put2(&filters, name, filter);
}
void s_blur(char*name, double blurx, double blury, int passes)
{
+ if(dictionary_lookup(&filters, name))
+ syntaxerror("filter %s defined twice", name);
+
FILTER_BLUR* filter = rfx_calloc(sizeof(FILTER_BLUR));
filter->type = FILTERTYPE_BLUR;
filter->blurx = blurx;
filter->blury = blury;
filter->passes = passes;
- if(dictionary_lookup(&filters, name))
- syntaxerror("filter %s defined twice", name);
dictionary_put2(&filters, name, filter);
}
{
ActionTAG* a = 0;
a = swf_ActionCompile(text, stack[0].swf->fileVersion);
- if(!a) {
- syntaxerror("Couldn't compile ActionScript");
+ if(!a)
+ {
+ swf_ActionFree(a);
+ syntaxerror("Couldn't compile ActionScript");
}
tag = swf_InsertTag(tag, ST_DOACTION);
ActionTAG* a = 0;
character_t*c = 0;
a = swf_ActionCompile(text, stack[0].swf->fileVersion);
- if(!a) {
- syntaxerror("Couldn't compile ActionScript");
+ if(!a)
+ {
+ swf_ActionFree(a);
+ syntaxerror("Couldn't compile ActionScript");
}
c = (character_t*)dictionary_lookup(&characters, character);
void s_outline(char*name, char*format, char*source)
{
+ if(dictionary_lookup(&outlines, name))
+ syntaxerror("outline %s defined twice", name);
+
outline_t* outline;
drawer_t draw;
outline->shape = shape;
outline->bbox = bounds;
- if(dictionary_lookup(&outlines, name))
- syntaxerror("outline %s defined twice", name);
dictionary_put2(&outlines, name, outline);
}
currentdepth++;
}
-void setPlacement(TAG*tag, U16 id, U16 depth, MATRIX m, char*name, parameters_t*p, char move)
-{
- SWFPLACEOBJECT po;
- FILTERLIST flist;
- swf_GetPlaceObject(NULL, &po);
- po.id = id;
- po.depth = depth;
- po.matrix = m;
- po.cxform = p->cxform;
- po.name = name;
- po.move = move;
- if(move)
- po.id = 0;
- if(p->blendmode) {
- po.blendmode = p->blendmode;
- }
- if(p->filter) {
- flist.num = 1;
- flist.filter[0] = p->filter;
- po.filters = &flist;
- }
- swf_SetPlaceObject(tag, &po);
+void setStartparameters(instance_t* i, parameters_t* p, TAG* tag)
+{
+ history_begin(i->history, "x", currentframe, tag, p->x);
+ history_begin(i->history, "y", currentframe, tag, p->y);
+ history_begin(i->history, "scalex", currentframe, tag, p->scalex);
+ history_begin(i->history, "scaley", currentframe, tag, p->scaley);
+ history_begin(i->history, "cxform.r0", currentframe, tag, p->cxform.r0);
+ history_begin(i->history, "cxform.g0", currentframe, tag, p->cxform.g0);
+ history_begin(i->history, "cxform.b0", currentframe, tag, p->cxform.b0);
+ history_begin(i->history, "cxform.a0", currentframe, tag, p->cxform.a0);
+ history_begin(i->history, "cxform.r1", currentframe, tag, p->cxform.r1);
+ history_begin(i->history, "cxform.g1", currentframe, tag, p->cxform.g1);
+ history_begin(i->history, "cxform.b1", currentframe, tag, p->cxform.b1);
+ history_begin(i->history, "cxform.a1", currentframe, tag, p->cxform.a1);
+ history_begin(i->history, "rotate", currentframe, tag, p->rotate);
+ history_begin(i->history, "shear", currentframe, tag, p->shear);
+ history_begin(i->history, "pivot.x", currentframe, tag, p->pivot.x);
+ history_begin(i->history, "pivot.y", currentframe, tag, p->pivot.y);
+ history_begin(i->history, "pin.x", currentframe, tag, p->pin.x);
+ history_begin(i->history, "pin.y", currentframe, tag, p->pin.y);
+ history_begin(i->history, "blendmode", currentframe, tag, p->blendmode);
+ history_beginFilter(i->history, currentframe, tag, p->filter);
}
void s_put(char*instance, char*character, parameters_t p)
character_t* c = dictionary_lookup(&characters, character);
instance_t* i;
MATRIX m;
- if(!c) {
- syntaxerror("character %s not known (in .put %s=%s)", character, instance, character);
- }
+ if(!c)
+ syntaxerror("character %s not known (in .put %s=%s)", character, instance, character);
i = s_addinstance(instance, c, currentdepth);
i->parameters = p;
m = s_instancepos(i->character->size, &p);
- if(p.blendmode || p.filter) {
- if(stack[0].swf->fileVersion < 8) {
- if(p.blendmode) warning("blendmodes only supported for flash version>=8");
- else warning("filters only supported for flash version>=8");
+ if(p.blendmode || p.filter)
+ {
+ if(stack[0].swf->fileVersion < 8)
+ {
+ if(p.blendmode)
+ warning("blendmodes only supported for flash version>=8");
+ else
+ warning("filters only supported for flash version>=8");
+ }
+ tag = swf_InsertTag(tag, ST_PLACEOBJECT3);
}
- tag = swf_InsertTag(tag, ST_PLACEOBJECT3);
- } else {
- tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
- }
+ else
+ tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
setPlacement(tag, c->id, currentdepth, m, instance, &p, 0);
-
+ setStartparameters(i, &p, tag);
i->lastTag = tag;
i->lastFrame = currentframe;
currentdepth++;
-
}
-void s_jump(char*instance, parameters_t p)
+void recordChanges(history_t* history, parameters_t p, int changeFunction, interpolation_t* inter)
{
- instance_t* i = dictionary_lookup(&instances, instance);
- MATRIX m;
- if(!i) {
- syntaxerror("instance %s not known", instance);
+ if (p.set & SF_X)
+ history_remember(history, "x", currentframe, changeFunction, p.x, inter);
+ if (p.set & SF_Y)
+ history_remember(history, "y", currentframe, changeFunction, p.y, inter);
+ if (p.set & SF_SCALEX)
+ history_remember(history, "scalex", currentframe, changeFunction, p.scalex, inter);
+ if (p.set & SF_SCALEY)
+ history_remember(history, "scaley", currentframe, changeFunction, p.scaley, inter);
+ if (p.set & SF_CX_R)
+ {
+ history_remember(history, "cxform.r0", currentframe, changeFunction, p.cxform.r0, inter);
+ history_remember(history, "cxform.r1", currentframe, changeFunction, p.cxform.r1, inter);
}
-
- i->parameters = p;
- m = s_instancepos(i->character->size, &p);
-
- if(p.blendmode || p.filter) {
- tag = swf_InsertTag(tag, ST_PLACEOBJECT3);
- } else {
- tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+ if (p.set & SF_CX_G)
+ {
+ history_remember(history, "cxform.g0", currentframe, changeFunction, p.cxform.g0, inter);
+ history_remember(history, "cxform.g1", currentframe, changeFunction, p.cxform.g1, inter);
}
- setPlacement(tag, 0, i->depth, m, 0, &p, 1);
-
- i->lastTag = tag;
- i->lastFrame = currentframe;
-}
-
-RGBA interpolateColor(RGBA c1, RGBA c2, float ratio)
-{
- RGBA c;
- c.r = c1.r * (1-ratio) + c2.r * ratio;
- c.g = c1.g * (1-ratio) + c2.g * ratio;
- c.b = c1.b * (1-ratio) + c2.b * ratio;
- c.a = c1.a * (1-ratio) + c2.a * ratio;
- return c;
-}
-
-FILTER* interpolateFilter(FILTER*filter1,FILTER*filter2, float ratio)
-{
- if(!filter1 && !filter2)
- return 0;
- if(!filter1)
- return interpolateFilter(filter2,filter1,1-ratio);
-
- if(filter2 && filter2->type != filter1->type)
- syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]);
-
- if(filter1->type == FILTERTYPE_BLUR) {
- FILTER_BLUR*f1 = (FILTER_BLUR*)filter1;
- FILTER_BLUR*f2 = (FILTER_BLUR*)filter2;
- if(f2 && f1->blurx == f2->blurx && f1->blury == f2->blury)
- return 0;
- FILTER_BLUR*f = (FILTER_BLUR*)swf_NewFilter(FILTERTYPE_BLUR);
- f->blurx= (f1->blurx)*(1-ratio) + (f2?f2->blurx:0)*ratio;
- f->blury= (f1->blury)*(1-ratio) + (f2?f2->blury:0)*ratio;
- f->passes= (f1->passes)*(1-ratio) + (f2?f2->passes:0)*ratio;
- return (FILTER*)f;
- } else if (filter1->type == FILTERTYPE_DROPSHADOW) {
- FILTER_DROPSHADOW*f1 = (FILTER_DROPSHADOW*)filter1;
- FILTER_DROPSHADOW*f2 = (FILTER_DROPSHADOW*)filter2;
- if(f2 && !memcmp(&f1->color,&f2->color,sizeof(RGBA)) && f1->strength == f2->strength &&
- f1->blurx == f2->blurx && f1->blury == f2->blury &&
- f1->angle == f2->angle && f1->distance == f2->distance)
- return 0;
- FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)swf_NewFilter(FILTERTYPE_DROPSHADOW);
- memcpy(f, f1, sizeof(FILTER_DROPSHADOW));
- f->color = interpolateColor(f1->color, f2->color, ratio);
- f->blurx= (f1->blurx)*(1-ratio) + (f2?f2->blurx:0)*ratio;
- f->blury= (f1->blury)*(1-ratio) + (f2?f2->blury:0)*ratio;
- f->passes= (f1->passes)*(1-ratio) + (f2?f2->passes:0)*ratio;
- f->angle= (f1->angle)*(1-ratio) + (f2?f2->angle:0)*ratio;
- f->distance= (f1->distance)*(1-ratio) + (f2?f2->distance:0)*ratio;
- f->strength= (f1->strength)*(1-ratio) + (f2?f2->strength:0)*ratio;
- return (FILTER*)f;
- } else if (filter1->type == FILTERTYPE_BEVEL) {
- FILTER_BEVEL*f1 = (FILTER_BEVEL*)filter1;
- FILTER_BEVEL*f2 = (FILTER_BEVEL*)filter2;
- if(f2 && !memcmp(&f1->shadow,&f2->shadow,sizeof(RGBA)) &&
- !memcmp(&f1->highlight,&f2->highlight,sizeof(RGBA)) &&
- f1->blurx == f2->blurx && f1->blury == f2->blury && f1->angle == f2->angle && f1->strength == f2->strength && f1->distance == f2->distance)
- return 0;
- FILTER_BEVEL*f = (FILTER_BEVEL*)swf_NewFilter(FILTERTYPE_BEVEL);
- memcpy(f, f1, sizeof(FILTER_BEVEL));
- f->shadow = interpolateColor(f1->shadow, f2->shadow, ratio);
- f->highlight = interpolateColor(f1->highlight, f2->highlight, ratio);
- f->blurx= (f1->blurx)*(1-ratio) + (f2?f2->blurx:0)*ratio;
- f->blury= (f1->blury)*(1-ratio) + (f2?f2->blury:0)*ratio;
- f->passes= (f1->passes)*(1-ratio) + (f2?f2->passes:0)*ratio;
- f->angle= (f1->angle)*(1-ratio) + (f2?f2->angle:0)*ratio;
- f->distance= (f1->distance)*(1-ratio) + (f2?f2->distance:0)*ratio;
- f->strength= (f1->strength)*(1-ratio) + (f2?f2->strength:0)*ratio;
- return (FILTER*)f;
- } /*else if (filter1->type == FILTERTYPE_GRADIENTGLOW) {
- FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW);
- // can't interpolate gradients
- memcpy(f, filter1, sizeof(FILTER_GRADIENTGLOW));
- return (FILTER*)f;
- }*/ else {
- syntaxerror("can't interpolate %s filters yet", filtername[filter1->type]);
+ if (p.set & SF_CX_B)
+ {
+ history_remember(history, "cxform.b0", currentframe, changeFunction, p.cxform.b0, inter);
+ history_remember(history, "cxform.b1", currentframe, changeFunction, p.cxform.b1, inter);
}
- return 0;
+ if (p.set & SF_CX_A)
+ {
+ history_remember(history, "cxform.a0", currentframe, changeFunction, p.cxform.a0, inter);
+ history_remember(history, "cxform.a1", currentframe, changeFunction, p.cxform.a1, inter);
+ }
+ if (p.set & SF_ROTATE)
+ history_remember(history, "rotate", currentframe, changeFunction, p.rotate, inter);
+ if (p.set & SF_SHEAR)
+ history_remember(history, "shear", currentframe, changeFunction, p.shear, inter);
+ if (p.set & SF_PIVOT)
+ {
+ history_remember(history, "pivot.x", currentframe, changeFunction, p.pivot.x, inter);
+ history_remember(history, "pivot.y", currentframe, changeFunction, p.pivot.y, inter);
+ }
+ if (p.set & SF_PIN)
+ {
+ history_remember(history, "pin.x", currentframe, changeFunction, p.pin.x, inter);
+ history_remember(history, "pin.y", currentframe, changeFunction, p.pin.y, inter);
+ }
+ if (p.set & SF_BLEND)
+ history_remember(history, "blendmode", currentframe, changeFunction, p.blendmode, inter);
+ if (p.set & SF_FILTER)
+ history_rememberFilter(history, currentframe, changeFunction, p.filter, inter);
}
-parameters_t s_interpolate(parameters_t*p1, parameters_t*p2, int pos, int num)
+void s_jump(char* instance, parameters_t p)
{
- parameters_t p;
- float ratio;
- if(num==0 || num==1)
- return *p1;
- ratio = (float)pos/(float)num;
-
- p.x = (p2->x-p1->x)*ratio + p1->x;
- p.y = (p2->y-p1->y)*ratio + p1->y;
- p.scalex = (p2->scalex-p1->scalex)*ratio + p1->scalex;
- p.scaley = (p2->scaley-p1->scaley)*ratio + p1->scaley;
- p.rotate = (p2->rotate-p1->rotate)*ratio + p1->rotate;
- p.shear = (p2->shear-p1->shear)*ratio + p1->shear;
-
- p.cxform.r0 = ((float)p2->cxform.r0-(float)p1->cxform.r0)*ratio + p1->cxform.r0;
- p.cxform.g0 = ((float)p2->cxform.g0-(float)p1->cxform.g0)*ratio + p1->cxform.g0;
- p.cxform.b0 = ((float)p2->cxform.b0-(float)p1->cxform.b0)*ratio + p1->cxform.b0;
- p.cxform.a0 = ((float)p2->cxform.a0-(float)p1->cxform.a0)*ratio + p1->cxform.a0;
-
- p.cxform.r1 = (p2->cxform.r1-p1->cxform.r1)*ratio + p1->cxform.r1;
- p.cxform.g1 = (p2->cxform.g1-p1->cxform.g1)*ratio + p1->cxform.g1;
- p.cxform.b1 = (p2->cxform.b1-p1->cxform.b1)*ratio + p1->cxform.b1;
- p.cxform.a1 = (p2->cxform.a1-p1->cxform.a1)*ratio + p1->cxform.a1;
-
- p.pivot.x = (p2->pivot.x-p1->pivot.x)*ratio + p1->pivot.x;
- p.pivot.y = (p2->pivot.y-p1->pivot.y)*ratio + p1->pivot.y;
- p.pin.x = (p2->pin.x-p1->pin.x)*ratio + p1->pin.x;
- p.pin.y = (p2->pin.y-p1->pin.y)*ratio + p1->pin.y;
-
- p.filter = interpolateFilter(p1->filter, p2->filter, ratio);
- return p;
+ instance_t* i = dictionary_lookup(&instances, instance);
+ if(!i)
+ syntaxerror("instance %s not known", instance);
+ recordChanges(i->history, p, CF_JUMP, 0);
}
-void s_change(char*instance, parameters_t p2)
+void s_change(char*instance, parameters_t p2, interpolation_t* inter)
{
instance_t* i = dictionary_lookup(&instances, instance);
- MATRIX m;
- parameters_t p1;
- TAG*t;
- int frame, allframes;
- if(!i) {
- syntaxerror("instance %s not known", instance);
- }
- p1 = i->parameters;
-
- allframes = currentframe - i->lastFrame - 1;
- if(allframes < 0) {
- warning(".change ignored. can only .put/.change an object once per frame.");
- return;
- }
-
- m = s_instancepos(i->character->size, &p2);
- if(p2.blendmode || p2.filter) {
- tag = swf_InsertTag(tag, ST_PLACEOBJECT3);
- } else {
- tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
- }
- setPlacement(tag, 0, i->depth, m, 0, &p2, 1);
- i->parameters = p2;
-
- /* o.k., we got the start and end point set. Now iterate though all the
- tags in between, inserting object changes after each new frame */
- t = i->lastTag;
- i->lastTag = tag;
- if(!t) syntaxerror("internal error(6)");
- frame = 0;
- while(frame < allframes) {
- if(t->id == ST_SHOWFRAME) {
- parameters_t p;
- MATRIX m;
- TAG*lt;
- frame ++;
- p = s_interpolate(&p1, &p2, frame, allframes);
- m = s_instancepos(i->character->size, &p); //needed?
-
- i->lastFrame = currentframe;
- if(p.blendmode || p.filter) {
- lt = swf_InsertTag(t, ST_PLACEOBJECT3);
- } else {
- lt = swf_InsertTag(t, ST_PLACEOBJECT2);
- }
- setPlacement(lt, 0, i->depth, m, 0, &p, 1);
- t = lt;
- if(frame == allframes)
- break;
- }
- t = t->next;
- if(!t)
- syntaxerror("internal error(8) (frame=%d/%d)", frame, allframes);
- }
+ if(!i)
+ syntaxerror("instance %s not known", instance);
+ recordChanges(i->history, p2, CF_CHANGE, inter);
}
void s_delinstance(char*instance)
{
instance_t* i = dictionary_lookup(&instances, instance);
- if(!i) {
- syntaxerror("instance %s not known", instance);
- }
+ if(!i)
+ syntaxerror("instance %s not known", instance);
tag = swf_InsertTag(tag, ST_REMOVEOBJECT2);
swf_SetU16(tag, i->depth);
dictionary_del(&instances, instance);
void s_qchange(char*instance, parameters_t p)
{
+ instance_t* i = dictionary_lookup(&instances, instance);
+ if(!i)
+ syntaxerror("instance %s not known", instance);
+ recordChanges(i->history, p, CF_QCHANGE, 0);
}
void s_end()
{
if(!stackpos)
syntaxerror(".end unexpected");
- if(stack[stackpos-1].type == 0)
- s_endSWF();
- else if(stack[stackpos-1].type == 1)
- s_endSprite();
- else if(stack[stackpos-1].type == 2)
- s_endClip();
- else if(stack[stackpos-1].type == 3)
- s_endButton();
- else syntaxerror("internal error 1");
+ switch (stack[stackpos-1].type)
+ {
+ case 0:
+ s_endSWF();
+ break;
+ case 1:
+ s_endSprite();
+ break;
+ case 2:
+ s_endClip();
+ break;
+ case 3:
+ s_endButton();
+ break;
+ default:
+ syntaxerror("internal error 1");
+ }
}
// ------------------------------------------------------------------------
char*s;
*dot++ = 0;
for(s=str;s<dot-1;s++)
- if(*s<'0' || *s>'9')
- syntaxerror("Not a coordinate: \"%s\"", str);
- for(s=dot;*s;s++) {
- if(*s<'0' || *s>'9')
- syntaxerror("Not a coordinate: \"%s\"", str);
- }
+ if(*s<'0' || *s>'9')
+ {
+ free(old);
+ syntaxerror("Not a coordinate: \"%s\"", str);
+ }
+ for(s=dot;*s;s++)
+ if(*s<'0' || *s>'9')
+ {
+ free(old);
+ syntaxerror("Not a coordinate: \"%s\"", str);
+ }
if(l>2 || (l==2 && (dot[1]!='0' && dot[1]!='5'))) {
dot[1] = ((dot[1]-0x30)/5)*5 + 0x30;
dot[2] = 0;
static mem_t mpoints;
int points_initialized = 0;
+static int c_interpolation(map_t *args)
+{
+ int i;
+ char* name = lu(args, "name");
+ if (dictionary_lookup(&interpolations, name))
+ syntaxerror("interpolation %s defined twice", name);
+
+ interpolation_t* inter = (interpolation_t*)malloc(sizeof(interpolation_t));
+ char* functionstr = lu(args, "function");
+ inter->function = 0;
+ for (i = 0; i < sizeof(interpolationFunctions) / sizeof(interpolationFunctions[0]); i++)
+ if (!strcmp(functionstr,interpolationFunctions[i]))
+ {
+ inter->function = i + 1;
+ break;
+ }
+ if (!inter->function)
+ syntaxerror("unkown interpolation function %s", functionstr);
+ inter->speed = parseFloat(lu(args, "speed"));
+ inter->amplitude = parseFloat(lu(args, "amplitude"));
+ inter->growth = parseFloat(lu(args, "growth"));
+ inter->bounces = parseInt(lu(args, "bounces"));
+ inter->damping = parseInt(lu(args, "damping"));
+
+ dictionary_put2(&interpolations, name, inter);
+ return 0;
+}
+
SPOINT getPoint(SRECT r, char*name)
{
int l=0;
readToken();
if(type != RAWDATA)
- syntaxerror("colon (:) expected");
+ syntaxerror("colon (:) expected");
+
+ if(dictionary_lookup(&gradients, name))
+ syntaxerror("gradient %s defined twice", name);
s_gradient(name, text, radial, rotate);
{
char*name = map_lookup(args, "name");
- if(s_playsound(name, 0,0,1)) {
- return 0;
- } else if(s_swf3action(name, "stop")) {
- return 0;
- }
+ if(s_playsound(name, 0,0,1))
+ return 0;
+ else if(s_swf3action(name, "stop"))
+ return 0;
syntaxerror("I don't know anything about sound/movie \"%s\"", name);
- return 0;
+ return 0;
}
static int c_nextframe(map_t*args)
char* pinstr = lu(args, "pin");
char* as = map_lookup(args, "as");
char* blendmode = lu(args, "blend");
- char*filterstr = lu(args, "filter");
+ char* filterstr = lu(args, "filter");
U8 blend;
MULADD r,g,b,a;
float oldwidth;
SRECT oldbbox;
MULADD luminance;
parameters_t p;
+ U32 set = 0x00000000;
- if(type==9) { // (?) .rotate or .arcchange
- pivotstr = lu(args, "pivot");
- anglestr = lu(args, "angle");
- } else {
- xstr = lu(args, "x");
- ystr = lu(args, "y");
+ if(type==9)
+ { // (?) .rotate or .arcchange
+ pivotstr = lu(args, "pivot");
+ anglestr = lu(args, "angle");
+ }
+ else
+ {
+ xstr = lu(args, "x");
+ ystr = lu(args, "y");
}
+
if(luminancestr[0])
- luminance = parseMulAdd(luminancestr);
- else {
- luminance.add = 0;
- luminance.mul = 256;
+ luminance = parseMulAdd(luminancestr);
+ else
+ {
+ luminance.add = 0;
+ luminance.mul = 256;
}
- if(scalestr[0]) {
- if(scalexstr[0]||scaleystr[0])
- syntaxerror("scalex/scaley and scale cannot both be set");
- scalexstr = scaleystr = scalestr;
+ if(scalestr[0])
+ {
+ if(scalexstr[0]||scaleystr[0])
+ syntaxerror("scalex/scaley and scale cannot both be set");
+ scalexstr = scaleystr = scalestr;
}
if(type == 0 || type == 4) {
}
/* x,y position */
- if(xstr[0]) {
- if(isRelative(xstr)) {
- if(type == 0 || type == 4)
- syntaxerror("relative x values not allowed for initial put or startclip");
- p.x += parseTwip(getOffset(xstr))*getSign(xstr);
- } else {
- p.x = parseTwip(xstr);
- }
- }
- if(ystr[0]) {
- if(isRelative(ystr)) {
- if(type == 0 || type == 4)
- syntaxerror("relative y values not allowed for initial put or startclip");
- p.y += parseTwip(getOffset(ystr))*getSign(ystr);
- } else {
- p.y = parseTwip(ystr);
+ if(xstr[0])
+ {
+ if(isRelative(xstr))
+ {
+ if(type == 0 || type == 4)
+ syntaxerror("relative x values not allowed for initial put or startclip");
+ p.x += parseTwip(getOffset(xstr))*getSign(xstr);
+ }
+ else
+ {
+ p.x = parseTwip(xstr);
+ }
+ set = set | SF_X;
+ }
+ if(ystr[0])
+ {
+ if(isRelative(ystr))
+ {
+ if(type == 0 || type == 4)
+ syntaxerror("relative y values not allowed for initial put or startclip");
+ p.y += parseTwip(getOffset(ystr))*getSign(ystr);
+ }
+ else
+ {
+ p.y = parseTwip(ystr);
+ }
+ set = set | SF_Y;
}
- }
/* scale, scalex, scaley */
- if(character) {
- oldbbox = s_getCharBBox(character);
- } else {
- oldbbox = s_getInstanceBBox(instance);
- }
+ if(character)
+ oldbbox = s_getCharBBox(character);
+ else
+ oldbbox = s_getInstanceBBox(instance);
oldwidth = oldbbox.xmax - oldbbox.xmin;
oldheight = oldbbox.ymax - oldbbox.ymin;
- if(scalexstr[0]) {
- if(oldwidth==0) p.scalex = 1.0;
- else {
- if(scalexstr[0])
- p.scalex = (float)(parseNewSize(scalexstr, oldwidth))/oldwidth;
- }
- }
- if(scaleystr[0]) {
- if(oldheight==0) p.scaley = 1.0;
- else {
- if(scaleystr[0])
- p.scaley = (float)(parseNewSize(scaleystr, oldheight))/oldheight;
- }
- }
+ if(scalexstr[0])
+ {
+ if(oldwidth==0)
+ p.scalex = 1.0;
+ else
+ if(scalexstr[0])
+ p.scalex = (float)(parseNewSize(scalexstr, oldwidth))/oldwidth;
+ set = set | SF_SCALEX;
+ }
+ if(scaleystr[0])
+ {
+ if(oldheight==0)
+ p.scaley = 1.0;
+ else
+ if(scaleystr[0])
+ p.scaley = (float)(parseNewSize(scaleystr, oldheight))/oldheight;
+ set = set | SF_SCALEY;
+ }
/* rotation */
- if(rotatestr[0]) {
- if(isRelative(rotatestr)) {
- p.rotate += parseFloat(getOffset(rotatestr))*getSign(rotatestr);
- } else {
- p.rotate = parseFloat(rotatestr);
+ if(rotatestr[0])
+ {
+ if(isRelative(rotatestr))
+ p.rotate += parseFloat(getOffset(rotatestr))*getSign(rotatestr);
+ else
+ p.rotate = parseFloat(rotatestr);
+ set = set | SF_ROTATE;
}
- }
/* shearing */
- if(shearstr[0]) {
- if(isRelative(shearstr)) {
- p.shear += parseFloat(getOffset(shearstr))*getSign(shearstr);
- } else {
- p.shear = parseFloat(shearstr);
- }
+ if(shearstr[0])
+ {
+ if(isRelative(shearstr))
+ p.shear += parseFloat(getOffset(shearstr))*getSign(shearstr);
+ else
+ p.shear = parseFloat(shearstr);
+ set = set | SF_SHEAR;
}
- if(pivotstr[0]) {
- if(isPoint(pivotstr))
- p.pivot = parsePoint(pivotstr);
- else
- p.pivot = getPoint(oldbbox, pivotstr);
+ if(pivotstr[0])
+ {
+ if(isPoint(pivotstr))
+ p.pivot = parsePoint(pivotstr);
+ else
+ p.pivot = getPoint(oldbbox, pivotstr);
+ set = set | SF_PIVOT;
}
- if(pinstr[0]) {
- if(isPoint(pinstr))
- p.pin = parsePoint(pinstr);
- else
- p.pin = getPoint(oldbbox, pinstr);
+
+ if(pinstr[0])
+ {
+ if(isPoint(pinstr))
+ p.pin = parsePoint(pinstr);
+ else
+ p.pin = getPoint(oldbbox, pinstr);
+ set = set | SF_PIN;
}
/* color transform */
- if(rstr[0] || luminancestr[0]) {
- MULADD r;
- if(rstr[0])
- r = parseMulAdd(rstr);
- else {
- r.add = p.cxform.r0;
- r.mul = p.cxform.r1;
- }
- r = mergeMulAdd(r, luminance);
- p.cxform.r0 = r.mul;p.cxform.r1 = r.add;
- }
- if(gstr[0] || luminancestr[0]) {
- MULADD g;
- if(gstr[0])
- g = parseMulAdd(gstr);
- else {
- g.add = p.cxform.g0;
- g.mul = p.cxform.g1;
- }
- g = mergeMulAdd(g, luminance);
- p.cxform.g0 = g.mul;p.cxform.g1 = g.add;
- }
- if(bstr[0] || luminancestr[0]) {
- MULADD b;
- if(bstr[0])
- b = parseMulAdd(bstr);
- else {
- b.add = p.cxform.b0;
- b.mul = p.cxform.b1;
+ if(rstr[0] || luminancestr[0])
+ {
+ MULADD r;
+ if(rstr[0])
+ r = parseMulAdd(rstr);
+ else
+ {
+ r.add = p.cxform.r0;
+ r.mul = p.cxform.r1;
+ }
+ r = mergeMulAdd(r, luminance);
+ p.cxform.r0 = r.mul;
+ p.cxform.r1 = r.add;
+ set = set | SF_CX_R;
}
- b = mergeMulAdd(b, luminance);
- p.cxform.b0 = b.mul;p.cxform.b1 = b.add;
- }
- if(astr[0]) {
- MULADD a = parseMulAdd(astr);
- p.cxform.a0 = a.mul;p.cxform.a1 = a.add;
+ if(gstr[0] || luminancestr[0])
+ {
+ MULADD g;
+ if(gstr[0])
+ g = parseMulAdd(gstr);
+ else
+ {
+ g.add = p.cxform.g0;
+ g.mul = p.cxform.g1;
+ }
+ g = mergeMulAdd(g, luminance);
+ p.cxform.g0 = g.mul;
+ p.cxform.g1 = g.add;
+ set = set | SF_CX_G;
+ }
+ if(bstr[0] || luminancestr[0])
+ {
+ MULADD b;
+ if(bstr[0])
+ b = parseMulAdd(bstr);
+ else
+ {
+ b.add = p.cxform.b0;
+ b.mul = p.cxform.b1;
+ }
+ b = mergeMulAdd(b, luminance);
+ p.cxform.b0 = b.mul;
+ p.cxform.b1 = b.add;
+ set = set | SF_CX_B;
+ }
+ if(astr[0])
+ {
+ MULADD a = parseMulAdd(astr);
+ p.cxform.a0 = a.mul;
+ p.cxform.a1 = a.add;
+ set = set | SF_CX_A;
}
- if(blendmode[0]) {
- int t;
- blend = 255;
- for(t=0;blendModeNames[t];t++) {
- if(!strcmp(blendModeNames[t], blendmode)) {
- blend = t;
- break;
- }
- }
- if(blend == 255) {
- syntaxerror("unknown blend mode: '%s'", blendmode);
+ if(blendmode[0])
+ {
+ int t;
+ blend = 255;
+ for(t = 0; blendModeNames[t]; t++)
+ {
+ if(!strcmp(blendModeNames[t], blendmode))
+ {
+ blend = t;
+ break;
+ }
+ }
+ if(blend == 255)
+ {
+ syntaxerror("unknown blend mode: '%s'", blendmode);
+ }
+ p.blendmode = blend;
+ set = set | SF_BLEND;
}
- p.blendmode = blend;
- }
- if(filterstr[0]) {
- FILTER*f = dictionary_lookup(&filters, filterstr);
- if(!f)
- syntaxerror("Unknown filter %s", filterstr);
- p.filter = f;
- }
-
-
- if(type == 0)
- s_put(instance, character, p);
- else if(type == 1)
- s_change(instance, p);
- else if(type == 2)
- s_qchange(instance, p);
- else if(type == 3)
- s_jump(instance, p);
- else if(type == 4)
- s_startclip(instance, character, p);
- else if(type == 5) {
- if(as && as[0]) {
- s_buttonput(character, as, p);
- } else {
- s_buttonput(character, "shape", p);
- }
+ if(filterstr[0])
+ {
+ FILTER*f = dictionary_lookup(&filters, filterstr);
+ if(!f)
+ syntaxerror("Unknown filter %s", filterstr);
+ p.filter = f;
+ set = set | SF_FILTER;
}
+
+ p.set = set;
+
+ switch (type)
+ {
+ case 0:
+ s_put(instance, character, p);
+ break;
+ case 1:
+ {
+ char* interstr = lu(args, "interpolation");
+ interpolation_t* inter = (interpolation_t*)dictionary_lookup(&interpolations, interstr);
+ if (!inter)
+ syntaxerror("unkown interpolation %s", interstr);
+ s_change(instance, p, inter);
+ }
+ break;
+ case 2:
+ s_qchange(instance, p);
+ break;
+ case 3:
+ s_jump(instance, p);
+ break;
+ case 4:
+ s_startclip(instance, character, p);
+ break;
+ case 5:
+ if(as && as[0])
+ s_buttonput(character, as, p);
+ else
+ s_buttonput(character, "shape", p);
+ break;
+// default:
+ }
return 0;
}
static int c_put(map_t*args)
}
static int c_change(map_t*args)
{
+ if (currentframe == 0)
+ warning("change commands in frame 1 will be ignored, please use the put command to set object parameters");
c_placement(args, 1);
return 0;
}
{
char*name = lu(args, "name");
char*filename = lu(args, "filename");
- s_font(name, filename);
+ fontData* usage = getFontData(name);
+ char* glyphs = usage->glyphs;
+ if (usage->needsAll)
+ glyphs = "";
+ else
+ if (usage->notUsed)
+ {
+ printf("font %s was defined but not used\n", name);
+ return 0;
+ }
+ s_font(name, filename, glyphs);
return 0;
}
{"font", c_font, "name filename"},
{"soundtrack", c_soundtrack, "filename"},
{"quicktime", c_quicktime, "url"},
-
+
// generators of primitives
{"point", c_point, "name x=0 y=0"},
{"gradient", c_gradient, "name @radial=0 rotate=0 scale= scalex= scaley= x= y= width= height= r= shear="}, //extra parameters like .texture
+ {"interpolation", c_interpolation, "name function=linear speed=1.3 amplitude=0 bounces=2 growth=1.5, damping=2"},
{"outline", c_outline, "name format=simple"},
{"textshape", c_textshape, "name font size=100% text"},
// object placement tags
{"put", c_put, "<i> x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
{"startclip", c_startclip, "<i> x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
- {"change", c_change, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
+ {"change", c_change, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= interpolation=linear"},
{"arcchange", c_arcchange, "name pivot= angle= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
{"qchange", c_qchange, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
{"jump", c_jump, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},