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(struct reader_t*r, uchar*newdata, int newlength)
15 reader_init (r, &newdata[3], newlength - 3);
18 struct flash_header swf_read_header(struct reader_t*r)
20 struct flash_header head;
25 u8* oldpos = reader_getinputpos(r);
27 reader_input1(r,&version);
28 head.version = version;
29 reader_input4(r,&length);
33 head.boundingBox = readRECT(r);
34 reader_input2(r,&rate);
36 reader_input2(r,&count);
39 head.headerlength = reader_getinputpos(r) - oldpos;
40 head.headerdata = oldpos;
45 void swf_write_header(struct writer_t*w, struct flash_header*head)
47 writer_writeu8(w, head->version);
48 writer_writeu32(w, head->length);
50 writer_writebits(w, 31, 5);
51 writer_writebits(w, head->boundingBox.x1, 31);
52 writer_writebits(w, head->boundingBox.x2, 31);
53 writer_writebits(w, head->boundingBox.y1, 31);
54 writer_writebits(w, head->boundingBox.y2, 31);
56 writer_writeu16(w, head->rate);
57 writer_writeu16(w, head->count);
60 struct RGB readRGB(struct reader_t*r)
63 reader_input1(r,&rgb.r);
64 reader_input1(r,&rgb.g);
65 reader_input1(r,&rgb.b);
69 struct RGBA readRGBA(struct reader_t*r)
72 reader_input1(r,&rgba.r);
73 reader_input1(r,&rgba.g);
74 reader_input1(r,&rgba.b);
75 reader_input1(r,&rgba.a);
79 struct GRADIENT readGRADIENT(struct reader_t*r, int shape)
81 struct GRADIENT gradient;
83 gradient.num = reader_readu8(r);
84 for(t=0;t<gradient.num;t++)
86 gradient.ratios[t] = reader_readu8(r);
88 gradient.rgb[t] = readRGB(r);
90 gradient.rgba[t] = readRGBA(r);
94 struct RECT readRECT(struct reader_t*reader)
99 reader_readbits(reader,&a,5);
100 reader_readsbits(reader,&b,a);
102 reader_readsbits(reader,&b,a);
104 reader_readsbits(reader,&b,a);
106 reader_readsbits(reader,&b,a);
112 void writeRECT(u8**pos, struct RECT*r)
116 writer_init(&w, *pos, 256);
117 writer_writebits(&w, 31, 5); //FIXME:count
118 writer_writebits(&w, r->x1, 31);
119 writer_writebits(&w, r->x2, 31);
120 writer_writebits(&w, r->y1, 31);
121 writer_writebits(&w, r->y2, 31);
122 writer_resetbits(&w);
123 *pos = writer_getpos(&w);
126 struct CXFORM readCXFORM(struct reader_t*r, char alpha)
130 c.hasadd=reader_readbit(r);
131 c.hasmult=reader_readbit(r);
132 bits=reader_getbits(r,4);
137 c.rmult=reader_getsbits(r,bits)/65536.0;
138 c.gmult=reader_getsbits(r,bits)/65536.0;
139 c.bmult=reader_getsbits(r,bits)/65536.0;
141 c.amult=reader_getsbits(r,bits)/65536.0;
145 c.radd=reader_getsbits(r,bits)/65536.0;
146 c.gadd=reader_getsbits(r,bits)/65536.0;
147 c.badd=reader_getsbits(r,bits)/65536.0;
149 c.aadd=reader_getsbits(r,bits)/65536.0;
154 void CXFORM_write(struct CXFORM *obj, struct writer_t*w)
157 writer_writebit(w,obj->hasadd);
158 writer_writebit(w,obj->hasmult);
159 writer_writebits(w, bits, 4);
162 writer_writebits(w, obj->rmult, bits);
163 writer_writebits(w, obj->gmult, bits);
164 writer_writebits(w, obj->bmult, bits);
166 writer_writebits(w, obj->amult, 4);
170 writer_writebits(w, obj->radd, bits);
171 writer_writebits(w, obj->gadd, bits);
172 writer_writebits(w, obj->badd, bits);
174 writer_writebits(w, obj->aadd, 4);
178 unsigned char* readSTRING(struct reader_t*r)
180 unsigned char*now = reader_getinputpos(r);
189 void MATRIX_init(struct MATRIX*m)
200 struct MATRIX readMATRIX(struct reader_t*r)
208 m.a[0][0] = m.a[1][1] = 1;
209 m.a[0][1] = m.a[1][0] = 0;
210 m.hasscale=reader_readbit(r);
213 u8 scalebits=reader_getbits(r,5);
214 s32 scalex=reader_getsbits(r,scalebits);
215 s32 scaley=reader_getsbits(r,scalebits);
216 m.a[0][0]=scalex/65536.0;
217 m.a[1][1]=scaley/65536.0;
219 m.hasrotate=reader_readbit(r);
222 u8 rotbits=reader_getbits(r,5);
223 s32 rotateskew0=reader_getsbits(r,rotbits);
224 s32 rotateskew1=reader_getsbits(r,rotbits);
225 m.a[0][1]=rotateskew0/65536.0;
226 m.a[1][0]=rotateskew1/65536.0;
229 translatebits=reader_getbits(r,5);
230 translatex=reader_getsbits(r,translatebits);
231 translatey=reader_getsbits(r,translatebits);
238 void MATRIX_write(struct MATRIX * m , struct writer_t*w)
240 writer_writebit (w, m->hasscale);
244 writer_writebits(w, bits, 5);
245 writer_writebits(w, (u32)(m->a[0][0]*65536.0), bits);
246 writer_writebits(w, (u32)(m->a[1][1]*65536.0), bits);
248 writer_writebit (w, m->hasrotate);
252 writer_writebits(w, bits, 5);
253 writer_writebits(w, (u32)(m->a[0][1]*65536.0), bits);
254 writer_writebits(w, (u32)(m->a[1][0]*65536.0), bits);
260 writer_writebits(w, bits, 5);
261 writer_writebits(w, (u32)(m->b[0]), bits);
262 writer_writebits(w, (u32)(m->b[1]), bits);
267 int swf_read_tag(struct reader_t*r, struct swf_tag* swftag)
269 u8*pos2,*pos = reader_getinputpos(r);
275 reader_input2(r, &tag);
277 taglength = tag & 0x3f;
278 if (taglength == 0x3f)
280 reader_input4(r, &taglength);
284 swftag->length = taglength;
285 swftag->data = reader_getinputpos(r);
286 reader_skip(r,taglength);
287 pos2 = reader_getinputpos(r);
288 swftag->fulllength = pos2 - pos;
289 swftag->fulldata = pos;
293 int swf_count_tags(struct reader_t*r)
295 u8*pos = reader_getinputpos(r);
301 swf_read_tag(r,&tag);
307 reader_setinputpos(r,pos);
311 void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag)
314 reader_init (&r, tag->data, tag->length);
315 obj -> id = reader_readu16(&r);
316 obj -> depth = reader_readu16(&r);
317 obj -> matrix = readMATRIX(&r);
318 obj -> hascxform = (reader_getinputpos(&r) < &tag->data[tag->length]);
320 obj -> cxform = readCXFORM(&r, 0);
323 void placeobject_write (struct PlaceObject*obj, struct writer_t*w)
325 u16 taghead = 0x3f | TAGID_PLACEOBJECT<<6;
330 writer_write(w, &taghead, 2);
331 lenpos = writer_getpos(w);
333 writer_write(w, &taghead, 2);
334 writer_write(w, &taghead, 2);
336 pos = writer_getpos(w);
338 writer_write(w, &obj->id, 2);
339 writer_write(w, &obj->depth, 2);
340 MATRIX_write(&obj->matrix, w);
344 CXFORM_write(&obj->cxform, w);
348 len = (u8*)writer_getpos(w) - pos;
355 void placeobject2_init (struct PlaceObject2*obj,struct swf_tag*tag)
359 reader_init (&r, tag->data, tag->length);
361 obj->reserved= (b>>7)&1;
362 obj->hasclipactions= (b>>6)&1;
363 obj->hasname= (b>>5)&1;
364 obj->hasratio= (b>>4)&1;
365 obj->hascolortransform=(b>>3)&1;
366 obj->hasmatrix= (b>>2)&1;
367 obj->hascharacter= (b>>1)&1;
368 obj->hasmove= (b>>0)&1;
370 obj->depth = reader_readu16(&r);
372 if(obj->hascharacter) {
373 obj->id = reader_readu16(&r);
376 obj->matrix = readMATRIX(&r);
378 if(obj->hascolortransform) {
379 obj->cxform = readCXFORM(&r,0);
382 obj->ratio=reader_readu16(&r);
386 obj->name=readSTRING(&r);
388 if(obj->hasclipactions) {
389 obj->clipactions=reader_readu16(&r);
393 void placeobject2_write (struct PlaceObject2*obj, struct writer_t*w)
395 u8 flags = obj->reserved<<7 | obj->hasclipactions<<6 | obj->hasname<<5 | obj->hasratio<<4 |
396 obj->hascolortransform<<3 | obj->hasmatrix<<2 | obj->hascharacter<<1 | obj->hasmove;
397 u16 taghead = SWAP16(0x3f | TAGID_PLACEOBJECT2<<6);
402 writer_write(w, &taghead, 2);
403 lenpos = writer_getpos(w);
404 writer_write(w, &taghead, 2);
405 writer_write(w, &taghead, 2);
407 pos = writer_getpos(w);
409 writer_writeu8(w, flags);
410 writer_writeu16(w, obj->depth);
411 if(obj->hascharacter)
412 writer_writeu16(w, obj->id);
414 MATRIX_write(&obj->matrix, w);
415 if(obj->hascolortransform)
416 CXFORM_write(&obj->cxform, w);
418 writer_writeu16(w, obj->ratio);
421 writer_write(w, obj->name, strlen(obj->name) + 1);
422 if(obj->hasclipactions)
423 writer_writeu16(w, obj->clipactions);
426 len = (u8*)writer_getpos(w) - pos;
433 void read_swf(struct swffile*swf, uchar*data, int length)
436 struct flash_header head;
439 swf_init(&r, data, length);
440 head = swf_read_header(&r);
441 logf("<debug> [HEADER] the version is %d", head.version);
442 logf("<debug> [HEADER] the length is %d", head.length);
443 logf("<debug> [HEADER] the boundingBox is %d:%d:%d:%d",
444 head.boundingBox.x1,head.boundingBox.y1,
445 head.boundingBox.x2,head.boundingBox.y2);
446 logf("<debug> [HEADER] the rate (frames/second) is %d", head.rate);
447 logf("<debug> [HEADER] the count (frame number) is %d", head.count);
449 tagnum = swf_count_tags(&r);
450 swf->tags = (struct swf_tag*)malloc(sizeof(struct swf_tag)*tagnum);
452 logf("<debug> [HEADER] the file consists of %d tags", tagnum);
458 swf_read_tag(&r, &tag);
459 logf("<debug> read tag %02x (%d bytes)", tag.id, tag.length);
460 swf->tags[pos] = tag;
462 if(tag.id == TAGID_END)
465 swf->tagnum = tagnum;
469 int definingtagids[] =
473 TAGID_DEFINEMORPHSHAPE,
478 TAGID_DEFINEEDITTEXT,
480 TAGID_DEFINEBITSJPEG2,
481 TAGID_DEFINEBITSJPEG3,
482 TAGID_DEFINEBITSLOSSLESS,
483 TAGID_DEFINEBITSLOSSLESS2,
492 // tags which may be used inside a sprite definition
498 TAGID_REMOVEOBJECT2, //?
502 TAGID_SOUNDSTREAMHEAD,
503 TAGID_SOUNDSTREAMHEAD2,
504 TAGID_SOUNDSTREAMBLOCK,
509 int getidfromtag(struct swf_tag* tag)
513 case TAGID_PLACEOBJECT2:
515 case TAGID_PLACEOBJECT: {
517 reader_init (&r, tag->data, tag->length);
519 char b = reader_readu8(&r);
524 return reader_readu16(&r);
527 case TAGID_REMOVEOBJECT:
528 return tag->data[0]+tag->data[1]*256;
530 case TAGID_REMOVEOBJECT2:
535 return tag->data[0]+tag->data[1]*256;
538 void setidintag(struct swf_tag* tag, int id)
541 tag->data[1] = id>>8;
544 char is_sprite_tag (int id)
547 while(spritetagids[t]>=0)
549 if(spritetagids[t] == id)
556 char is_defining_tag (int id)
559 while(definingtagids[t]>=0)
561 if(definingtagids[t] == id)
568 struct swf_tag* duptag(struct swf_tag*tag)
570 struct swf_tag* newtag = (struct swf_tag*)malloc(sizeof(struct swf_tag));
571 newtag->id = tag->id;
572 newtag->fulldata = (u8*)malloc(tag->fulllength);
573 newtag->fulllength = tag->fulllength;
574 newtag->data = newtag->fulldata + (tag->data - tag->fulldata);
575 newtag->length = tag->length;
576 memcpy(newtag->fulldata, tag->fulldata, tag->fulllength);