X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Frfxswf.c;h=0e000060965b70e4302f4a2669aed417325bec83;hp=5347ba03f022c355765ab24af55b70f803ada4ab;hb=34de503961eb25613a5b3f2a8e5bdb5d1f5de0e9;hpb=4818394f9d96fe1a48d182ae3d1e1e9964203ad5 diff --git a/lib/rfxswf.c b/lib/rfxswf.c index 5347ba0..0e00006 100644 --- a/lib/rfxswf.c +++ b/lib/rfxswf.c @@ -16,20 +16,19 @@ #include "rfxswf.h" -#ifdef HAVE_LIBJPEG -#ifdef HAVE_JPEGLIB_H +#ifdef HAVE_JPEGLIB #define HAVE_BOOLEAN #include -#define _JPEGLIB_INCLUDED_ -#endif // HAVE_JPEGLIB_H -#endif // HAVE_LIBJPEG +#endif // HAVE_JPEGLIB -#ifdef HAVE_LIBZ -#ifdef HAVE_ZLIB_H +#ifdef HAVE_ZLIB #include -#define _ZLIB_INCLUDED_ -#endif // HAVE_ZLIB_H -#endif // HAVE_LIBZ +#endif // HAVE_ZLIB + +#define LAME +#include "lame/lame.h" + +#include "./bitio.h" // internal constants @@ -67,6 +66,13 @@ void swf_SetTagPos(TAG * t,U32 pos) #endif } +char* swf_GetString(TAG*t) +{ + char* str = ((char*)(&(t)->data[(t)->pos])); + while(swf_GetU8(t)); + return str; +} + U8 swf_GetU8(TAG * t) { swf_ResetReadBits(t); #ifdef DEBUG_RFXSWF @@ -128,6 +134,7 @@ int swf_SetBlock(TAG * t,U8 * b,int l) { #ifdef DEBUG_RFXSWF fprintf(stderr,"Fatal Error: malloc()/realloc() failed (1). (%d bytes)\n", newmem); + *(int*)0=0; #endif return 0; } @@ -198,9 +205,6 @@ U32 swf_GetBits(TAG * t,int nbits) return res; } -/* reader/writer stuff - from ../src/bitio.c */ -#include "./bitio.c" - S32 swf_GetSBits(TAG * t,int nbits) { U32 res = swf_GetBits(t,nbits); if (res&(1<<(nbits-1))) res|=(0xffffffff<xmin=r->xmax=r->ymin=r->ymax=0;return 0;} if (!r) r = &dummy; nbits = (int) swf_GetBits(t,5); r->xmin = swf_GetSBits(t,nbits); @@ -347,6 +352,10 @@ int swf_SetRect(TAG * t,SRECT * r) nbits = swf_CountBits(r->xmax,nbits); nbits = swf_CountBits(r->ymin,nbits); nbits = swf_CountBits(r->ymax,nbits); + if(nbits>=32) { + fprintf(stderr, "rfxswf: Warning: num_bits overflow in swf_SetRect\n"); + nbits=31; + } swf_SetBits(t,nbits,5); swf_SetBits(t,r->xmin,nbits); @@ -357,6 +366,58 @@ int swf_SetRect(TAG * t,SRECT * r) return 0; } +void swf_ExpandRect(SRECT*src, SPOINT add) +{ + if(add.x < src->xmin) + src->xmin = add.x; + if(add.x > src->xmax) + src->xmax = add.x; + if(add.y < src->ymin) + src->ymin = add.y; + if(add.y > src->ymax) + src->ymax = add.y; +} +void swf_ExpandRect2(SRECT*src, SRECT*add) +{ + if((add->xmin | add->ymin | add->xmax | add->ymax)==0) + return; + if(add->xmin < src->xmin) + src->xmin = add->xmin; + if(add->ymin < src->ymin) + src->ymin = add->ymin; + if(add->xmax > src->xmax) + src->xmax = add->xmax; + if(add->ymax > src->ymax) + src->ymax = add->ymax; +} +SPOINT swf_TurnPoint(SPOINT p, MATRIX* m) +{ + SPOINT r; + r.x = (int)(m->sx*(1/65536.0)*p.x + m->r1*(1/65536.0)*p.y + 0.5) + m->tx; + r.y = (int)(m->r0*(1/65536.0)*p.x + m->sy*(1/65536.0)*p.y + 0.5) + m->ty; + return r; +} +SRECT swf_TurnRect(SRECT r, MATRIX* m) +{ + SRECT g; + SPOINT p1,p2,p3,p4,pp1,pp2,pp3,pp4; + p1.x = r.xmin;p1.y = r.ymin; + p2.x = r.xmax;p2.y = r.ymin; + p3.x = r.xmin;p3.y = r.ymax; + p4.x = r.xmax;p4.y = r.ymax; + pp1 = swf_TurnPoint(p1, m); + pp2 = swf_TurnPoint(p2, m); + pp3 = swf_TurnPoint(p3, m); + pp4 = swf_TurnPoint(p4, m); + g.xmin = g.xmax = pp1.x; + g.ymin = g.ymax = pp1.y; + swf_ExpandRect(&g, pp2); + swf_ExpandRect(&g, pp3); + swf_ExpandRect(&g, pp4); + return g; +} + + int swf_GetMatrix(TAG * t,MATRIX * m) { MATRIX dummy; int nbits; @@ -579,6 +640,17 @@ TAG * swf_InsertTag(TAG * after,U16 id) // updates frames, if nescessary return t; } +void swf_ClearTag(TAG * t) +{ + if (t->data) free(t->data); + t->data = 0; + t->pos = 0; + t->len = 0; + t->readBit = 0; + t->writeBit = 0; + t->memsize = 0; +} + int swf_DeleteTag(TAG * t) { if (!t) return -1; @@ -731,45 +803,112 @@ int swf_DefineSprite_GetRealSize(TAG * t) } do { t = swf_NextTag(t); - if (t->id!=ST_DEFINESPRITE) len += swf_WriteTag(-1, t); + if (t && t->id!=ST_DEFINESPRITE) len += swf_WriteTag(-1, t); else t = NULL; } while (t&&(t->id!=ST_END)); return len; } +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*)malloc(it->len); + it->memsize = it->len; + swf_GetBlock(t, it->data, it->len); + } + + if(!level) + break; + } + + 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,tmpid; + 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); - //frames = swf_GetU16(t); 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&&t!=ST_END); + } while(t && level); + if(level) + fprintf(stderr, "rfxswf error: sprite doesn't end(1)\n"); - t = swf_NextTag(sprtag); swf_SetU16(sprtag, id); swf_SetU16(sprtag, frames); + t = swf_NextTag(sprtag); + level = 1; + do { - tmpid= t->id; if(t->len<0x3f) { swf_SetU16(sprtag,t->len|(t->id<<6)); } else { @@ -779,15 +918,26 @@ void swf_FoldSprite(TAG * t) 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(tmp); } - while (t&&(tmpid!=ST_END)); + 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; @@ -798,6 +948,71 @@ void swf_FoldAll(SWF*swf) } } +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; + tag->prev->next = tag; + changes = 1; + } + } + if(tag->id == ST_END) { + level--; + } + + tag = next; + } + } while(changes); +} + // Movie Functions int swf_ReadSWF2(struct reader_t*reader, SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails @@ -838,7 +1053,7 @@ int swf_ReadSWF2(struct reader_t*reader, SWF * swf) // Reads SWF to memory (ma t1.next->prev = NULL; } - return 0; + return reader->pos; } int swf_ReadSWF(int handle, SWF * swf) @@ -848,10 +1063,12 @@ int swf_ReadSWF(int handle, SWF * swf) return swf_ReadSWF2(&reader, swf); } -int swf_WriteSWF2(struct writer_t*writer, SWF * swf, bool compress) // Writes SWF to file, returns length or <0 if fails +int swf_WriteSWF2(struct writer_t*writer, SWF * swf) // Writes SWF to file, returns length or <0 if fails { U32 len; TAG * t; + int frameCount=0; struct writer_t zwriter; + int fileSize = 0; if (!swf) return -1; @@ -869,11 +1086,11 @@ int swf_WriteSWF2(struct writer_t*writer, SWF * swf, bool compress) // Writ len = 0; t = swf->firstTag; - swf->frameCount = 0; + frameCount = 0; while(t) { len += swf_WriteTag(-1, t); - if (t->id==ST_SHOWFRAME) swf->frameCount++; + if (t->id==ST_SHOWFRAME) frameCount++; t = swf_NextTag(t); } @@ -896,9 +1113,14 @@ int swf_WriteSWF2(struct writer_t*writer, SWF * swf, bool compress) // Writ swf_SetU16(&t2, swf->frameCount); l = swf_GetTagLen(&t2)+8; } - swf->fileSize = l+len; + + fileSize = l+len; + if(len) {// don't touch headers without tags + swf->fileSize = fileSize; + swf->frameCount = frameCount; + } - if(compress) { + if(swf->compressed) { char*id = "CWS"; writer->write(writer, id, 3); } @@ -911,7 +1133,7 @@ int swf_WriteSWF2(struct writer_t*writer, SWF * swf, bool compress) // Writ PUT32(b4, swf->fileSize); writer->write(writer, b4, 4); - if(compress) { + if(swf->compressed) { writer_init_zlibdeflate(&zwriter, writer); writer = &zwriter; } @@ -926,7 +1148,7 @@ int swf_WriteSWF2(struct writer_t*writer, SWF * swf, bool compress) // Writ if (ret!=swf_GetTagLen(&t1)) { #ifdef DEBUG_RFXSWF - printf("ret:%d\n",ret); + fprintf(stderr, "ret:%d\n",ret); perror("write:"); fprintf(stderr,"WriteSWF() failed: Header.\n"); #endif @@ -941,35 +1163,43 @@ int swf_WriteSWF2(struct writer_t*writer, SWF * swf, bool compress) // Writ writer->finish(writer); //e.g. flush zlib buffers } } - return (int)swf->fileSize; + return (int)fileSize; } int swf_WriteSWF(int handle, SWF * swf) // Writes SWF to file, returns length or <0 if fails { struct writer_t writer; + swf->compressed = 0; if(handle<0) - return swf_WriteSWF2(&writer, swf, FALSE); + return swf_WriteSWF2(&writer, swf); writer_init_filewriter(&writer, handle); - return swf_WriteSWF2(&writer, swf, FALSE); + return swf_WriteSWF2(&writer, swf); } int swf_WriteSWC(int handle, SWF * swf) // Writes SWF to file, returns length or <0 if fails { struct writer_t writer; + swf->compressed = 1; if(handle<0) - return swf_WriteSWF2(&writer, swf, TRUE); + return swf_WriteSWF2(&writer, swf); writer_init_filewriter(&writer, handle); - return swf_WriteSWF2(&writer, swf, TRUE); + return swf_WriteSWF2(&writer, swf); } +int swf_WriteHeader2(struct writer_t*writer,SWF * swf) +{ + SWF myswf; + memcpy(&myswf,swf,sizeof(SWF)); + myswf.firstTag = 0; + return swf_WriteSWF2(writer, &myswf); +} int swf_WriteHeader(int handle,SWF * swf) { SWF myswf; memcpy(&myswf,swf,sizeof(SWF)); myswf.firstTag = 0; - swf_WriteSWF(handle, &myswf); - return 0; + return swf_WriteSWF(handle, &myswf); } int swf_WriteCGI(SWF * swf) @@ -1013,4 +1243,3 @@ void swf_FreeTags(SWF * swf) // Frees all malloc'ed memory for t #include "modules/swfbits.c" #include "modules/swfaction.c" #include "modules/swfsound.c" -