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
24 // Win32 support may be broken since it was only tested in an older version for Watcom C
37 #define MALLOC_SIZE 128
38 #define INSERT_RFX_TAG
40 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
42 // inline wrapper functions
44 TAG * NextTag(TAG * t) { return t->next; }
45 TAG * PrevTag(TAG * t) { return t->prev; }
46 int GetFrameNo(TAG * t) { return t->frame; }
47 U16 GetTagID(TAG * t) { return t->id; }
48 U32 GetDataSize(TAG * t) { return t->len; }
49 U8* GetDataSizePtr(TAG * t) { return &(t->data[t->len]); }
50 U32 GetTagPos(TAG * t) { return t->pos; }
52 // Basic Data Access Functions
54 #define ResetBitmask(tag) if (tag->bitmask) { tag->pos++; tag->bitmask = 0; }
55 #define ResetBitcount(tag) if (tag->bitcount) { tag->bitcount = 0; }
57 // for future purpose: avoid high level lib functions to change tagpos/bitcount
59 #define SaveTagPos(tag)
60 #define RestoreTagPos(tag)
62 void SetTagPos(TAG * t,U32 pos)
64 if (pos<=t->len) t->pos = pos;
66 else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
74 { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
78 return t->data[t->pos++];
85 if (t->pos>(t->len-2))
86 { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);
90 res = t->data[t->pos] | (t->data[t->pos+1]<<8);
99 if (t->pos>(t->len-4))
100 { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);
104 res = t->data[t->pos] | (t->data[t->pos+1]<<8) |
105 (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);
110 int GetBlock(TAG * t,U8 * b,int l)
111 // returns number of bytes written (<=l)
112 // b = NULL -> skip data
114 if ((t->len-t->pos)<l) l=t->len-t->pos;
115 if (b && l) memcpy(b,&t->data[t->pos],l);
120 int SetBlock(TAG * t,U8 * b,int l)
121 // Appends Block to the end of Tagdata, returns size
122 { U32 newlen = t->len + l;
124 if (newlen>t->memsize)
125 { U32 newmem = MEMSIZE(newlen);
126 U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));
130 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
137 if (b) memcpy(&t->data[t->len],b,l);
138 else memset(&t->data[t->len],0x00,l);
143 int SetU8(TAG * t,U8 v)
145 if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1;
146 t->data[t->len++] = v;
150 int SetU16(TAG * t,U16 v)
156 if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1;
157 t->data[t->len++] = a[0];
158 t->data[t->len++] = a[1];
162 int SetU32(TAG * t,U32 v)
164 a[0] = v&0xff; // to ensure correct handling of non-intel byteorder
170 if ((t->len+4)>t->memsize) return (SetBlock(t,a,4)==4)?0:-1;
171 t->data[t->len++] = a[0];
172 t->data[t->len++] = a[1];
173 t->data[t->len++] = a[2];
174 t->data[t->len++] = a[3];
178 U32 GetBits(TAG * t,int nbits)
180 if (!nbits) return 0;
181 if (!t->bitmask) t->bitmask = 0x80;
184 if (t->data[t->pos]&t->bitmask) res|=1;
188 { if (nbits) t->bitmask = 0x80;
191 { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);
201 S32 GetSBits(TAG * t,int nbits)
202 { U32 res = GetBits(t,nbits);
203 if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
207 int SetBits(TAG * t,U32 v,int nbits)
208 { U32 bm = 1<<(nbits-1);
212 { if (FAILED(SetU8(t,0))) return -1;
215 if (v&bm) t->data[t->len-1] |= t->bitcount;
223 // Advanced Data Access Functions
225 int SetRGB(TAG * t,RGBA * col)
231 } else SetBlock(t,NULL,3);
235 int SetRGBA(TAG * t,RGBA * col)
242 } else SetBlock(t,NULL,4);
246 int CountBits(U32 v,int nbits)
264 return (n>nbits)?n:nbits;
267 int GetRect(TAG * t,SRECT * r)
271 nbits = (int) GetBits(t,5);
272 r->xmin = GetSBits(t,nbits);
273 r->xmax = GetSBits(t,nbits);
274 r->ymin = GetSBits(t,nbits);
275 r->ymax = GetSBits(t,nbits);
279 int SetRect(TAG * t,SRECT * r)
282 nbits = CountBits(r->xmin,0);
283 nbits = CountBits(r->xmax,nbits);
284 nbits = CountBits(r->ymin,nbits);
285 nbits = CountBits(r->ymax,nbits);
288 SetBits(t,r->xmin,nbits);
289 SetBits(t,r->xmax,nbits);
290 SetBits(t,r->ymin,nbits);
291 SetBits(t,r->ymax,nbits);
296 int GetMatrix(TAG * t,MATRIX * m)
303 { m->sx = m->sy = 0x10000;
312 { nbits = GetBits(t,5);
313 m->sx = GetSBits(t,nbits);
314 m->sy = GetSBits(t,nbits);
316 else m->sx = m->sy = 0x10000;
319 { nbits = GetBits(t,5);
320 m->r0 = GetSBits(t,nbits);
321 m->r1 = GetSBits(t,nbits);
323 else m->r0 = m->r1 = 0x0;
325 nbits = GetBits(t,5);
326 m->tx = GetSBits(t,nbits);
327 m->ty = GetSBits(t,nbits);
332 int SetMatrix(TAG * t,MATRIX * m)
338 ma.sx = ma.sy = 0x10000;
345 if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1);
348 nbits = CountBits(m->sx,0);
349 nbits = CountBits(m->sy,nbits);
351 SetBits(t,m->sx,nbits);
352 SetBits(t,m->sy,nbits);
355 if ((!m->r0)&&(!m->r1)) SetBits(t,0,1);
358 nbits = CountBits(m->r0,0);
359 nbits = CountBits(m->r1,nbits);
361 SetBits(t,m->r0,nbits);
362 SetBits(t,m->r1,nbits);
365 nbits = CountBits(m->tx,0);
366 nbits = CountBits(m->ty,nbits);
368 SetBits(t,m->tx,nbits);
369 SetBits(t,m->ty,nbits);
374 int GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool
382 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
383 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
388 hasadd = GetBits(t,1);
389 hasmul = GetBits(t,1);
390 nbits = GetBits(t,4);
393 { cx->r0 = (S16)GetSBits(t,nbits);
394 cx->g0 = (S16)GetSBits(t,nbits);
395 cx->b0 = (S16)GetSBits(t,nbits);
397 cx->a0 = (S16)GetSBits(t,nbits);
401 { cx->r1 = (S16)GetSBits(t,nbits);
402 cx->g1 = (S16)GetSBits(t,nbits);
403 cx->b1 = (S16)GetSBits(t,nbits);
405 cx->a1 = (S16)GetSBits(t,nbits);
411 int SetCXForm(TAG * t,CXFORM * cx,U8 alpha)
419 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
420 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
430 hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);
431 hasadd = cx->a1|cx->r1|cx->g1|cx->b1;
434 { if (alpha) nbits = CountBits((S32)cx->a0,nbits);
435 nbits = CountBits((S32)cx->r0,nbits);
436 nbits = CountBits((S32)cx->g0,nbits);
437 nbits = CountBits((S32)cx->b0,nbits);
441 { if (alpha) nbits = CountBits((S32)cx->a1,nbits);
442 nbits = CountBits((S32)cx->r1,nbits);
443 nbits = CountBits((S32)cx->g1,nbits);
444 nbits = CountBits((S32)cx->b1,nbits);
448 SetBits(t,hasadd?1:0,1);
449 SetBits(t,hasmul?1:0,1);
453 { SetBits(t,cx->r0,nbits);
454 SetBits(t,cx->g0,nbits);
455 SetBits(t,cx->b0,nbits);
456 if (alpha) SetBits(t,cx->a0,nbits);
460 { SetBits(t,cx->r1,nbits);
461 SetBits(t,cx->g1,nbits);
462 SetBits(t,cx->b1,nbits);
463 if (alpha) SetBits(t,cx->a1,nbits);
469 int GetPoint(TAG * t,SPOINT * p) { return 0; }
470 int SetPoint(TAG * t,SPOINT * p) { return 0; }
472 // Tag List Manipulating Functions
474 int RFXSWF_UpdateFrame(TAG * t,S8 delta)
475 // returns number of frames
485 #define UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)
487 TAG * InsertTag(TAG * after,U16 id) // updates frames, if nescessary
490 t = (TAG *)malloc(sizeof(TAG));
492 { memset(t,0x00,sizeof(TAG));
497 { t->frame = after->frame;
499 t->next = after->next;
501 if (t->next) t->next->prev = t;
503 if (id==ST_SHOWFRAME) UpdateFrame(t->next,+1);
509 int DeleteTag(TAG * t)
512 if (t->id==ST_SHOWFRAME) UpdateFrame(t->next,-1);
514 if (t->prev) t->prev->next = t->next;
515 if (t->next) t->next->prev = t->prev;
517 if (t->data) free(t->data);
522 TAG * RFXSWF_ReadTag(int handle,TAG * prev)
528 if (read(handle,&raw,2)!=2) return NULL;
534 { if (read(handle,&len,4)!=4) return NULL;
537 if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);
538 // Sprite handling fix: Flaten sprite tree
540 t = (TAG *)malloc(sizeof(TAG));
545 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
550 memset(t,0x00,sizeof(TAG));
556 { t->data = (U8*)malloc(t->len);
560 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
565 if (read(handle,t->data,t->len)!=t->len) return NULL;
569 { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);
577 int DefineSprite_GetRealSize(TAG * t);
579 int RFXSWF_WriteTag(int handle,TAG * t)
580 // returns tag length in bytes (incl. Header), -1 = Error
581 // handle = -1 -> no output
588 len = (t->id==ST_DEFINESPRITE)?DefineSprite_GetRealSize(t):t->len;
590 short_tag = len<0x3f;
594 { raw[0] = len|((t->id&0x3ff)<<6);
595 if (write(handle,raw,2)!=2)
598 fprintf(stderr,"WriteTag() failed: Short Header.\n");
604 { raw[0] = (t->id<<6)|0x3f;
605 raw[1] = (U16)(len&0xffff);
606 raw[2] = (U16)(len>>16);
607 if (write(handle,raw,6)!=6)
610 fprintf(stderr,"WriteTag() failed: Long Header.\n");
617 { if (write(handle,t->data,t->len)!=t->len)
620 fprintf(stderr,"WriteTag() failed: Data.\n");
626 else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);
630 return t->len+(short_tag?2:6);
633 int DefineSprite_GetRealSize(TAG * t)
634 // Sprite Handling: Helper function to pack DefineSprite-Tag
638 if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);
640 } while (t&&(t->id!=ST_END));
644 #define ReadTag(a,b) RFXSWF_ReadTag(a,b)
645 #define WriteTag(a,b) RFXSWF_WriteTag(a,b)
649 int ReadSWF(int handle,SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
652 memset(swf,0x00,sizeof(SWF));
654 { char b[32]; // Header lesen
658 memset(&t1,0x00,sizeof(TAG));
660 if ((t1.len=read(handle,b,32))<21) return -1;
663 if (GetU8(&t1)!=(U8)'F') return -1;
664 if (GetU8(&t1)!=(U8)'W') return -1;
665 if (GetU8(&t1)!=(U8)'S') return -1;
667 swf->FileVersion = GetU8(&t1);
668 swf->FileSize = GetU32(&t1);
669 GetRect(&t1,&swf->MovieSize);
670 swf->FrameRate = GetU16(&t1);
671 swf->FrameCount = GetU16(&t1);
674 lseek(handle,GetTagPos(&t1)-1,SEEK_SET);
676 // Tags lesen und verketten
678 while (t) t = ReadTag(handle,t);
679 swf->FirstTag = t1.next;
680 t1.next->prev = NULL;
685 int WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or <0 if fails
693 #ifdef INSERT_RFX_TAG
695 if (NextTag(swf->FirstTag))
696 if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX)
697 SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3);
699 #endif // INSERT_RFX_TAG
701 // Count Frames + File Size
708 { len += WriteTag(-1,t);
709 if (t->id==ST_SHOWFRAME) swf->FrameCount++;
717 memset(&t1,0x00,sizeof(TAG));
724 SetU8(&t1,swf->FileVersion);
726 SetU32(&t1,0); // Keep space for filesize
727 SetRect(&t1,&swf->MovieSize);
728 SetU16(&t1,swf->FrameRate);
729 SetU16(&t1,swf->FrameCount);
731 l = GetDataSize(&t1);
732 swf->FileSize = l+len;
733 t1.len = 4; // bad & ugly trick !
734 SetU32(&t1,swf->FileSize);
738 int ret = write(handle,b,l);
742 printf("ret:%d (fd:%d)\n",ret, handle);
744 fprintf(stderr,"WriteSWF() failed: Header.\n");
751 { if (WriteTag(handle,t)<0) return -1;
756 return (int)swf->FileSize;
759 int WriteCGI(SWF * swf)
763 len = WriteSWF(-1,swf);
765 if (len<0) return -1;
767 sprintf(s,"Content-type: application/x-shockwave-flash\n"
768 "Accept-Ranges: bytes\n"
769 "Content-Length: %lu\n"
770 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
773 write(fileno(stdout),s,strlen(s));
774 return WriteSWF(fileno(stdout),swf);
777 void FreeTags(SWF * swf) // Frees all malloc'ed memory for tags
778 { TAG * t = swf->FirstTag;
781 { TAG * tnew = t->next;
782 if (t->data) free(t->data);
788 // include advanced functions
792 #include "modules\swfdump.c"
793 #include "modules\swfshape.c"
794 #include "modules\swftext.c"
795 #include "modules\swfobject.c"
796 #include "modules\swfbutton.c"
797 #include "modules\swftools.c"
798 #include "modules\swfcgi.c"
799 #include "modules\swfbits.c"
803 #include "modules/swfdump.c"
804 #include "modules/swfshape.c"
805 #include "modules/swftext.c"
806 #include "modules/swfobject.c"
807 #include "modules/swfbutton.c"
808 #include "modules/swftools.c"
809 #include "modules/swfcgi.c"
810 #include "modules/swfbits.c"