1 /*
2     Ming, an SWF output library
3     Copyright (C) 2002  Opaque Industries - http://www.opaque.net/
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 /* $Id$ */
21 
22 
23 #include "ming_config.h"
24 
25 #include "libming.h"
26 #include "fromswf.h"
27 #include "method.h"
28 #include "input.h"
29 #include "output.h"
30 #include "error.h"
31 
32 #ifndef __C2MAN__
33 #include <stdlib.h>
34 #include <string.h>
35 #endif
36 
37 #if USE_ZLIB
38 #include <zlib.h>
39 #endif
40 
41 static void
writeSWFPrebuiltClipToMethod(SWFBlock block,SWFByteOutputMethod method,void * data)42 writeSWFPrebuiltClipToMethod(SWFBlock block, SWFByteOutputMethod method, void *data)
43 {
44 	SWFPrebuiltClip clip = (SWFPrebuiltClip) block;
45 	methodWriteUInt16(CHARACTERID(clip), method, data);
46 	methodWriteUInt16(clip->frames, method, data);
47 
48 	SWFOutput_writeToMethod(clip->display, method, data);
49 }
50 
51 static int
completeSWFPrebuiltClip(SWFBlock block)52 completeSWFPrebuiltClip(SWFBlock block)
53 {
54 	return 4 + SWFPrebuiltClipLength(block);
55 }
56 
57 int
SWFPrebuiltClipLength(SWFBlock block)58 SWFPrebuiltClipLength(SWFBlock block)
59 {	SWFPrebuiltClip clip = (SWFPrebuiltClip)block;
60 	return SWFOutput_getLength(clip->display);
61 }
62 
63 /*
64  * destroys a SWFPrebuiltClip instance
65  */
66 void
destroySWFPrebuiltClip(SWFPrebuiltClip clip)67 destroySWFPrebuiltClip(SWFPrebuiltClip clip)
68 {	destroySWFOutput(clip->display);
69 	destroySWFCharacter((SWFCharacter) clip);
70 }
71 
72 SWFPrebuiltClip
newSWFPrebuiltClip()73 newSWFPrebuiltClip()
74 {
75 	SWFPrebuiltClip clip = (SWFPrebuiltClip)malloc(sizeof(struct SWFPrebuiltClip_s));
76 
77 	SWFCharacterInit((SWFCharacter)clip);
78 
79 	BLOCK(clip)->type = SWF_PREBUILTCLIP;
80 	BLOCK(clip)->writeBlock = writeSWFPrebuiltClipToMethod;
81 	BLOCK(clip)->complete = completeSWFPrebuiltClip;
82 	BLOCK(clip)->dtor = (destroySWFBlockMethod) destroySWFPrebuiltClip;
83 
84 	clip->frames = 0;
85 	clip->display = newSWFOutput();
86 	return clip;
87 }
88 
89 static void
writeSWFPrebuiltToMethod(SWFBlock block,SWFByteOutputMethod method,void * data)90 writeSWFPrebuiltToMethod(SWFBlock block, SWFByteOutputMethod method, void *data)
91 {
92 	SWFPrebuilt defines = (SWFPrebuilt) block;
93 
94 	SWFOutput_writeToMethod(defines->defines, method, data);
95 }
96 
97 static int
completeSWFPrebuilt(SWFBlock block)98 completeSWFPrebuilt(SWFBlock block)
99 {
100 	SWFPrebuilt defines = (SWFPrebuilt) block;
101 	return SWFOutput_getLength(defines->defines);
102 }
103 
104 void
destroySWFPrebuilt(SWFPrebuilt defines)105 destroySWFPrebuilt(SWFPrebuilt defines)
106 {	destroySWFOutput(defines->defines);
107 	free((SWFBlock) defines);
108 }
109 
110 SWFPrebuilt
newSWFPrebuilt()111 newSWFPrebuilt()
112 {
113 	SWFPrebuilt data = (SWFPrebuilt)malloc(sizeof(struct SWFPrebuilt_s));
114 
115 	SWFBlockInit((SWFBlock)data);
116 	BLOCK(data)->type = SWF_PREBUILT;
117 	BLOCK(data)->writeBlock = writeSWFPrebuiltToMethod;
118 	BLOCK(data)->complete = completeSWFPrebuilt;
119 	BLOCK(data)->dtor = (destroySWFBlockMethod) destroySWFPrebuilt;
120 
121 	data->defines = newSWFOutput();
122 	return data;
123 }
124 
125 // functions to read swf
126 
127 static int verbose = {0};
128 
129 struct bitstream
130 {	char lastch;
131 	char bitoff;
132 	unsigned char (*readc)(void *);
133 };
134 typedef struct bitstream *BITS;
135 
136 #define alignbits(x) ((BITS)x)->bitoff = 0
137 
138 static int
getbits(BITS bp,int nbits)139 getbits(BITS bp, int nbits)
140 {	int res = 0, nb, db;
141 	for(nb = 0 ; nb < nbits ; nb += db)
142 	{	if(bp->bitoff == 0)
143 		{	bp->lastch = bp->readc(bp);
144 			bp->bitoff = 8;
145 		}
146 		db = nbits - nb;
147 		if(db > bp->bitoff)
148 			db = bp->bitoff;
149 		/* db bits von vorn wegnehmen */
150 		res <<= db;
151 		res |= (bp->lastch >> (bp->bitoff -= db)) & ((1 << db) - 1);
152 	}
153 	return res;
154 }
155 static int
getsbits(BITS bp,int nbits)156 getsbits(BITS bp, int nbits)
157 {	int res = getbits(bp, nbits);
158 	if(res & (1 << (nbits-1)))
159 		res |= (-1) << nbits;
160 	return(res);
161 }
162 
163 /* rectangle */
rect(BITS bp)164 static void rect(BITS bp)
165 {	int nbits, xmin, xmax, ymin, ymax;
166 	nbits = getbits(bp, 5);
167 	xmin = getbits(bp, nbits);
168 	xmax = getbits(bp, nbits);
169 	ymin = getbits(bp, nbits);
170 	ymax = getbits(bp, nbits);
171 	if(verbose)
172 		printf("rect %.2f,%.2f %.2f,%.2f\n", xmin/Ming_scale, ymin/Ming_scale, xmax/Ming_scale, ymax/Ming_scale);
173 }
174 /* matrix */
matrix(BITS bp)175 static void matrix(BITS bp)
176 {	int hasscale, nscalebits, scalex, scaley;
177 	int hasrotate, nrotatebits, rotateskew0, rotateskew1;
178 	int ntranslatebits, translatex, translatey;
179 	if((hasscale = getbits(bp, 1)))
180 	{	nscalebits = getbits(bp, 5);
181 		scalex = getbits(bp, nscalebits);
182 		scaley = getbits(bp, nscalebits);
183 		if(verbose)
184 			printf("scale %d %d\n", scalex, scaley);
185 	}
186 	if((hasrotate = getbits(bp, 1)))
187 	{	nrotatebits = getbits(bp, 5);
188 		rotateskew0 = getsbits(bp, nrotatebits);
189 		rotateskew1 = getsbits(bp, nrotatebits);
190 		if(verbose)
191 			printf("skew %d %d\n", rotateskew0, rotateskew1);
192 	}
193 	ntranslatebits = getbits(bp, 5);
194 	translatex = getsbits(bp, ntranslatebits);
195 	translatey = getsbits(bp, ntranslatebits);
196 	if(verbose)
197 		printf("translate %d %d\n", translatex, translatey);
198 }
199 /* rgb */
rgb(BITS bp)200 static void rgb(BITS bp)
201 {	int r, g, b;
202 	alignbits(bp);
203 	r = bp->readc(bp); g = bp->readc(bp); b = bp->readc(bp);
204 	if(verbose)
205 		printf("rgb %x %x %x\n", r, g, b);
206 }
rgba(BITS bp)207 static void rgba(BITS bp)
208 {	int r, g, b, a;
209 	alignbits(bp);
210 	r = bp->readc(bp); g = bp->readc(bp); b = bp->readc(bp);
211 	a = bp->readc(bp);
212 	if(verbose)
213 		printf("rgba %x %x %x %x\n", r, g, b, a);
214 }
215 static int
readint2(BITS bp)216 readint2(BITS bp)
217 {	int res;
218 	res = bp->readc(bp);
219 	res |= bp->readc(bp) << 8;
220 	return res;
221 }
222 static int
readint4(BITS bp)223 readint4(BITS bp)
224 {	int res;
225 	res = bp->readc(bp);
226 	res |= bp->readc(bp) << 8;
227 	res |= bp->readc(bp) << 16;
228 	res |= bp->readc(bp) << 24;
229 	return res;
230 }
putint2(unsigned char * p,int val)231 static void putint2(unsigned char *p, int val)
232 {	*p++ = val;
233 	*p++ = val >> 8;
234 }
putint4(unsigned char * p,int val)235 static void putint4(unsigned char *p, int val)
236 {	*p++ = val;
237 	*p++ = val >> 8;
238 	*p++ = val >> 16;
239 	*p++ = val >> 24;
240 }
241 
242 /* open a swf file as a stream */
243 struct swfile
244 {	char lastch;
245 	char bitoff;
246 	unsigned char (*readc)(struct swfile *);
247 
248 	char *name;
249 	unsigned char vers[4];
250 	int fsize;
251 
252 	char rect[9];
253 	unsigned short rectlen;
254 	SWFInput input;
255 	short frames, rate;
256 
257 	short compressed;
258 	unsigned char *zbuf, *zptr, *zend;
259 };
freadc(struct swfile * sp)260 static unsigned char freadc(struct swfile *sp)
261 {	return SWFInput_getChar(sp->input);
262 }
r_readc(struct swfile * sp)263 static unsigned char r_readc(struct swfile *sp)
264 {	return sp->rect[sp->rectlen++] = freadc(sp);
265 }
swfseek(struct swfile * sp,int delta)266 static void swfseek(struct swfile *sp, int delta)
267 {	SWFInput_seek(sp->input, delta, 1);
268 }
269 
openswf(SWFInput input)270 static struct swfile *openswf(SWFInput input)
271 {	struct swfile *res = (struct swfile *)malloc(sizeof(struct swfile));
272 	SWFInput_read(input, res->vers, 4);
273 	if(memcmp(res->vers, "FWS", 3) && memcmp(res->vers, "CWS", 3))
274 		SWF_error("input not a SWF stream\n");
275 	res->fsize = SWFInput_getUInt32(input);
276 	res->compressed = res->vers[0] == 'C';
277 	if(res->compressed)
278 	{
279 #if USE_ZLIB
280 		static z_stream z = {0};
281 		int len = SWFInput_length(input);
282 		unsigned char *zbuf;
283 
284 		z.next_in = (unsigned char *)malloc(z.avail_in = len - 8);
285 		SWFInput_read(input, z.next_in, z.avail_in);
286 		// caller will do, leave it here for double memory consumption
287 		//destroySWFInput(input);
288 		zbuf = z.next_out = (unsigned char *)malloc(z.avail_out = res->fsize - 8);
289 		inflateInit(&z);
290 		inflate(&z, Z_FINISH);
291 		inflateEnd(&z);
292 		input = newSWFInput_allocedBuffer(zbuf, z.next_out-zbuf);
293 #else
294 		SWF_error("The SWF to be opened is compressed, but we can't uncompress it (no zlib compiled into this version of Ming).\n");
295 		return NULL;
296 #endif
297 	}
298 	res->input = input;
299 	// setup to read that rect...
300 	alignbits(res);
301 	res->rectlen = 0;
302 	res->readc = r_readc;
303 	rect((BITS) res);
304 	res->readc = freadc;
305 	readint2((BITS) res);	// movie rate
306 	res->frames = readint2((BITS) res);
307 	return res;
308 }
309 
310 /* tag */
311 struct swftag
312 {	char lastch;
313 	char bitoff;
314 	unsigned char (*readc)(struct swftag *sp);
315 
316 	short type; int size;
317 	unsigned char hdr[6]; short hdrlen;
318 	unsigned char *datbuf, *datptr, *datend;
319 	short alloced;
320 };
321 typedef struct swftag *TAG;
322 
treadc(TAG tp)323 static unsigned char treadc(TAG tp)
324 {	return *tp->datptr++;
325 }
326 
readtag_common(BITS bp)327 static TAG readtag_common(BITS bp)
328 {	TAG res = (TAG) malloc(sizeof(struct swftag));
329 	res->type = readint2(bp);
330 	res->size = res->type & 63;
331 	putint2(res->hdr, res->type);
332 	res->type >>= 6;
333 	res->hdrlen = 2;
334 	if(res->size == 63)
335 	{	res->size = readint4(bp);
336 		putint4(res->hdr+2, res->size);
337 		res->hdrlen = 6;
338 	}
339 	res->bitoff = 0;
340 	res->readc = treadc;
341 	res->alloced = 0;
342 	return res;
343 }
readtag_file(struct swfile * sp)344 static TAG readtag_file(struct swfile *sp)
345 {	TAG res = (TAG) readtag_common((BITS) sp);
346 	if(res->size)
347 	{	res->datbuf = res->datptr = (unsigned char *)malloc(res->size);
348 		res->datend = res->datbuf + res->size;
349 		SWFInput_read(sp->input, res->datbuf, res->size);
350 		res->alloced = 1;
351 	}
352 	return res;
353 }
readtag_sprite(TAG tp)354 static TAG readtag_sprite(TAG tp)
355 {	TAG res = readtag_common((BITS) tp);
356 	if(res->size)
357 	{	res->datbuf = res->datptr = tp->datptr;
358 		res->datend = res->datbuf + res->size;
359 		tp->datptr += res->size;
360 	}
361 	return res;
362 }
363 
364 static int idoffset = {0}, maxid = {0};
change_id(TAG tp)365 static int change_id(TAG tp)
366 {	int val = readint2((BITS) tp);
367 	if(val != 0 && val != 65535)
368 	{	val += idoffset;
369 		if(val > maxid)
370 			maxid = val;
371 		putint2(tp->datptr-2, val);
372 	}
373 	return val;
374 }
375 
376 // processing functions for handle()
377 static void defineshape(TAG tp, int lev);
378 static void definetext(TAG tp, int lev);
379 static void placeobject(TAG tp, int lv);
380 static void definebutton(TAG tp);
381 static void definebutton2(TAG tp);
382 static void definetextfield(TAG tp);
383 static void definesprite(TAG tp);
384 static void definemorphshape(TAG tp,int lev);
385 static void exportassets(TAG tp);
386 static void definebuttonsound(TAG tp);
387 static void fillandlinestyles(TAG tp, int lev);
388 static void linestyle(TAG tp, int lev);
389 static void shape(TAG tp, int lev);
390 static void morphlinestyle2(TAG tp);
391 
drop_tag(TAG tp)392 static int drop_tag(TAG tp)
393 {
394 	switch(tp->type)
395 	{
396 		case SWF_FILEATTRIBUTES:
397 		case SWF_METADATA:
398 		case SWF_DEFINESCENEANDFRAMEDATA: // only allowed in main timeline -> merge ?
399 			return 1;
400 		default:
401 			return 0;
402 	}
403 }
404 
handle_tag(TAG tp)405 static int handle_tag(TAG tp)
406 {	int id;
407 	int displaylist = 0;
408 	if(verbose)
409 	{	char *tagnam = "inknown";
410 		switch(tp->type)
411 		{
412 			case SWF_END:
413 				tagnam = "stagEnd"; break;
414 			case SWF_SHOWFRAME:
415 				tagnam = "stagShowFrame"; break;
416 			case SWF_DEFINESHAPE:
417 				tagnam = "stagDefineShape"; break;
418 			case SWF_FREECHARACTER:
419 				tagnam = "stagFreeCharacter"; break;
420 			case SWF_PLACEOBJECT:
421 				tagnam = "stagPlaceObject"; break;
422 			case SWF_REMOVEOBJECT:
423 				tagnam = "stagRemoveObject"; break;
424 			case SWF_DEFINEBITS:
425 				tagnam = "stagDefineBits"; break;
426 			case SWF_DEFINEBUTTON:
427 				tagnam = "stagDefineButton"; break;
428 			case SWF_JPEGTABLES:
429 				tagnam = "stagJPEGTables"; break;
430 			case SWF_SETBACKGROUNDCOLOR:
431 				tagnam = "stagSetBackgroundColor"; break;
432 			case SWF_DEFINEFONT:
433 				tagnam = "stagDefineFont"; break;
434 			case SWF_DEFINETEXT:
435 				tagnam = "stagDefineText"; break;
436 			case SWF_DOACTION:
437 				tagnam = "stagDoAction"; break;
438 			case SWF_DEFINEFONTINFO:
439 				tagnam = "stagDefineFontInfo"; break;
440 			case SWF_DEFINESOUND:
441 				tagnam = "stagDefineSound"; break;
442 			case SWF_STARTSOUND:
443 				tagnam = "stagStartSound"; break;
444 			case SWF_DEFINEBUTTONSOUND:
445 				tagnam = "stagDefineButtonSound"; break;
446 			case SWF_SOUNDSTREAMHEAD:
447 				tagnam = "stagSoundStreamHead"; break;
448 			case SWF_SOUNDSTREAMBLOCK:
449 				tagnam = "stagSoundStreamBlock"; break;
450 			case SWF_DEFINELOSSLESS:
451 				tagnam = "stagDefineBitsLossless"; break;
452 			case SWF_DEFINEBITSJPEG2:
453 				tagnam = "stagDefineBitsJPEG2"; break;
454 			case SWF_DEFINESHAPE2:
455 				tagnam = "stagDefineShape2"; break;
456 			case SWF_DEFINEBUTTONCXFORM:
457 				tagnam = "stagDefineButtonCxform"; break;
458 			case SWF_PROTECT:
459 				tagnam = "stagProtect"; break;
460 			case SWF_PLACEOBJECT2:
461 				tagnam = "stagPlaceObject2"; break;
462 			case SWF_PLACEOBJECT3:
463 				tagnam = "stagPlaceObject3"; break;
464 			case SWF_REMOVEOBJECT2:
465 				tagnam = "stagRemoveObject2"; break;
466 			case SWF_DEFINESHAPE3:
467 				tagnam = "stagDefineShape3"; break;
468 			case SWF_DEFINESHAPE4:
469 				tagnam = "stagDefineShape4"; break;
470 			case SWF_DEFINETEXT2:
471 				tagnam = "stagDefineText2"; break;
472 			case SWF_DEFINEBUTTON2:
473 				tagnam = "stagDefineButton2"; break;
474 			case SWF_DEFINEBITSJPEG3:
475 				tagnam = "stagDefineBitsJPEG3"; break;
476 			case SWF_DEFINELOSSLESS2:
477 				tagnam = "stagDefineBitsLossless2"; break;
478 			case SWF_DEFINEEDITTEXT:
479 				tagnam = "stagDefineTextField"; break;
480 			case SWF_DEFINESPRITE:
481 				tagnam = "stagDefineSprite"; break;
482 			case SWF_NAMECHARACTER:
483 				tagnam = "stagNameCharacter"; break;
484 			case SWF_FRAMELABEL:
485 				tagnam = "stagFrameLabel"; break;
486 			case SWF_SOUNDSTREAMHEAD2:
487 				tagnam = "stagSoundStreamHead2"; break;
488 			case SWF_DEFINEMORPHSHAPE:
489 				tagnam = "stagDefineMorphShape"; break;
490 			case SWF_DEFINEMORPHSHAPE2:
491 				tagnam = "stagDefineMorphShape2"; break;
492 			case SWF_DEFINEFONT2:
493 				tagnam = "stagDefineFont2"; break;
494 			case SWF_DEFINEFONT3:
495 				tagnam = "stagDefineFont3"; break;
496 			case SWF_DEFINEFONTALIGNZONES:
497 				tagnam = "stagDefineFontAlignZones"; break;
498 			case SWF_EXPORTASSETS:
499 				tagnam = "stagExportAssets"; break;
500 			/*case stagClipInit:
501 				tagnam = "stagClipInit"; break;*/
502 			/*case stagNewFontInfo:
503 				tagnam = "stagNewFontInfo"; break;*/
504 			case SWF_DEFINEVIDEOSTREAM:
505 				tagnam = "stagDefineVideoStrem"; break;
506 			case SWF_VIDEOFRAME:
507 				tagnam = "stagVideoFrame"; break;
508 			case SWF_INITACTION:
509 				tagnam = "stagInitAction"; break;
510 		}
511 		printf("tag %d %s\n", tp->type, tagnam);
512 	}
513 	switch(tp->type)
514 	{	/* tags without an id */
515 		case SWF_END:
516 		case SWF_SHOWFRAME:
517 		case SWF_SETBACKGROUNDCOLOR:
518 		case SWF_DOACTION:
519 		case SWF_PROTECT:
520 		case SWF_REMOVEOBJECT2:
521 		case SWF_FRAMELABEL:
522 		case SWF_SOUNDSTREAMHEAD:
523 		case SWF_SOUNDSTREAMHEAD2:
524 		case SWF_SOUNDSTREAMBLOCK:
525 		case SWF_JPEGTABLES:
526 		case SWF_SYMBOLCLASS:
527 		case SWF_DOABC:
528 		case SWF_DEFINEFONTNAME:
529 		/*case stagClipInit:*/
530 			break;
531 		/* simple tags - one id at beginning */
532 		case SWF_FREECHARACTER:
533 		case SWF_PLACEOBJECT:
534 		case SWF_REMOVEOBJECT:
535 		case SWF_DEFINEBITS:
536 		case SWF_DEFINEBITSJPEG2:
537 		case SWF_DEFINEBITSJPEG3:
538 		case SWF_DEFINELOSSLESS:
539 		case SWF_DEFINELOSSLESS2:
540 		case SWF_DEFINEFONT:
541 		case SWF_DEFINEFONTINFO:
542 		case SWF_DEFINESOUND:
543 		case SWF_STARTSOUND:
544 		case SWF_NAMECHARACTER:
545 		case SWF_DEFINEFONT2:
546 		case SWF_DEFINEFONT3:
547 		case SWF_DEFINEFONTALIGNZONES:
548 		case SWF_DEFINEBUTTONCXFORM:
549 		case SWF_DEFINEVIDEOSTREAM:
550 		case SWF_VIDEOFRAME:
551 		case SWF_INITACTION:
552 		case SWF_DEFINEBINARYDATA:
553 		/*case SWF_NEWFONTINFO:*/
554 			id = change_id(tp);
555 			if(verbose)
556 				printf("id %d offset %d\n", id, idoffset);
557 			break;
558 		/* to be processed specially */
559 		case SWF_DEFINESHAPE:
560 			defineshape(tp, 1);
561 			break;
562 		case SWF_DEFINETEXT:
563 			definetext(tp, 1);
564 			break;
565 		case SWF_DEFINESHAPE2:
566 			defineshape(tp, 2);
567 			break;
568 		case SWF_PLACEOBJECT2:
569 			placeobject(tp, 2);
570 			break;
571 		case SWF_PLACEOBJECT3:
572 			placeobject(tp, 3);
573 			break;
574 		case SWF_DEFINESHAPE3:
575 			defineshape(tp, 3);
576 			break;
577 		case SWF_DEFINESHAPE4:
578 			defineshape(tp, 4);
579 			break;
580 		case SWF_DEFINETEXT2:
581 			definetext(tp, 2);
582 			break;
583 		case SWF_DEFINEBUTTON:
584 			definebutton(tp);
585 			break;
586 		case SWF_DEFINEBUTTON2:
587 			definebutton2(tp);
588 			break;
589 		case SWF_DEFINEEDITTEXT:
590 			definetextfield(tp);
591 			break;
592 		case SWF_DEFINESPRITE:
593 			definesprite(tp);
594 			break;
595 		case SWF_DEFINEMORPHSHAPE:
596 			definemorphshape(tp, 1);
597 			break;
598 		case SWF_DEFINEMORPHSHAPE2:
599 			definemorphshape(tp, 2);
600 			break;
601 		case SWF_EXPORTASSETS:
602 			exportassets(tp);
603 			break;
604 		case SWF_DEFINEBUTTONSOUND:
605 			definebuttonsound(tp);
606 			break;
607 		default:
608 			SWF_error("unknown tag %d\n", tp->type);
609 	}
610 	switch(tp->type)
611 	{	case SWF_END:
612 		case SWF_SHOWFRAME:
613 		case SWF_DOACTION:
614 		case SWF_REMOVEOBJECT2:
615 		case SWF_FRAMELABEL:
616 		case SWF_SOUNDSTREAMHEAD:
617 		case SWF_SOUNDSTREAMHEAD2:
618 		case SWF_SOUNDSTREAMBLOCK:
619 		case SWF_DEFINEVIDEOSTREAM:
620 		case SWF_VIDEOFRAME:
621 		case SWF_INITACTION:
622 		case SWF_FREECHARACTER:
623 		case SWF_PLACEOBJECT:
624 		case SWF_REMOVEOBJECT:
625 		case SWF_STARTSOUND:
626 		case SWF_NAMECHARACTER:
627 		case SWF_PLACEOBJECT2:
628 		case SWF_PLACEOBJECT3:
629 			displaylist = 1;
630 	}
631 	return displaylist;
632 }
633 
definesprite(TAG sp)634 static void definesprite(TAG sp)
635 {	TAG tp;
636 	int type;
637 	int id, frames;
638 	id = change_id(sp);
639 	frames = readint2((BITS) sp);
640 	if(verbose)
641 		printf("sprite %d, %d frames\n", id, frames);
642 	do
643 	{	tp = readtag_sprite(sp);
644 		handle_tag(tp);
645 		type = tp->type;
646 		free(tp);
647 	} while(type);
648 	if(sp->datptr != sp->datend)
649 		SWF_error("consistency check: file size wrong in sprite\n");
650 }
651 
652 /* shape */
shaperecord(TAG tp,int nfillbits,int nlinebits,int lev)653 static void shaperecord(TAG tp, int nfillbits, int nlinebits, int lev)
654 {	int type, statenewstyles, statelinestyle, statefillstyle1, statefillstyle0;
655 	int statemoveto, movebits, movex, movey, fill0style, fill1style, linestyle;
656 	int edgeflag, nbits, genlineflag, dx, dy, vertlineflag;
657 	int cdx, cdy, adx, ady;
658 
659 	while(1)
660 	{	type = getbits((BITS) tp, 1);
661 
662 		if(!type)
663 		{	statenewstyles = getbits((BITS) tp, 1);
664 			statelinestyle = getbits((BITS) tp, 1);
665 			statefillstyle1 = getbits((BITS) tp, 1);
666 			statefillstyle0 = getbits((BITS) tp, 1);
667 			if((statemoveto = getbits((BITS) tp, 1)))
668 			{	movebits = getbits((BITS) tp, 5);
669 				movex = getsbits((BITS) tp, movebits);
670 				movey = getsbits((BITS) tp, movebits);
671 				if(verbose)
672 					printf("move %d %d\n", movex, movey);
673 			}
674 			if(statenewstyles == 0 && statelinestyle == 0 && statefillstyle1 == 0&& statefillstyle0 == 0 && statemoveto == 0)
675 				break;
676 			if(statefillstyle0)
677 			{	fill0style = getbits((BITS) tp, nfillbits);
678 				if(verbose)
679 					printf("fillstyle0 %d\n", fill0style);
680 			}
681 			if(statefillstyle1)
682 			{	fill1style = getbits((BITS) tp, nfillbits);
683 				if(verbose)
684 					printf("fillstyle1 %d\n", fill1style);
685 			}
686 			if(statelinestyle)
687 			{	linestyle = getbits((BITS) tp, nlinebits);
688 				if(verbose)
689 					printf("linestyle %d\n", linestyle);
690 			}
691 /* contrary to document, but
692  ... seems to work AND make sense
693  */
694 			if(statefillstyle0 || statefillstyle1 || statelinestyle)
695 				;
696 			else
697 			if(statenewstyles)
698 				fillandlinestyles(tp, lev);
699 		}
700 		else
701 		{	edgeflag = getbits((BITS) tp, 1);
702 			if(!edgeflag)	/* curve */
703 			{	nbits = getbits((BITS) tp, 4)+2;
704 				cdx = getsbits((BITS) tp, nbits);
705 				cdy = getsbits((BITS) tp, nbits);
706 				adx = getsbits((BITS) tp, nbits);
707 				ady = getsbits((BITS) tp, nbits);
708 				if(verbose)
709 					printf("curve %d,%d %d,%d\n", cdx, cdy, adx, ady);
710 			}
711 			else
712 			{	nbits = getbits((BITS) tp, 4)+2;
713 				if((genlineflag = getbits((BITS) tp, 1)))
714 				{	dx = getsbits((BITS) tp, nbits);
715 					dy = getsbits((BITS) tp, nbits);
716 				}
717 				else if((vertlineflag = getbits((BITS) tp, 1)))
718 				{	dx = 0;
719 					dy = getsbits((BITS) tp, nbits);
720 				}
721 				else
722 				{	dx = getsbits((BITS) tp, nbits);
723 					dy = 0;
724 				}
725 				if(verbose)
726 					printf("line %d,%d\n", dx, dy);
727 			}
728 		}
729 	}
730 }
731 
gradient(TAG tp,int alpha,int cod)732 static void gradient(TAG tp, int alpha, int cod)
733 {	int n, ngrad, r1;
734 
735 	alignbits(tp);
736 	ngrad = tp->readc(tp);
737 	for(n = 0 ; n < ngrad ; n++)
738 	{	r1 = tp->readc(tp);
739 		if(verbose)
740 			printf("ratio %d\n", r1);
741 		if(alpha) rgba((BITS) tp); else rgb((BITS) tp);
742 	}
743 	if (cod == 0x13)
744 		readint2((BITS) tp);
745 }
746 
fillstyle(TAG tp,int lev)747 static void fillstyle(TAG tp, int lev)
748 {	unsigned short id;
749 	char cod;
750 
751 	alignbits(tp);
752 	cod = tp->readc(tp);
753 	switch(cod)
754 	{	case 0:
755 			if(verbose) printf("solid fill:\n"); break;
756 		case 0x10:
757 			if(verbose) printf("linear gradient fill\n"); break;
758 		case 0x12:
759 			if(verbose) printf("radial gradient fill:\n"); break;
760 		case 0x13:
761 			if(verbose) printf("focal gradient fill:\n"); break;
762 		case 0x40:
763 			if(verbose) printf("tiled bitmap fill:\n"); break;
764 		case 0x41:
765 			if(verbose) printf("clipped bitmap fill\n"); break;
766 		case 0x42:
767 			if(verbose) printf("tilled bitmap fill with hard edges\n"); break;
768 		case 0x43:
769 			if(verbose) printf("clipped bitmap fill with hard edges\n"); break;
770 	}
771 	if(cod == 0)
772 		if(lev >= 3) rgba((BITS) tp); else rgb((BITS) tp);
773 	else if(cod == 0x10 || cod == 0x12 || cod == 0x13)
774 	{	matrix((BITS) tp);
775 		gradient(tp, lev >= 3, cod);
776 	}
777 	else if(cod == 0x40 || cod == 0x41 || cod == 0x42 || cod == 0x43)
778 	{	id = change_id(tp);
779 		if(verbose)
780 			printf("fill with id %d\n", id);
781 		matrix((BITS) tp);
782 	}
783 	else
784 		printf("%s:%d: UNEXPEDCED %x\n", __FILE__, __LINE__, cod);
785 }
786 
morphgradient(TAG tp)787 static void morphgradient(TAG tp)
788 {	int n, ngrad, r1, r2;
789 
790 	alignbits(tp);
791 	ngrad = tp->readc(tp);
792 	for(n = 0 ; n < ngrad ; n++)
793 	{	r1 = tp->readc(tp);
794 		if(verbose)
795 			printf("ratio %d\n", r1);
796 		rgba((BITS) tp);
797 		r2 = tp->readc(tp);
798 		if(verbose)
799 			printf("ratio %d\n", r2);
800 		rgba((BITS) tp);
801 	}
802 }
803 
morphfillstyle(TAG tp)804 static void morphfillstyle(TAG tp)
805 {	unsigned short id;
806 	char cod;
807 
808 	alignbits(tp);
809 	cod = tp->readc(tp);
810 	switch(cod)
811 	{	case 0:
812 			if(verbose) printf("solid fill:\n"); break;
813 		case 0x10:
814 			if(verbose) printf("linear gradient fill\n"); break;
815 		case 0x12:
816 			if(verbose) printf("radial gradient fill:\n"); break;
817 		case 0x13:
818 			if(verbose) printf("focal gradient fill:\n"); break;
819 		case 0x40:
820 			if(verbose) printf("tiled bitmap fill:\n"); break;
821 		case 0x41:
822 			if(verbose) printf("clipped bitmap fill\n"); break;
823 		case 0x42:
824 			if(verbose) printf("tilled bitmap fill with hard edges\n"); break;
825 		case 0x43:
826 			if(verbose) printf("clipped bitmap fill with hard edges\n"); break;
827 	}
828 	if(cod == 0)
829 	{	rgba((BITS) tp);
830 		rgba((BITS) tp);
831 	}
832 	else if(cod == 0x10 || cod == 0x12 || cod == 0x13)
833 	{	matrix((BITS) tp);
834 		alignbits(tp);
835 		matrix((BITS) tp);
836 		morphgradient(tp);
837 	}
838 	else if(cod == 0x40 || cod == 0x41 || cod == 0x42 || cod == 0x43)
839 	{	id = change_id(tp);
840 		if(verbose) printf("fill with id %d\n", id);
841 		matrix((BITS) tp);
842 		alignbits(tp);
843 		matrix((BITS) tp);
844 	}
845 	else
846 		printf("%s:%d: UNEXPEDCED %x\n", __FILE__, __LINE__, cod);
847 }
848 
fillandlinestyles(TAG tp,int lev)849 static void fillandlinestyles(TAG tp, int lev)
850 {	int n, nfill, nline;
851 
852 	alignbits(tp);
853 	nfill = tp->readc(tp);
854 	if(nfill == 0xff)
855 		nfill = readint2((BITS) tp);
856 	if(verbose)
857 		printf ("%d fill styles\n", nfill);
858 	for(n = 0 ; n < nfill ; n++)
859 		fillstyle(tp, lev);
860 	alignbits(tp);
861 	nline = tp->readc(tp);
862 	if(nline == 0xff)
863 		nline = readint2((BITS) tp);
864 	if(verbose)
865 		printf ("%d line styles\n", nline);
866 	for(n = 0 ; n < nline ; n++)
867 		if (lev == 4)
868 			morphlinestyle2(tp);
869 		else
870 			linestyle(tp, lev);
871 }
872 
linestyle(TAG tp,int lev)873 static void linestyle(TAG tp, int lev)
874 {	unsigned short w;
875 	w = readint2((BITS) tp);
876 	if(verbose)
877 		printf ("w %d\n", w);
878 	if(lev >= 3) rgba((BITS) tp); else rgb((BITS) tp);
879 }
880 
morphlinestyle(TAG tp)881 static void morphlinestyle(TAG tp)
882 {	unsigned short w1, w2;
883 	w1 = readint2((BITS) tp);
884 	w2 = readint2((BITS) tp);
885 	if(verbose)
886 		printf("w %d => %d\n", w1, w2);
887 	rgba((BITS) tp); rgba((BITS) tp);
888 }
889 
morphlinestyle2(TAG tp)890 static void morphlinestyle2(TAG tp)
891 {	unsigned short w1;
892 	int join_style;
893 	int has_fill;
894 	int is_morph = (tp->type == SWF_DEFINEMORPHSHAPE2);
895 	w1 = readint2((BITS) tp);
896 	if (is_morph) {
897 		unsigned short w2;
898 		w2 = readint2((BITS) tp);
899 		if(verbose)
900 			printf("w %d => %d\n", w1, w2);
901 	} else {
902 		if(verbose)
903 			printf("w %d\n", w1);
904 	}
905 	getbits((BITS) tp, 2);
906 	join_style = getbits((BITS) tp, 2);
907 	has_fill = getbits((BITS) tp, 1);
908 	getbits((BITS) tp, 11);
909 	if (join_style == 2) {
910 		readint2((BITS) tp);
911 	} else {
912 		if (has_fill) {
913 			if (is_morph)
914 				morphfillstyle(tp);
915 			else
916 				fillstyle(tp, 4);
917 		} else {
918 			rgba((BITS) tp);
919 			if (is_morph)
920 				rgba((BITS) tp);
921 		}
922 	}
923 }
924 
defineshape(TAG tp,int lev)925 static void defineshape(TAG tp, int lev)
926 {	unsigned short id;
927 
928 	id = change_id(tp);
929 	if(verbose)
930 		printf("shape %d\n", id);
931 	alignbits(tp);
932 	rect((BITS) tp);
933 	if(lev == 4) {
934 		alignbits(tp);
935 		rect((BITS) tp);
936 		alignbits(tp);
937 		tp->readc(tp);
938 	}
939 	fillandlinestyles(tp, lev);
940 	shape(tp, lev);
941 }
942 
shape(TAG tp,int lev)943 static void shape(TAG tp, int lev)
944 {	int nfillbits, nlinebits;
945 	alignbits(tp);
946 	nfillbits = getbits((BITS) tp, 4);
947 	nlinebits = getbits((BITS) tp, 4);
948 	shaperecord(tp, nfillbits, nlinebits,lev);
949 }
950 
definemorphshape(TAG tp,int lev)951 static void definemorphshape(TAG tp, int lev)
952 {	unsigned short id, fcnt, lcnt;
953 	unsigned long loff;
954 	unsigned char *endp;
955 	int n;
956 
957 	id = change_id(tp);
958 	if(verbose)
959 		printf("morph %d\n", id);
960 	rect((BITS) tp);
961 	alignbits(tp);
962 	rect((BITS) tp);
963 	if (lev == 2) {
964 		rect((BITS) tp);
965 		rect((BITS) tp);
966 		tp->readc(tp);
967 	}
968 	loff = readint4((BITS) tp);
969 	endp = tp->datptr + loff;
970 	fcnt = tp->readc(tp);
971 	if(fcnt == 0xff)
972 		fcnt = readint2((BITS) tp);
973 	if(verbose)
974 		printf ("%d fill styles\n", fcnt);
975 	for(n = 0 ; n < fcnt ; n++)
976 	{	alignbits(tp);
977 		morphfillstyle(tp);
978 	}
979 	lcnt = tp->readc(tp);
980 	if(lcnt == 0xff)
981 		lcnt = readint2((BITS) tp);
982 	if(verbose)
983 		printf ("%d line styles\n", lcnt);
984 	for(n = 0 ; n < lcnt ; n++)
985 	{	alignbits(tp);
986 		if (lev == 2)
987 			morphlinestyle2(tp);
988 		else
989 			morphlinestyle(tp);
990 	}
991 /*	for(n = 0 ; tp->datptr < endp ; n++)
992 	{	alignbits(tp);
993 		shaperecord(tp, bits_req(fcnt), bits_req(lcnt), 3);
994 	}
995 	for( ; n > 0 ; --n)
996 	{	alignbits(tp);
997 		shaperecord(tp, bits_req(fcnt), bits_req(lcnt), 3);
998 	}*/
999 	shape(tp, 3);
1000 }
1001 
definetext(TAG tp,int lev)1002 static void definetext(TAG tp, int lev)
1003 {	unsigned short textid;
1004 	int nglyphbits, nadvancebits;
1005 	int n, nglyphs, chcode, dx;
1006 	int hasfont, hascolor, hasyoffset, hasxoffset;
1007 	unsigned short font=0, height;
1008 	signed short xoffs, yoffs;
1009 
1010 	textid = change_id(tp);
1011 	if(verbose) printf("text %d\n", textid);
1012 	rect((BITS) tp);
1013 	alignbits(tp);
1014 	matrix((BITS) tp);
1015 	nglyphbits = tp->readc(tp);
1016 	nadvancebits = tp->readc(tp);
1017 	alignbits(tp);
1018 	while(1)
1019 	{	if(!getbits((BITS) tp, 1))
1020 		{	nglyphs = getbits((BITS) tp, 7);
1021 			if(!nglyphs)
1022 				break;
1023 			if(verbose) printf("%d chars:\n", nglyphs);
1024 			for(n = 0 ; n < nglyphs ; n++)
1025 			{	chcode = getbits((BITS) tp, nglyphbits);
1026 				dx = getsbits((BITS) tp, nadvancebits);
1027 				if(verbose) printf("code %d dx %d\n", chcode, dx);
1028 			}
1029 		}
1030 		else
1031 		{	getbits((BITS) tp, 3);
1032 			hasfont = getbits((BITS) tp, 1);
1033 			hascolor = getbits((BITS) tp, 1);
1034 			hasyoffset = getbits((BITS) tp, 1);
1035 			hasxoffset = getbits((BITS) tp, 1);
1036 			if(hasfont)
1037 				font = change_id(tp);
1038 			if(hascolor)
1039 			{	if(lev == 2) rgba((BITS) tp);
1040 				else rgb((BITS) tp);
1041 			}
1042 			if(hasxoffset)
1043 			{	xoffs = readint2((BITS) tp);
1044 				if(verbose) printf("dx %d\n", xoffs);
1045 			}
1046 			if(hasyoffset)
1047 			{	yoffs = readint2((BITS) tp);
1048 				if(verbose) printf("dy %d\n", yoffs);
1049 			}
1050 			if(hasfont)
1051 			{	height = readint2((BITS) tp);
1052 				if(verbose) printf("font %d size %d\n", font, height);
1053 			}
1054 		}
1055 		alignbits(tp);
1056 	}
1057 }
1058 
placeobject(TAG tp,int lv)1059 static void placeobject(TAG tp, int lv)
1060 {	int hasname, hasratio, hascxform, hasmatrix, haschar, hasmove, hasactions, hasmask;
1061 	short depth, charid;
1062 	int hasfilters, hasbitmapcaching, hasblendmode;
1063 	if (lv == 3) {
1064 		getbits((BITS)tp, 5);
1065 		hasbitmapcaching = getbits((BITS)tp, 1);
1066 		hasblendmode = getbits((BITS)tp, 1);
1067 		hasfilters = getbits((BITS)tp, 1);
1068 	}
1069 	hasactions = getbits((BITS)tp, 1);
1070 	hasmask = getbits((BITS)tp, 1);
1071 	hasname = getbits((BITS)tp, 1);
1072 	hasratio = getbits((BITS)tp, 1);
1073 	hascxform = getbits((BITS)tp, 1);
1074 	hasmatrix = getbits((BITS)tp, 1);
1075 	haschar = getbits((BITS)tp, 1);
1076 	hasmove = getbits((BITS)tp, 1);
1077 	depth = readint2((BITS) tp);
1078 	if(haschar)
1079 	{	charid = change_id(tp);
1080 		if(verbose) printf("char %d depth %d\n", charid, depth);
1081 	}
1082 }
1083 
definebutton(TAG tp)1084 static void definebutton(TAG tp)
1085 {	short butid, charid, layer;
1086 	unsigned char bstate;
1087 
1088 	butid = change_id(tp);
1089 	if(verbose)
1090 		printf("char %d:\n", butid);
1091 	while((bstate = tp->readc(tp)))
1092 	{	if(bstate & 8)
1093 			if(verbose) printf("hit test ");
1094 		if(bstate & 4)
1095 			if(verbose) printf("down ");
1096 		if(bstate & 2)
1097 			if(verbose) printf("over ");
1098 		if(bstate & 1)
1099 			if(verbose) printf("up");
1100 		if(verbose) printf("\n");
1101 		charid = change_id(tp);
1102 		layer = readint2((BITS) tp);
1103 		if(verbose) printf("char %d layer %d\n", charid, layer);
1104 		alignbits(tp);
1105 		matrix((BITS) tp);
1106 	}
1107 }
1108 
cxform(TAG tp,int alpha)1109 static void cxform(TAG tp, int alpha)
1110 {	int hasadd, hasmult, nbits;
1111 	int ra, ga, ba, aa, rm, gm, bm, am=0;
1112 	hasadd = getbits((BITS) tp, 1);
1113 	hasmult = getbits((BITS) tp, 1);
1114 	nbits = getbits((BITS) tp, 4);
1115 	if(verbose) printf("cxform ");
1116 	if(hasmult)
1117 	{	rm = getsbits((BITS) tp, nbits);
1118 		gm = getsbits((BITS) tp, nbits);
1119 		bm = getsbits((BITS) tp, nbits);
1120 		if(alpha) am  = getsbits((BITS) tp, nbits);
1121 		if(verbose) printf("mul %d %d %d ", rm, gm, bm);
1122 		if(verbose) if(alpha) printf("%d ", am);
1123 	}
1124 	if(hasadd)
1125 	{	ra = getsbits((BITS) tp, nbits);
1126 		ga = getsbits((BITS) tp, nbits);
1127 		ba = getsbits((BITS) tp, nbits);
1128 		if(alpha) aa = getsbits((BITS) tp, nbits);
1129 		if(verbose) printf("add %d %d %d", ra, ga, ba);
1130 		if(verbose) if(alpha) printf(" %d", am);
1131 	}
1132 	if(verbose) printf("\n");
1133 }
1134 
definebutton2(TAG tp)1135 static void definebutton2(TAG tp)
1136 {	short id, charid, offs, layer;
1137 	unsigned char ch, bstate;
1138 
1139 	id = change_id(tp);
1140 	ch = tp->readc(tp);
1141 	offs = readint2((BITS) tp);
1142 	if(verbose)
1143 		printf("id %d %s action offset %d\n", id, ch ? "menu" : "button", offs);
1144 	while((bstate = tp->readc(tp)))
1145 	{	if(bstate & 8)
1146 			if(verbose) printf("hit test ");
1147 		if(bstate & 4)
1148 			if(verbose) printf("down ");
1149 		if(bstate & 2)
1150 			if(verbose) printf("over ");
1151 		if(bstate & 1)
1152 			if(verbose) printf("up");
1153 		if(verbose) printf("\n");
1154 		charid = change_id(tp);
1155 		layer = readint2((BITS) tp);
1156 		if(verbose) printf("char %d layer %d\n", charid, layer);
1157 		alignbits(tp);
1158 		matrix((BITS) tp);
1159 		alignbits(tp);
1160 		cxform(tp, 1);
1161 	}
1162 }
1163 
definetextfield(TAG tp)1164 static void definetextfield(TAG tp)
1165 {
1166 	short textid, fontid=0;
1167 	int haslength, noedit, password, multiline, wordwrap, drawbox, noselect, html, usefont;
1168 	int hascolor, haslayout, hastext, hasfont;
1169 
1170 	textid = change_id(tp);
1171 	if(verbose) printf("textfield %d\n", textid);
1172 	rect((BITS) tp);
1173 	alignbits(tp);
1174 	hastext = getbits((BITS) tp, 1);
1175 	wordwrap = getbits((BITS) tp, 1);
1176 	multiline = getbits((BITS) tp, 1);
1177 	password = getbits((BITS) tp, 1);
1178 	noedit = getbits((BITS) tp, 1);
1179 	hascolor = getbits((BITS) tp, 1);
1180 	haslength = getbits((BITS) tp, 1);
1181 	hasfont = getbits((BITS) tp, 1);
1182 	getbits((BITS) tp, 2);
1183 	haslayout = getbits((BITS) tp, 1);
1184 	noselect = getbits((BITS) tp, 1);
1185 	drawbox = getbits((BITS) tp, 1);
1186 	getbits((BITS) tp, 1);
1187 	html = getbits((BITS) tp, 1);
1188 	usefont = getbits((BITS) tp, 1);
1189 	if(hasfont)
1190 		fontid = change_id(tp);
1191 	if(verbose)
1192 	{	if ( fontid ) printf("font %d ", fontid);
1193 		if(noedit) printf("noedit ");
1194 		if(password) printf("password ");
1195 		if(multiline) printf("multiline ");
1196 		if(wordwrap) printf("wordwrap ");
1197 		if(drawbox) printf("drawbox ");
1198 		if(noselect) printf("noselect ");
1199 		if(html) printf("html ");
1200 		if(usefont) printf("usefont ");
1201 		if(hascolor) rgba((BITS) tp);
1202 		putchar('\n');
1203 	}
1204 }
1205 
exportassets(TAG tp)1206 static void exportassets(TAG tp)
1207 {	short n, nobj, id;
1208 	char ch;
1209 	nobj = readint2((BITS) tp);
1210 	for(n = 0 ; n < nobj ; n++)
1211 	{	id = change_id(tp);
1212 		if(verbose) printf("%d ", id);
1213 		while((ch = tp->readc(tp)))
1214 			if(verbose) putchar(ch);
1215 		if(verbose)
1216 			putchar((n < nobj-1) ? ' ' : '\n');
1217 	}
1218 }
1219 
soundinfo(TAG tp)1220 static void soundinfo(TAG tp)
1221 {	char flags, hasenvelope, hasloops, hasoutpoint, hasinpoint, npoints;
1222 	signed short loops, lev0, lev1;
1223 	int soundpoint, n;
1224 	flags = getbits((BITS) tp, 4);
1225 	hasenvelope = getbits((BITS) tp, 1);
1226 	hasloops = getbits((BITS) tp, 1);
1227 	hasoutpoint = getbits((BITS) tp, 1);
1228 	hasinpoint = getbits((BITS) tp, 1);
1229 	if(flags & 1)
1230 		if(verbose) printf("no multiple ");
1231 	if(flags & 2)
1232 		if(verbose) printf("stop");
1233 	if(flags & 3)
1234 		if(verbose) putchar('\n');
1235 	if(hasinpoint)
1236 	{	soundpoint = readint4((BITS) tp);
1237 		if(verbose) printf("inpoint %d\n", soundpoint);
1238 	}
1239 	if(hasoutpoint)
1240 	{	soundpoint = readint4((BITS) tp);
1241 		if(verbose) printf("outpoint %d\n", soundpoint);
1242 	}
1243 	if(hasloops)
1244 	{	loops = readint2((BITS) tp);
1245 		if(verbose) printf("%d loops\n", loops);
1246 	}
1247 	if(hasenvelope)
1248 	{	npoints = tp->readc(tp);
1249 		for(n = 0 ; n < npoints ; n++)
1250 		{	soundpoint = readint4((BITS) tp);
1251 			lev0 = readint2((BITS) tp);
1252 			lev1 = readint2((BITS) tp);
1253 			if(verbose) printf("%d: %d %d\n", soundpoint, lev0, lev1);
1254 		}
1255 	}
1256 }
1257 
definebuttonsound(TAG tp)1258 static void definebuttonsound(TAG tp)
1259 {	int id, n, snds[4];
1260 	id = change_id(tp);
1261 	if(verbose)
1262 		printf("id %d\n", id);
1263 	for(n = 0 ; n < 4 ; n++)
1264 	{	snds[n] = change_id(tp);
1265 		if(verbose)
1266 			printf("sound %d:\n", snds[n]);
1267 		alignbits(tp);
1268 		if(snds[n]) soundinfo(tp);
1269 	}
1270 }
1271 
1272 extern int SWF_gNumCharacters;
1273 
1274 /*
1275  * load and create a SWF File as MovieClip
1276  */
1277 SWFPrebuiltClip
newSWFPrebuiltClip_fromInput(SWFInput input)1278 newSWFPrebuiltClip_fromInput(SWFInput input)
1279 {	SWFPrebuiltClip clip;
1280 	SWFOutput display, defines, out;
1281 	SWFPrebuilt deps;
1282 	TAG tp;
1283 	struct swfile *swf;
1284 	int type = 0, todisplay;
1285 
1286 	swf = openswf(input);
1287 	if ( ! swf ) return NULL;
1288 	clip = newSWFPrebuiltClip();
1289 	clip->frames = swf->frames;
1290 	display = clip->display;
1291 	deps = newSWFPrebuilt();
1292 	SWFCharacter_addDependency((SWFCharacter)clip, (SWFCharacter)deps);
1293 	defines = deps->defines;
1294 	idoffset = SWF_gNumCharacters;
1295 	maxid = SWF_gNumCharacters;
1296 	// read the swf file here
1297 	tp = readtag_file(swf);
1298 		if(tp->type != SWF_SETBACKGROUNDCOLOR)
1299 			swfseek(swf, -(tp->hdrlen + tp->size));
1300 	if(tp->alloced)
1301 		free(tp->datbuf);
1302 	free(tp);
1303 	do
1304 	{	tp = readtag_file(swf);
1305 		type = tp->type;
1306 		if(drop_tag(tp))
1307 		{
1308 			if(tp->alloced)
1309 				free(tp->datbuf);
1310 			free(tp);
1311 			continue;
1312 		}
1313 		todisplay = handle_tag(tp);
1314 		out = todisplay ? display : defines;
1315 		SWFOutput_writeBuffer(out, tp->hdr, tp->hdrlen);
1316 		if(tp->size)
1317 			SWFOutput_writeBuffer(out, tp->datbuf, tp->size);
1318 		if(tp->alloced)
1319 			free(tp->datbuf);
1320 		free(tp);
1321 	} while(type);
1322 	if(swf->compressed)
1323 		destroySWFInput(swf->input);
1324 	SWF_gNumCharacters = maxid + 1;
1325 	CHARACTERID(clip) = SWF_gNumCharacters++;
1326 	return clip;
1327 }
1328 
1329 /*
1330  * load SWF file which can be used as a MovieClip
1331  */
1332 SWFPrebuiltClip
newSWFPrebuiltClip_fromFile(const char * filename)1333 newSWFPrebuiltClip_fromFile(const char *filename)
1334 {	FILE *fp;
1335 	SWFPrebuiltClip clip;
1336 	SWFInput input;
1337 	if(!(fp = fopen(filename, "rb")))
1338 		return NULL;
1339 	input = newSWFInput_file(fp);
1340 	clip = newSWFPrebuiltClip_fromInput(input);
1341 	destroySWFInput(input);
1342 	fclose(fp);
1343 	return clip;
1344 }
1345