X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Frfxswf.c;h=944418d6f172accd2bb53e0d65450690ec4b83c5;hp=1c9bd667667258fd9422aa05d8e8bdafc0758ca8;hb=6feed80959ad2c11f0427bf0e5a30aab8abd7083;hpb=cfb06dab4b1674078f1306d1c537ad03d00def26 diff --git a/lib/rfxswf.c b/lib/rfxswf.c index 1c9bd66..944418d 100644 --- a/lib/rfxswf.c +++ b/lib/rfxswf.c @@ -1,4 +1,5 @@ -/* rfxswf.c +/* vi: set sts=2 sw=2 :*/ +/* rfxswf.c Library for creating and reading SWF files or parts of it. There's a module directory which provides some extended functionality. @@ -6,32 +7,43 @@ Part of the swftools package. - Copyright (c) 2000, 2001 Rainer Böhme - - This file is distributed under the GPL, see file COPYING for details + Copyright (c) 2000-2003 Rainer Böhme + Copyright (c) 2003 Matthias Kramm -*/ + 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 */ #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 - -// Win32 support may be broken since it was only tested in an older version for Watcom C -#ifdef __NT__ -# include -# include -# include -# ifdef DEBUG_RFXSWF -# include -# endif -#else +#endif // HAVE_JPEGLIB + +#ifdef HAVE_ZLIB +#include +#endif // HAVE_ZLIB + +#ifndef RFXSWF_DISABLESOUND +#ifdef HAVE_LAME +#include "lame/lame.h" +#endif #endif +#include "./bitio.h" +#include "./MD5.h" + // internal constants #define MALLOC_SIZE 128 @@ -39,36 +51,43 @@ #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE) + // inline wrapper functions -TAG * NextTag(TAG * t) { return t->next; } -TAG * PrevTag(TAG * t) { return t->prev; } -int GetFrameNo(TAG * t) { return t->frame; } -U16 GetTagID(TAG * t) { return t->id; } -U32 GetDataSize(TAG * t) { return t->len; } -U8* GetDataSizePtr(TAG * t) { return &(t->data[t->len]); } -U32 GetTagPos(TAG * t) { return t->pos; } +TAG * swf_NextTag(TAG * t) { return t->next; } +TAG * swf_PrevTag(TAG * t) { return t->prev; } +U16 swf_GetTagID(TAG * t) { return t->id; } +U32 swf_GetTagLen(TAG * t) { return t->len; } +U8* swf_GetTagLenPtr(TAG * t) { return &(t->data[t->len]); } +U32 swf_GetTagPos(TAG * t) { return t->pos; } // Basic Data Access Functions -#define ResetBitmask(tag) if (tag->bitmask) { tag->pos++; tag->bitmask = 0; } -#define ResetBitcount(tag) if (tag->bitcount) { tag->bitcount = 0; } +#define swf_ResetReadBits(tag) if (tag->readBit) { tag->pos++; tag->readBit = 0; } +#define swf_ResetWriteBits(tag) if (tag->writeBit) { tag->writeBit = 0; } -// for future purpose: avoid high level lib functions to change tagpos/bitcount +// for future purpose: avoid high level lib functions to change tagpos/bitpos -#define SaveTagPos(tag) -#define RestoreTagPos(tag) +#define swf_SaveTagPos(tag) +#define swf_RestoreTagPos(tag) -void SetTagPos(TAG * t,U32 pos) -{ ResetBitmask(t); +void swf_SetTagPos(TAG * t,U32 pos) +{ swf_ResetReadBits(t); if (pos<=t->len) t->pos = pos; #ifdef DEBUG_RFXSWF else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id); #endif } -U8 GetU8(TAG * t) -{ ResetBitmask(t); +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 if (t->pos>=t->len) { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id); @@ -78,9 +97,9 @@ U8 GetU8(TAG * t) return t->data[t->pos++]; } -U16 GetU16(TAG * t) +U16 swf_GetU16(TAG * t) { U16 res; - ResetBitmask(t); + swf_ResetReadBits(t); #ifdef DEBUG_RFXSWF if (t->pos>(t->len-2)) { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id); @@ -92,9 +111,9 @@ U16 GetU16(TAG * t) return res; } -U32 GetU32(TAG * t) +U32 swf_GetU32(TAG * t) { U32 res; - ResetBitmask(t); + swf_ResetReadBits(t); #ifdef DEBUG_RFXSWF if (t->pos>(t->len-4)) { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id); @@ -107,27 +126,28 @@ U32 GetU32(TAG * t) return res; } -int GetBlock(TAG * t,U8 * b,int l) +int swf_GetBlock(TAG * t,U8 * b,int l) // returns number of bytes written (<=l) // b = NULL -> skip data -{ ResetBitmask(t); +{ swf_ResetReadBits(t); if ((t->len-t->pos)len-t->pos; if (b && l) memcpy(b,&t->data[t->pos],l); t->pos+=l; return l; } -int SetBlock(TAG * t,U8 * b,int l) +int swf_SetBlock(TAG * t,U8 * b,int l) // Appends Block to the end of Tagdata, returns size { U32 newlen = t->len + l; - ResetBitcount(t); + swf_ResetWriteBits(t); if (newlen>t->memsize) { U32 newmem = MEMSIZE(newlen); U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem)); if (!newdata) { #ifdef DEBUG_RFXSWF - fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n"); + fprintf(stderr,"Fatal Error: malloc()/realloc() failed (1). (%d bytes)\n", newmem); + *(int*)0=0; #endif return 0; } @@ -140,34 +160,34 @@ int SetBlock(TAG * t,U8 * b,int l) return l; } -int SetU8(TAG * t,U8 v) -{ ResetBitcount(t); - if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1; +int swf_SetU8(TAG * t,U8 v) +{ swf_ResetWriteBits(t); + if ((t->len+1)>t->memsize) return (swf_SetBlock(t,&v,1)==1)?0:-1; t->data[t->len++] = v; return 0; } -int SetU16(TAG * t,U16 v) +int swf_SetU16(TAG * t,U16 v) { U8 a[2]; a[0] = v&0xff; a[1] = v>>8; - ResetBitcount(t); - if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1; + swf_ResetWriteBits(t); + if ((t->len+2)>t->memsize) return (swf_SetBlock(t,a,2)==2)?0:-1; t->data[t->len++] = a[0]; t->data[t->len++] = a[1]; return 0; } -int SetU32(TAG * t,U32 v) +int swf_SetU32(TAG * t,U32 v) { U8 a[4]; a[0] = v&0xff; // to ensure correct handling of non-intel byteorder a[1] = (v>>8)&0xff; a[2] = (v>>16)&0xff; a[3] = (v>>24)&0xff; - ResetBitcount(t); - if ((t->len+4)>t->memsize) return (SetBlock(t,a,4)==4)?0:-1; + swf_ResetWriteBits(t); + if ((t->len+4)>t->memsize) return (swf_SetBlock(t,a,4)==4)?0:-1; t->data[t->len++] = a[0]; t->data[t->len++] = a[1]; t->data[t->len++] = a[2]; @@ -175,17 +195,17 @@ int SetU32(TAG * t,U32 v) return 0; } -U32 GetBits(TAG * t,int nbits) +U32 swf_GetBits(TAG * t,int nbits) { U32 res = 0; if (!nbits) return 0; - if (!t->bitmask) t->bitmask = 0x80; + if (!t->readBit) t->readBit = 0x80; while (nbits) { res<<=1; - if (t->data[t->pos]&t->bitmask) res|=1; - t->bitmask>>=1; + if (t->data[t->pos]&t->readBit) res|=1; + t->readBit>>=1; nbits--; - if (!t->bitmask) - { if (nbits) t->bitmask = 0x80; + if (!t->readBit) + { if (nbits) t->readBit = 0x80; #ifdef DEBUG_RFXSWF if (t->pos>=t->len) { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id); @@ -198,23 +218,32 @@ U32 GetBits(TAG * t,int nbits) return res; } -S32 GetSBits(TAG * t,int nbits) -{ U32 res = GetBits(t,nbits); +S32 swf_GetSBits(TAG * t,int nbits) +{ U32 res = swf_GetBits(t,nbits); + if (res&(1<<(nbits-1))) res|=(0xffffffff<bitcount) - { if (FAILED(SetU8(t,0))) return -1; - t->bitcount = 0x80; + { if (!t->writeBit) + { if (FAILED(swf_SetU8(t,0))) return -1; + t->writeBit = 0x80; } - if (v&bm) t->data[t->len-1] |= t->bitcount; + if (v&bm) t->data[t->len-1] |= t->writeBit; bm>>=1; - t->bitcount>>=1; + t->writeBit>>=1; nbits--; } return 0; @@ -222,78 +251,222 @@ int SetBits(TAG * t,U32 v,int nbits) // Advanced Data Access Functions -int SetRGB(TAG * t,RGBA * col) +int swf_SetRGB(TAG * t,RGBA * col) { if (!t) return -1; if (col) - { SetU8(t,col->r); - SetU8(t,col->g); - SetU8(t,col->b); - } else SetBlock(t,NULL,3); + { swf_SetU8(t,col->r); + swf_SetU8(t,col->g); + swf_SetU8(t,col->b); + } else swf_SetBlock(t,NULL,3); return 0; } +void swf_GetRGB(TAG * t, RGBA * col) +{ + RGBA dummy; + if(!col) + col = &dummy; + col->r = swf_GetU8(t); + col->g = swf_GetU8(t); + col->b = swf_GetU8(t); + col->a = 255; +} -int SetRGBA(TAG * t,RGBA * col) +int swf_SetRGBA(TAG * t,RGBA * col) { if (!t) return -1; if (col) - { SetU8(t,col->r); - SetU8(t,col->g); - SetU8(t,col->b); - SetU8(t,col->a); - } else SetBlock(t,NULL,4); + { swf_SetU8(t,col->r); + swf_SetU8(t,col->g); + swf_SetU8(t,col->b); + swf_SetU8(t,col->a); + } else swf_SetBlock(t,NULL,4); return 0; } +void swf_GetRGBA(TAG * t, RGBA * col) +{ + RGBA dummy; + if(!col); + col = &dummy; + col->r = swf_GetU8(t); + col->g = swf_GetU8(t); + col->b = swf_GetU8(t); + col->a = swf_GetU8(t); +} -int CountBits(U32 v,int nbits) +void swf_GetGradient(TAG * tag, GRADIENT * gradient, char alpha) +{ + GRADIENT dummy; + int t; + if(!tag) { + memset(gradient, 0, sizeof(GRADIENT)); + return; + } + if(!gradient) + gradient = &dummy; + gradient->num = swf_GetU8(tag); + for(t=0;tnum;t++) + { + int s=t; + if(s>=8) //FIXME + s=7; + gradient->ratios[t] = swf_GetU8(tag); + if(!alpha) + swf_GetRGB(tag, &gradient->rgba[t]); + else + swf_GetRGBA(tag, &gradient->rgba[t]); + } +} + +void swf_SetGradient(TAG * tag, GRADIENT * gradient, char alpha) +{ + int t; + if(!tag) { + memset(gradient, 0, sizeof(GRADIENT)); + return; + } + swf_SetU8(tag, gradient->num); + for(t=0; t<8 && tnum; t++) + { + swf_SetU8(tag, gradient->ratios[t]); + if(!alpha) + swf_SetRGB(tag, &gradient->rgba[t]); + else + swf_SetRGBA(tag, &gradient->rgba[t]); + } +} + +int swf_CountUBits(U32 v,int nbits) +{ int n = 32; + U32 m = 0x80000000; + if(v == 0x00000000) n = 0; + else + while (!(v&m)) + { n--; + m>>=1; + } + return (n>nbits)?n:nbits; +} + +int swf_CountBits(U32 v,int nbits) { int n = 33; U32 m = 0x80000000; - if (!v) n = 0; else if (v&m) - { while (v&m) + { if(v == 0xffffffff) n = 1; + else + while (v&m) { n--; m>>=1; - if (!m) break; } } else - { while (!(v&m)) + { if(v == 0x00000000) n = 0; + else + while (!(v&m)) { n--; m>>=1; - if (!m) break; } } return (n>nbits)?n:nbits; } -int GetRect(TAG * t,SRECT * r) +int swf_GetRect(TAG * t,SRECT * r) +{ int nbits; + SRECT dummy; + if(!t) {r->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); + r->xmax = swf_GetSBits(t,nbits); + r->ymin = swf_GetSBits(t,nbits); + r->ymax = swf_GetSBits(t,nbits); + return 0; +} + +int reader_GetRect(struct reader_t*reader,SRECT * r) { int nbits; SRECT dummy; if (!r) r = &dummy; - nbits = (int) GetBits(t,5); - r->xmin = GetSBits(t,nbits); - r->xmax = GetSBits(t,nbits); - r->ymin = GetSBits(t,nbits); - r->ymax = GetSBits(t,nbits); + nbits = (int) reader_GetBits(reader,5); + r->xmin = reader_GetSBits(reader,nbits); + r->xmax = reader_GetSBits(reader,nbits); + r->ymin = reader_GetSBits(reader,nbits); + r->ymax = reader_GetSBits(reader,nbits); return 0; } -int SetRect(TAG * t,SRECT * r) +int swf_SetRect(TAG * t,SRECT * r) { int nbits; - nbits = CountBits(r->xmin,0); - nbits = CountBits(r->xmax,nbits); - nbits = CountBits(r->ymin,nbits); - nbits = CountBits(r->ymax,nbits); + nbits = swf_CountBits(r->xmin,0); + 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; + } - SetBits(t,nbits,5); - SetBits(t,r->xmin,nbits); - SetBits(t,r->xmax,nbits); - SetBits(t,r->ymin,nbits); - SetBits(t,r->ymax,nbits); + swf_SetBits(t,nbits,5); + swf_SetBits(t,r->xmin,nbits); + swf_SetBits(t,r->xmax,nbits); + swf_SetBits(t,r->ymin,nbits); + swf_SetBits(t,r->ymax,nbits); return 0; } -int GetMatrix(TAG * t,MATRIX * m) +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; @@ -306,30 +479,30 @@ int GetMatrix(TAG * t,MATRIX * m) return -1; } - ResetBitmask(t); + swf_ResetReadBits(t); - if (GetBits(t,1)) - { nbits = GetBits(t,5); - m->sx = GetSBits(t,nbits); - m->sy = GetSBits(t,nbits); + if (swf_GetBits(t,1)) + { nbits = swf_GetBits(t,5); + m->sx = swf_GetSBits(t,nbits); + m->sy = swf_GetSBits(t,nbits); } else m->sx = m->sy = 0x10000; - if (GetBits(t,1)) - { nbits = GetBits(t,5); - m->r0 = GetSBits(t,nbits); - m->r1 = GetSBits(t,nbits); + if (swf_GetBits(t,1)) + { nbits = swf_GetBits(t,5); + m->r0 = swf_GetSBits(t,nbits); + m->r1 = swf_GetSBits(t,nbits); } else m->r0 = m->r1 = 0x0; - nbits = GetBits(t,5); - m->tx = GetSBits(t,nbits); - m->ty = GetSBits(t,nbits); + nbits = swf_GetBits(t,5); + m->tx = swf_GetSBits(t,nbits); + m->ty = swf_GetSBits(t,nbits); return 0; } -int SetMatrix(TAG * t,MATRIX * m) +int swf_SetMatrix(TAG * t,MATRIX * m) { int nbits; MATRIX ma; @@ -340,38 +513,50 @@ int SetMatrix(TAG * t,MATRIX * m) ma.tx = ma.ty = 0; } - ResetBitcount(t); + swf_ResetWriteBits(t); - if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1); + if ((m->sx==0x10000)&&(m->sy==0x10000)) swf_SetBits(t,0,1); else - { SetBits(t,1,1); - nbits = CountBits(m->sx,0); - nbits = CountBits(m->sy,nbits); - SetBits(t,nbits,5); - SetBits(t,m->sx,nbits); - SetBits(t,m->sy,nbits); + { swf_SetBits(t,1,1); + nbits = swf_CountBits(m->sx,0); + nbits = swf_CountBits(m->sy,nbits); + if(nbits>=32) { + fprintf(stderr,"rfxswf: Error: matrix values too large\n"); + nbits = 31; + } + swf_SetBits(t,nbits,5); + swf_SetBits(t,m->sx,nbits); + swf_SetBits(t,m->sy,nbits); } - if ((!m->r0)&&(!m->r1)) SetBits(t,0,1); + if ((!m->r0)&&(!m->r1)) swf_SetBits(t,0,1); else - { SetBits(t,1,1); - nbits = CountBits(m->r0,0); - nbits = CountBits(m->r1,nbits); - SetBits(t,nbits,5); - SetBits(t,m->r0,nbits); - SetBits(t,m->r1,nbits); + { swf_SetBits(t,1,1); + nbits = swf_CountBits(m->r0,0); + nbits = swf_CountBits(m->r1,nbits); + if(nbits>=32) { + fprintf(stderr,"rfxswf: Error: matrix values too large\n"); + nbits = 31; + } + swf_SetBits(t,nbits,5); + swf_SetBits(t,m->r0,nbits); + swf_SetBits(t,m->r1,nbits); } - nbits = CountBits(m->tx,0); - nbits = CountBits(m->ty,nbits); - SetBits(t,nbits,5); - SetBits(t,m->tx,nbits); - SetBits(t,m->ty,nbits); + nbits = swf_CountBits(m->tx,0); + nbits = swf_CountBits(m->ty,nbits); + if(nbits>=32) { + fprintf(stderr,"rfxswf: Error: matrix values too large\n"); + nbits = 31; + } + swf_SetBits(t,nbits,5); + swf_SetBits(t,m->tx,nbits); + swf_SetBits(t,m->ty,nbits); return 0; } -int GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool +int swf_GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool { CXFORM cxf; int hasadd; int hasmul; @@ -384,31 +569,31 @@ int GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool if (!t) return 0; - ResetBitmask(t); - hasadd = GetBits(t,1); - hasmul = GetBits(t,1); - nbits = GetBits(t,4); + swf_ResetReadBits(t); + hasadd = swf_GetBits(t,1); + hasmul = swf_GetBits(t,1); + nbits = swf_GetBits(t,4); if (hasmul) - { cx->r0 = (S16)GetSBits(t,nbits); - cx->g0 = (S16)GetSBits(t,nbits); - cx->b0 = (S16)GetSBits(t,nbits); + { cx->r0 = (S16)swf_GetSBits(t,nbits); + cx->g0 = (S16)swf_GetSBits(t,nbits); + cx->b0 = (S16)swf_GetSBits(t,nbits); if (alpha) - cx->a0 = (S16)GetSBits(t,nbits); + cx->a0 = (S16)swf_GetSBits(t,nbits); } if (hasadd) - { cx->r1 = (S16)GetSBits(t,nbits); - cx->g1 = (S16)GetSBits(t,nbits); - cx->b1 = (S16)GetSBits(t,nbits); + { cx->r1 = (S16)swf_GetSBits(t,nbits); + cx->g1 = (S16)swf_GetSBits(t,nbits); + cx->b1 = (S16)swf_GetSBits(t,nbits); if (alpha) - cx->a1 = (S16)GetSBits(t,nbits); + cx->a1 = (S16)swf_GetSBits(t,nbits); } return 0; } -int SetCXForm(TAG * t,CXFORM * cx,U8 alpha) +int swf_SetCXForm(TAG * t,CXFORM * cx,U8 alpha) { CXFORM cxf; int hasadd; int hasmul; @@ -431,86 +616,141 @@ int SetCXForm(TAG * t,CXFORM * cx,U8 alpha) hasadd = cx->a1|cx->r1|cx->g1|cx->b1; if (hasmul) - { if (alpha) nbits = CountBits((S32)cx->a0,nbits); - nbits = CountBits((S32)cx->r0,nbits); - nbits = CountBits((S32)cx->g0,nbits); - nbits = CountBits((S32)cx->b0,nbits); + { if (alpha) nbits = swf_CountBits((S32)cx->a0,nbits); + nbits = swf_CountBits((S32)cx->r0,nbits); + nbits = swf_CountBits((S32)cx->g0,nbits); + nbits = swf_CountBits((S32)cx->b0,nbits); } if (hasadd) - { if (alpha) nbits = CountBits((S32)cx->a1,nbits); - nbits = CountBits((S32)cx->r1,nbits); - nbits = CountBits((S32)cx->g1,nbits); - nbits = CountBits((S32)cx->b1,nbits); + { if (alpha) nbits = swf_CountBits((S32)cx->a1,nbits); + nbits = swf_CountBits((S32)cx->r1,nbits); + nbits = swf_CountBits((S32)cx->g1,nbits); + nbits = swf_CountBits((S32)cx->b1,nbits); } - ResetBitcount(t); - SetBits(t,hasadd?1:0,1); - SetBits(t,hasmul?1:0,1); - SetBits(t,nbits,4); + swf_ResetWriteBits(t); + swf_SetBits(t,hasadd?1:0,1); + swf_SetBits(t,hasmul?1:0,1); + swf_SetBits(t,nbits,4); if (hasmul) - { SetBits(t,cx->r0,nbits); - SetBits(t,cx->g0,nbits); - SetBits(t,cx->b0,nbits); - if (alpha) SetBits(t,cx->a0,nbits); + { swf_SetBits(t,cx->r0,nbits); + swf_SetBits(t,cx->g0,nbits); + swf_SetBits(t,cx->b0,nbits); + if (alpha) swf_SetBits(t,cx->a0,nbits); } if (hasadd) - { SetBits(t,cx->r1,nbits); - SetBits(t,cx->g1,nbits); - SetBits(t,cx->b1,nbits); - if (alpha) SetBits(t,cx->a1,nbits); + { swf_SetBits(t,cx->r1,nbits); + swf_SetBits(t,cx->g1,nbits); + swf_SetBits(t,cx->b1,nbits); + if (alpha) swf_SetBits(t,cx->a1,nbits); } return 0; } -int GetPoint(TAG * t,SPOINT * p) { return 0; } -int SetPoint(TAG * t,SPOINT * p) { return 0; } +//int swf_GetPoint(TAG * t,SPOINT * p) { return 0; } +//int swf_SetPoint(TAG * t,SPOINT * p) { return 0; } -// Tag List Manipulating Functions +void swf_SetPassword(TAG * t, const char * password) +{ + /* WARNING: crypt_md5 is not reentrant */ + char* md5string = crypt_md5(password, "salt"); /* FIXME- get random salt */ + swf_SetString(t, md5string); +} -int RFXSWF_UpdateFrame(TAG * t,S8 delta) -// returns number of frames -{ int res = -1; - while (t) - { t->frame+=delta; - res = t->frame; - t = t->next; - } - return res; +int swf_VerifyPassword(TAG * t, const char * password) +{ + char*md5string1, *md5string2; + char*x; + char*md5, *salt; + int n; + + md5string1 = swf_GetString(t); + + if(!strncmp(md5string1, "$1$",3 )) { + return 0; + } + x = strchr(md5string1+3, '$'); + if(!x) + return 0; + n = x-(md5string1+3); + salt = (char*)malloc(n+1); + memcpy(salt, md5string1+3, n); + salt[n] = 0; + + md5string2 = crypt_md5(password, salt); + free(salt); + if(strcmp(md5string1, md5string2) != 0) + return 0; + return 1; } -#define UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b) +// Tag List Manipulating Functions -TAG * InsertTag(TAG * after,U16 id) // updates frames, if nescessary +TAG * swf_InsertTag(TAG * after,U16 id) { TAG * t; t = (TAG *)malloc(sizeof(TAG)); if (t) { memset(t,0x00,sizeof(TAG)); t->id = id; - t->bitcount = 0x80; if (after) - { t->frame = after->frame; + { t->prev = after; t->next = after->next; after->next = t; if (t->next) t->next->prev = t; - - if (id==ST_SHOWFRAME) UpdateFrame(t->next,+1); } } return t; } -int DeleteTag(TAG * t) -{ if (!t) return -1; +TAG * swf_InsertTagBefore(SWF* swf, TAG * before,U16 id) +{ TAG * t; - if (t->id==ST_SHOWFRAME) UpdateFrame(t->next,-1); + t = (TAG *)malloc(sizeof(TAG)); + if (t) + { memset(t,0x00,sizeof(TAG)); + t->id = id; + if (before) + { + t->next = before; + t->prev = before->prev; + before->prev = t; + if (t->prev) t->prev->next = t; + } + } + if(swf && swf->firstTag == before) { + swf->firstTag = t; + } + 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; +} + +void swf_ResetTag(TAG*tag, U16 id) +{ + tag->len = tag->pos = tag->readBit = tag->writeBit = 0; + tag->id = id; +} + +int swf_DeleteTag(TAG * t) +{ if (!t) return -1; + if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; @@ -519,30 +759,33 @@ int DeleteTag(TAG * t) return 0; } -TAG * RFXSWF_ReadTag(int handle,TAG * prev) +TAG * swf_ReadTag(struct reader_t*reader, TAG * prev) { TAG * t; U16 raw; U32 len; int id; - if (read(handle,&raw,2)!=2) return NULL; + if (reader->read(reader, &raw, 2) !=2 ) return NULL; + raw = SWAP16(raw); len = raw&0x3f; id = raw>>6; if (len==0x3f) - { if (read(handle,&len,4)!=4) return NULL; + { + if (reader->read(reader, &len, 4) != 4) return NULL; + len = SWAP32(len); } if (id==ST_DEFINESPRITE) len = 2*sizeof(U16); - // Sprite handling fix: Flaten sprite tree + // Sprite handling fix: Flatten sprite tree t = (TAG *)malloc(sizeof(TAG)); if (!t) { #ifdef DEBUG_RFXSWF - fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n"); + fprintf(stderr,"Fatal Error: malloc()/realloc() failed (2). (%d bytes)\n", sizeof(TAG)); #endif return NULL; } @@ -557,16 +800,16 @@ TAG * RFXSWF_ReadTag(int handle,TAG * prev) if (!t->data) { #ifdef DEBUG_RFXSWF - fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n"); + fprintf(stderr,"Fatal Error: malloc()/realloc() failed (3). (%d bytes)\n", t->len); #endif return NULL; } t->memsize = t->len; - if (read(handle,t->data,t->len)!=t->len) return NULL; + if (reader->read(reader, t->data, t->len) != t->len) return NULL; } if (prev) - { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0); + { t->prev = prev; prev->next = t; } @@ -574,25 +817,25 @@ TAG * RFXSWF_ReadTag(int handle,TAG * prev) return t; } -int DefineSprite_GetRealSize(TAG * t); +int swf_DefineSprite_GetRealSize(TAG * t); -int RFXSWF_WriteTag(int handle,TAG * t) +int swf_WriteTag2(struct writer_t*writer, TAG * t) // returns tag length in bytes (incl. Header), -1 = Error -// handle = -1 -> no output +// writer = 0 -> no output { U16 raw[3]; U32 len; int short_tag; if (!t) return -1; - len = (t->id==ST_DEFINESPRITE)?DefineSprite_GetRealSize(t):t->len; + len = (t->id==ST_DEFINESPRITE)?swf_DefineSprite_GetRealSize(t):t->len; short_tag = len<0x3f; - if (handle>=0) + if (writer) { if (short_tag) - { raw[0] = len|((t->id&0x3ff)<<6); - if (write(handle,raw,2)!=2) + { raw[0] = SWAP16(len|((t->id&0x3ff)<<6)); + if (writer->write(writer,raw,2)!=2) { #ifdef DEBUG_RFXSWF fprintf(stderr,"WriteTag() failed: Short Header.\n"); @@ -601,20 +844,28 @@ int RFXSWF_WriteTag(int handle,TAG * t) } } else - { raw[0] = (t->id<<6)|0x3f; - raw[1] = (U16)(len&0xffff); - raw[2] = (U16)(len>>16); - if (write(handle,raw,6)!=6) + { + raw[0] = SWAP16((t->id<<6)|0x3f); + if (writer->write(writer,raw,2)!=2) + { +#ifdef DEBUG_RFXSWF + fprintf(stderr,"WriteTag() failed: Long Header (1).\n"); +#endif + return -1; + } + + len = SWAP32(len); + if (writer->write(writer,&len,4)!=4) { #ifdef DEBUG_RFXSWF - fprintf(stderr,"WriteTag() failed: Long Header.\n"); + fprintf(stderr,"WriteTag() failed: Long Header (2).\n"); #endif return -1; } } if (t->data) - { if (write(handle,t->data,t->len)!=t->len) + { if (writer->write(writer,t->data,t->len)!=t->len) { #ifdef DEBUG_RFXSWF fprintf(stderr,"WriteTag() failed: Data.\n"); @@ -630,61 +881,292 @@ int RFXSWF_WriteTag(int handle,TAG * t) return t->len+(short_tag?2:6); } -int DefineSprite_GetRealSize(TAG * t) +int swf_WriteTag(int handle, TAG * t) +{ + struct writer_t writer; + if(handle<0) + return swf_WriteTag2(0, t); + writer_init_filewriter(&writer, handle); + return swf_WriteTag2(&writer, t); +} + +int swf_DefineSprite_GetRealSize(TAG * t) // Sprite Handling: Helper function to pack DefineSprite-Tag { U32 len = t->len; + if(len>4) { // folded sprite + return t->len; + } do - { t = NextTag(t); - if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t); + { t = swf_NextTag(t); + if (t && t->id!=ST_DEFINESPRITE) len += swf_WriteTag(-1, t); else t = NULL; } while (t&&(t->id!=ST_END)); return len; } -#define ReadTag(a,b) RFXSWF_ReadTag(a,b) -#define WriteTag(a,b) RFXSWF_WriteTag(a,b) +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); + 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) { + 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(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; + tag->prev->next = tag; + changes = 1; + } + } + if(tag->id == ST_END) { + level--; + } + + tag = next; + } + } while(changes); +} // Movie Functions -int ReadSWF(int handle,SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails +int swf_ReadSWF2(struct reader_t*reader, SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails { if (!swf) return -1; memset(swf,0x00,sizeof(SWF)); - { char b[32]; // Header lesen - TAG t1; + { char b[32]; // read Header + int len; TAG * t; + TAG t1; + struct reader_t zreader; - memset(&t1,0x00,sizeof(TAG)); + if ((len = reader->read(reader ,b,8))<8) return -1; + + if (b[0]!='F' && b[0]!='C') return -1; + if (b[1]!='W') return -1; + if (b[2]!='S') return -1; + swf->fileVersion = b[3]; + swf->compressed = (b[0]=='C')?1:0; + swf->fileSize = GET32(&b[4]); - if ((t1.len=read(handle,b,32))<21) return -1; - t1.data = (U8*)b; - - if (GetU8(&t1)!=(U8)'F') return -1; - if (GetU8(&t1)!=(U8)'W') return -1; - if (GetU8(&t1)!=(U8)'S') return -1; + if(swf->compressed) { + reader_init_zlibinflate(&zreader, reader); + reader = &zreader; + } - swf->FileVersion = GetU8(&t1); - swf->FileSize = GetU32(&t1); - GetRect(&t1,&swf->MovieSize); - swf->FrameRate = GetU16(&t1); - swf->FrameCount = GetU16(&t1); + reader_GetRect(reader, &swf->movieSize); + reader->read(reader, &swf->frameRate, 2); + swf->frameRate = SWAP16(swf->frameRate); + reader->read(reader, &swf->frameCount, 2); + swf->frameCount = SWAP16(swf->frameCount); - GetU8(&t1); - lseek(handle,GetTagPos(&t1)-1,SEEK_SET); - - // Tags lesen und verketten + /* read tags and connect to list */ t = &t1; - while (t) t = ReadTag(handle,t); - swf->FirstTag = t1.next; + while (t) t = swf_ReadTag(reader,t); + swf->firstTag = t1.next; t1.next->prev = NULL; } - return 0; + return reader->pos; } -int WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or <0 if fails + +int swf_ReadSWF(int handle, SWF * swf) +{ + struct reader_t reader; + reader_init_filereader(&reader, handle); + return swf_ReadSWF2(&reader, swf); +} + +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; @@ -692,75 +1174,150 @@ int WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or #ifdef INSERT_RFX_TAG - if (NextTag(swf->FirstTag)) - if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX) - SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3); + if (swf->firstTag && swf_NextTag(swf->firstTag)) + if (swf_GetTagID(swf_NextTag(swf->firstTag))!=ST_REFLEX) + swf_SetBlock(swf_InsertTag(swf->firstTag,ST_REFLEX),"rfx",3); #endif // INSERT_RFX_TAG // Count Frames + File Size len = 0; - t = swf->FirstTag; - swf->FrameCount = 0; + t = swf->firstTag; + frameCount = 0; while(t) - { len += WriteTag(-1,t); - if (t->id==ST_SHOWFRAME) swf->FrameCount++; - t = NextTag(t); + { len += swf_WriteTag(-1, t); + if (t->id==ST_SHOWFRAME) frameCount++; + t = swf_NextTag(t); } { TAG t1; - char b[64]; + char b[64],b4[4]; U32 l; memset(&t1,0x00,sizeof(TAG)); t1.data = (U8*)b; t1.memsize = 64; - SetU8(&t1,'F'); - SetU8(&t1,'W'); - SetU8(&t1,'S'); - SetU8(&t1,swf->FileVersion); - - SetU32(&t1,0); // Keep space for filesize - SetRect(&t1,&swf->MovieSize); - SetU16(&t1,swf->FrameRate); - SetU16(&t1,swf->FrameCount); + { // measure header file size + TAG t2; + char b2[64]; + memset(&t2,0x00,sizeof(TAG)); + t2.data = (U8*)b2; + t2.memsize = 64; + swf_SetRect(&t2, &swf->movieSize); + swf_SetU16(&t2, swf->frameRate); + swf_SetU16(&t2, swf->frameCount); + l = swf_GetTagLen(&t2)+8; + } + if(swf->compressed == 8) { + l -= 8; + } + + fileSize = l+len; + if(len) {// don't touch headers without tags + swf->fileSize = fileSize; + swf->frameCount = frameCount; + } + + if(swf->compressed != 8) { + /* compressed flag set to 8 means "skip first 8 + header bytes". This is necessary if the caller wants to + create compressed SWFs himself */ + if(swf->compressed) { + char*id = "CWS"; + writer->write(writer, id, 3); + } + else { + char*id = "FWS"; + writer->write(writer, id, 3); + } - l = GetDataSize(&t1); - swf->FileSize = l+len; - t1.len = 4; // bad & ugly trick ! - SetU32(&t1,swf->FileSize); + writer->write(writer, &swf->fileVersion, 1); + PUT32(b4, swf->fileSize); + writer->write(writer, b4, 4); + + if(swf->compressed) { + writer_init_zlibdeflate(&zwriter, writer); + writer = &zwriter; + } + } - if (handle>=0) + swf_SetRect(&t1,&swf->movieSize); + swf_SetU16(&t1,swf->frameRate); + swf_SetU16(&t1,swf->frameCount); + + if (writer) { - int ret = write(handle,b,l); - if (ret!=l) + int ret = writer->write(writer,b,swf_GetTagLen(&t1)); + if (ret!=swf_GetTagLen(&t1)) { #ifdef DEBUG_RFXSWF - printf("ret:%d (fd:%d)\n",ret, handle); - perror("write:"); + fprintf(stderr, "ret:%d\n",ret); + perror("write:"); fprintf(stderr,"WriteSWF() failed: Header.\n"); #endif return -1; } - t = swf->FirstTag; + t = swf->firstTag; while (t) - { if (WriteTag(handle,t)<0) return -1; - t = NextTag(t); + { if (swf_WriteTag2(writer, t)<0) return -1; + t = swf_NextTag(t); } + if(swf->compressed != 8) + writer->finish(writer); // flush zlib buffers - only if _we_ initialized that writer. } } - return (int)swf->FileSize; + return (int)fileSize; } -int WriteCGI(SWF * swf) +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) { + writer_init_nullwriter(&writer); + return swf_WriteSWF2(&writer, swf); + } + writer_init_filewriter(&writer, handle); + 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) { + writer_init_nullwriter(&writer); + return swf_WriteSWF2(&writer, swf); + } + writer_init_filewriter(&writer, handle); + 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; + return swf_WriteSWF(handle, &myswf); +} + +int swf_WriteCGI(SWF * swf) { int len; char s[1024]; - len = WriteSWF(-1,swf); + len = swf_WriteSWF(-1,swf); if (len<0) return -1; @@ -771,11 +1328,11 @@ int WriteCGI(SWF * swf) "\n",len); write(fileno(stdout),s,strlen(s)); - return WriteSWF(fileno(stdout),swf); + return swf_WriteSWF(fileno(stdout),swf); } -void FreeTags(SWF * swf) // Frees all malloc'ed memory for tags -{ TAG * t = swf->FirstTag; +void swf_FreeTags(SWF * swf) // Frees all malloc'ed memory for tags +{ TAG * t = swf->firstTag; while (t) { TAG * tnew = t->next; @@ -787,28 +1344,15 @@ void FreeTags(SWF * swf) // Frees all malloc'ed memory for tags // include advanced functions -#ifdef __NT__ - -#include "modules\swfdump.c" -#include "modules\swfshape.c" -#include "modules\swftext.c" -#include "modules\swfobject.c" -#include "modules\swfbutton.c" -#include "modules\swftools.c" -#include "modules\swfcgi.c" -#include "modules\swfbits.c" - -#else - #include "modules/swfdump.c" #include "modules/swfshape.c" #include "modules/swftext.c" +#include "modules/swffont.c" #include "modules/swfobject.c" #include "modules/swfbutton.c" #include "modules/swftools.c" #include "modules/swfcgi.c" #include "modules/swfbits.c" - -#endif - - +#include "modules/swfaction.c" +#include "modules/swfsound.c" +#include "modules/swfdraw.c"