X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fmodules%2Fswftools.c;h=1dc66d89fd6e7dca20a76ca669c1f3414be0a76d;hp=8ee200115198c90322db65d6fa32e9eafbe63e5e;hb=faa7df4336cea6ae258ac4f83ae09e0227ca844d;hpb=fac8829512fe1eed7124f90c06b51ac3c9b4e18a diff --git a/lib/modules/swftools.c b/lib/modules/swftools.c index 8ee2001..1dc66d8 100644 --- a/lib/modules/swftools.c +++ b/lib/modules/swftools.c @@ -23,12 +23,14 @@ // Matrix & Math tools for SWF files +#include "../rfxswf.h" + #define S64 long long SFIXED RFXSWF_SP(SFIXED a1,SFIXED a2,SFIXED b1,SFIXED b2) { S64 a = ((S64)a1*(S64)b1+(S64)a2*(S64)b2)>>16; SFIXED result = (SFIXED)(a); if(a!=result) - fprintf(stderr, "Warning: overflow in matrix multiplication"); + fprintf(stderr, "Warning: overflow in matrix multiplication\n"); return result; } SFIXED RFXSWF_QFIX(int zaehler,int nenner) // bildet Quotient von zwei INTs in SFIXED @@ -121,6 +123,7 @@ U16 swf_GetDefineID(TAG * t) case ST_DEFINEFONTALIGNZONES: //pseudodefine case ST_DEFINEFONTNAME: //pseudodefine case ST_DEFINETEXT: + case ST_DEFINEBINARY: case ST_DEFINETEXT2: case ST_DEFINESOUND: case ST_DEFINESPRITE: @@ -461,6 +464,92 @@ void swf_GetMorphGradient(TAG * tag, GRADIENT * gradient1, GRADIENT * gradient2) #define DEBUG_ENUMERATE if(0) //#define DEBUG_ENUMERATE +void enumerateUsedIDs_fillstyle(TAG * tag, int t, void (*callback)(TAG*, int, void*), void*callback_data, int num, int morph) +{ + int type; + type = swf_GetU8(tag); //type + DEBUG_ENUMERATE printf("fill style %d) type=%02x (tagpos=%d)\n", t, type, tag->pos); + if(type == 0) { + RGBA color; + if(num >= 3) + {swf_GetRGBA(tag, &color);if(morph) swf_GetRGBA(tag, NULL);} + else + {swf_GetRGB(tag, &color);if(morph) swf_GetRGB(tag, NULL);} + DEBUG_ENUMERATE printf(" %02x%02x%02x%02x\n", color.r,color.g,color.b,color.a); + } + else if(type == 0x10 || type == 0x12 || type == 0x13) + { + swf_ResetReadBits(tag); + MATRIX m; + swf_GetMatrix(tag, &m); + DEBUG_ENUMERATE swf_DumpMatrix(stdout, &m); + if(morph) { + swf_GetMatrix(tag, &m); + DEBUG_ENUMERATE swf_DumpMatrix(stdout, &m); + } + swf_ResetReadBits(tag); + if(morph) { + swf_GetMorphGradient(tag, NULL, NULL); + if(type == 0x13) { + swf_GetU16(tag); + swf_GetU16(tag); + } + } else { + GRADIENT g; + swf_GetGradient(tag, &g, /*alpha*/ num>=3?1:0); + DEBUG_ENUMERATE swf_DumpGradient(stdout, &g); + if(type == 0x13) + swf_GetU16(tag); + } + } + else if(type == 0x40 || type == 0x41 || type == 0x42 || type == 0x43) + { + swf_ResetReadBits(tag); + if(tag->data[tag->pos] != 0xff || + tag->data[tag->pos+1] != 0xff) + (callback)(tag, tag->pos, callback_data); + + swf_GetU16(tag); + swf_ResetReadBits(tag); + swf_GetMatrix(tag, NULL); + if(morph) + swf_GetMatrix(tag, NULL); + } + else { + fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x in tag %02d\n",type, tag->id); + } +} + +void enumerateUsedIDs_linestyle(TAG * tag, int t, void (*callback)(TAG*, int, void*), void*callback_data, int num, int morph) +{ + U16 width; + RGBA color; + width = swf_GetU16(tag); + char fill=0; + if(morph) + swf_GetU16(tag); + if(num >= 4) { + U16 flags = swf_GetU16(tag); + DEBUG_ENUMERATE printf("line style %d) flags: %08x\n", t, flags); + if((flags & 0x30) == 0x20) { + U16 miter = swf_GetU16(tag); // miter limit + DEBUG_ENUMERATE printf("line style %d) miter join: %08x\n", t, miter); + } + if(flags & 0x08) { + fill = 1; + } + } + if(!fill) { + if(num >= 3) + {swf_GetRGBA(tag, &color);if(morph) swf_GetRGBA(tag, NULL);} + else + {swf_GetRGB(tag, &color);if(morph) swf_GetRGB(tag, NULL);} + } else { + enumerateUsedIDs_fillstyle(tag, t, callback, callback_data, num, morph); + } + DEBUG_ENUMERATE printf("line style %d) width=%.2f color=%02x%02x%02x%02x \n", t, width/20.0, color.r,color.g,color.b,color.a); +} + void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void*callback_data, int num, int morph) { U16 count; @@ -472,50 +561,7 @@ void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void DEBUG_ENUMERATE printf("%d fill styles\n", count); for(t=0;tpos); - if(type == 0) { - if(num >= 3) - {swf_GetRGBA(tag, NULL);if(morph) swf_GetRGBA(tag, NULL);} - else - {swf_GetRGB(tag, NULL);if(morph) swf_GetRGB(tag, NULL);} - } - else if(type == 0x10 || type == 0x12 || type == 0x13) - { - swf_ResetReadBits(tag); - MATRIX m; - swf_GetMatrix(tag, &m); - DEBUG_ENUMERATE swf_DumpMatrix(stdout, &m); - if(morph) - swf_GetMatrix(tag, NULL); - swf_ResetReadBits(tag); - if(morph) - swf_GetMorphGradient(tag, NULL, NULL); - else { - GRADIENT g; - swf_GetGradient(tag, &g, /*alpha*/ num>=3?1:0); - DEBUG_ENUMERATE swf_DumpGradient(stdout, &g); - if(type == 0x13) - swf_GetU16(tag); - } - } - else if(type == 0x40 || type == 0x41 || type == 0x42 || type == 0x43) - { - swf_ResetReadBits(tag); - if(tag->data[tag->pos] != 0xff || - tag->data[tag->pos+1] != 0xff) - (callback)(tag, tag->pos, callback_data); - - swf_GetU16(tag); - swf_ResetReadBits(tag); - swf_GetMatrix(tag, NULL); - if(morph) - swf_GetMatrix(tag, NULL); - } - else { - fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x in tag %02x\n",type, tag->id); - } + enumerateUsedIDs_fillstyle(tag, t, callback, callback_data, num, morph); } swf_ResetReadBits(tag); count = swf_GetU8(tag); // line style array @@ -524,24 +570,7 @@ void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void DEBUG_ENUMERATE printf("%d line styles\n", count); for(t=0;t= 4) { - U16 flags = swf_GetU16(tag); - if(flags & 0x2000) - swf_GetU16(tag); // miter limit - if(flags & 0x0800) { - fprintf(stderr, "Filled strokes parsing not yet supported\n"); - } - } - if(num >= 3) - {swf_GetRGBA(tag, &color);if(morph) swf_GetRGBA(tag, NULL);} - else - {swf_GetRGB(tag, &color);if(morph) swf_GetRGB(tag, NULL);} - DEBUG_ENUMERATE printf("line style %d: %02x%02x%02x%02x \n", t, color.r,color.g,color.b,color.a); + enumerateUsedIDs_linestyle(tag, t, callback, callback_data, num, morph); } } @@ -583,6 +612,7 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v callback(tag, tag->pos + base, callback_data); //button id break; + case ST_SYMBOLCLASS: case ST_EXPORTASSETS: { int num = swf_GetU16(tag); int t; @@ -607,9 +637,12 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v } } break; + case ST_DOABC: + case ST_RAWABC: + break; + case ST_FREECHARACTER: /* unusual tags, which all start with an ID */ case ST_NAMECHARACTER: - case ST_DEFINEBINARY: case ST_DEFINEFONTNAME: case ST_GENERATORTEXT: callback(tag, tag->pos + base, callback_data); @@ -658,7 +691,7 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v /* I never saw recursive sprites, but they are (theoretically) possible, so better add base here again */ enumerateUsedIDs(tag2, tag->pos + base, callback, callback_data); - swf_DeleteTag(tag2); + swf_DeleteTag(0, tag2); swf_GetBlock(tag, NULL, len); } } @@ -676,7 +709,8 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v } while(1) { - if(!swf_GetU8(tag)) //flags + U8 flags = swf_GetU8(tag); + if(!flags) //flags break; callback(tag, tag->pos + base, callback_data); swf_GetU16(tag); //char @@ -687,6 +721,16 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v swf_ResetReadBits(tag); swf_GetCXForm(tag, NULL, 1); } + if(flags&0x10) { + U8 num = swf_GetU8(tag); + int t; + for(t=0;tfirstTag; + char ok = 1; + + int current_id=0; +#define NEW_ID(n) \ + for(current_id++;current_id<65536;current_id++) { \ + if(!bitmap[current_id]) { \ + n = current_id; \ + break; \ + } \ + } \ + if(current_id==65536) { \ + fprintf(stderr, "swf_Relocate: Couldn't relocate: Out of IDs\n"); \ + return 0; \ + } + while(tag) { int num; int *ptr; - int t; if(swf_isDefiningTag(tag)) { @@ -940,18 +1001,12 @@ void swf_Relocate (SWF*swf, char*bitmap) if(!bitmap[id]) { //free newid = id; + } else if(slaveids[id]>0) { + newid = slaveids[id]; + } else { + NEW_ID(newid); } - else { - newid = 0; - for (t=1;t<65536;t++) - { - if(!bitmap[t]) - { - newid = t; - break; - } - } - } + bitmap[newid] = 1; slaveids[id] = newid; @@ -962,20 +1017,43 @@ void swf_Relocate (SWF*swf, char*bitmap) if(num) { ptr = (int*)rfx_alloc(sizeof(int)*num); swf_GetUsedIDs(tag, ptr); - + int t; for(t=0;tdata[ptr[t]]); if(slaveids[id]<0) { - fprintf(stderr, "swf_Relocate: Mapping id (%d) never encountered before in %s\n", id, - swf_TagGetName(tag)); + if(!id && bitmap[id]) { + /* id 0 is only used in SWF versions >=9. It's the ID of + the main timeline. It's used in e.g. SYMBOLTAG tags, but + never defined, so if we're asked to reallocate it, we have + to allocate an ID for it on the fly. */ + int newid; + NEW_ID(newid); + bitmap[newid] = 1; + slaveids[id] = newid; + id = newid; + } else if(!bitmap[id]) { + /* well- we don't know this id, but it's not reserved anyway, so just + leave it alone */ + } else { + /* this actually happens with files created with Flash CS4 and never. + Apparently e.g. DefineButton tags are able to use forward declarations of objects. */ + fprintf(stderr, "warning: Mapping id (%d) never encountered before in %s\n", id, + swf_TagGetName(tag)); + int newid; + NEW_ID(newid); + id = slaveids[id] = newid; + ok = 0; + } } else { id = slaveids[id]; - PUT16(&tag->data[ptr[t]], id); } + PUT16(&tag->data[ptr[t]], id); } + free(ptr); } tag=tag->next; } + return ok; } /* untested */ @@ -1004,6 +1082,7 @@ void swf_Relocate2(SWF*swf, int*id2id) PUT16(&tag->data[ptr[t]], id); } } + free(ptr); } } } @@ -1086,6 +1165,7 @@ U8 swf_isFontTag(TAG*tag) { if(tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2 || + tag->id == ST_DEFINEFONT3 || tag->id == ST_DEFINEFONTINFO) return 1; return 0; @@ -1226,9 +1306,7 @@ void swf_Optimize(SWF*swf) /* we found two identical tags- remap one of them */ remap[id] = swf_GetDefineID(tag2); - swf_DeleteTag(tag); - if(tag == swf->firstTag) - swf->firstTag = next; + swf_DeleteTag(swf, tag); } } else if(swf_isPseudoDefiningTag(tag)) { int id = swf_GetDefineID(tag); @@ -1236,9 +1314,7 @@ void swf_Optimize(SWF*swf) /* if this tag was remapped, we don't need the helper tag anymore. Discard it. */ - swf_DeleteTag(tag); - if(tag == swf->firstTag) - swf->firstTag = next; + swf_DeleteTag(swf, tag); } }