-/* 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.
#endif // HAVE_ZLIB_H
#endif // HAVE_LIBZ
-// Win32 support may be broken since it was only tested in an older version for Watcom C
-#ifdef __NT__
-# include <io.h>
-# include <malloc.h>
-# include <string.h>
-# ifdef DEBUG_RFXSWF
-# include <stdio.h>
-# endif
-#else
-#endif
+#define LAME
+#include "lame/lame.h"
+
+#include "./bitio.h"
// internal constants
#define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
+
// inline wrapper functions
TAG * swf_NextTag(TAG * t) { return t->next; }
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;
}
return (S32)res;
}
+U32 reader_GetBits(struct reader_t*reader, int nbits)
+{ return reader_readbits(reader, nbits);
+}
+S32 reader_GetSBits(struct reader_t*reader, int nbits)
+{ U32 res = reader_readbits(reader, nbits);
+ if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
+ return (S32)res;
+}
+
int swf_SetBits(TAG * t,U32 v,int nbits)
{ U32 bm = 1<<(nbits-1);
}
}
+void swf_GetMorphGradient(TAG * tag, GRADIENT * gradient1, GRADIENT * gradient2)
+{
+ GRADIENT dummy1;
+ GRADIENT dummy2;
+ int t;
+ if(!gradient1)
+ gradient1 = &dummy1;
+ if(!gradient2)
+ gradient2 = &dummy2;
+ gradient1->num =
+ gradient2->num = swf_GetU8(tag);
+ for(t=0;t<gradient1->num;t++)
+ {
+ int s=t;
+ if(s>=8) //FIXME
+ s=7;
+ gradient1->ratios[t] = swf_GetU8(tag);
+ swf_GetRGBA(tag, &gradient1->rgba[t]);
+ gradient2->ratios[t] = swf_GetU8(tag);
+ swf_GetRGBA(tag, &gradient2->rgba[t]);
+ }
+}
+
int swf_CountBits(U32 v,int nbits)
{ int n = 33;
U32 m = 0x80000000;
return 0;
}
+int reader_GetRect(struct reader_t*reader,SRECT * r)
+{ int nbits;
+ SRECT dummy;
+ if (!r) r = &dummy;
+ 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 swf_SetRect(TAG * t,SRECT * r)
{ int nbits;
// Tag List Manipulating Functions
-int RFXSWF_UpdateFrame(TAG * t,S8 delta)
+int swf_UpdateFrame(TAG * t,S8 delta)
// returns number of frames
{ int res = -1;
while (t)
return res;
}
-#define swf_UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)
-
TAG * swf_InsertTag(TAG * after,U16 id) // updates frames, if nescessary
{ 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;
if (len==0x3f)
{
- if (read(handle,&len,4)!=4) return NULL;
+ if (reader->read(reader, &len, 4) != 4) return NULL;
len = SWAP32(len);
}
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;
}
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)
return t;
}
-int RFXSWF_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)?RFXSWF_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] = SWAP16(len|((t->id&0x3ff)<<6));
- if (write(handle,raw,2)!=2)
+ if (writer->write(writer,raw,2)!=2)
{
#ifdef DEBUG_RFXSWF
fprintf(stderr,"WriteTag() failed: Short Header.\n");
else
{
raw[0] = SWAP16((t->id<<6)|0x3f);
- if (write(handle,raw,2)!=2)
+ if (writer->write(writer,raw,2)!=2)
{
#ifdef DEBUG_RFXSWF
fprintf(stderr,"WriteTag() failed: Long Header (1).\n");
}
len = SWAP32(len);
- if (write(handle,&len,4)!=4)
+ if (writer->write(writer,&len,4)!=4)
{
#ifdef DEBUG_RFXSWF
fprintf(stderr,"WriteTag() failed: Long Header (2).\n");
}
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");
return t->len+(short_tag?2:6);
}
-int swf_WriteTag(int handle,TAG * t)
+int swf_WriteTag(int handle, TAG * t)
{
- return RFXSWF_WriteTag(handle, t);
+ struct writer_t writer;
+ if(handle<0)
+ return swf_WriteTag2(0, t);
+ writer_init_filewriter(&writer, handle);
+ return swf_WriteTag2(&writer, t);
}
-int RFXSWF_DefineSprite_GetRealSize(TAG * t)
+int swf_DefineSprite_GetRealSize(TAG * t)
// Sprite Handling: Helper function to pack DefineSprite-Tag
{ U32 len = t->len;
if(len>4) { // folded sprite
}
do
{ t = swf_NextTag(t);
- if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);
+ if (t->id!=ST_DEFINESPRITE) len += swf_WriteTag(-1, t);
else t = NULL;
} while (t&&(t->id!=ST_END));
return 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);
}
}
-#define swf_ReadTag(a,b) RFXSWF_ReadTag(a,b)
-#define swf_WriteTag(a,b) RFXSWF_WriteTag(a,b)
-
// Movie Functions
-int swf_InitSWF(void*data, int length, SWF * swf) /* copy a swf in memory into SWF struct */
-{
- TAG reader;
- /*
- unfinished!
- */
- *(int*)0=0xDEAD;
- if (!swf) return -1;
- memset(swf,0x00,sizeof(SWF));
- memset(&reader,0x00,sizeof(TAG));
- reader.data = data;
- reader.len = reader.memsize = length;
-
- { char b[32]; // read Header
- TAG * t;
-
- if (swf_GetU8(&reader)!=(U8)'F') return -1;
- if (swf_GetU8(&reader)!=(U8)'W') return -1;
- if (swf_GetU8(&reader)!=(U8)'S') return -1;
-
- swf->fileVersion = swf_GetU8(&reader);
- swf->fileSize = swf_GetU32(&reader);
- swf_GetRect(&reader,&swf->movieSize);
- swf->frameRate = swf_GetU16(&reader);
- swf->frameCount = swf_GetU16(&reader);
-
- /*t = &t1;
- while (t) t = swf_ReadTag(handle,t);
- swf->firstTag = t1.next;
- t1.next->prev = NULL;*/
- }
- return 0;
-}
-
-int swf_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]; // read Header
- TAG t1;
+ 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 (swf_GetU8(&t1)!=(U8)'F') return -1;
- if (swf_GetU8(&t1)!=(U8)'W') return -1;
- if (swf_GetU8(&t1)!=(U8)'S') return -1;
+ if(swf->compressed) {
+ reader_init_zlibinflate(&zreader, reader);
+ reader = &zreader;
+ }
- swf->fileVersion = swf_GetU8(&t1);
- swf->fileSize = swf_GetU32(&t1);
- swf_GetRect(&t1,&swf->movieSize);
- swf->frameRate = swf_GetU16(&t1);
- swf->frameCount = swf_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);
- swf_GetU8(&t1);
- lseek(handle,swf_GetTagPos(&t1)-1,SEEK_SET);
-
- // reda tags and connect to list
+ /* read tags and connect to list */
t = &t1;
- while (t) t = swf_ReadTag(handle,t);
+ while (t) t = swf_ReadTag(reader,t);
swf->firstTag = t1.next;
t1.next->prev = NULL;
}
- return 0;
+ return reader->pos;
}
-int swf_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;
if (!swf) return -1;
len = 0;
t = swf->firstTag;
- swf->frameCount = 0;
+ frameCount = 0;
while(t)
- { len += swf_WriteTag(-1,t);
- if (t->id==ST_SHOWFRAME) swf->frameCount++;
+ { 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;
- swf_SetU8(&t1,'F');
- swf_SetU8(&t1,'W');
- swf_SetU8(&t1,'S');
- swf_SetU8(&t1,swf->fileVersion);
-
- swf_SetU32(&t1,swf->fileSize); // Keep space for filesize
+ { // 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(len) {// don't touch headers without tags
+ swf->fileSize = l+len;
+ swf->frameCount = frameCount;
+ }
+
+ if(swf->compressed) {
+ char*id = "CWS";
+ writer->write(writer, id, 3);
+ }
+ else {
+ char*id = "FWS";
+ writer->write(writer, id, 3);
+ }
+
+ 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;
+ }
+
swf_SetRect(&t1,&swf->movieSize);
swf_SetU16(&t1,swf->frameRate);
swf_SetU16(&t1,swf->frameCount);
- l = swf_GetTagLen(&t1);
- swf->fileSize = l+len;
- if(swf->firstTag) {
- t1.len = 4; // bad & ugly trick !
- swf_SetU32(&t1,swf->fileSize);
- }
-
- if (handle>=0)
+ 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);
+ printf("ret:%d\n",ret);
perror("write:");
fprintf(stderr,"WriteSWF() failed: Header.\n");
#endif
t = swf->firstTag;
while (t)
- { if (swf_WriteTag(handle,t)<0) return -1;
+ { if (swf_WriteTag2(writer, t)<0) return -1;
t = swf_NextTag(t);
}
+ writer->finish(writer); //e.g. flush zlib buffers
}
}
return (int)swf->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);
+ 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)
+ 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;
- swf_WriteSWF(handle, &myswf);
- return 0;
+ SWF myswf;
+ memcpy(&myswf,swf,sizeof(SWF));
+ myswf.firstTag = 0;
+ return swf_WriteSWF(handle, &myswf);
}
int swf_WriteCGI(SWF * swf)
// 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"
-#include "modules\swfaction.c"
-#include "modules\swfsound.c"
-
-#else
-
#include "modules/swfdump.c"
#include "modules/swfshape.c"
#include "modules/swftext.c"
#include "modules/swfaction.c"
#include "modules/swfsound.c"
-#endif
-
-