* always add a final SHOWFRAME tag
[swftools.git] / src / swfc.c
index 75b38a3..3a2f7ed 100644 (file)
@@ -40,6 +40,7 @@
 static char * filename = 0;
 static char * outputname = "output.swf";
 static int verbose = 2;
+static int optimize = 0;
 static int override_outputname = 0;
 
 static struct options_t options[] = {
@@ -47,6 +48,7 @@ static struct options_t options[] = {
 {"V", "version"},
 {"v", "verbose"},
 {"o", "output"},
+{"O", "optimize"},
 {0,0}
 };
     
@@ -61,6 +63,10 @@ int args_callback_option(char*name,char*val)
        override_outputname = 1;
        return 1;
     }
+    else if(!strcmp(name, "O")) {
+       optimize = 1;
+       return 0;
+    }
     else if(!strcmp(name, "v")) {
        verbose ++;
        return 0;
@@ -231,6 +237,7 @@ typedef struct _outline {
 typedef struct _gradient {
     GRADIENT gradient;
     char radial;
+    int rotate;
 } gradient_t;
 
 static void character_init(character_t*c)
@@ -320,7 +327,8 @@ static void parameters_clear(parameters_t*p)
 {
     p->x = 0; p->y = 0; 
     p->scalex = 1.0; p->scaley = 1.0;
-    p->pin.x = 1; p->pin.y = 0;
+    p->pin.x = 0;  //1??
+    p->pin.y = 0;
     p->pivot.x = 0; p->pivot.y = 0;
     p->rotate = 0; 
     p->shear = 0; 
@@ -347,7 +355,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;
@@ -497,11 +505,11 @@ void s_buttonput(char*character, char*as, parameters_t p)
 
     while(1) {
        if(*s==',' || *s==0) {
-           if(!strncmp(o,"idle",s-o)) mybutton.records[0]=r;
-           else if(!strncmp(o,"shape",s-o)) mybutton.records[0]=r;
-           else if(!strncmp(o,"hover",s-o)) mybutton.records[1]=r;
-           else if(!strncmp(o,"pressed",s-o)) mybutton.records[2]=r;
-           else if(!strncmp(o,"area",s-o)) mybutton.records[3]=r;
+           if(!strncmp(o,"idle",s-o)) {mybutton.records[0]=r;o=s+1;}
+           else if(!strncmp(o,"shape",s-o)) {mybutton.records[0]=r;o=s+1;}
+           else if(!strncmp(o,"hover",s-o)) {mybutton.records[1]=r;o=s+1;}
+           else if(!strncmp(o,"pressed",s-o)) {mybutton.records[2]=r;o=s+1;}
+           else if(!strncmp(o,"area",s-o)) {mybutton.records[3]=r;o=s+1;}
            else syntaxerror("unknown \"as\" argument: \"%s\"", strdup_n(o,s-o));
        }
        if(!*s)
@@ -635,12 +643,15 @@ static void s_endSWF()
     swf = stack[stackpos].swf;
     filename = stack[stackpos].filename;
    
-    //tag = swf_InsertTag(tag, ST_SHOWFRAME); //?
-
+    tag = swf_InsertTag(tag, ST_SHOWFRAME);
     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" */
     }
@@ -691,13 +702,29 @@ int s_getframe()
     return currentframe;
 }
 
-void s_frame(int nr, int cut)
+void s_frame(int nr, int cut, char*name)
 {
     int t;
     TAG*now = tag;
 
+    /* // enabling the following code will make the frame
+       handling much more intuitive, but also break old
+       code:
+       
+       if(nr<1) 
+       syntaxerror("Frame number need to be at least 1");
+    nr--;*/
+
     for(t=currentframe;t<nr;t++) {
        tag = swf_InsertTag(tag, ST_SHOWFRAME);
+       if(t==nr-1 && name && *name) {
+           tag = swf_InsertTag(tag, ST_FRAMELABEL);
+           swf_SetString(tag, name);
+       }
+    }
+    if(nr == 0 && currentframe == 0 && name) {
+        tag = swf_InsertTag(tag, ST_FRAMELABEL);
+        swf_SetString(tag, name);
     }
 
     if(cut) {
@@ -730,10 +757,22 @@ int addFillStyle(SHAPE*s, SRECT*r, char*texture)
        return swf_ShapeAddBitmapFillStyle(s, &m, image->id, 0);
     } /*else if ((texture = dictionary_lookup(&textures, texture))) {
     } */ else if ((gradient = dictionary_lookup(&gradients, texture))) {
-       MATRIX m;
+       SRECT r2;
+       MATRIX rot,m;
+       double ccos,csin;
+       swf_GetMatrix(0, &rot);
+       ccos = cos(-gradient->rotate*2*3.14159265358979/360);
+       csin = sin(-gradient->rotate*2*3.14159265358979/360);
+       rot.sx =  ccos*65536;
+       rot.r1 = -csin*65536;
+       rot.r0 =  csin*65536;
+       rot.sy =  ccos*65536;
+       r2 = swf_TurnRect(*r, &rot);
        swf_GetMatrix(0, &m);
-       m.sx = (r->xmax - r->xmin)*2;
-       m.sy = (r->ymax - r->ymin)*2;
+       m.sx =  (r2.xmax - r2.xmin)*2*ccos;
+       m.r1 = -(r2.xmax - r2.xmin)*2*csin;
+       m.r0 =  (r2.ymax - r2.ymin)*2*csin;
+       m.sy =  (r2.ymax - r2.ymin)*2*ccos;
        m.tx = r->xmin + (r->xmax - r->xmin)/2;
        m.ty = r->ymin + (r->ymax - r->ymin)/2;
        return swf_ShapeAddGradientFillStyle(s, &m, &gradient->gradient, gradient->radial);
@@ -755,7 +794,7 @@ void s_box(char*name, int width, int height, RGBA color, int linewidth, char*tex
     r2.ymin = 0;
     r2.xmax = width;
     r2.ymax = height;
-    tag = swf_InsertTag(tag, ST_DEFINESHAPE);
+    tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
     ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
 
@@ -793,7 +832,7 @@ void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*textu
     }
     r2 = outline->bbox;
 
-    tag = swf_InsertTag(tag, ST_DEFINESHAPE);
+    tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
     ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
     if(texture)
@@ -825,7 +864,7 @@ void s_circle(char*name, int r, RGBA color, int linewidth, char*texture)
     r2.xmax = 2*r;
     r2.ymax = 2*r;
 
-    tag = swf_InsertTag(tag, ST_DEFINESHAPE);
+    tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
     ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
     if(texture)
@@ -888,7 +927,7 @@ void s_textshape(char*name, char*fontname, float size, char*_text)
 void s_text(char*name, char*fontname, char*text, int size, RGBA color)
 {
     SRECT r;
-
+    MATRIX _m,*m=0;
     SWFFONT*font;
     font = dictionary_lookup(&fonts, fontname);
     if(!font)
@@ -906,6 +945,21 @@ void s_text(char*name, char*fontname, char*text, int size, RGBA color)
     incrementid();
 }
 
+void s_quicktime(char*name, char*url)
+{
+    SRECT r;
+    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();
+}
+
 void s_edittext(char*name, char*fontname, int size, int width, int height, char*text, RGBA*color, int maxlength, char*variable, int flags)
 {
     SWFFONT*font;
@@ -1016,6 +1070,8 @@ 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;
     tag = swf_InsertTag(tag, ST_DEFINEFONT2);
@@ -1120,13 +1176,14 @@ GRADIENT parseGradient(const char*str)
     return gradient;
 }
 
-void s_gradient(char*name, const char*text, int radial)
+void s_gradient(char*name, const char*text, int radial, int rotate)
 {
     gradient_t* gradient;
     gradient = malloc(sizeof(gradient_t));
     memset(gradient, 0, sizeof(gradient_t));
     gradient->gradient = parseGradient(text);
     gradient->radial = radial;
+    gradient->rotate = rotate;
 
     if(dictionary_lookup(&gradients, name))
        syntaxerror("gradient %s defined twice", name);
@@ -1151,8 +1208,11 @@ void s_action(const char*text)
 int s_swf3action(char*name, char*action)
 {
     ActionTAG* a = 0;
-    instance_t* object = dictionary_lookup(&instances, name);
-    if(!object) {
+    instance_t* object = 0;
+    if(name) 
+       dictionary_lookup(&instances, name);
+    if(!object && name && *name) {
+       /* we have a name, but couldn't find it. Abort. */
        return 0;
     }
     a = action_SetTarget(0, name);
@@ -1200,7 +1260,10 @@ void s_outline(char*name, char*format, char*source)
 
 int s_playsound(char*name, int loops, int nomultiple, int stop)
 {
-    sound_t* sound = dictionary_lookup(&sounds, name);
+    sound_t* sound;
+    if(!name)
+       return 0;
+    sound = dictionary_lookup(&sounds, name);
     SOUNDINFO info;
     if(!sound)
        return 0;
@@ -1224,7 +1287,7 @@ void s_includeswf(char*name, char*filename)
     TAG* s;
     int level = 0;
     U16 cutout[] = {ST_SETBACKGROUNDCOLOR, ST_PROTECT, ST_FREEALL, ST_REFLEX};
-    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));
        s_box(name, 0, 0, black, 20, 0);
@@ -1335,6 +1398,7 @@ void s_endClip()
     swf_SetTagPos(stack[stackpos].tag, 0);
     swf_GetPlaceObject(stack[stackpos].tag, &p);
     p.clipdepth = currentdepth;
+    p.name = 0;
     swf_ClearTag(stack[stackpos].tag);
     swf_SetPlaceObject(stack[stackpos].tag, &p);
     currentdepth++;
@@ -1821,12 +1885,13 @@ static int c_gradient(map_t*args)
 {
     char*name = lu(args, "name");
     int radial= strcmp(lu(args, "radial"), "radial")?0:1;
+    int rotate = parseInt(lu(args, "rotate"));
 
     readToken();
     if(type != RAWDATA)
        syntaxerror("colon (:) expected");
 
-    s_gradient(name, text, radial);
+    s_gradient(name, text, radial,rotate);
     return 0;
 }
 static int c_point(map_t*args) 
@@ -1869,7 +1934,7 @@ static int c_play(map_t*args)
 
 static int c_stop(map_t*args) 
 {
-    char*name = lu(args, "name");
+    char*name = map_lookup(args, "name");
 
     if(s_playsound(name, 0,0,1)) {
        return 0;
@@ -2151,6 +2216,7 @@ static int c_frame(map_t*args)
 {
     char*framestr = lu(args, "n");
     char*cutstr = lu(args, "cut");
+    char*name = lu(args, "name");
     int frame;
     int cut = 0;
     if(strcmp(cutstr, "no"))
@@ -2167,7 +2233,7 @@ static int c_frame(map_t*args)
                && !(frame==0 && s_getframe()==frame)) // equality is o.k. for frame 0
            syntaxerror("frame expression must be >%d (is:%s)", s_getframe(), framestr);
     }
-    s_frame(frame, cut);
+    s_frame(frame, cut, name);
     return 0;
 }
 static int c_primitive(map_t*args) 
@@ -2266,6 +2332,14 @@ static int c_soundtrack(map_t*args)
     return 0;
 }
 
+static int c_quicktime(map_t*args) 
+{
+    char*name = lu(args, "name");
+    char*url = lu(args, "url");
+    s_quicktime(name, url);
+    return 0;
+}
+
 static int c_image(map_t*args) 
 {
     char*command = lu(args, "commandname");
@@ -2428,7 +2502,7 @@ 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"},
     char*name = lu(args, "name");
     char*font = lu(args, "font");
-    int size = (int)(100*20*parsePercent(lu(args, "size")));
+    int size = (int)(1024*parsePercent(lu(args, "size")));
     int width = parseTwip(lu(args, "width"));
     int height = parseTwip(lu(args, "height"));
     char*text  = lu(args, "text");
@@ -2479,7 +2553,7 @@ static struct {
     char*arguments;
 } arguments[] =
 {{"flash", c_flash, "bbox=autocrop background=black version=5 fps=50 name=!default! @compress=default"},
- {"frame", c_frame, "n=<plus>1 @cut=no"},
+ {"frame", c_frame, "n=<plus>1 name= @cut=no"},
  // "import" type stuff
  {"swf", c_swf, "name filename"},
  {"shape", c_swf, "name filename"},
@@ -2489,11 +2563,12 @@ static struct {
  {"sound", c_sound, "name filename"},
  {"font", c_font, "name filename"},
  {"soundtrack", c_soundtrack, "filename"},
+ {"quicktime", c_quicktime, "url"},
 
     // generators of primitives
 
  {"point", c_point, "name x=0 y=0"},
- {"gradient", c_gradient, "name @radial=0"},
+ {"gradient", c_gradient, "name @radial=0 rotate=0"},
  {"outline", c_outline, "name format=simple"},
  {"textshape", c_textshape, "name font size=100% text"},
 
@@ -2510,13 +2585,13 @@ static struct {
     {"show", c_show,             "name x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below= as="},
     {"on_press", c_on_press, "position=inside"},
     {"on_release", c_on_release, "position=anywhere"},
-    {"on_move_in", c_on_move_out, "state=not_pressed"},
+    {"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"},
+ {"stop", c_stop, "name= "},
  {"nextframe", c_nextframe, "name"},
  {"previousframe", c_previousframe, "name"},