X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfc.c;h=f57a98eb14c9ed656d615a0106d2d3748319ccea;hb=5480f1eae83c641a75b225db52bbfc1fcb62e6b6;hp=9fd752ac6f1b12345773056cc00680d3b363aa3a;hpb=f6d4dc96fb50a920313da1dbdd92296aa406f7ad;p=swftools.git diff --git a/src/swfc.c b/src/swfc.c index 9fd752a..f57a98e 100644 --- a/src/swfc.c +++ b/src/swfc.c @@ -4,8 +4,20 @@ 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - This file is distributed under the GPL, see file COPYING for details */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include @@ -13,21 +25,21 @@ #include #include #include -#define logf logarithmf // logf is also used by ../lib/log.h #include -#undef logf #include "../config.h" #include "../lib/rfxswf.h" #include "../lib/log.h" #include "../lib/args.h" -#include "q.h" +#include "../lib/q.h" #include "parser.h" +#include "wav.h" //#define DEBUG static char * filename = 0; static char * outputname = "output.swf"; static int verbose = 2; +static int override_outputname = 0; static struct options_t options[] = { @@ -45,6 +57,7 @@ int args_callback_option(char*name,char*val) } else if(!strcmp(name, "o")) { outputname = val; + override_outputname = 1; return 1; } else if(!strcmp(name, "v")) { @@ -175,6 +188,7 @@ static SRECT currentrect; //current bounding box in current level static U16 currentdepth; static dictionary_t instances; static dictionary_t fonts; +static dictionary_t sounds; typedef struct _parameters { int x,y; @@ -323,10 +337,9 @@ static MATRIX s_instancepos(instance_t*i, parameters_t*p) return m; } -void s_swf(char*name, SRECT r, int version, int fps, int compress) +void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA background) { SWF*swf = (SWF*)malloc(sizeof(SWF)); - RGBA rgb; if(stackpos) syntaxerror(".swf blocks can't be nested"); @@ -337,8 +350,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress) swf->frameRate = fps; swf->firstTag = tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR); swf->compressed = compress; - rgb.r = 0x00;rgb.g = 0x00;rgb.b = 0x00; - swf_SetRGB(tag,&rgb); + swf_SetRGB(tag,&background); if(stackpos==sizeof(stack)/sizeof(stack[0])) syntaxerror("too many levels of recursion"); @@ -346,6 +358,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress) dictionary_init(&characters); dictionary_init(&instances); dictionary_init(&fonts); + dictionary_init(&sounds); memset(&stack[stackpos], 0, sizeof(stack[0])); stack[stackpos].type = 0; @@ -430,8 +443,13 @@ static void s_endSWF() 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; + } - fi = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); + fi = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); if(fi<0) { syntaxerror("couldn't create output file %s", filename); } @@ -445,6 +463,7 @@ static void s_endSWF() dictionary_clear(&instances); dictionary_clear(&characters); dictionary_clear(&fonts); + dictionary_clear(&sounds); swf_FreeTags(swf); free(swf); @@ -608,7 +627,7 @@ void s_font(char*name, char*filename) int f; SWF swf; SWFFONT* font; - f = open(filename,O_RDONLY); + f = open(filename,O_RDONLY|O_BINARY); if (f<0) { warning("Couldn't open file \"%s\": %s", filename, strerror(errno)); font = (SWFFONT*)malloc(sizeof(SWFFONT)); @@ -647,6 +666,64 @@ void s_font(char*name, char*filename) dictionary_put2(&fonts, name, font); } +typedef struct _sound_t +{ + U16 id; + TAG*tag; +} sound_t; + +void s_sound(char*name, char*filename) +{ + struct WAV wav, wav2; + sound_t* sound; + U16*samples; + int numsamples; + + if(!readWAV(filename, &wav)) { + warning("Couldn't read wav file \"%s\"", filename); + samples = 0; + numsamples = 0; + } else { + convertWAV2mono(&wav, &wav2, 44100); + samples = (U16*)wav2.data; + numsamples = wav2.size/2; + free(wav.data); + } + + tag = swf_InsertTag(tag, ST_DEFINESOUND); + swf_SetU16(tag, id); //id + swf_SetSoundDefine(tag, samples, numsamples); + + sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */ + sound->tag = tag; + sound->id = id; + + if(dictionary_lookup(&sounds, name)) + syntaxerror("sound %s defined twice", name); + dictionary_put2(&sounds, name, sound); + + incrementid(); + + if(samples) + free(samples); +} + +void s_playsound(char*name, int loops, int nomultiple, int stop) +{ + sound_t* sound = dictionary_lookup(&sounds, name); + SOUNDINFO info; + if(!sound) + syntaxerror("Don't know anything about sound \"%s\"", name); + + tag = swf_InsertTag(tag, ST_STARTSOUND); + swf_SetU16(tag, sound->id); //id + memset(&info, 0, sizeof(info)); + info.stop = stop; + info.loops = loops; + info.nomultiple = nomultiple; + swf_SetSoundInfo(tag, &info); +} + void s_shape(char*name, char*filename) { int f; @@ -854,7 +931,7 @@ void s_change(char*instance, parameters_t p2) p1 = i->parameters; allframes = currentframe - i->lastFrame - 1; - if(!allframes) { + if(allframes < 0) { warning(".change ignored. can only .put/.change an object once per frame."); return; } @@ -982,11 +1059,18 @@ int parseInt(char*str) } int parseTwip(char*str) { - char*dot = strchr(str, '.'); + char*dot; + int sign=1; + if(str[0]=='+' || str[0]=='-') { + if(str[0]=='-') + sign = -1; + str++; + } + dot = strchr(str, '.'); if(!dot) { int l=strlen(str); int t; - return parseInt(str)*20; + return sign*parseInt(str)*20; } else { int l=strlen(++dot); char*s; @@ -1003,11 +1087,11 @@ int parseTwip(char*str) l=2; } if(l==0) - return atoi(str)*20; + return sign*atoi(str)*20; if(l==1) - return atoi(str)*20+atoi(dot)*2; + return sign*atoi(str)*20+atoi(dot)*2; if(l==2) - return atoi(str)*20+atoi(dot)/5; + return sign*atoi(str)*20+atoi(dot)/5; } return 0; } @@ -1040,10 +1124,23 @@ int parseColor2(char*str, RGBA*color) int l = strlen(str); int r,g,b,a; int t; - char*names[8] = {"black", "blue", "green", "cyan", - "red", "violet", "yellow", "white"}; - a=255; - r=g=b=0; + + struct {unsigned char r,g,b;char*name;} colors[] = + {{255,250,250,"snow"},{220,220,220,"gainsboro"},{250,240,230,"linen"},{255,228,196,"bisque"}, + {255,228,181,"moccasin"},{255,248,220,"cornsilk"},{255,255,240,"ivory"},{255,245,238,"seashell"}, + {240,255,240,"honeydew"},{240,255,255,"azure"},{230,230,250,"lavender"},{255,255,255,"white"}, + {0,0,0,"black"},{190,190,190,"gray"},{190,190,190,"grey"},{0,0,128,"navy"},{0,0,255,"blue"}, + {64,224,208,"turquoise"},{0,255,255,"cyan"},{127,255,212,"aquamarine"}, {0,255,0,"green"}, + {127,255,0,"chartreuse"},{240,230,140,"khaki"},{255,255,0,"yellow"}, + {255,215,0,"gold"},{218,165,32,"goldenrod"},{160,82,45,"sienna"},{205,133,63,"peru"}, + {222,184,135,"burlywood"},{245,245,220,"beige"},{245,222,179,"wheat"},{210,180,140,"tan"}, + {210,105,30,"chocolate"},{178,34,34,"firebrick"},{165,42,42,"brown"},{250,128,114,"salmon"}, + {255,165,0,"orange"},{255,127,80,"coral"},{255,99,71,"tomato"},{255,0,0,"red"}, + {255,192,203,"pink"},{176,48,96,"maroon"},{255,0,255,"magenta"},{238,130,238,"violet"}, + {221,160,221,"plum"},{218,112,214,"orchid"},{160,32,240,"purple"},{216,191,216,"thistle"}}; + + a=255;r=g=b=0; + if(str[0]=='#' && (l==7 || l==9)) { if(l == 7 && !(sscanf(str, "#%02x%02x%02x", &r, &g, &b))) return 0; @@ -1052,14 +1149,12 @@ int parseColor2(char*str, RGBA*color) color->r = r; color->g = g; color->b = b; color->a = a; return 1; } - for(t=0;t<8;t++) - if(!strcmp(str, names[t])) { - if(t&1) - b = 255; - if(t&2) - g = 255; - if(t&4) - r = 255; + for(t=0;tr = r; color->g = g; color->b = b; color->a = a; return 1; } @@ -1155,6 +1250,7 @@ static char* lu(map_t* args, char*name) { char* value = map_lookup(args, name); if(!value) { + map_dump(args, stdout, ""); syntaxerror("internal error 2: value %s should be set", name); } return value; @@ -1168,7 +1264,8 @@ static int c_swf(map_t*args) int version = parseInt(lu(args, "version")); int fps = (int)(parseFloat(lu(args, "fps"))*256); int compress = 0; - if(!strcmp(name, "!default!")) + RGBA color = parseColor(lu(args, "background")); + if(!strcmp(name, "!default!") || override_outputname) name = outputname; if(!strcmp(compressstr, "default")) @@ -1179,7 +1276,7 @@ static int c_swf(map_t*args) compress = 0; else syntaxerror("value \"%s\" not supported for the compress argument", compressstr); - s_swf(name, bbox, version, fps, compress); + s_swf(name, bbox, version, fps, compress, color); return 0; } int isRelative(char*str) @@ -1211,7 +1308,7 @@ int points_initialized = 0; SPOINT getPoint(SRECT r, char*name) { - int l; + int l=0; if(!strcmp(name, "center")) { SPOINT p; p.x = (r.xmin + r.xmax)/2; @@ -1219,13 +1316,18 @@ SPOINT getPoint(SRECT r, char*name) return p; } - l = (int)dictionary_lookup(&points, name); + if(points_initialized) + l = (int)dictionary_lookup(&points, name); if(l==0) { - syntaxerror("Couldn't find point \"%s\".", name); + syntaxerror("Invalid point: \"%s\".", name); } l--; return *(SPOINT*)&mpoints.buffer[l]; } +static int c_gradient(map_t*args) +{ + return 0; +} static int c_point(map_t*args) { char*name = lu(args, "name"); @@ -1245,6 +1347,28 @@ static int c_point(map_t*args) dictionary_put(&points, s1, (void*)pos); return 0; } +static int c_play(map_t*args) +{ + char*name = lu(args, "sound"); + char*loop = lu(args, "loop"); + char*nomultiple = lu(args, "nomultiple"); + int nm = 0; + if(!strcmp(nomultiple, "nomultiple")) + nm = 1; + else + nm = parseInt(nomultiple); + + s_playsound(name, parseInt(loop), nm, 0); + return 0; +} + +static int c_stop(map_t*args) +{ + char*name = lu(args, "sound"); + s_playsound(name, 0,0,1); + return 0; +} + static int c_placement(map_t*args, int type) { char*instance = lu(args, (type==0||type==4)?"instance":"name"); @@ -1477,9 +1601,11 @@ static int c_frame(map_t*args) { char*framestr = lu(args, "n"); int frame; - if(framestr[0]=='+') { + if(isRelative(framestr)) { frame = s_getframe(); - frame += parseInt(framestr+1); + if(getSign(framestr)<0) + syntaxerror("relative frame expressions must be positive"); + frame += parseInt(getOffset(framestr)); } else { frame = parseInt(framestr); @@ -1556,6 +1682,14 @@ static int c_font(map_t*args) return 0; } +static int c_sound(map_t*args) +{ + char*name = lu(args, "name"); + char*filename = lu(args, "filename"); + s_sound(name, filename); + return 0; +} + static int c_text(map_t*args) { char*name = lu(args, "name"); @@ -1567,13 +1701,17 @@ static int c_text(map_t*args) return 0; } +static int c_soundtrack(map_t*args) +{ + return 0; +} + int fakechar(map_t*args) { char*name = lu(args, "name"); s_box(name, 0, 0, black, 20, black, 0); return 0; } -static int c_circle(map_t*args) {return fakechar(args);} static int c_egon(map_t*args) {return fakechar(args);} static int c_button(map_t*args) {return fakechar(args);} @@ -1582,12 +1720,7 @@ static int c_edittext(map_t*args) {return fakechar(args);} static int c_morphshape(map_t*args) {return fakechar(args);} static int c_image(map_t*args) {return fakechar(args);} static int c_movie(map_t*args) {return fakechar(args);} -static int c_sound(map_t*args) {return fakechar(args);} -static int c_play(map_t*args) {return 0;} -static int c_stop(map_t*args) {return 0;} - -static int c_soundtrack(map_t*args) {return 0;} static int c_buttonsounds(map_t*args) {return 0;} static int c_buttonput(map_t*args) {return 0;} static int c_texture(map_t*args) {return 0;} @@ -1598,8 +1731,8 @@ static struct { command_func_t* func; char*arguments; } arguments[] = -{{"swf", c_swf, "bbox=autocrop version=5 fps=50 name=!default! @compress=default"}, - {"frame", c_frame, "n=+1"}, +{{"swf", c_swf, "bbox=autocrop background=black version=5 fps=50 name=!default! @compress=default"}, + {"frame", c_frame, "n=1"}, // "import" type stuff {"shape", c_shape, "name filename"}, @@ -1611,6 +1744,11 @@ static struct { {"font", c_font, "name filename"}, {"soundtrack", c_soundtrack, "filename"}, + // generators of primitives + + {"point", c_point, "name x=0 y=0"}, + {"gradient", c_gradient, "name"}, + // character generators {"box", c_primitive, "name width height color=white line=1 @fill=none"}, {"circle", c_primitive, "name r color=white line=1 @fill=none"}, @@ -1637,7 +1775,6 @@ static struct { // virtual object placement {"buttonput", c_buttonput, " x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex=100% scaley=100% shear=0 rotate=0 above= below="}, {"texture", c_texture, " x=0 y=0 scale= scalex=100% scaley=100% shear=0 rotate=0"}, - {"point", c_point, "name x=0 y=0"}, // commands which start a block //startclip (see above) @@ -1731,7 +1868,7 @@ static map_t parseArguments(char*command, char*pattern) len = pos; /* for(t=0;ttextlen?name[pos].len:textlen)) || (type != ASSIGNMENT && !set[pos])) { if(set[pos]) { - syntaxerror("value %s set twice (old value:%s)", text, strndup(value[pos].str, value[pos].len)); + syntaxerror("value %s set twice (old value:%s)", text, strdup_n(value[pos].str, value[pos].len)); } if(type == ASSIGNMENT) readToken(); @@ -1774,8 +1911,8 @@ static map_t parseArguments(char*command, char*pattern) value[pos].len = strlen(text); #if 0//def DEBUG printf("setting parameter %s (to %s)\n", - strndup(name[pos].str, name[pos].len), - strndup(value[pos].str, value[pos].len)); + strdup_n(name[pos].str, name[pos].len), + strdup_n(value[pos].str, value[pos].len)); #endif break; } @@ -1786,7 +1923,7 @@ static map_t parseArguments(char*command, char*pattern) } #if 0//def DEBUG for(t=0;t