moved wav.h to ../lib
[swftools.git] / src / swfc.c
index 3bf8a73..131c794 100644 (file)
 #include "../lib/log.h"
 #include "../lib/args.h"
 #include "../lib/q.h"
+#include "../lib/mp3.h"
+#include "../lib/wav.h"
 #include "parser.h"
-#include "wav.h"
+#include "../lib/png.h"
 
 //#define DEBUG
 
@@ -48,7 +50,6 @@ static struct options_t options[] = {
 {"V", "version"},
 {"v", "verbose"},
 {"o", "output"},
-{"O", "optimize"},
 {0,0}
 };
     
@@ -728,11 +729,13 @@ void s_frame(int nr, int cut, char*name)
        if(t==nr-1 && name && *name) {
            tag = swf_InsertTag(tag, ST_FRAMELABEL);
            swf_SetString(tag, name);
+           swf_SetU8(tag, 1); //make this an anchor
        }
     }
     if(nr == 0 && currentframe == 0 && name) {
         tag = swf_InsertTag(tag, ST_FRAMELABEL);
         swf_SetString(tag, name);
+       swf_SetU8(tag, 1); //make this an anchor
     }
 
     if(cut) {
@@ -806,16 +809,18 @@ void s_box(char*name, int width, int height, RGBA color, int linewidth, char*tex
     r2.ymax = height;
     tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
-    if(linewidth)
-        ls1 = swf_ShapeAddLineStyle(s,linewidth>=20?linewidth-20:0,&color);
+    if(linewidth) {
+       linewidth = linewidth>=20?linewidth-20:0;
+        ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
+    }
     if(texture)
        fs1 = addFillStyle(s, &r2, texture);
 
     swf_SetU16(tag,id);
-    r.xmin = r2.xmin-linewidth-linewidth/2;
-    r.ymin = r2.ymin-linewidth-linewidth/2;
-    r.xmax = r2.xmax+linewidth+linewidth/2;
-    r.ymax = r2.ymax+linewidth+linewidth/2;
+    r.xmin = r2.xmin-linewidth/2;
+    r.ymin = r2.ymin-linewidth/2;
+    r.xmax = r2.xmax+linewidth/2;
+    r.ymax = r2.ymax+linewidth/2;
     swf_SetRect(tag,&r);
     swf_SetShapeHeader(tag,s);
     swf_ShapeSetAll(tag,s,0,0,ls1,fs1,0);
@@ -844,22 +849,24 @@ void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*textu
 
     tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
-    if(linewidth)
-        ls1 = swf_ShapeAddLineStyle(s,linewidth>=20?linewidth-20:0,&color);
+    if(linewidth) {
+       linewidth = linewidth>=20?linewidth-20:0;
+        ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
+    }
     if(texture)
        fs1 = addFillStyle(s, &r2, texture);
     
     swf_SetU16(tag,id);
-    rect.xmin = r2.xmin-linewidth-linewidth/2;
-    rect.ymin = r2.ymin-linewidth-linewidth/2;
-    rect.xmax = r2.xmax+linewidth+linewidth/2;
-    rect.ymax = r2.ymax+linewidth+linewidth/2;
+    rect.xmin = r2.xmin-linewidth/2;
+    rect.ymin = r2.ymin-linewidth/2;
+    rect.xmax = r2.xmax+linewidth/2;
+    rect.ymax = r2.ymax+linewidth/2;
 
     swf_SetRect(tag,&rect);
     swf_SetShapeStyles(tag, s);
     swf_ShapeCountBits(s,0,0);
-    swf_RecodeShapeData(outline->shape->data, outline->shape->bitlen, 1,            1, 
-                        &s->data,             &s->bitlen,             s->bits.fill, s->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);
     swf_ShapeFree(s);
@@ -879,15 +886,17 @@ void s_circle(char*name, int r, RGBA color, int linewidth, char*texture)
 
     tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
-    if(linewidth)
-        ls1 = swf_ShapeAddLineStyle(s,linewidth>=20?linewidth-20:0,&color);
+    if(linewidth) {
+       linewidth = linewidth>=20?linewidth-20:0;
+        ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
+    }
     if(texture)
        fs1 = addFillStyle(s, &r2, texture);
     swf_SetU16(tag,id);
-    rect.xmin = r2.xmin-linewidth-linewidth/2;
-    rect.ymin = r2.ymin-linewidth-linewidth/2;
-    rect.xmax = r2.xmax+linewidth+linewidth/2;
-    rect.ymax = r2.ymax+linewidth+linewidth/2;
+    rect.xmin = r2.xmin-linewidth/2;
+    rect.ymin = r2.ymin-linewidth/2;
+    rect.xmax = r2.xmax+linewidth/2;
+    rect.ymax = r2.ymax+linewidth/2;
 
     swf_SetRect(tag,&rect);
     swf_SetShapeHeader(tag,s);
@@ -974,7 +983,7 @@ void s_quicktime(char*name, char*url)
     incrementid();
 }
 
-void s_edittext(char*name, char*fontname, int size, int width, int height, char*text, RGBA*color, int maxlength, char*variable, int flags)
+void s_edittext(char*name, char*fontname, int size, int width, int height, char*text, RGBA*color, int maxlength, char*variable, int flags, int align)
 {
     SWFFONT*font = 0;
     EditTextLayout layout;
@@ -988,7 +997,7 @@ void s_edittext(char*name, char*fontname, int size, int width, int height, char*
     }
     tag = swf_InsertTag(tag, ST_DEFINEEDITTEXT);
     swf_SetU16(tag, id);
-    layout.align = 0;
+    layout.align = align;
     layout.leftmargin = 0;
     layout.rightmargin = 0;
     layout.indent = 0;
@@ -1015,12 +1024,7 @@ void s_image(char*name, char*type, char*filename, int quality)
     SRECT r;
     int imageID = id;
     int width, height;
-    if(type=="png") {
-       warning("image type \"png\" not supported yet!");
-       s_box(name, 0, 0, black, 20, 0);
-       return;
-    }
-    if(type=="jpeg") {
+    if(!strcmp(type,"jpeg")) {
 #ifndef HAVE_LIBJPEG
        warning("no jpeg support compiled in");
        s_box(name, 0, 0, black, 20, 0);
@@ -1043,6 +1047,31 @@ void s_image(char*name, char*type, char*filename, int quality)
        s_addimage(name, id, tag, r);
        incrementid();
 #endif
+    } else if(!strcmp(type,"png")) {
+       RGBA*data = 0;
+       swf_SetU16(tag, imageID);
+
+       getPNG(filename, &width, &height, (unsigned char**)&data);
+
+       if(!data) {
+           syntaxerror("Image \"%s\" not found, or contains errors", filename);
+       }
+
+       /*tag = swf_AddImage(tag, imageID, data, width, height, quality)*/
+       tag = swf_InsertTag(tag, ST_DEFINEBITSLOSSLESS);
+       swf_SetU16(tag, imageID);
+       swf_SetLosslessImage(tag, data, width, height);
+
+       r.xmin = 0;
+       r.ymin = 0;
+       r.xmax = width*20;
+       r.ymax = height*20;
+       s_addimage(name, id, tag, r);
+       incrementid();
+    } else {
+       warning("image type \"%s\" not supported yet!", type);
+       s_box(name, 0, 0, black, 20, 0);
+       return;
     }
 
     /* step 2: the character */
@@ -1151,6 +1180,10 @@ void s_font(char*name, char*filename)
     font->id = id;
     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(dictionary_lookup(&fonts, name))
@@ -1169,17 +1202,16 @@ typedef struct _sound_t
 void s_sound(char*name, char*filename)
 {
     struct WAV wav, wav2;
+    struct MP3 mp3;
     sound_t* sound;
-    U16*samples;
-    int numsamples;
-    int t;
-
-    if(!readWAV(filename, &wav)) {
-       warning("Couldn't read wav file \"%s\"", filename);
-       samples = 0;
-       numsamples = 0;
-    } else {
-       convertWAV2mono(&wav, &wav2, 44100);
+    U16*samples = NULL;
+    unsigned numsamples;
+    unsigned blocksize = 1152;
+    int is_mp3 = 0;
+
+    if(wav_read(filename, &wav)) {
+        int t;
+       wav_convert2mono(&wav, &wav2, 44100);
        samples = (U16*)wav2.data;
        numsamples = wav2.size/2;
        free(wav.data);
@@ -1189,11 +1221,47 @@ void s_sound(char*name, char*filename)
            samples[t] = (samples[t]>>8)&0xff | (samples[t]<<8)&0xff00;
        }
 #endif
+    } else if(mp3_read(&mp3, filename)) {
+        fprintf(stderr, "\"%s\" seems to work as a MP3 file...\n", filename);
+        blocksize = 1;
+        is_mp3 = 1;
+    }
+    else
+    {
+       warning("Couldn't read WAV/MP3 file \"%s\"", filename);
+       samples = 0;
+       numsamples = 0;
+    }
+    
+    if(numsamples%blocksize != 0)
+    {
+       // apply padding, so that block is a multiple of blocksize
+       int numblocks = (numsamples+blocksize-1)/blocksize;
+       int numsamples2;
+       U16* samples2;
+       numsamples2 = numblocks * blocksize;
+       samples2 = malloc(sizeof(U16)*numsamples2);
+       memcpy(samples2, samples, numsamples*sizeof(U16));
+       memset(&samples2[numsamples], 0, sizeof(U16)*(numsamples2 - numsamples));
+       numsamples = numsamples2;
+       samples = samples2;
     }
 
     tag = swf_InsertTag(tag, ST_DEFINESOUND);
     swf_SetU16(tag, id); //id
-    swf_SetSoundDefine(tag, samples, numsamples);
+    if(is_mp3)
+    {
+        swf_SetSoundDefineMP3(
+                tag, mp3.data, mp3.size,
+                mp3.SampRate,
+                mp3.Channels,
+                mp3.NumFrames);
+       mp3_clear(&mp3);
+    }
+    else
+    {
+        swf_SetSoundDefine(tag, samples, numsamples);
+    }
    
     sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */
     sound->tag = tag;
@@ -1291,6 +1359,24 @@ void s_action(const char*text)
     swf_ActionFree(a);
 }
 
+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) {
+       syntaxerror("Couldn't compile ActionScript");
+    }
+
+    c = (character_t*)dictionary_lookup(&characters, character);
+
+    tag = swf_InsertTag(tag, ST_DOINITACTION);
+    swf_SetU16(tag, c->id);
+    swf_ActionSet(tag, a);
+
+    swf_ActionFree(a);
+}
+
 int s_swf3action(char*name, char*action)
 {
     ActionTAG* a = 0;
@@ -1324,7 +1410,9 @@ void s_outline(char*name, char*format, char*source)
     SHAPE2* shape2;
     SRECT bounds;
     
+    //swf_Shape10DrawerInit(&draw, 0);
     swf_Shape11DrawerInit(&draw, 0);
+
     draw_string(&draw, source);
     draw.finish(&draw);
     shape = swf_ShapeDrawerToShape(&draw);
@@ -2683,7 +2771,7 @@ static int c_on_key(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"},
+ //"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");
     char*font = lu(args, "font");
     int size = (int)(1024*parsePxOrPercent(font, lu(args, "size")));
@@ -2700,6 +2788,9 @@ static int c_edittext(map_t*args)
     char*noselectstr = lu(args, "noselect");
     char*readonlystr = lu(args, "readonly");
     char*borderstr = lu(args, "border");
+    char*autosizestr = lu(args, "autosize");
+    char*alignstr = lu(args, "align");
+    int align = -1;
 
     int flags = 0;
     if(!strcmp(passwordstr, "password")) flags |= ET_PASSWORD;
@@ -2709,14 +2800,37 @@ static int c_edittext(map_t*args)
     if(!strcmp(htmlstr, "html")) flags |= ET_HTML;
     if(!strcmp(noselectstr, "noselect")) flags |= ET_NOSELECT;
     if(!strcmp(borderstr, "border")) flags |= ET_BORDER;
-
-    s_edittext(name, font, size, width, height, text, &color, maxlength, variable, flags);
+    if(!strcmp(autosizestr, "autosize")) flags |= ET_AUTOSIZE;
+    if(!strcmp(alignstr, "left") || !*alignstr) align = ET_ALIGN_LEFT;
+    else if(!strcmp(alignstr, "right")) align = ET_ALIGN_RIGHT;
+    else if(!strcmp(alignstr, "center")) align = ET_ALIGN_CENTER;
+    else if(!strcmp(alignstr, "justify")) align = ET_ALIGN_JUSTIFY;
+    else syntaxerror("Unknown alignment: %s", alignstr);
+
+    s_edittext(name, font, size, width, height, text, &color, maxlength, variable, flags, align);
     return 0;
 }
 
 static int c_morphshape(map_t*args) {return fakechar(args);}
 static int c_movie(map_t*args) {return fakechar(args);}
 
+static char* readfile(const char*filename)
+{
+    FILE*fi = fopen(filename, "rb");
+    int l;
+    char*text;
+    if(!fi) 
+       syntaxerror("Couldn't find file %s: %s", filename, strerror(errno));
+    fseek(fi, 0, SEEK_END);
+    l = ftell(fi);
+    fseek(fi, 0, SEEK_SET);
+    text = rfx_alloc(l+1);
+    fread(text, l, 1, fi);
+    text[l]=0;
+    fclose(fi);
+    return text;
+}
+
 static int c_action(map_t*args) 
 {
     char* filename  = map_lookup(args, "filename");
@@ -2727,20 +2841,24 @@ static int c_action(map_t*args)
        }
        s_action(text);
     } else {
-       FILE*fi = fopen(filename, "rb");
-       int l;
-       char*text;
-       if(!fi) 
-           syntaxerror("Couldn't find file %s: %s", filename, strerror(errno));
-       fseek(fi, 0, SEEK_END);
-       l = ftell(fi);
-       fseek(fi, 0, SEEK_SET);
-       text = rfx_alloc(l+1);
-       fread(text, l, 1, fi);
-       text[l]=0;
-       fclose(fi);
+       s_action(readfile(filename));
+    }
+   
+    return 0;
+}
 
-       s_action(text);
+static int c_initaction(map_t*args) 
+{
+    char* character = lu(args, "name");
+    char* filename  = map_lookup(args, "filename");
+    if(!filename ||!*filename) {
+       readToken();
+       if(type != RAWDATA) {
+           syntaxerror("colon (:) expected");
+       }
+       s_initaction(character, text);
+    } else {
+       s_initaction(character, readfile(filename));
     }
    
     return 0;
@@ -2778,7 +2896,7 @@ static struct {
 
  {"egon", c_egon, "name vertices color=white line=1 @fill=none"},
  {"text", c_text, "name text font size=100% color=white"},
- {"edittext", c_edittext, "name font= size=100% width height text="" color=white maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0 @border=0"},
+ {"edittext", c_edittext, "name font= size=100% width height text="" color=white maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0 @border=0 @autosize=0 align="},
  {"morphshape", c_morphshape, "name start end"},
  {"button", c_button, "name"},
     {"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="},
@@ -2809,6 +2927,7 @@ static struct {
 //startclip (see above)
  {"sprite", c_sprite, "name"},
  {"action", c_action, "filename="},
+ {"initaction", c_initaction, "name filename="},
 
  {"end", c_end, ""}
 };