X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftools.c;h=1ed9e17083e96dc7191d8c9af21a39f710e9244b;hb=6f9968fe9231b75ffc067c8b27a05aaefca5bfb2;hp=1099bc3b4cf5e8826fda87e6442792e6761ba482;hpb=1baa73fc6c64b3a3f97ed3807321ca5a46a5a756;p=swftools.git diff --git a/lib/modules/swftools.c b/lib/modules/swftools.c index 1099bc3..1ed9e17 100644 --- a/lib/modules/swftools.c +++ b/lib/modules/swftools.c @@ -25,8 +25,7 @@ #define S64 long long SFIXED RFXSWF_SP(SFIXED a1,SFIXED a2,SFIXED b1,SFIXED b2) -{ S64 a; - a = ((S64)a1*(S64)b1+(S64)a2*(S64)b2)>>16; +{ 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"); @@ -99,6 +98,7 @@ U16 swf_GetDefineID(TAG * t) { case ST_DEFINESHAPE: case ST_DEFINESHAPE2: case ST_DEFINESHAPE3: + case ST_DEFINESHAPE4: case ST_DEFINEMORPHSHAPE: case ST_DEFINEEDITTEXT: case ST_DEFINEBITS: @@ -106,14 +106,18 @@ U16 swf_GetDefineID(TAG * t) case ST_DEFINEBITSJPEG3: case ST_DEFINEBITSLOSSLESS: case ST_DEFINEBITSLOSSLESS2: + case ST_DEFINESCALINGGRID: //pseudodefine case ST_DEFINEBUTTON: case ST_DEFINEBUTTON2: case ST_DEFINEBUTTONCXFORM: //pseudodefine case ST_DEFINEBUTTONSOUND: //pseudodefine + case ST_CSMTEXTSETTINGS: //pseudodefine case ST_DEFINEFONT: case ST_DEFINEFONT2: + case ST_DEFINEFONT3: case ST_DEFINEFONTINFO: //pseudodefine case ST_DEFINEFONTINFO2: //pseudodefine + case ST_DEFINEFONTALIGNZONES: //pseudodefine case ST_DEFINETEXT: case ST_DEFINETEXT2: case ST_DEFINESOUND: @@ -199,6 +203,12 @@ U16 swf_GetPlaceID(TAG * t) U16 d = swf_GetU16(t); id = (flags&PF_CHAR)?swf_GetU16(t):id; } break; + case ST_PLACEOBJECT3: + { U8 flags = swf_GetU8(t); + U8 flags2 = swf_GetU8(t); + U16 d = swf_GetU16(t); + id = (flags&PF_CHAR)?swf_GetU16(t):id; + } break; } @@ -211,9 +221,11 @@ static int swf_definingtagids[] = {ST_DEFINESHAPE, ST_DEFINESHAPE2, ST_DEFINESHAPE3, + ST_DEFINESHAPE4, ST_DEFINEMORPHSHAPE, ST_DEFINEFONT, ST_DEFINEFONT2, + ST_DEFINEFONT3, ST_DEFINETEXT, ST_DEFINETEXT2, ST_DEFINEEDITTEXT, @@ -236,8 +248,9 @@ static int swf_spritetagids[] = {ST_SHOWFRAME, ST_PLACEOBJECT, ST_PLACEOBJECT2, + ST_PLACEOBJECT3, ST_REMOVEOBJECT, - ST_REMOVEOBJECT2, //? + ST_REMOVEOBJECT2, ST_DOACTION, ST_STARTSOUND, ST_FRAMELABEL, @@ -248,12 +261,16 @@ static int swf_spritetagids[] = -1 }; +/* tags which add content or information to a character with a given ID */ static int swf_pseudodefiningtagids[] = { ST_DEFINEFONTINFO, ST_DEFINEFONTINFO2, + ST_DEFINEFONTALIGNZONES, ST_DEFINEBUTTONCXFORM, ST_DEFINEBUTTONSOUND, + ST_DEFINESCALINGGRID, + ST_CSMTEXTSETTINGS, ST_NAMECHARACTER, ST_DOINITACTION, ST_VIDEOFRAME, @@ -320,6 +337,11 @@ int swf_GetDepth(TAG * t) { U8 flags = swf_GetU8(t); depth = swf_GetU16(t); } break; + case ST_PLACEOBJECT3: + { U8 flags = swf_GetU8(t); + U8 flags2 = swf_GetU8(t); + depth = swf_GetU16(t); + } break; case ST_SETTABINDEX: { depth = swf_GetU16(t); @@ -363,8 +385,11 @@ char* swf_GetName(TAG * t) case ST_FRAMELABEL: name = &t->data[swf_GetTagPos(t)]; break; + case ST_PLACEOBJECT3: case ST_PLACEOBJECT2: { U8 flags = swf_GetU8(t); + if(t->id == ST_PLACEOBJECT3) + swf_GetU8(t); swf_GetU16(t); //depth; if(flags&PF_CHAR) swf_GetU16(t); //id @@ -374,7 +399,7 @@ char* swf_GetName(TAG * t) swf_GetCXForm(t, &c, 1); if(flags&PF_RATIO) swf_GetU16(t); - if(flags&PF_CLIPACTION) + if(flags&PF_CLIPDEPTH) swf_GetU16(t); if(flags&PF_NAME) { swf_ResetReadBits(t); @@ -402,50 +427,55 @@ void swf_GetMorphGradient(TAG * tag, GRADIENT * gradient1, GRADIENT * gradient2) for(t=0;tnum;t++) { int s=t; - if(s>=8) //FIXME - s=7; - gradient1->ratios[t] = swf_GetU8(tag); - swf_GetRGBA(tag, &gradient1->rgba[t]); - gradient2->ratios[t] = swf_GetU8(tag); - swf_GetRGBA(tag, &gradient2->rgba[t]); + if(s>=16) //FIXME + s=15; + gradient1->ratios[s] = swf_GetU8(tag); + swf_GetRGBA(tag, &gradient1->rgba[s]); + gradient2->ratios[s] = swf_GetU8(tag); + swf_GetRGBA(tag, &gradient2->rgba[s]); } } #define DEBUG_ENUMERATE if(0) +//#define DEBUG_ENUMERATE void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void*callback_data, int num, int morph) { U16 count; int t; count = swf_GetU8(tag); - if(count == 0xff && num>1) // defineshape2,3 only + if(count == 0xff && num>1) // defineshape2,3,4 only count = swf_GetU16(tag); + 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) + else if(type == 0x10 || type == 0x12 || type == 0x13) { swf_ResetReadBits(tag); - swf_GetMatrix(tag, NULL); + 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 + else { swf_GetGradient(tag, NULL, /*alpha*/ num>=3?1:0); + } } - else if(type == 0x40 || type == 0x41) + else if(type == 0x40 || type == 0x41 || type == 0x42 || type == 0x43) { swf_ResetReadBits(tag); // we made it. @@ -460,22 +490,26 @@ void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void swf_GetMatrix(tag, NULL); } else { - fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x\n",type); + fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x in tag %02x\n",type, tag->id); } } swf_ResetReadBits(tag); count = swf_GetU8(tag); // line style array if(count == 0xff) count = swf_GetU16(tag); + DEBUG_ENUMERATE printf("%d line styles\n", count); for(t=0;tpos + base, callback_data); //button id + swf_GetU16(tag); //id + while(swf_GetU8(tag)); //name + } + } break; + case ST_FREECHARACTER: /* unusual tags, which all start with an ID */ case ST_NAMECHARACTER: case ST_GENERATORTEXT: @@ -541,6 +589,12 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v break; callback(tag, 3 + base, callback_data); break; + case ST_PLACEOBJECT3: + // only if placeflaghascharacter + if(!(tag->data[0]&2)) + break; + callback(tag, 4 + base, callback_data); + break; case ST_REMOVEOBJECT: callback(tag, tag->pos + base, callback_data); break; @@ -629,44 +683,47 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v advancebits = swf_GetU8(tag); //advancebits while(1) { U16 flags; + int t; swf_ResetReadBits(tag); flags = swf_GetBits(tag, 8); if(!flags) break; - if(flags & 128) // text style record - { + + swf_ResetReadBits(tag); + if(flags & 8) { // hasfont + callback(tag, tag->pos + base, callback_data); + id = swf_GetU16(tag); + } + if(flags & 4) { // hascolor + if(num==1) swf_GetRGB(tag, NULL); + else swf_GetRGBA(tag, NULL); + } + if(flags & 2) { //has x offset swf_ResetReadBits(tag); - if(flags & 8) { // hasfont - callback(tag, tag->pos + base, callback_data); - id = swf_GetU16(tag); - } - if(flags & 4) { // hascolor - if(num==1) swf_GetRGB(tag, NULL); - else swf_GetRGBA(tag, NULL); - } - if(flags & 2) { //has x offset - swf_ResetReadBits(tag); - swf_GetU16(tag); - } - if(flags & 1) { //has y offset - swf_ResetReadBits(tag); - swf_GetU16(tag); - } - if(flags & 8) { //has height - swf_ResetReadBits(tag); - swf_GetU16(tag); - } - } else { // glyph record - int t; + swf_GetU16(tag); + } + if(flags & 1) { //has y offset swf_ResetReadBits(tag); - for(t=0;tpos + base, callback_data); break; + case ST_DEFINEMORPHSHAPE2: + case ST_DEFINESHAPE4: + num++; case ST_DEFINEMORPHSHAPE: case ST_DEFINESHAPE3: num++; //fallthrough @@ -690,21 +750,32 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v int id; int numshapes = 1; int morph = 0; - if(tag->id == ST_DEFINEMORPHSHAPE) { + if(tag->id == ST_DEFINEMORPHSHAPE || tag->id==ST_DEFINEMORPHSHAPE2) { numshapes = 2; morph = 1; } id = swf_GetU16(tag); // id; - swf_GetRect(tag, NULL); // bounds + SRECT r; + swf_GetRect(tag, &r); // shape bounds if(morph) { swf_ResetReadBits(tag); - swf_GetRect(tag, NULL); // bounds2 + swf_GetRect(tag, NULL); // shape bounds2 + if(num>=4) + swf_GetRect(tag, NULL); // edge bounds1 + } + if(num>=4) { + swf_GetRect(tag, NULL); // edge bounds + swf_GetU8(tag); // flags, &1: contains scaling stroke, &2: contains non-scaling stroke + } + if(morph) { swf_GetU32(tag); //offset to endedges } DEBUG_ENUMERATE printf("Tag:%d Name:%s ID:%d\n", tag->id, swf_TagGetName(tag), id); + DEBUG_ENUMERATE printf("BBox %.2f %.2f %.2f %.2f\n", r.xmin/20.0,r.ymin/20.0,r.xmax/20.0,r.ymax/20.0); + DEBUG_ENUMERATE printf("style tag pos: %d\n", tag->pos); enumerateUsedIDs_styles(tag, callback, callback_data, num, morph); DEBUG_ENUMERATE printf("-------\n"); while(--numshapes>=0) /* morph shapes define two shapes */ @@ -712,7 +783,7 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v DEBUG_ENUMERATE printf("shape:%d\n", numshapes); fillbits = swf_GetBits(tag, 4); linebits = swf_GetBits(tag, 4); - DEBUG_ENUMERATE printf("%d %d\n", fillbits, linebits); + DEBUG_ENUMERATE printf("fillbits=%d linebits=%d\n", fillbits, linebits); swf_ResetReadBits(tag); while(1) { int flags; @@ -868,6 +939,36 @@ void swf_Relocate (SWF*swf, char*bitmap) } } +/* untested */ +void swf_Relocate2(SWF*swf, int*id2id) +{ + TAG*tag; + tag = swf->firstTag; + while(tag) { + if(swf_isDefiningTag(tag)) { + int id = swf_GetDefineID(tag); + id = id2id[id]; + if(id>=0) { + swf_SetDefineID(tag, id); + } + } + int num = swf_GetNumUsedIDs(tag); + if(num) { + int *ptr; + int t; + ptr = rfx_alloc(sizeof(int)*num); + swf_GetUsedIDs(tag, ptr); + for(t=0;tdata[ptr[t]]); + id = id2id[id]; + if(id>=0) { + PUT16(&tag->data[ptr[t]], id); + } + } + } + } +} + void swf_RelocateDepth(SWF*swf, char*bitmap) { TAG*tag; @@ -883,10 +984,27 @@ void swf_RelocateDepth(SWF*swf, char*bitmap) while(tag) { + int depth; /* TODO * clip depths * sprites */ - int depth = swf_GetDepth(tag); + if(tag->id == ST_PLACEOBJECT2) { + SWFPLACEOBJECT obj; + swf_GetPlaceObject(tag, &obj); + if(obj.clipdepth) { + int newdepth = obj.clipdepth+nr; + if(newdepth>65535) { + fprintf(stderr, "Couldn't relocate depths: too large values\n"); + newdepth = 65535; + } + obj.clipdepth = newdepth; + swf_ResetTag(tag, ST_PLACEOBJECT2); + swf_SetPlaceObject(tag, &obj); + } + swf_PlaceObjectFree(&obj); + } + + depth = swf_GetDepth(tag); if(depth>=0) { int newdepth = depth+nr; if(newdepth>65535) { @@ -903,7 +1021,8 @@ U8 swf_isShapeTag(TAG*tag) { if(tag->id == ST_DEFINESHAPE || tag->id == ST_DEFINESHAPE2 || - tag->id == ST_DEFINESHAPE3) + tag->id == ST_DEFINESHAPE3 || + tag->id == ST_DEFINESHAPE4) return 1; return 0; } @@ -911,7 +1030,8 @@ U8 swf_isShapeTag(TAG*tag) U8 swf_isPlaceTag(TAG*tag) { if(tag->id == ST_PLACEOBJECT || - tag->id == ST_PLACEOBJECT2) + tag->id == ST_PLACEOBJECT2 || + tag->id == ST_PLACEOBJECT3) return 1; return 0; } @@ -1029,8 +1149,6 @@ void swf_Optimize(SWF*swf) } tag = swf->firstTag; while(tag) { - int doremap=1; - TAG*next = tag->next; /* remap the tag */ @@ -1044,7 +1162,6 @@ void swf_Optimize(SWF*swf) PUT16(&tag->data[positions[t]], id); } rfx_free(positions); - tag = tag->next; /* now look for previous tags with the same content */ @@ -1055,22 +1172,11 @@ void swf_Optimize(SWF*swf) int match=0; if(!dontremap[id]) while((tag2 = hashmap[hash%hash_size])) { - if(tag2 != (TAG*)(-1) && tag->len == tag2->len) { - int t; - /* start at pos 2, as 0 and 1 are the id */ - for(t=2;tlen;t++) { - if(tag->data[t] != tag2->data[t]) - break; - } - if(t == tag->len) { - match=1; - } - } - if(match) { - /* we found two identical tags- remap one - of them */ - remap[id] = swf_GetDefineID(tag2); - break; + if(tag2 != (TAG*)0 && tag->len == tag2->len) { + if(memcmp(&tag->data[2],&tag2->data[2],tag->len-2) == 0) { + match = 1; + break; + } } hash++; } @@ -1078,10 +1184,12 @@ void swf_Optimize(SWF*swf) while(hashmap[hash%hash_size]) hash++; hashmap[hash%hash_size] = tag; } else { + /* we found two identical tags- remap one + of them */ + remap[id] = swf_GetDefineID(tag2); swf_DeleteTag(tag); if(tag == swf->firstTag) swf->firstTag = next; - doremap = 0; } } else if(swf_isPseudoDefiningTag(tag)) { int id = swf_GetDefineID(tag); @@ -1092,12 +1200,12 @@ void swf_Optimize(SWF*swf) swf_DeleteTag(tag); if(tag == swf->firstTag) swf->firstTag = next; - doremap = 0; } } tag = next; } + rfx_free(dontremap); rfx_free(remap); rfx_free(id2tag);