3 Library for creating and reading SWF files or parts of it.
4 There's a module directory which provides some extended functionality.
5 Most modules are included at the bottom of this file.
7 Part of the swftools package.
9 Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
11 This file is distributed under the GPL, see file COPYING for details
20 #define _JPEGLIB_INCLUDED_
21 #endif // HAVE_JPEGLIB_H
22 #endif // HAVE_LIBJPEG
27 #define _ZLIB_INCLUDED_
31 // Win32 support may be broken since it was only tested in an older version for Watcom C
44 #define MALLOC_SIZE 128
45 #define INSERT_RFX_TAG
47 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
49 // inline wrapper functions
51 TAG * swf_NextTag(TAG * t) { return t->next; }
52 TAG * swf_PrevTag(TAG * t) { return t->prev; }
53 int swf_GetFrameNo(TAG * t) { return t->frame; }
54 U16 swf_GetTagID(TAG * t) { return t->id; }
55 U32 swf_GetDataSize(TAG * t) { return t->len; }
56 U8* swf_GetDataSizePtr(TAG * t) { return &(t->data[t->len]); }
57 U32 swf_GetTagPos(TAG * t) { return t->pos; }
59 // Basic Data Access Functions
61 #define swf_ResetReadBits(tag) if (tag->readBit) { tag->pos++; tag->readBit = 0; }
62 #define swf_ResetWriteBits(tag) if (tag->writeBit) { tag->writeBit = 0; }
64 // for future purpose: avoid high level lib functions to change tagpos/bitpos
66 #define swf_SaveTagPos(tag)
67 #define swf_RestoreTagPos(tag)
69 void swf_SetTagPos(TAG * t,U32 pos)
70 { swf_ResetReadBits(t);
71 if (pos<=t->len) t->pos = pos;
73 else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
78 { swf_ResetReadBits(t);
81 { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
85 return t->data[t->pos++];
88 U16 swf_GetU16(TAG * t)
92 if (t->pos>(t->len-2))
93 { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);
97 res = t->data[t->pos] | (t->data[t->pos+1]<<8);
102 U32 swf_GetU32(TAG * t)
104 swf_ResetReadBits(t);
106 if (t->pos>(t->len-4))
107 { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);
111 res = t->data[t->pos] | (t->data[t->pos+1]<<8) |
112 (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);
117 int swf_GetBlock(TAG * t,U8 * b,int l)
118 // returns number of bytes written (<=l)
119 // b = NULL -> skip data
120 { swf_ResetReadBits(t);
121 if ((t->len-t->pos)<l) l=t->len-t->pos;
122 if (b && l) memcpy(b,&t->data[t->pos],l);
127 int swf_SetBlock(TAG * t,U8 * b,int l)
128 // Appends Block to the end of Tagdata, returns size
129 { U32 newlen = t->len + l;
130 swf_ResetWriteBits(t);
131 if (newlen>t->memsize)
132 { U32 newmem = MEMSIZE(newlen);
133 U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));
137 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
144 if (b) memcpy(&t->data[t->len],b,l);
145 else memset(&t->data[t->len],0x00,l);
150 int swf_SetU8(TAG * t,U8 v)
151 { swf_ResetWriteBits(t);
152 if ((t->len+1)>t->memsize) return (swf_SetBlock(t,&v,1)==1)?0:-1;
153 t->data[t->len++] = v;
157 int swf_SetU16(TAG * t,U16 v)
162 swf_ResetWriteBits(t);
163 if ((t->len+2)>t->memsize) return (swf_SetBlock(t,a,2)==2)?0:-1;
164 t->data[t->len++] = a[0];
165 t->data[t->len++] = a[1];
169 int swf_SetU32(TAG * t,U32 v)
171 a[0] = v&0xff; // to ensure correct handling of non-intel byteorder
176 swf_ResetWriteBits(t);
177 if ((t->len+4)>t->memsize) return (swf_SetBlock(t,a,4)==4)?0:-1;
178 t->data[t->len++] = a[0];
179 t->data[t->len++] = a[1];
180 t->data[t->len++] = a[2];
181 t->data[t->len++] = a[3];
185 U32 swf_GetBits(TAG * t,int nbits)
187 if (!nbits) return 0;
188 if (!t->readBit) t->readBit = 0x80;
191 if (t->data[t->pos]&t->readBit) res|=1;
195 { if (nbits) t->readBit = 0x80;
198 { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);
208 S32 swf_GetSBits(TAG * t,int nbits)
209 { U32 res = swf_GetBits(t,nbits);
210 if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
214 int swf_SetBits(TAG * t,U32 v,int nbits)
215 { U32 bm = 1<<(nbits-1);
219 { if (FAILED(swf_SetU8(t,0))) return -1;
222 if (v&bm) t->data[t->len-1] |= t->writeBit;
230 // Advanced Data Access Functions
232 int swf_SetRGB(TAG * t,RGBA * col)
235 { swf_SetU8(t,col->r);
238 } else swf_SetBlock(t,NULL,3);
242 int swf_SetRGBA(TAG * t,RGBA * col)
245 { swf_SetU8(t,col->r);
249 } else swf_SetBlock(t,NULL,4);
253 int swf_CountBits(U32 v,int nbits)
271 return (n>nbits)?n:nbits;
274 int swf_GetRect(TAG * t,SRECT * r)
278 nbits = (int) swf_GetBits(t,5);
279 r->xmin = swf_GetSBits(t,nbits);
280 r->xmax = swf_GetSBits(t,nbits);
281 r->ymin = swf_GetSBits(t,nbits);
282 r->ymax = swf_GetSBits(t,nbits);
286 int swf_SetRect(TAG * t,SRECT * r)
289 nbits = swf_CountBits(r->xmin,0);
290 nbits = swf_CountBits(r->xmax,nbits);
291 nbits = swf_CountBits(r->ymin,nbits);
292 nbits = swf_CountBits(r->ymax,nbits);
294 swf_SetBits(t,nbits,5);
295 swf_SetBits(t,r->xmin,nbits);
296 swf_SetBits(t,r->xmax,nbits);
297 swf_SetBits(t,r->ymin,nbits);
298 swf_SetBits(t,r->ymax,nbits);
303 int swf_GetMatrix(TAG * t,MATRIX * m)
310 { m->sx = m->sy = 0x10000;
316 swf_ResetReadBits(t);
318 if (swf_GetBits(t,1))
319 { nbits = swf_GetBits(t,5);
320 m->sx = swf_GetSBits(t,nbits);
321 m->sy = swf_GetSBits(t,nbits);
323 else m->sx = m->sy = 0x10000;
325 if (swf_GetBits(t,1))
326 { nbits = swf_GetBits(t,5);
327 m->r0 = swf_GetSBits(t,nbits);
328 m->r1 = swf_GetSBits(t,nbits);
330 else m->r0 = m->r1 = 0x0;
332 nbits = swf_GetBits(t,5);
333 m->tx = swf_GetSBits(t,nbits);
334 m->ty = swf_GetSBits(t,nbits);
339 int swf_SetMatrix(TAG * t,MATRIX * m)
345 ma.sx = ma.sy = 0x10000;
350 swf_ResetWriteBits(t);
352 if ((m->sx==0x10000)&&(m->sy==0x10000)) swf_SetBits(t,0,1);
354 { swf_SetBits(t,1,1);
355 nbits = swf_CountBits(m->sx,0);
356 nbits = swf_CountBits(m->sy,nbits);
357 swf_SetBits(t,nbits,5);
358 swf_SetBits(t,m->sx,nbits);
359 swf_SetBits(t,m->sy,nbits);
362 if ((!m->r0)&&(!m->r1)) swf_SetBits(t,0,1);
364 { swf_SetBits(t,1,1);
365 nbits = swf_CountBits(m->r0,0);
366 nbits = swf_CountBits(m->r1,nbits);
367 swf_SetBits(t,nbits,5);
368 swf_SetBits(t,m->r0,nbits);
369 swf_SetBits(t,m->r1,nbits);
372 nbits = swf_CountBits(m->tx,0);
373 nbits = swf_CountBits(m->ty,nbits);
374 swf_SetBits(t,nbits,5);
375 swf_SetBits(t,m->tx,nbits);
376 swf_SetBits(t,m->ty,nbits);
381 int swf_GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool
389 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
390 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
394 swf_ResetReadBits(t);
395 hasadd = swf_GetBits(t,1);
396 hasmul = swf_GetBits(t,1);
397 nbits = swf_GetBits(t,4);
400 { cx->r0 = (S16)swf_GetSBits(t,nbits);
401 cx->g0 = (S16)swf_GetSBits(t,nbits);
402 cx->b0 = (S16)swf_GetSBits(t,nbits);
404 cx->a0 = (S16)swf_GetSBits(t,nbits);
408 { cx->r1 = (S16)swf_GetSBits(t,nbits);
409 cx->g1 = (S16)swf_GetSBits(t,nbits);
410 cx->b1 = (S16)swf_GetSBits(t,nbits);
412 cx->a1 = (S16)swf_GetSBits(t,nbits);
418 int swf_SetCXForm(TAG * t,CXFORM * cx,U8 alpha)
426 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
427 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
437 hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);
438 hasadd = cx->a1|cx->r1|cx->g1|cx->b1;
441 { if (alpha) nbits = swf_CountBits((S32)cx->a0,nbits);
442 nbits = swf_CountBits((S32)cx->r0,nbits);
443 nbits = swf_CountBits((S32)cx->g0,nbits);
444 nbits = swf_CountBits((S32)cx->b0,nbits);
448 { if (alpha) nbits = swf_CountBits((S32)cx->a1,nbits);
449 nbits = swf_CountBits((S32)cx->r1,nbits);
450 nbits = swf_CountBits((S32)cx->g1,nbits);
451 nbits = swf_CountBits((S32)cx->b1,nbits);
454 swf_ResetWriteBits(t);
455 swf_SetBits(t,hasadd?1:0,1);
456 swf_SetBits(t,hasmul?1:0,1);
457 swf_SetBits(t,nbits,4);
460 { swf_SetBits(t,cx->r0,nbits);
461 swf_SetBits(t,cx->g0,nbits);
462 swf_SetBits(t,cx->b0,nbits);
463 if (alpha) swf_SetBits(t,cx->a0,nbits);
467 { swf_SetBits(t,cx->r1,nbits);
468 swf_SetBits(t,cx->g1,nbits);
469 swf_SetBits(t,cx->b1,nbits);
470 if (alpha) swf_SetBits(t,cx->a1,nbits);
476 int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
477 int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
479 // Tag List Manipulating Functions
481 int RFXSWF_UpdateFrame(TAG * t,S8 delta)
482 // returns number of frames
492 #define swf_UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)
494 TAG * swf_InsertTag(TAG * after,U16 id) // updates frames, if nescessary
497 t = (TAG *)malloc(sizeof(TAG));
499 { memset(t,0x00,sizeof(TAG));
504 { t->frame = after->frame;
506 t->next = after->next;
508 if (t->next) t->next->prev = t;
510 if (id==ST_SHOWFRAME) swf_UpdateFrame(t->next,+1);
516 int swf_DeleteTag(TAG * t)
519 if (t->id==ST_SHOWFRAME) swf_UpdateFrame(t->next,-1);
521 if (t->prev) t->prev->next = t->next;
522 if (t->next) t->next->prev = t->prev;
524 if (t->data) free(t->data);
529 TAG * RFXSWF_ReadTag(int handle,TAG * prev)
535 if (read(handle,&raw,2)!=2) return NULL;
541 { if (read(handle,&len,4)!=4) return NULL;
544 if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);
545 // Sprite handling fix: Flaten sprite tree
547 t = (TAG *)malloc(sizeof(TAG));
552 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
557 memset(t,0x00,sizeof(TAG));
563 { t->data = (U8*)malloc(t->len);
567 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
572 if (read(handle,t->data,t->len)!=t->len) return NULL;
576 { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);
584 int RFXSWF_DefineSprite_GetRealSize(TAG * t);
586 int RFXSWF_WriteTag(int handle,TAG * t)
587 // returns tag length in bytes (incl. Header), -1 = Error
588 // handle = -1 -> no output
595 len = (t->id==ST_DEFINESPRITE)?RFXSWF_DefineSprite_GetRealSize(t):t->len;
597 short_tag = len<0x3f;
601 { raw[0] = len|((t->id&0x3ff)<<6);
602 if (write(handle,raw,2)!=2)
605 fprintf(stderr,"WriteTag() failed: Short Header.\n");
611 { raw[0] = (t->id<<6)|0x3f;
612 raw[1] = (U16)(len&0xffff);
613 raw[2] = (U16)(len>>16);
614 if (write(handle,raw,6)!=6)
617 fprintf(stderr,"WriteTag() failed: Long Header.\n");
624 { if (write(handle,t->data,t->len)!=t->len)
627 fprintf(stderr,"WriteTag() failed: Data.\n");
633 else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);
637 return t->len+(short_tag?2:6);
640 int RFXSWF_DefineSprite_GetRealSize(TAG * t)
641 // Sprite Handling: Helper function to pack DefineSprite-Tag
644 { t = swf_NextTag(t);
645 if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);
647 } while (t&&(t->id!=ST_END));
651 #define swf_ReadTag(a,b) RFXSWF_ReadTag(a,b)
652 #define swf_WriteTag(a,b) RFXSWF_WriteTag(a,b)
656 int swf_ReadSWF(int handle,SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
659 memset(swf,0x00,sizeof(SWF));
661 { char b[32]; // read Header
665 memset(&t1,0x00,sizeof(TAG));
667 if ((t1.len=read(handle,b,32))<21) return -1;
670 if (swf_GetU8(&t1)!=(U8)'F') return -1;
671 if (swf_GetU8(&t1)!=(U8)'W') return -1;
672 if (swf_GetU8(&t1)!=(U8)'S') return -1;
674 swf->fileVersion = swf_GetU8(&t1);
675 swf->fileSize = swf_GetU32(&t1);
676 swf_GetRect(&t1,&swf->movieSize);
677 swf->frameRate = swf_GetU16(&t1);
678 swf->frameCount = swf_GetU16(&t1);
681 lseek(handle,swf_GetTagPos(&t1)-1,SEEK_SET);
683 // reda tags and connect to list
685 while (t) t = swf_ReadTag(handle,t);
686 swf->firstTag = t1.next;
687 t1.next->prev = NULL;
692 int swf_WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or <0 if fails
700 #ifdef INSERT_RFX_TAG
702 if (swf_NextTag(swf->firstTag))
703 if (swf_GetTagID(swf_NextTag(swf->firstTag))!=ST_REFLEX)
704 swf_SetBlock(swf_InsertTag(swf->firstTag,ST_REFLEX),"rfx",3);
706 #endif // INSERT_RFX_TAG
708 // Count Frames + File Size
715 { len += swf_WriteTag(-1,t);
716 if (t->id==ST_SHOWFRAME) swf->frameCount++;
724 memset(&t1,0x00,sizeof(TAG));
731 swf_SetU8(&t1,swf->fileVersion);
733 swf_SetU32(&t1,0); // Keep space for filesize
734 swf_SetRect(&t1,&swf->movieSize);
735 swf_SetU16(&t1,swf->frameRate);
736 swf_SetU16(&t1,swf->frameCount);
738 l = swf_GetDataSize(&t1);
739 swf->fileSize = l+len;
740 t1.len = 4; // bad & ugly trick !
741 swf_SetU32(&t1,swf->fileSize);
745 int ret = write(handle,b,l);
749 printf("ret:%d (fd:%d)\n",ret, handle);
751 fprintf(stderr,"WriteSWF() failed: Header.\n");
758 { if (swf_WriteTag(handle,t)<0) return -1;
763 return (int)swf->fileSize;
766 int WriteCGI(SWF * swf)
770 len = swf_WriteSWF(-1,swf);
772 if (len<0) return -1;
774 sprintf(s,"Content-type: application/x-shockwave-flash\n"
775 "Accept-Ranges: bytes\n"
776 "Content-Length: %lu\n"
777 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
780 write(fileno(stdout),s,strlen(s));
781 return swf_WriteSWF(fileno(stdout),swf);
784 void swf_FreeTags(SWF * swf) // Frees all malloc'ed memory for tags
785 { TAG * t = swf->firstTag;
788 { TAG * tnew = t->next;
789 if (t->data) free(t->data);
795 // include advanced functions
799 #include "modules\swfdump.c"
800 #include "modules\swfshape.c"
801 #include "modules\swftext.c"
802 #include "modules\swfobject.c"
803 #include "modules\swfbutton.c"
804 #include "modules\swftools.c"
805 #include "modules\swfcgi.c"
806 #include "modules\swfbits.c"
807 #include "modules\swfaction.c"
811 #include "modules/swfdump.c"
812 #include "modules/swfshape.c"
813 #include "modules/swftext.c"
814 #include "modules/swfobject.c"
815 #include "modules/swfbutton.c"
816 #include "modules/swftools.c"
817 #include "modules/swfcgi.c"
818 #include "modules/swfbits.c"
819 #include "modules/swfaction.c"