-/* 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.
#ifdef HAVE_LIBJPEG
#ifdef HAVE_JPEGLIB_H
+#define HAVE_BOOLEAN
#include <jpeglib.h>
#define _JPEGLIB_INCLUDED_
#endif // HAVE_JPEGLIB_H
#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
-
// internal constants
#define MALLOC_SIZE 128
#define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
+
// inline wrapper functions
TAG * swf_NextTag(TAG * t) { return t->next; }
TAG * swf_PrevTag(TAG * t) { return t->prev; }
int swf_GetFrameNo(TAG * t) { return t->frame; }
U16 swf_GetTagID(TAG * t) { return t->id; }
-U32 swf_GetDataSize(TAG * t) { return t->len; }
-U8* swf_GetDataSizePtr(TAG * t) { return &(t->data[t->len]); }
+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
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);
#endif
return 0;
}
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<<nbits);
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);
} 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 swf_SetRGBA(TAG * t,RGBA * col)
{ if (!t) return -1;
} 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);
+}
+
+void swf_GetGradient(TAG * tag, GRADIENT * gradient, char alpha)
+{
+ GRADIENT dummy;
+ int t;
+ if(!gradient)
+ gradient = &dummy;
+ gradient->num = swf_GetU8(tag);
+ for(t=0;t<gradient->num;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]);
+ }
+}
int swf_CountBits(U32 v,int nbits)
{ int n = 33;
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;
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);
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] = 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");
}
}
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");
return t->len+(short_tag?2:6);
}
-int RFXSWF_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 = 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;
}
-#define swf_ReadTag(a,b) RFXSWF_ReadTag(a,b)
-#define swf_WriteTag(a,b) RFXSWF_WriteTag(a,b)
+void swf_FoldSprite(TAG * t)
+{
+ TAG*sprtag=t,*tmp;
+ U16 id,frames,tmpid;
+ if(t->id!=ST_DEFINESPRITE)
+ return;
+ if(!t->len) {
+ fprintf(stderr, "Error: Sprite has no ID!");
+ 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;
+
+ do
+ {
+ if(t->id==ST_SHOWFRAME) frames++;
+ t = swf_NextTag(t);
+ } while(t&&t!=ST_END);
+
+ t = swf_NextTag(sprtag);
+ swf_SetU16(sprtag, id);
+ swf_SetU16(sprtag, frames);
+
+ do
+ {
+ tmpid= t->id;
+ 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;
+ t = swf_NextTag(t);
+ swf_DeleteTag(tmp);
+ }
+ while (t&&(tmpid!=ST_END));
+
+// sprtag->next = t;
+// t->prev = sprtag;
+}
+
+void swf_FoldAll(SWF*swf)
+{
+ TAG*tag = swf->firstTag;
+ while(tag) {
+ if(tag->id == ST_DEFINESPRITE)
+ swf_FoldSprite(tag);
+ tag = swf_NextTag(tag);
+ }
+}
// Movie Functions
-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;
}
-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, bool compress) // Writes SWF to file, returns length or <0 if fails
{ U32 len;
TAG * t;
+ struct writer_t zwriter;
if (!swf) return -1;
#ifdef INSERT_RFX_TAG
- if (swf_NextTag(swf->firstTag))
+ 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);
swf->frameCount = 0;
while(t)
- { len += swf_WriteTag(-1,t);
+ { len += swf_WriteTag(-1, t);
if (t->id==ST_SHOWFRAME) swf->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,0); // 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;
+ }
+ swf->fileSize = l+len;
+
+ if(compress) {
+ 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(compress) {
+ writer_init_zlibdeflate(&zwriter, writer);
+ writer = &zwriter;
+ }
+
swf_SetRect(&t1,&swf->movieSize);
swf_SetU16(&t1,swf->frameRate);
swf_SetU16(&t1,swf->frameCount);
- l = swf_GetDataSize(&t1);
- swf->fileSize = l+len;
- 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;
+ if(handle<0)
+ return swf_WriteSWF2(&writer, swf, FALSE);
+ writer_init_filewriter(&writer, handle);
+ return swf_WriteSWF2(&writer, swf, FALSE);
+}
+
+int swf_WriteSWC(int handle, SWF * swf) // Writes SWF to file, returns length or <0 if fails
+{
+ struct writer_t writer;
+ if(handle<0)
+ return swf_WriteSWF2(&writer, swf, TRUE);
+ writer_init_filewriter(&writer, handle);
+ return swf_WriteSWF2(&writer, swf, TRUE);
+}
+
+
+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];
// 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"
-
-#else
-
#include "modules/swfdump.c"
#include "modules/swfshape.c"
#include "modules/swftext.c"
#include "modules/swfcgi.c"
#include "modules/swfbits.c"
#include "modules/swfaction.c"
-
-#endif
-
+#include "modules/swfsound.c"