X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfc.c;h=2db2d108fa3b051dc9108315a0ac088213bb23d5;hb=7528e9af6df5b0d27fc6d27158ab3cc51d6cbf64;hp=16f4b9ba82e5961c922e7fbc7f7c3c6d5e220beb;hpb=b038726a1b933b38d04d10eb1d8f093b07e80b73;p=swftools.git diff --git a/src/swfc.c b/src/swfc.c index 16f4b9b..2db2d10 100644 --- a/src/swfc.c +++ b/src/swfc.c @@ -4,7 +4,7 @@ Part of the swftools package. Copyright (c) 2001 Matthias Kramm - + 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 @@ -46,6 +46,8 @@ 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 int do_exports = 0; static struct options_t options[] = { {"h", "help"}, @@ -55,7 +57,7 @@ static struct options_t options[] = { {"o", "output"}, {0,0} }; - + int args_callback_option(char*name,char*val) { if(!strcmp(name, "V")) { @@ -153,6 +155,19 @@ static int noMoreTokens() return 0; } +enum +{ + PT_PUT = 0, + PT_CHANGE = 1, + PT_SCHANGE = 2, + PT_MOVE = 3, + PT_SMOVE = 4, + PT_SWEEP = 5, + PT_JUMP = 6, + PT_STARTCLIP = 7, + PT_BUTTON = 8 +}; + // ------------------------------ swf routines ---------------------------- struct _character; static struct level @@ -161,7 +176,7 @@ static struct level /* for swf (0): */ SWF*swf; - char*filename; + char*filename; /* for sprites (1): */ TAG*tag; @@ -173,6 +188,8 @@ static struct level SRECT oldrect; TAG* cut; + SRECT scalegrid; + } stack[256]; static int stackpos = 0; @@ -196,16 +213,17 @@ static dictionary_t sounds; static dictionary_t fontUsage; typedef struct _parameters { - int x,y; - float scalex, scaley; + int x,y; + float scalex, scaley; CXFORM cxform; float rotate; float shear; 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 + U16 flags; // bits to toggle anything you may care to implement as a toggle } parameters_t; typedef struct _character { @@ -218,8 +236,6 @@ 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 history_t* history; } instance_t; @@ -255,31 +271,6 @@ char* interpolationFunctions[] = {"linear", \ "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)); @@ -323,11 +314,6 @@ 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); @@ -354,8 +340,8 @@ static void free_outline(void* o) static void freeDictionaries() { - dictionary_free_all(&instances, free_instance); - dictionary_free_all(&characters, free); + 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); @@ -363,8 +349,13 @@ static void freeDictionaries() 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); + cleanUp = 0; +} + +static void freeFontDictionary() +{ + dictionary_free_all(&fonts, free_font); } static void incrementid() @@ -381,25 +372,27 @@ 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; dictionary_put2(&characters, name, c); - tag = swf_InsertTag(tag, ST_NAMECHARACTER); - swf_SetU16(tag, id); - swf_SetString(tag, name); - tag = swf_InsertTag(tag, ST_EXPORTASSETS); - swf_SetU16(tag, 1); - swf_SetU16(tag, id); - swf_SetString(tag, name); + if(do_exports) { + tag = swf_InsertTag(tag, ST_NAMECHARACTER); + swf_SetU16(tag, id); + swf_SetString(tag, name); + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } } 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; @@ -420,15 +413,15 @@ static instance_t* s_addinstance(char*name, character_t*c, U16 depth) static void parameters_clear(parameters_t*p) { - p->x = 0; p->y = 0; + p->x = 0; p->y = 0; p->scalex = 1.0; p->scaley = 1.0; p->pin.x = 0; //1?? p->pin.y = 0; p->pivot.x = 0; p->pivot.y = 0; - p->rotate = 0; - p->shear = 0; + p->rotate = 0; + p->shear = 0; p->blendmode = 0; - p->filter = 0; + p->filters = 0; swf_GetCXForm(0, &p->cxform, 1); } @@ -437,14 +430,14 @@ static void makeMatrix(MATRIX*m, parameters_t*p) SPOINT h; float sx,r1,r0,sy; - /* /sx r1\ /x\ + /* /sx r1\ /x\ * \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); @@ -452,7 +445,7 @@ static void makeMatrix(MATRIX*m, parameters_t*p) m->sy = (int)(sy*65536+0.5); m->tx = m->ty = 0; - + h = swf_TurnPoint(p->pin, m); m->tx = p->x - h.x; m->ty = p->y - h.y; @@ -464,7 +457,7 @@ static MATRIX s_instancepos(SRECT rect, parameters_t*p) SRECT r; makeMatrix(&m, p); r = swf_TurnRect(rect, &m); - if(currentrect.xmin == 0 && currentrect.ymin == 0 && + if(currentrect.xmin == 0 && currentrect.ymin == 0 && currentrect.xmax == 0 && currentrect.ymax == 0) currentrect = r; else @@ -472,7 +465,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)); @@ -481,42 +474,54 @@ void builtInInterpolations() new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUAD_IN; + new->slope = 0; dictionary_put2(&interpolations, "quadIn", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUAD_OUT; + new->slope = 0; dictionary_put2(&interpolations, "quadOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUAD_IN_OUT; + new->slope = 0; dictionary_put2(&interpolations, "quadInOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_CUBIC_IN; + new->slope = 0; dictionary_put2(&interpolations, "cubicIn", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_CUBIC_OUT; + new->slope = 0; dictionary_put2(&interpolations, "cubicOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_CUBIC_IN_OUT; + new->slope = 0; dictionary_put2(&interpolations, "cubicInOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUART_IN; + new->slope = 0; dictionary_put2(&interpolations, "quartIn", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUART_OUT; + new->slope = 0; dictionary_put2(&interpolations, "quartOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUART_IN_OUT; + new->slope = 0; dictionary_put2(&interpolations, "quartInOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUINT_IN; + new->slope = 0; dictionary_put2(&interpolations, "quintIn", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUINT_OUT; + new->slope = 0; dictionary_put2(&interpolations, "quintOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); new->function = IF_QUINT_IN_OUT; + new->slope = 0; dictionary_put2(&interpolations, "quintInOut", new); new = (interpolation_t*)malloc(sizeof(interpolation_t)); @@ -548,6 +553,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. + FILTER* dummy = (FILTER*)malloc(sizeof(FILTER)); + 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) @@ -556,7 +597,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou 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)); @@ -566,7 +607,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou swf->firstTag = tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR); swf->compressed = compress; swf_SetRGB(tag,&background); - + dictionary_init(&characters); dictionary_init(&images); dictionary_init(&textures); @@ -574,10 +615,9 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou dictionary_init(&gradients); dictionary_init(&filters); dictionary_init(&instances); - dictionary_init(&fonts); dictionary_init(&sounds); dictionary_init(&interpolations); - builtInInterpolations(); + initBuiltIns(); cleanUp = &freeDictionaries; memset(&stack[stackpos], 0, sizeof(stack[0])); @@ -586,17 +626,16 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou stack[stackpos].swf = swf; stack[stackpos].oldframe = -1; stackpos++; - id = 0; currentframe = 0; memset(¤trect, 0, sizeof(currentrect)); currentdepth = 1; - + memset(idmap, 0, sizeof(idmap)); incrementid(); } -void s_sprite(char*name) +void s_sprite(char*name, SRECT*scalegrid) { tag = swf_InsertTag(tag, ST_DEFINESPRITE); swf_SetU16(tag, id); //id @@ -611,7 +650,12 @@ void s_sprite(char*name) stack[stackpos].tag = tag; stack[stackpos].id = id; stack[stackpos].name = strdup(name); - + if(scalegrid) { + stack[stackpos].scalegrid = *scalegrid; + } else { + memset(&stack[stackpos].scalegrid, 0, sizeof(SRECT)); + } + /* FIXME: those four fields should be bundled together */ dictionary_init(&instances); currentframe = 0; @@ -674,7 +718,7 @@ void s_buttonput(char*character, char*as, parameters_t p) if(mybutton.endofshapes) { syntaxerror("a .do may not precede a .show", character, character); } - + m = s_instancepos(c->size, &p); r.id = c->id; @@ -701,7 +745,7 @@ static void setbuttonrecords(TAG*tag) int flags[] = {BS_UP,BS_OVER,BS_DOWN,BS_HIT}; if(!mybutton.endofshapes) { int t; - + if(!mybutton.records[3].set) { memcpy(&mybutton.records[3], &mybutton.records[0], sizeof(buttonrecord_t)); } @@ -722,8 +766,12 @@ void s_buttonaction(int flags, char*action) if(flags==0) { return; } + if(!stackpos || !stack[stackpos-1].tag || + stack[stackpos-1].tag->id != ST_DEFINEBUTTON2) { + syntaxerror("Need to be inside a button for .on_* commands"); + } setbuttonrecords(stack[stackpos-1].tag); - + a = swf_ActionCompile(text, stack[0].swf->fileVersion); if(!a) { syntaxerror("Couldn't compile ActionScript"); @@ -755,7 +803,7 @@ static void s_endButton() setbuttonrecords(stack[stackpos-1].tag); setactionend(stack[stackpos-1].tag); stackpos--; - + swf_ButtonPostProcess(stack[stackpos].tag, mybutton.nr_actions); r = currentrect; @@ -772,13 +820,54 @@ TAG* removeFromTo(TAG*from, TAG*to) TAG*save = from->prev; while(from!=to) { TAG*next = from->next; - swf_DeleteTag(from); + if(swf_isAllowedSpriteTag(from)) + swf_DeleteTag(0, from); from = next; } save->next = 0; 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"); @@ -793,14 +882,14 @@ static void readParameters(history_t* history, parameters_t* p, int frame) 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->rotate = history_rotateValue(history, frame); 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); + p->filters = history_filterValue(history, frame); } void setPlacement(TAG*tag, U16 id, U16 depth, MATRIX m, char*name, parameters_t*p, char move) @@ -819,11 +908,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); } @@ -833,21 +919,27 @@ static void writeInstance(instance_t* i) MATRIX m; int frame = i->history->firstFrame; TAG* tag = i->history->firstTag; + history_processFlags(i->history); while (frame < currentframe) { frame++; - readParameters(i->history, &p, frame); - while (tag->id != ST_SHOWFRAME) + while (tag && tag->id != ST_SHOWFRAME) tag = tag->next; - m = s_instancepos(i->character->size, &p); + if (parametersChange(i->history, frame)) + { + readParameters(i->history, &p, frame); + m = s_instancepos(i->character->size, &p); - if(p.blendmode || p.filter) - tag = swf_InsertTag(tag, ST_PLACEOBJECT3); + 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.filters) + free_filterlist(p.filters); + } else - tag = swf_InsertTag(tag, ST_PLACEOBJECT2); - setPlacement(tag, 0, i->depth, m, 0, &p, 1); - if (p.filter) - free(p.filter); + tag = tag->next; } } @@ -865,28 +957,43 @@ void dumpSWF(SWF*swf) static void s_endSprite() { SRECT r = currentrect; - - if(stack[stackpos].cut) - 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) + int num; + for (num = 0; num < dictionary_count(&instances); num++) { - i = dictionary_lookup(&instances, name); - writeInstance(i); - num++; - name = stringarray_at(index, num); + char* name = stringarray_at(index, num); + if (name) + { + i = dictionary_lookup(&instances, name); + writeInstance(i); + } } - + + if(stack[stackpos].cut) + tag = removeFromTo(stack[stackpos].cut, tag); + + // the writeInstance loop above may have inserted tags after what used yo be the current tag, + // so let's make sure 'tag' point to the current tag again. + while (tag->next) + tag = tag->next; + tag = swf_InsertTag(tag, ST_SHOWFRAME); tag = swf_InsertTag(tag, ST_END); tag = stack[stackpos].tag; swf_FoldSprite(tag); + + if(stack[stackpos].scalegrid.xmin | stack[stackpos].scalegrid.ymin | + stack[stackpos].scalegrid.xmax | stack[stackpos].scalegrid.ymax) + { + tag = swf_InsertTag(tag, ST_DEFINESCALINGGRID); + swf_SetU16(tag, stack[stackpos].id); + swf_SetRect(tag, &stack[stackpos].scalegrid); + } + if(tag->next != 0) syntaxerror("internal error(7)"); /* TODO: before clearing, prepend "." to names and @@ -907,27 +1014,33 @@ static void s_endSWF() int fi; SWF* swf; char*filename; - + instance_t *i; - stringarray_t* index =dictionary_index(&instances); - int num = 0; - char* name = stringarray_at(index, num); - while (name) + stringarray_t* index = dictionary_index(&instances); + int num; + for (num = 0; num < dictionary_count(&instances); num++) { - i = dictionary_lookup(&instances, name); - writeInstance(i); - num++; - name = stringarray_at(index, num); + char* name = stringarray_at(index, num); + if (name) + { + i = dictionary_lookup(&instances, name); + writeInstance(i); + } } if(stack[stackpos].cut) tag = removeFromTo(stack[stackpos].cut, tag); stackpos--; - + swf = stack[stackpos].swf; filename = stack[stackpos].filename; - + + // the writeInstance loop above may have inserted tags after what used yo be the current tag, + // so let's make sure 'tag' point to the current tag again. + while (tag->next) + tag = tag->next; + //if(tag->prev && tag->prev->id != ST_SHOWFRAME) // tag = swf_InsertTag(tag, ST_SHOWFRAME); tag = swf_InsertTag(tag, ST_SHOWFRAME); @@ -935,21 +1048,21 @@ static void s_endSWF() tag = swf_InsertTag(tag, ST_END); swf_OptimizeTagOrder(swf); - + if(optimize) { swf_Optimize(swf); } - + if(!(swf->movieSize.xmax-swf->movieSize.xmin) || !(swf->movieSize.ymax-swf->movieSize.ymin)) { swf->movieSize = currentrect; /* "autocrop" */ } - + if(!(swf->movieSize.xmax-swf->movieSize.xmin) || !(swf->movieSize.ymax-swf->movieSize.ymin)) { swf->movieSize.xmax += 20; /* 1 by 1 pixels */ swf->movieSize.ymax += 20; warning("Empty bounding box for movie"); } - + if(do_cgi || !strcmp(filename, "-")) fi = fileno(stdout); else @@ -959,8 +1072,6 @@ static void s_endSWF() } if(do_cgi) {if(swf_WriteCGI(swf)<0) syntaxerror("WriteCGI() failed.\n");} - else if(swf->compressed) - {if(swf_WriteSWC(fi, swf)<0) syntaxerror("WriteSWC() failed.\n");} else {if(swf_WriteSWF(fi, swf)<0) syntaxerror("WriteSWF() failed.\n");} @@ -995,7 +1106,7 @@ void s_frame(int nr, int cut, char*name, char anchor) int t; TAG*now = tag; - if(nr<1) + if(nr<1) syntaxerror("Illegal frame number"); nr--; // internally, frame 1 is frame 0 @@ -1051,8 +1162,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; @@ -1073,7 +1184,7 @@ int addFillStyle(SHAPE*s, SRECT*r, char*name) return 0; } } - + RGBA black={r:0,g:0,b:0,a:0}; void s_box(char*name, int width, int height, RGBA color, int linewidth, char*texture) { @@ -1107,7 +1218,7 @@ void s_box(char*name, int width, int height, RGBA color, int linewidth, char*tex swf_ShapeSetLine(tag,s,0,-height); swf_ShapeSetEnd(tag); swf_ShapeFree(s); - + s_addcharacter(name, id, tag, r); incrementid(); } @@ -1132,7 +1243,7 @@ void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*textu } if(texture) fs1 = addFillStyle(s, &r2, texture); - + swf_SetU16(tag,id); rect.xmin = r2.xmin-linewidth/2; rect.ymin = r2.ymin-linewidth/2; @@ -1142,7 +1253,7 @@ void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*textu swf_SetRect(tag,&rect); swf_SetShapeStyles(tag, s); swf_ShapeCountBits(s,0,0); - swf_RecodeShapeData(outline->shape->data, outline->shape->bitlen, outline->shape->bits.fill, outline->shape->bits.line, + swf_RecodeShapeData(outline->shape->data, outline->shape->bitlen, outline->shape->bits.fill, outline->shape->bits.line, &s->data, &s->bitlen, s->bits.fill, s->bits.line); swf_SetShapeBits(tag, s); swf_SetBlock(tag, s->data, (s->bitlen+7)/8); @@ -1181,7 +1292,7 @@ void s_circle(char*name, int r, RGBA color, int linewidth, char*texture) swf_ShapeSetCircle(tag, s, r,r,r,r); swf_ShapeSetEnd(tag); swf_ShapeFree(s); - + s_addcharacter(name, id, tag, rect); incrementid(); } @@ -1196,7 +1307,7 @@ void s_textshape(char*name, char*fontname, float size, char*_text) font = dictionary_lookup(&fonts, fontname); if(!font) syntaxerror("font \"%s\" not known!", fontname); - + if(text[0] >= font->maxascii || font->ascii2glyph[text[0]]<0) { warning("no character 0x%02x (%c) in font \"%s\"", text[0], text[0], fontname); s_box(name, 0, 0, black, 20, 0); @@ -1208,7 +1319,7 @@ void s_textshape(char*name, char*fontname, float size, char*_text) memset(outline, 0, sizeof(outline_t)); outline->shape = font->glyph[g].shape; outline->bbox = font->layout->bounds[g]; - + { drawer_t draw; swf_Shape11DrawerInit(&draw, 0); @@ -1232,7 +1343,7 @@ void s_text(char*name, char*fontname, char*text, int size, RGBA color) font = dictionary_lookup(&fonts, fontname); if(!font) syntaxerror("font \"%s\" not known!", fontname); - + tag = swf_InsertTag(tag, ST_DEFINETEXT2); swf_SetU16(tag, id); if(!font->numchars) { @@ -1249,7 +1360,7 @@ void s_text(char*name, char*fontname, char*text, int size, RGBA color) swf_SetU32(tag, 0);//sharpness swf_SetU8(tag, 0);//reserved } - + s_addcharacter(name, id, tag, r); incrementid(); } @@ -1260,11 +1371,11 @@ void s_quicktime(char*name, char*url) MATRIX _m,*m=0; memset(&r, 0, sizeof(r)); - + tag = swf_InsertTag(tag, ST_DEFINEMOVIE); swf_SetU16(tag, id); swf_SetString(tag, url); - + s_addcharacter(name, id, tag, r); incrementid(); } @@ -1292,7 +1403,7 @@ void s_edittext(char*name, char*fontname, int size, int width, int height, char* r.ymin = 0; r.xmax = width; r.ymax = height; - + swf_SetEditText(tag, flags, r, text, color, maxlength, font?font->id:0, size, &layout, variable); s_addcharacter(name, id, tag, r); @@ -1305,7 +1416,7 @@ void s_image(char*name, char*type, char*filename, int quality) { /* an image is actually two folded: 1st bitmap, 2nd character. Both of them can be used separately */ - + /* step 1: the bitmap */ SRECT r; int imageID = id; @@ -1435,20 +1546,8 @@ void s_texture(char*name, char*object, int x, int y, float scalex, float scaley, void s_font(char*name, char*filename) { - if(dictionary_lookup(&fonts, name)) - syntaxerror("font %s defined twice", name); - SWFFONT* font; - font = swf_LoadFont(filename); - - if(font == 0) { - warning("Couldn't open font file \"%s\"", filename); - font = (SWFFONT*)malloc(sizeof(SWFFONT)); - memset(font, 0, sizeof(SWFFONT)); - dictionary_put2(&fonts, name, font); - return; - } - + font = dictionary_lookup(&fonts, name); if(0) { /* fix the layout. Only needed for old fonts */ @@ -1459,19 +1558,18 @@ void s_font(char*name, char*filename) font->layout = 0; swf_FontCreateLayout(font); } - /* just in case this thing is used in .edittext later on */ - swf_FontPrepareForEditText(font); - font->id = id; + swf_FontReduce_swfc(font); tag = swf_InsertTag(tag, ST_DEFINEFONT2); swf_FontSetDefine2(tag, font); - tag = swf_InsertTag(tag, ST_EXPORTASSETS); - swf_SetU16(tag, 1); - swf_SetU16(tag, id); - swf_SetString(tag, name); - incrementid(); + if(do_exports) { + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } - dictionary_put2(&fonts, name, font); + incrementid(); } @@ -1494,7 +1592,7 @@ void s_sound(char*name, char*filename) if(dictionary_lookup(&sounds, name)) syntaxerror("sound %s defined twice", name); - + if(wav_read(&wav, filename)) { int t; @@ -1521,7 +1619,7 @@ void s_sound(char*name, char*filename) samples = 0; numsamples = 0; } - + if(numsamples%blocksize != 0) { // apply padding, so that block is a multiple of blocksize @@ -1550,21 +1648,23 @@ void s_sound(char*name, char*filename) } else swf_SetSoundDefine(tag, samples, numsamples); - - tag = swf_InsertTag(tag, ST_NAMECHARACTER); - swf_SetU16(tag, id); - swf_SetString(tag, name); - tag = swf_InsertTag(tag, ST_EXPORTASSETS); - swf_SetU16(tag, 1); - swf_SetU16(tag, id); - swf_SetString(tag, name); + + if(do_exports) { + tag = swf_InsertTag(tag, ST_NAMECHARACTER); + swf_SetU16(tag, id); + swf_SetString(tag, name); + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */ sound->tag = tag; sound->id = id; dictionary_put2(&sounds, name, sound); - + incrementid(); if (samples) @@ -1577,7 +1677,7 @@ static char* gradient_getToken(const char**p) char*result; while(**p && strchr(" \t\n\r", **p)) { (*p)++; - } + } start = *p; while(**p && !strchr(" \t\n\r", **p)) { (*p)++; @@ -1599,7 +1699,7 @@ GRADIENT parseGradient(const char*str) memset(&gradient, 0, sizeof(GRADIENT)); gradient.ratios = rfx_calloc(16*sizeof(U8)); gradient.rgba = rfx_calloc(16*sizeof(RGBA)); - + while(*p) { char*posstr,*colorstr; @@ -1638,6 +1738,44 @@ GRADIENT parseGradient(const char*str) return gradient; } +FILTERLIST* parseFilters(char* list) +{ + if (!strcmp(list, "no_filters")) + return 0; + 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; @@ -1649,20 +1787,20 @@ void s_gradient(char*name, const char*text, int radial, int rotate) dictionary_put2(&gradients, name, gradient); } - -void s_gradientglow(char*name, char*gradient, float blurx, float blury, - float angle, float distance, float strength, char innershadow, + +void s_gradientglow(char*name, char*gradient, float blurx, float blury, + 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); + 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; @@ -1762,7 +1900,7 @@ void s_initaction(const char*character, const char*text) ActionTAG* a = 0; character_t*c = 0; a = swf_ActionCompile(text, stack[0].swf->fileVersion); - if(!a) + if(!a) { swf_ActionFree(a); syntaxerror("Couldn't compile ActionScript"); @@ -1781,7 +1919,7 @@ int s_swf3action(char*name, char*action) { ActionTAG* a = 0; instance_t* object = 0; - if(name) + if(name) object = (instance_t*)dictionary_lookup(&instances, name); if(!object && name && *name) { /* we have a name, but couldn't find it. Abort. */ @@ -1805,14 +1943,14 @@ 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; SHAPE* shape; SHAPE2* shape2; SRECT bounds; - + //swf_Shape10DrawerInit(&draw, 0); swf_Shape11DrawerInit(&draw, 0); @@ -1821,11 +1959,11 @@ void s_outline(char*name, char*format, char*source) shape = swf_ShapeDrawerToShape(&draw); bounds = swf_ShapeDrawerGetBBox(&draw); draw.dealloc(&draw); - + outline = (outline_t*)rfx_calloc(sizeof(outline_t)); outline->shape = shape; outline->bbox = bounds; - + dictionary_put2(&outlines, name, outline); } @@ -1859,25 +1997,25 @@ void s_includeswf(char*name, char*filename) int level = 0; U16 cutout[] = {ST_SETBACKGROUNDCOLOR, ST_PROTECT, ST_FREEALL, ST_REFLEX}; f = open(filename,O_RDONLY|O_BINARY); - if (f<0) { + if (f<0) { warning("Couldn't open file \"%s\": %s", filename, strerror(errno)); s_box(name, 0, 0, black, 20, 0); return; } - if (swf_ReadSWF(f,&swf)<0) { + if (swf_ReadSWF(f,&swf)<0) { warning("Only SWF files supported in .shape for now. File \"%s\" wasn't SWF.", filename); s_box(name, 0, 0, black, 20, 0); return; } close(f); - /* FIXME: The following sets the bounding Box for the character. + /* FIXME: The following sets the bounding Box for the character. It is wrong for two reasons: a) It may be too small (in case objects in the movie clip at the borders) b) it may be too big (because the poor movie never got autocropped) */ r = swf.movieSize; - + s = tag = swf_InsertTag(tag, ST_DEFINESPRITE); swf_SetU16(tag, id); swf_SetU16(tag, swf.frameCount); @@ -1903,7 +2041,7 @@ void s_includeswf(char*name, char*filename) if(ftag->id != ST_SETBACKGROUNDCOLOR) { /* We simply dump all tags right after the sprite header, relying on the fact that swf_OptimizeTagOrder() will - sort things out for us later. + sort things out for us later. We also rely on the fact that the imported SWF is well-formed. */ tag = swf_InsertTag(tag, ftag->id); @@ -1936,12 +2074,42 @@ 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 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->filters); + history_begin(i->history, "flags", currentframe, tag, 0); } + void s_startclip(char*instance, char*character, parameters_t p) { character_t* c = dictionary_lookup(&characters, character); @@ -1953,17 +2121,16 @@ void s_startclip(char*instance, char*character, parameters_t p) i = s_addinstance(instance, c, currentdepth); i->parameters = p; m = s_instancepos(i->character->size, &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; stackpos++; + setStartparameters(i, &p, tag); currentdepth++; } void s_endClip() @@ -1973,51 +2140,27 @@ void s_endClip() swf_SetTagPos(stack[stackpos].tag, 0); swf_GetPlaceObject(stack[stackpos].tag, &p); p.clipdepth = currentdepth; - p.name = 0; + //p.name = 0; swf_ClearTag(stack[stackpos].tag); swf_SetPlaceObject(stack[stackpos].tag, &p); currentdepth++; } -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) + 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(p.blendmode || p.filters) { - if(stack[0].swf->fileVersion < 8) + if(stack[0].swf->fileVersion < 8) { if(p.blendmode) warning("blendmodes only supported for flash version>=8"); @@ -2030,8 +2173,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++; } @@ -2082,7 +2223,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) @@ -2093,12 +2234,31 @@ void s_jump(char* instance, parameters_t p) recordChanges(i->history, p, CF_JUMP, 0); } -void s_change(char*instance, parameters_t p2, interpolation_t* inter) +void s_change(char*instance, parameters_t p, 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); + recordChanges(i->history, p, CF_CHANGE, inter); +} + +void s_sweep(char* instance, parameters_t p, float radius, int clockwise, int short_arc, interpolation_t* inter) +{ + instance_t* i = dictionary_lookup(&instances, instance); + if(!i) + syntaxerror("instance %s not known", instance); + history_rememberSweep(i->history, currentframe, p.x, p.y, radius, clockwise, short_arc, inter); +} + +void s_toggle(char* instance, U16 flagsOn, U16 flagsOff) +{ + instance_t* i = dictionary_lookup(&instances, instance); + if (!i) + syntaxerror("instance %s not known", instance); + U16 flags = (U16)history_value(i->history, currentframe, "flags"); + flags |= flagsOn; + flags &= flagsOff; + history_remember(i->history, "flags", currentframe, CF_JUMP, flags, 0); } void s_delinstance(char*instance) @@ -2106,17 +2266,18 @@ void s_delinstance(char*instance) instance_t* i = dictionary_lookup(&instances, instance); if(!i) syntaxerror("instance %s not known", instance); + writeInstance(i); tag = swf_InsertTag(tag, ST_REMOVEOBJECT2); swf_SetU16(tag, i->depth); dictionary_del(&instances, instance); } -void s_qchange(char*instance, parameters_t p) +void s_schange(char*instance, parameters_t p, interpolation_t* inter) { instance_t* i = dictionary_lookup(&instances, instance); if(!i) syntaxerror("instance %s not known", instance); - recordChanges(i->history, p, CF_QCHANGE, 0); + recordChanges(i->history, p, CF_SCHANGE, inter); } void s_end() @@ -2203,7 +2364,7 @@ int parseInt(char*str) syntaxerror("Not an Integer: \"%s\"", str); return atoi(str); } -int parseTwip(char*str) +static double parseRawTwip(char*str) { char*dot; int sign=1; @@ -2216,23 +2377,25 @@ int parseTwip(char*str) if(!dot) { int l=strlen(str); int t; - return sign*parseInt(str)*20; + return sign*parseInt(str); } else { char* old = strdup(str); int l=strlen(dot+1); char*s; *dot++ = 0; - for(s=str;s'9') - { - free(old); - syntaxerror("Not a coordinate: \"%s\"", str); + for(s=str;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); + 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; @@ -2242,15 +2405,165 @@ int parseTwip(char*str) } free(old); if(l==0) - return sign*atoi(str)*20; + return sign*(atoi(str)); if(l==1) - return sign*atoi(str)*20+atoi(dot)*2; + return sign*(atoi(str)+0.1*atoi(dot)); if(l==2) - return sign*atoi(str)*20+atoi(dot)/5; + return sign*(atoi(str)+0.01*atoi(dot)); } return 0; } +static dictionary_t defines; +static int defines_initialized = 0; +static mem_t define_values; + +static double parseNameOrTwip(char*s) +{ + int l = 0; + double v; + if(defines_initialized) { + l = (int)dictionary_lookup(&defines, s); + } + if(l) { + return *(int*)&define_values.buffer[l-1]; + } else { + return parseRawTwip(s); + } +} + +/* automatically generated by yiyiyacc, http://www.quiss.org/yiyiyacc/ */ +static double parseExpression(char*s) +{ + int chr2index[256]; + memset(chr2index, -1, sizeof(chr2index)); + chr2index['+'] = 0; + chr2index['-'] = 1; + chr2index['*'] = 2; + chr2index['/'] = 3; + chr2index['('] = 5; + chr2index[')'] = 6; + chr2index['\0'] = 7; + + int stackpos = 1; + int stack[256]; + double values[256]; + stack[0]=0; + values[0]=0; + int accept = 18; + int left[10]={11,8,8,8,8,9,9,9,10,10}; //production left side + int plen[10]={1,3,2,3,1,3,3,1,1,3}; //production size + int table[18][12] = { + {0, 4, 0, 0, 5, 6, 0, 0, 1, 2, 3, 0}, + {7, 8, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0}, + {-4, -4, 9, 10, 0, 0, -4, -4, 0, 0, 0, 0}, + {-7, -7, -7, -7, 0, 0, -7, -7, 0, 0, 0, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 11, 3, 0}, + {-8, -8, -8, -8, 0, 0, -8, -8, 0, 0, 0, 0}, + {0, 4, 0, 0, 5, 6, 0, 0, 12, 2, 3, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 13, 3, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 14, 3, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 15, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 16, 0}, + {-2, -2, 9, 10, 0, 0, -2, -2, 0, 0, 0, 0}, + {7, 8, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0}, + {-1, -1, 9, 10, 0, 0, -1, -1, 0, 0, 0, 0}, + {-3, -3, 9, 10, 0, 0, -3, -3, 0, 0, 0, 0}, + {-5, -5, -5, -5, 0, 0, -5, -5, 0, 0, 0, 0}, + {-6, -6, -6, -6, 0, 0, -6, -6, 0, 0, 0, 0}, + {-9, -9, -9, -9, 0, 0, -9, -9, 0, 0, 0, 0}}; + + char*p = s; + while(1) { + char*pnext = p+1; + int action; + double value = 0; + if(!stackpos) { + fprintf(stderr, "Error in expression\n"); + return 0.0; + } + + if(chr2index[*p]<0) { + action = table[stack[stackpos-1]][4]; + if(action>0) { + while(chr2index[*pnext]<0) + pnext++; + char save = *pnext; + *pnext = 0; + value = parseNameOrTwip(p); + *pnext = save; + } + } else { + action = table[stack[stackpos-1]][chr2index[*p]]; + } + + if(action == accept) { + return values[stack[stackpos-1]]; + } else if(action>0) { // shift + if(stackpos>254) { + fprintf(stderr, "Stack overflow while parsing expression\n"); + return 0.0; + } + values[stackpos]=value; + stack[stackpos++]=action; + p=pnext; + } else if(action<0) { // reduce + stackpos-=plen[-action]; + stack[stackpos] = table[stack[stackpos-1]][left[-action]]; + switch(-action) { + case 1: + values[stackpos] = values[stackpos+0] + values[stackpos+2]; + break; + case 2: + values[stackpos] = 0 - values[stackpos+1]; + break; + case 3: + values[stackpos] = values[stackpos+0] - values[stackpos+2]; + break; + case 5: + values[stackpos] = values[stackpos+0] * values[stackpos+2]; + break; + case 6: + values[stackpos] = values[stackpos+0] / values[stackpos+2]; + break; + case 9: + values[stackpos] = values[stackpos+1]; + break; + } + stackpos++; + } else { + fprintf(stderr, "Syntax error in expression\n"); + return 0.0; + } + } +} + +int parseTwip(char*str) +{ + int v = (int)(parseExpression(str)*20); + return v; +} + +int parseArc(char* str) +{ + if (!strcmp(str, "short")) + return 1; + if (!strcmp(str, "long")) + return 0; + syntaxerror("invalid value for the arc parameter: %s", str); + return 1; +} + +int parseDir(char* str) +{ + if (!strcmp(str, "clockwise")) + return 1; + if (!strcmp(str, "counterclockwise")) + return 0; + syntaxerror("invalid value for the dir parameter: %s", str); + return 1; +} + int isPoint(char*str) { if(strchr(str, '(')) @@ -2430,15 +2743,17 @@ static char* lu(map_t* args, char*name) return value; } -static int c_flash(map_t*args) +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"); + char* exportstr = lu(args, "export"); 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 */ @@ -2453,7 +2768,7 @@ static int c_flash(map_t*args) if(!filename || override_outputname) filename = outputname; - + if(!strcmp(compressstr, "default")) compress = version>=6; else if(!strcmp(compressstr, "yes") || !strcmp(compressstr, "compress")) @@ -2462,6 +2777,14 @@ 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); + + do_exports=atoi(exportstr); + s_swf(filename, bbox, version, fps, compress, color); return 0; } @@ -2488,9 +2811,10 @@ int getSign(char*str) syntaxerror("internal error (348)"); return 0; } + static dictionary_t points; static mem_t mpoints; -int points_initialized = 0; +static int points_initialized = 0; static int c_interpolation(map_t *args) { @@ -2498,7 +2822,7 @@ static int c_interpolation(map_t *args) 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; @@ -2511,11 +2835,12 @@ static int c_interpolation(map_t *args) if (!inter->function) syntaxerror("unkown interpolation function %s", functionstr); inter->speed = parseFloat(lu(args, "speed")); - inter->amplitude = parseFloat(lu(args, "amplitude")); + inter->amplitude = parseTwip(lu(args, "amplitude")); inter->growth = parseFloat(lu(args, "growth")); inter->bounces = parseInt(lu(args, "bounces")); - inter->damping = parseInt(lu(args, "damping")); - + inter->damping = parseFloat(lu(args, "damping")); + inter->slope = parseFloat(lu(args, "slope")); + dictionary_put2(&interpolations, name, inter); return 0; } @@ -2524,22 +2849,71 @@ SPOINT getPoint(SRECT r, char*name) { int l=0; if(!strcmp(name, "center")) { - SPOINT p; - p.x = (r.xmin + r.xmax)/2; - p.y = (r.ymin + r.ymax)/2; - return p; + SPOINT p; + p.x = (r.xmin + r.xmax)/2; + p.y = (r.ymin + r.ymax)/2; + return p; + } + if (!strcmp(name, "bottom-center")) { + SPOINT p; + p.x = (r.xmin + r.xmax)/2; + p.y = r.ymax; + return p; + } + if (!strcmp(name, "top-center")) { + SPOINT p; + p.x = (r.xmin + r.xmax)/2; + p.y = r.ymin; + return p; + } + if (!strcmp(name, "top-left")) { + SPOINT p; + p.x = r.xmin; + p.y = r.ymin; + return p; + } + if (!strcmp(name, "top-right")) { + SPOINT p; + p.x = r.xmax; + p.y = r.ymin; + return p; + } + if (!strcmp(name, "bottom-right")) { + SPOINT p; + p.x = r.xmax; + p.y = r.ymax; + return p; + } + if (!strcmp(name, "bottom-left")) { + SPOINT p; + p.x = r.xmin; + p.y = r.ymax; + return p; + } + if (!strcmp(name, "left-center")) { + SPOINT p; + p.x = r.xmin; + p.y = (r.ymin + r.ymax)/2; + return p; + } + if (!strcmp(name, "right-center")) { + SPOINT p; + p.x = r.xmax; + p.y = (r.ymin + r.ymax)/2; + return p; } + if(points_initialized) - l = (int)dictionary_lookup(&points, name); + l = (int)dictionary_lookup(&points, name); if(l==0) { - syntaxerror("Invalid point: \"%s\".", name); + syntaxerror("Invalid point: \"%s\".", name); } - l--; - return *(SPOINT*)&mpoints.buffer[l]; + return *(SPOINT*)&mpoints.buffer[l-1]; } -static int texture2(char*name, char*object, map_t*args, int errors) + +static int texture2(char*name, char*object, map_t*args, int errors) { SPOINT pos,size; char*xstr = map_lookup(args, "x"); @@ -2601,14 +2975,14 @@ static int texture2(char*name, char*object, map_t*args, int errors) return 0; } -static int c_texture(map_t*args) +static int c_texture(map_t*args) { char*name = lu(args, "instance"); char*object = lu(args, "character"); return texture2(name, object, args, 1); } -static int c_gradient(map_t*args) +static int c_gradient(map_t*args) { char*name = lu(args, "name"); int radial= strcmp(lu(args, "radial"), "radial")?0:1; @@ -2632,9 +3006,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"); + 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"); @@ -2642,7 +3024,7 @@ static int c_blur(map_t*args) if(blurstr[0]) { blurx = parseFloat(blurstr); blury = parseFloat(blurstr); - } + } if(blurxstr[0]) blurx = parseFloat(blurxstr); if(blurystr[0]) @@ -2652,9 +3034,9 @@ static int c_blur(map_t*args) return 0; } -static int c_gradientglow(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"); @@ -2663,7 +3045,7 @@ static int c_gradientglow(map_t*args) if(blurstr[0]) { blurx = parseFloat(blurstr); blury = parseFloat(blurstr); - } + } if(blurxstr[0]) blurx = parseFloat(blurxstr); if(blurystr[0]) @@ -2682,9 +3064,9 @@ static int c_gradientglow(map_t*args) return 0; } -static int c_dropshadow(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"); @@ -2693,7 +3075,7 @@ static int c_dropshadow(map_t*args) if(blurstr[0]) { blurx = parseFloat(blurstr); blury = parseFloat(blurstr); - } + } if(blurxstr[0]) blurx = parseFloat(blurxstr); if(blurystr[0]) @@ -2711,9 +3093,9 @@ static int c_dropshadow(map_t*args) return 0; } -static int c_bevel(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"); @@ -2723,7 +3105,7 @@ static int c_bevel(map_t*args) if(blurstr[0]) { blurx = parseFloat(blurstr); blury = parseFloat(blurstr); - } + } if(blurxstr[0]) blurx = parseFloat(blurxstr); if(blurystr[0]) @@ -2742,7 +3124,24 @@ static int c_bevel(map_t*args) return 0; } -static int c_point(map_t*args) +static int c_define(map_t*args) +{ + char*name = lu(args, "name"); + char*value = lu(args, "value"); + + if(!defines_initialized) { + dictionary_init(&defines); + mem_init(&define_values); + defines_initialized = 1; + } + int val = parseTwip(value); + int pos = mem_put(&define_values, &val, sizeof(val)); + string_t s; + string_set(&s, name); + dictionary_put(&defines, s, (void*)(pos+1)); + return 0; +} +static int c_point(map_t*args) { char*name = lu(args, "name"); int pos; @@ -2757,11 +3156,10 @@ static int c_point(map_t*args) p.y = parseTwip(lu(args, "y")); pos = mem_put(&mpoints, &p, sizeof(p)); string_set(&s1, name); - pos++; - dictionary_put(&points, s1, (void*)pos); + dictionary_put(&points, s1, (void*)(pos+1)); return 0; } -static int c_play(map_t*args) +static int c_play(map_t*args) { char*name = lu(args, "name"); char*loop = lu(args, "loop"); @@ -2780,7 +3178,7 @@ static int c_play(map_t*args) return 0; } -static int c_stop(map_t*args) +static int c_stop(map_t*args) { char*name = map_lookup(args, "name"); @@ -2792,7 +3190,7 @@ static int c_stop(map_t*args) return 0; } -static int c_nextframe(map_t*args) +static int c_nextframe(map_t*args) { char*name = lu(args, "name"); @@ -2803,7 +3201,7 @@ static int c_nextframe(map_t*args) return 0; } -static int c_previousframe(map_t*args) +static int c_previousframe(map_t*args) { char*name = lu(args, "name"); @@ -2814,9 +3212,99 @@ static int c_previousframe(map_t*args) return 0; } +static int c_movement(map_t*args, int type) +{ + char*instance = lu(args, "name"); + + char* xstr=""; + char* ystr=""; + SRECT oldbbox; + parameters_t p; + U16 set = 0x0000; + + xstr = lu(args, "x"); + ystr = lu(args, "y"); + + s_getParameters(instance, &p); + + /* x,y position */ + if(xstr[0]) + { + if(isRelative(xstr)) + { + if(type == PT_PUT || type == PT_STARTCLIP) + 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 == PT_PUT || type == PT_STARTCLIP) + 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; + } + + if (change_sets_all) + set = SF_ALL; + p.set = set; + + switch (type) + { + case PT_MOVE: + { + 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 PT_SMOVE: + { + char* interstr = lu(args, "interpolation"); + interpolation_t* inter = (interpolation_t*)dictionary_lookup(&interpolations, interstr); + if (!inter) + syntaxerror("unkown interpolation %s", interstr); + s_schange(instance, p, inter); + } + break; + case PT_SWEEP: + { + char* rstr = lu(args, "r"); + int radius = parseTwip(rstr); + if (radius <= 0) + syntaxerror("sweep not possible: radius must be greater than 0."); + char* dirstr = lu(args, "dir"); + int clockwise = parseDir(dirstr); + char* arcstr = lu(args, "arc"); + int short_arc = parseArc(arcstr); + char* interstr = lu(args, "interpolation"); + interpolation_t* inter = (interpolation_t*)dictionary_lookup(&interpolations, interstr); + if (!inter) + syntaxerror("unkown interpolation %s", interstr); + s_sweep(instance, p, radius, clockwise, short_arc, inter); + } + break; + } + return 0; +} + static int c_placement(map_t*args, int type) { - char*instance = lu(args, (type==0||type==4)?"instance":"name"); + char*instance = lu(args, (type==PT_PUT||type==PT_STARTCLIP)?"instance":"name"); char*character = 0; char* luminancestr = lu(args, "luminance"); @@ -2844,7 +3332,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 @@ -2856,7 +3344,7 @@ static int c_placement(map_t*args, int type) xstr = lu(args, "x"); ystr = lu(args, "y"); } - + if(luminancestr[0]) luminance = parseMulAdd(luminancestr); else @@ -2871,25 +3359,25 @@ static int c_placement(map_t*args, int type) syntaxerror("scalex/scaley and scale cannot both be set"); scalexstr = scaleystr = scalestr; } - - if(type == 0 || type == 4) { + + if(type == PT_PUT || type == PT_STARTCLIP) { // put or startclip character = lu(args, "character"); parameters_clear(&p); - } else if (type == 5) { + } else if (type == PT_BUTTON) { character = lu(args, "name"); parameters_clear(&p); // button's show } else { - p = s_getParameters(instance); + s_getParameters(instance, &p); } /* x,y position */ - if(xstr[0]) + if(xstr[0]) { if(isRelative(xstr)) { - if(type == 0 || type == 4) + if(type == PT_PUT || type == PT_STARTCLIP) syntaxerror("relative x values not allowed for initial put or startclip"); p.x += parseTwip(getOffset(xstr))*getSign(xstr); } @@ -2903,7 +3391,7 @@ static int c_placement(map_t*args, int type) { if(isRelative(ystr)) { - if(type == 0 || type == 4) + if(type == PT_PUT || type == PT_STARTCLIP) syntaxerror("relative y values not allowed for initial put or startclip"); p.y += parseTwip(getOffset(ystr))*getSign(ystr); } @@ -2939,7 +3427,7 @@ static int c_placement(map_t*args, int type) p.scaley = (float)(parseNewSize(scaleystr, oldheight))/oldheight; set = set | SF_SCALEY; } - + /* rotation */ if(rotatestr[0]) { @@ -2964,11 +3452,11 @@ static int c_placement(map_t*args, int type) { if(isPoint(pivotstr)) p.pivot = parsePoint(pivotstr); - else + else p.pivot = getPoint(oldbbox, pivotstr); set = set | SF_PIVOT; } - + if(pinstr[0]) { if(isPoint(pinstr)) @@ -2977,7 +3465,7 @@ static int c_placement(map_t*args, int type) p.pin = getPoint(oldbbox, pinstr); set = set | SF_PIN; } - + /* color transform */ if(rstr[0] || luminancestr[0]) @@ -3052,24 +3540,29 @@ static int c_placement(map_t*args, int type) p.blendmode = blend; set = set | SF_BLEND; } - + 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 (type == PT_CHANGE && set & (SF_X | SF_Y)) + warning("As of version 0.8.2 using the .change command to modify an \ +object's position on the stage is considered deprecated. Future \ +versions may consider x and y parameters for the .change command \ +to be illegal; please use the .move command."); + + if (change_sets_all) + set = SF_ALL; p.set = set; switch (type) { - case 0: + case PT_PUT: s_put(instance, character, p); break; - case 1: + case PT_CHANGE: { char* interstr = lu(args, "interpolation"); interpolation_t* inter = (interpolation_t*)dictionary_lookup(&interpolations, interstr); @@ -3078,84 +3571,127 @@ static int c_placement(map_t*args, int type) s_change(instance, p, inter); } break; - case 2: - s_qchange(instance, p); + case PT_SCHANGE: + { + char* interstr = lu(args, "interpolation"); + interpolation_t* inter = (interpolation_t*)dictionary_lookup(&interpolations, interstr); + if (!inter) + syntaxerror("unkown interpolation %s", interstr); + s_schange(instance, p, inter); + } break; - case 3: + case PT_JUMP: s_jump(instance, p); break; - case 4: + case PT_STARTCLIP: s_startclip(instance, character, p); break; - case 5: + case PT_BUTTON: if(as && as[0]) s_buttonput(character, as, p); else s_buttonput(character, "shape", p); break; -// default: +// default: } return 0; } -static int c_put(map_t*args) +static int c_put(map_t*args) { - c_placement(args, 0); + c_placement(args, PT_PUT); return 0; } -static int c_change(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); + c_placement(args, PT_CHANGE); + return 0; +} +static int c_schange(map_t*args) +{ + c_placement(args, PT_SCHANGE); + return 0; +} +static int c_move(map_t* args) +{ + c_movement(args, PT_MOVE); + return 0; +} +static int c_smove(map_t* args) +{ + c_movement(args, PT_SMOVE); + return 0; +} +static int c_sweep(map_t* args) +{ + c_movement(args, PT_SWEEP); return 0; } -static int c_qchange(map_t*args) +static int c_arcchange(map_t*args) { - c_placement(args, 2); + c_placement(args, 0); return 0; } -static int c_arcchange(map_t*args) +static int c_jump(map_t*args) { - c_placement(args, 2); + c_placement(args, PT_JUMP); return 0; } -static int c_jump(map_t*args) +static int c_startclip(map_t*args) { - c_placement(args, 3); + c_placement(args, PT_STARTCLIP); return 0; } -static int c_startclip(map_t*args) +static int c_show(map_t*args) { - c_placement(args, 4); + c_placement(args, PT_BUTTON); return 0; } -static int c_show(map_t*args) +static int c_toggle(map_t* args) { - c_placement(args, 5); + char*instance = lu(args, "name"); + U16 flagsOn = 0x0000, flagsOff = 0xffff; + char* alignstr = lu(args, "fixed_alignment"); + if (!strcmp(alignstr, "on")) + flagsOn += IF_FIXED_ALIGNMENT; + else + if (!strcmp(alignstr, "off")) + flagsOff -= IF_FIXED_ALIGNMENT; + else + syntaxerror("values for toggle must be \"on\" or \"off\". %s is not legal.", alignstr); + s_toggle(instance, flagsOn, flagsOff); return 0; } -static int c_del(map_t*args) +static int c_del(map_t*args) { char*instance = lu(args, "name"); s_delinstance(instance); return 0; } -static int c_end(map_t*args) +static int c_end(map_t*args) { s_end(); return 0; } -static int c_sprite(map_t*args) +static int c_sprite(map_t*args) { char* name = lu(args, "name"); - s_sprite(name); + char* scalinggrid = lu(args, "scalinggrid"); + + if(scalinggrid && *scalinggrid) { + SRECT r = parseBox(scalinggrid); + s_sprite(name, &r); + } else { + s_sprite(name, 0); + } return 0; } -static int c_frame(map_t*args) +static int c_frame(map_t*args) { char*framestr = lu(args, "n"); char*cutstr = lu(args, "cut"); - + char*name = lu(args, "name"); char*anchor = lu(args, "anchor"); char buf[40]; @@ -3182,7 +3718,7 @@ static int c_frame(map_t*args) s_frame(frame, cut, name, !strcmp(anchor, "anchor")); return 0; } -static int c_primitive(map_t*args) +static int c_primitive(map_t*args) { char*name = lu(args, "name"); char*command = lu(args, "commandname"); @@ -3201,7 +3737,7 @@ static int c_primitive(map_t*args) type = 1; else if(!strcmp(command, "filled")) type = 2; - + if(type==0) { width = parseTwip(lu(args, "width")); height = parseTwip(lu(args, "height")); @@ -3217,14 +3753,14 @@ static int c_primitive(map_t*args) fillstr = 0; if(width<0 || height<0 || linewidth<0 || r<0) syntaxerror("values width, height, line, r must be positive"); - + if(type == 0) s_box(name, width, height, color, linewidth, fillstr); else if(type==1) s_circle(name, r, color, linewidth, fillstr); else if(type==2) s_filled(name, outline, color, linewidth, fillstr); return 0; } -static int c_textshape(map_t*args) +static int c_textshape(map_t*args) { char*name = lu(args, "name"); char*text = lu(args, "text"); @@ -3235,7 +3771,7 @@ static int c_textshape(map_t*args) return 0; } -static int c_swf(map_t*args) +static int c_swf(map_t*args) { char*name = lu(args, "name"); char*filename = lu(args, "filename"); @@ -3246,7 +3782,7 @@ static int c_swf(map_t*args) return 0; } -static int c_font(map_t*args) +static int c_font(map_t*args) { char*name = lu(args, "name"); char*filename = lu(args, "filename"); @@ -3254,7 +3790,7 @@ static int c_font(map_t*args) return 0; } -static int c_sound(map_t*args) +static int c_sound(map_t*args) { char*name = lu(args, "name"); char*filename = lu(args, "filename"); @@ -3262,7 +3798,7 @@ static int c_sound(map_t*args) return 0; } -static int c_text(map_t*args) +static int c_text(map_t*args) { char*name = lu(args, "name"); char*text = lu(args, "text"); @@ -3273,12 +3809,12 @@ static int c_text(map_t*args) return 0; } -static int c_soundtrack(map_t*args) +static int c_soundtrack(map_t*args) { return 0; } -static int c_quicktime(map_t*args) +static int c_quicktime(map_t*args) { char*name = lu(args, "name"); char*url = lu(args, "url"); @@ -3286,7 +3822,7 @@ static int c_quicktime(map_t*args) return 0; } -static int c_image(map_t*args) +static int c_image(map_t*args) { char*command = lu(args, "commandname"); char*name = lu(args, "name"); @@ -3300,7 +3836,7 @@ static int c_image(map_t*args) return 0; } -static int c_outline(map_t*args) +static int c_outline(map_t*args) { char*name = lu(args, "name"); char*format = lu(args, "format"); @@ -3425,7 +3961,7 @@ static int c_on_key(map_t*args) return 1; } } else { - /* TODO: + /* TODO: = 0x200*(x-'a') esc = = 0x3600 space = = 0x4000; @@ -3443,7 +3979,7 @@ static int c_on_key(map_t*args) return 0; } -static int c_edittext(map_t*args) +static int c_edittext(map_t*args) { //"name font size width height text="" color=black maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0 @autosize=0"}, char*name = lu(args, "name"); @@ -3493,7 +4029,7 @@ static char* readfile(const char*filename) FILE*fi = fopen(filename, "rb"); int l; char*text; - if(!fi) + if(!fi) syntaxerror("Couldn't find file %s: %s", filename, strerror(errno)); fseek(fi, 0, SEEK_END); l = ftell(fi); @@ -3505,7 +4041,7 @@ static char* readfile(const char*filename) return text; } -static int c_action(map_t*args) +static int c_action(map_t*args) { char* filename = map_lookup(args, "filename"); if(!filename ||!*filename) { @@ -3517,11 +4053,11 @@ static int c_action(map_t*args) } else { s_action(readfile(filename)); } - + return 0; } -static int c_initaction(map_t*args) +static int c_initaction(map_t*args) { char* character = lu(args, "name"); char* filename = map_lookup(args, "filename"); @@ -3534,7 +4070,7 @@ static int c_initaction(map_t*args) } else { s_initaction(character, readfile(filename)); } - + return 0; } @@ -3543,7 +4079,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 @export=1"}, {"frame", c_frame, "n=1 name= @cut=no @anchor=no"}, // "import" type stuff {"swf", c_swf, "name filename"}, @@ -3552,15 +4088,16 @@ static struct { {"png", c_image, "name filename"}, {"movie", c_movie, "name filename"}, {"sound", c_sound, "name filename"}, - {"font", c_font, "name filename"}, + {"font", c_font, "name filename glyphs="}, {"soundtrack", c_soundtrack, "filename"}, {"quicktime", c_quicktime, "url"}, - + // generators of primitives + {"define", c_define, "name value=0"}, {"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"}, + {"interpolation", c_interpolation, "name function=linear speed=1.3 amplitude=0 bounces=2 growth=1.5 damping=2 slope=0"}, {"outline", c_outline, "name format=simple"}, {"textshape", c_textshape, "name font size=100% text"}, @@ -3586,7 +4123,7 @@ static struct { {"on_move_in", c_on_move_in, "state=not_pressed"}, {"on_move_out", c_on_move_out, "state=not_pressed"}, {"on_key", c_on_key, "key=any"}, - + // control tags {"play", c_play, "name loop=0 @nomultiple=0"}, {"stop", c_stop, "name= "}, @@ -3596,17 +4133,22 @@ static struct { // object placement tags {"put", c_put, " 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, " 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="}, + {"move", c_move, "name x= y= interpolation=linear"}, + {"smove", c_smove, "name x= y= interpolation=linear"}, + {"sweep", c_sweep, "name x= y= r= dir=counterclockwise arc=short interpolation=linear"}, {"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="}, + //{"arcchange", c_arcchange, "name pivot= angle= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="}, + {"schange", c_schange, "name red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= interpolation=linear"}, {"jump", c_jump, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="}, {"del", c_del, "name"}, // virtual object placement {"texture", c_texture, " x=0 y=0 width= height= scale= scalex= scaley= r= shear= rotate="}, + // switching + {"toggle", c_toggle, "name fixed_alignment="}, // commands which start a block //startclip (see above) - {"sprite", c_sprite, "name"}, + {"sprite", c_sprite, "name scalinggrid="}, {"action", c_action, "filename="}, {"initaction", c_initaction, "name filename="}, @@ -3618,7 +4160,7 @@ static map_t parseArguments(char*command, char*pattern) { char*x; char*d,*e; - + string_t name[64]; string_t value[64]; int set[64]; @@ -3678,7 +4220,7 @@ static map_t parseArguments(char*command, char*pattern) d=&x[strlen(x)]; set[pos] = 0; - if(!e || d analyse Command: %s (line %d)", command, line); + + for(t=0;tuse->glyphs_specified = 1; + } + else + { + if (strcmp (glyphs_to_include, "")) + { + swf_FontUseUTF8(font, glyphs_to_include); + font->use->glyphs_specified = 1; + } + else + swf_FontInitUsage(font); + } + } + dictionary_put2(&fonts, name, font); + } + else + { + SWFFONT* font = dictionary_lookup(&fonts, lu(&args, "font")); + if (!font) + syntaxerror("font %s is not known in line %d", lu(&args, "font"), line); + else + if (font->use && !font->use->glyphs_specified) + { + if (!strcmp(command, "edittext")) + { + swf_FontUseAll(font); + font->use->glyphs_specified = 1; + } + else + swf_FontUseUTF8(font, lu(&args, "text")); + } + } + map_clear(&args); + return; +} + +void skipParameters() +{ + do + readToken(); + while (type != COMMAND); + pushBack(); +} + +void findFontUsage() +{ + char* fontRelated = "font;text;textshape;edittext;"; + while(!noMoreTokens()) + { + readToken(); + if(type != COMMAND) + syntaxerror("command expected"); + if (strstr(fontRelated, text)) + analyseArgumentsForCommand(text); + else + if(strcmp(text, "end")) + skipParameters(); + } +} + +void firstPass() +{ + pos = 0; + id = 0; + dictionary_init(&fonts); + cleanUp = &freeFontDictionary; + findFontUsage(); +} + int main (int argc,char ** argv) -{ +{ int t; processargs(argc, argv); initLog(0,-1,0,0,-1,verbose); @@ -3847,12 +4505,13 @@ int main (int argc,char ** argv) args_callback_usage(argv[0]); exit(1); } - + file = generateTokens(filename); if(!file) { fprintf(stderr, "parser returned error.\n"); return 1; } + firstPass(); pos=0; t=0;