X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfc.c;h=2db2d108fa3b051dc9108315a0ac088213bb23d5;hb=5ed16e8e59191e1626e2394532d492d0a55ff4bb;hp=8ebb8425d239acad4dd7820c8f275a0757e0ea24;hpb=d8071bf754f070a660ac49108bd35d1900301066;p=swftools.git diff --git a/src/swfc.c b/src/swfc.c index 8ebb842..2db2d10 100644 --- a/src/swfc.c +++ b/src/swfc.c @@ -47,6 +47,7 @@ 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"}, @@ -154,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 @@ -174,6 +188,8 @@ static struct level SRECT oldrect; TAG* cut; + SRECT scalegrid; + } stack[256]; static int stackpos = 0; @@ -207,6 +223,7 @@ typedef struct _parameters { U8 blendmode; //not interpolated 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 { @@ -219,7 +236,6 @@ typedef struct _instance { character_t*character; U16 depth; parameters_t parameters; - U16 deathFrame; history_t* history; } instance_t; @@ -324,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); @@ -334,6 +350,7 @@ static void freeDictionaries() dictionary_free_all(&fonts, free_font); dictionary_free_all(&sounds, free); dictionary_free_all(&interpolations, free); + cleanUp = 0; } static void freeFontDictionary() @@ -361,13 +378,15 @@ static void s_addcharacter(char*name, U16 id, TAG*ctag, SRECT r) 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) { @@ -455,42 +474,54 @@ void initBuiltIns() 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)); @@ -540,7 +571,7 @@ void initBuiltIns() 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); + FILTER* dummy = (FILTER*)malloc(sizeof(FILTER)); dictionary_put2(&filters, "no_filters", dummy); noBlur = (FILTER_BLUR*) swf_NewFilter(FILTERTYPE_BLUR); noBlur->passes = 1; @@ -604,7 +635,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou incrementid(); } -void s_sprite(char*name) +void s_sprite(char*name, SRECT*scalegrid) { tag = swf_InsertTag(tag, ST_DEFINESPRITE); swf_SetU16(tag, id); //id @@ -619,6 +650,11 @@ 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); @@ -730,6 +766,10 @@ 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); @@ -780,7 +820,8 @@ 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; @@ -841,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->filters = 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) @@ -878,30 +919,25 @@ 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++; - while (tag->id != ST_SHOWFRAME) + while (tag && 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); + m = s_instancepos(i->character->size, &p); 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); + 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 = tag->next; } @@ -922,21 +958,25 @@ 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; @@ -945,6 +985,15 @@ static void s_endSprite() 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 @@ -968,14 +1017,15 @@ static void s_endSWF() 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) @@ -986,6 +1036,11 @@ static void s_endSWF() 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); @@ -1017,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");} @@ -1506,13 +1559,15 @@ void s_font(char*name, char*filename) swf_FontCreateLayout(font); } font->id = id; - swf_FontReduce_swfc(font); + 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); + if(do_exports) { + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } incrementid(); } @@ -1594,13 +1649,15 @@ 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; @@ -1684,7 +1741,7 @@ GRADIENT parseGradient(const char*str) FILTERLIST* parseFilters(char* list) { if (!strcmp(list, "no_filters")) - return noFilters; + return 0; FILTER* f; FILTERLIST* f_list = (FILTERLIST*)malloc(sizeof(FILTERLIST)); f_list->num = 0; @@ -2027,6 +2084,32 @@ void s_getParameters(char*name, parameters_t* p) 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); @@ -2047,6 +2130,7 @@ void s_startclip(char*instance, char*character, parameters_t p) stack[stackpos].type = 2; stackpos++; + setStartparameters(i, &p, tag); currentdepth++; } void s_endClip() @@ -2056,36 +2140,12 @@ 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->filters); -} - void s_put(char*instance, char*character, parameters_t p) { character_t* c = dictionary_lookup(&characters, character); @@ -2174,13 +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, p, CF_CHANGE, inter); +} - recordChanges(i->history, p2, 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) @@ -2188,15 +2266,18 @@ void s_delinstance(char*instance) instance_t* i = dictionary_lookup(&instances, instance); if(!i) syntaxerror("instance %s not known", instance); - i->deathFrame = currentframe; + 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() @@ -2283,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; @@ -2296,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; @@ -2322,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, '(')) @@ -2515,6 +2748,7 @@ 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); @@ -2549,6 +2783,8 @@ static int c_flash(map_t*args) 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; } @@ -2575,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) { @@ -2598,10 +2835,11 @@ 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; @@ -2611,21 +2849,70 @@ 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) { SPOINT pos,size; @@ -2721,7 +3008,7 @@ static int c_gradient(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; @@ -2837,6 +3124,23 @@ static int c_bevel(map_t*args) return 0; } +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"); @@ -2852,8 +3156,7 @@ 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) @@ -2909,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"); @@ -2967,11 +3360,11 @@ static int c_placement(map_t*args, int type) 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 @@ -2984,7 +3377,7 @@ static int c_placement(map_t*args, int type) { 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); } @@ -2998,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); } @@ -3154,16 +3547,22 @@ static int c_placement(map_t*args, int type) 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); @@ -3172,16 +3571,22 @@ 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 @@ -3193,39 +3598,69 @@ static int c_placement(map_t*args, int type) } 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) { 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_qchange(map_t*args) +static int c_smove(map_t* args) { - c_placement(args, 2); + c_movement(args, PT_SMOVE); + return 0; +} +static int c_sweep(map_t* args) +{ + c_movement(args, PT_SWEEP); return 0; } static int c_arcchange(map_t*args) { - c_placement(args, 2); + c_placement(args, 0); return 0; } static int c_jump(map_t*args) { - c_placement(args, 3); + c_placement(args, PT_JUMP); return 0; } static int c_startclip(map_t*args) { - c_placement(args, 4); + c_placement(args, PT_STARTCLIP); return 0; } static int c_show(map_t*args) { - c_placement(args, 5); + c_placement(args, PT_BUTTON); + return 0; +} +static int c_toggle(map_t* args) +{ + 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) @@ -3242,7 +3677,14 @@ static int c_end(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) @@ -3637,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 @change-sets-all=no"}, +{{"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"}, @@ -3646,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"}, @@ -3690,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="}, @@ -3941,6 +4389,7 @@ static void analyseArgumentsForCommand(char*command) map_t args; char* fontfile; int nr = -1; + U8* glyphs_to_include; msg(" 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 @@ -3979,10 +4447,16 @@ static void analyseArgumentsForCommand(char*command) if (!font) syntaxerror("font %s is not known in line %d", lu(&args, "font"), line); else - if (!strcmp(command, "edittext")) - swf_FontUseAll(font); - else - swf_FontUseUTF8(font, lu(&args, "text")); + 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;