X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftools.c;h=e92b44f0c7b7ef65b395c670cb617ffa1870b200;hb=c9d171c9692c7729e4eef7cfb8e6d93970c599c7;hp=1425383271cbf6cebf6cddf0a7ee440d26fa18fd;hpb=faca00b8c7eeee769980e19057a15ea82f52da7a;p=swftools.git diff --git a/lib/modules/swftools.c b/lib/modules/swftools.c index 1425383..e92b44f 100644 --- a/lib/modules/swftools.c +++ b/lib/modules/swftools.c @@ -119,8 +119,11 @@ U16 swf_GetDefineID(TAG * t) 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); @@ -930,3 +933,123 @@ 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; +} + +void swf_Optimize(SWF*swf) +{ + const int hash_size = 131072; + char* dontremap = malloc(sizeof(char)*65536); + U16* remap = malloc(sizeof(U16)*65536); + TAG* id2tag = malloc(sizeof(TAG*)*65536); + TAG** hashmap = malloc(sizeof(TAG*)*hash_size); + TAG* tag; + memset(dontremap, 0, sizeof(char)*65536); + memset(hashmap, 0, sizeof(TAG*)*hash_size); + memset(id2tag, 0, sizeof(TAG*)*65536); + 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)) { + //dontremap[swf_GetDefineID(tag)] = 1; //FIXME + } + tag=tag->next; + } + tag = swf->firstTag; + while(tag) { + int doremap=1; + + TAG*next = tag->next; + + 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; + } + } + + if(doremap) + { + int num = swf_GetNumUsedIDs(tag); + int*positions = malloc(sizeof(int)*num); + int t; + swf_GetUsedIDs(tag, positions); + for(t=0;tdata[positions[t]]); + id = remap[id]; + PUT16(&tag->data[positions[t]], id); + } + free(positions); + tag = tag->next; + } + + tag = next; + } + free(dontremap); + free(remap); + free(id2tag); + free(hashmap); +}