implement --merge, --frame and --stack1 options.
authorkramm <kramm>
Sun, 16 Dec 2001 01:16:35 +0000 (01:16 +0000)
committerkramm <kramm>
Sun, 16 Dec 2001 01:16:35 +0000 (01:16 +0000)
src/combine.c
src/settings.h
src/swfcombine.1
src/swfcombine.c

index 8547d37..02e714c 100644 (file)
@@ -19,8 +19,9 @@
 // TODO:
 // * readers should be object-oriented
 
-static char* slavename;
-static int slaveid;
+static char* slavename = 0;
+static int slaveid = -1;
+static int slaveframe = -1;
 
 static char* tag_placeobject2_name (struct swf_tag* tag)
 {
@@ -230,7 +231,7 @@ void write_sprite(struct writer_t*w, int spriteid, int replaceddefine)
        writer_write(w, &tmp,2);
     }
 
-    if(config.overlay) {
+    if(config.overlay && !config.isframe) {
        tmp = 5 + (TAGID_PLACEOBJECT2 << 6);
        writer_write(w, &tmp, 2);
        tmp = 2; //flags: character
@@ -263,18 +264,47 @@ void write_sprite(struct writer_t*w, int spriteid, int replaceddefine)
     logf("<verbose> sprite length is %d",*tagidpos);
 }
 
+static char tag_ok_for_slave(int id)
+{
+    if(id == TAGID_BACKGROUNDCOLOR)
+       return 0;
+    return 1;
+}
+
 #define FLAGS_WRITEDEFINES 1
 #define FLAGS_WRITENONDEFINES 2
 #define FLAGS_WRITESPRITE 4
+#define FLAGS_WRITESLAVE 8
 void write_master(struct writer_t*w, int spriteid, int replaceddefine, int flags)
 {
     int pos = 0;
-    do {
-       if(is_defining_tag(master.tags[pos].id) && (flags&1))
+    int spos = 0;
+    int outputslave = 0;
+    int frame = 0;
+    int sframe = 0;
+    int slavewritten = 0;
+    while(master.tags[pos].id != 0)
+    {
+       if(master.tags[pos].id == TAGID_SHOWFRAME && outputslave)
+       {
+           while(slave.tags[spos].id) {
+               if(slave.tags[spos].id == TAGID_SHOWFRAME) {
+                   spos++;
+                   sframe++;
+                   break;
+               }
+               if(tag_ok_for_slave(slave.tags[spos].id))
+                   writer_write(w, slave.tags[spos].fulldata, slave.tags[spos].fulllength);
+               spos++;
+           }
+           frame ++;
+       }
+
+       if(is_defining_tag(master.tags[pos].id) && (flags&FLAGS_WRITEDEFINES))
        {
            logf("<debug> [master] write tag %02x (%d bytes in body)", 
                    master.tags[pos].id, master.tags[pos].length);
-           if( getidfromtag(&master.tags[pos]) == spriteid) 
+           if(getidfromtag(&master.tags[pos]) == spriteid && !config.isframe)
            {
                if(config.overlay)
                {
@@ -286,23 +316,84 @@ void write_master(struct writer_t*w, int spriteid, int replaceddefine, int flags
                            ,spriteid);
                }
 
-               if(flags&4)
+               if(flags&FLAGS_WRITESPRITE)
                {
                    write_sprite_defines(w);
                    write_sprite(w, spriteid, replaceddefine);
                }
+               if(flags&FLAGS_WRITESLAVE)
+               {
+                   outputslave = 1;
+               }
            } else { 
                writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
            }
        }
-       if(!is_defining_tag(master.tags[pos].id) && (flags&2))
+       if(frame == slaveframe)
        {
-           logf("<debug> [master] write tag %02x (%d bytes in body)", 
-                   master.tags[pos].id, master.tags[pos].length);
-           writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
+           if(flags&FLAGS_WRITESLAVE) {
+               outputslave = 1;
+               slavewritten = 1;
+           }
+           if((flags&FLAGS_WRITESPRITE) && !slavewritten)
+           {
+               int id = get_free_id();
+               int depth = 0;
+               char data[7];
+               if(config.clip) {
+                   logf("<fatal> Can't combine --clip and --frame");
+               }
+               *(u16*)&data[0] = (u16)(TAGID_PLACEOBJECT2<<6) + 5 ;
+               *(u8*)&data[2]= 2; //flags: id
+               *(u16*)&data[3]= depth; // depth
+               *(u16*)&data[5]= id;
+               write_sprite_defines(w);
+               write_sprite(w, id, -1);
+               writer_write(w,data,7);
+               slavewritten = 1;
+           }
+       }
+       if(!is_defining_tag(master.tags[pos].id) && (flags&FLAGS_WRITENONDEFINES))
+       {
+           int dontwrite = 0;
+           switch(master.tags[pos].id) {
+               case TAGID_PLACEOBJECT:
+               case TAGID_PLACEOBJECT2:
+                   if(frame == slaveframe && !config.overlay)
+                       dontwrite = 1;
+               case TAGID_REMOVEOBJECT:
+//             case TAGID_REMOVEOBJECT2:
+                   /* place/removetags for the object we replaced
+                      should be discarded, too, as the object to insert 
+                      isn't a sprite 
+                    */
+                   if(spriteid>=0 && getidfromtag(&master.tags[pos]) == spriteid && !config.isframe)
+                       dontwrite = 1;
+               break;
+           }
+           if(!dontwrite) {
+               logf("<debug> [master] write tag %02x (%d bytes in body)", 
+                       master.tags[pos].id, master.tags[pos].length);
+               writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
+           }
        }
+       pos++;
+    }
+   
+    if(outputslave) 
+    while(slave.tags[spos].id)
+    {
+           if(tag_ok_for_slave(slave.tags[spos].id))
+               writer_write(w, slave.tags[spos].fulldata, slave.tags[spos].fulllength);
+           spos++;
+    }
+    if(!slavewritten && config.isframe && (flags&(FLAGS_WRITESLAVE|FLAGS_WRITESPRITE)))
+    {
+       logf("<warning> Frame %d doesn't exist in file. No substitution will occur",
+               slaveframe);
     }
-    while(master.tags[pos++].id != 0);
+    //write END tag: 
+    writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
 }
 
 void writeheader(struct writer_t*w, u8*data, int length)
@@ -335,13 +426,19 @@ uchar * catcombine(uchar*masterdata, int masterlength, char*_slavename, uchar*sl
        struct writer_t w;
        u32*headlength;
        u32 tmp32;
-       int length = masterlength + slavelength;
+       int length = masterlength*2 + slavelength;
        int pos = 0;
+       int t;
+       char* depths;
        uchar*newdata = malloc(length);
        if(!newdata) {
            logf("<fatal> Couldn't allocate %d bytes of memory", length);
            return 0;
        }
+       if(config.isframe) {
+           logf("<fatal> Can't combine --cat and --frame");
+           exit(1);
+       }
        writer_init(&w, newdata, length);
        
        do {
@@ -361,15 +458,54 @@ uchar * catcombine(uchar*masterdata, int masterlength, char*_slavename, uchar*sl
        headlength = (u32*)(writer_getpos(&w) + 1);
        writeheader(&w, master.header.headerdata, master.header.headerlength);
 
+       depths = malloc(65536);
+       if(!depths) {
+           logf("<fatal> Couldn't allocate %d bytes of memory", 65536);
+           return 0;
+       }
+       memset(depths, 0, 65536);
        pos = 0;
        do {
+           int num=1;
+           u16 depth;
            logf("<debug> [master] write tag %02x (%d bytes in body)", 
                    master.tags[pos].id, master.tags[pos].length);
+           switch(master.tags[pos].id) {
+               case TAGID_PLACEOBJECT2:
+                   num++;
+               case TAGID_PLACEOBJECT:
+                  reader_init (master.tags[pos].data, master.tags[pos].length);
+                  if(num>=2)
+                       readu8();
+                  depth = readu16();
+                  depths[depth] = 1;
+               break;
+               case TAGID_REMOVEOBJECT:
+                  reader_init (master.tags[pos].data, master.tags[pos].length);
+                  readu16();
+                  depths[readu16()] = 0;
+               break;
+               case TAGID_REMOVEOBJECT2:
+                  reader_init (master.tags[pos].data, master.tags[pos].length);
+                  depths[readu16()] = 0;
+               break;
+           }
            if(master.tags[pos].id != 0)
                writer_write(&w, master.tags[pos].fulldata, master.tags[pos].fulllength);
        }
        while(master.tags[pos++].id != 0);
 
+       for(t=0;t<65536;t++) 
+       if(depths[t])
+       {
+           char data[16];
+           int len;
+           *(u16*)(&data[0]) = (TAGID_REMOVEOBJECT2<<6) + 2;
+           *(u16*)(&data[2]) = t;
+           writer_write(&w, data, 4);
+       }
+       free(depths);
+
        pos = 0;
        do {
            logf("<debug> [slave] write tag %02x (%d bytes in body)", 
@@ -395,6 +531,8 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar
        int spriteid = -1;
        int replaceddefine = -1;
        struct writer_t w;
+       int frame;
+       char*framelabel;
        
        length = masterlength + slavelength*2 + 128; // this is a guess, but a good guess.
        newdata = malloc(length);
@@ -429,12 +567,22 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar
                      logf("<notice> Slave file attached to object %d.", id);
                    }
                }
+           } else if(tag == TAGID_SHOWFRAME) {
+               if(slaveframe>=0 && frame==slaveframe) {
+                   logf("<notice> Slave file attached to frame %d.", frame);
+               }
+               frame++;
+           } else if(tag == TAGID_FRAMELABEL) {
+               char * name = master.tags[pos].data;
+               if(name && slavename && config.isframe && !strcmp(name, slavename)) {
+                   slaveframe = frame;
+                   logf("<notice> Slave file attached to frame %d (%s).", frame, name);
+               }
            }
        }
        while(master.tags[pos++].id != 0);
 
-       if (spriteid<0)
-       {
+       if (spriteid<0 && !config.isframe) {
            if(slavename) {
                if(strcmp(slavename,"!!dummy!!"))
                    logf("<warning> Didn't find anything named %s in file. No substitutions will occur.", slavename);
@@ -448,7 +596,7 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar
 
        read_swf(&slave, slavedata, slavelength);
        
-       if(config.overlay)
+       if (config.overlay)
            replaceddefine = get_free_id();
        
        // write file 
@@ -457,13 +605,20 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar
        headlength = (u32*)(writer_getpos(&w) + 1);
        writeheader(&w, master.header.headerdata, master.header.headerlength);
 
-       if(config.antistream) {
+       if (config.antistream) {
+           if (config.merge) {
+               logf("<fatal> Can't combine --antistream and --merge");
+           }
            write_sprite_defines(&w);
            write_sprite(&w, spriteid, replaceddefine);
            write_master(&w, spriteid, replaceddefine, FLAGS_WRITEDEFINES);
            write_master(&w, spriteid, replaceddefine, FLAGS_WRITENONDEFINES);
        } else {
-           write_master(&w, spriteid, replaceddefine, 
+           if (config.merge)
+               write_master(&w, spriteid, replaceddefine, 
+                   FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES|FLAGS_WRITESLAVE);
+           else
+               write_master(&w, spriteid, replaceddefine, 
                    FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES|FLAGS_WRITESPRITE);
        }
 
@@ -479,16 +634,26 @@ uchar * combine(uchar*masterdata, int masterlength, char*_slavename, uchar*slave
     char master_flash = 0;
     char slave_flash = 0;
     slavename = _slavename;
+
+    slaveid = -1;
+    slaveframe = -1;
+
     if(slavename[0] == '#')
     {
        slaveid = atoi(&slavename[1]);
        slavename = 0;
     }
+    if(config.isframe)
+    {
+       slaveframe = slaveid;
+       slaveid = -1;
+    }
 
     logf("<debug> move x (%d)", config.movex);
     logf("<debug> move y (%d)", config.movey);
     logf("<debug> scale x (%d)", config.scalex);
     logf("<debug> scale y (%d)", config.scaley);
+    logf("<debug> is frame (%d)", config.isframe);
     
     memset(masterids, -1, sizeof(masterids));
 
index 5fe39b1..19470a9 100644 (file)
@@ -16,9 +16,12 @@ struct config_t
    char alloctest;
    char clip;
    char stack;
+   char stack1;
    char antistream;
    char dummy;
    char cat;
+   char merge;
+   char isframe;
    int loglevel;
    int movex;
    int movey;
index 71736fa..297d4f6 100644 (file)
@@ -12,6 +12,9 @@ swfcombine - a tool for combining swf (flash) files
 [\fIoptions\fR] --stack [\fIslavename1=\fR][\fIslavefile1.swf\fR] ... [\fIslavenameN=\fR][\fIslavefileN.swf\fR]
 
 .B swfcombine
+[\fIoptions\fR] --cat [\fIslavename1=\fR][\fIslavefile1.swf\fR] ... [\fIslavenameN=\fR][\fIslavefileN.swf\fR]
+
+.B swfcombine
 [\fIoptions\fR] --dummy [\fIfile.swf\fR]
 .SH DESCRIPTION
 Take two or more SWF files, and combine them into a new SWF. SWFs can either
@@ -40,6 +43,9 @@ Don't remove any master objects, only overlay new objects.
 \fB\-c\fR, \fB\-\-clip\fR
 Clip the slave objects by the corresponding master objects.
 .TP
+\fB\-m\fR, \fB\-\-merge\fR
+Do not store the slave files in a sprite/MovieClip. Instead, merge the files frame by frame.
+.TP
 \fB\-d\fR, \fB\-\-dummy\fR
 Don't require the presence of slave objects. Usually used together with \fB\-X\fR, \fB\-Y\fR or \fB\-r\fR.
 .TP
@@ -62,6 +68,10 @@ Force the output to height \fIheight\fR. (Otherwise, the height of the master fi
 \fB\-r\fR, \fB\-\-rate\fR \fIrate\fR
 Force the output to have the framerate \fIrate\fR. (Otherwise, the framerate of the master file will be used)
 .TP
+\fB\-f\fR, \fB\-\-frame\fR
+The next slave replaces a frame, not an object. Therefore the slave identifier is a
+frame number (#frame=) or frame label (framelabel=).
+.TP
 \fB\-x\fR, \fB\-\-xpos\fR \fIxpos\fR
 (move x) Adjust position of slave by xpos twips (1/20 pixel).
 .TP
index 4790359..f190e9a 100644 (file)
@@ -25,6 +25,7 @@ int slave_movex[128];
 int slave_movey[128];
 float slave_scalex[128];
 float slave_scaley[128];
+char slave_isframe[128];
 int numslaves = 0;
 
 char * outputname = "output.swf";
@@ -70,6 +71,16 @@ int args_callback_option(char*name,char*val) {
        config.movey = atoi(val);
        return 1;
     }
+    else if (!strcmp(name, "m"))
+    {
+       config.merge = 1;
+       return 0;
+    }
+    else if (!strcmp(name, "f"))
+    {
+       config.isframe = 1;
+       return 0;
+    }
     else if (!strcmp(name, "d"))
     {
        config.dummy = 1;
@@ -97,13 +108,15 @@ int args_callback_option(char*name,char*val) {
        config.scalex = config.scaley = atoi(val)/100.0;
        return 1;
     }
-    else if (!strcmp(name, "t"))
+    else if (!strcmp(name, "t") || !strcmp(name, "T"))
     {
        if(master_filename) {
            fprintf(stderr, "error with arguments. Try --help.\n");
            exit(1);
        }
        config.stack = 1;
+       if(!strcmp(name,"T"))
+           config.stack1 = 1;
        master_filename = "__none__";
        return 0;
     }
@@ -128,8 +141,11 @@ struct options_t options[] =
  {"X","width"},
  {"Y","height"},
  {"r","rate"},
+ {"f","frame"},
  {"l","overlay"},
+ {"m","merge"},
  {"t","stack"},
+ {"T","stack1"},
  {"v","verbose"},
  {"V","version"},
  {"c","clip"},
@@ -160,7 +176,6 @@ int args_callback_command(char*name, char*val) {
     }
 
     if(!master_filename) {
-
        master_filename = filename;
        master_name = myname;
     } else {            
@@ -172,6 +187,8 @@ int args_callback_command(char*name, char*val) {
        slave_movey[numslaves] = config.movey;
        slave_scalex[numslaves] = config.scalex;
        slave_scaley[numslaves] = config.scaley;
+       slave_isframe[numslaves] = config.isframe; 
+       config.isframe = 0;
        config.movex = config.movey = 0;
        config.scalex = config.scaley = 1.0;
        numslaves ++;
@@ -181,21 +198,27 @@ int args_callback_command(char*name, char*val) {
 
 void args_callback_usage(char*name)
 {
-    printf("Usage: %s [-l][-t] [-o outputfile] [[name=]masterfile] [-x xpos] [-y ypos] [-s scale] [name1=]slavefile1 .. [-x xpos] [-y ypos] [-s scale] [nameN=]slavefileN\n", name);
+    printf("Usage: %s [-rXYomlcv] [-f] masterfile] [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN\n", name);
+    printf("OR:    %s [-rXYomv] --stack[1] [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN\n", name);
+    printf("OR:    %s [-rXYov] --cat [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN\n", name);
+    printf("OR:    %s [-rXYomlcv] --dummy [-xys] [file]\n", name);
     printf("\n");
-    printf("-o outputfile       (output) explicitly specify output file. (otherwise, output.swf will be used)\n");
-    printf("-t                  (stack) place each slave into a seperate frame (no master movie)\n");
-    printf("-a                  (cat) concatenate all slave files (no master movie)\n");
-    printf("-l                  (overlay) Don't remove any master objects, only overlay new objects\n");
-    printf("-c                  (clip) Clip the slave objects by the corresponding master objects\n");
-    printf("-v                  (verbose) Use more than one -v for greater effect \n");
-    printf("-d                  (dummy) Don't require slave objects \n");
-    printf("-x xpos             (move x) Adjust position of slave by xpos twips (1/20 pixel)\n");
-    printf("-y ypos             (move y) Adjust position of slave by ypos twips (1/20 pixel)\n");
-    printf("-s scale            (scale) Adjust size of slave by scale%\n");
-    printf("-r framerate        (rate) Set movie framerate (100 frames/sec)\n");
-    printf("-X width            (width) Force movie width to scale (default: use master width) (not with -t)\n");
-    printf("-Y height           (height) Force movie height to scale (default: use master height) (not with -t)\n");
+    printf("-o outputfile       --output    explicitly specify output file. (otherwise, output.swf will be used\n");
+    printf("-t                  --stack     place each slave in a seperate frame (no master movie\n");
+    printf("-T                  --stack1    place each slave in the first frame (no master movie\n");
+    printf("-m                  --merge     Don't store the slaves in Sprites/MovieClips\n");
+    printf("-a                  --cat       concatenate all slave files (no master movie\n");
+    printf("-l                  --overlay   Don't remove any master objects, only overlay new objects\n");
+    printf("-c                  --clip      Clip the slave objects by the corresponding master objects\n");
+    printf("-v                  --verbose   Use more than one -v for greater effect \n");
+    printf("-d                  --dummy     Don't require slave objects \n");
+    printf("-f                  --frame     The following identifier is a frame or framelabel, not an id or objectname\n");
+    printf("-x xpos             --movex     x Adjust position of slave by xpos twips (1/20 pixel\n");
+    printf("-y ypos             --movey     y Adjust position of slave by ypos twips (1/20 pixel\n");
+    printf("-s scale            --scale     Adjust size of slave by scale%\n");
+    printf("-r framerate        --rate      Set movie framerate (100 frames/sec\n");
+    printf("-X width            --width     Force movie width to scale (default: use master width (not with -t\n");
+    printf("-Y height           --height    Force movie height to scale (default: use master height (not with -t\n");
 }
 
 /* read a whole file in memory */
@@ -320,16 +343,19 @@ void makestackmaster(u8**masterdata, int*masterlength)
        *(u16*)&pos[6] = 0; // TAG1
        *(u16*)&pos[8] = (u16)(TAGID_PLACEOBJECT2<<6) + 6 + namelen;
        *(u16*)&pos[10]= 34; //flags: id+name
-       *(u16*)&pos[11]= 1; // depth
+       *(u16*)&pos[11]= 1+t; // depth
        *(u16*)&pos[13]= t+1; // id
        sprintf(&pos[15],slave_name[t]);
        pos += 15 + namelen + 1;
-       *(u16*)&pos[0]= (u16)(TAGID_SHOWFRAME<<6) + 0;
-       pos += 2;
+       if(!config.stack1 || t == numslaves-1) {
+           *(u16*)&pos[0]= (u16)(TAGID_SHOWFRAME<<6) + 0;
+           pos += 2;
+       }
+       if(!config.stack)
        if(t!=numslaves-1)
        {
            *(u16*)&pos[0]= (u16)(TAGID_REMOVEOBJECT2<<6) + 2;
-           *(u16*)&pos[2]= 1; // depth;
+           *(u16*)&pos[2]= 1+t; // depth;
            pos += 4;
        }
     }
@@ -354,6 +380,7 @@ int main(int argn, char *argv[])
     config.antistream = 0; 
     config.alloctest = 0;
     config.cat = 0;
+    config.merge = 0;
     config.clip = 0;
     config.loglevel = 2; 
     config.movex = 0;
@@ -366,11 +393,17 @@ int main(int argn, char *argv[])
     config.hassizey = 0;
     config.framerate = 0;
     config.stack = 0;
+    config.stack1 = 0;
     config.dummy = 0;
 
     processargs(argn, argv);
     initLog(0,-1,0,0,-1,config.loglevel);
 
+    if(config.merge && config.cat) {
+       logf("<error> Can't combine --cat and --merge");
+       exit(1);
+    }
+
     if(config.stack) {
 
        if(config.overlay) {
@@ -403,8 +436,10 @@ int main(int argn, char *argv[])
        fclose(fi);
     }
 
-    for(t=0;t<numslaves;t++)
-       logf("<verbose> slave entity(%d) %s (named \"%s\")\n", t+1, slave_filename[t], slave_name[t]);
+    for(t=0;t<numslaves;t++) {
+           logf("<verbose> slave entity(%d) %s (%s \"%s\")\n", t+1, slave_filename[t], 
+                   slave_isframe[t]?"frame":"object", slave_name[t]);
+    }
 
     if(config.dummy)
     {
@@ -414,8 +449,9 @@ int main(int argn, char *argv[])
            exit(1);
        }
        numslaves = 1;
-       slave_filename[t] = "!!dummy!!";
-       slave_name[t] = "!!dummy!!";
+       slave_filename[0] = "!!dummy!!";
+       slave_name[0] = "!!dummy!!";
+       slave_isframe[0] = 0;
     }
 
     if (config.alloctest)
@@ -441,6 +477,7 @@ int main(int argn, char *argv[])
            config.movey = slave_movey[t];
            config.scalex = slave_scalex[t];
            config.scaley = slave_scaley[t];
+           config.isframe = slave_isframe[t];
 
            logf("<notice> Combine [%s]%s and [%s]%s", master_name, master_filename,
                    slave_name[t], slave_filename[t]);