X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfc.c;h=8ebb8425d239acad4dd7820c8f275a0757e0ea24;hb=d8071bf754f070a660ac49108bd35d1900301066;hp=41e5b93bc47f8b9433c55b3375e411c650dabcf6;hpb=57c76fea2ab1652cb1727342ab7caf02569eeab7;p=swftools.git diff --git a/src/swfc.c b/src/swfc.c index 41e5b93..8ebb842 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"}, @@ -204,7 +205,7 @@ typedef struct _parameters { SPOINT pivot; SPOINT pin; U8 blendmode; //not interpolated - FILTER*filter; + FILTERLIST* filters; U16 set; // bits indicating wether a parameter was set in the c_placement function } parameters_t; @@ -218,8 +219,7 @@ typedef struct _instance { character_t*character; U16 depth; parameters_t parameters; - TAG* lastTag; //last tag which set the object - U16 lastFrame; //frame lastTag is in + U16 deathFrame; history_t* history; } instance_t; @@ -402,7 +402,7 @@ static void parameters_clear(parameters_t*p) p->rotate = 0; p->shear = 0; p->blendmode = 0; - p->filter = 0; + p->filters = 0; swf_GetCXForm(0, &p->cxform, 1); } @@ -415,10 +415,10 @@ static void makeMatrix(MATRIX*m, parameters_t*p) * \r0 sy/ \y/ */ - 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; + sx = p->scalex*cos(p->rotate/360*2*M_PI); + r1 = -p->scalex*sin(p->rotate/360*2*M_PI)+sx*p->shear; + r0 = p->scaley*sin(p->rotate/360*2*M_PI); + sy = p->scaley*cos(p->rotate/360*2*M_PI)+r0*p->shear; m->sx = (int)(sx*65536+0.5); m->r1 = (int)(r1*65536+0.5); @@ -446,7 +446,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 +522,42 @@ 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); + + noFilters = 0; +// put a no_filters entry in the filters dictionary to provoce a message when a user tries +// to define a no_filters filter. The real filter=no_filters case is handled in parseFilters. + char* dummy = (char*)malloc(2); + dictionary_put2(&filters, "no_filters", dummy); + 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; + noBevel->composite = 1; + dictionary_put2(&filters, "no_bevel", noBevel); + noDropshadow = (FILTER_DROPSHADOW*) swf_NewFilter(FILTERTYPE_DROPSHADOW); + noDropshadow->passes = 1; + noDropshadow->composite = 1; + dictionary_put2(&filters, "no_dropshadow", noDropshadow); + noGradientGlow = (FILTER_GRADIENTGLOW*) swf_NewFilter(FILTERTYPE_GRADIENTGLOW); + noGradientGlow->passes = 1; + noGradientGlow->composite = 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 +586,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 +787,46 @@ 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 free_filterlist(FILTERLIST* f_list) +{ + int i; + for (i = 0; i < f_list->num; i++) + { + if (f_list->filter[i]->type == FILTERTYPE_GRADIENTGLOW) + gradient_free(((FILTER_GRADIENTGLOW*)f_list->filter[i])->gradient); + free(f_list->filter[i]); + } + free(f_list); +} + static void readParameters(history_t* history, parameters_t* p, int frame) { p->x = history_value(history, frame, "x"); @@ -772,7 +848,7 @@ static void readParameters(history_t* history, parameters_t* p, int frame) 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); + p->filters = history_valueFilter(history, frame); } void setPlacement(TAG*tag, U16 id, U16 depth, MATRIX m, char*name, parameters_t*p, char move) @@ -791,11 +867,8 @@ void setPlacement(TAG*tag, U16 id, U16 depth, MATRIX m, char*name, parameters_t* if(p->blendmode) { po.blendmode = p->blendmode; } - if(p->filter) { - flist.num = 1; - flist.filter[0] = p->filter; - po.filters = &flist; - } + if (p->filters) + po.filters = p->filters; swf_SetPlaceObject(tag, &po); } @@ -808,18 +881,29 @@ static void writeInstance(instance_t* i) while (frame < currentframe) { frame++; - readParameters(i->history, &p, frame); while (tag->id != ST_SHOWFRAME) tag = tag->next; + if (i->deathFrame == frame) + { + tag = swf_InsertTag(tag, ST_REMOVEOBJECT2); + swf_SetU16(tag, i->depth); + break; + } + if (parametersChange(i->history, frame)) + { + readParameters(i->history, &p, frame); m = s_instancepos(i->character->size, &p); - if(p.blendmode || p.filter) + if(p.blendmode || p.filters) 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); + if (p.filters) + free_filterlist(p.filters); +} + else + tag = tag->next; } } @@ -853,6 +937,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); @@ -1023,8 +1109,8 @@ int addFillStyle(SHAPE*s, SRECT*r, char*name) MATRIX rot,m; double ccos,csin; swf_GetMatrix(0, &rot); - ccos = cos(-gradient->rotate*2*PI/360); - csin = sin(-gradient->rotate*2*PI/360); + ccos = cos(-gradient->rotate*2*M_PI/360); + csin = sin(-gradient->rotate*2*M_PI/360); rot.sx = ccos*65536; rot.r1 = -csin*65536; rot.r0 = csin*65536; @@ -1595,6 +1681,44 @@ GRADIENT parseGradient(const char*str) return gradient; } +FILTERLIST* parseFilters(char* list) +{ + if (!strcmp(list, "no_filters")) + return noFilters; + FILTER* f; + FILTERLIST* f_list = (FILTERLIST*)malloc(sizeof(FILTERLIST)); + f_list->num = 0; + char* f_start = list; + char* f_end; + while (f_start) + { + f_end = strchr(f_start, ','); + if (f_end) + *f_end = '\0'; + f = dictionary_lookup(&filters, f_start); + if (!f) + { + free(f_list); + syntaxerror("unknown filter %s", f_start); + } + if (f_list->num == 8) + { + warning("too many filters in filterlist, no more than 8 please, rest ignored"); + break; + } + f_list->filter[f_list->num] = f; + f_list->num++; + if (f_end) + { + *f_end = ','; + f_start = f_end + 1; + } + else + f_start = 0; + } + return f_list; +} + void s_gradient(char*name, const char*text, int radial, int rotate) { gradient_t* gradient; @@ -1615,11 +1739,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 +2017,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) { @@ -1914,8 +2042,6 @@ void s_startclip(char*instance, char*character, parameters_t p) tag = swf_InsertTag(tag, ST_PLACEOBJECT2); /* TODO: should be ObjectPlaceClip, with clipdepth backpatched */ swf_ObjectPlace(tag, c->id, currentdepth, &m, &p.cxform, instance); - i->lastTag = tag; - i->lastFrame= currentframe; stack[stackpos].tag = tag; stack[stackpos].type = 2; @@ -1957,7 +2083,7 @@ void setStartparameters(instance_t* i, parameters_t* p, TAG* tag) 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); + history_beginFilter(i->history, currentframe, tag, p->filters); } void s_put(char*instance, char*character, parameters_t p) @@ -1972,7 +2098,7 @@ void s_put(char*instance, char*character, parameters_t p) i->parameters = p; m = s_instancepos(i->character->size, &p); - if(p.blendmode || p.filter) + if(p.blendmode || p.filters) { if(stack[0].swf->fileVersion < 8) { @@ -1987,8 +2113,6 @@ void s_put(char*instance, char*character, parameters_t p) 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++; } @@ -2039,7 +2163,7 @@ void recordChanges(history_t* history, parameters_t p, int changeFunction, 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); + history_rememberFilter(history, currentframe, changeFunction, p.filters, inter); } void s_jump(char* instance, parameters_t p) @@ -2055,6 +2179,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); } @@ -2063,9 +2188,7 @@ void s_delinstance(char*instance) instance_t* i = dictionary_lookup(&instances, instance); if(!i) syntaxerror("instance %s not known", instance); - tag = swf_InsertTag(tag, ST_REMOVEOBJECT2); - swf_SetU16(tag, i->depth); - dictionary_del(&instances, instance); + i->deathFrame = currentframe; } void s_qchange(char*instance, parameters_t p) @@ -2391,11 +2514,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 +2543,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; } @@ -2589,9 +2719,17 @@ static int c_gradient(map_t*args) return 0; } -static int c_blur(map_t*args) +static char* checkFiltername(map_t* args) { char*name = lu(args, "name"); + if (strchr(name, ',')) + syntaxerror("the comma (,) is used to separate filters in filterlists. Please do not use in filternames."); + return name; +} + +static int c_blur(map_t*args) +{ + char*name = checkFiltername(args); char*blurstr = lu(args, "blur"); char*blurxstr = lu(args, "blurx"); char*blurystr = lu(args, "blury"); @@ -2611,7 +2749,7 @@ static int c_blur(map_t*args) static int c_gradientglow(map_t*args) { - char*name = lu(args, "name"); + char*name = checkFiltername(args); char*gradient = lu(args, "gradient"); char*blurstr = lu(args, "blur"); char*blurxstr = lu(args, "blurx"); @@ -2641,7 +2779,7 @@ static int c_gradientglow(map_t*args) static int c_dropshadow(map_t*args) { - char*name = lu(args, "name"); + char*name = checkFiltername(args); RGBA color = parseColor(lu(args, "color")); char*blurstr = lu(args, "blur"); char*blurxstr = lu(args, "blurx"); @@ -2670,7 +2808,7 @@ static int c_dropshadow(map_t*args) static int c_bevel(map_t*args) { - char*name = lu(args, "name"); + char*name = checkFiltername(args); RGBA shadow = parseColor(lu(args, "shadow")); RGBA highlight = parseColor(lu(args, "highlight")); char*blurstr = lu(args, "blur"); @@ -2801,7 +2939,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 +2976,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 */ @@ -3012,13 +3150,12 @@ static int c_placement(map_t*args, int type) if(filterstr[0]) { - FILTER*f = dictionary_lookup(&filters, filterstr); - if(!f) - syntaxerror("Unknown filter %s", filterstr); - p.filter = f; + p.filters = parseFilters(filterstr); set = set | SF_FILTER; } + if (change_sets_all) + set = SF_ALL; p.set = set; switch (type) @@ -3500,7 +3637,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"},