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
21 #define _JPEGLIB_INCLUDED_
22 #endif // HAVE_JPEGLIB_H
23 #endif // HAVE_LIBJPEG
28 #define _ZLIB_INCLUDED_
32 // Win32 support may be broken since it was only tested in an older version for Watcom C
45 #define MALLOC_SIZE 128
46 #define INSERT_RFX_TAG
48 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
50 // inline wrapper functions
52 TAG * swf_NextTag(TAG * t) { return t->next; }
53 TAG * swf_PrevTag(TAG * t) { return t->prev; }
54 int swf_GetFrameNo(TAG * t) { return t->frame; }
55 U16 swf_GetTagID(TAG * t) { return t->id; }
56 U32 swf_GetTagLen(TAG * t) { return t->len; }
57 U8* swf_GetTagLenPtr(TAG * t) { return &(t->data[t->len]); }
58 U32 swf_GetTagPos(TAG * t) { return t->pos; }
60 // Basic Data Access Functions
62 #define swf_ResetReadBits(tag) if (tag->readBit) { tag->pos++; tag->readBit = 0; }
63 #define swf_ResetWriteBits(tag) if (tag->writeBit) { tag->writeBit = 0; }
65 // for future purpose: avoid high level lib functions to change tagpos/bitpos
67 #define swf_SaveTagPos(tag)
68 #define swf_RestoreTagPos(tag)
70 void swf_SetTagPos(TAG * t,U32 pos)
71 { swf_ResetReadBits(t);
72 if (pos<=t->len) t->pos = pos;
74 else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
79 { swf_ResetReadBits(t);
82 { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
86 return t->data[t->pos++];
89 U16 swf_GetU16(TAG * t)
93 if (t->pos>(t->len-2))
94 { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);
98 res = t->data[t->pos] | (t->data[t->pos+1]<<8);
103 U32 swf_GetU32(TAG * t)
105 swf_ResetReadBits(t);
107 if (t->pos>(t->len-4))
108 { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);
112 res = t->data[t->pos] | (t->data[t->pos+1]<<8) |
113 (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);
118 int swf_GetBlock(TAG * t,U8 * b,int l)
119 // returns number of bytes written (<=l)
120 // b = NULL -> skip data
121 { swf_ResetReadBits(t);
122 if ((t->len-t->pos)<l) l=t->len-t->pos;
123 if (b && l) memcpy(b,&t->data[t->pos],l);
128 int swf_SetBlock(TAG * t,U8 * b,int l)
129 // Appends Block to the end of Tagdata, returns size
130 { U32 newlen = t->len + l;
131 swf_ResetWriteBits(t);
132 if (newlen>t->memsize)
133 { U32 newmem = MEMSIZE(newlen);
134 U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));
138 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
145 if (b) memcpy(&t->data[t->len],b,l);
146 else memset(&t->data[t->len],0x00,l);
151 int swf_SetU8(TAG * t,U8 v)
152 { swf_ResetWriteBits(t);
153 if ((t->len+1)>t->memsize) return (swf_SetBlock(t,&v,1)==1)?0:-1;
154 t->data[t->len++] = v;
158 int swf_SetU16(TAG * t,U16 v)
163 swf_ResetWriteBits(t);
164 if ((t->len+2)>t->memsize) return (swf_SetBlock(t,a,2)==2)?0:-1;
165 t->data[t->len++] = a[0];
166 t->data[t->len++] = a[1];
170 int swf_SetU32(TAG * t,U32 v)
172 a[0] = v&0xff; // to ensure correct handling of non-intel byteorder
177 swf_ResetWriteBits(t);
178 if ((t->len+4)>t->memsize) return (swf_SetBlock(t,a,4)==4)?0:-1;
179 t->data[t->len++] = a[0];
180 t->data[t->len++] = a[1];
181 t->data[t->len++] = a[2];
182 t->data[t->len++] = a[3];
186 U32 swf_GetBits(TAG * t,int nbits)
188 if (!nbits) return 0;
189 if (!t->readBit) t->readBit = 0x80;
192 if (t->data[t->pos]&t->readBit) res|=1;
196 { if (nbits) t->readBit = 0x80;
199 { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);
209 S32 swf_GetSBits(TAG * t,int nbits)
210 { U32 res = swf_GetBits(t,nbits);
211 if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
215 int swf_SetBits(TAG * t,U32 v,int nbits)
216 { U32 bm = 1<<(nbits-1);
220 { if (FAILED(swf_SetU8(t,0))) return -1;
223 if (v&bm) t->data[t->len-1] |= t->writeBit;
231 // Advanced Data Access Functions
233 int swf_SetRGB(TAG * t,RGBA * col)
236 { swf_SetU8(t,col->r);
239 } else swf_SetBlock(t,NULL,3);
243 int swf_SetRGBA(TAG * t,RGBA * col)
246 { swf_SetU8(t,col->r);
250 } else swf_SetBlock(t,NULL,4);
254 int swf_CountBits(U32 v,int nbits)
272 return (n>nbits)?n:nbits;
275 int swf_GetRect(TAG * t,SRECT * r)
279 nbits = (int) swf_GetBits(t,5);
280 r->xmin = swf_GetSBits(t,nbits);
281 r->xmax = swf_GetSBits(t,nbits);
282 r->ymin = swf_GetSBits(t,nbits);
283 r->ymax = swf_GetSBits(t,nbits);
287 int swf_SetRect(TAG * t,SRECT * r)
290 nbits = swf_CountBits(r->xmin,0);
291 nbits = swf_CountBits(r->xmax,nbits);
292 nbits = swf_CountBits(r->ymin,nbits);
293 nbits = swf_CountBits(r->ymax,nbits);
295 swf_SetBits(t,nbits,5);
296 swf_SetBits(t,r->xmin,nbits);
297 swf_SetBits(t,r->xmax,nbits);
298 swf_SetBits(t,r->ymin,nbits);
299 swf_SetBits(t,r->ymax,nbits);
304 int swf_GetMatrix(TAG * t,MATRIX * m)
311 { m->sx = m->sy = 0x10000;
317 swf_ResetReadBits(t);
319 if (swf_GetBits(t,1))
320 { nbits = swf_GetBits(t,5);
321 m->sx = swf_GetSBits(t,nbits);
322 m->sy = swf_GetSBits(t,nbits);
324 else m->sx = m->sy = 0x10000;
326 if (swf_GetBits(t,1))
327 { nbits = swf_GetBits(t,5);
328 m->r0 = swf_GetSBits(t,nbits);
329 m->r1 = swf_GetSBits(t,nbits);
331 else m->r0 = m->r1 = 0x0;
333 nbits = swf_GetBits(t,5);
334 m->tx = swf_GetSBits(t,nbits);
335 m->ty = swf_GetSBits(t,nbits);
340 int swf_SetMatrix(TAG * t,MATRIX * m)
346 ma.sx = ma.sy = 0x10000;
351 swf_ResetWriteBits(t);
353 if ((m->sx==0x10000)&&(m->sy==0x10000)) swf_SetBits(t,0,1);
355 { swf_SetBits(t,1,1);
356 nbits = swf_CountBits(m->sx,0);
357 nbits = swf_CountBits(m->sy,nbits);
359 fprintf(stderr,"rfxswf: Error: matrix values too large\n");
362 swf_SetBits(t,nbits,5);
363 swf_SetBits(t,m->sx,nbits);
364 swf_SetBits(t,m->sy,nbits);
367 if ((!m->r0)&&(!m->r1)) swf_SetBits(t,0,1);
369 { swf_SetBits(t,1,1);
370 nbits = swf_CountBits(m->r0,0);
371 nbits = swf_CountBits(m->r1,nbits);
373 fprintf(stderr,"rfxswf: Error: matrix values too large\n");
376 swf_SetBits(t,nbits,5);
377 swf_SetBits(t,m->r0,nbits);
378 swf_SetBits(t,m->r1,nbits);
381 nbits = swf_CountBits(m->tx,0);
382 nbits = swf_CountBits(m->ty,nbits);
384 fprintf(stderr,"rfxswf: Error: matrix values too large\n");
387 swf_SetBits(t,nbits,5);
388 swf_SetBits(t,m->tx,nbits);
389 swf_SetBits(t,m->ty,nbits);
394 int swf_GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool
402 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
403 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
407 swf_ResetReadBits(t);
408 hasadd = swf_GetBits(t,1);
409 hasmul = swf_GetBits(t,1);
410 nbits = swf_GetBits(t,4);
413 { cx->r0 = (S16)swf_GetSBits(t,nbits);
414 cx->g0 = (S16)swf_GetSBits(t,nbits);
415 cx->b0 = (S16)swf_GetSBits(t,nbits);
417 cx->a0 = (S16)swf_GetSBits(t,nbits);
421 { cx->r1 = (S16)swf_GetSBits(t,nbits);
422 cx->g1 = (S16)swf_GetSBits(t,nbits);
423 cx->b1 = (S16)swf_GetSBits(t,nbits);
425 cx->a1 = (S16)swf_GetSBits(t,nbits);
431 int swf_SetCXForm(TAG * t,CXFORM * cx,U8 alpha)
439 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
440 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
450 hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);
451 hasadd = cx->a1|cx->r1|cx->g1|cx->b1;
454 { if (alpha) nbits = swf_CountBits((S32)cx->a0,nbits);
455 nbits = swf_CountBits((S32)cx->r0,nbits);
456 nbits = swf_CountBits((S32)cx->g0,nbits);
457 nbits = swf_CountBits((S32)cx->b0,nbits);
461 { if (alpha) nbits = swf_CountBits((S32)cx->a1,nbits);
462 nbits = swf_CountBits((S32)cx->r1,nbits);
463 nbits = swf_CountBits((S32)cx->g1,nbits);
464 nbits = swf_CountBits((S32)cx->b1,nbits);
467 swf_ResetWriteBits(t);
468 swf_SetBits(t,hasadd?1:0,1);
469 swf_SetBits(t,hasmul?1:0,1);
470 swf_SetBits(t,nbits,4);
473 { swf_SetBits(t,cx->r0,nbits);
474 swf_SetBits(t,cx->g0,nbits);
475 swf_SetBits(t,cx->b0,nbits);
476 if (alpha) swf_SetBits(t,cx->a0,nbits);
480 { swf_SetBits(t,cx->r1,nbits);
481 swf_SetBits(t,cx->g1,nbits);
482 swf_SetBits(t,cx->b1,nbits);
483 if (alpha) swf_SetBits(t,cx->a1,nbits);
489 int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
490 int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
492 // Tag List Manipulating Functions
494 int RFXSWF_UpdateFrame(TAG * t,S8 delta)
495 // returns number of frames
505 #define swf_UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)
507 TAG * swf_InsertTag(TAG * after,U16 id) // updates frames, if nescessary
510 t = (TAG *)malloc(sizeof(TAG));
512 { memset(t,0x00,sizeof(TAG));
516 { t->frame = after->frame;
518 t->next = after->next;
520 if (t->next) t->next->prev = t;
522 if (id==ST_SHOWFRAME) swf_UpdateFrame(t->next,+1);
528 int swf_DeleteTag(TAG * t)
531 if (t->id==ST_SHOWFRAME) swf_UpdateFrame(t->next,-1);
533 if (t->prev) t->prev->next = t->next;
534 if (t->next) t->next->prev = t->prev;
536 if (t->data) free(t->data);
541 TAG * RFXSWF_ReadTag(int handle,TAG * prev)
547 if (read(handle,&raw,2)!=2) return NULL;
555 if (read(handle,&len,4)!=4) return NULL;
559 if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);
560 // Sprite handling fix: Flaten sprite tree
562 t = (TAG *)malloc(sizeof(TAG));
567 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
572 memset(t,0x00,sizeof(TAG));
578 { t->data = (U8*)malloc(t->len);
582 fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
587 if (read(handle,t->data,t->len)!=t->len) return NULL;
591 { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);
599 int RFXSWF_DefineSprite_GetRealSize(TAG * t);
601 int RFXSWF_WriteTag(int handle,TAG * t)
602 // returns tag length in bytes (incl. Header), -1 = Error
603 // handle = -1 -> no output
610 len = (t->id==ST_DEFINESPRITE)?RFXSWF_DefineSprite_GetRealSize(t):t->len;
612 short_tag = len<0x3f;
616 { raw[0] = SWAP16(len|((t->id&0x3ff)<<6));
617 if (write(handle,raw,2)!=2)
620 fprintf(stderr,"WriteTag() failed: Short Header.\n");
627 raw[0] = SWAP16((t->id<<6)|0x3f);
628 if (write(handle,raw,2)!=2)
631 fprintf(stderr,"WriteTag() failed: Long Header (1).\n");
637 if (write(handle,&len,4)!=4)
640 fprintf(stderr,"WriteTag() failed: Long Header (2).\n");
647 { if (write(handle,t->data,t->len)!=t->len)
650 fprintf(stderr,"WriteTag() failed: Data.\n");
656 else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);
660 return t->len+(short_tag?2:6);
663 int RFXSWF_DefineSprite_GetRealSize(TAG * t)
664 // Sprite Handling: Helper function to pack DefineSprite-Tag
667 { t = swf_NextTag(t);
668 if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);
670 } while (t&&(t->id!=ST_END));
674 #define swf_ReadTag(a,b) RFXSWF_ReadTag(a,b)
675 #define swf_WriteTag(a,b) RFXSWF_WriteTag(a,b)
679 int swf_ReadSWF(int handle,SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
682 memset(swf,0x00,sizeof(SWF));
684 { char b[32]; // read Header
688 memset(&t1,0x00,sizeof(TAG));
690 if ((t1.len=read(handle,b,32))<21) return -1;
693 if (swf_GetU8(&t1)!=(U8)'F') return -1;
694 if (swf_GetU8(&t1)!=(U8)'W') return -1;
695 if (swf_GetU8(&t1)!=(U8)'S') return -1;
697 swf->fileVersion = swf_GetU8(&t1);
698 swf->fileSize = swf_GetU32(&t1);
699 swf_GetRect(&t1,&swf->movieSize);
700 swf->frameRate = swf_GetU16(&t1);
701 swf->frameCount = swf_GetU16(&t1);
704 lseek(handle,swf_GetTagPos(&t1)-1,SEEK_SET);
706 // reda tags and connect to list
708 while (t) t = swf_ReadTag(handle,t);
709 swf->firstTag = t1.next;
710 t1.next->prev = NULL;
715 int swf_WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or <0 if fails
723 #ifdef INSERT_RFX_TAG
725 if (swf_NextTag(swf->firstTag))
726 if (swf_GetTagID(swf_NextTag(swf->firstTag))!=ST_REFLEX)
727 swf_SetBlock(swf_InsertTag(swf->firstTag,ST_REFLEX),"rfx",3);
729 #endif // INSERT_RFX_TAG
731 // Count Frames + File Size
738 { len += swf_WriteTag(-1,t);
739 if (t->id==ST_SHOWFRAME) swf->frameCount++;
747 memset(&t1,0x00,sizeof(TAG));
754 swf_SetU8(&t1,swf->fileVersion);
756 swf_SetU32(&t1,0); // Keep space for filesize
757 swf_SetRect(&t1,&swf->movieSize);
758 swf_SetU16(&t1,swf->frameRate);
759 swf_SetU16(&t1,swf->frameCount);
761 l = swf_GetTagLen(&t1);
762 swf->fileSize = l+len;
763 t1.len = 4; // bad & ugly trick !
764 swf_SetU32(&t1,swf->fileSize);
768 int ret = write(handle,b,l);
772 printf("ret:%d (fd:%d)\n",ret, handle);
774 fprintf(stderr,"WriteSWF() failed: Header.\n");
781 { if (swf_WriteTag(handle,t)<0) return -1;
786 return (int)swf->fileSize;
789 int swf_WriteCGI(SWF * swf)
793 len = swf_WriteSWF(-1,swf);
795 if (len<0) return -1;
797 sprintf(s,"Content-type: application/x-shockwave-flash\n"
798 "Accept-Ranges: bytes\n"
799 "Content-Length: %lu\n"
800 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
803 write(fileno(stdout),s,strlen(s));
804 return swf_WriteSWF(fileno(stdout),swf);
807 void swf_FreeTags(SWF * swf) // Frees all malloc'ed memory for tags
808 { TAG * t = swf->firstTag;
811 { TAG * tnew = t->next;
812 if (t->data) free(t->data);
818 // include advanced functions
822 #include "modules\swfdump.c"
823 #include "modules\swfshape.c"
824 #include "modules\swftext.c"
825 #include "modules\swfobject.c"
826 #include "modules\swfbutton.c"
827 #include "modules\swftools.c"
828 #include "modules\swfcgi.c"
829 #include "modules\swfbits.c"
830 #include "modules\swfaction.c"
834 #include "modules/swfdump.c"
835 #include "modules/swfshape.c"
836 #include "modules/swftext.c"
837 #include "modules/swfobject.c"
838 #include "modules/swfbutton.c"
839 #include "modules/swftools.c"
840 #include "modules/swfcgi.c"
841 #include "modules/swfbits.c"
842 #include "modules/swfaction.c"