X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftools.c;h=d6e93def09b03659369bbb66216deec6779f965f;hb=1b92dcdf739c6b827ac037ce74a9d9df0fc857a8;hp=4117fc3d8a9b02e54443959dc1613429b75cc691;hpb=0ee8530d9e3fc453e1f97fa2623f5db344622a40;p=swftools.git diff --git a/lib/modules/swftools.c b/lib/modules/swftools.c index 4117fc3..d6e93de 100644 --- a/lib/modules/swftools.c +++ b/lib/modules/swftools.c @@ -7,9 +7,19 @@ Copyright (c) 2000, 2001 Rainer Böhme - This file is distributed under the GPL, see file COPYING for details + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -*/ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Matrix & Math tools for SWF files @@ -65,6 +75,14 @@ MATRIX * swf_MatrixMapTriangle(MATRIX * m,int dx,int dy,int x0,int y0, return m; } +void swf_SetDefineID(TAG * tag, U16 newid) +{ + int oldlen = tag->len; + tag->len = 0; + swf_SetU16(tag, newid); /* set defining ID */ + tag->len = oldlen; +} + U16 swf_GetDefineID(TAG * t) // up to SWF 4.0 { U32 oldTagPos; @@ -91,10 +109,14 @@ U16 swf_GetDefineID(TAG * t) case ST_DEFINEFONT: case ST_DEFINEFONT2: case ST_DEFINEFONTINFO: //pseudodefine + case ST_DEFINEFONTINFO2: //pseudodefine case ST_DEFINETEXT: case ST_DEFINETEXT2: case ST_DEFINESOUND: case ST_DEFINESPRITE: + case ST_DEFINEMOVIE: + case ST_DEFINEVIDEOSTREAM: + case ST_VIDEOFRAME: //pseudodefine case ST_NAMECHARACTER: //pseudodefine id = swf_GetU16(t); break; @@ -105,6 +127,50 @@ U16 swf_GetDefineID(TAG * t) return id; } +SRECT swf_GetDefineBBox(TAG * t) +{ + U32 oldTagPos; + U16 id = 0; + SRECT b1,b2; + + oldTagPos = swf_GetTagPos(t); + swf_SetTagPos(t,0); + + swf_GetRect(0, &b1); + + switch (swf_GetTagID(t)) + { case ST_DEFINESHAPE: + case ST_DEFINESHAPE2: + case ST_DEFINESHAPE3: + case ST_DEFINEEDITTEXT: + case ST_DEFINEBUTTON: + case ST_DEFINEBUTTON2: + case ST_DEFINETEXT: + case ST_DEFINETEXT2: + case ST_DEFINEVIDEOSTREAM: + id = swf_GetU16(t); + swf_GetRect(t, &b1); + break; + case ST_DEFINEMORPHSHAPE: + id = swf_GetU16(t); + swf_GetRect(t, &b1); + swf_GetRect(t, &b2); + swf_ExpandRect2(&b1, &b2); + break; + case ST_DEFINEBITSLOSSLESS: + case ST_DEFINEBITSLOSSLESS2: + case ST_DEFINEBITS: + case ST_DEFINEBITSJPEG2: + case ST_DEFINEBITSJPEG3: + // FIXME + break; + } + + swf_SetTagPos(t,oldTagPos); + + return b1; +} + U16 swf_GetPlaceID(TAG * t) // up to SWF 4.0 { U32 oldTagPos; @@ -116,6 +182,7 @@ U16 swf_GetPlaceID(TAG * t) switch (swf_GetTagID(t)) { case ST_PLACEOBJECT: case ST_REMOVEOBJECT: + case ST_FREECHARACTER: case ST_STARTSOUND: id = swf_GetU16(t); break; @@ -153,6 +220,7 @@ static int swf_definingtagids[] = ST_DEFINEBUTTON, ST_DEFINEBUTTON2, ST_DEFINESOUND, + ST_DEFINEVIDEOSTREAM, -1 }; @@ -176,9 +244,12 @@ static int swf_spritetagids[] = static int swf_pseudodefiningtagids[] = { ST_DEFINEFONTINFO, + ST_DEFINEFONTINFO2, ST_DEFINEBUTTONCXFORM, ST_DEFINEBUTTONSOUND, ST_NAMECHARACTER, + ST_DOINITACTION, + ST_VIDEOFRAME, -1 }; @@ -221,10 +292,9 @@ U8 swf_isPseudoDefiningTag(TAG * tag) return 0; } -U16 swf_GetDepth(TAG * t) -// up to SWF 4.0 +int swf_GetDepth(TAG * t) { - U16 depth = 0; + int depth = -1; U32 oldTagPos; oldTagPos = swf_GetTagPos(t); swf_SetTagPos(t,0); @@ -242,11 +312,36 @@ U16 swf_GetDepth(TAG * t) { U8 flags = swf_GetU8(t); depth = swf_GetU16(t); } break; + case ST_SETTABINDEX: + { + depth = swf_GetU16(t); + } } swf_SetTagPos(t,oldTagPos); return depth; } +void swf_SetDepth(TAG * t, U16 depth) +{ + switch (swf_GetTagID(t)) + { case ST_PLACEOBJECT: + case ST_REMOVEOBJECT: + PUT16(t->data, depth); + break; + case ST_REMOVEOBJECT2: + PUT16(t->data, depth); + break; + case ST_PLACEOBJECT2: + PUT16(&t->data[1], depth); + break; + case ST_SETTABINDEX: + PUT16(t->data, depth); + break; + default: + fprintf(stderr, "rfxswf: Error: tag %d has no depth\n", t->id); + } +} + char* swf_GetName(TAG * t) { char* name = 0; @@ -271,6 +366,8 @@ char* swf_GetName(TAG * t) swf_GetCXForm(t, &c, 1); if(flags&PF_RATIO) swf_GetU16(t); + if(flags&PF_CLIPACTION) + swf_GetU16(t); if(flags&PF_NAME) { swf_ResetReadBits(t); name = &t->data[swf_GetTagPos(t)]; @@ -282,7 +379,33 @@ char* swf_GetName(TAG * t) return name; } -void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void*callback_data, int num) +/* used in enumerateUsedIDs */ +void swf_GetMorphGradient(TAG * tag, GRADIENT * gradient1, GRADIENT * gradient2) +{ + GRADIENT dummy1; + GRADIENT dummy2; + int t; + if(!gradient1) + gradient1 = &dummy1; + if(!gradient2) + gradient2 = &dummy2; + gradient1->num = + gradient2->num = swf_GetU8(tag); + 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]); + } +} + +#define DEBUG_ENUMERATE if(0) + +static void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void*callback_data, int num, int morph) { U16 count; int t; @@ -298,16 +421,21 @@ void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void type = swf_GetU8(tag); //type if(type == 0) { if(num == 3) - swf_GetRGBA(tag, NULL); + {swf_GetRGBA(tag, NULL);if(morph) swf_GetRGBA(tag, NULL);} else - swf_GetRGB(tag, NULL); + {swf_GetRGB(tag, NULL);if(morph) swf_GetRGB(tag, NULL);} } else if(type == 0x10 || type == 0x12) { swf_ResetReadBits(tag); swf_GetMatrix(tag, NULL); + if(morph) + swf_GetMatrix(tag, NULL); swf_ResetReadBits(tag); - swf_GetGradient(tag, NULL, /*alpha*/ num>=3?1:0); + if(morph) + swf_GetMorphGradient(tag, NULL, NULL); + else + swf_GetGradient(tag, NULL, /*alpha*/ num>=3?1:0); } else if(type == 0x40 || type == 0x41) { @@ -320,6 +448,8 @@ void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void 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\n",type); @@ -332,10 +462,12 @@ void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void for(t=0;tpos + base, callback_data); //button id break; + + case ST_EXPORTASSETS: { + int num = swf_GetU16(tag); + int t; + 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: + callback(tag, tag->pos + base, callback_data); + break; case ST_PLACEOBJECT: callback(tag, tag->pos + base, callback_data); break; @@ -511,10 +659,19 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v break; } case ST_DEFINEFONTINFO: + case ST_DEFINEFONTINFO2: + case ST_VIDEOFRAME: + callback(tag, tag->pos + base, callback_data); + break; + case ST_DEFINEVIDEOSTREAM: + break; + + case ST_DOINITACTION: callback(tag, tag->pos + base, callback_data); break; - case ST_DEFINESHAPE3: // these thingies might have bitmap ids in their fillstyles + case ST_DEFINEMORPHSHAPE: + case ST_DEFINESHAPE3: num++; //fallthrough case ST_DEFINESHAPE2: num++; //fallthrough @@ -522,56 +679,91 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v int fillbits; int linebits; int id; + int numshapes = 1; + int morph = 0; + if(tag->id == ST_DEFINEMORPHSHAPE) { + numshapes = 2; + morph = 1; + } + id = swf_GetU16(tag); // id; swf_GetRect(tag, NULL); // bounds + if(morph) { + swf_ResetReadBits(tag); + swf_GetRect(tag, NULL); // bounds2 + swf_GetU32(tag); //offset to endedges + } + + DEBUG_ENUMERATE printf("Tag:%d Name:%s ID:%d\n", tag->id, swf_TagGetName(tag), id); - enumerateUsedIDs_styles(tag, callback, callback_data, num); - fillbits = swf_GetBits(tag, 4); - linebits = swf_GetBits(tag, 4); - swf_ResetReadBits(tag); - while(1) { - int flags; - flags = swf_GetBits(tag, 1); - if(!flags) { //style change - flags = swf_GetBits(tag, 5); - if(!flags) - break; - if(flags&1) { //move - int n = swf_GetBits(tag, 5); - swf_GetBits(tag, n); //x - swf_GetBits(tag, n); //y - } - if(flags&2) { //fill0 - swf_GetBits(tag, fillbits); - } - if(flags&4) { //fill1 - swf_GetBits(tag, fillbits); - } - if(flags&8) { //linestyle - swf_GetBits(tag, linebits); - } - if(flags&16) { - enumerateUsedIDs_styles(tag, callback, callback_data, num); - fillbits = swf_GetBits(tag, 4); - linebits = swf_GetBits(tag, 4); - } - } else { + enumerateUsedIDs_styles(tag, callback, callback_data, num, morph); + DEBUG_ENUMERATE printf("-------\n"); + while(--numshapes>=0) /* morph shapes define two shapes */ + { + 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); + swf_ResetReadBits(tag); + while(1) { + int flags; flags = swf_GetBits(tag, 1); - if(flags) { //straight edge - int n = swf_GetBits(tag, 4) + 2; - if(swf_GetBits(tag, 1)) { //line flag - swf_GetBits(tag, n); //delta x - swf_GetBits(tag, n); //delta y - } else { - int v=swf_GetBits(tag, 1); - swf_GetBits(tag, n); //vert/horz + if(!flags) { //style change + flags = swf_GetBits(tag, 5); + if(!flags) + break; + if(flags&1) { //move + int n = swf_GetBits(tag, 5); + int x,y; + x = swf_GetBits(tag, n); //x + y = swf_GetBits(tag, n); //y + DEBUG_ENUMERATE printf("move %f %f\n",x/20.0,y/20.0); + } + if(flags&2) { //fill0 + int fill0; + fill0 = swf_GetBits(tag, fillbits); + DEBUG_ENUMERATE printf("fill0 %d\n", fill0); + } + if(flags&4) { //fill1 + int fill1; + fill1 = swf_GetBits(tag, fillbits); + DEBUG_ENUMERATE printf("fill1 %d\n", fill1); + } + if(flags&8) { //linestyle + int line; + line = swf_GetBits(tag, linebits); + DEBUG_ENUMERATE printf("linestyle %d\n",line); + } + if(flags&16) { + DEBUG_ENUMERATE printf("more fillstyles\n"); + enumerateUsedIDs_styles(tag, callback, callback_data, num, 0); + fillbits = swf_GetBits(tag, 4); + linebits = swf_GetBits(tag, 4); + } + } else { + flags = swf_GetBits(tag, 1); + if(flags) { //straight edge + int n = swf_GetBits(tag, 4) + 2; + if(swf_GetBits(tag, 1)) { //line flag + int x,y; + x = swf_GetSBits(tag, n); //delta x + y = swf_GetSBits(tag, n); //delta y + DEBUG_ENUMERATE printf("line %f %f\n",x/20.0,y/20.0); + } else { + int v=swf_GetBits(tag, 1); + int d; + d = swf_GetSBits(tag, n); //vert/horz + DEBUG_ENUMERATE printf("%s %f\n",v?"vertical":"horizontal", d/20.0); + } + } else { //curved edge + int n = swf_GetBits(tag, 4) + 2; + int x1,y1,x2,y2; + x1 = swf_GetSBits(tag, n); + y1 = swf_GetSBits(tag, n); + x2 = swf_GetSBits(tag, n); + y2 = swf_GetSBits(tag, n); + DEBUG_ENUMERATE printf("curve %f %f %f %f\n", x1/20.0, y1/20.0, x2/20.0, y2/20.0); } - } else { //curved edge - int n = swf_GetBits(tag, 4) + 2; - swf_GetBits(tag, n); - swf_GetBits(tag, n); - swf_GetBits(tag, n); - swf_GetBits(tag, n); } } } @@ -585,12 +777,14 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v void callbackCount(TAG * t,int pos, void*ptr) { (*(int*)ptr)++; + DEBUG_ENUMERATE printf("callback(%d) %d\n", pos, *(U16*)&t->data[pos]); } void callbackFillin(TAG * t,int pos, void*ptr) { **(int**)ptr = pos; (*(int**)ptr)++; + DEBUG_ENUMERATE printf("callback(%d) %d\n", pos, *(U16*)&t->data[pos]); } int swf_GetNumUsedIDs(TAG * t) @@ -606,3 +800,87 @@ void swf_GetUsedIDs(TAG * t, int * positions) enumerateUsedIDs(t, 0, callbackFillin, &ptr); } +void swf_Relocate (SWF*swf, char*bitmap) +{ + TAG*tag; + int slaveids[65536]; + memset(slaveids, -1, sizeof(slaveids)); + tag = swf->firstTag; + while(tag) + { + int num; + int *ptr; + int t; + + if(swf_isDefiningTag(tag)) + { + int newid; + int id; + + id = swf_GetDefineID(tag); //own id + + if(!bitmap[id]) { //free + newid = id; + } + else { + newid = 0; + for (t=1;t<65536;t++) + { + if(!bitmap[t]) + { + newid = t; + break; + } + } + } + bitmap[newid] = 1; + slaveids[id] = newid; + + swf_SetDefineID(tag, newid); + } + + num = swf_GetNumUsedIDs(tag); + ptr = malloc(sizeof(int)*num); + swf_GetUsedIDs(tag, ptr); + + for(t=0;tdata[ptr[t]]); + if(slaveids[id]<0) { + fprintf(stderr, "swf_Relocate: Mapping id never encountered before: %d\n", id); + return ; + } + id = slaveids[id]; + PUT16(&tag->data[ptr[t]], id); + } + tag=tag->next; + } +} + +void swf_RelocateDepth(SWF*swf, char*bitmap) +{ + TAG*tag; + int nr; + tag = swf->firstTag; + for(nr=65535;nr>=0;nr--) { + if(bitmap[nr] != 0) + break; + } + // now nr is the highest used depth. So we start + // assigning depths at nr+1 + nr++; + + while(tag) + { + int depth = swf_GetDepth(tag); + if(depth>=0) { + int newdepth = depth+nr; + if(newdepth>65535) { + fprintf(stderr, "Couldn't relocate depths: too large values\n"); + newdepth = 65535; + } + swf_SetDepth(tag, newdepth); + } + tag=tag->next; + } +} +