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