2 Various routines for reading and writing swf files and tags.
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This file is distributed under the GPL, see file COPYING for details */
13 void swf_init(uchar*newdata, int newlength)
15 reader_init (&newdata[3], newlength - 3);
18 struct flash_header swf_read_header()
20 struct flash_header head;
25 u8* oldpos = getinputpos();
28 head.version = version;
33 head.boundingBox = readRECT();
39 head.headerlength = getinputpos() - oldpos;
40 head.headerdata = oldpos;
54 struct RGBA readRGBA()
64 struct GRADIENT readGRADIENT(int shape)
66 struct GRADIENT gradient;
68 gradient.num = readu8();
69 for(t=0;t<gradient.num;t++)
71 gradient.ratios[t] = readu8();
73 gradient.rgb[t] = readRGB();
75 gradient.rgba[t] = readRGBA();
79 struct RECT readRECT()
97 void writeRECT(u8**pos, struct RECT*r)
101 writer_init(&w, *pos, 256);
102 writer_writebits(&w, 31, 5); //FIXME:count
103 writer_writebits(&w, r->x1, 31);
104 writer_writebits(&w, r->x2, 31);
105 writer_writebits(&w, r->y1, 31);
106 writer_writebits(&w, r->y2, 31);
107 writer_resetbits(&w);
108 *pos = writer_getpos(&w);
111 struct CXFORM readCXFORM()
122 c.rmult=getsbits(bits)/65536.0;
123 c.gmult=getsbits(bits)/65536.0;
124 c.bmult=getsbits(bits)/65536.0;
126 c.amult=getsbits(bits)/65536.0;
130 c.radd=getsbits(bits)/65536.0;
131 c.gadd=getsbits(bits)/65536.0;
132 c.badd=getsbits(bits)/65536.0;
134 c.aadd=getsbits(bits)/65536.0;
139 void CXFORM_write(struct CXFORM *obj, struct writer_t*w)
142 writer_writebit(w,obj->hasadd);
143 writer_writebit(w,obj->hasmult);
144 writer_writebits(w, bits, 4);
147 writer_writebits(w, obj->rmult, bits);
148 writer_writebits(w, obj->gmult, bits);
149 writer_writebits(w, obj->bmult, bits);
151 writer_writebits(w, obj->amult, 4);
155 writer_writebits(w, obj->radd, bits);
156 writer_writebits(w, obj->gadd, bits);
157 writer_writebits(w, obj->badd, bits);
159 writer_writebits(w, obj->aadd, 4);
163 unsigned char* readSTRING()
165 unsigned char*now = getinputpos();
174 void MATRIX_init(struct MATRIX*m)
185 struct MATRIX readMATRIX()
193 m.a[0][0] = m.a[1][1] = 1;
194 m.a[0][1] = m.a[1][0] = 0;
195 m.hasscale=readbit();
198 u8 scalebits=getbits(5);
199 s32 scalex=getsbits(scalebits);
200 s32 scaley=getsbits(scalebits);
201 m.a[0][0]=scalex/65536.0;
202 m.a[1][1]=scaley/65536.0;
204 m.hasrotate=readbit();
207 u8 rotbits=getbits(5);
208 s32 rotateskew0=getsbits(rotbits);
209 s32 rotateskew1=getsbits(rotbits);
210 m.a[0][1]=rotateskew0/65536.0;
211 m.a[1][0]=rotateskew1/65536.0;
214 translatebits=getbits(5);
215 translatex=getsbits(translatebits);
216 translatey=getsbits(translatebits);
223 void MATRIX_write(struct MATRIX * m , struct writer_t*w)
225 writer_writebit (w, m->hasscale);
229 writer_writebits(w, bits, 5);
230 writer_writebits(w, (u32)(m->a[0][0]*65536.0), bits);
231 writer_writebits(w, (u32)(m->a[1][1]*65536.0), bits);
233 writer_writebit (w, m->hasrotate);
237 writer_writebits(w, bits, 5);
238 writer_writebits(w, (u32)(m->a[0][1]*65536.0), bits);
239 writer_writebits(w, (u32)(m->a[1][0]*65536.0), bits);
245 writer_writebits(w, bits, 5);
246 writer_writebits(w, (u32)(m->b[0]), bits);
247 writer_writebits(w, (u32)(m->b[1]), bits);
252 int swf_read_tag(struct swf_tag* swftag)
254 u8*pos2,*pos = getinputpos();
262 taglength = tag & 0x3f;
263 if (taglength == 0x3f)
269 swftag->length = taglength;
270 swftag->data = getinputpos();
272 pos2 = getinputpos();
273 swftag->fulllength = pos2 - pos;
274 swftag->fulldata = pos;
280 u8*pos = getinputpos();
296 void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag)
298 reader_init (tag->data, tag->length);
299 obj -> id = readu16();
300 obj -> depth = readu16();
301 obj -> matrix = readMATRIX();
302 obj -> hascxform = (getinputpos() < &tag->data[tag->length]);
304 obj -> cxform = readCXFORM();
307 void placeobject_write (struct PlaceObject*obj, struct writer_t*w)
309 u16 taghead = 0x3f | TAGID_PLACEOBJECT<<6;
313 writer_write(w, &taghead, 2);
314 lenpos = writer_getpos(w);
316 writer_write(w, &taghead, 2);
317 writer_write(w, &taghead, 2);
319 pos = writer_getpos(w);
321 writer_write(w, &obj->id, 2);
322 writer_write(w, &obj->depth, 2);
323 MATRIX_write(&obj->matrix, w);
327 CXFORM_write(&obj->cxform, w);
331 *(u32*)lenpos = (u8*)writer_getpos(w) - pos;
334 void placeobject2_init (struct PlaceObject2*obj,struct swf_tag*tag)
337 reader_init (tag->data, tag->length);
339 obj->reserved= (b>>7)&1;
340 obj->hasclipactions= (b>>6)&1;
341 obj->hasname= (b>>5)&1;
342 obj->hasratio= (b>>4)&1;
343 obj->hascolortransform=(b>>3)&1;
344 obj->hasmatrix= (b>>2)&1;
345 obj->hascharacter= (b>>1)&1;
346 obj->hasmove= (b>>0)&1;
348 obj->depth = readu16();
350 if(obj->hascharacter) {
354 obj->matrix = readMATRIX();
356 if(obj->hascolortransform) {
357 obj->cxform = readCXFORM();
360 obj->ratio=readu16();
364 obj->name=readSTRING();
366 if(obj->hasclipactions) {
367 obj->clipactions=readu16();
371 void placeobject2_write (struct PlaceObject2*obj, struct writer_t*w)
373 u8 flags = obj->reserved<<7 | obj->hasclipactions<<6 | obj->hasname<<5 | obj->hasratio<<4 |
374 obj->hascolortransform<<3 | obj->hasmatrix<<2 | obj->hascharacter<<1 | obj->hasmove;
375 u16 taghead = 0x3f | TAGID_PLACEOBJECT2<<6;
379 writer_write(w, &taghead, 2);
380 lenpos = writer_getpos(w);
381 writer_write(w, &taghead, 2);
382 writer_write(w, &taghead, 2);
384 pos = writer_getpos(w);
386 writer_writeu8(w, flags);
387 writer_writeu16(w, obj->depth);
388 if(obj->hascharacter)
389 writer_writeu16(w, obj->id);
391 MATRIX_write(&obj->matrix, w);
392 if(obj->hascolortransform)
393 CXFORM_write(&obj->cxform, w);
395 writer_writeu16(w, obj->ratio);
398 writer_write(w, obj->name, strlen(obj->name) + 1);
399 if(obj->hasclipactions)
400 writer_writeu16(w, obj->clipactions);
402 *(u32*)lenpos = (u8*)writer_getpos(w) - pos;
405 void read_swf(struct swffile*swf, uchar*data, int length)
408 struct flash_header head;
410 swf_init(data, length);
411 head = swf_read_header(data);
412 logf("<debug> [HEADER] the version is %d", head.version);
413 logf("<debug> [HEADER] the length is %d", head.length);
414 logf("<debug> [HEADER] the boundingBox is %d:%d:%d:%d",
415 head.boundingBox.x1,head.boundingBox.y1,
416 head.boundingBox.x2,head.boundingBox.y2);
417 logf("<debug> [HEADER] the rate (frames/second) is %d", head.rate);
418 logf("<debug> [HEADER] the count (frame number) is %d", head.count);
420 tagnum = swf_count_tags();
421 swf->tags = (struct swf_tag*)malloc(sizeof(struct swf_tag)*tagnum);
423 logf("<debug> [HEADER] the file consists of %d tags", tagnum);
430 logf("<debug> read tag %02x (%d bytes)", tag.id, tag.length);
431 swf->tags[pos] = tag;
433 if(tag.id == TAGID_END)
436 swf->tagnum = tagnum;
440 int definingtagids[] =
444 TAGID_DEFINEMORPHSHAPE,
449 TAGID_DEFINEEDITTEXT,
451 TAGID_DEFINEBITSJPEG2,
452 TAGID_DEFINEBITSJPEG3,
453 TAGID_DEFINEBITSLOSSLESS,
454 TAGID_DEFINEBITSLOSSLESS2,
463 // tags which may be used inside a sprite definition
469 TAGID_REMOVEOBJECT2, //?
473 TAGID_SOUNDSTREAMHEAD,
474 TAGID_SOUNDSTREAMHEAD2,
475 TAGID_SOUNDSTREAMBLOCK,
480 int getidfromtag(struct swf_tag* tag)
482 // todo: check for more than one id
483 return *(u16*)tag->data;
486 void setidintag(struct swf_tag* tag, int id)
488 *(u16*)tag->data = id;
491 char is_sprite_tag (int id)
495 while(spritetagids[t]>=0)
497 if(spritetagids[t] == id)
504 char is_defining_tag (int id)
508 while(definingtagids[t]>=0)
510 if(definingtagids[t] == id)
517 struct swf_tag* duptag(struct swf_tag*tag)
519 struct swf_tag* newtag = (struct swf_tag*)malloc(sizeof(struct swf_tag));
520 newtag->id = tag->id;
521 newtag->fulldata = (u8*)malloc(tag->fulllength);
522 newtag->fulllength = tag->fulllength;
523 newtag->data = newtag->fulldata + (tag->data - tag->fulldata);
524 newtag->length = tag->length;
525 memcpy(newtag->fulldata, tag->fulldata, tag->fulllength);