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;
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);
69 struct RGBA readRGBA()
79 struct GRADIENT readGRADIENT(int shape)
81 struct GRADIENT gradient;
83 gradient.num = readu8();
84 for(t=0;t<gradient.num;t++)
86 gradient.ratios[t] = readu8();
88 gradient.rgb[t] = readRGB();
90 gradient.rgba[t] = readRGBA();
94 struct RECT readRECT()
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()
137 c.rmult=getsbits(bits)/65536.0;
138 c.gmult=getsbits(bits)/65536.0;
139 c.bmult=getsbits(bits)/65536.0;
141 c.amult=getsbits(bits)/65536.0;
145 c.radd=getsbits(bits)/65536.0;
146 c.gadd=getsbits(bits)/65536.0;
147 c.badd=getsbits(bits)/65536.0;
149 c.aadd=getsbits(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()
180 unsigned char*now = getinputpos();
189 void MATRIX_init(struct MATRIX*m)
200 struct MATRIX readMATRIX()
208 m.a[0][0] = m.a[1][1] = 1;
209 m.a[0][1] = m.a[1][0] = 0;
210 m.hasscale=readbit();
213 u8 scalebits=getbits(5);
214 s32 scalex=getsbits(scalebits);
215 s32 scaley=getsbits(scalebits);
216 m.a[0][0]=scalex/65536.0;
217 m.a[1][1]=scaley/65536.0;
219 m.hasrotate=readbit();
222 u8 rotbits=getbits(5);
223 s32 rotateskew0=getsbits(rotbits);
224 s32 rotateskew1=getsbits(rotbits);
225 m.a[0][1]=rotateskew0/65536.0;
226 m.a[1][0]=rotateskew1/65536.0;
229 translatebits=getbits(5);
230 translatex=getsbits(translatebits);
231 translatey=getsbits(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 swf_tag* swftag)
269 u8*pos2,*pos = getinputpos();
277 taglength = tag & 0x3f;
278 if (taglength == 0x3f)
284 swftag->length = taglength;
285 swftag->data = getinputpos();
287 pos2 = getinputpos();
288 swftag->fulllength = pos2 - pos;
289 swftag->fulldata = pos;
295 u8*pos = getinputpos();
311 void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag)
313 reader_init (tag->data, tag->length);
314 obj -> id = readu16();
315 obj -> depth = readu16();
316 obj -> matrix = readMATRIX();
317 obj -> hascxform = (getinputpos() < &tag->data[tag->length]);
319 obj -> cxform = readCXFORM();
322 void placeobject_write (struct PlaceObject*obj, struct writer_t*w)
324 u16 taghead = 0x3f | TAGID_PLACEOBJECT<<6;
328 writer_write(w, &taghead, 2);
329 lenpos = writer_getpos(w);
331 writer_write(w, &taghead, 2);
332 writer_write(w, &taghead, 2);
334 pos = writer_getpos(w);
336 writer_write(w, &obj->id, 2);
337 writer_write(w, &obj->depth, 2);
338 MATRIX_write(&obj->matrix, w);
342 CXFORM_write(&obj->cxform, w);
346 *(u32*)lenpos = (u8*)writer_getpos(w) - pos;
349 void placeobject2_init (struct PlaceObject2*obj,struct swf_tag*tag)
352 reader_init (tag->data, tag->length);
354 obj->reserved= (b>>7)&1;
355 obj->hasclipactions= (b>>6)&1;
356 obj->hasname= (b>>5)&1;
357 obj->hasratio= (b>>4)&1;
358 obj->hascolortransform=(b>>3)&1;
359 obj->hasmatrix= (b>>2)&1;
360 obj->hascharacter= (b>>1)&1;
361 obj->hasmove= (b>>0)&1;
363 obj->depth = readu16();
365 if(obj->hascharacter) {
369 obj->matrix = readMATRIX();
371 if(obj->hascolortransform) {
372 obj->cxform = readCXFORM();
375 obj->ratio=readu16();
379 obj->name=readSTRING();
381 if(obj->hasclipactions) {
382 obj->clipactions=readu16();
386 void placeobject2_write (struct PlaceObject2*obj, struct writer_t*w)
388 u8 flags = obj->reserved<<7 | obj->hasclipactions<<6 | obj->hasname<<5 | obj->hasratio<<4 |
389 obj->hascolortransform<<3 | obj->hasmatrix<<2 | obj->hascharacter<<1 | obj->hasmove;
390 u16 taghead = 0x3f | TAGID_PLACEOBJECT2<<6;
394 writer_write(w, &taghead, 2);
395 lenpos = writer_getpos(w);
396 writer_write(w, &taghead, 2);
397 writer_write(w, &taghead, 2);
399 pos = writer_getpos(w);
401 writer_writeu8(w, flags);
402 writer_writeu16(w, obj->depth);
403 if(obj->hascharacter)
404 writer_writeu16(w, obj->id);
406 MATRIX_write(&obj->matrix, w);
407 if(obj->hascolortransform)
408 CXFORM_write(&obj->cxform, w);
410 writer_writeu16(w, obj->ratio);
413 writer_write(w, obj->name, strlen(obj->name) + 1);
414 if(obj->hasclipactions)
415 writer_writeu16(w, obj->clipactions);
417 *(u32*)lenpos = (u8*)writer_getpos(w) - pos;
420 void read_swf(struct swffile*swf, uchar*data, int length)
423 struct flash_header head;
425 swf_init(data, length);
426 head = swf_read_header(data);
427 logf("<debug> [HEADER] the version is %d", head.version);
428 logf("<debug> [HEADER] the length is %d", head.length);
429 logf("<debug> [HEADER] the boundingBox is %d:%d:%d:%d",
430 head.boundingBox.x1,head.boundingBox.y1,
431 head.boundingBox.x2,head.boundingBox.y2);
432 logf("<debug> [HEADER] the rate (frames/second) is %d", head.rate);
433 logf("<debug> [HEADER] the count (frame number) is %d", head.count);
435 tagnum = swf_count_tags();
436 swf->tags = (struct swf_tag*)malloc(sizeof(struct swf_tag)*tagnum);
438 logf("<debug> [HEADER] the file consists of %d tags", tagnum);
445 logf("<debug> read tag %02x (%d bytes)", tag.id, tag.length);
446 swf->tags[pos] = tag;
448 if(tag.id == TAGID_END)
451 swf->tagnum = tagnum;
455 int definingtagids[] =
459 TAGID_DEFINEMORPHSHAPE,
464 TAGID_DEFINEEDITTEXT,
466 TAGID_DEFINEBITSJPEG2,
467 TAGID_DEFINEBITSJPEG3,
468 TAGID_DEFINEBITSLOSSLESS,
469 TAGID_DEFINEBITSLOSSLESS2,
478 // tags which may be used inside a sprite definition
484 TAGID_REMOVEOBJECT2, //?
488 TAGID_SOUNDSTREAMHEAD,
489 TAGID_SOUNDSTREAMHEAD2,
490 TAGID_SOUNDSTREAMBLOCK,
495 int getidfromtag(struct swf_tag* tag)
497 // todo: check for more than one id
498 return *(u16*)tag->data;
501 void setidintag(struct swf_tag* tag, int id)
503 *(u16*)tag->data = id;
506 char is_sprite_tag (int id)
510 while(spritetagids[t]>=0)
512 if(spritetagids[t] == id)
519 char is_defining_tag (int id)
523 while(definingtagids[t]>=0)
525 if(definingtagids[t] == id)
532 struct swf_tag* duptag(struct swf_tag*tag)
534 struct swf_tag* newtag = (struct swf_tag*)malloc(sizeof(struct swf_tag));
535 newtag->id = tag->id;
536 newtag->fulldata = (u8*)malloc(tag->fulllength);
537 newtag->fulllength = tag->fulllength;
538 newtag->data = newtag->fulldata + (tag->data - tag->fulldata);
539 newtag->length = tag->length;
540 memcpy(newtag->fulldata, tag->fulldata, tag->fulllength);