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 * NextTag(TAG * t) { return t->next; }
52 TAG * PrevTag(TAG * t) { return t->prev; }
53 int GetFrameNo(TAG * t) { return t->frame; }
54 U16 GetTagID(TAG * t) { return t->id; }
55 U32 GetDataSize(TAG * t) { return t->len; }
56 U8* GetDataSizePtr(TAG * t) { return &(t->data[t->len]); }
57 U32 GetTagPos(TAG * t) { return t->pos; }
59 // Basic Data Access Functions
61 #define ResetBitmask(tag) if (tag->bitmask) { tag->pos++; tag->bitmask = 0; }
62 #define ResetBitcount(tag) if (tag->bitcount) { tag->bitcount = 0; }
64 // for future purpose: avoid high level lib functions to change tagpos/bitcount
66 #define SaveTagPos(tag)
67 #define RestoreTagPos(tag)
69 void SetTagPos(TAG * t,U32 pos)
71 if (pos<=t->len) t->pos = pos;
73 else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
81 { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
85 return t->data[t->pos++];
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);
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 GetBlock(TAG * t,U8 * b,int l)
118 // returns number of bytes written (<=l)
119 // b = NULL -> skip data
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 SetBlock(TAG * t,U8 * b,int l)
128 // Appends Block to the end of Tagdata, returns size
129 { U32 newlen = t->len + l;
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 SetU8(TAG * t,U8 v)
152 if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1;
153 t->data[t->len++] = v;
157 int SetU16(TAG * t,U16 v)
163 if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1;
164 t->data[t->len++] = a[0];
165 t->data[t->len++] = a[1];
169 int SetU32(TAG * t,U32 v)
171 a[0] = v&0xff; // to ensure correct handling of non-intel byteorder
177 if ((t->len+4)>t->memsize) return (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 GetBits(TAG * t,int nbits)
187 if (!nbits) return 0;
188 if (!t->bitmask) t->bitmask = 0x80;
191 if (t->data[t->pos]&t->bitmask) res|=1;
195 { if (nbits) t->bitmask = 0x80;
198 { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);
208 S32 GetSBits(TAG * t,int nbits)
209 { U32 res = GetBits(t,nbits);
210 if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
214 int SetBits(TAG * t,U32 v,int nbits)
215 { U32 bm = 1<<(nbits-1);
219 { if (FAILED(SetU8(t,0))) return -1;
222 if (v&bm) t->data[t->len-1] |= t->bitcount;
230 // Advanced Data Access Functions
232 int SetRGB(TAG * t,RGBA * col)
238 } else SetBlock(t,NULL,3);
242 int SetRGBA(TAG * t,RGBA * col)
249 } else SetBlock(t,NULL,4);
253 int CountBits(U32 v,int nbits)
271 return (n>nbits)?n:nbits;
274 int GetRect(TAG * t,SRECT * r)
278 nbits = (int) GetBits(t,5);
279 r->xmin = GetSBits(t,nbits);
280 r->xmax = GetSBits(t,nbits);
281 r->ymin = GetSBits(t,nbits);
282 r->ymax = GetSBits(t,nbits);
286 int SetRect(TAG * t,SRECT * r)
289 nbits = CountBits(r->xmin,0);
290 nbits = CountBits(r->xmax,nbits);
291 nbits = CountBits(r->ymin,nbits);
292 nbits = CountBits(r->ymax,nbits);
295 SetBits(t,r->xmin,nbits);
296 SetBits(t,r->xmax,nbits);
297 SetBits(t,r->ymin,nbits);
298 SetBits(t,r->ymax,nbits);
303 int GetMatrix(TAG * t,MATRIX * m)
310 { m->sx = m->sy = 0x10000;
319 { nbits = GetBits(t,5);
320 m->sx = GetSBits(t,nbits);
321 m->sy = GetSBits(t,nbits);
323 else m->sx = m->sy = 0x10000;
326 { nbits = GetBits(t,5);
327 m->r0 = GetSBits(t,nbits);
328 m->r1 = GetSBits(t,nbits);
330 else m->r0 = m->r1 = 0x0;
332 nbits = GetBits(t,5);
333 m->tx = GetSBits(t,nbits);
334 m->ty = GetSBits(t,nbits);
339 int SetMatrix(TAG * t,MATRIX * m)
345 ma.sx = ma.sy = 0x10000;
352 if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1);
355 nbits = CountBits(m->sx,0);
356 nbits = CountBits(m->sy,nbits);
358 SetBits(t,m->sx,nbits);
359 SetBits(t,m->sy,nbits);
362 if ((!m->r0)&&(!m->r1)) SetBits(t,0,1);
365 nbits = CountBits(m->r0,0);
366 nbits = CountBits(m->r1,nbits);
368 SetBits(t,m->r0,nbits);
369 SetBits(t,m->r1,nbits);
372 nbits = CountBits(m->tx,0);
373 nbits = CountBits(m->ty,nbits);
375 SetBits(t,m->tx,nbits);
376 SetBits(t,m->ty,nbits);
381 int 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;
395 hasadd = GetBits(t,1);
396 hasmul = GetBits(t,1);
397 nbits = GetBits(t,4);
400 { cx->r0 = (S16)GetSBits(t,nbits);
401 cx->g0 = (S16)GetSBits(t,nbits);
402 cx->b0 = (S16)GetSBits(t,nbits);
404 cx->a0 = (S16)GetSBits(t,nbits);
408 { cx->r1 = (S16)GetSBits(t,nbits);
409 cx->g1 = (S16)GetSBits(t,nbits);
410 cx->b1 = (S16)GetSBits(t,nbits);
412 cx->a1 = (S16)GetSBits(t,nbits);
418 int 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 = CountBits((S32)cx->a0,nbits);
442 nbits = CountBits((S32)cx->r0,nbits);
443 nbits = CountBits((S32)cx->g0,nbits);
444 nbits = CountBits((S32)cx->b0,nbits);
448 { if (alpha) nbits = CountBits((S32)cx->a1,nbits);
449 nbits = CountBits((S32)cx->r1,nbits);
450 nbits = CountBits((S32)cx->g1,nbits);
451 nbits = CountBits((S32)cx->b1,nbits);
455 SetBits(t,hasadd?1:0,1);
456 SetBits(t,hasmul?1:0,1);
460 { SetBits(t,cx->r0,nbits);
461 SetBits(t,cx->g0,nbits);
462 SetBits(t,cx->b0,nbits);
463 if (alpha) SetBits(t,cx->a0,nbits);
467 { SetBits(t,cx->r1,nbits);
468 SetBits(t,cx->g1,nbits);
469 SetBits(t,cx->b1,nbits);
470 if (alpha) SetBits(t,cx->a1,nbits);
476 int GetPoint(TAG * t,SPOINT * p) { return 0; }
477 int 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 UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)
494 TAG * 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) UpdateFrame(t->next,+1);
516 int DeleteTag(TAG * t)
519 if (t->id==ST_SHOWFRAME) 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 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)?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 DefineSprite_GetRealSize(TAG * t)
641 // Sprite Handling: Helper function to pack DefineSprite-Tag
645 if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);
647 } while (t&&(t->id!=ST_END));
651 #define ReadTag(a,b) RFXSWF_ReadTag(a,b)
652 #define WriteTag(a,b) RFXSWF_WriteTag(a,b)
656 int 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 (GetU8(&t1)!=(U8)'F') return -1;
671 if (GetU8(&t1)!=(U8)'W') return -1;
672 if (GetU8(&t1)!=(U8)'S') return -1;
674 swf->FileVersion = GetU8(&t1);
675 swf->FileSize = GetU32(&t1);
676 GetRect(&t1,&swf->MovieSize);
677 swf->FrameRate = GetU16(&t1);
678 swf->FrameCount = GetU16(&t1);
681 lseek(handle,GetTagPos(&t1)-1,SEEK_SET);
683 // reda tags and connect to list
685 while (t) t = ReadTag(handle,t);
686 swf->FirstTag = t1.next;
687 t1.next->prev = NULL;
692 int WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or <0 if fails
700 #ifdef INSERT_RFX_TAG
702 if (NextTag(swf->FirstTag))
703 if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX)
704 SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3);
706 #endif // INSERT_RFX_TAG
708 // Count Frames + File Size
715 { len += WriteTag(-1,t);
716 if (t->id==ST_SHOWFRAME) swf->FrameCount++;
724 memset(&t1,0x00,sizeof(TAG));
731 SetU8(&t1,swf->FileVersion);
733 SetU32(&t1,0); // Keep space for filesize
734 SetRect(&t1,&swf->MovieSize);
735 SetU16(&t1,swf->FrameRate);
736 SetU16(&t1,swf->FrameCount);
738 l = GetDataSize(&t1);
739 swf->FileSize = l+len;
740 t1.len = 4; // bad & ugly trick !
741 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 (WriteTag(handle,t)<0) return -1;
763 return (int)swf->FileSize;
766 int WriteCGI(SWF * swf)
770 len = 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 WriteSWF(fileno(stdout),swf);
784 void 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"
810 #include "modules/swfdump.c"
811 #include "modules/swfshape.c"
812 #include "modules/swftext.c"
813 #include "modules/swfobject.c"
814 #include "modules/swfbutton.c"
815 #include "modules/swftools.c"
816 #include "modules/swfcgi.c"
817 #include "modules/swfbits.c"