added support for non-filled outlines.
[swftools.git] / src / swfc.c
index 4d744ff..2c23d95 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;
@@ -636,13 +642,19 @@ static void s_endSWF()
 
     swf = stack[stackpos].swf;
     filename = stack[stackpos].filename;
-   
-    //tag = swf_InsertTag(tag, ST_SHOWFRAME); //?
+  
+    //if(tag->prev && tag->prev->id != ST_SHOWFRAME)
+    //    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" */
     }
@@ -690,7 +702,7 @@ void s_close()
 
 int s_getframe()
 {
-    return currentframe;
+    return currentframe+1;
 }
 
 void s_frame(int nr, int cut, char*name)
@@ -698,6 +710,10 @@ void s_frame(int nr, int cut, char*name)
     int t;
     TAG*now = tag;
 
+    if(nr<1) 
+       syntaxerror("Illegal frame number");
+    nr--; // internally, frame 1 is frame 0
+
     for(t=currentframe;t<nr;t++) {
        tag = swf_InsertTag(tag, ST_SHOWFRAME);
        if(t==nr-1 && name && *name) {
@@ -705,6 +721,10 @@ void s_frame(int nr, int cut, char*name)
            swf_SetString(tag, name);
        }
     }
+    if(nr == 0 && currentframe == 0 && name) {
+        tag = swf_InsertTag(tag, ST_FRAMELABEL);
+        swf_SetString(tag, name);
+    }
 
     if(cut) {
        if(now == tag) {
@@ -768,15 +788,15 @@ void s_box(char*name, int width, int height, RGBA color, int linewidth, char*tex
 {
     SRECT r,r2;
     SHAPE* s;
-    int ls1,fs1=0;
+    int ls1=0,fs1=0;
     r2.xmin = 0;
     r2.ymin = 0;
     r2.xmax = width;
     r2.ymax = height;
     tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
-    ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
-
+    if(linewidth)
+        ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
     if(texture)
        fs1 = addFillStyle(s, &r2, texture);
 
@@ -799,6 +819,37 @@ void s_box(char*name, int width, int height, RGBA color, int linewidth, char*tex
     incrementid();
 }
 
+void swf_RecodeShapeData(U8*data, int bitlen, int in_bits_fill, int in_bits_line, 
+                         U8**destdata, U32*destbitlen, int out_bits_fill, int out_bits_line)
+{
+    SHAPE2 s2;
+    SHAPE s;
+    SHAPELINE*line;
+    memset(&s2, 0, sizeof(s2));
+    s2.lines = swf_ParseShapeData(data, bitlen, in_bits_fill, in_bits_line);
+    s2.numfillstyles = out_bits_fill?1<<(out_bits_fill-1):0;
+    s2.numlinestyles = out_bits_line?1<<(out_bits_line-1):0;
+    s2.fillstyles = rfx_calloc(sizeof(FILLSTYLE)*s2.numfillstyles);
+    s2.linestyles = rfx_calloc(sizeof(LINESTYLE)*s2.numlinestyles);
+
+    line = s2.lines;
+    while(line) {
+        if(line->fillstyle0 > s2.numfillstyles) line->fillstyle0 = 0;
+        if(line->fillstyle1 > s2.numfillstyles) line->fillstyle1 = 0;
+        if(line->linestyle > s2.numlinestyles) line->linestyle = 0;
+        line = line->next;
+    }
+
+    swf_Shape2ToShape(&s2,&s);
+
+    free(s2.fillstyles);
+    free(s2.linestyles);
+    free(s.fillstyle.data);
+    free(s.linestyle.data);
+    *destdata = s.data;
+    *destbitlen = s.bitlen;
+}
+
 void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*texture)
 {
     SRECT rect,r2;
@@ -813,11 +864,11 @@ void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*textu
 
     tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
-    ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
+    if(linewidth)
+        ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
     if(texture)
        fs1 = addFillStyle(s, &r2, texture);
-    else 
-       syntaxerror("non filled outlines not yet supported- please supply a fill=<color/texture> argument");
+    
     swf_SetU16(tag,id);
     rect.xmin = r2.xmin-linewidth-linewidth/2;
     rect.ymin = r2.ymin-linewidth-linewidth/2;
@@ -826,8 +877,11 @@ void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*textu
 
     swf_SetRect(tag,&rect);
     swf_SetShapeStyles(tag, s);
-    swf_SetShapeBits(tag, outline->shape); //does not count bits!
-    swf_SetBlock(tag, outline->shape->data, (outline->shape->bitlen+7)/8);
+    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_SetShapeBits(tag, s);
+    swf_SetBlock(tag, s->data, (s->bitlen+7)/8);
     swf_ShapeFree(s);
 
     s_addcharacter(name, id, tag, rect);
@@ -838,14 +892,15 @@ void s_circle(char*name, int r, RGBA color, int linewidth, char*texture)
 {
     SRECT rect,r2;
     SHAPE* s;
-    int ls1,fs1=0;
+    int ls1=0,fs1=0;
     r2.xmin = r2.ymin = 0;
     r2.xmax = 2*r;
     r2.ymax = 2*r;
 
     tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
     swf_ShapeNew(&s);
-    ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
+    if(linewidth)
+        ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
     if(texture)
        fs1 = addFillStyle(s, &r2, texture);
     swf_SetU16(tag,id);
@@ -924,6 +979,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;
@@ -1172,8 +1242,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);
@@ -1203,14 +1276,10 @@ void s_outline(char*name, char*format, char*source)
     draw_string(&draw, source);
     draw.finish(&draw);
     shape = swf_ShapeDrawerToShape(&draw);
-    //shape2 = swf_ShapeToShape2(shape);
-    //bounds = swf_GetShapeBoundingBox(shape2);
-    //swf_Shape2Free(shape2);
     bounds = swf_ShapeDrawerGetBBox(&draw);
     draw.dealloc(&draw);
     
-    outline = (outline_t*)malloc(sizeof(outline_t));
-    memset(outline, 0, sizeof(outline_t));
+    outline = (outline_t*)rfx_calloc(sizeof(outline_t));
     outline->shape = shape;
     outline->bbox = bounds;
     
@@ -1221,7 +1290,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;
@@ -1892,7 +1964,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;
@@ -2188,7 +2260,7 @@ static int c_frame(map_t*args)
     else {
        frame = parseInt(framestr);
        if(s_getframe() >= frame
-               && !(frame==0 && s_getframe()==frame)) // equality is o.k. for frame 0
+               && !(frame==1 && 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, name);
@@ -2290,6 +2362,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");
@@ -2513,6 +2593,7 @@ static struct {
  {"sound", c_sound, "name filename"},
  {"font", c_font, "name filename"},
  {"soundtrack", c_soundtrack, "filename"},
+ {"quicktime", c_quicktime, "url"},
 
     // generators of primitives
 
@@ -2540,7 +2621,7 @@ static struct {
  
     // 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"},