added -b option docs to --help
[swftools.git] / src / swfdump.c
index 95b06f6..c01a2b3 100644 (file)
@@ -53,8 +53,10 @@ static int action = 0;
 static int html = 0;
 static int xy = 0;
 static int showtext = 0;
+static int showshapes = 0;
 static int hex = 0;
 static int used = 0;
+static int bbox = 0;
 
 static struct options_t options[] = {
 {"h", "help"},
@@ -63,7 +65,9 @@ static struct options_t options[] = {
 {"e", "html"},
 {"a", "action"},
 {"t", "text"},
+{"s", "shapes"},
 {"p", "placements"},
+{"b", "bbox"},
 {"X", "width"},
 {"Y", "height"},
 {"r", "rate"},
@@ -91,6 +95,10 @@ int args_callback_option(char*name,char*val)
         showtext = 1;
         return 0;
     }
+    else if(name[0]=='s') {
+        showshapes = 1;
+        return 0;
+    }
     else if(name[0]=='e') {
         html = 1;
         return 0;
@@ -119,8 +127,12 @@ int args_callback_option(char*name,char*val)
        used = 1;
        return 0;
     }
+    else if(name[0]=='b') {
+       bbox = 1;
+       return 0;
+    }
     else if(name[0]=='D') {
-       action = placements = showtext = 1;
+       action = placements = showtext = showshapes = 1;
        return 0;
     }
     else {
@@ -145,7 +157,9 @@ void args_callback_usage(char *name)
     printf("-e , --html                    Print out html code for embedding the file\n");
     printf("-a , --action                  Disassemble action tags\n");
     printf("-t , --text                    Show text fields (like swfstrings).\n");
+    printf("-s , --shapes                  Show shape coordinates/styles\n");
     printf("-p , --placements              Show placement information\n");
+    printf("-b , --bbox                    Print tag's bounding boxes\n");
     printf("-X , --width                   Prints out a string of the form \"-X width\".\n");
     printf("-Y , --height                  Prints out a string of the form \"-Y height\".\n");
     printf("-r , --rate                    Prints out a string of the form \"-r rate\".\n");
@@ -226,31 +240,14 @@ void dumpButtonActions(TAG*tag, char*prefix)
     swf_DumpActions(actions, prefix);
 }
 
-#define ET_HASTEXT 32768
-#define ET_WORDWRAP 16384
-#define ET_MULTILINE 8192
-#define ET_PASSWORD 4096
-#define ET_READONLY 2048
-#define ET_HASTEXTCOLOR 1024
-#define ET_HASMAXLENGTH 512
-#define ET_HASFONT 256
-#define ET_X3 128
-#define ET_X2 64
-#define ET_HASLAYOUT 32
-#define ET_NOSELECT 16
-#define ET_BORDER 8
-#define ET_X1 4
-#define ET_X0 2
-#define ET_USEOUTLINES 1
-
 SWF swf;
 int fontnum = 0;
 SWFFONT**fonts;
 
-void textcallback(int*glyphs, int nr, int fontid) 
+void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color) 
 {
     int font=-1,t;
-    printf("                <%2d glyphs in font %2d> ",nr, fontid);
+    printf("                <%2d glyphs in font %2d, color #%02x%02x%02x%02x> ",nr, fontid, color->r, color->g, color->b, color->a);
     for(t=0;t<fontnum;t++)
     {
        if(fonts[t]->id == fontid) {
@@ -265,9 +262,9 @@ void textcallback(int*glyphs, int nr, int fontid)
        if(font>=0) {
            if(glyphs[t] >= fonts[font]->numchars  /*glyph is in range*/
                    || !fonts[font]->glyph2ascii /* font has ascii<->glyph mapping */
-             )
-               continue;
-           a = fonts[font]->glyph2ascii[glyphs[t]];
+             ) a = glyphs[t];
+           else
+               a = fonts[font]->glyph2ascii[glyphs[t]];
        } else {
            a = glyphs[t];
        }
@@ -282,7 +279,7 @@ void textcallback(int*glyphs, int nr, int fontid)
 void handleText(TAG*tag) 
 {
   printf("\n");
-  swf_FontExtract_DefineTextCallback(-1,0,tag,4, textcallback);
+  swf_ParseDefineText(tag,textcallback, 0);
 }
            
 void handleDefineSound(TAG*tag)
@@ -332,7 +329,9 @@ void handleEditText(TAG*tag)
     int t;
     id = swf_GetU16(tag);
     swf_GetRect(tag,0);
+    
     //swf_ResetReadBits(tag);
+
     if (tag->readBit)  
     { tag->pos++; 
       tag->readBit = 0; 
@@ -358,20 +357,20 @@ void handleEditText(TAG*tag)
        swf_GetU16(tag); //indent
        swf_GetU16(tag); //leading
     }
-    printf(" variable \"%s\"", &tag->data[tag->pos]);
+    printf(" variable \"%s\" ", &tag->data[tag->pos]);
+    if(flags & ET_HTML) printf("(html)");
+    if(flags & ET_NOSELECT) printf("(noselect)");
+    if(flags & ET_PASSWORD) printf("(password)");
+    if(flags & ET_READONLY) printf("(readonly)");
 
-    if(flags & (ET_X1 | ET_X2 | ET_X3 | ET_X0))
+    if(flags & (ET_X1 | ET_X3 ))
     {
-       printf(" undefined flags: %d%d%d%d", 
-               (flags&ET_X0?1:0),
-               (flags&ET_X1?1:0),
-               (flags&ET_X2?1:0),
-               (flags&ET_X3?1:0));
+       printf(" undefined flags: %08x (%08x)", (flags&(ET_X1|ET_X3)), flags);
     }
     
     while(tag->data[tag->pos++]);
     if(flags & ET_HASTEXT)
-   //  printf(" text \"%s\"\n", &tag->data[tag->pos])
+   //  printf(" text \"%s\"\n", &tag->data[tag->pos]) //TODO
        ;
 }
 void printhandlerflags(U32 handlerflags) 
@@ -551,14 +550,108 @@ void handlePlaceObject2(TAG*tag, char*prefix)
 
 void handlePlaceObject(TAG*tag, char*prefix)
 {
-    /*TODO*/
+    TAG*tag2 = swf_InsertTag(0, ST_PLACEOBJECT2);
+
+    U16 id = swf_GetU16(tag);
+    U16 depth = swf_GetU16(tag);
+    MATRIX matrix; 
+    CXFORM cxform;
+    swf_GetMatrix(tag, &matrix);
+    swf_GetCXForm(tag, &cxform, 0);
+
+    swf_SetU8(tag2, 14);
+    swf_SetU16(tag2, depth);
+    swf_SetMatrix(tag2, &matrix);
+    swf_SetCXForm(tag2, &cxform, 1);
+
+    handlePlaceObject2(tag2, prefix);
+}
+char stylebuf[256];
+char* fillstyle2str(FILLSTYLE*style)
+{
+    switch(style->type) {
+       case 0x00:
+           sprintf(stylebuf, "SOLID %02x%02x%02x%02x", style->color.r, style->color.g, style->color.b, style->color.a);
+           break;
+       case 0x10: case 0x12:
+           sprintf(stylebuf, "GRADIENT (%d steps)", style->gradient.num);
+           break;
+       case 0x40: case 0x41:
+           /* TODO: display information about that bitmap */
+           sprintf(stylebuf, "BITMAP %d", style->id_bitmap);
+           break;
+       default:
+           sprintf(stylebuf, "UNKNOWN[%02x]",style->type);
+    }
+    return stylebuf;
+}
+char* linestyle2str(LINESTYLE*style)
+{
+    sprintf(stylebuf, "%.2f %02x%02x%02x%02x", style->width/20.0, style->color.r, style->color.g, style->color.b, style->color.a);
+    return stylebuf;
+}
+
+void handleShape(TAG*tag, char*prefix)
+{
+    SHAPE2 shape;
+    SHAPELINE*line;
+    int t,max;
+
+    tag->pos = 0;
+    tag->readBit = 0;
+    swf_ParseDefineShape(tag, &shape);
+
+    max = shape.numlinestyles > shape.numfillstyles?shape.numlinestyles:shape.numfillstyles;
+
+    if(max) printf("%s | fillstyles(%02d)        linestyles(%02d)\n", 
+           prefix,
+           shape.numfillstyles,
+           shape.numlinestyles
+           );
+    else    printf("%s | (Neither line nor fill styles)\n", prefix);
+
+    for(t=0;t<max;t++) {
+       printf("%s", prefix);
+       if(t < shape.numfillstyles) {
+           printf(" | %-2d) %-18.18s", t+1, fillstyle2str(&shape.fillstyles[t]));
+       } else {
+           printf("                         ");
+       }
+       if(t < shape.numlinestyles) {
+           printf("%-2d) %s", t+1, linestyle2str(&shape.linestyles[t]));
+       }
+       printf("\n");
+    }
+
+    printf("%s |\n", prefix);
+
+    line = shape.lines;
+    while(line) {
+       printf("%s | fill: %02d/%02d line:%02d - ",
+               prefix, 
+               line->fillstyle0,
+               line->fillstyle1,
+               line->linestyle);
+       if(line->type == moveTo) {
+           printf("moveTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
+       } else if(line->type == lineTo) {
+           printf("lineTo %.2f %.2f\n", line->x/20.0, line->y/20.0);
+       } else if(line->type == splineTo) {
+           printf("splineTo (%.2f %.2f) %.2f %.2f\n", 
+                   line->sx/20.0, line->sy/20.0,
+                   line->x/20.0, line->y/20.0
+                   );
+       }
+       line = line->next;
+    }
+    printf("%s |\n", prefix);
 }
     
-void fontcallback1(U16 id,U8 * name)
+void fontcallback1(void*self, U16 id,U8 * name)
 { fontnum++;
 }
 
-void fontcallback2(U16 id,U8 * name)
+void fontcallback2(void*self, U16 id,U8 * name)
 { 
   swf_FontExtract(&swf,id,&fonts[fontnum]);
   fontnum++;
@@ -579,9 +672,9 @@ void hexdumpTag(TAG*tag, char* prefix)
        ascii[t&15] = printable(tag->data[t]);
        if((t && ((t&15)==15)) || (t==tag->len-1))
        {
-           int s,p=((t-1)&15)+1;
+           int s,p=((t)&15)+1;
            ascii[p] = 0;
-           for(s=p;s<16;s++) {
+           for(s=p-1;s<16;s++) {
                printf("   ");
            }
            if(t==tag->len-1)
@@ -718,9 +811,9 @@ int main (int argc,char ** argv)
     if(html)
     {
        char*fileversions[] = {"","1,0,0,0", "2,0,0,0","3,0,0,0","4,0,0,0",
-                              "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0"};
-       if(swf.fileVersion>8) {
-           fprintf(stderr, "Fileversion>8\n");
+                              "5,0,0,0","6,0,23,0","7,0,0,0","8,0,0,0","9,0,0,0"};
+       if(swf.fileVersion>9) {
+           fprintf(stderr, "Fileversion>9\n");
            exit(1);
        }
        printf("<OBJECT CLASSID=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n"
@@ -768,10 +861,10 @@ int main (int argc,char ** argv)
    
     if(showtext) {
        fontnum = 0;
-       swf_FontEnumerate(&swf,&fontcallback1);
+       swf_FontEnumerate(&swf,&fontcallback1, 0);
        fonts = (SWFFONT**)malloc(fontnum*sizeof(SWFFONT*));
        fontnum = 0;
-       swf_FontEnumerate(&swf,&fontcallback2);
+       swf_FontEnumerate(&swf,&fontcallback2, 0);
     }
 
     while(tag) {
@@ -810,7 +903,6 @@ int main (int argc,char ** argv)
             printf(" places id %04d at depth %04x", swf_GetPlaceID(tag), swf_GetDepth(tag));
             if(swf_GetName(tag))
                 printf(" name \"%s\"",swf_GetName(tag));
-           handlePlaceObject(tag, myprefix);
         }
        else if(tag->id == ST_PLACEOBJECT2) {
            if(tag->data[0]&1)
@@ -884,9 +976,9 @@ int main (int argc,char ** argv)
                }
            }
            if(nframe == frame)
-               printf(" %d (%s)", frame, timestring(frame*(256.0/(swf.frameRate+0.1))));
+               printf(" %d (%s)", frame+1, timestring(frame*(256.0/(swf.frameRate+0.1))));
            else
-               printf(" %d-%d (%s-%s)", frame, nframe,
+               printf(" %d-%d (%s-%s)", frame+1, nframe+1,
                        timestring(frame*(256.0/(swf.frameRate+0.1))),
                        timestring(nframe*(256.0/(swf.frameRate+0.1)))
                        );
@@ -905,6 +997,8 @@ int main (int argc,char ** argv)
        else if(tag->id == ST_PROTECT) {
            if(tag->len>0) {
                printf(" %s\n", swf_GetString(tag));
+           } else {
+               printf("\n");
            }
        }
        else if(tag->id == ST_DEFINEBITSLOSSLESS ||
@@ -948,6 +1042,15 @@ int main (int argc,char ** argv)
        else {
            printf("\n");
        }
+
+       if(bbox && swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) {
+           SRECT r = swf_GetDefineBBox(tag);
+           printf("                %s bbox [%.2f, %.2f, %.2f, %.2f]\n", prefix,
+                   r.xmin/20.0,
+                   r.ymin/20.0,
+                   r.xmax/20.0,
+                   r.ymax/20.0);
+       }
         
         sprintf(myprefix, "                %s", prefix);
 
@@ -975,15 +1078,30 @@ int main (int argc,char ** argv)
             actions = swf_ActionGet(tag);
             swf_DumpActions(actions, myprefix);
         }
+        else if(tag->id == ST_DOINITACTION && action) {
+            ActionTAG*actions;
+            swf_GetU16(tag); // id
+            actions = swf_ActionGet(tag);
+            swf_DumpActions(actions, myprefix);
+        }
        else if(tag->id == ST_DEFINEBUTTON && action) {
            dumpButtonActions(tag, myprefix);
        }
        else if(tag->id == ST_DEFINEBUTTON2 && action) {
            dumpButton2Actions(tag, myprefix);
        }
+       else if(tag->id == ST_PLACEOBJECT) {
+           handlePlaceObject(tag, myprefix);
+       }
        else if(tag->id == ST_PLACEOBJECT2) {
            handlePlaceObject2(tag, myprefix);
        }
+       else if(tag->id == ST_DEFINESHAPE ||
+               tag->id == ST_DEFINESHAPE2 ||
+               tag->id == ST_DEFINESHAPE3) {
+           if(showshapes)
+               handleShape(tag, myprefix);
+       }
 
        if(tag->len && used) {
            int num = swf_GetNumUsedIDs(tag);
@@ -994,8 +1112,13 @@ int main (int argc,char ** argv)
                swf_GetUsedIDs(tag, used);
                printf("%s%suses IDs: ", indent, prefix);
                for(t=0;t<num;t++) {
+                   int id;
                    swf_SetTagPos(tag, used[t]);
-                   printf("%d%s", swf_GetU16(tag), t<num-1?", ":"");
+                   id = swf_GetU16(tag);
+                   printf("%d%s", id, t<num-1?", ":"");
+                   if(!idtab[id]) {
+                       dumperror("Id %04d is not yet defined.\n", id);
+                   }
                }
                printf("\n");
            }