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
);
100 return t
->data
[t
->pos
++];
103 U16
swf_GetU16(TAG
* t
)
105 swf_ResetReadBits(t
);
107 if ((int)t
->pos
>((int)t
->len
-2))
108 { fprintf(stderr
,"GetU16() out of bounds: TagID = %i\n",t
->id
);
112 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8);
117 U32
swf_GetU32(TAG
* t
)
119 swf_ResetReadBits(t
);
121 if ((int)t
->pos
>((int)t
->len
-4))
122 { fprintf(stderr
,"GetU32() out of bounds: TagID = %i\n",t
->id
);
126 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8) |
127 (t
->data
[t
->pos
+2]<<16) | (t
->data
[t
->pos
+3]<<24);
132 int swf_GetBlock(TAG
* t
,U8
* b
,int l
)
133 // returns number of bytes written (<=l)
134 // b = NULL -> skip data
135 { swf_ResetReadBits(t
);
136 if ((t
->len
-t
->pos
)<l
) l
=t
->len
-t
->pos
;
137 if (b
&& l
) memcpy(b
,&t
->data
[t
->pos
],l
);
142 int swf_SetBlock(TAG
* t
,const U8
* b
,int l
)
143 // Appends Block to the end of Tagdata, returns size
144 { U32 newlen
= t
->len
+ l
;
145 swf_ResetWriteBits(t
);
146 if (newlen
>t
->memsize
)
147 { U32 newmem
= MEMSIZE(newlen
);
148 U8
* newdata
= (U8
*)(rfx_realloc(t
->data
,newmem
));
152 if (b
) memcpy(&t
->data
[t
->len
],b
,l
);
153 else memset(&t
->data
[t
->len
],0x00,l
);
158 int swf_SetU8(TAG
* t
,U8 v
)
159 { swf_ResetWriteBits(t
);
160 if ((t
->len
+1)>t
->memsize
) return (swf_SetBlock(t
,&v
,1)==1)?0:-1;
161 t
->data
[t
->len
++] = v
;
165 int swf_SetU16(TAG
* t
,U16 v
)
170 swf_ResetWriteBits(t
);
171 if ((t
->len
+2)>t
->memsize
) return (swf_SetBlock(t
,a
,2)==2)?0:-1;
172 t
->data
[t
->len
++] = a
[0];
173 t
->data
[t
->len
++] = a
[1];
176 void swf_SetS16(TAG
* t
,int v
)
178 if(v
>32767 || v
<-32768) {
180 fprintf(stderr
, "Warning: S16 overflow: %d\n", v
);
183 swf_SetU16(t
, (S16
)v
);
186 int swf_SetU32(TAG
* t
,U32 v
)
188 a
[0] = v
&0xff; // to ensure correct handling of non-intel byteorder
193 swf_ResetWriteBits(t
);
194 if ((t
->len
+4)>t
->memsize
) return (swf_SetBlock(t
,a
,4)==4)?0:-1;
195 t
->data
[t
->len
++] = a
[0];
196 t
->data
[t
->len
++] = a
[1];
197 t
->data
[t
->len
++] = a
[2];
198 t
->data
[t
->len
++] = a
[3];
202 U32
swf_GetBits(TAG
* t
,int nbits
)
204 if (!nbits
) return 0;
205 if (!t
->readBit
) t
->readBit
= 0x80;
210 { fprintf(stderr
,"GetBits() out of bounds: TagID = %i, pos=%d, len=%d\n",t
->id
, t
->pos
, t
->len
);
211 int i
,m
=t
->len
>10?10:t
->len
;
213 fprintf(stderr
, "(%d)%02x ", i
, t
->data
[i
]);
215 fprintf(stderr
, "\n");
219 if (t
->data
[t
->pos
]&t
->readBit
) res
|=1;
223 { if (nbits
) t
->readBit
= 0x80;
230 S32
swf_GetSBits(TAG
* t
,int nbits
)
231 { U32 res
= swf_GetBits(t
,nbits
);
232 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
236 U32
reader_GetBits(reader_t
*reader
, int nbits
)
237 { return reader_readbits(reader
, nbits
);
239 S32
reader_GetSBits(reader_t
*reader
, int nbits
)
240 { U32 res
= reader_readbits(reader
, nbits
);
241 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
245 int swf_SetBits(TAG
* t
,U32 v
,int nbits
)
246 { U32 bm
= 1<<(nbits
-1);
250 { if (FAILED(swf_SetU8(t
,0))) return -1;
253 if (v
&bm
) t
->data
[t
->len
-1] |= t
->writeBit
;
261 // Advanced Data Access Functions
263 double swf_GetFixed(TAG
* t
)
265 U16 low
= swf_GetU16(t
);
266 U16 high
= swf_GetU16(t
);
267 return high
+ low
*(1/65536.0);
269 void swf_SetFixed(TAG
* t
, double f
)
271 U16 fr
= (U16
)((f
-(int)f
)*65536);
273 swf_SetU16(t
, (U16
)f
- (f
<0 && fr
!=0));
275 float swf_GetFixed8(TAG
* t
)
277 U8 low
= swf_GetU8(t
);
278 U8 high
= swf_GetU8(t
);
279 return (float)(high
+ low
*(1/256.0));
281 void swf_SetFixed8(TAG
* t
, float f
)
283 U8 fr
= (U8
)((f
-(int)f
)*256);
285 swf_SetU8(t
, (U8
)f
- (f
<0 && fr
!=0));
288 U32
swf_GetU30(TAG
*tag
)
294 U8 b
= swf_GetU8(tag
);
298 if(!(b
&128) || shift
>=32)
301 /*int nr2= swf_SetU30(0, s);
303 printf("Unsigned value %d stored in %d bytes, I'd store it in %d bytes\n", s, nr, nr2);
308 int swf_SetU30(TAG
*tag
, U32 u
)
313 swf_SetU8(tag
, (u
&~0x7f?0x80:0) | (u
&0x7F));
320 void swf_SetABCU32(TAG
*tag
, U32 u
)
323 swf_SetU8(tag
, (u
&~0x7f?0x80:0) | (u
&0x7F));
327 U32
swf_GetABCU32(TAG
*tag
)
329 return swf_GetU30(tag
);
331 void swf_SetABCS32(TAG
*tag
, S32 v
)
333 swf_SetABCU32(tag
, v
);
335 S32
swf_GetABCS32(TAG
*tag
)
337 return swf_GetABCU32(tag
);
342 /*The AVM2 spec is just plain wrong, claiming that S32 values are sign
343 extended. They're not.
344 This wastes up to 4 bytes for every negative value. */
346 void swf_SetABCS32(TAG
*tag
, S32 s
)
348 printf("write S32: %d\n", s
);
350 U8 sign
= s
<0?0x40:0;
356 if(s
==neg
&& vsign
==sign
) {
357 /* if the value we now write has the same sign as s
358 and all the remaining bits are equal to the sign of s
361 printf("put %02x\n", val
);
364 swf_SetU8(tag
, 0x80 | val
);
365 printf("put %02x\n", 0x80|val
);
369 int swf_GetS30(TAG
*tag
)
375 U8 b
= swf_GetU8(tag
);
377 nt i
,m
=t
->len
>10?10:t
->len
;
379 fprintf(stderr
, "%02x ", t
->data
[i
]);
381 fprintf(stderr
, "\n");
384 if(!(b
&128) || shift
>=32) {
387 s
|=0xffffffff<<shift
;
392 /* It's not uncommon for other applications (Flex for all negative numbers, and
393 Flash for -1) to generate a lot more bytes than would be necessary.
394 int nr2= swf_SetS30(0, s);
396 printf("Signed value %d stored in %d bytes, I'd store it in %d bytes\n", s, nr, nr2);
402 int swf_SetU30String(TAG
*tag
, const char*str
, int l
)
405 len
+=swf_SetU30(tag
, l
);
407 swf_SetBlock(tag
, (void*)str
, l
);
411 float swf_GetF16(TAG
* t
)
413 U16 f1
= swf_GetU16(t
);
414 if(!(f1
&0x3ff)) return 0.0;
418 /* gcc 4.1.2 seems to require a union here. *(float*)u doesn't work */
424 U16 e
= (f1
>>10)&0x1f;
426 /* find highest bit in mantissa */
436 f2
.u
= (f1
&0x8000)<<16; //sign
437 f2
.u
|= e
<<23; //exponent
438 f2
.u
|= m
<<13; //mantissa
442 void swf_SetF16(TAG
* t
, float f
)
450 U16 result
= (v
.u
>>16)&0x8000; //sign
451 int exp
= ((v
.u
>>23)&0xff)-0x7f+0x10;
452 U16 m
= (v
.u
>>13)&0x3ff;
453 //fprintf(stderr, "%f: %04x sign, %d exp, %04x mantissa\n", f, result, exp, m);
455 // underflow (clamp to 0.0)
459 // partial underflow- strip some bits
465 fprintf(stderr
, "Exponent overflow in FLOAT16 encoding\n");
472 swf_SetU16(t
, result
);
475 float F16toFloat(U16 x
)
482 return swf_GetF16(&t
);
485 float floatToF16(float f
)
497 float swf_GetFloat(TAG
*tag
)
503 f
.uint_bits
= swf_GetU32(tag
);
507 void swf_SetFloat(TAG
*tag
, float v
)
514 swf_SetU32(tag
, f
.uint_bits
);
517 double swf_GetD64(TAG
*tag
)
519 /* FIXME: this is not big-endian compatible */
520 double value
= *(double*)&tag
->data
[tag
->pos
];
525 int swf_SetD64(TAG
*tag
, double v
)
527 /* FIXME: this is not big-endian compatible */
528 swf_SetU32(tag
, ((U32
*)&v
)[0]);
529 swf_SetU32(tag
, ((U32
*)&v
)[1]);
532 int swf_GetU24(TAG
*tag
)
534 int b1
= swf_GetU8(tag
);
535 int b2
= swf_GetU8(tag
);
536 int b3
= swf_GetU8(tag
);
537 return b3
<<16|b2
<<8|b1
;
539 int swf_GetS24(TAG
*tag
)
541 int b1
= swf_GetU8(tag
);
542 int b2
= swf_GetU8(tag
);
543 int b3
= swf_GetU8(tag
);
545 return -1-((b3
<<16|b2
<<8|b1
)^0xffffff);
547 return b3
<<16|b2
<<8|b1
;
550 int swf_SetU24(TAG
*tag
, U32 v
)
554 fprintf(stderr
, "Error: Overflow in swf_SetU24()\n");
556 swf_SetU8(tag
, v
>>8);
557 swf_SetU8(tag
, v
>>16);
561 int swf_SetS24(TAG
*tag
, U32 v
)
565 return swf_SetU24(tag
, v
);
566 if((v
&0xff000000)!=0xff000000) {
567 fprintf(stderr
, "Error: Overflow in swf_SetS24()\n");
570 swf_SetU8(tag
, v
>>8);
571 swf_SetU8(tag
, v
>>16);
577 int swf_SetRGB(TAG
* t
,RGBA
* col
)
580 { swf_SetU8(t
,col
->r
);
583 } else swf_SetBlock(t
,NULL
,3);
586 void swf_GetRGB(TAG
* t
, RGBA
* col
)
591 col
->r
= swf_GetU8(t
);
592 col
->g
= swf_GetU8(t
);
593 col
->b
= swf_GetU8(t
);
597 int swf_SetRGBA(TAG
* t
,RGBA
* col
)
600 { swf_SetU8(t
,col
->r
);
604 } else swf_SetBlock(t
,NULL
,4);
607 void swf_GetRGBA(TAG
* t
, RGBA
* col
)
612 col
->r
= swf_GetU8(t
);
613 col
->g
= swf_GetU8(t
);
614 col
->b
= swf_GetU8(t
);
615 col
->a
= swf_GetU8(t
);
618 void swf_GetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
622 memset(gradient
, 0, sizeof(GRADIENT
));
625 U8 num
= swf_GetU8(tag
) & 15;
628 gradient
->rgba
= (RGBA
*)rfx_calloc(sizeof(RGBA
)*gradient
->num
);
629 gradient
->ratios
= (U8
*)rfx_calloc(sizeof(gradient
->ratios
[0])*gradient
->num
);
633 U8 ratio
= swf_GetU8(tag
);
636 swf_GetRGB(tag
, &color
);
638 swf_GetRGBA(tag
, &color
);
640 gradient
->ratios
[t
] = ratio
;
641 gradient
->rgba
[t
] = color
;
646 void swf_SetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
650 memset(gradient
, 0, sizeof(GRADIENT
));
653 swf_SetU8(tag
, gradient
->num
);
654 for(t
=0; t
<8 && t
<gradient
->num
; t
++)
656 swf_SetU8(tag
, gradient
->ratios
[t
]);
658 swf_SetRGB(tag
, &gradient
->rgba
[t
]);
660 swf_SetRGBA(tag
, &gradient
->rgba
[t
]);
664 void swf_FreeGradient(GRADIENT
* gradient
)
667 rfx_free(gradient
->ratios
);
669 rfx_free(gradient
->rgba
);
670 memset(gradient
, 0, sizeof(GRADIENT
));
673 int swf_CountUBits(U32 v
,int nbits
)
676 if(v
== 0x00000000) n
= 0;
682 return (n
>nbits
)?n
:nbits
;
685 int swf_CountBits(U32 v
,int nbits
)
689 { if(v
== 0xffffffff) n
= 1;
697 { if(v
== 0x00000000) n
= 0;
704 return (n
>nbits
)?n
:nbits
;
707 int swf_GetRect(TAG
* t
,SRECT
* r
)
710 if(!t
) {r
->xmin
=r
->xmax
=r
->ymin
=r
->ymax
=0;return 0;}
712 nbits
= (int) swf_GetBits(t
,5);
713 r
->xmin
= swf_GetSBits(t
,nbits
);
714 r
->xmax
= swf_GetSBits(t
,nbits
);
715 r
->ymin
= swf_GetSBits(t
,nbits
);
716 r
->ymax
= swf_GetSBits(t
,nbits
);
720 int reader_GetRect(reader_t
*reader
,SRECT
* r
)
724 nbits
= (int) reader_GetBits(reader
,5);
725 r
->xmin
= reader_GetSBits(reader
,nbits
);
726 r
->xmax
= reader_GetSBits(reader
,nbits
);
727 r
->ymin
= reader_GetSBits(reader
,nbits
);
728 r
->ymax
= reader_GetSBits(reader
,nbits
);
732 int swf_SetRect(TAG
* t
,SRECT
* r
)
735 nbits
= swf_CountBits(r
->xmin
,0);
736 nbits
= swf_CountBits(r
->xmax
,nbits
);
737 nbits
= swf_CountBits(r
->ymin
,nbits
);
738 nbits
= swf_CountBits(r
->ymax
,nbits
);
741 fprintf(stderr
, "rfxswf: Warning: num_bits overflow in swf_SetRect\n");
746 swf_SetBits(t
,nbits
,5);
747 swf_SetBits(t
,r
->xmin
,nbits
);
748 swf_SetBits(t
,r
->xmax
,nbits
);
749 swf_SetBits(t
,r
->ymin
,nbits
);
750 swf_SetBits(t
,r
->ymax
,nbits
);
755 SRECT
swf_ClipRect(SRECT border
, SRECT r
)
757 if(r
.xmax
> border
.xmax
) r
.xmax
= border
.xmax
;
758 if(r
.ymax
> border
.ymax
) r
.ymax
= border
.ymax
;
759 if(r
.xmax
< border
.xmin
) r
.xmax
= border
.xmin
;
760 if(r
.ymax
< border
.ymin
) r
.ymax
= border
.ymin
;
762 if(r
.xmin
> border
.xmax
) r
.xmin
= border
.xmax
;
763 if(r
.ymin
> border
.ymax
) r
.ymin
= border
.ymax
;
764 if(r
.xmin
< border
.xmin
) r
.xmin
= border
.xmin
;
765 if(r
.ymin
< border
.ymin
) r
.ymin
= border
.ymin
;
769 void swf_ExpandRect(SRECT
*src
, SPOINT add
)
771 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
776 if((add
.x
|add
.y
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
779 if(add
.x
< src
->xmin
)
781 if(add
.x
> src
->xmax
)
783 if(add
.y
< src
->ymin
)
785 if(add
.y
> src
->ymax
)
788 void swf_ExpandRect2(SRECT
*src
, SRECT
*add
)
790 if((add
->xmin
| add
->ymin
| add
->xmax
| add
->ymax
)==0)
792 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0)
794 if(add
->xmin
< src
->xmin
)
795 src
->xmin
= add
->xmin
;
796 if(add
->ymin
< src
->ymin
)
797 src
->ymin
= add
->ymin
;
798 if(add
->xmax
> src
->xmax
)
799 src
->xmax
= add
->xmax
;
800 if(add
->ymax
> src
->ymax
)
801 src
->ymax
= add
->ymax
;
803 void swf_ExpandRect3(SRECT
*src
, SPOINT center
, int radius
)
805 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
806 src
->xmin
= center
.x
-radius
;
807 src
->ymin
= center
.y
-radius
;
808 src
->xmax
= center
.x
+radius
;
809 src
->ymax
= center
.y
+radius
;
810 if((center
.x
|center
.y
|radius
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
813 if(center
.x
- radius
< src
->xmin
)
814 src
->xmin
= center
.x
- radius
;
815 if(center
.x
+ radius
> src
->xmax
)
816 src
->xmax
= center
.x
+ radius
;
817 if(center
.y
- radius
< src
->ymin
)
818 src
->ymin
= center
.y
- radius
;
819 if(center
.y
+ radius
> src
->ymax
)
820 src
->ymax
= center
.y
+ radius
;
822 SPOINT
swf_TurnPoint(SPOINT p
, MATRIX
* m
)
825 r
.x
= (int)(m
->sx
*(1/65536.0)*p
.x
+ m
->r1
*(1/65536.0)*p
.y
+ 0.5) + m
->tx
;
826 r
.y
= (int)(m
->r0
*(1/65536.0)*p
.x
+ m
->sy
*(1/65536.0)*p
.y
+ 0.5) + m
->ty
;
829 SRECT
swf_TurnRect(SRECT r
, MATRIX
* m
)
832 SPOINT p1
,p2
,p3
,p4
,pp1
,pp2
,pp3
,pp4
;
835 p1
.x
= r
.xmin
;p1
.y
= r
.ymin
;
836 p2
.x
= r
.xmax
;p2
.y
= r
.ymin
;
837 p3
.x
= r
.xmin
;p3
.y
= r
.ymax
;
838 p4
.x
= r
.xmax
;p4
.y
= r
.ymax
;
839 pp1
= swf_TurnPoint(p1
, m
);
840 pp2
= swf_TurnPoint(p2
, m
);
841 pp3
= swf_TurnPoint(p3
, m
);
842 pp4
= swf_TurnPoint(p4
, m
);
843 g
.xmin
= g
.xmax
= pp1
.x
;
844 g
.ymin
= g
.ymax
= pp1
.y
;
845 swf_ExpandRect(&g
, pp2
);
846 swf_ExpandRect(&g
, pp3
);
847 swf_ExpandRect(&g
, pp4
);
852 int swf_GetMatrix(TAG
* t
,MATRIX
* m
)
859 { m
->sx
= m
->sy
= 0x10000;
865 swf_ResetReadBits(t
);
867 if (swf_GetBits(t
,1))
868 { nbits
= swf_GetBits(t
,5);
869 m
->sx
= swf_GetSBits(t
,nbits
);
870 m
->sy
= swf_GetSBits(t
,nbits
);
872 else m
->sx
= m
->sy
= 0x10000;
874 if (swf_GetBits(t
,1))
875 { nbits
= swf_GetBits(t
,5);
876 m
->r0
= swf_GetSBits(t
,nbits
);
877 m
->r1
= swf_GetSBits(t
,nbits
);
879 else m
->r0
= m
->r1
= 0x0;
881 nbits
= swf_GetBits(t
,5);
882 m
->tx
= swf_GetSBits(t
,nbits
);
883 m
->ty
= swf_GetSBits(t
,nbits
);
888 int swf_SetMatrix(TAG
* t
,MATRIX
* m
)
894 ma
.sx
= ma
.sy
= 0x10000;
899 swf_ResetWriteBits(t
);
901 if ((m
->sx
==0x10000)&&(m
->sy
==0x10000)) swf_SetBits(t
,0,1);
903 { swf_SetBits(t
,1,1);
904 nbits
= swf_CountBits(m
->sx
,0);
905 nbits
= swf_CountBits(m
->sy
,nbits
);
907 /* TODO: happens on AMD64 systems for normal values? */
909 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
913 swf_SetBits(t
,nbits
,5);
914 swf_SetBits(t
,m
->sx
,nbits
);
915 swf_SetBits(t
,m
->sy
,nbits
);
918 if ((!m
->r0
)&&(!m
->r1
)) swf_SetBits(t
,0,1);
920 { swf_SetBits(t
,1,1);
921 nbits
= swf_CountBits(m
->r0
,0);
922 nbits
= swf_CountBits(m
->r1
,nbits
);
925 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
929 swf_SetBits(t
,nbits
,5);
930 swf_SetBits(t
,m
->r0
,nbits
);
931 swf_SetBits(t
,m
->r1
,nbits
);
934 nbits
= swf_CountBits(m
->tx
,0);
935 nbits
= swf_CountBits(m
->ty
,nbits
);
938 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
942 swf_SetBits(t
,nbits
,5);
943 swf_SetBits(t
,m
->tx
,nbits
);
944 swf_SetBits(t
,m
->ty
,nbits
);
949 int swf_GetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
)
957 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
958 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
962 swf_ResetReadBits(t
);
963 hasadd
= swf_GetBits(t
,1);
964 hasmul
= swf_GetBits(t
,1);
965 nbits
= swf_GetBits(t
,4);
968 { cx
->r0
= (S16
)swf_GetSBits(t
,nbits
);
969 cx
->g0
= (S16
)swf_GetSBits(t
,nbits
);
970 cx
->b0
= (S16
)swf_GetSBits(t
,nbits
);
972 cx
->a0
= (S16
)swf_GetSBits(t
,nbits
);
976 { cx
->r1
= (S16
)swf_GetSBits(t
,nbits
);
977 cx
->g1
= (S16
)swf_GetSBits(t
,nbits
);
978 cx
->b1
= (S16
)swf_GetSBits(t
,nbits
);
980 cx
->a1
= (S16
)swf_GetSBits(t
,nbits
);
986 int swf_SetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
)
994 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
995 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
1005 hasmul
= (cx
->a0
!=256)||(cx
->r0
!=256)||(cx
->g0
!=256)||(cx
->b0
!=256);
1006 hasadd
= cx
->a1
|cx
->r1
|cx
->g1
|cx
->b1
;
1009 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a0
,nbits
);
1010 nbits
= swf_CountBits((S32
)cx
->r0
,nbits
);
1011 nbits
= swf_CountBits((S32
)cx
->g0
,nbits
);
1012 nbits
= swf_CountBits((S32
)cx
->b0
,nbits
);
1016 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a1
,nbits
);
1017 nbits
= swf_CountBits((S32
)cx
->r1
,nbits
);
1018 nbits
= swf_CountBits((S32
)cx
->g1
,nbits
);
1019 nbits
= swf_CountBits((S32
)cx
->b1
,nbits
);
1022 swf_ResetWriteBits(t
);
1023 swf_SetBits(t
,hasadd
?1:0,1);
1024 swf_SetBits(t
,hasmul
?1:0,1);
1025 swf_SetBits(t
,nbits
,4);
1028 { swf_SetBits(t
,cx
->r0
,nbits
);
1029 swf_SetBits(t
,cx
->g0
,nbits
);
1030 swf_SetBits(t
,cx
->b0
,nbits
);
1031 if (alpha
) swf_SetBits(t
,cx
->a0
,nbits
);
1035 { swf_SetBits(t
,cx
->r1
,nbits
);
1036 swf_SetBits(t
,cx
->g1
,nbits
);
1037 swf_SetBits(t
,cx
->b1
,nbits
);
1038 if (alpha
) swf_SetBits(t
,cx
->a1
,nbits
);
1044 //int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
1045 //int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
1047 void swf_SetPassword(TAG
* t
, const char * password
)
1050 /* WARNING: crypt_md5 is not reentrant */
1054 #if defined(HAVE_LRAND48) && defined(HAVE_SRAND48) && defined(HAVE_TIME_H) && defined(HAVE_TIME)
1055 salt
[0] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
1056 salt
[1] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
1060 fprintf(stderr
, "rfxswf: Warning- no usable random generator found\n");
1061 fprintf(stderr
, "Your password will be vulnerable to dictionary attacks\n");
1065 md5string
= crypt_md5(password
, salt
);
1068 swf_SetString(t
, md5string
);
1070 fprintf(stderr
, "Error: No MD5 compiled in");
1074 void swf_SetString(TAG
*t
, const char* s
)
1079 swf_SetBlock(t
,(U8
*)s
,strlen(s
)+1);
1083 int swf_VerifyPassword(TAG
* t
, const char * password
)
1086 char*md5string1
, *md5string2
;
1091 if(t
->len
>= 5 && t
->pos
==0 &&
1096 printf("%d %d %d %d\n", t
->len
, t
->pos
, t
->data
[0], t
->data
[1]);
1099 md5string1
= swf_GetString(t
);
1101 if(strncmp(md5string1
, "$1$",3 )) {
1102 fprintf(stderr
, "rfxswf: no salt in pw string\n");
1105 x
= strchr(md5string1
+3, '$');
1107 fprintf(stderr
, "rfxswf: invalid salt format in pw string\n");
1110 n
= x
-(md5string1
+3);
1111 salt
= (char*)rfx_alloc(n
+1);
1112 memcpy(salt
, md5string1
+3, n
);
1115 md5string2
= crypt_md5(password
, salt
);
1117 if(strcmp(md5string1
, md5string2
) != 0)
1121 fprintf(stderr
, "Error: No MD5 compiled in");
1126 // Tag List Manipulating Functions
1128 TAG
* swf_InsertTag(TAG
* after
,U16 id
)
1131 t
= (TAG
*)rfx_calloc(sizeof(TAG
));
1137 t
->next
= after
->next
;
1139 if (t
->next
) t
->next
->prev
= t
;
1144 TAG
* swf_InsertTagBefore(SWF
* swf
, TAG
* before
,U16 id
)
1147 t
= (TAG
*)rfx_calloc(sizeof(TAG
));
1153 t
->prev
= before
->prev
;
1155 if (t
->prev
) t
->prev
->next
= t
;
1157 if(swf
&& swf
->firstTag
== before
) {
1163 void swf_ClearTag(TAG
* t
)
1165 if (t
->data
) rfx_free(t
->data
);
1174 void swf_ResetTag(TAG
*tag
, U16 id
)
1176 tag
->len
= tag
->pos
= tag
->readBit
= tag
->writeBit
= 0;
1180 TAG
* swf_CopyTag(TAG
*tag
, TAG
*to_copy
)
1182 tag
= swf_InsertTag(tag
, to_copy
->id
);
1183 swf_SetBlock(tag
, to_copy
->data
, to_copy
->len
);
1187 TAG
* swf_DeleteTag(SWF
*swf
, TAG
* t
)
1191 if (swf
&& swf
->firstTag
==t
)
1192 swf
->firstTag
= t
->next
;
1193 if (t
->prev
) t
->prev
->next
= t
->next
;
1194 if (t
->next
) t
->next
->prev
= t
->prev
;
1196 if (t
->data
) rfx_free(t
->data
);
1201 TAG
* swf_ReadTag(reader_t
*reader
, TAG
* prev
)
1207 if (reader
->read(reader
, &raw
, 2) !=2 ) return NULL
;
1208 raw
= LE_16_TO_NATIVE(raw
);
1215 len
= reader_readU32(reader
);
1218 if (id
==ST_DEFINESPRITE
) len
= 2*sizeof(U16
);
1219 // Sprite handling fix: Flatten sprite tree
1221 t
= (TAG
*)rfx_calloc(sizeof(TAG
));
1227 { t
->data
= (U8
*)rfx_alloc(t
->len
);
1228 t
->memsize
= t
->len
;
1229 if (reader
->read(reader
, t
->data
, t
->len
) != t
->len
) {
1231 fprintf(stderr
, "rfxswf: Warning: Short read (tagid %d). File truncated?\n", t
->id
);
1233 free(t
->data
);t
->data
=0;
1248 int swf_DefineSprite_GetRealSize(TAG
* t
);
1250 int swf_WriteTag2(writer_t
*writer
, TAG
* t
)
1251 // returns tag length in bytes (incl. Header), -1 = Error
1252 // writer = 0 -> no output
1259 len
= (t
->id
==ST_DEFINESPRITE
)?swf_DefineSprite_GetRealSize(t
):t
->len
;
1261 short_tag
= len
<0x3f&&
1262 (t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
&&t
->id
!=ST_SOUNDSTREAMBLOCK
&&
1263 t
->id
!=ST_DEFINEBITSJPEG
&&t
->id
!=ST_DEFINEBITSJPEG2
&&t
->id
!=ST_DEFINEBITSJPEG3
);
1268 int oldpos
= writer
->pos
;
1272 { raw
[0] = LE_16_TO_NATIVE(len
|((t
->id
&0x3ff)<<6));
1273 if (writer
->write(writer
,raw
,2)!=2)
1276 fprintf(stderr
,"WriteTag() failed: Short Header.\n");
1283 raw
[0] = LE_16_TO_NATIVE((t
->id
<<6)|0x3f);
1284 if (writer
->write(writer
,raw
,2)!=2)
1287 fprintf(stderr
,"WriteTag() failed: Long Header (1).\n");
1292 writer_writeU32(writer
, len
);
1296 { if (writer
->write(writer
,t
->data
,t
->len
)!=t
->len
)
1299 fprintf(stderr
,"WriteTag() failed: Data.\n");
1305 else if (t
->len
) fprintf(stderr
,"WriteTag(): Tag Data Error, id=%i\n",t
->id
);
1309 writer
->flush(writer
);
1310 printf("TAG %s costs %d bytes\n", swf_TagGetName(t
), writer
->pos
-oldpos
);
1314 return t
->len
+(short_tag
?2:6);
1317 int swf_WriteTag(int handle
, TAG
* t
)
1322 return swf_WriteTag2(0, t
);
1323 writer_init_filewriter(&writer
, handle
);
1324 len
= swf_WriteTag2(&writer
, t
);
1325 writer
.finish(&writer
);
1329 int swf_DefineSprite_GetRealSize(TAG
* t
)
1330 // Sprite Handling: Helper function to pack DefineSprite-Tag
1332 if(len
>4) { // folded sprite
1336 { t
= swf_NextTag(t
);
1337 if (t
&& t
->id
!=ST_DEFINESPRITE
) len
+= swf_WriteTag(-1, t
);
1339 } while (t
&&(t
->id
!=ST_END
));
1343 void swf_UnFoldSprite(TAG
* t
)
1348 U16 spriteid
,spriteframes
;
1350 if(t
->id
!=ST_DEFINESPRITE
)
1352 if(t
->len
<=4) // not folded
1357 spriteid
= swf_GetU16(t
); //id
1358 spriteframes
= swf_GetU16(t
); //frames
1365 tmp
= swf_GetU16(t
);
1370 if(id
== ST_DEFINESPRITE
&& len
<=4)
1374 len
= swf_GetU32(t
);
1375 it
= swf_InsertTag(next
, id
);
1380 { it
->data
= (U8
*)rfx_alloc(it
->len
);
1381 it
->memsize
= it
->len
;
1382 swf_GetBlock(t
, it
->data
, it
->len
);
1389 rfx_free(t
->data
); t
->data
= 0;
1390 t
->memsize
= t
->len
= t
->pos
= 0;
1392 swf_SetU16(t
, spriteid
);
1393 swf_SetU16(t
, spriteframes
);
1396 void swf_FoldSprite(TAG
* t
)
1401 if(t
->id
!=ST_DEFINESPRITE
)
1405 fprintf(stderr
, "Error: Sprite has no ID!");
1410 /* sprite is already folded */
1417 t
->len
= t
->pos
= t
->memsize
= 0;
1422 t
= swf_NextTag(sprtag
);
1427 if(t
->id
==ST_SHOWFRAME
) frames
++;
1428 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1433 } while(t
&& level
);
1435 fprintf(stderr
, "rfxswf error: sprite doesn't end(1)\n");
1437 swf_SetU16(sprtag
, id
);
1438 swf_SetU16(sprtag
, frames
);
1440 t
= swf_NextTag(sprtag
);
1446 (t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
&&t
->id
!=ST_SOUNDSTREAMBLOCK
&&
1447 t
->id
!=ST_DEFINEBITSJPEG
&&t
->id
!=ST_DEFINEBITSJPEG2
&&t
->id
!=ST_DEFINEBITSJPEG3
)
1449 swf_SetU16(sprtag
,t
->len
|(t
->id
<<6));
1451 swf_SetU16(sprtag
,0x3f|(t
->id
<<6));
1452 swf_SetU32(sprtag
,t
->len
);
1455 swf_SetBlock(sprtag
,t
->data
, t
->len
);
1457 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1462 swf_DeleteTag(0, tmp
);
1466 fprintf(stderr
, "rfxswf error: sprite doesn't end(2)\n");
1468 // sprtag->next = t;
1469 // t->prev = sprtag;
1472 int swf_IsFolded(TAG
* t
)
1474 return (t
->id
== ST_DEFINESPRITE
&& t
->len
>4);
1477 void swf_FoldAll(SWF
*swf
)
1479 TAG
*tag
= swf
->firstTag
;
1480 //swf_DumpSWF(stdout, swf);
1482 if(tag
->id
== ST_DEFINESPRITE
) {
1483 swf_FoldSprite(tag
);
1484 //swf_DumpSWF(stdout, swf);
1486 tag
= swf_NextTag(tag
);
1490 void swf_UnFoldAll(SWF
*swf
)
1492 TAG
*tag
= swf
->firstTag
;
1494 if(tag
->id
== ST_DEFINESPRITE
)
1495 swf_UnFoldSprite(tag
);
1500 void swf_OptimizeTagOrder(SWF
*swf
)
1507 /* at the moment, we don't actually do optimizing,
1508 only fixing of non-spec-conformant things like
1515 tag
= swf
->firstTag
;
1518 if(tag
->id
== ST_DEFINESPRITE
) {
1520 /* ??? all sprites are supposed to be unfolded */
1521 fprintf(stderr
, "librfxswf error - internal error in OptimizeTagOrder/UnfoldAll\n");
1531 /* move non-sprite tags out of sprite */
1532 if(!swf_isAllowedSpriteTag(tag
) || level
>=2) {
1533 /* remove tag from current position */
1534 tag
->prev
->next
= tag
->next
;
1536 tag
->next
->prev
= tag
->prev
;
1538 /* insert before tag level0 */
1540 tag
->prev
= level0
->prev
;
1543 tag
->prev
->next
= tag
;
1545 swf
->firstTag
= tag
;
1549 if(tag
->id
== ST_END
) {
1560 int swf_ReadSWF2(reader_t
*reader
, SWF
* swf
) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
1562 if (!swf
) return -1;
1563 memset(swf
,0x00,sizeof(SWF
));
1565 { char b
[32]; // read Header
1571 if ((len
= reader
->read(reader
,b
,8))<8) return -1;
1573 if (b
[0]!='F' && b
[0]!='C') return -1;
1574 if (b
[1]!='W') return -1;
1575 if (b
[2]!='S') return -1;
1576 swf
->fileVersion
= b
[3];
1577 swf
->compressed
= (b
[0]=='C')?1:0;
1578 swf
->fileSize
= GET32(&b
[4]);
1580 if(swf
->compressed
) {
1581 reader_init_zlibinflate(&zreader
, reader
);
1584 swf
->compressed
= 0; // derive from version number from now on
1586 reader_GetRect(reader
, &swf
->movieSize
);
1587 reader
->read(reader
, &swf
->frameRate
, 2);
1588 swf
->frameRate
= LE_16_TO_NATIVE(swf
->frameRate
);
1589 reader
->read(reader
, &swf
->frameCount
, 2);
1590 swf
->frameCount
= LE_16_TO_NATIVE(swf
->frameCount
);
1592 /* read tags and connect to list */
1596 t
= swf_ReadTag(reader
,t
);
1597 if(t
&& t
->id
== ST_FILEATTRIBUTES
) {
1598 swf
->fileAttributes
= swf_GetU32(t
);
1599 swf_ResetReadBits(t
);
1602 swf
->firstTag
= t1
.next
;
1604 t1
.next
->prev
= NULL
;
1610 SWF
* swf_OpenSWF(char*filename
)
1612 int fi
= open(filename
, O_RDONLY
|O_BINARY
);
1614 fprintf(stderr
, "Failed to open %s\n", filename
);
1617 SWF
* swf
= rfx_alloc(sizeof(SWF
));
1618 swf_ReadSWF(fi
, swf
);
1623 int swf_ReadSWF(int handle
, SWF
* swf
)
1626 reader_init_filereader(&reader
, handle
);
1627 return swf_ReadSWF2(&reader
, swf
);
1630 void swf_ReadABCfile(char*filename
, SWF
*swf
)
1632 memset(swf
, 0, sizeof(SWF
));
1634 swf
->fileAttributes
=FILEATTRIBUTE_AS3
; //as3
1635 TAG
*tag
= swf
->firstTag
= swf_InsertTag(0, ST_RAWABC
);
1636 memfile_t
*file
= memfile_open(filename
);
1637 swf_SetBlock(tag
, file
->data
, file
->len
);
1638 memfile_close(file
);
1641 int no_extra_tags
= 0;
1643 int WriteExtraTags(SWF
*swf
, writer_t
*writer
)
1645 TAG
*t
= swf
->firstTag
;
1646 TAG
* has_fileattributes
=0;
1647 int has_scenedescription
=0;
1648 int has_version_8_action
=0;
1649 int has_version_9_action
=0;
1652 if(t
->id
== ST_FILEATTRIBUTES
)
1653 has_fileattributes
= t
;
1654 if(t
->id
== ST_SCENEDESCRIPTION
)
1655 has_scenedescription
= 1;
1656 if(t
->id
== ST_DOABC
)
1657 has_version_9_action
=1;
1658 /* FIXME: this doesn't yet find actionscript in buttons */
1659 if(t
->id
== ST_DOACTION
|| t
->id
== ST_DOINITACTION
)
1660 has_version_8_action
=1;
1661 if(t
->id
== ST_PLACEOBJECT2
&& t
->len
&& (t
->data
[0]&0x80))
1662 has_version_8_action
=1;
1665 if(has_version_8_action
&& has_version_9_action
) {
1666 fprintf(stderr
, "Warning: File contains both flash 8 and flash 9 actionscript\n");
1669 if(swf
->fileVersion
>= 9) {
1670 if(!has_fileattributes
) {
1671 U32 flags
= swf
->fileAttributes
|FILEATTRIBUTE_AS3
; // 16 = has symbolclass tag | 8 = actionscript3 | 1 = usenetwork
1672 if(has_version_8_action
&& !has_version_9_action
)
1673 flags
&= ~FILEATTRIBUTE_AS3
;
1674 TAG
*fileattrib
= swf_InsertTag(0, ST_FILEATTRIBUTES
);
1675 swf_SetU32(fileattrib
, flags
);
1677 if(swf_WriteTag2(writer
, fileattrib
)<0)
1680 len
+= swf_WriteTag(-1,fileattrib
);
1682 swf_DeleteTag(0, fileattrib
);
1684 if(swf
->fileAttributes
) {
1685 /* if we're writing a file out again where we might have possible
1686 modified the fileattributes in the header, adjust the tag data */
1687 TAG
*tt
= swf_CopyTag(0,has_fileattributes
);
1688 U32 flags
= swf_GetU32(tt
) | swf
->fileAttributes
;
1689 swf_ResetTag(tt
, tt
->id
);
1690 swf_SetU32(tt
, flags
);
1691 if(swf_WriteTag2(writer
, has_fileattributes
)<0) return -1;
1692 swf_DeleteTag(0, tt
);
1694 if(swf_WriteTag2(writer
, has_fileattributes
)<0)
1698 if(0 && !has_scenedescription
) {
1699 TAG
*scene
= swf_InsertTag(0, ST_SCENEDESCRIPTION
);
1700 swf_SetU16(scene
, 1);
1701 swf_SetString(scene
, "Scene 1");
1702 swf_SetU8(scene
, 0);
1704 if(swf_WriteTag2(writer
, scene
)<0)
1707 len
+= swf_WriteTag(-1,scene
);
1709 swf_DeleteTag(0, scene
);
1715 int swf_WriteSWF2(writer_t
*writer
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1723 writer_t
*original_writer
= writer
;
1724 int writer_lastpos
= 0;
1726 if (!swf
) return -1;
1727 if (!writer
) return -1; // the caller should provide a nullwriter, not 0, for querying SWF size
1729 if(original_writer
) writer_lastpos
= original_writer
->pos
;
1731 // Count Frames + File Size
1737 if(swf
->firstTag
&& !no_extra_tags
) {
1738 len
+= WriteExtraTags(swf
, 0);
1741 len
+= swf_WriteTag(-1,t
);
1742 if(t
->id
== ST_DEFINESPRITE
&& !swf_IsFolded(t
)) inSprite
++;
1743 else if(t
->id
== ST_END
&& inSprite
) inSprite
--;
1744 else if(t
->id
== ST_END
&& !inSprite
) {
1745 if(t
->prev
&& t
->prev
->id
!=ST_SHOWFRAME
)
1748 else if(t
->id
== ST_SHOWFRAME
&& !inSprite
) frameCount
++;
1756 memset(&t1
,0x00,sizeof(TAG
));
1760 { // measure header file size
1763 memset(&t2
,0x00,sizeof(TAG
));
1766 swf_SetRect(&t2
, &swf
->movieSize
);
1767 swf_SetU16(&t2
, swf
->frameRate
);
1768 swf_SetU16(&t2
, swf
->frameCount
);
1769 l
= swf_GetTagLen(&t2
)+8;
1771 if(swf
->compressed
== 8) {
1776 if(len
) {// don't touch headers without tags
1777 swf
->fileSize
= fileSize
;
1778 swf
->frameCount
= frameCount
;
1781 if(swf
->compressed
!= 8) {
1782 /* compressed flag set to 8 means "skip first 8
1783 header bytes". This is necessary if the caller wants to
1784 create compressed SWFs himself .
1785 It also means that we don't initialize our own zlib
1786 writer, but assume the caller provided one.
1788 if(swf
->compressed
==1 || (swf
->compressed
==0 && swf
->fileVersion
>=6)) {
1790 writer
->write(writer
, id
, 3);
1793 writer
->write(writer
, id
, 3);
1796 writer
->write(writer
, &swf
->fileVersion
, 1);
1797 PUT32(b4
, swf
->fileSize
);
1798 writer
->write(writer
, b4
, 4);
1800 if(swf
->compressed
==1 || (swf
->compressed
==0 && swf
->fileVersion
>=6)) {
1801 writer_init_zlibdeflate(&zwriter
, writer
);
1806 swf_SetRect(&t1
,&swf
->movieSize
);
1807 swf_SetU16(&t1
,swf
->frameRate
);
1808 swf_SetU16(&t1
,swf
->frameCount
);
1810 ret
= writer
->write(writer
,b
,swf_GetTagLen(&t1
));
1811 if (ret
!=swf_GetTagLen(&t1
))
1814 fprintf(stderr
, "ret:%d\n",ret
);
1816 fprintf(stderr
,"WriteSWF() failed: Header.\n");
1821 if(swf
->firstTag
&& !no_extra_tags
) {
1822 WriteExtraTags(swf
, writer
);
1827 if(no_extra_tags
|| t
->id
!= ST_FILEATTRIBUTES
) {
1828 if(swf_WriteTag2(writer
, t
)<0)
1833 if(swf
->compressed
==1 || (swf
->compressed
==0 && swf
->fileVersion
>=6) || swf
->compressed
==8) {
1834 if(swf
->compressed
!= 8) {
1835 zwriter
.finish(&zwriter
);
1836 return original_writer
->pos
- writer_lastpos
;
1838 return (int)fileSize
;
1840 return (int)fileSize
;
1845 int swf_SaveSWF(SWF
* swf
, char*filename
)
1847 int fi
= open(filename
, O_BINARY
|O_RDWR
|O_TRUNC
|O_CREAT
, 0777);
1852 if(swf_WriteSWF(fi
, swf
)<0) {
1853 fprintf(stderr
, "Unable to write output file: %s\n", filename
);
1860 int swf_WriteSWF(int handle
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1866 writer_init_nullwriter(&writer
);
1867 len
= swf_WriteSWF2(&writer
, swf
);
1870 writer_init_filewriter(&writer
, handle
);
1871 len
= swf_WriteSWF2(&writer
, swf
);
1872 writer
.finish(&writer
);
1876 int swf_WriteHeader2(writer_t
*writer
,SWF
* swf
)
1879 memcpy(&myswf
,swf
,sizeof(SWF
));
1881 return swf_WriteSWF2(writer
, &myswf
);
1884 int swf_WriteHeader(int handle
,SWF
* swf
)
1887 memcpy(&myswf
,swf
,sizeof(SWF
));
1889 return swf_WriteSWF(handle
, &myswf
);
1892 int swf_WriteCGI(SWF
* swf
)
1896 len
= swf_WriteSWF(-1,swf
);
1898 if (len
<0) return -1;
1900 sprintf(s
,"Content-type: application/x-shockwave-flash\n"
1901 "Accept-Ranges: bytes\n"
1902 "Content-Length: %d\n"
1903 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
1906 write(fileno(stdout
),s
,strlen(s
));
1907 return swf_WriteSWF(fileno(stdout
),swf
);
1910 SWF
* swf_CopySWF(SWF
*swf
)
1912 SWF
*nswf
= (SWF
*)rfx_alloc(sizeof(SWF
));
1914 memcpy(nswf
, swf
, sizeof(SWF
));
1916 tag
= swf
->firstTag
;
1919 ntag
= swf_CopyTag(ntag
, tag
);
1921 nswf
->firstTag
= ntag
;
1927 void swf_FreeTags(SWF
* swf
) // Frees all malloc'ed memory for tags
1928 { TAG
* t
= swf
->firstTag
;
1931 { TAG
* tnew
= t
->next
;
1932 if (t
->data
) rfx_free(t
->data
);
1939 // include advanced functions
1941 //#include "modules/swfdump.c"
1942 //#include "modules/swfshape.c"
1943 //#include "modules/swftext.c"
1944 //#include "modules/swffont.c"
1945 //#include "modules/swfobject.c"
1946 //#include "modules/swfbutton.c"
1947 //#include "modules/swftools.c"
1948 //#include "modules/swfcgi.c"
1949 //#include "modules/swfbits.c"
1950 //#include "modules/swfaction.c"
1951 //#include "modules/swfabc.c"
1952 //#include "modules/swfsound.c"
1953 //#include "modules/swfdraw.c"
1954 //#include "modules/swfrender.c"
1955 //#include "modules/swffilter.c"