1 /* vi: set sts=2 sw=2 :*/
4 Library for creating and reading SWF files or parts of it.
5 There's a module directory which provides some extended functionality.
6 Most modules are included at the bottom of this file.
8 Part of the swftools package.
10 Copyright (c) 2000-2003 Rainer Böhme <rfxswf@reflex-studio.de>
11 Copyright (c) 2003 Matthias Kramm <kramm@quiss.org>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
33 #ifndef RFXSWF_DISABLESOUND
35 #include "lame/lame.h"
52 #define MALLOC_SIZE 128
53 #define INSERT_RFX_TAG
55 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
57 // inline wrapper functions
59 TAG
* swf_NextTag(TAG
* t
) { return t
->next
; }
60 TAG
* swf_PrevTag(TAG
* t
) { return t
->prev
; }
61 U16
swf_GetTagID(TAG
* t
) { return t
->id
; }
62 U32
swf_GetTagLen(TAG
* t
) { return t
->len
; }
63 U8
* swf_GetTagLenPtr(TAG
* t
) { return &(t
->data
[t
->len
]); }
64 U32
swf_GetTagPos(TAG
* t
) { return t
->pos
; }
66 void swf_SetTagPos(TAG
* t
,U32 pos
)
67 { swf_ResetReadBits(t
);
68 if (pos
<=t
->len
) t
->pos
= pos
;
71 fprintf(stderr
,"SetTagPos(%d) out of bounds: TagID = %i\n",pos
, t
->id
);
76 char* swf_GetString(TAG
*t
)
79 while(t
->pos
< t
->len
&& swf_GetU8(t
));
80 /* make sure we always have a trailing zero byte */
81 if(t
->pos
== t
->len
) {
82 if(t
->len
== t
->memsize
) {
83 swf_ResetWriteBits(t
);
89 return (char*)&(t
->data
[pos
]);
93 { swf_ResetReadBits(t
);
95 if ((int)t
->pos
>=(int)t
->len
)
96 { fprintf(stderr
,"GetU8() out of bounds: TagID = %i\n",t
->id
);
101 return t
->data
[t
->pos
++];
104 U16
swf_GetU16(TAG
* t
)
106 swf_ResetReadBits(t
);
108 if ((int)t
->pos
>((int)t
->len
-2))
109 { fprintf(stderr
,"GetU16() out of bounds: TagID = %i\n",t
->id
);
113 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8);
118 U32
swf_GetU32(TAG
* t
)
120 swf_ResetReadBits(t
);
122 if ((int)t
->pos
>((int)t
->len
-4))
123 { fprintf(stderr
,"GetU32() out of bounds: TagID = %i\n",t
->id
);
127 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8) |
128 (t
->data
[t
->pos
+2]<<16) | (t
->data
[t
->pos
+3]<<24);
133 int swf_GetBlock(TAG
* t
,U8
* b
,int l
)
134 // returns number of bytes written (<=l)
135 // b = NULL -> skip data
136 { swf_ResetReadBits(t
);
137 if ((t
->len
-t
->pos
)<l
) l
=t
->len
-t
->pos
;
138 if (b
&& l
) memcpy(b
,&t
->data
[t
->pos
],l
);
143 int swf_SetBlock(TAG
* t
,const U8
* b
,int l
)
144 // Appends Block to the end of Tagdata, returns size
145 { U32 newlen
= t
->len
+ l
;
146 swf_ResetWriteBits(t
);
147 if (newlen
>t
->memsize
)
148 { U32 newmem
= MEMSIZE(newlen
);
149 U8
* newdata
= (U8
*)(rfx_realloc(t
->data
,newmem
));
153 if (b
) memcpy(&t
->data
[t
->len
],b
,l
);
154 else memset(&t
->data
[t
->len
],0x00,l
);
159 int swf_SetU8(TAG
* t
,U8 v
)
160 { swf_ResetWriteBits(t
);
161 if ((t
->len
+1)>t
->memsize
) return (swf_SetBlock(t
,&v
,1)==1)?0:-1;
162 t
->data
[t
->len
++] = v
;
166 int swf_SetU16(TAG
* t
,U16 v
)
171 swf_ResetWriteBits(t
);
172 if ((t
->len
+2)>t
->memsize
) return (swf_SetBlock(t
,a
,2)==2)?0:-1;
173 t
->data
[t
->len
++] = a
[0];
174 t
->data
[t
->len
++] = a
[1];
177 void swf_SetS16(TAG
* t
,int v
)
179 if(v
>32767 || v
<-32768) {
181 fprintf(stderr
, "Warning: S16 overflow: %d\n", v
);
184 swf_SetU16(t
, (S16
)v
);
187 int swf_SetU32(TAG
* t
,U32 v
)
189 a
[0] = v
&0xff; // to ensure correct handling of non-intel byteorder
194 swf_ResetWriteBits(t
);
195 if ((t
->len
+4)>t
->memsize
) return (swf_SetBlock(t
,a
,4)==4)?0:-1;
196 t
->data
[t
->len
++] = a
[0];
197 t
->data
[t
->len
++] = a
[1];
198 t
->data
[t
->len
++] = a
[2];
199 t
->data
[t
->len
++] = a
[3];
203 U32
swf_GetBits(TAG
* t
,int nbits
)
205 if (!nbits
) return 0;
206 if (!t
->readBit
) t
->readBit
= 0x80;
211 { fprintf(stderr
,"GetBits() out of bounds: TagID = %i, pos=%d, len=%d\n",t
->id
, t
->pos
, t
->len
);
212 int i
,m
=t
->len
>10?10:t
->len
;
214 fprintf(stderr
, "(%d)%02x ", i
, t
->data
[i
]);
216 fprintf(stderr
, "\n");
220 if (t
->data
[t
->pos
]&t
->readBit
) res
|=1;
224 { if (nbits
) t
->readBit
= 0x80;
231 S32
swf_GetSBits(TAG
* t
,int nbits
)
232 { U32 res
= swf_GetBits(t
,nbits
);
233 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
237 U32
reader_GetBits(reader_t
*reader
, int nbits
)
238 { return reader_readbits(reader
, nbits
);
240 S32
reader_GetSBits(reader_t
*reader
, int nbits
)
241 { U32 res
= reader_readbits(reader
, nbits
);
242 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
246 int swf_SetBits(TAG
* t
,U32 v
,int nbits
)
247 { U32 bm
= 1<<(nbits
-1);
251 { if (FAILED(swf_SetU8(t
,0))) return -1;
254 if (v
&bm
) t
->data
[t
->len
-1] |= t
->writeBit
;
262 // Advanced Data Access Functions
264 double swf_GetFixed(TAG
* t
)
266 U16 low
= swf_GetU16(t
);
267 U16 high
= swf_GetU16(t
);
268 return high
+ low
*(1/65536.0);
270 void swf_SetFixed(TAG
* t
, double f
)
272 U16 fr
= (U16
)((f
-(int)f
)*65536);
274 swf_SetU16(t
, (U16
)f
- (f
<0 && fr
!=0));
276 float swf_GetFixed8(TAG
* t
)
278 U8 low
= swf_GetU8(t
);
279 U8 high
= swf_GetU8(t
);
280 return (float)(high
+ low
*(1/256.0));
282 void swf_SetFixed8(TAG
* t
, float f
)
284 U8 fr
= (U8
)((f
-(int)f
)*256);
286 swf_SetU8(t
, (U8
)f
- (f
<0 && fr
!=0));
289 U32
swf_GetU30(TAG
*tag
)
295 U8 b
= swf_GetU8(tag
);
299 if(!(b
&128) || shift
>=32)
302 /*int nr2= swf_SetU30(0, s);
304 printf("Unsigned value %d stored in %d bytes, I'd store it in %d bytes\n", s, nr, nr2);
309 int swf_SetU30(TAG
*tag
, U32 u
)
314 swf_SetU8(tag
, (u
&~0x7f?0x80:0) | (u
&0x7F));
321 void swf_SetABCU32(TAG
*tag
, U32 u
)
324 swf_SetU8(tag
, (u
&~0x7f?0x80:0) | (u
&0x7F));
328 U32
swf_GetABCU32(TAG
*tag
)
330 return swf_GetU30(tag
);
332 void swf_SetABCS32(TAG
*tag
, S32 v
)
334 swf_SetABCU32(tag
, v
);
336 S32
swf_GetABCS32(TAG
*tag
)
338 return swf_GetABCU32(tag
);
343 /*The AVM2 spec is just plain wrong, claiming that S32 values are sign
344 extended. They're not.
345 This wastes up to 4 bytes for every negative value. */
347 void swf_SetABCS32(TAG
*tag
, S32 s
)
349 printf("write S32: %d\n", s
);
351 U8 sign
= s
<0?0x40:0;
357 if(s
==neg
&& vsign
==sign
) {
358 /* if the value we now write has the same sign as s
359 and all the remaining bits are equal to the sign of s
362 printf("put %02x\n", val
);
365 swf_SetU8(tag
, 0x80 | val
);
366 printf("put %02x\n", 0x80|val
);
370 int swf_GetS30(TAG
*tag
)
376 U8 b
= swf_GetU8(tag
);
378 nt i
,m
=t
->len
>10?10:t
->len
;
380 fprintf(stderr
, "%02x ", t
->data
[i
]);
382 fprintf(stderr
, "\n");
385 if(!(b
&128) || shift
>=32) {
388 s
|=0xffffffff<<shift
;
393 /* It's not uncommon for other applications (Flex for all negative numbers, and
394 Flash for -1) to generate a lot more bytes than would be necessary.
395 int nr2= swf_SetS30(0, s);
397 printf("Signed value %d stored in %d bytes, I'd store it in %d bytes\n", s, nr, nr2);
403 int swf_SetU30String(TAG
*tag
, const char*str
, int l
)
406 len
+=swf_SetU30(tag
, l
);
408 swf_SetBlock(tag
, (void*)str
, l
);
412 float swf_GetF16(TAG
* t
)
414 U16 f1
= swf_GetU16(t
);
415 if(!(f1
&0x3ff)) return 0.0;
419 /* gcc 4.1.2 seems to require a union here. *(float*)u doesn't work */
425 U16 e
= (f1
>>10)&0x1f;
427 /* find highest bit in mantissa */
437 f2
.u
= (f1
&0x8000)<<16; //sign
438 f2
.u
|= e
<<23; //exponent
439 f2
.u
|= m
<<13; //mantissa
443 void swf_SetF16(TAG
* t
, float f
)
451 U16 result
= (v
.u
>>16)&0x8000; //sign
452 int exp
= ((v
.u
>>23)&0xff)-0x7f+0x10;
453 U16 m
= (v
.u
>>13)&0x3ff;
454 //fprintf(stderr, "%f: %04x sign, %d exp, %04x mantissa\n", f, result, exp, m);
456 // underflow (clamp to 0.0)
460 // partial underflow- strip some bits
466 fprintf(stderr
, "Exponent overflow in FLOAT16 encoding\n");
473 swf_SetU16(t
, result
);
476 float F16toFloat(U16 x
)
483 return swf_GetF16(&t
);
486 float floatToF16(float f
)
498 double swf_GetD64(TAG
*tag
)
500 /* FIXME: this is not big-endian compatible */
501 double value
= *(double*)&tag
->data
[tag
->pos
];
506 int swf_SetD64(TAG
*tag
, double v
)
508 /* FIXME: this is not big-endian compatible */
509 swf_SetU32(tag
, ((U32
*)&v
)[0]);
510 swf_SetU32(tag
, ((U32
*)&v
)[1]);
513 int swf_GetU24(TAG
*tag
)
515 int b1
= swf_GetU8(tag
);
516 int b2
= swf_GetU8(tag
);
517 int b3
= swf_GetU8(tag
);
518 return b3
<<16|b2
<<8|b1
;
520 int swf_GetS24(TAG
*tag
)
522 int b1
= swf_GetU8(tag
);
523 int b2
= swf_GetU8(tag
);
524 int b3
= swf_GetU8(tag
);
526 return -1-((b3
<<16|b2
<<8|b1
)^0xffffff);
528 return b3
<<16|b2
<<8|b1
;
531 int swf_SetU24(TAG
*tag
, U32 v
)
535 fprintf(stderr
, "Error: Overflow in swf_SetU24()\n");
537 swf_SetU8(tag
, v
>>8);
538 swf_SetU8(tag
, v
>>16);
542 int swf_SetS24(TAG
*tag
, U32 v
)
546 return swf_SetU24(tag
, v
);
547 if((v
&0xff000000)!=0xff000000) {
548 fprintf(stderr
, "Error: Overflow in swf_SetS24()\n");
551 swf_SetU8(tag
, v
>>8);
552 swf_SetU8(tag
, v
>>16);
558 int swf_SetRGB(TAG
* t
,RGBA
* col
)
561 { swf_SetU8(t
,col
->r
);
564 } else swf_SetBlock(t
,NULL
,3);
567 void swf_GetRGB(TAG
* t
, RGBA
* col
)
572 col
->r
= swf_GetU8(t
);
573 col
->g
= swf_GetU8(t
);
574 col
->b
= swf_GetU8(t
);
578 int swf_SetRGBA(TAG
* t
,RGBA
* col
)
581 { swf_SetU8(t
,col
->r
);
585 } else swf_SetBlock(t
,NULL
,4);
588 void swf_GetRGBA(TAG
* t
, RGBA
* col
)
593 col
->r
= swf_GetU8(t
);
594 col
->g
= swf_GetU8(t
);
595 col
->b
= swf_GetU8(t
);
596 col
->a
= swf_GetU8(t
);
599 void swf_GetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
603 memset(gradient
, 0, sizeof(GRADIENT
));
606 U8 num
= swf_GetU8(tag
) & 15;
609 gradient
->rgba
= (RGBA
*)rfx_calloc(sizeof(RGBA
)*gradient
->num
);
610 gradient
->ratios
= (U8
*)rfx_calloc(sizeof(gradient
->ratios
[0])*gradient
->num
);
614 U8 ratio
= swf_GetU8(tag
);
617 swf_GetRGB(tag
, &color
);
619 swf_GetRGBA(tag
, &color
);
621 gradient
->ratios
[t
] = ratio
;
622 gradient
->rgba
[t
] = color
;
627 void swf_SetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
631 memset(gradient
, 0, sizeof(GRADIENT
));
634 swf_SetU8(tag
, gradient
->num
);
635 for(t
=0; t
<8 && t
<gradient
->num
; t
++)
637 swf_SetU8(tag
, gradient
->ratios
[t
]);
639 swf_SetRGB(tag
, &gradient
->rgba
[t
]);
641 swf_SetRGBA(tag
, &gradient
->rgba
[t
]);
645 void swf_FreeGradient(GRADIENT
* gradient
)
648 rfx_free(gradient
->ratios
);
650 rfx_free(gradient
->rgba
);
651 memset(gradient
, 0, sizeof(GRADIENT
));
654 int swf_CountUBits(U32 v
,int nbits
)
657 if(v
== 0x00000000) n
= 0;
663 return (n
>nbits
)?n
:nbits
;
666 int swf_CountBits(U32 v
,int nbits
)
670 { if(v
== 0xffffffff) n
= 1;
678 { if(v
== 0x00000000) n
= 0;
685 return (n
>nbits
)?n
:nbits
;
688 int swf_GetRect(TAG
* t
,SRECT
* r
)
691 if(!t
) {r
->xmin
=r
->xmax
=r
->ymin
=r
->ymax
=0;return 0;}
693 nbits
= (int) swf_GetBits(t
,5);
694 r
->xmin
= swf_GetSBits(t
,nbits
);
695 r
->xmax
= swf_GetSBits(t
,nbits
);
696 r
->ymin
= swf_GetSBits(t
,nbits
);
697 r
->ymax
= swf_GetSBits(t
,nbits
);
701 int reader_GetRect(reader_t
*reader
,SRECT
* r
)
705 nbits
= (int) reader_GetBits(reader
,5);
706 r
->xmin
= reader_GetSBits(reader
,nbits
);
707 r
->xmax
= reader_GetSBits(reader
,nbits
);
708 r
->ymin
= reader_GetSBits(reader
,nbits
);
709 r
->ymax
= reader_GetSBits(reader
,nbits
);
713 int swf_SetRect(TAG
* t
,SRECT
* r
)
716 nbits
= swf_CountBits(r
->xmin
,0);
717 nbits
= swf_CountBits(r
->xmax
,nbits
);
718 nbits
= swf_CountBits(r
->ymin
,nbits
);
719 nbits
= swf_CountBits(r
->ymax
,nbits
);
722 fprintf(stderr
, "rfxswf: Warning: num_bits overflow in swf_SetRect\n");
727 swf_SetBits(t
,nbits
,5);
728 swf_SetBits(t
,r
->xmin
,nbits
);
729 swf_SetBits(t
,r
->xmax
,nbits
);
730 swf_SetBits(t
,r
->ymin
,nbits
);
731 swf_SetBits(t
,r
->ymax
,nbits
);
736 SRECT
swf_ClipRect(SRECT border
, SRECT r
)
738 if(r
.xmax
> border
.xmax
) r
.xmax
= border
.xmax
;
739 if(r
.ymax
> border
.ymax
) r
.ymax
= border
.ymax
;
740 if(r
.xmax
< border
.xmin
) r
.xmax
= border
.xmin
;
741 if(r
.ymax
< border
.ymin
) r
.ymax
= border
.ymin
;
743 if(r
.xmin
> border
.xmax
) r
.xmin
= border
.xmax
;
744 if(r
.ymin
> border
.ymax
) r
.ymin
= border
.ymax
;
745 if(r
.xmin
< border
.xmin
) r
.xmin
= border
.xmin
;
746 if(r
.ymin
< border
.ymin
) r
.ymin
= border
.ymin
;
750 void swf_ExpandRect(SRECT
*src
, SPOINT add
)
752 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
757 if((add
.x
|add
.y
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
760 if(add
.x
< src
->xmin
)
762 if(add
.x
> src
->xmax
)
764 if(add
.y
< src
->ymin
)
766 if(add
.y
> src
->ymax
)
769 void swf_ExpandRect2(SRECT
*src
, SRECT
*add
)
771 if((add
->xmin
| add
->ymin
| add
->xmax
| add
->ymax
)==0)
773 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0)
775 if(add
->xmin
< src
->xmin
)
776 src
->xmin
= add
->xmin
;
777 if(add
->ymin
< src
->ymin
)
778 src
->ymin
= add
->ymin
;
779 if(add
->xmax
> src
->xmax
)
780 src
->xmax
= add
->xmax
;
781 if(add
->ymax
> src
->ymax
)
782 src
->ymax
= add
->ymax
;
784 void swf_ExpandRect3(SRECT
*src
, SPOINT center
, int radius
)
786 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
787 src
->xmin
= center
.x
-radius
;
788 src
->ymin
= center
.y
-radius
;
789 src
->xmax
= center
.x
+radius
;
790 src
->ymax
= center
.y
+radius
;
791 if((center
.x
|center
.y
|radius
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
794 if(center
.x
- radius
< src
->xmin
)
795 src
->xmin
= center
.x
- radius
;
796 if(center
.x
+ radius
> src
->xmax
)
797 src
->xmax
= center
.x
+ radius
;
798 if(center
.y
- radius
< src
->ymin
)
799 src
->ymin
= center
.y
- radius
;
800 if(center
.y
+ radius
> src
->ymax
)
801 src
->ymax
= center
.y
+ radius
;
803 SPOINT
swf_TurnPoint(SPOINT p
, MATRIX
* m
)
806 r
.x
= (int)(m
->sx
*(1/65536.0)*p
.x
+ m
->r1
*(1/65536.0)*p
.y
+ 0.5) + m
->tx
;
807 r
.y
= (int)(m
->r0
*(1/65536.0)*p
.x
+ m
->sy
*(1/65536.0)*p
.y
+ 0.5) + m
->ty
;
810 SRECT
swf_TurnRect(SRECT r
, MATRIX
* m
)
813 SPOINT p1
,p2
,p3
,p4
,pp1
,pp2
,pp3
,pp4
;
816 p1
.x
= r
.xmin
;p1
.y
= r
.ymin
;
817 p2
.x
= r
.xmax
;p2
.y
= r
.ymin
;
818 p3
.x
= r
.xmin
;p3
.y
= r
.ymax
;
819 p4
.x
= r
.xmax
;p4
.y
= r
.ymax
;
820 pp1
= swf_TurnPoint(p1
, m
);
821 pp2
= swf_TurnPoint(p2
, m
);
822 pp3
= swf_TurnPoint(p3
, m
);
823 pp4
= swf_TurnPoint(p4
, m
);
824 g
.xmin
= g
.xmax
= pp1
.x
;
825 g
.ymin
= g
.ymax
= pp1
.y
;
826 swf_ExpandRect(&g
, pp2
);
827 swf_ExpandRect(&g
, pp3
);
828 swf_ExpandRect(&g
, pp4
);
833 int swf_GetMatrix(TAG
* t
,MATRIX
* m
)
840 { m
->sx
= m
->sy
= 0x10000;
846 swf_ResetReadBits(t
);
848 if (swf_GetBits(t
,1))
849 { nbits
= swf_GetBits(t
,5);
850 m
->sx
= swf_GetSBits(t
,nbits
);
851 m
->sy
= swf_GetSBits(t
,nbits
);
853 else m
->sx
= m
->sy
= 0x10000;
855 if (swf_GetBits(t
,1))
856 { nbits
= swf_GetBits(t
,5);
857 m
->r0
= swf_GetSBits(t
,nbits
);
858 m
->r1
= swf_GetSBits(t
,nbits
);
860 else m
->r0
= m
->r1
= 0x0;
862 nbits
= swf_GetBits(t
,5);
863 m
->tx
= swf_GetSBits(t
,nbits
);
864 m
->ty
= swf_GetSBits(t
,nbits
);
869 int swf_SetMatrix(TAG
* t
,MATRIX
* m
)
875 ma
.sx
= ma
.sy
= 0x10000;
880 swf_ResetWriteBits(t
);
882 if ((m
->sx
==0x10000)&&(m
->sy
==0x10000)) swf_SetBits(t
,0,1);
884 { swf_SetBits(t
,1,1);
885 nbits
= swf_CountBits(m
->sx
,0);
886 nbits
= swf_CountBits(m
->sy
,nbits
);
888 /* TODO: happens on AMD64 systems for normal values? */
890 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
894 swf_SetBits(t
,nbits
,5);
895 swf_SetBits(t
,m
->sx
,nbits
);
896 swf_SetBits(t
,m
->sy
,nbits
);
899 if ((!m
->r0
)&&(!m
->r1
)) swf_SetBits(t
,0,1);
901 { swf_SetBits(t
,1,1);
902 nbits
= swf_CountBits(m
->r0
,0);
903 nbits
= swf_CountBits(m
->r1
,nbits
);
906 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
910 swf_SetBits(t
,nbits
,5);
911 swf_SetBits(t
,m
->r0
,nbits
);
912 swf_SetBits(t
,m
->r1
,nbits
);
915 nbits
= swf_CountBits(m
->tx
,0);
916 nbits
= swf_CountBits(m
->ty
,nbits
);
919 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
923 swf_SetBits(t
,nbits
,5);
924 swf_SetBits(t
,m
->tx
,nbits
);
925 swf_SetBits(t
,m
->ty
,nbits
);
930 int swf_GetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
)
938 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
939 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
943 swf_ResetReadBits(t
);
944 hasadd
= swf_GetBits(t
,1);
945 hasmul
= swf_GetBits(t
,1);
946 nbits
= swf_GetBits(t
,4);
949 { cx
->r0
= (S16
)swf_GetSBits(t
,nbits
);
950 cx
->g0
= (S16
)swf_GetSBits(t
,nbits
);
951 cx
->b0
= (S16
)swf_GetSBits(t
,nbits
);
953 cx
->a0
= (S16
)swf_GetSBits(t
,nbits
);
957 { cx
->r1
= (S16
)swf_GetSBits(t
,nbits
);
958 cx
->g1
= (S16
)swf_GetSBits(t
,nbits
);
959 cx
->b1
= (S16
)swf_GetSBits(t
,nbits
);
961 cx
->a1
= (S16
)swf_GetSBits(t
,nbits
);
967 int swf_SetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
)
975 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
976 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
986 hasmul
= (cx
->a0
!=256)||(cx
->r0
!=256)||(cx
->g0
!=256)||(cx
->b0
!=256);
987 hasadd
= cx
->a1
|cx
->r1
|cx
->g1
|cx
->b1
;
990 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a0
,nbits
);
991 nbits
= swf_CountBits((S32
)cx
->r0
,nbits
);
992 nbits
= swf_CountBits((S32
)cx
->g0
,nbits
);
993 nbits
= swf_CountBits((S32
)cx
->b0
,nbits
);
997 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a1
,nbits
);
998 nbits
= swf_CountBits((S32
)cx
->r1
,nbits
);
999 nbits
= swf_CountBits((S32
)cx
->g1
,nbits
);
1000 nbits
= swf_CountBits((S32
)cx
->b1
,nbits
);
1003 swf_ResetWriteBits(t
);
1004 swf_SetBits(t
,hasadd
?1:0,1);
1005 swf_SetBits(t
,hasmul
?1:0,1);
1006 swf_SetBits(t
,nbits
,4);
1009 { swf_SetBits(t
,cx
->r0
,nbits
);
1010 swf_SetBits(t
,cx
->g0
,nbits
);
1011 swf_SetBits(t
,cx
->b0
,nbits
);
1012 if (alpha
) swf_SetBits(t
,cx
->a0
,nbits
);
1016 { swf_SetBits(t
,cx
->r1
,nbits
);
1017 swf_SetBits(t
,cx
->g1
,nbits
);
1018 swf_SetBits(t
,cx
->b1
,nbits
);
1019 if (alpha
) swf_SetBits(t
,cx
->a1
,nbits
);
1025 //int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
1026 //int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
1028 void swf_SetPassword(TAG
* t
, const char * password
)
1031 /* WARNING: crypt_md5 is not reentrant */
1035 #if defined(HAVE_LRAND48) && defined(HAVE_SRAND48) && defined(HAVE_TIME_H) && defined(HAVE_TIME)
1037 salt
[0] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
1038 salt
[1] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
1042 fprintf(stderr
, "rfxswf: Warning- no usable random generator found\n");
1043 fprintf(stderr
, "Your password will be vulnerable to dictionary attacks\n");
1047 md5string
= crypt_md5(password
, salt
);
1050 swf_SetString(t
, md5string
);
1052 fprintf(stderr
, "Error: No MD5 compiled in");
1056 void swf_SetString(TAG
*t
, const char* s
)
1061 swf_SetBlock(t
,(U8
*)s
,strlen(s
)+1);
1065 int swf_VerifyPassword(TAG
* t
, const char * password
)
1068 char*md5string1
, *md5string2
;
1073 if(t
->len
>= 5 && t
->pos
==0 &&
1078 printf("%d %d %d %d\n", t
->len
, t
->pos
, t
->data
[0], t
->data
[1]);
1081 md5string1
= swf_GetString(t
);
1083 if(strncmp(md5string1
, "$1$",3 )) {
1084 fprintf(stderr
, "rfxswf: no salt in pw string\n");
1087 x
= strchr(md5string1
+3, '$');
1089 fprintf(stderr
, "rfxswf: invalid salt format in pw string\n");
1092 n
= x
-(md5string1
+3);
1093 salt
= (char*)rfx_alloc(n
+1);
1094 memcpy(salt
, md5string1
+3, n
);
1097 md5string2
= crypt_md5(password
, salt
);
1099 if(strcmp(md5string1
, md5string2
) != 0)
1103 fprintf(stderr
, "Error: No MD5 compiled in");
1108 // Tag List Manipulating Functions
1110 TAG
* swf_InsertTag(TAG
* after
,U16 id
)
1113 t
= (TAG
*)rfx_calloc(sizeof(TAG
));
1119 t
->next
= after
->next
;
1121 if (t
->next
) t
->next
->prev
= t
;
1126 TAG
* swf_InsertTagBefore(SWF
* swf
, TAG
* before
,U16 id
)
1129 t
= (TAG
*)rfx_calloc(sizeof(TAG
));
1135 t
->prev
= before
->prev
;
1137 if (t
->prev
) t
->prev
->next
= t
;
1139 if(swf
&& swf
->firstTag
== before
) {
1145 void swf_ClearTag(TAG
* t
)
1147 if (t
->data
) rfx_free(t
->data
);
1156 void swf_ResetTag(TAG
*tag
, U16 id
)
1158 tag
->len
= tag
->pos
= tag
->readBit
= tag
->writeBit
= 0;
1162 TAG
* swf_CopyTag(TAG
*tag
, TAG
*to_copy
)
1164 tag
= swf_InsertTag(tag
, to_copy
->id
);
1165 swf_SetBlock(tag
, to_copy
->data
, to_copy
->len
);
1169 TAG
* swf_DeleteTag(SWF
*swf
, TAG
* t
)
1173 if (swf
&& swf
->firstTag
==t
)
1174 swf
->firstTag
= t
->next
;
1175 if (t
->prev
) t
->prev
->next
= t
->next
;
1176 if (t
->next
) t
->next
->prev
= t
->prev
;
1178 if (t
->data
) rfx_free(t
->data
);
1183 TAG
* swf_ReadTag(reader_t
*reader
, TAG
* prev
)
1189 if (reader
->read(reader
, &raw
, 2) !=2 ) return NULL
;
1190 raw
= LE_16_TO_NATIVE(raw
);
1197 len
= reader_readU32(reader
);
1200 if (id
==ST_DEFINESPRITE
) len
= 2*sizeof(U16
);
1201 // Sprite handling fix: Flatten sprite tree
1203 t
= (TAG
*)rfx_calloc(sizeof(TAG
));
1209 { t
->data
= (U8
*)rfx_alloc(t
->len
);
1210 t
->memsize
= t
->len
;
1211 if (reader
->read(reader
, t
->data
, t
->len
) != t
->len
) {
1213 fprintf(stderr
, "rfxswf: Warning: Short read (tagid %d). File truncated?\n", t
->id
);
1215 free(t
->data
);t
->data
=0;
1230 int swf_DefineSprite_GetRealSize(TAG
* t
);
1232 int swf_WriteTag2(writer_t
*writer
, TAG
* t
)
1233 // returns tag length in bytes (incl. Header), -1 = Error
1234 // writer = 0 -> no output
1241 len
= (t
->id
==ST_DEFINESPRITE
)?swf_DefineSprite_GetRealSize(t
):t
->len
;
1243 short_tag
= len
<0x3f&&
1244 (t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
&&t
->id
!=ST_SOUNDSTREAMBLOCK
&&
1245 t
->id
!=ST_DEFINEBITSJPEG
&&t
->id
!=ST_DEFINEBITSJPEG2
&&t
->id
!=ST_DEFINEBITSJPEG3
);
1250 int oldpos
= writer
->pos
;
1254 { raw
[0] = LE_16_TO_NATIVE(len
|((t
->id
&0x3ff)<<6));
1255 if (writer
->write(writer
,raw
,2)!=2)
1258 fprintf(stderr
,"WriteTag() failed: Short Header.\n");
1265 raw
[0] = LE_16_TO_NATIVE((t
->id
<<6)|0x3f);
1266 if (writer
->write(writer
,raw
,2)!=2)
1269 fprintf(stderr
,"WriteTag() failed: Long Header (1).\n");
1274 writer_writeU32(writer
, len
);
1278 { if (writer
->write(writer
,t
->data
,t
->len
)!=t
->len
)
1281 fprintf(stderr
,"WriteTag() failed: Data.\n");
1287 else if (t
->len
) fprintf(stderr
,"WriteTag(): Tag Data Error, id=%i\n",t
->id
);
1291 writer
->flush(writer
);
1292 printf("TAG %s costs %d bytes\n", swf_TagGetName(t
), writer
->pos
-oldpos
);
1296 return t
->len
+(short_tag
?2:6);
1299 int swf_WriteTag(int handle
, TAG
* t
)
1304 return swf_WriteTag2(0, t
);
1305 writer_init_filewriter(&writer
, handle
);
1306 len
= swf_WriteTag2(&writer
, t
);
1307 writer
.finish(&writer
);
1311 int swf_DefineSprite_GetRealSize(TAG
* t
)
1312 // Sprite Handling: Helper function to pack DefineSprite-Tag
1314 if(len
>4) { // folded sprite
1318 { t
= swf_NextTag(t
);
1319 if (t
&& t
->id
!=ST_DEFINESPRITE
) len
+= swf_WriteTag(-1, t
);
1321 } while (t
&&(t
->id
!=ST_END
));
1325 void swf_UnFoldSprite(TAG
* t
)
1330 U16 spriteid
,spriteframes
;
1332 if(t
->id
!=ST_DEFINESPRITE
)
1334 if(t
->len
<=4) // not folded
1339 spriteid
= swf_GetU16(t
); //id
1340 spriteframes
= swf_GetU16(t
); //frames
1347 tmp
= swf_GetU16(t
);
1352 if(id
== ST_DEFINESPRITE
&& len
<=4)
1356 len
= swf_GetU32(t
);
1357 it
= swf_InsertTag(next
, id
);
1362 { it
->data
= (U8
*)rfx_alloc(it
->len
);
1363 it
->memsize
= it
->len
;
1364 swf_GetBlock(t
, it
->data
, it
->len
);
1371 rfx_free(t
->data
); t
->data
= 0;
1372 t
->memsize
= t
->len
= t
->pos
= 0;
1374 swf_SetU16(t
, spriteid
);
1375 swf_SetU16(t
, spriteframes
);
1378 void swf_FoldSprite(TAG
* t
)
1383 if(t
->id
!=ST_DEFINESPRITE
)
1387 fprintf(stderr
, "Error: Sprite has no ID!");
1392 /* sprite is already folded */
1399 t
->len
= t
->pos
= t
->memsize
= 0;
1404 t
= swf_NextTag(sprtag
);
1409 if(t
->id
==ST_SHOWFRAME
) frames
++;
1410 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1415 } while(t
&& level
);
1417 fprintf(stderr
, "rfxswf error: sprite doesn't end(1)\n");
1419 swf_SetU16(sprtag
, id
);
1420 swf_SetU16(sprtag
, frames
);
1422 t
= swf_NextTag(sprtag
);
1428 (t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
&&t
->id
!=ST_SOUNDSTREAMBLOCK
&&
1429 t
->id
!=ST_DEFINEBITSJPEG
&&t
->id
!=ST_DEFINEBITSJPEG2
&&t
->id
!=ST_DEFINEBITSJPEG3
)
1431 swf_SetU16(sprtag
,t
->len
|(t
->id
<<6));
1433 swf_SetU16(sprtag
,0x3f|(t
->id
<<6));
1434 swf_SetU32(sprtag
,t
->len
);
1437 swf_SetBlock(sprtag
,t
->data
, t
->len
);
1439 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1444 swf_DeleteTag(0, tmp
);
1448 fprintf(stderr
, "rfxswf error: sprite doesn't end(2)\n");
1450 // sprtag->next = t;
1451 // t->prev = sprtag;
1454 int swf_IsFolded(TAG
* t
)
1456 return (t
->id
== ST_DEFINESPRITE
&& t
->len
>4);
1459 void swf_FoldAll(SWF
*swf
)
1461 TAG
*tag
= swf
->firstTag
;
1462 //swf_DumpSWF(stdout, swf);
1464 if(tag
->id
== ST_DEFINESPRITE
) {
1465 swf_FoldSprite(tag
);
1466 //swf_DumpSWF(stdout, swf);
1468 tag
= swf_NextTag(tag
);
1472 void swf_UnFoldAll(SWF
*swf
)
1474 TAG
*tag
= swf
->firstTag
;
1476 if(tag
->id
== ST_DEFINESPRITE
)
1477 swf_UnFoldSprite(tag
);
1482 void swf_OptimizeTagOrder(SWF
*swf
)
1489 /* at the moment, we don't actually do optimizing,
1490 only fixing of non-spec-conformant things like
1497 tag
= swf
->firstTag
;
1500 if(tag
->id
== ST_DEFINESPRITE
) {
1502 /* ??? all sprites are supposed to be unfolded */
1503 fprintf(stderr
, "librfxswf error - internal error in OptimizeTagOrder/UnfoldAll\n");
1513 /* move non-sprite tags out of sprite */
1514 if(!swf_isAllowedSpriteTag(tag
) || level
>=2) {
1515 /* remove tag from current position */
1516 tag
->prev
->next
= tag
->next
;
1518 tag
->next
->prev
= tag
->prev
;
1520 /* insert before tag level0 */
1522 tag
->prev
= level0
->prev
;
1525 tag
->prev
->next
= tag
;
1527 swf
->firstTag
= tag
;
1531 if(tag
->id
== ST_END
) {
1542 int swf_ReadSWF2(reader_t
*reader
, SWF
* swf
) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
1544 if (!swf
) return -1;
1545 memset(swf
,0x00,sizeof(SWF
));
1547 { char b
[32]; // read Header
1553 if ((len
= reader
->read(reader
,b
,8))<8) return -1;
1555 if (b
[0]!='F' && b
[0]!='C') return -1;
1556 if (b
[1]!='W') return -1;
1557 if (b
[2]!='S') return -1;
1558 swf
->fileVersion
= b
[3];
1559 swf
->compressed
= (b
[0]=='C')?1:0;
1560 swf
->fileSize
= GET32(&b
[4]);
1562 if(swf
->compressed
) {
1563 reader_init_zlibinflate(&zreader
, reader
);
1566 swf
->compressed
= 0; // derive from version number from now on
1568 reader_GetRect(reader
, &swf
->movieSize
);
1569 reader
->read(reader
, &swf
->frameRate
, 2);
1570 swf
->frameRate
= LE_16_TO_NATIVE(swf
->frameRate
);
1571 reader
->read(reader
, &swf
->frameCount
, 2);
1572 swf
->frameCount
= LE_16_TO_NATIVE(swf
->frameCount
);
1574 /* read tags and connect to list */
1578 t
= swf_ReadTag(reader
,t
);
1579 if(t
&& t
->id
== ST_FILEATTRIBUTES
) {
1580 swf
->fileAttributes
= swf_GetU32(t
);
1581 swf_ResetReadBits(t
);
1584 swf
->firstTag
= t1
.next
;
1586 t1
.next
->prev
= NULL
;
1592 SWF
* swf_OpenSWF(char*filename
)
1594 int fi
= open(filename
, O_RDONLY
|O_BINARY
);
1596 fprintf(stderr
, "Failed to open %s\n", filename
);
1599 SWF
* swf
= rfx_alloc(sizeof(SWF
));
1600 swf_ReadSWF(fi
, swf
);
1605 int swf_ReadSWF(int handle
, SWF
* swf
)
1608 reader_init_filereader(&reader
, handle
);
1609 return swf_ReadSWF2(&reader
, swf
);
1612 void swf_ReadABCfile(char*filename
, SWF
*swf
)
1614 memset(swf
, 0, sizeof(SWF
));
1616 swf
->fileAttributes
=FILEATTRIBUTE_AS3
; //as3
1617 TAG
*tag
= swf
->firstTag
= swf_InsertTag(0, ST_RAWABC
);
1618 memfile_t
*file
= memfile_open(filename
);
1619 swf_SetBlock(tag
, file
->data
, file
->len
);
1620 memfile_close(file
);
1623 int no_extra_tags
= 0;
1625 int WriteExtraTags(SWF
*swf
, writer_t
*writer
)
1627 TAG
*t
= swf
->firstTag
;
1628 TAG
* has_fileattributes
=0;
1629 int has_scenedescription
=0;
1630 int has_version_8_action
=0;
1631 int has_version_9_action
=0;
1634 if(t
->id
== ST_FILEATTRIBUTES
)
1635 has_fileattributes
= t
;
1636 if(t
->id
== ST_SCENEDESCRIPTION
)
1637 has_scenedescription
= 1;
1638 if(t
->id
== ST_DOABC
)
1639 has_version_9_action
=1;
1640 /* FIXME: this doesn't yet find actionscript in buttons */
1641 if(t
->id
== ST_DOACTION
|| t
->id
== ST_DOINITACTION
)
1642 has_version_8_action
=1;
1643 if(t
->id
== ST_PLACEOBJECT2
&& t
->len
&& (t
->data
[0]&0x80))
1644 has_version_8_action
=1;
1647 if(has_version_8_action
&& has_version_9_action
) {
1648 fprintf(stderr
, "Warning: File contains both flash 8 and flash 9 actionscript\n");
1651 if(swf
->fileVersion
>= 9) {
1652 if(!has_fileattributes
) {
1653 U32 flags
= swf
->fileAttributes
|FILEATTRIBUTE_AS3
; // 16 = has symbolclass tag | 8 = actionscript3 | 1 = usenetwork
1654 if(has_version_8_action
&& !has_version_9_action
)
1655 flags
&= ~FILEATTRIBUTE_AS3
;
1656 TAG
*fileattrib
= swf_InsertTag(0, ST_FILEATTRIBUTES
);
1657 swf_SetU32(fileattrib
, flags
);
1659 if(swf_WriteTag2(writer
, fileattrib
)<0)
1662 len
+= swf_WriteTag(-1,fileattrib
);
1664 swf_DeleteTag(0, fileattrib
);
1666 if(swf
->fileAttributes
) {
1667 /* if we're writing a file out again where we might have possible
1668 modified the fileattributes in the header, adjust the tag data */
1669 TAG
*tt
= swf_CopyTag(0,has_fileattributes
);
1670 U32 flags
= swf_GetU32(tt
) | swf
->fileAttributes
;
1671 swf_ResetTag(tt
, tt
->id
);
1672 swf_SetU32(tt
, flags
);
1673 if(swf_WriteTag2(writer
, has_fileattributes
)<0) return -1;
1674 swf_DeleteTag(0, tt
);
1676 if(swf_WriteTag2(writer
, has_fileattributes
)<0)
1680 if(0 && !has_scenedescription
) {
1681 TAG
*scene
= swf_InsertTag(0, ST_SCENEDESCRIPTION
);
1682 swf_SetU16(scene
, 1);
1683 swf_SetString(scene
, "Scene 1");
1684 swf_SetU8(scene
, 0);
1686 if(swf_WriteTag2(writer
, scene
)<0)
1689 len
+= swf_WriteTag(-1,scene
);
1691 swf_DeleteTag(0, scene
);
1697 int swf_WriteSWF2(writer_t
*writer
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1705 writer_t
*original_writer
= writer
;
1706 int writer_lastpos
= 0;
1708 if (!swf
) return -1;
1709 if (!writer
) return -1; // the caller should provide a nullwriter, not 0, for querying SWF size
1711 if(original_writer
) writer_lastpos
= original_writer
->pos
;
1713 // Count Frames + File Size
1719 if(swf
->firstTag
&& !no_extra_tags
) {
1720 len
+= WriteExtraTags(swf
, 0);
1723 len
+= swf_WriteTag(-1,t
);
1724 if(t
->id
== ST_DEFINESPRITE
&& !swf_IsFolded(t
)) inSprite
++;
1725 else if(t
->id
== ST_END
&& inSprite
) inSprite
--;
1726 else if(t
->id
== ST_END
&& !inSprite
) {
1727 if(t
->prev
&& t
->prev
->id
!=ST_SHOWFRAME
)
1730 else if(t
->id
== ST_SHOWFRAME
&& !inSprite
) frameCount
++;
1738 memset(&t1
,0x00,sizeof(TAG
));
1742 { // measure header file size
1745 memset(&t2
,0x00,sizeof(TAG
));
1748 swf_SetRect(&t2
, &swf
->movieSize
);
1749 swf_SetU16(&t2
, swf
->frameRate
);
1750 swf_SetU16(&t2
, swf
->frameCount
);
1751 l
= swf_GetTagLen(&t2
)+8;
1753 if(swf
->compressed
== 8) {
1758 if(len
) {// don't touch headers without tags
1759 swf
->fileSize
= fileSize
;
1760 swf
->frameCount
= frameCount
;
1763 if(swf
->compressed
!= 8) {
1764 /* compressed flag set to 8 means "skip first 8
1765 header bytes". This is necessary if the caller wants to
1766 create compressed SWFs himself .
1767 It also means that we don't initialize our own zlib
1768 writer, but assume the caller provided one.
1770 if(swf
->compressed
==1 || (swf
->compressed
==0 && swf
->fileVersion
>=6)) {
1772 writer
->write(writer
, id
, 3);
1775 writer
->write(writer
, id
, 3);
1778 writer
->write(writer
, &swf
->fileVersion
, 1);
1779 PUT32(b4
, swf
->fileSize
);
1780 writer
->write(writer
, b4
, 4);
1782 if(swf
->compressed
==1 || (swf
->compressed
==0 && swf
->fileVersion
>=6)) {
1783 writer_init_zlibdeflate(&zwriter
, writer
);
1788 swf_SetRect(&t1
,&swf
->movieSize
);
1789 swf_SetU16(&t1
,swf
->frameRate
);
1790 swf_SetU16(&t1
,swf
->frameCount
);
1792 ret
= writer
->write(writer
,b
,swf_GetTagLen(&t1
));
1793 if (ret
!=swf_GetTagLen(&t1
))
1796 fprintf(stderr
, "ret:%d\n",ret
);
1798 fprintf(stderr
,"WriteSWF() failed: Header.\n");
1803 if(swf
->firstTag
&& !no_extra_tags
) {
1804 WriteExtraTags(swf
, writer
);
1809 if(no_extra_tags
|| t
->id
!= ST_FILEATTRIBUTES
) {
1810 if(swf_WriteTag2(writer
, t
)<0)
1815 if(swf
->compressed
==1 || (swf
->compressed
==0 && swf
->fileVersion
>=6) || swf
->compressed
==8) {
1816 if(swf
->compressed
!= 8) {
1817 zwriter
.finish(&zwriter
);
1818 return original_writer
->pos
- writer_lastpos
;
1820 return (int)fileSize
;
1822 return (int)fileSize
;
1827 int swf_SaveSWF(SWF
* swf
, char*filename
)
1829 int fi
= open(filename
, O_BINARY
|O_RDWR
|O_TRUNC
|O_CREAT
, 0777);
1834 if(swf_WriteSWF(fi
, swf
)<0) {
1835 fprintf(stderr
, "Unable to write output file: %s\n", filename
);
1842 int swf_WriteSWF(int handle
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1848 writer_init_nullwriter(&writer
);
1849 len
= swf_WriteSWF2(&writer
, swf
);
1852 writer_init_filewriter(&writer
, handle
);
1853 len
= swf_WriteSWF2(&writer
, swf
);
1854 writer
.finish(&writer
);
1858 int swf_WriteHeader2(writer_t
*writer
,SWF
* swf
)
1861 memcpy(&myswf
,swf
,sizeof(SWF
));
1863 return swf_WriteSWF2(writer
, &myswf
);
1866 int swf_WriteHeader(int handle
,SWF
* swf
)
1869 memcpy(&myswf
,swf
,sizeof(SWF
));
1871 return swf_WriteSWF(handle
, &myswf
);
1874 int swf_WriteCGI(SWF
* swf
)
1878 len
= swf_WriteSWF(-1,swf
);
1880 if (len
<0) return -1;
1882 sprintf(s
,"Content-type: application/x-shockwave-flash\n"
1883 "Accept-Ranges: bytes\n"
1884 "Content-Length: %d\n"
1885 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
1888 write(fileno(stdout
),s
,strlen(s
));
1889 return swf_WriteSWF(fileno(stdout
),swf
);
1892 SWF
* swf_CopySWF(SWF
*swf
)
1894 SWF
*nswf
= (SWF
*)rfx_alloc(sizeof(SWF
));
1896 memcpy(nswf
, swf
, sizeof(SWF
));
1898 tag
= swf
->firstTag
;
1901 ntag
= swf_CopyTag(ntag
, tag
);
1903 nswf
->firstTag
= ntag
;
1909 void swf_FreeTags(SWF
* swf
) // Frees all malloc'ed memory for tags
1910 { TAG
* t
= swf
->firstTag
;
1913 { TAG
* tnew
= t
->next
;
1914 if (t
->data
) rfx_free(t
->data
);
1921 // include advanced functions
1923 //#include "modules/swfdump.c"
1924 //#include "modules/swfshape.c"
1925 //#include "modules/swftext.c"
1926 //#include "modules/swffont.c"
1927 //#include "modules/swfobject.c"
1928 //#include "modules/swfbutton.c"
1929 //#include "modules/swftools.c"
1930 //#include "modules/swfcgi.c"
1931 //#include "modules/swfbits.c"
1932 //#include "modules/swfaction.c"
1933 //#include "modules/swfabc.c"
1934 //#include "modules/swfsound.c"
1935 //#include "modules/swfdraw.c"
1936 //#include "modules/swfrender.c"
1937 //#include "modules/swffilter.c"