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 */
32 #endif // HAVE_JPEGLIB
38 #ifndef RFXSWF_DISABLESOUND
40 #include "lame/lame.h"
53 #define MALLOC_SIZE 128
54 #define INSERT_RFX_TAG
56 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
59 // inline wrapper functions
61 TAG
* swf_NextTag(TAG
* t
) { return t
->next
; }
62 TAG
* swf_PrevTag(TAG
* t
) { return t
->prev
; }
63 U16
swf_GetTagID(TAG
* t
) { return t
->id
; }
64 U32
swf_GetTagLen(TAG
* t
) { return t
->len
; }
65 U8
* swf_GetTagLenPtr(TAG
* t
) { return &(t
->data
[t
->len
]); }
66 U32
swf_GetTagPos(TAG
* t
) { return t
->pos
; }
68 // for future purpose: avoid high level lib functions to change tagpos/bitpos
70 #define swf_SaveTagPos(tag)
71 #define swf_RestoreTagPos(tag)
73 void swf_SetTagPos(TAG
* t
,U32 pos
)
74 { swf_ResetReadBits(t
);
75 if (pos
<=t
->len
) t
->pos
= pos
;
78 fprintf(stderr
,"SetTagPos(%d) out of bounds: TagID = %i\n",pos
, t
->id
);
83 char* swf_GetString(TAG
*t
)
85 char* str
= ((char*)(&(t
)->data
[(t
)->pos
]));
91 { swf_ResetReadBits(t
);
94 { fprintf(stderr
,"GetU8() out of bounds: TagID = %i\n",t
->id
);
98 return t
->data
[t
->pos
++];
101 U16
swf_GetU16(TAG
* t
)
103 swf_ResetReadBits(t
);
105 if (t
->pos
>(t
->len
-2))
106 { fprintf(stderr
,"GetU16() out of bounds: TagID = %i\n",t
->id
);
110 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8);
115 U32
swf_GetU32(TAG
* t
)
117 swf_ResetReadBits(t
);
119 if (t
->pos
>(t
->len
-4))
120 { fprintf(stderr
,"GetU32() out of bounds: TagID = %i\n",t
->id
);
124 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8) |
125 (t
->data
[t
->pos
+2]<<16) | (t
->data
[t
->pos
+3]<<24);
130 int swf_GetBlock(TAG
* t
,U8
* b
,int l
)
131 // returns number of bytes written (<=l)
132 // b = NULL -> skip data
133 { swf_ResetReadBits(t
);
134 if ((t
->len
-t
->pos
)<l
) l
=t
->len
-t
->pos
;
135 if (b
&& l
) memcpy(b
,&t
->data
[t
->pos
],l
);
140 int swf_SetBlock(TAG
* t
,U8
* b
,int l
)
141 // Appends Block to the end of Tagdata, returns size
142 { U32 newlen
= t
->len
+ l
;
143 swf_ResetWriteBits(t
);
144 if (newlen
>t
->memsize
)
145 { U32 newmem
= MEMSIZE(newlen
);
146 U8
* newdata
= (U8
*)((t
->data
)?realloc(t
->data
,newmem
):malloc(newmem
));
150 fprintf(stderr
,"Fatal Error: malloc()/realloc() failed (1). (%d bytes)\n", newmem
);
158 if (b
) memcpy(&t
->data
[t
->len
],b
,l
);
159 else memset(&t
->data
[t
->len
],0x00,l
);
164 int swf_SetU8(TAG
* t
,U8 v
)
165 { swf_ResetWriteBits(t
);
166 if ((t
->len
+1)>t
->memsize
) return (swf_SetBlock(t
,&v
,1)==1)?0:-1;
167 t
->data
[t
->len
++] = v
;
171 int swf_SetU16(TAG
* t
,U16 v
)
176 swf_ResetWriteBits(t
);
177 if ((t
->len
+2)>t
->memsize
) return (swf_SetBlock(t
,a
,2)==2)?0:-1;
178 t
->data
[t
->len
++] = a
[0];
179 t
->data
[t
->len
++] = a
[1];
182 void swf_SetS16(TAG
* t
,int v
)
184 if(v
>32767 || v
<-32768) {
185 fprintf(stderr
, "Warning: S16 overflow: %d\n", v
);
187 swf_SetU16(t
, (S16
)v
);
190 int swf_SetU32(TAG
* t
,U32 v
)
192 a
[0] = v
&0xff; // to ensure correct handling of non-intel byteorder
197 swf_ResetWriteBits(t
);
198 if ((t
->len
+4)>t
->memsize
) return (swf_SetBlock(t
,a
,4)==4)?0:-1;
199 t
->data
[t
->len
++] = a
[0];
200 t
->data
[t
->len
++] = a
[1];
201 t
->data
[t
->len
++] = a
[2];
202 t
->data
[t
->len
++] = a
[3];
206 U32
swf_GetBits(TAG
* t
,int nbits
)
208 if (!nbits
) return 0;
209 if (!t
->readBit
) t
->readBit
= 0x80;
212 if (t
->data
[t
->pos
]&t
->readBit
) res
|=1;
216 { if (nbits
) t
->readBit
= 0x80;
219 { fprintf(stderr
,"GetBits() out of bounds: TagID = %i\n",t
->id
);
229 S32
swf_GetSBits(TAG
* t
,int nbits
)
230 { U32 res
= swf_GetBits(t
,nbits
);
231 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
235 U32
reader_GetBits(struct reader_t
*reader
, int nbits
)
236 { return reader_readbits(reader
, nbits
);
238 S32
reader_GetSBits(struct reader_t
*reader
, int nbits
)
239 { U32 res
= reader_readbits(reader
, nbits
);
240 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
244 int swf_SetBits(TAG
* t
,U32 v
,int nbits
)
245 { U32 bm
= 1<<(nbits
-1);
249 { if (FAILED(swf_SetU8(t
,0))) return -1;
252 if (v
&bm
) t
->data
[t
->len
-1] |= t
->writeBit
;
260 // Advanced Data Access Functions
262 int swf_SetRGB(TAG
* t
,RGBA
* col
)
265 { swf_SetU8(t
,col
->r
);
268 } else swf_SetBlock(t
,NULL
,3);
271 void swf_GetRGB(TAG
* t
, RGBA
* col
)
276 col
->r
= swf_GetU8(t
);
277 col
->g
= swf_GetU8(t
);
278 col
->b
= swf_GetU8(t
);
282 int swf_SetRGBA(TAG
* t
,RGBA
* col
)
285 { swf_SetU8(t
,col
->r
);
289 } else swf_SetBlock(t
,NULL
,4);
292 void swf_GetRGBA(TAG
* t
, RGBA
* col
)
297 col
->r
= swf_GetU8(t
);
298 col
->g
= swf_GetU8(t
);
299 col
->b
= swf_GetU8(t
);
300 col
->a
= swf_GetU8(t
);
303 void swf_GetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
308 memset(gradient
, 0, sizeof(GRADIENT
));
313 gradient
->num
= swf_GetU8(tag
);
314 for(t
=0;t
<gradient
->num
;t
++)
319 gradient
->ratios
[t
] = swf_GetU8(tag
);
321 swf_GetRGB(tag
, &gradient
->rgba
[t
]);
323 swf_GetRGBA(tag
, &gradient
->rgba
[t
]);
327 void swf_SetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
331 memset(gradient
, 0, sizeof(GRADIENT
));
334 swf_SetU8(tag
, gradient
->num
);
335 for(t
=0; t
<8 && t
<gradient
->num
; t
++)
337 swf_SetU8(tag
, gradient
->ratios
[t
]);
339 swf_SetRGB(tag
, &gradient
->rgba
[t
]);
341 swf_SetRGBA(tag
, &gradient
->rgba
[t
]);
345 int swf_CountUBits(U32 v
,int nbits
)
348 if(v
== 0x00000000) n
= 0;
354 return (n
>nbits
)?n
:nbits
;
357 int swf_CountBits(U32 v
,int nbits
)
361 { if(v
== 0xffffffff) n
= 1;
369 { if(v
== 0x00000000) n
= 0;
376 return (n
>nbits
)?n
:nbits
;
379 int swf_GetRect(TAG
* t
,SRECT
* r
)
382 if(!t
) {r
->xmin
=r
->xmax
=r
->ymin
=r
->ymax
=0;return 0;}
384 nbits
= (int) swf_GetBits(t
,5);
385 r
->xmin
= swf_GetSBits(t
,nbits
);
386 r
->xmax
= swf_GetSBits(t
,nbits
);
387 r
->ymin
= swf_GetSBits(t
,nbits
);
388 r
->ymax
= swf_GetSBits(t
,nbits
);
392 int reader_GetRect(struct reader_t
*reader
,SRECT
* r
)
396 nbits
= (int) reader_GetBits(reader
,5);
397 r
->xmin
= reader_GetSBits(reader
,nbits
);
398 r
->xmax
= reader_GetSBits(reader
,nbits
);
399 r
->ymin
= reader_GetSBits(reader
,nbits
);
400 r
->ymax
= reader_GetSBits(reader
,nbits
);
404 int swf_SetRect(TAG
* t
,SRECT
* r
)
407 nbits
= swf_CountBits(r
->xmin
,0);
408 nbits
= swf_CountBits(r
->xmax
,nbits
);
409 nbits
= swf_CountBits(r
->ymin
,nbits
);
410 nbits
= swf_CountBits(r
->ymax
,nbits
);
412 fprintf(stderr
, "rfxswf: Warning: num_bits overflow in swf_SetRect\n");
416 swf_SetBits(t
,nbits
,5);
417 swf_SetBits(t
,r
->xmin
,nbits
);
418 swf_SetBits(t
,r
->xmax
,nbits
);
419 swf_SetBits(t
,r
->ymin
,nbits
);
420 swf_SetBits(t
,r
->ymax
,nbits
);
425 void swf_ExpandRect(SRECT
*src
, SPOINT add
)
427 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
432 if((add
.x
|add
.y
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
435 if(add
.x
< src
->xmin
)
437 if(add
.x
> src
->xmax
)
439 if(add
.y
< src
->ymin
)
441 if(add
.y
> src
->ymax
)
444 void swf_ExpandRect2(SRECT
*src
, SRECT
*add
)
446 if((add
->xmin
| add
->ymin
| add
->xmax
| add
->ymax
)==0)
448 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0)
450 if(add
->xmin
< src
->xmin
)
451 src
->xmin
= add
->xmin
;
452 if(add
->ymin
< src
->ymin
)
453 src
->ymin
= add
->ymin
;
454 if(add
->xmax
> src
->xmax
)
455 src
->xmax
= add
->xmax
;
456 if(add
->ymax
> src
->ymax
)
457 src
->ymax
= add
->ymax
;
459 void swf_ExpandRect3(SRECT
*src
, SPOINT center
, int radius
)
461 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
462 src
->xmin
= center
.x
-radius
;
463 src
->ymin
= center
.y
-radius
;
464 src
->xmax
= center
.x
+radius
;
465 src
->ymax
= center
.y
+radius
;
466 if((center
.x
|center
.y
|radius
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
469 if(center
.x
- radius
< src
->xmin
)
470 src
->xmin
= center
.x
- radius
;
471 if(center
.x
+ radius
> src
->xmax
)
472 src
->xmax
= center
.x
- radius
;
473 if(center
.y
- radius
< src
->ymin
)
474 src
->ymin
= center
.y
- radius
;
475 if(center
.y
+ radius
> src
->ymax
)
476 src
->ymax
= center
.y
- radius
;
478 SPOINT
swf_TurnPoint(SPOINT p
, MATRIX
* m
)
481 r
.x
= (int)(m
->sx
*(1/65536.0)*p
.x
+ m
->r1
*(1/65536.0)*p
.y
+ 0.5) + m
->tx
;
482 r
.y
= (int)(m
->r0
*(1/65536.0)*p
.x
+ m
->sy
*(1/65536.0)*p
.y
+ 0.5) + m
->ty
;
485 SRECT
swf_TurnRect(SRECT r
, MATRIX
* m
)
488 SPOINT p1
,p2
,p3
,p4
,pp1
,pp2
,pp3
,pp4
;
489 p1
.x
= r
.xmin
;p1
.y
= r
.ymin
;
490 p2
.x
= r
.xmax
;p2
.y
= r
.ymin
;
491 p3
.x
= r
.xmin
;p3
.y
= r
.ymax
;
492 p4
.x
= r
.xmax
;p4
.y
= r
.ymax
;
493 pp1
= swf_TurnPoint(p1
, m
);
494 pp2
= swf_TurnPoint(p2
, m
);
495 pp3
= swf_TurnPoint(p3
, m
);
496 pp4
= swf_TurnPoint(p4
, m
);
497 g
.xmin
= g
.xmax
= pp1
.x
;
498 g
.ymin
= g
.ymax
= pp1
.y
;
499 swf_ExpandRect(&g
, pp2
);
500 swf_ExpandRect(&g
, pp3
);
501 swf_ExpandRect(&g
, pp4
);
506 int swf_GetMatrix(TAG
* t
,MATRIX
* m
)
513 { m
->sx
= m
->sy
= 0x10000;
519 swf_ResetReadBits(t
);
521 if (swf_GetBits(t
,1))
522 { nbits
= swf_GetBits(t
,5);
523 m
->sx
= swf_GetSBits(t
,nbits
);
524 m
->sy
= swf_GetSBits(t
,nbits
);
526 else m
->sx
= m
->sy
= 0x10000;
528 if (swf_GetBits(t
,1))
529 { nbits
= swf_GetBits(t
,5);
530 m
->r0
= swf_GetSBits(t
,nbits
);
531 m
->r1
= swf_GetSBits(t
,nbits
);
533 else m
->r0
= m
->r1
= 0x0;
535 nbits
= swf_GetBits(t
,5);
536 m
->tx
= swf_GetSBits(t
,nbits
);
537 m
->ty
= swf_GetSBits(t
,nbits
);
542 int swf_SetMatrix(TAG
* t
,MATRIX
* m
)
548 ma
.sx
= ma
.sy
= 0x10000;
553 swf_ResetWriteBits(t
);
555 if ((m
->sx
==0x10000)&&(m
->sy
==0x10000)) swf_SetBits(t
,0,1);
557 { swf_SetBits(t
,1,1);
558 nbits
= swf_CountBits(m
->sx
,0);
559 nbits
= swf_CountBits(m
->sy
,nbits
);
561 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
564 swf_SetBits(t
,nbits
,5);
565 swf_SetBits(t
,m
->sx
,nbits
);
566 swf_SetBits(t
,m
->sy
,nbits
);
569 if ((!m
->r0
)&&(!m
->r1
)) swf_SetBits(t
,0,1);
571 { swf_SetBits(t
,1,1);
572 nbits
= swf_CountBits(m
->r0
,0);
573 nbits
= swf_CountBits(m
->r1
,nbits
);
575 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
578 swf_SetBits(t
,nbits
,5);
579 swf_SetBits(t
,m
->r0
,nbits
);
580 swf_SetBits(t
,m
->r1
,nbits
);
583 nbits
= swf_CountBits(m
->tx
,0);
584 nbits
= swf_CountBits(m
->ty
,nbits
);
586 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
589 swf_SetBits(t
,nbits
,5);
590 swf_SetBits(t
,m
->tx
,nbits
);
591 swf_SetBits(t
,m
->ty
,nbits
);
596 int swf_GetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
) //FIXME: alpha should be type bool
604 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
605 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
609 swf_ResetReadBits(t
);
610 hasadd
= swf_GetBits(t
,1);
611 hasmul
= swf_GetBits(t
,1);
612 nbits
= swf_GetBits(t
,4);
615 { cx
->r0
= (S16
)swf_GetSBits(t
,nbits
);
616 cx
->g0
= (S16
)swf_GetSBits(t
,nbits
);
617 cx
->b0
= (S16
)swf_GetSBits(t
,nbits
);
619 cx
->a0
= (S16
)swf_GetSBits(t
,nbits
);
623 { cx
->r1
= (S16
)swf_GetSBits(t
,nbits
);
624 cx
->g1
= (S16
)swf_GetSBits(t
,nbits
);
625 cx
->b1
= (S16
)swf_GetSBits(t
,nbits
);
627 cx
->a1
= (S16
)swf_GetSBits(t
,nbits
);
633 int swf_SetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
)
641 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
642 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
652 hasmul
= (cx
->a0
!=256)||(cx
->r0
!=256)||(cx
->g0
!=256)||(cx
->b0
!=256);
653 hasadd
= cx
->a1
|cx
->r1
|cx
->g1
|cx
->b1
;
656 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a0
,nbits
);
657 nbits
= swf_CountBits((S32
)cx
->r0
,nbits
);
658 nbits
= swf_CountBits((S32
)cx
->g0
,nbits
);
659 nbits
= swf_CountBits((S32
)cx
->b0
,nbits
);
663 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a1
,nbits
);
664 nbits
= swf_CountBits((S32
)cx
->r1
,nbits
);
665 nbits
= swf_CountBits((S32
)cx
->g1
,nbits
);
666 nbits
= swf_CountBits((S32
)cx
->b1
,nbits
);
669 swf_ResetWriteBits(t
);
670 swf_SetBits(t
,hasadd
?1:0,1);
671 swf_SetBits(t
,hasmul
?1:0,1);
672 swf_SetBits(t
,nbits
,4);
675 { swf_SetBits(t
,cx
->r0
,nbits
);
676 swf_SetBits(t
,cx
->g0
,nbits
);
677 swf_SetBits(t
,cx
->b0
,nbits
);
678 if (alpha
) swf_SetBits(t
,cx
->a0
,nbits
);
682 { swf_SetBits(t
,cx
->r1
,nbits
);
683 swf_SetBits(t
,cx
->g1
,nbits
);
684 swf_SetBits(t
,cx
->b1
,nbits
);
685 if (alpha
) swf_SetBits(t
,cx
->a1
,nbits
);
691 //int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
692 //int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
694 void swf_SetPassword(TAG
* t
, const char * password
)
696 /* WARNING: crypt_md5 is not reentrant */
700 #if defined(HAVE_LRAND48) && defined(HAVE_SRAND48) && defined(HAVE_TIME_H) && defined(HAVE_TIME)
702 salt
[0] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
703 salt
[1] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
707 fprintf(stderr
, "rfxswf: Warning- no usable random generator found\n");
708 fprintf(stderr
, "Your password will be vulnerable to dictionary attacks\n");
711 md5string
= crypt_md5(password
, salt
);
714 swf_SetString(t
, md5string
);
717 int swf_VerifyPassword(TAG
* t
, const char * password
)
719 char*md5string1
, *md5string2
;
724 if(t
->len
>= 5 && t
->pos
==0 &&
729 printf("%d %d %d %d\n", t
->len
, t
->pos
, t
->data
[0], t
->data
[1]);
732 md5string1
= swf_GetString(t
);
734 if(strncmp(md5string1
, "$1$",3 )) {
735 fprintf(stderr
, "rfxswf: no salt in pw string\n");
738 x
= strchr(md5string1
+3, '$');
740 fprintf(stderr
, "rfxswf: invalid salt format in pw string\n");
743 n
= x
-(md5string1
+3);
744 salt
= (char*)malloc(n
+1);
745 memcpy(salt
, md5string1
+3, n
);
748 md5string2
= crypt_md5(password
, salt
);
750 if(strcmp(md5string1
, md5string2
) != 0)
755 // Tag List Manipulating Functions
757 TAG
* swf_InsertTag(TAG
* after
,U16 id
)
760 t
= (TAG
*)malloc(sizeof(TAG
));
762 { memset(t
,0x00,sizeof(TAG
));
768 t
->next
= after
->next
;
770 if (t
->next
) t
->next
->prev
= t
;
776 TAG
* swf_InsertTagBefore(SWF
* swf
, TAG
* before
,U16 id
)
779 t
= (TAG
*)malloc(sizeof(TAG
));
781 { memset(t
,0x00,sizeof(TAG
));
787 t
->prev
= before
->prev
;
789 if (t
->prev
) t
->prev
->next
= t
;
792 if(swf
&& swf
->firstTag
== before
) {
798 void swf_ClearTag(TAG
* t
)
800 if (t
->data
) free(t
->data
);
809 void swf_ResetTag(TAG
*tag
, U16 id
)
811 tag
->len
= tag
->pos
= tag
->readBit
= tag
->writeBit
= 0;
815 int swf_DeleteTag(TAG
* t
)
818 if (t
->prev
) t
->prev
->next
= t
->next
;
819 if (t
->next
) t
->next
->prev
= t
->prev
;
821 if (t
->data
) free(t
->data
);
826 TAG
* swf_ReadTag(struct reader_t
*reader
, TAG
* prev
)
832 if (reader
->read(reader
, &raw
, 2) !=2 ) return NULL
;
840 if (reader
->read(reader
, &len
, 4) != 4) return NULL
;
844 if (id
==ST_DEFINESPRITE
) len
= 2*sizeof(U16
);
845 // Sprite handling fix: Flatten sprite tree
847 t
= (TAG
*)malloc(sizeof(TAG
));
852 fprintf(stderr
,"Fatal Error: malloc()/realloc() failed (2). (%d bytes)\n", sizeof(TAG
));
857 memset(t
,0x00,sizeof(TAG
));
863 { t
->data
= (U8
*)malloc(t
->len
);
867 fprintf(stderr
,"Fatal Error: malloc()/realloc() failed (3). (%d bytes)\n", t
->len
);
872 if (reader
->read(reader
, t
->data
, t
->len
) != t
->len
) return NULL
;
884 int swf_DefineSprite_GetRealSize(TAG
* t
);
886 int swf_WriteTag2(struct writer_t
*writer
, TAG
* t
)
887 // returns tag length in bytes (incl. Header), -1 = Error
888 // writer = 0 -> no output
895 len
= (t
->id
==ST_DEFINESPRITE
)?swf_DefineSprite_GetRealSize(t
):t
->len
;
897 short_tag
= len
<0x3f&&(t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
);
901 { raw
[0] = SWAP16(len
|((t
->id
&0x3ff)<<6));
902 if (writer
->write(writer
,raw
,2)!=2)
905 fprintf(stderr
,"WriteTag() failed: Short Header.\n");
912 raw
[0] = SWAP16((t
->id
<<6)|0x3f);
913 if (writer
->write(writer
,raw
,2)!=2)
916 fprintf(stderr
,"WriteTag() failed: Long Header (1).\n");
922 if (writer
->write(writer
,&len
,4)!=4)
925 fprintf(stderr
,"WriteTag() failed: Long Header (2).\n");
932 { if (writer
->write(writer
,t
->data
,t
->len
)!=t
->len
)
935 fprintf(stderr
,"WriteTag() failed: Data.\n");
941 else if (t
->len
) fprintf(stderr
,"WriteTag(): Tag Data Error, id=%i\n",t
->id
);
945 return t
->len
+(short_tag
?2:6);
948 int swf_WriteTag(int handle
, TAG
* t
)
950 struct writer_t writer
;
953 return swf_WriteTag2(0, t
);
954 writer_init_filewriter(&writer
, handle
);
955 len
= swf_WriteTag2(&writer
, t
);
956 writer
.finish(&writer
);
960 int swf_DefineSprite_GetRealSize(TAG
* t
)
961 // Sprite Handling: Helper function to pack DefineSprite-Tag
963 if(len
>4) { // folded sprite
967 { t
= swf_NextTag(t
);
968 if (t
&& t
->id
!=ST_DEFINESPRITE
) len
+= swf_WriteTag(-1, t
);
970 } while (t
&&(t
->id
!=ST_END
));
974 void swf_UnFoldSprite(TAG
* t
)
979 U16 spriteid
,spriteframes
;
981 if(t
->id
!=ST_DEFINESPRITE
)
983 if(t
->len
<=4) // not folded
988 spriteid
= swf_GetU16(t
); //id
989 spriteframes
= swf_GetU16(t
); //frames
1001 if(id
== ST_DEFINESPRITE
&& len
<=4)
1005 len
= swf_GetU32(t
);
1006 it
= swf_InsertTag(next
, id
);
1011 { it
->data
= (U8
*)malloc(it
->len
);
1012 it
->memsize
= it
->len
;
1013 swf_GetBlock(t
, it
->data
, it
->len
);
1020 free(t
->data
); t
->data
= 0;
1021 t
->memsize
= t
->len
= t
->pos
= 0;
1023 swf_SetU16(t
, spriteid
);
1024 swf_SetU16(t
, spriteframes
);
1027 void swf_FoldSprite(TAG
* t
)
1030 U16 id
,frames
,tmpid
;
1032 if(t
->id
!=ST_DEFINESPRITE
)
1035 fprintf(stderr
, "Error: Sprite has no ID!");
1039 /* sprite is already folded */
1046 t
->len
= t
->pos
= t
->memsize
= 0;
1051 t
= swf_NextTag(sprtag
);
1056 if(t
->id
==ST_SHOWFRAME
) frames
++;
1057 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1062 } while(t
&& level
);
1064 fprintf(stderr
, "rfxswf error: sprite doesn't end(1)\n");
1066 swf_SetU16(sprtag
, id
);
1067 swf_SetU16(sprtag
, frames
);
1069 t
= swf_NextTag(sprtag
);
1074 if(t
->len
<0x3f&&t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
) {
1075 swf_SetU16(sprtag
,t
->len
|(t
->id
<<6));
1077 swf_SetU16(sprtag
,0x3f|(t
->id
<<6));
1078 swf_SetU32(sprtag
,t
->len
);
1081 swf_SetBlock(sprtag
,t
->data
, t
->len
);
1083 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1092 fprintf(stderr
, "rfxswf error: sprite doesn't end(2)\n");
1094 // sprtag->next = t;
1095 // t->prev = sprtag;
1098 int swf_IsFolded(TAG
* t
)
1100 return (t
->id
== ST_DEFINESPRITE
&& t
->len
>4);
1103 void swf_FoldAll(SWF
*swf
)
1105 TAG
*tag
= swf
->firstTag
;
1106 //swf_DumpSWF(stdout, swf);
1108 if(tag
->id
== ST_DEFINESPRITE
) {
1109 swf_FoldSprite(tag
);
1110 //swf_DumpSWF(stdout, swf);
1112 tag
= swf_NextTag(tag
);
1116 void swf_UnFoldAll(SWF
*swf
)
1118 TAG
*tag
= swf
->firstTag
;
1120 if(tag
->id
== ST_DEFINESPRITE
)
1121 swf_UnFoldSprite(tag
);
1126 void swf_OptimizeTagOrder(SWF
*swf
)
1133 /* at the moment, we don't actually do optimizing,
1134 only fixing of non-spec-conformant things like
1141 tag
= swf
->firstTag
;
1144 if(tag
->id
== ST_DEFINESPRITE
) {
1146 /* ??? all sprites are supposed to be unfolded */
1147 fprintf(stderr
, "librfxswf error - internal error in OptimizeTagOrder/UnfoldAll\n");
1157 /* move non-sprite tags out of sprite */
1158 if(!swf_isAllowedSpriteTag(tag
) || level
>=2) {
1159 /* remove tag from current position */
1160 tag
->prev
->next
= tag
->next
;
1162 tag
->next
->prev
= tag
->prev
;
1164 /* insert before tag level0 */
1166 tag
->prev
= level0
->prev
;
1168 tag
->prev
->next
= tag
;
1172 if(tag
->id
== ST_END
) {
1183 int swf_ReadSWF2(struct reader_t
*reader
, SWF
* swf
) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
1185 if (!swf
) return -1;
1186 memset(swf
,0x00,sizeof(SWF
));
1188 { char b
[32]; // read Header
1192 struct reader_t zreader
;
1194 if ((len
= reader
->read(reader
,b
,8))<8) return -1;
1196 if (b
[0]!='F' && b
[0]!='C') return -1;
1197 if (b
[1]!='W') return -1;
1198 if (b
[2]!='S') return -1;
1199 swf
->fileVersion
= b
[3];
1200 swf
->compressed
= (b
[0]=='C')?1:0;
1201 swf
->fileSize
= GET32(&b
[4]);
1203 if(swf
->compressed
) {
1204 reader_init_zlibinflate(&zreader
, reader
);
1208 reader_GetRect(reader
, &swf
->movieSize
);
1209 reader
->read(reader
, &swf
->frameRate
, 2);
1210 swf
->frameRate
= SWAP16(swf
->frameRate
);
1211 reader
->read(reader
, &swf
->frameCount
, 2);
1212 swf
->frameCount
= SWAP16(swf
->frameCount
);
1214 /* read tags and connect to list */
1216 while (t
) t
= swf_ReadTag(reader
,t
);
1217 swf
->firstTag
= t1
.next
;
1218 t1
.next
->prev
= NULL
;
1224 int swf_ReadSWF(int handle
, SWF
* swf
)
1226 struct reader_t reader
;
1227 reader_init_filereader(&reader
, handle
);
1228 return swf_ReadSWF2(&reader
, swf
);
1231 int swf_WriteSWF2(struct writer_t
*writer
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1235 struct writer_t zwriter
;
1238 int writer_lastpos
= 0;
1241 if (!swf
) return -1;
1242 if (!writer
) return -1; // the caller should provide a nullwriter, not 0, for querying SWF size
1244 if(writer
) writer_lastpos
= writer
->pos
;
1246 // Insert REFLEX Tag
1248 #ifdef INSERT_RFX_TAG
1250 if (swf
->firstTag
&& swf_NextTag(swf
->firstTag
))
1251 if (swf_GetTagID(swf_NextTag(swf
->firstTag
))!=ST_REFLEX
)
1252 swf_SetBlock(swf_InsertTagBefore(swf
, swf
->firstTag
,ST_REFLEX
),"rfx",3);
1254 #endif // INSERT_RFX_TAG
1256 // Count Frames + File Size
1263 len
+= swf_WriteTag(-1,t
);
1264 if(t
->id
== ST_DEFINESPRITE
&& !swf_IsFolded(t
)) inSprite
++;
1265 else if(t
->id
== ST_END
&& inSprite
) inSprite
--;
1266 else if(t
->id
== ST_SHOWFRAME
&& !inSprite
) frameCount
++;
1274 memset(&t1
,0x00,sizeof(TAG
));
1278 { // measure header file size
1281 memset(&t2
,0x00,sizeof(TAG
));
1284 swf_SetRect(&t2
, &swf
->movieSize
);
1285 swf_SetU16(&t2
, swf
->frameRate
);
1286 swf_SetU16(&t2
, swf
->frameCount
);
1287 l
= swf_GetTagLen(&t2
)+8;
1289 if(swf
->compressed
== 8) {
1294 if(len
) {// don't touch headers without tags
1295 swf
->fileSize
= fileSize
;
1296 swf
->frameCount
= frameCount
;
1299 if(swf
->compressed
!= 8) {
1300 /* compressed flag set to 8 means "skip first 8
1301 header bytes". This is necessary if the caller wants to
1302 create compressed SWFs himself .
1303 It also means that we don't initialize our own zlib
1304 writer, but assume the caller provided one.
1306 if(swf
->compressed
) {
1308 writer
->write(writer
, id
, 3);
1312 writer
->write(writer
, id
, 3);
1315 writer
->write(writer
, &swf
->fileVersion
, 1);
1316 PUT32(b4
, swf
->fileSize
);
1317 writer
->write(writer
, b4
, 4);
1319 if(swf
->compressed
) {
1320 writer_init_zlibdeflate(&zwriter
, writer
);
1325 swf_SetRect(&t1
,&swf
->movieSize
);
1326 swf_SetU16(&t1
,swf
->frameRate
);
1327 swf_SetU16(&t1
,swf
->frameCount
);
1329 ret
= writer
->write(writer
,b
,swf_GetTagLen(&t1
));
1330 if (ret
!=swf_GetTagLen(&t1
))
1333 fprintf(stderr
, "ret:%d\n",ret
);
1335 fprintf(stderr
,"WriteSWF() failed: Header.\n");
1342 { if (swf_WriteTag2(writer
, t
)<0) return -1;
1345 if(swf
->compressed
) {
1346 if(swf
->compressed
!= 8) {
1347 zwriter
.finish(&zwriter
);
1348 return writer
->pos
- writer_lastpos
;
1350 return (int)fileSize
;
1352 return (int)fileSize
;
1357 int swf_WriteSWF(int handle
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1359 struct writer_t writer
;
1361 swf
->compressed
= 0;
1364 writer_init_nullwriter(&writer
);
1365 len
= swf_WriteSWF2(&writer
, swf
);
1367 writer_init_filewriter(&writer
, handle
);
1368 len
= swf_WriteSWF2(&writer
, swf
);
1369 writer
.finish(&writer
);
1373 int swf_WriteSWC(int handle
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1375 struct writer_t writer
;
1377 swf
->compressed
= 1;
1380 writer_init_nullwriter(&writer
);
1381 len
= swf_WriteSWF2(&writer
, swf
);
1383 writer_init_filewriter(&writer
, handle
);
1384 len
= swf_WriteSWF2(&writer
, swf
);
1385 writer
.finish(&writer
);
1389 int swf_WriteHeader2(struct writer_t
*writer
,SWF
* swf
)
1392 memcpy(&myswf
,swf
,sizeof(SWF
));
1394 return swf_WriteSWF2(writer
, &myswf
);
1397 int swf_WriteHeader(int handle
,SWF
* swf
)
1400 memcpy(&myswf
,swf
,sizeof(SWF
));
1402 return swf_WriteSWF(handle
, &myswf
);
1405 int swf_WriteCGI(SWF
* swf
)
1409 len
= swf_WriteSWF(-1,swf
);
1411 if (len
<0) return -1;
1413 sprintf(s
,"Content-type: application/x-shockwave-flash\n"
1414 "Accept-Ranges: bytes\n"
1415 "Content-Length: %lu\n"
1416 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
1419 write(fileno(stdout
),s
,strlen(s
));
1420 return swf_WriteSWF(fileno(stdout
),swf
);
1423 void swf_FreeTags(SWF
* swf
) // Frees all malloc'ed memory for tags
1424 { TAG
* t
= swf
->firstTag
;
1427 { TAG
* tnew
= t
->next
;
1428 if (t
->data
) free(t
->data
);
1435 // include advanced functions
1437 #include "modules/swfdump.c"
1438 #include "modules/swfshape.c"
1439 #include "modules/swftext.c"
1440 #include "modules/swffont.c"
1441 #include "modules/swfobject.c"
1442 #include "modules/swfbutton.c"
1443 #include "modules/swftools.c"
1444 #include "modules/swfcgi.c"
1445 #include "modules/swfbits.c"
1446 #include "modules/swfaction.c"
1447 #include "modules/swfsound.c"
1448 #include "modules/swfdraw.c"