X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftools.c;h=c4f6e0581f2ad64991223d7b5e59bdda62336a33;hb=4acb3c6593a57f4feb0e8b496025ef8497f8e9a2;hp=8f6b418a901fef0480ffe0ccaecc0211d3c410ed;hpb=b628ac5236f25c4729c0bb660cd6f4605af26b24;p=swftools.git diff --git a/lib/modules/swftools.c b/lib/modules/swftools.c index 8f6b418..c4f6e05 100644 --- a/lib/modules/swftools.c +++ b/lib/modules/swftools.c @@ -116,10 +116,14 @@ U16 swf_GetDefineID(TAG * t) case ST_DEFINESPRITE: case ST_DEFINEMOVIE: case ST_DEFINEVIDEOSTREAM: + case ST_GLYPHNAMES: //pseudodefine case ST_VIDEOFRAME: //pseudodefine case ST_NAMECHARACTER: //pseudodefine + case ST_DOINITACTION: //pseudodefine id = swf_GetU16(t); break; + default: + fprintf(stderr, "rfxswf: Error: tag %d (%s) has no id\n", t->id, swf_TagGetName(t)); } swf_SetTagPos(t,oldTagPos); @@ -132,6 +136,7 @@ SRECT swf_GetDefineBBox(TAG * t) U32 oldTagPos; U16 id = 0; SRECT b1,b2; + memset(&b1, 0, sizeof(b1)); oldTagPos = swf_GetTagPos(t); swf_SetTagPos(t,0); @@ -143,8 +148,6 @@ SRECT swf_GetDefineBBox(TAG * t) case ST_DEFINESHAPE2: case ST_DEFINESHAPE3: case ST_DEFINEEDITTEXT: - case ST_DEFINEBUTTON: - case ST_DEFINEBUTTON2: case ST_DEFINETEXT: case ST_DEFINETEXT2: case ST_DEFINEVIDEOSTREAM: @@ -558,7 +561,7 @@ void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), v if(id == ST_END) break; tag2->len = tag2->memsize = len; - tag2->data = malloc(len); + tag2->data = rfx_alloc(len); memcpy(tag2->data, &tag->data[tag->pos], len); /* I never saw recursive sprites, but they are (theoretically) possible, so better add base here again */ @@ -842,17 +845,19 @@ void swf_Relocate (SWF*swf, char*bitmap) } 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 ; + if(num) { + ptr = rfx_alloc(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); } - id = slaveids[id]; - PUT16(&tag->data[ptr[t]], id); } tag=tag->next; } @@ -873,6 +878,9 @@ void swf_RelocateDepth(SWF*swf, char*bitmap) while(tag) { + /* TODO * clip depths + * sprites + */ int depth = swf_GetDepth(tag); if(depth>=0) { int newdepth = depth+nr; @@ -886,6 +894,26 @@ void swf_RelocateDepth(SWF*swf, char*bitmap) } } +U8 swf_isShapeTag(TAG*tag) +{ + if(tag->id == ST_DEFINESHAPE || + tag->id == ST_DEFINESHAPE2 || + tag->id == ST_DEFINESHAPE3) + return 1; + return 0; +} + +U8 swf_isImageTag(TAG*tag) +{ + if(tag->id == ST_DEFINEBITSJPEG || + tag->id == ST_DEFINEBITSJPEG2 || + tag->id == ST_DEFINEBITSJPEG3 || + tag->id == ST_DEFINEBITSLOSSLESS || + tag->id == ST_DEFINEBITSLOSSLESS2) + return 1; + return 0; +} + TAG* swf_Concatenate (TAG*list1,TAG*list2) { TAG*tag=0,*lasttag=0; @@ -928,3 +956,159 @@ TAG* swf_Concatenate (TAG*list1,TAG*list2) return swf1.firstTag; } + +static int tagHash(TAG*tag) +{ + int t, h=0; + unsigned int a = 0x6b973e5a; + /* start at pos 2, as 0 and 1 are the id */ + for(t=2;tlen;t++) { + unsigned int b = a; + a >>= 8; + a += tag->data[t]*0xefbc35a5*b*(t+1); + } + return a&0x7fffffff; //always return positive number +} + +void swf_Optimize(SWF*swf) +{ + const int hash_size = 131072; + char* dontremap = rfx_calloc(sizeof(char)*65536); + U16* remap = rfx_alloc(sizeof(U16)*65536); + TAG* id2tag = rfx_calloc(sizeof(TAG*)*65536); + TAG** hashmap = rfx_calloc(sizeof(TAG*)*hash_size); + TAG* tag; + int t; + for(t=0;t<65536;t++) { + remap[t] = t; + } + + swf_FoldAll(swf); + + tag = swf->firstTag; + while(tag) { + /* make sure we don't remap to this tag, + as it might have different "helper tags" + FIXME: a better way would be to compare + the helper tags, too. + */ + if(swf_isPseudoDefiningTag(tag) && + tag->id != ST_NAMECHARACTER) { + dontremap[swf_GetDefineID(tag)] = 1; + } + tag=tag->next; + } + tag = swf->firstTag; + while(tag) { + int doremap=1; + + TAG*next = tag->next; + + /* remap the tag */ + int num = swf_GetNumUsedIDs(tag); + int*positions = rfx_alloc(sizeof(int)*num); + int t; + swf_GetUsedIDs(tag, positions); + for(t=0;tdata[positions[t]]); + id = remap[id]; + PUT16(&tag->data[positions[t]], id); + } + rfx_free(positions); + tag = tag->next; + + /* now look for previous tags with the same + content */ + if(swf_isDefiningTag(tag)) { + TAG*tag2; + int id = swf_GetDefineID(tag); + int hash = tagHash(tag); + 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; + } + hash++; + } + if(!match) { + while(hashmap[hash%hash_size]) hash++; + hashmap[hash%hash_size] = tag; + } else { + swf_DeleteTag(tag); + if(tag == swf->firstTag) + swf->firstTag = next; + doremap = 0; + } + } else if(swf_isPseudoDefiningTag(tag)) { + int id = swf_GetDefineID(tag); + if(remap[id]!=id) { + /* 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; + doremap = 0; + } + } + + tag = next; + } + rfx_free(dontremap); + rfx_free(remap); + rfx_free(id2tag); + rfx_free(hashmap); +} + +void swf_SetDefineBBox(TAG * tag, SRECT newbbox) +{ + U16 id = 0; + SRECT b1; + swf_SetTagPos(tag,0); + + switch (swf_GetTagID(tag)) + { + case ST_DEFINESHAPE: + case ST_DEFINESHAPE2: + case ST_DEFINESHAPE3: + case ST_DEFINEEDITTEXT: + case ST_DEFINETEXT: + case ST_DEFINETEXT2: + case ST_DEFINEVIDEOSTREAM: { + U32 after_bbox_offset = 0, len; + U8*data; + id = swf_GetU16(tag); + swf_GetRect(tag, &b1); + swf_ResetReadBits(tag); + after_bbox_offset = tag->pos; + len = tag->len - after_bbox_offset; + data = malloc(len); + memcpy(data, &tag->data[after_bbox_offset], len); + tag->writeBit = 0; + tag->len = 2; + swf_SetRect(tag, &newbbox); + swf_SetBlock(tag, data, len); + free(data); + tag->pos = tag->readBit = 0; + + } break; + default: + fprintf(stderr, "rfxswf: Tag %d (%s) has no bbox\n", tag->id, swf_TagGetName(tag)); + } +} +