1 /* vi: set sts=2 sw=2 :*/
5 Library for creating and reading SWF files or parts of it.
6 There's a module directory which provides some extended functionality.
7 Most modules are included at the bottom of this file.
9 Part of the swftools package.
11 Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
13 This file is distributed under the GPL, see file COPYING for details
23 #define _JPEGLIB_INCLUDED_
24 #endif // HAVE_JPEGLIB_H
25 #endif // HAVE_LIBJPEG
32 #include "lame/lame.h"
38 #define MALLOC_SIZE 128
39 #define INSERT_RFX_TAG
41 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
44 // inline wrapper functions
46 TAG * swf_NextTag(TAG * t) { return t->next; }
47 TAG * swf_PrevTag(TAG * t) { return t->prev; }
48 int swf_GetFrameNo(TAG * t) { return t->frame; }
49 U16 swf_GetTagID(TAG * t) { return t->id; }
50 U32 swf_GetTagLen(TAG * t) { return t->len; }
51 U8* swf_GetTagLenPtr(TAG * t) { return &(t->data[t->len]); }
52 U32 swf_GetTagPos(TAG * t) { return t->pos; }
54 // Basic Data Access Functions
56 #define swf_ResetReadBits(tag) if (tag->readBit) { tag->pos++; tag->readBit = 0; }
57 #define swf_ResetWriteBits(tag) if (tag->writeBit) { tag->writeBit = 0; }
59 // for future purpose: avoid high level lib functions to change tagpos/bitpos
61 #define swf_SaveTagPos(tag)
62 #define swf_RestoreTagPos(tag)
64 void swf_SetTagPos(TAG * t,U32 pos)
65 { swf_ResetReadBits(t);
66 if (pos<=t->len) t->pos = pos;
68 else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
72 char* swf_GetString(TAG*t)
74 char* str = ((char*)(&(t)->data[(t)->pos]));
80 { swf_ResetReadBits(t);
83 { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
87 return t->data[t->pos++];
90 U16 swf_GetU16(TAG * t)
94 if (t->pos>(t->len-2))
95 { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);
99 res = t->data[t->pos] | (t->data[t->pos+1]<<8);
104 U32 swf_GetU32(TAG * t)
106 swf_ResetReadBits(t);
108 if (t->pos>(t->len-4))
109 { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);
113 res = t->data[t->pos] | (t->data[t->pos+1]<<8) |
114 (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);
119 int swf_GetBlock(TAG * t,U8 * b,int l)
120 // returns number of bytes written (<=l)
121 // b = NULL -> skip data
122 { swf_ResetReadBits(t);
123 if ((t->len-t->pos)<l) l=t->len-t->pos;
124 if (b && l) memcpy(b,&t->data[t->pos],l);
129 int swf_SetBlock(TAG * t,U8 * b,int l)
130 // Appends Block to the end of Tagdata, returns size
131 { U32 newlen = t->len + l;
132 swf_ResetWriteBits(t);
133 if (newlen>t->memsize)
134 { U32 newmem = MEMSIZE(newlen);
135 U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));
139 fprintf(stderr,"Fatal Error: malloc()/realloc() failed (1). (%d bytes)\n", newmem);
147 if (b) memcpy(&t->data[t->len],b,l);
148 else memset(&t->data[t->len],0x00,l);
153 int swf_SetU8(TAG * t,U8 v)
154 { swf_ResetWriteBits(t);
155 if ((t->len+1)>t->memsize) return (swf_SetBlock(t,&v,1)==1)?0:-1;
156 t->data[t->len++] = v;
160 int swf_SetU16(TAG * t,U16 v)
165 swf_ResetWriteBits(t);
166 if ((t->len+2)>t->memsize) return (swf_SetBlock(t,a,2)==2)?0:-1;
167 t->data[t->len++] = a[0];
168 t->data[t->len++] = a[1];
172 int swf_SetU32(TAG * t,U32 v)
174 a[0] = v&0xff; // to ensure correct handling of non-intel byteorder
179 swf_ResetWriteBits(t);
180 if ((t->len+4)>t->memsize) return (swf_SetBlock(t,a,4)==4)?0:-1;
181 t->data[t->len++] = a[0];
182 t->data[t->len++] = a[1];
183 t->data[t->len++] = a[2];
184 t->data[t->len++] = a[3];
188 U32 swf_GetBits(TAG * t,int nbits)
190 if (!nbits) return 0;
191 if (!t->readBit) t->readBit = 0x80;
194 if (t->data[t->pos]&t->readBit) res|=1;
198 { if (nbits) t->readBit = 0x80;
201 { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);
211 S32 swf_GetSBits(TAG * t,int nbits)
212 { U32 res = swf_GetBits(t,nbits);
213 if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
217 U32 reader_GetBits(struct reader_t*reader, int nbits)
218 { return reader_readbits(reader, nbits);
220 S32 reader_GetSBits(struct reader_t*reader, int nbits)
221 { U32 res = reader_readbits(reader, nbits);
222 if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
226 int swf_SetBits(TAG * t,U32 v,int nbits)
227 { U32 bm = 1<<(nbits-1);
231 { if (FAILED(swf_SetU8(t,0))) return -1;
234 if (v&bm) t->data[t->len-1] |= t->writeBit;
242 // Advanced Data Access Functions
244 int swf_SetRGB(TAG * t,RGBA * col)
247 { swf_SetU8(t,col->r);
250 } else swf_SetBlock(t,NULL,3);
253 void swf_GetRGB(TAG * t, RGBA * col)
258 col->r = swf_GetU8(t);
259 col->g = swf_GetU8(t);
260 col->b = swf_GetU8(t);
264 int swf_SetRGBA(TAG * t,RGBA * col)
267 { swf_SetU8(t,col->r);
271 } else swf_SetBlock(t,NULL,4);
274 void swf_GetRGBA(TAG * t, RGBA * col)
279 col->r = swf_GetU8(t);
280 col->g = swf_GetU8(t);
281 col->b = swf_GetU8(t);
282 col->a = swf_GetU8(t);
285 void swf_GetGradient(TAG * tag, GRADIENT * gradient, char alpha)
291 gradient->num = swf_GetU8(tag);
292 for(t=0;t<gradient->num;t++)
297 gradient->ratios[t] = swf_GetU8(tag);
299 swf_GetRGB(tag, &gradient->rgba[t]);
301 swf_GetRGBA(tag, &gradient->rgba[t]);
305 int swf_CountBits(U32 v,int nbits)
323 return (n>nbits)?n:nbits;
326 int swf_GetRect(TAG * t,SRECT * r)
329 if(!t) {r->xmin=r->xmax=r->ymin=r->ymax=0;return 0;}
331 nbits = (int) swf_GetBits(t,5);
332 r->xmin = swf_GetSBits(t,nbits);
333 r->xmax = swf_GetSBits(t,nbits);
334 r->ymin = swf_GetSBits(t,nbits);
335 r->ymax = swf_GetSBits(t,nbits);
339 int reader_GetRect(struct reader_t*reader,SRECT * r)
343 nbits = (int) reader_GetBits(reader,5);
344 r->xmin = reader_GetSBits(reader,nbits);
345 r->xmax = reader_GetSBits(reader,nbits);
346 r->ymin = reader_GetSBits(reader,nbits);
347 r->ymax = reader_GetSBits(reader,nbits);
351 int swf_SetRect(TAG * t,SRECT * r)
354 nbits = swf_CountBits(r->xmin,0);
355 nbits = swf_CountBits(r->xmax,nbits);
356 nbits = swf_CountBits(r->ymin,nbits);
357 nbits = swf_CountBits(r->ymax,nbits);
359 fprintf(stderr, "rfxswf: Warning: num_bits overflow in swf_SetRect\n");
363 swf_SetBits(t,nbits,5);
364 swf_SetBits(t,r->xmin,nbits);
365 swf_SetBits(t,r->xmax,nbits);
366 swf_SetBits(t,r->ymin,nbits);
367 swf_SetBits(t,r->ymax,nbits);
372 void swf_ExpandRect(SRECT*src, SPOINT add)
374 if(add.x < src->xmin)
376 if(add.x > src->xmax)
378 if(add.y < src->ymin)
380 if(add.y > src->ymax)
383 void swf_ExpandRect2(SRECT*src, SRECT*add)
385 if((add->xmin | add->ymin | add->xmax | add->ymax)==0)
387 if(add->xmin < src->xmin)
388 src->xmin = add->xmin;
389 if(add->ymin < src->ymin)
390 src->ymin = add->ymin;
391 if(add->xmax > src->xmax)
392 src->xmax = add->xmax;
393 if(add->ymax > src->ymax)
394 src->ymax = add->ymax;
396 SPOINT swf_TurnPoint(SPOINT p, MATRIX* m)
399 r.x = (int)(m->sx*(1/65536.0)*p.x + m->r1*(1/65536.0)*p.y + 0.5) + m->tx;
400 r.y = (int)(m->r0*(1/65536.0)*p.x + m->sy*(1/65536.0)*p.y + 0.5) + m->ty;
403 SRECT swf_TurnRect(SRECT r, MATRIX* m)
406 SPOINT p1,p2,p3,p4,pp1,pp2,pp3,pp4;
407 p1.x = r.xmin;p1.y = r.ymin;
408 p2.x = r.xmax;p2.y = r.ymin;
409 p3.x = r.xmin;p3.y = r.ymax;
410 p4.x = r.xmax;p4.y = r.ymax;
411 pp1 = swf_TurnPoint(p1, m);
412 pp2 = swf_TurnPoint(p2, m);
413 pp3 = swf_TurnPoint(p3, m);
414 pp4 = swf_TurnPoint(p4, m);
415 g.xmin = g.xmax = pp1.x;
416 g.ymin = g.ymax = pp1.y;
417 swf_ExpandRect(&g, pp2);
418 swf_ExpandRect(&g, pp3);
419 swf_ExpandRect(&g, pp4);
424 int swf_GetMatrix(TAG * t,MATRIX * m)
431 { m->sx = m->sy = 0x10000;
437 swf_ResetReadBits(t);
439 if (swf_GetBits(t,1))
440 { nbits = swf_GetBits(t,5);
441 m->sx = swf_GetSBits(t,nbits);
442 m->sy = swf_GetSBits(t,nbits);
444 else m->sx = m->sy = 0x10000;
446 if (swf_GetBits(t,1))
447 { nbits = swf_GetBits(t,5);
448 m->r0 = swf_GetSBits(t,nbits);
449 m->r1 = swf_GetSBits(t,nbits);
451 else m->r0 = m->r1 = 0x0;
453 nbits = swf_GetBits(t,5);
454 m->tx = swf_GetSBits(t,nbits);
455 m->ty = swf_GetSBits(t,nbits);
460 int swf_SetMatrix(TAG * t,MATRIX * m)
466 ma.sx = ma.sy = 0x10000;
471 swf_ResetWriteBits(t);
473 if ((m->sx==0x10000)&&(m->sy==0x10000)) swf_SetBits(t,0,1);
475 { swf_SetBits(t,1,1);
476 nbits = swf_CountBits(m->sx,0);
477 nbits = swf_CountBits(m->sy,nbits);
479 fprintf(stderr,"rfxswf: Error: matrix values too large\n");
482 swf_SetBits(t,nbits,5);
483 swf_SetBits(t,m->sx,nbits);
484 swf_SetBits(t,m->sy,nbits);
487 if ((!m->r0)&&(!m->r1)) swf_SetBits(t,0,1);
489 { swf_SetBits(t,1,1);
490 nbits = swf_CountBits(m->r0,0);
491 nbits = swf_CountBits(m->r1,nbits);
493 fprintf(stderr,"rfxswf: Error: matrix values too large\n");
496 swf_SetBits(t,nbits,5);
497 swf_SetBits(t,m->r0,nbits);
498 swf_SetBits(t,m->r1,nbits);
501 nbits = swf_CountBits(m->tx,0);
502 nbits = swf_CountBits(m->ty,nbits);
504 fprintf(stderr,"rfxswf: Error: matrix values too large\n");
507 swf_SetBits(t,nbits,5);
508 swf_SetBits(t,m->tx,nbits);
509 swf_SetBits(t,m->ty,nbits);
514 int swf_GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool
522 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
523 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
527 swf_ResetReadBits(t);
528 hasadd = swf_GetBits(t,1);
529 hasmul = swf_GetBits(t,1);
530 nbits = swf_GetBits(t,4);
533 { cx->r0 = (S16)swf_GetSBits(t,nbits);
534 cx->g0 = (S16)swf_GetSBits(t,nbits);
535 cx->b0 = (S16)swf_GetSBits(t,nbits);
537 cx->a0 = (S16)swf_GetSBits(t,nbits);
541 { cx->r1 = (S16)swf_GetSBits(t,nbits);
542 cx->g1 = (S16)swf_GetSBits(t,nbits);
543 cx->b1 = (S16)swf_GetSBits(t,nbits);
545 cx->a1 = (S16)swf_GetSBits(t,nbits);
551 int swf_SetCXForm(TAG * t,CXFORM * cx,U8 alpha)
559 cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
560 cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
570 hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);
571 hasadd = cx->a1|cx->r1|cx->g1|cx->b1;
574 { if (alpha) nbits = swf_CountBits((S32)cx->a0,nbits);
575 nbits = swf_CountBits((S32)cx->r0,nbits);
576 nbits = swf_CountBits((S32)cx->g0,nbits);
577 nbits = swf_CountBits((S32)cx->b0,nbits);
581 { if (alpha) nbits = swf_CountBits((S32)cx->a1,nbits);
582 nbits = swf_CountBits((S32)cx->r1,nbits);
583 nbits = swf_CountBits((S32)cx->g1,nbits);
584 nbits = swf_CountBits((S32)cx->b1,nbits);
587 swf_ResetWriteBits(t);
588 swf_SetBits(t,hasadd?1:0,1);
589 swf_SetBits(t,hasmul?1:0,1);
590 swf_SetBits(t,nbits,4);
593 { swf_SetBits(t,cx->r0,nbits);
594 swf_SetBits(t,cx->g0,nbits);
595 swf_SetBits(t,cx->b0,nbits);
596 if (alpha) swf_SetBits(t,cx->a0,nbits);
600 { swf_SetBits(t,cx->r1,nbits);
601 swf_SetBits(t,cx->g1,nbits);
602 swf_SetBits(t,cx->b1,nbits);
603 if (alpha) swf_SetBits(t,cx->a1,nbits);
609 int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
610 int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
612 // Tag List Manipulating Functions
614 int swf_UpdateFrame(TAG * t,S8 delta)
615 // returns number of frames
625 TAG * swf_InsertTag(TAG * after,U16 id) // updates frames, if nescessary
628 t = (TAG *)malloc(sizeof(TAG));
630 { memset(t,0x00,sizeof(TAG));
634 { t->frame = after->frame;
636 t->next = after->next;
638 if (t->next) t->next->prev = t;
640 if (id==ST_SHOWFRAME) swf_UpdateFrame(t->next,+1);
646 void swf_ClearTag(TAG * t)
648 if (t->data) free(t->data);
657 int swf_DeleteTag(TAG * t)
660 if (t->id==ST_SHOWFRAME) swf_UpdateFrame(t->next,-1);
662 if (t->prev) t->prev->next = t->next;
663 if (t->next) t->next->prev = t->prev;
665 if (t->data) free(t->data);
670 TAG * swf_ReadTag(struct reader_t*reader, TAG * prev)
676 if (reader->read(reader, &raw, 2) !=2 ) return NULL;
684 if (reader->read(reader, &len, 4) != 4) return NULL;
688 if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);
689 // Sprite handling fix: Flaten sprite tree
691 t = (TAG *)malloc(sizeof(TAG));
696 fprintf(stderr,"Fatal Error: malloc()/realloc() failed (2). (%d bytes)\n", sizeof(TAG));
701 memset(t,0x00,sizeof(TAG));
707 { t->data = (U8*)malloc(t->len);
711 fprintf(stderr,"Fatal Error: malloc()/realloc() failed (3). (%d bytes)\n", t->len);
716 if (reader->read(reader, t->data, t->len) != t->len) return NULL;
720 { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);
728 int swf_DefineSprite_GetRealSize(TAG * t);
730 int swf_WriteTag2(struct writer_t*writer, TAG * t)
731 // returns tag length in bytes (incl. Header), -1 = Error
732 // writer = 0 -> no output
739 len = (t->id==ST_DEFINESPRITE)?swf_DefineSprite_GetRealSize(t):t->len;
741 short_tag = len<0x3f;
745 { raw[0] = SWAP16(len|((t->id&0x3ff)<<6));
746 if (writer->write(writer,raw,2)!=2)
749 fprintf(stderr,"WriteTag() failed: Short Header.\n");
756 raw[0] = SWAP16((t->id<<6)|0x3f);
757 if (writer->write(writer,raw,2)!=2)
760 fprintf(stderr,"WriteTag() failed: Long Header (1).\n");
766 if (writer->write(writer,&len,4)!=4)
769 fprintf(stderr,"WriteTag() failed: Long Header (2).\n");
776 { if (writer->write(writer,t->data,t->len)!=t->len)
779 fprintf(stderr,"WriteTag() failed: Data.\n");
785 else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);
789 return t->len+(short_tag?2:6);
792 int swf_WriteTag(int handle, TAG * t)
794 struct writer_t writer;
796 return swf_WriteTag2(0, t);
797 writer_init_filewriter(&writer, handle);
798 return swf_WriteTag2(&writer, t);
801 int swf_DefineSprite_GetRealSize(TAG * t)
802 // Sprite Handling: Helper function to pack DefineSprite-Tag
804 if(len>4) { // folded sprite
808 { t = swf_NextTag(t);
809 if (t && t->id!=ST_DEFINESPRITE) len += swf_WriteTag(-1, t);
811 } while (t&&(t->id!=ST_END));
815 void swf_UnFoldSprite(TAG * t)
820 U16 spriteid,spriteframes;
822 if(t->id!=ST_DEFINESPRITE)
824 if(t->len<=4) // not folded
829 spriteid = swf_GetU16(t); //id
830 spriteframes = swf_GetU16(t); //frames
842 if(id == ST_DEFINESPRITE && len<=4)
847 it = swf_InsertTag(next, id);
852 { it->data = (U8*)malloc(it->len);
853 it->memsize = it->len;
854 swf_GetBlock(t, it->data, it->len);
861 free(t->data); t->data = 0;
862 t->memsize = t->len = t->pos = 0;
864 swf_SetU16(t, spriteid);
865 swf_SetU16(t, spriteframes);
868 void swf_FoldSprite(TAG * t)
873 if(t->id!=ST_DEFINESPRITE)
876 fprintf(stderr, "Error: Sprite has no ID!");
880 /* sprite is already folded */
887 t->len = t->pos = t->memsize = 0;
892 t = swf_NextTag(sprtag);
897 if(t->id==ST_SHOWFRAME) frames++;
898 if(t->id == ST_DEFINESPRITE && t->len<=4)
905 fprintf(stderr, "rfxswf error: sprite doesn't end(1)\n");
907 swf_SetU16(sprtag, id);
908 swf_SetU16(sprtag, frames);
910 t = swf_NextTag(sprtag);
916 swf_SetU16(sprtag,t->len|(t->id<<6));
918 swf_SetU16(sprtag,0x3f|(t->id<<6));
919 swf_SetU32(sprtag,t->len);
922 swf_SetBlock(sprtag,t->data, t->len);
924 if(t->id == ST_DEFINESPRITE && t->len<=4)
933 fprintf(stderr, "rfxswf error: sprite doesn't end(2)\n");
939 int swf_IsFolded(TAG * t)
941 return (t->id == ST_DEFINESPRITE && t->len>4);
944 void swf_FoldAll(SWF*swf)
946 TAG*tag = swf->firstTag;
948 if(tag->id == ST_DEFINESPRITE)
950 tag = swf_NextTag(tag);
954 void swf_UnFoldAll(SWF*swf)
956 TAG*tag = swf->firstTag;
958 if(tag->id == ST_DEFINESPRITE)
959 swf_UnFoldSprite(tag);
964 void swf_OptimizeTagOrder(SWF*swf)
971 /* at the moment, we don't actually do optimizing,
972 only fixing of non-spec-conformant things like
982 if(tag->id == ST_DEFINESPRITE) {
984 /* ??? all sprites are supposed to be unfolded */
985 fprintf(stderr, "librfxswf error - internal error in OptimizeTagOrder/UnfoldAll\n");
995 /* move non-sprite tags out of sprite */
996 if(!swf_isAllowedSpriteTag(tag) || level>=2) {
997 /* remove tag from current position */
998 tag->prev->next = tag->next;
1000 tag->next->prev = tag->prev;
1002 /* insert before tag level0 */
1004 tag->prev = level0->prev;
1006 tag->prev->next = tag;
1010 if(tag->id == ST_END) {
1021 int swf_ReadSWF2(struct reader_t*reader, SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
1023 if (!swf) return -1;
1024 memset(swf,0x00,sizeof(SWF));
1026 { char b[32]; // read Header
1030 struct reader_t zreader;
1032 if ((len = reader->read(reader ,b,8))<8) return -1;
1034 if (b[0]!='F' && b[0]!='C') return -1;
1035 if (b[1]!='W') return -1;
1036 if (b[2]!='S') return -1;
1037 swf->fileVersion = b[3];
1038 swf->compressed = (b[0]=='C')?1:0;
1039 swf->fileSize = GET32(&b[4]);
1041 if(swf->compressed) {
1042 reader_init_zlibinflate(&zreader, reader);
1046 reader_GetRect(reader, &swf->movieSize);
1047 reader->read(reader, &swf->frameRate, 2);
1048 swf->frameRate = SWAP16(swf->frameRate);
1049 reader->read(reader, &swf->frameCount, 2);
1050 swf->frameCount = SWAP16(swf->frameCount);
1052 /* read tags and connect to list */
1054 while (t) t = swf_ReadTag(reader,t);
1055 swf->firstTag = t1.next;
1056 t1.next->prev = NULL;
1062 int swf_ReadSWF(int handle, SWF * swf)
1064 struct reader_t reader;
1065 reader_init_filereader(&reader, handle);
1066 return swf_ReadSWF2(&reader, swf);
1069 int swf_WriteSWF2(struct writer_t*writer, SWF * swf) // Writes SWF to file, returns length or <0 if fails
1073 struct writer_t zwriter;
1076 if (!swf) return -1;
1078 // Insert REFLEX Tag
1080 #ifdef INSERT_RFX_TAG
1082 if (swf->firstTag && swf_NextTag(swf->firstTag))
1083 if (swf_GetTagID(swf_NextTag(swf->firstTag))!=ST_REFLEX)
1084 swf_SetBlock(swf_InsertTag(swf->firstTag,ST_REFLEX),"rfx",3);
1086 #endif // INSERT_RFX_TAG
1088 // Count Frames + File Size
1095 { len += swf_WriteTag(-1, t);
1096 if (t->id==ST_SHOWFRAME) frameCount++;
1104 memset(&t1,0x00,sizeof(TAG));
1108 { // measure header file size
1111 memset(&t2,0x00,sizeof(TAG));
1114 swf_SetRect(&t2, &swf->movieSize);
1115 swf_SetU16(&t2, swf->frameRate);
1116 swf_SetU16(&t2, swf->frameCount);
1117 l = swf_GetTagLen(&t2)+8;
1121 if(len) {// don't touch headers without tags
1122 swf->fileSize = fileSize;
1123 swf->frameCount = frameCount;
1126 if(swf->compressed) {
1128 writer->write(writer, id, 3);
1132 writer->write(writer, id, 3);
1135 writer->write(writer, &swf->fileVersion, 1);
1136 PUT32(b4, swf->fileSize);
1137 writer->write(writer, b4, 4);
1139 if(swf->compressed) {
1140 writer_init_zlibdeflate(&zwriter, writer);
1144 swf_SetRect(&t1,&swf->movieSize);
1145 swf_SetU16(&t1,swf->frameRate);
1146 swf_SetU16(&t1,swf->frameCount);
1150 int ret = writer->write(writer,b,swf_GetTagLen(&t1));
1151 if (ret!=swf_GetTagLen(&t1))
1154 fprintf(stderr, "ret:%d\n",ret);
1156 fprintf(stderr,"WriteSWF() failed: Header.\n");
1163 { if (swf_WriteTag2(writer, t)<0) return -1;
1166 writer->finish(writer); //e.g. flush zlib buffers
1169 return (int)fileSize;
1172 int swf_WriteSWF(int handle, SWF * swf) // Writes SWF to file, returns length or <0 if fails
1174 struct writer_t writer;
1175 swf->compressed = 0;
1177 return swf_WriteSWF2(&writer, swf);
1178 writer_init_filewriter(&writer, handle);
1179 return swf_WriteSWF2(&writer, swf);
1182 int swf_WriteSWC(int handle, SWF * swf) // Writes SWF to file, returns length or <0 if fails
1184 struct writer_t writer;
1185 swf->compressed = 1;
1187 return swf_WriteSWF2(&writer, swf);
1188 writer_init_filewriter(&writer, handle);
1189 return swf_WriteSWF2(&writer, swf);
1192 int swf_WriteHeader2(struct writer_t*writer,SWF * swf)
1195 memcpy(&myswf,swf,sizeof(SWF));
1197 return swf_WriteSWF2(writer, &myswf);
1200 int swf_WriteHeader(int handle,SWF * swf)
1203 memcpy(&myswf,swf,sizeof(SWF));
1205 return swf_WriteSWF(handle, &myswf);
1208 int swf_WriteCGI(SWF * swf)
1212 len = swf_WriteSWF(-1,swf);
1214 if (len<0) return -1;
1216 sprintf(s,"Content-type: application/x-shockwave-flash\n"
1217 "Accept-Ranges: bytes\n"
1218 "Content-Length: %lu\n"
1219 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
1222 write(fileno(stdout),s,strlen(s));
1223 return swf_WriteSWF(fileno(stdout),swf);
1226 void swf_FreeTags(SWF * swf) // Frees all malloc'ed memory for tags
1227 { TAG * t = swf->firstTag;
1230 { TAG * tnew = t->next;
1231 if (t->data) free(t->data);
1237 // include advanced functions
1239 #include "modules/swfdump.c"
1240 #include "modules/swfshape.c"
1241 #include "modules/swftext.c"
1242 #include "modules/swfobject.c"
1243 #include "modules/swfbutton.c"
1244 #include "modules/swftools.c"
1245 #include "modules/swfcgi.c"
1246 #include "modules/swfbits.c"
1247 #include "modules/swfaction.c"
1248 #include "modules/swfsound.c"