+void swf_UnFoldSprite(TAG * t)
+{
+ U16 id,tmp;
+ U32 len;
+ TAG*next = t;
+ U16 spriteid,spriteframes;
+ int level;
+ if(t->id!=ST_DEFINESPRITE)
+ return;
+ if(t->len<=4) // not folded
+ return;
+
+ swf_SetTagPos(t,0);
+
+ spriteid = swf_GetU16(t); //id
+ spriteframes = swf_GetU16(t); //frames
+
+ level = 1;
+
+ while(1)
+ {
+ TAG*it = 0;
+ tmp = swf_GetU16(t);
+ len = tmp&0x3f;
+ id = tmp>>6;
+ if(id == ST_END)
+ level--;
+ if(id == ST_DEFINESPRITE && len<=4)
+ level++;
+
+ if (len==0x3f)
+ len = swf_GetU32(t);
+ it = swf_InsertTag(next, id);
+ next = it;
+ it->len = len;
+ it->id = id;
+ if (it->len)
+ { it->data = (U8*)rfx_alloc(it->len);
+ it->memsize = it->len;
+ swf_GetBlock(t, it->data, it->len);
+ }
+
+ if(!level)
+ break;
+ }
+
+ rfx_free(t->data); t->data = 0;
+ t->memsize = t->len = t->pos = 0;
+
+ swf_SetU16(t, spriteid);
+ swf_SetU16(t, spriteframes);
+}
+
+void swf_FoldSprite(TAG * t)
+{
+ TAG*sprtag=t,*tmp;
+ U16 id,frames;
+ int level;
+ if(t->id!=ST_DEFINESPRITE)
+ return;
+ if(!t->len) {
+ fprintf(stderr, "Error: Sprite has no ID!");
+ return;
+ }
+ if(t->len>4) {
+ /* sprite is already folded */
+ return;
+ }
+
+ t->pos = 0;
+ id = swf_GetU16(t);
+ rfx_free(t->data);
+ t->len = t->pos = t->memsize = 0;
+ t->data = 0;
+
+ frames = 0;
+
+ t = swf_NextTag(sprtag);
+ level = 1;
+
+ do
+ {
+ if(t->id==ST_SHOWFRAME) frames++;
+ if(t->id == ST_DEFINESPRITE && t->len<=4)
+ level++;
+ if(t->id == ST_END)
+ level--;
+ t = swf_NextTag(t);
+ } while(t && level);
+ if(level)
+ fprintf(stderr, "rfxswf error: sprite doesn't end(1)\n");
+
+ swf_SetU16(sprtag, id);
+ swf_SetU16(sprtag, frames);
+
+ t = swf_NextTag(sprtag);
+ level = 1;
+
+ do
+ {
+ if(t->len<0x3f&&
+ (t->id!=ST_DEFINEBITSLOSSLESS&&t->id!=ST_DEFINEBITSLOSSLESS2&&t->id!=ST_SOUNDSTREAMBLOCK&&
+ t->id!=ST_DEFINEBITSJPEG&&t->id!=ST_DEFINEBITSJPEG2&&t->id!=ST_DEFINEBITSJPEG3)
+ ) {
+ swf_SetU16(sprtag,t->len|(t->id<<6));
+ } else {
+ swf_SetU16(sprtag,0x3f|(t->id<<6));
+ swf_SetU32(sprtag,t->len);
+ }
+ if(t->len)
+ swf_SetBlock(sprtag,t->data, t->len);
+ tmp = t;
+ if(t->id == ST_DEFINESPRITE && t->len<=4)
+ level++;
+ if(t->id == ST_END)
+ level--;
+ t = swf_NextTag(t);
+ swf_DeleteTag(0, tmp);
+ }
+ while (t && level);
+ if(level)
+ fprintf(stderr, "rfxswf error: sprite doesn't end(2)\n");
+
+// sprtag->next = t;
+// t->prev = sprtag;
+}
+
+int swf_IsFolded(TAG * t)
+{
+ return (t->id == ST_DEFINESPRITE && t->len>4);
+}
+
+void swf_FoldAll(SWF*swf)
+{
+ TAG*tag = swf->firstTag;
+ //swf_DumpSWF(stdout, swf);
+ while(tag) {
+ if(tag->id == ST_DEFINESPRITE) {
+ swf_FoldSprite(tag);
+ //swf_DumpSWF(stdout, swf);
+ }
+ tag = swf_NextTag(tag);
+ }
+}
+
+void swf_UnFoldAll(SWF*swf)
+{
+ TAG*tag = swf->firstTag;
+ while(tag) {
+ if(tag->id == ST_DEFINESPRITE)
+ swf_UnFoldSprite(tag);
+ tag = tag->next;
+ }
+}
+
+void swf_OptimizeTagOrder(SWF*swf)
+{
+ TAG*tag,*next;
+ TAG*level0;
+ int level;
+ int changes;
+ swf_UnFoldAll(swf);
+ /* at the moment, we don't actually do optimizing,
+ only fixing of non-spec-conformant things like
+ sprite tags */
+
+ do {
+ changes = 0;
+ level = 0;
+ level0 = 0;
+ tag = swf->firstTag;
+ while(tag) {
+ next = tag->next;
+ if(tag->id == ST_DEFINESPRITE) {
+ if(tag->len>4) {
+ /* ??? all sprites are supposed to be unfolded */
+ fprintf(stderr, "librfxswf error - internal error in OptimizeTagOrder/UnfoldAll\n");
+ }
+ level++;
+ if(level==1) {
+ level0 = tag;
+ tag = next;
+ continue;
+ }
+ }
+ if(level>=1) {
+ /* move non-sprite tags out of sprite */
+ if(!swf_isAllowedSpriteTag(tag) || level>=2) {
+ /* remove tag from current position */
+ tag->prev->next = tag->next;
+ if(tag->next)
+ tag->next->prev = tag->prev;
+
+ /* insert before tag level0 */
+ tag->next = level0;
+ tag->prev = level0->prev;
+ level0->prev = tag;
+ if(tag->prev)
+ tag->prev->next = tag;
+ else
+ swf->firstTag = tag;
+ changes = 1;
+ }
+ }
+ if(tag->id == ST_END) {
+ level--;
+ }
+
+ tag = next;
+ }
+ } while(changes);
+}