From: kramm Date: Tue, 7 Aug 2007 17:18:55 +0000 (+0000) Subject: Huub Schaek's interpolation patch X-Git-Tag: buttons-working~598 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=8f9567dee2a2bbcd105d8a32538e660e1a01870e Huub Schaek's interpolation patch --- diff --git a/src/swfc-history.c b/src/swfc-history.c index 40f694c..1a8b609 100644 --- a/src/swfc-history.c +++ b/src/swfc-history.c @@ -48,12 +48,65 @@ void change_init(change_t* change) void change_append(change_t* first, change_t* newChange) { + change_t* previous = 0; + change_t* start = first; + float p0, p1, m0, m1; + while (first->next) + { + previous = first; first = first->next; + } first->next = newChange; + if (first->function == CF_QCHANGE) + { + p0 = previous->value; + p1 = first->value; + if (previous->function == CF_QCHANGE) + m0 = (3 * previous->spline.a + 2 * previous->spline.b + previous->spline.c); + else + if (previous->function == CF_CHANGE) + m0 = (change_value(start, previous->frame) - change_value(start, previous->frame - 1)) * (first->frame - previous->frame); + else + m0 = (first->value - previous->value); + if (newChange->function == CF_QCHANGE) + m1 = 0.5 * (newChange->value - previous->value); + else + if (newChange->function == CF_CHANGE) + m1 = (change_value(previous, first->frame + 1) - change_value(previous, first->frame)) * (first->frame - previous->frame); + else + m1 = (first->value - previous->value); + first->spline.a = 2 * p0 + m0 - 2 * p1 + m1; + first->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1; + first->spline.c = m0; + first->spline.d = p0; + } + if (newChange->function == CF_QCHANGE) + { + p0 = first->value; + p1 = newChange->value; + if (first->function == CF_QCHANGE) + m0 = m1; + else + if (first->function == CF_CHANGE) + m0 = (change_value(start, first->frame) - change_value(start, first->frame - 1)) * (first->frame - previous->frame); + else + m0 = (newChange->value - first->value); + m1 = (newChange->value - first->value); + newChange->spline.a = 2 * p0 + m0 - 2 * p1 + m1; + newChange->spline.b = -3 * p0 - 2 * m0 + 3 * p1 - m1; + newChange->spline.c = m0; + newChange->spline.d = p0; + } } -float interpolateParameter(float p1, float p2, float fraction, interpolation_t* inter) +float calculateSpline(change_t* modification, float fraction) +{ + spline_t s = modification->spline; + return (((s.a * fraction) + s.b) * fraction + s.c) * fraction + s.d; +} + +float interpolateScalar(float p1, float p2, float fraction, interpolation_t* inter) { if (!inter) return linear(fraction, p1, p2 - p1); @@ -97,35 +150,54 @@ float interpolateParameter(float p1, float p2, float fraction, interpolation_t* } } -float change_value(change_t* first, U16 frame) +int change_differs(change_t* modification, U16 frame) { - change_t* previous = first; - while (first && first->frame < frame) + change_t* previous = modification; + while (modification && modification->frame < frame) { - previous = first; - first = first->next; + previous = modification; + modification = modification->next; + } + if (!modification) + return 0; + if (modification->frame == frame) + return 1; + return (modification->function != CF_JUMP); } - if (!first) + +float change_value(change_t* modification, U16 frame) +{ + change_t* previous = modification; + while (modification && modification->frame < frame) + { + previous = modification; + modification = modification->next; + } + if (!modification) return previous->value; - if (first->frame == frame) + if (modification->frame == frame) { - float result; do { - result = first->value; - first = first->next; + previous = modification; + modification = modification->next; } - while (first && first->frame == frame); - return result; + while (modification && modification->frame == frame); + return previous->value; } - switch (first->function) + switch (modification->function) { case CF_PUT: - return first->value; + return modification->value; case CF_CHANGE: { - float fraction = (frame - previous->frame) / (float)(first->frame - previous->frame); - return interpolateParameter(previous->value, first->value, fraction, first->interpolation); + float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame); + return interpolateScalar(previous->value, modification->value, fraction, modification->interpolation); + } + case CF_QCHANGE: + { + float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame); + return calculateSpline(modification, fraction); } case CF_JUMP: return previous->value; @@ -167,61 +239,195 @@ void changeFilter_append(changeFilter_t* first, changeFilter_t* 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; + c.r = interpolateScalar(c1.r, c2.r, ratio, inter); + c.g = interpolateScalar(c1.g, c2.g, ratio, inter); + c.b = interpolateScalar(c1.b, c2.b, ratio, inter); + c.a = interpolateScalar(c1.a, c2.a, ratio, inter); return c; } -FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter) +GRADIENT* interpolateNodes(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter) { - if(!filter1 && !filter2) - return 0; - if(!filter1) - return interpolateFilter(filter2,filter1,1-ratio, inter); + if (g1->num != g2->num) + syntaxerror("Internal error: gradients are not equal in size"); - if(filter2 && filter2->type != filter1->type) - syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]); + int i; + GRADIENT* g = (GRADIENT*) malloc(sizeof(GRADIENT)); + g->ratios = rfx_calloc(16*sizeof(U8)); + g->rgba = rfx_calloc(16*sizeof(RGBA)); + g->num = g1->num; + for (i = 0; i < g->num; i++) + { + g->ratios[i] = interpolateScalar(g1->ratios[i], g2->ratios[i], fraction, inter); + g->rgba[i] = interpolateColor(g1->rgba[i], g2->rgba[i], fraction, inter); + } + return g; +} + +void copyGradient(GRADIENT* dest, GRADIENT* source) +{ + dest->num = source->num; + memcpy(dest->ratios, source->ratios, source->num * sizeof(U8)); + memcpy(dest->rgba, source->rgba, source->num * sizeof(RGBA)); +} + +void insertNode(GRADIENT* g, int pos) +{ + memmove(&g->ratios[pos + 1], &g->ratios[pos], (g->num - pos) * sizeof(U8)); + memmove(&g->rgba[pos + 1], &g->rgba[pos], (g->num - pos) * sizeof(RGBA)); + if (pos == 0) + { + g->ratios[0] = g->ratios[1] / 2; + g->rgba[0] = g->rgba[1]; + } + else + if (pos == g->num) + { + g->ratios[pos] = (255 + g->ratios[g->num - 1]) / 2; + g->rgba[pos] = g->rgba[pos - 1]; + } + else + { + g->ratios[pos] = (g->ratios[pos - 1] + g->ratios[pos + 1]) / 2; + g->rgba[pos] = interpolateColor(g->rgba[pos - 1], g->rgba[pos + 1], 0.5, 0); + } + g->num++; +} + +void insertOptimalNode(GRADIENT* g) +{ + int i, next_gap; + int pos = 0; + int gap = g->ratios[0]; + for (i = 0; i < g->num - 1; i++) + { + next_gap = g->ratios[i + 1] - g->ratios[i]; + if (next_gap > gap) + { + gap = next_gap; + pos = i + 1; + } + } + next_gap = 255 - g->ratios[g->num -1]; + if (next_gap > gap) + pos = g->num; + insertNode(g, pos); +} - if(filter1->type == FILTERTYPE_BLUR) +void growGradient(GRADIENT* start, int size) +{ + while (start->num < size) + insertOptimalNode(start); +} + +GRADIENT* interpolateGradient(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter) +{ + int i; + GRADIENT g; + g.ratios = rfx_calloc(16*sizeof(U8)); + g.rgba = rfx_calloc(16*sizeof(RGBA)); + + if (g1->num > g2->num) + { + copyGradient(&g, g2); + growGradient(&g, g1->num); + GRADIENT* result = interpolateNodes(g1, &g, fraction, inter); + rfx_free(g.rgba); + rfx_free(g.ratios); + return result; + } + else + if (g1->num < g2->num) + { + copyGradient(&g, g1); + growGradient(&g, g2->num); + GRADIENT* result = interpolateNodes(&g, g2, fraction, inter); + rfx_free(g.rgba); + rfx_free(g.ratios); + return result; + } + else + return interpolateNodes(g1, g2, fraction, inter); +} + +FILTER* interpolateBlur(FILTER* filter1, FILTER* filter2, float ratio, interpolation_t* inter) { FILTER_BLUR*f1 = (FILTER_BLUR*)filter1; FILTER_BLUR*f2 = (FILTER_BLUR*)filter2; - if(f2 && f1->blurx == f2->blurx && f1->blury == f2->blury) + if (!f1) + f1 = noBlur; + if (!f2) + f2 = noBlur; + if(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; + f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter); + f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter); + f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter); return (FILTER*)f; } - else - if (filter1->type == FILTERTYPE_DROPSHADOW) + +void matchDropshadowFlags(FILTER_DROPSHADOW* unset, FILTER_DROPSHADOW* target) +{ + unset->innershadow = target->innershadow; + unset->knockout = target->knockout; + unset->composite = target->composite; +} + +FILTER* interpolateDropshadow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter) { 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 && + if (!f1) + f1 = noDropshadow; + if (!f2) + f2 = noDropshadow; + if(!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; + f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter); + f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter); + f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter); + f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter); + f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter); + f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter); + if (f1 == noDropshadow) + { + if (f2 != noDropshadow) + matchDropshadowFlags(f, f2); } else - if (filter1->type == FILTERTYPE_BEVEL) + if (f2 == noDropshadow) + matchDropshadowFlags(f, f1); + else + if (ratio > 0.5) + matchDropshadowFlags(f, f2); + else + matchDropshadowFlags(f, f1); + return (FILTER*)f; +} + +void matchBevelFlags(FILTER_BEVEL* unset, FILTER_BEVEL* target) +{ + unset->innershadow = target->innershadow; + unset->knockout = target->knockout; + unset->composite = target->composite; + unset->ontop = target->ontop; +} + +FILTER* interpolateBevel(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter) { FILTER_BEVEL*f1 = (FILTER_BEVEL*)filter1; FILTER_BEVEL*f2 = (FILTER_BEVEL*)filter2; - if(f2 && !memcmp(&f1->shadow,&f2->shadow,sizeof(RGBA)) && + if (!f1) + f1 = noBevel; + if (!f2) + f2 = noBevel; + if(!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; @@ -229,20 +435,113 @@ FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpol 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; + f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter); + f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter); + f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter); + f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter); + f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter); + f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter); + if (f1 == noBevel) + { + if (f2 != noBevel) + matchBevelFlags(f, f2); + } + else + if (f2 == noBevel) + matchBevelFlags(f, f1); + else + if (ratio > 0.5) + matchBevelFlags(f, f2); + else + matchBevelFlags(f, f1); return (FILTER*)f; - } /*else if (filter1->type == FILTERTYPE_GRADIENTGLOW) { +} + +void matchGradientGlowFlags(FILTER_GRADIENTGLOW* unset, FILTER_GRADIENTGLOW* target) +{ + unset->innershadow = target->innershadow; + unset->knockout = target->knockout; + unset->composite = target->composite; + unset->ontop = target->ontop; +} + +FILTER* interpolateGradientGlow(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter) +{ + FILTER_GRADIENTGLOW*f1 = (FILTER_GRADIENTGLOW*)filter1; + FILTER_GRADIENTGLOW*f2 = (FILTER_GRADIENTGLOW*)filter2; + if (!f1) + f1 = noGradientGlow; + if (!f2) + f2 = noGradientGlow; + if(f1->gradient->num == f2->gradient->num && + !memcmp(&f1->gradient->ratios,&f2->gradient->ratios,f1->gradient->num * sizeof(U8)) && + !memcmp(&f1->gradient->rgba,&f2->gradient->rgba,f1->gradient->num * 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_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)swf_NewFilter(FILTERTYPE_GRADIENTGLOW); - // can't interpolate gradients - memcpy(f, filter1, sizeof(FILTER_GRADIENTGLOW)); + memcpy(f, f1, sizeof(FILTER_GRADIENTGLOW)); + f->blurx= interpolateScalar(f1->blurx, (f2->blurx), ratio, inter); + f->blury= interpolateScalar(f1->blury, (f2->blury), ratio, inter); + f->passes= interpolateScalar(f1->passes, (f2->passes), ratio, inter); + f->angle= interpolateScalar(f1->angle, (f2->angle), ratio, inter); + f->distance= interpolateScalar(f1->distance, (f2->distance), ratio, inter); + double d = f->distance; + double fr; + if (d < 0) + fr = ((int)d - d)*65536; + else + fr = (d - (int)d)*65536; + printf("%.3f <> %.3f : %.3f = %.3f [%.3f . %.3f] - %.5u.%.5u\n", f1->distance, f2->distance, ratio, f->distance, d, fr/65536, (U16)d, (U16)fr); + f->strength= interpolateScalar(f1->strength, (f2->strength), ratio, inter); + f->gradient= interpolateGradient(f1->gradient, f2->gradient, ratio, inter); + if (f1 == noGradientGlow) + { + if (f2 != noGradientGlow) + matchGradientGlowFlags(f, f2); + } + else + if (f2 == noGradientGlow) + matchGradientGlowFlags(f, f1); + else + if (ratio > 0.5) + matchGradientGlowFlags(f, f2); + else + matchGradientGlowFlags(f, f1); return (FILTER*)f; - }*/ else - syntaxerror("can't interpolate %s filters yet", filtername[filter1->type]); +} + +FILTER* interpolateFilter(FILTER* filter1,FILTER* filter2, float ratio, interpolation_t* inter) +{ + if(!filter1 && !filter2) + return 0; + + + int filter_type; + if (!filter1) + filter_type = filter2->type; + else + if (!filter2) + filter_type = filter1->type; + else + if(filter2->type != filter1->type) + syntaxerror("can't interpolate between %s and %s filters yet", filtername[filter1->type], filtername[filter2->type]); + else + filter_type = filter1->type; + + + switch (filter_type) + { + case FILTERTYPE_BLUR: + return interpolateBlur(filter1, filter2, ratio, inter); + case FILTERTYPE_BEVEL: + return interpolateBevel(filter1, filter2, ratio, inter); + case FILTERTYPE_DROPSHADOW: + return interpolateDropshadow(filter1, filter2, ratio, inter); + case FILTERTYPE_GRADIENTGLOW: + return interpolateGradientGlow(filter1, filter2, ratio, inter); + default: + syntaxerror("Filtertype %s not supported yet.\n", filtername[filter1->type]); + } return 0; } @@ -257,7 +556,14 @@ FILTER* copyFilter(FILTER* original) memcpy(copy, original, sizeof(FILTER_BLUR)); break; case FILTERTYPE_GRADIENTGLOW: + { memcpy(copy, original, sizeof(FILTER_GRADIENTGLOW)); + FILTER_GRADIENTGLOW* ggcopy = (FILTER_GRADIENTGLOW*)copy; + ggcopy->gradient = (GRADIENT*)malloc(sizeof(GRADIENT)); + ggcopy->gradient->ratios = (U8*)malloc(16 * sizeof(U8)); + ggcopy->gradient->rgba = (RGBA*)malloc(16 * sizeof(RGBA)); + copyGradient(ggcopy->gradient, ((FILTER_GRADIENTGLOW*)original)->gradient); + } break; case FILTERTYPE_DROPSHADOW: memcpy(copy, original, sizeof(FILTER_DROPSHADOW)); @@ -265,40 +571,54 @@ FILTER* copyFilter(FILTER* original) case FILTERTYPE_BEVEL: memcpy(copy, original, sizeof(FILTER_BEVEL)); break; - default: printf("unsupported filterype"); + default: syntaxerror("Internal error: unsupported filterype"); } return copy; } -FILTER* changeFilter_value(changeFilter_t* first, U16 frame) +int changeFilter_differs(changeFilter_t* modification, U16 frame) { - changeFilter_t* previous = first; - while (first && first->frame < frame) + changeFilter_t* previous = modification; + while (modification && modification->frame < frame) { - previous = first; - first = first->next; + previous = modification; + modification = modification->next; } - if (!first) + if (!modification) + return 0; + if (modification->frame == frame) + return 1; + return (modification->function != CF_JUMP); +} + +FILTER* changeFilter_value(changeFilter_t* modification, U16 frame) +{ + changeFilter_t* previous = modification; + while (modification && modification->frame < frame) + { + previous = modification; + modification = modification->next; + } + if (!modification) return copyFilter(previous->value); - if (first->frame == frame) + if (modification->frame == frame) { - FILTER* result; do { - result = first->value; - first = first->next; + previous = modification; + modification = modification->next; } - while (first && first->frame == frame); - return copyFilter(result); + while (modification && modification->frame == frame); + return copyFilter(previous->value); } - switch (first->function) + switch (modification->function) { case CF_PUT: - return copyFilter(first->value); + return copyFilter(modification->value); case CF_CHANGE: { - float fraction = (frame - previous->frame) / (float)(first->frame - previous->frame); - return interpolateFilter(previous->value, first->value, fraction, first->interpolation); + float fraction = (frame - previous->frame) / (float)(modification->frame - previous->frame); + return interpolateFilter(previous->value, modification->value, fraction, modification->interpolation); } case CF_JUMP: return copyFilter(previous->value); @@ -382,6 +702,15 @@ void history_rememberFilter(history_t* past, U16 frame, int function, FILTER* va } } +int history_change(history_t* past, U16 frame, char* parameter) +{ + change_t* first = dictionary_lookup(past->changes, parameter); + if (first) //should always be true. + return change_differs(first, frame); + printf("no history found for parameter %s\n", parameter); + return 0; +} + float history_value(history_t* past, U16 frame, char* parameter) { change_t* first = dictionary_lookup(past->changes, parameter); @@ -391,6 +720,15 @@ float history_value(history_t* past, U16 frame, char* parameter) return 0; } +int history_changeFilter(history_t* past, U16 frame) +{ + changeFilter_t* first = dictionary_lookup(past->changes, "filter"); + if (first) //should always be true. + return changeFilter_differs(first, frame); + printf("no history found for parameter filter\n"); + return 0; +} + FILTER* history_valueFilter(history_t* past, U16 frame) { changeFilter_t* first = dictionary_lookup(past->changes, "filter"); diff --git a/src/swfc-history.h b/src/swfc-history.h index 00c5be4..b8529df 100644 --- a/src/swfc-history.h +++ b/src/swfc-history.h @@ -49,9 +49,19 @@ enum #define SF_SHEAR 0x0200 #define SF_PIVOT 0x0400 #define SF_PIN 0x0800 -#define SF_BLEND 0x01000 -#define SF_FILTER 0x02000 +#define SF_BLEND 0x1000 +#define SF_FILTER 0x2000 +#define SF_ALL 0x3fff +FILTER_BLUR* noBlur; +FILTER_BEVEL* noBevel; +FILTER_DROPSHADOW* noDropshadow; +FILTER_GRADIENTGLOW* noGradientGlow; + +typedef struct _spline +{ + float a, b, c, d; +} spline_t; typedef struct _change { @@ -59,6 +69,7 @@ typedef struct _change float value; int function; interpolation_t* interpolation; + spline_t spline; struct _change* next; } change_t; @@ -75,6 +86,7 @@ typedef struct _changeFilter int function; interpolation_t* interpolation; struct _changeFilter* next; + spline_t spline; } changeFilter_t; changeFilter_t* changeFilter_new(U16 frame, int function, FILTER* value, interpolation_t* inter); @@ -97,7 +109,9 @@ void history_begin(history_t* past, char* parameter, U16 frame, TAG* tag, float void history_beginFilter(history_t* past, U16 frame, TAG* tag, FILTER* value); void history_remember(history_t* past, char* parameter, U16 frame, int function, float value, interpolation_t* inter); void history_rememberFilter(history_t* past, U16 frame, int function, FILTER* value, interpolation_t* inter); +int history_change(history_t* past, U16 frame, char* parameter); float history_value(history_t* past, U16 frame, char* parameter); +int history_changeFilter(history_t* past, U16 frame); FILTER* history_valueFilter(history_t* past, U16 frame); #endif diff --git a/src/swfc.c b/src/swfc.c index 41e5b93..a93fea5 100644 --- a/src/swfc.c +++ b/src/swfc.c @@ -46,6 +46,7 @@ static int verbose = 2; static int optimize = 0; static int override_outputname = 0; static int do_cgi = 0; +static int change_sets_all = 0; static struct options_t options[] = { {"h", "help"}, @@ -446,7 +447,7 @@ static MATRIX s_instancepos(SRECT rect, parameters_t*p) return m; } -void builtInInterpolations() +void initBuiltIns() { interpolation_t* new; new = (interpolation_t*)malloc(sizeof(interpolation_t)); @@ -522,6 +523,34 @@ void builtInInterpolations() new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_SINE_IN_OUT; dictionary_put2(&interpolations, "sineInOut", new); + + RGBA c; + memset(&c, 0, sizeof(RGBA)); + gradient_t* noGradient = (gradient_t*)malloc(sizeof(gradient_t)); + noGradient->gradient.ratios = (U8*)malloc(16 * sizeof(U8)); + noGradient->gradient.rgba = (RGBA*)malloc(16 * sizeof(RGBA)); + noGradient->gradient.num = 2; + noGradient->gradient.rgba[0] = c; + noGradient->gradient.ratios[0] = 0; + noGradient->gradient.rgba[1] = c; + noGradient->gradient.ratios[1] = 255; + noGradient->radial = 0; + noGradient->rotate = 0; + dictionary_put2(&gradients, "no_gradient", noGradient); + + noBlur = (FILTER_BLUR*) swf_NewFilter(FILTERTYPE_BLUR); + noBlur->passes = 1; + dictionary_put2(&filters, "no_blur", noBlur); + noBevel = (FILTER_BEVEL*) swf_NewFilter(FILTERTYPE_BEVEL); + noBevel->passes = 1; + dictionary_put2(&filters, "no_bevel", noBevel); + noDropshadow = (FILTER_DROPSHADOW*) swf_NewFilter(FILTERTYPE_DROPSHADOW); + noDropshadow->passes = 1; + dictionary_put2(&filters, "no_dropshadow", noDropshadow); + noGradientGlow = (FILTER_GRADIENTGLOW*) swf_NewFilter(FILTERTYPE_GRADIENTGLOW); + noGradientGlow->passes = 1; + noGradientGlow->gradient = &noGradient->gradient; + dictionary_put2(&filters, "no_gradientglow", noGradientGlow); } void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA background) @@ -550,7 +579,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou dictionary_init(&instances); dictionary_init(&sounds); dictionary_init(&interpolations); - builtInInterpolations(); + initBuiltIns(); cleanUp = &freeDictionaries; memset(&stack[stackpos], 0, sizeof(stack[0])); @@ -751,6 +780,34 @@ TAG* removeFromTo(TAG*from, TAG*to) return save; } +static int parametersChange(history_t* history, int frame) +{ + int willChange = 0; + + willChange = willChange || history_change(history, frame, "x"); + willChange = willChange || history_change(history, frame, "y"); + willChange = willChange || history_change(history, frame, "scalex"); + willChange = willChange || history_change(history, frame, "scaley"); + willChange = willChange || history_change(history, frame, "cxform.r0"); + willChange = willChange || history_change(history, frame, "cxform.g0"); + willChange = willChange || history_change(history, frame, "cxform.b0"); + willChange = willChange || history_change(history, frame, "cxform.a0"); + willChange = willChange || history_change(history, frame, "cxform.r1"); + willChange = willChange || history_change(history, frame, "cxform.g1"); + willChange = willChange || history_change(history, frame, "cxform.b1"); + willChange = willChange || history_change(history, frame, "cxform.a1"); + willChange = willChange || history_change(history, frame, "rotate"); + willChange = willChange || history_change(history, frame, "shear"); + willChange = willChange || history_change(history, frame, "pivot.x"); + willChange = willChange || history_change(history, frame, "pivot.y"); + willChange = willChange || history_change(history, frame, "pin.x"); + willChange = willChange || history_change(history, frame, "pin.y"); + willChange = willChange || history_change(history, frame, "blendmode"); + willChange = willChange || history_changeFilter(history, frame); + + return willChange; +} + static void readParameters(history_t* history, parameters_t* p, int frame) { p->x = history_value(history, frame, "x"); @@ -808,9 +865,11 @@ static void writeInstance(instance_t* i) while (frame < currentframe) { frame++; - readParameters(i->history, &p, frame); while (tag->id != ST_SHOWFRAME) tag = tag->next; + if (parametersChange(i->history, frame)) + { + readParameters(i->history, &p, frame); m = s_instancepos(i->character->size, &p); if(p.blendmode || p.filter) @@ -819,9 +878,16 @@ static void writeInstance(instance_t* i) tag = swf_InsertTag(tag, ST_PLACEOBJECT2); setPlacement(tag, 0, i->depth, m, 0, &p, 1); if (p.filter) + { + if (p.filter->type == FILTERTYPE_GRADIENTGLOW) + gradient_free(((FILTER_GRADIENTGLOW*)p.filter)->gradient); free(p.filter); } } + else + tag = tag->next; + } +} void dumpSWF(SWF*swf) { @@ -853,6 +919,8 @@ static void s_endSprite() num++; name = stringarray_at(index, num); } + while (tag->next) + tag = tag->next; tag = swf_InsertTag(tag, ST_SHOWFRAME); tag = swf_InsertTag(tag, ST_END); @@ -1615,11 +1683,11 @@ void s_gradientglow(char*name, char*gradient, float blurx, float blury, syntaxerror("filter %s defined twice", name); gradient_t* g = dictionary_lookup(&gradients, gradient); + if(!g) + syntaxerror("unknown gradient %s", gradient); composite = 1; - if(!g) - syntaxerror("unknown gradient %s", gradient); FILTER_GRADIENTGLOW* filter = rfx_calloc(sizeof(FILTER_GRADIENTGLOW)); filter->type = FILTERTYPE_GRADIENTGLOW; filter->gradient = &g->gradient; @@ -1893,11 +1961,15 @@ SRECT s_getInstanceBBox(char*name) if(!c) syntaxerror("internal error(5)"); return c->size; } -parameters_t s_getParameters(char*name) +void s_getParameters(char*name, parameters_t* p) { instance_t * i = dictionary_lookup(&instances, name); - if(!i) syntaxerror("instance '%s' unknown(10)", name); - return i->parameters; + if(!i) + syntaxerror("instance '%s' unknown(10)", name); + if (change_sets_all) + readParameters(i->history, p, currentframe); + else + *p = i->parameters; } void s_startclip(char*instance, char*character, parameters_t p) { @@ -2055,6 +2127,7 @@ void s_change(char*instance, parameters_t p2, interpolation_t* inter) instance_t* i = dictionary_lookup(&instances, instance); if(!i) syntaxerror("instance %s not known", instance); + recordChanges(i->history, p2, CF_CHANGE, inter); } @@ -2391,11 +2464,12 @@ static int c_flash(map_t*args) { char* filename = map_lookup(args, "filename"); char* compressstr = lu(args, "compress"); + char* change_modestr = lu(args, "change-sets-all"); SRECT bbox = parseBox(lu(args, "bbox")); int version = parseInt(lu(args, "version")); int fps = (int)(parseFloat(lu(args, "fps"))*256); - int compress = 0; RGBA color = parseColor(lu(args, "background")); + int compress = 0; if(!filename || !*filename) { /* for compatibility */ @@ -2419,6 +2493,12 @@ static int c_flash(map_t*args) compress = 0; else syntaxerror("value \"%s\" not supported for the compress argument", compressstr); + if(!strcmp(change_modestr, "yes")) + change_sets_all = 1; + else + if(strcmp(change_modestr, "no")) + syntaxerror("value \"%s\" not supported for the change-sets-all argument", change_modestr); + s_swf(filename, bbox, version, fps, compress, color); return 0; } @@ -2801,7 +2881,7 @@ static int c_placement(map_t*args, int type) SRECT oldbbox; MULADD luminance; parameters_t p; - U32 set = 0x00000000; + U16 set = 0x0000; if(type==9) { // (?) .rotate or .arcchange @@ -2838,7 +2918,7 @@ static int c_placement(map_t*args, int type) parameters_clear(&p); // button's show } else { - p = s_getParameters(instance); + s_getParameters(instance, &p); } /* x,y position */ @@ -3019,6 +3099,8 @@ static int c_placement(map_t*args, int type) set = set | SF_FILTER; } + if (change_sets_all) + set = SF_ALL; p.set = set; switch (type) @@ -3500,7 +3582,7 @@ static struct { command_func_t* func; char*arguments; } arguments[] = -{{"flash", c_flash, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default"}, +{{"flash", c_flash, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default @change-sets-all=no"}, {"frame", c_frame, "n=1 name= @cut=no @anchor=no"}, // "import" type stuff {"swf", c_swf, "name filename"},