3 Math and matrix functions, misc tools
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
10 This file is distributed under the GPL, see file COPYING for details
14 // Matrix & Math tools for SWF files
17 SFIXED RFXSWF_SP(SFIXED a1,SFIXED a2,SFIXED b1,SFIXED b2)
19 a = (S64)a1*(S64)b1+(S64)a2*(S64)b2;
20 return (SFIXED)(a>>16);
22 SFIXED RFXSWF_QFIX(int zaehler,int nenner) // bildet Quotient von zwei INTs in SFIXED
23 { S64 z = zaehler<<16;
24 S64 a = z/(S64)nenner;
29 MATRIX * swf_MatrixJoin(MATRIX * d,MATRIX * s1,MATRIX * s2)
32 if (!s1) return (s2)?(MATRIX *)memcpy(d,s2,sizeof(MATRIX)):NULL;
33 if (!s2) return (MATRIX *)memcpy(d,s1,sizeof(MATRIX));
35 d->tx = s1->tx + s2->tx;
36 d->ty = s1->ty + s2->ty;
38 d->sx = RFXSWF_SP(s1->sx,s1->r1,s2->sx,s2->r0);
39 d->sy = RFXSWF_SP(s1->r0,s1->sy,s2->r1,s2->sy);
40 d->r0 = RFXSWF_SP(s1->r0,s1->sy,s2->sx,s2->r0);
41 d->r1 = RFXSWF_SP(s1->sx,s1->r1,s2->r1,s2->sy);
48 MATRIX * swf_MatrixMapTriangle(MATRIX * m,int dx,int dy,int x0,int y0,
49 int x1,int y1,int x2,int y2)
56 if ((!dx)||(!dy)) return NULL; // check DIV by zero
60 m->sx = RFXSWF_QFIX(dx1,dx);
61 m->sy = RFXSWF_QFIX(dy2,dy);
62 m->r0 = RFXSWF_QFIX(dy1,dx);
63 m->r1 = RFXSWF_QFIX(dx2,dy);
68 void swf_SetDefineID(TAG * tag, U16 newid)
70 int oldlen = tag->len;
72 swf_SetU16(tag, newid); /* set defining ID */
76 U16 swf_GetDefineID(TAG * t)
81 oldTagPos = swf_GetTagPos(t);
84 switch (swf_GetTagID(t))
85 { case ST_DEFINESHAPE:
88 case ST_DEFINEMORPHSHAPE:
89 case ST_DEFINEEDITTEXT:
91 case ST_DEFINEBITSJPEG2:
92 case ST_DEFINEBITSJPEG3:
93 case ST_DEFINEBITSLOSSLESS:
94 case ST_DEFINEBITSLOSSLESS2:
96 case ST_DEFINEBUTTON2:
97 case ST_DEFINEBUTTONCXFORM: //pseudodefine
98 case ST_DEFINEBUTTONSOUND: //pseudodefine
101 case ST_DEFINEFONTINFO: //pseudodefine
105 case ST_DEFINESPRITE:
106 case ST_NAMECHARACTER: //pseudodefine
111 swf_SetTagPos(t,oldTagPos);
116 U16 swf_GetPlaceID(TAG * t)
121 oldTagPos = swf_GetTagPos(t);
124 switch (swf_GetTagID(t))
125 { case ST_PLACEOBJECT:
126 case ST_REMOVEOBJECT:
131 case ST_PLACEOBJECT2:
132 { U8 flags = swf_GetU8(t);
133 U16 d = swf_GetU16(t);
134 id = (flags&PF_CHAR)?swf_GetU16(t):id;
139 swf_SetTagPos(t,oldTagPos);
144 static int swf_definingtagids[] =
157 ST_DEFINEBITSLOSSLESS,
158 ST_DEFINEBITSLOSSLESS2,
167 // tags which may be used inside a sprite definition
168 static int swf_spritetagids[] =
173 ST_REMOVEOBJECT2, //?
184 static int swf_pseudodefiningtagids[] =
187 ST_DEFINEBUTTONCXFORM,
188 ST_DEFINEBUTTONSOUND,
193 U8 swf_isAllowedSpriteTag(TAG * tag)
197 while(swf_spritetagids[t]>=0)
199 if(swf_spritetagids[t] == id)
206 U8 swf_isDefiningTag(TAG * tag)
210 while(swf_definingtagids[t]>=0)
212 if(swf_definingtagids[t] == id)
219 U8 swf_isPseudoDefiningTag(TAG * tag)
223 while(swf_pseudodefiningtagids[t]>=0)
225 if(swf_pseudodefiningtagids[t] == id)
232 U16 swf_GetDepth(TAG * t)
237 oldTagPos = swf_GetTagPos(t);
240 switch (swf_GetTagID(t))
241 { case ST_PLACEOBJECT:
242 case ST_REMOVEOBJECT:
244 depth = swf_GetU16(t);
246 case ST_REMOVEOBJECT2:
247 depth = swf_GetU16(t);
249 case ST_PLACEOBJECT2:
250 { U8 flags = swf_GetU8(t);
251 depth = swf_GetU16(t);
254 swf_SetTagPos(t,oldTagPos);
258 char* swf_GetName(TAG * t)
264 oldTagPos = swf_GetTagPos(t);
266 switch(swf_GetTagID(t))
269 name = &t->data[swf_GetTagPos(t)];
271 case ST_PLACEOBJECT2: {
272 U8 flags = swf_GetU8(t);
273 swf_GetU16(t); //depth;
277 swf_GetMatrix(t, &m);
279 swf_GetCXForm(t, &c, 1);
283 swf_ResetReadBits(t);
284 name = &t->data[swf_GetTagPos(t)];
289 swf_SetTagPos(t,oldTagPos);
293 static void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void*callback_data, int num)
297 count = swf_GetU8(tag);
298 if(count == 0xff && num>1) // defineshape2,3 only
299 count = swf_GetU16(tag);
305 swf_ResetReadBits(tag);
306 type = swf_GetU8(tag); //type
309 swf_GetRGBA(tag, NULL);
311 swf_GetRGB(tag, NULL);
313 else if(type == 0x10 || type == 0x12)
315 swf_ResetReadBits(tag);
316 swf_GetMatrix(tag, NULL);
317 swf_ResetReadBits(tag);
318 swf_GetGradient(tag, NULL, /*alpha*/ num>=3?1:0);
320 else if(type == 0x40 || type == 0x41)
322 swf_ResetReadBits(tag);
324 if(tag->data[tag->pos] != 0xff ||
325 tag->data[tag->pos+1] != 0xff)
326 (callback)(tag, tag->pos, callback_data);
329 swf_ResetReadBits(tag);
330 swf_GetMatrix(tag, NULL);
333 fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x\n",type);
336 swf_ResetReadBits(tag);
337 count = swf_GetU8(tag); // line style array
339 count = swf_GetU16(tag);
344 swf_GetRGBA(tag, NULL);
346 swf_GetRGB(tag, NULL);
350 void enumerateUsedIDs(TAG * tag, int base, void (*callback)(TAG*, int, void*), void*callback_data)
353 swf_ResetReadBits(tag);
357 case ST_DEFINEBUTTONCXFORM: {
359 callback(tag, tag->pos + base, callback_data);
362 callback(tag, tag->pos + base, callback_data);
363 swf_GetU16(tag); //sound id
364 flags = swf_GetU8(tag);
366 swf_GetU32(tag); // in point
368 swf_GetU32(tag); // out points
370 swf_GetU16(tag); // loop count
373 int npoints = swf_GetU8(tag);
375 for(s=0;s<npoints;s++)
384 case ST_DEFINEBUTTONSOUND:
385 callback(tag, tag->pos + base, callback_data); //button id
388 callback(tag, tag->pos + base, callback_data);
390 case ST_PLACEOBJECT2:
391 // only if placeflaghascharacter
392 if(!(tag->data[0]&2))
394 callback(tag, 3 + base, callback_data);
396 case ST_REMOVEOBJECT:
397 callback(tag, tag->pos + base, callback_data);
400 callback(tag, tag->pos + base, callback_data);
402 case ST_DEFINESPRITE: {
404 break; // sprite is expanded
406 swf_GetU16(tag); // id
407 swf_GetU16(tag); // framenum
410 U16 flags = swf_GetU16(tag);
413 TAG *tag2 = swf_InsertTag(NULL, id);
416 len = swf_GetU32(tag);
419 tag2->len = tag2->memsize = len;
420 tag2->data = malloc(len);
421 memcpy(tag2->data, &tag->data[tag->pos], len);
422 /* I never saw recursive sprites, but they are (theoretically)
423 possible, so better add base here again */
424 enumerateUsedIDs(tag2, tag->pos + base, callback, callback_data);
426 swf_GetBlock(tag, NULL, len);
430 case ST_DEFINEBUTTON2: // has some font ids in the button records
433 case ST_DEFINEBUTTON: {
434 swf_GetU16(tag); //button id
438 swf_GetU8(tag); //flag
439 offset = swf_GetU16(tag); //offset
444 if(!swf_GetU8(tag)) //flags
446 callback(tag, tag->pos + base, callback_data);
447 swf_GetU16(tag); //char
448 swf_GetU16(tag); //layer
449 swf_ResetReadBits(tag);
450 swf_GetMatrix(tag, NULL);
452 swf_ResetReadBits(tag);
453 swf_GetCXForm(tag, NULL, 1);
459 case ST_DEFINEEDITTEXT: {
461 swf_GetU16(tag); //id
462 swf_GetRect(tag, NULL); //bounding box
463 swf_ResetReadBits(tag);
464 flags1 = swf_GetU8(tag);
465 flags2 = swf_GetU8(tag);
467 callback(tag, tag->pos + base, callback_data);
472 case ST_DEFINETEXT: {
473 int glyphbits, advancebits;
475 id = swf_GetU16(tag); //id
476 swf_GetRect(tag, NULL); //bounding box
477 swf_ResetReadBits(tag);
478 swf_GetMatrix(tag, NULL); //matrix
479 swf_ResetReadBits(tag);
480 glyphbits = swf_GetU8(tag); //glyphbits
481 advancebits = swf_GetU8(tag); //advancebits
484 swf_ResetReadBits(tag);
485 flags = swf_GetBits(tag, 8);
487 if(flags & 128) // text style record
489 swf_ResetReadBits(tag);
490 if(flags & 8) { // hasfont
491 callback(tag, tag->pos + base, callback_data);
492 id = swf_GetU16(tag);
494 if(flags & 4) { // hascolor
495 if(num==1) swf_GetRGB(tag, NULL);
496 else swf_GetRGBA(tag, NULL);
498 if(flags & 2) { //has x offset
499 swf_ResetReadBits(tag);
502 if(flags & 1) { //has y offset
503 swf_ResetReadBits(tag);
506 if(flags & 8) { //has height
507 swf_ResetReadBits(tag);
510 } else { // glyph record
512 swf_ResetReadBits(tag);
513 for(t=0;t<flags;t++) {
514 swf_GetBits(tag, glyphbits);
515 swf_GetBits(tag, advancebits);
521 case ST_DEFINEFONTINFO:
522 callback(tag, tag->pos + base, callback_data);
525 case ST_DEFINESHAPE3: // these thingies might have bitmap ids in their fillstyles
527 case ST_DEFINESHAPE2:
529 case ST_DEFINESHAPE: {
533 id = swf_GetU16(tag); // id;
534 swf_GetRect(tag, NULL); // bounds
536 enumerateUsedIDs_styles(tag, callback, callback_data, num);
537 fillbits = swf_GetBits(tag, 4);
538 linebits = swf_GetBits(tag, 4);
539 swf_ResetReadBits(tag);
542 flags = swf_GetBits(tag, 1);
543 if(!flags) { //style change
544 flags = swf_GetBits(tag, 5);
548 int n = swf_GetBits(tag, 5);
549 swf_GetBits(tag, n); //x
550 swf_GetBits(tag, n); //y
552 if(flags&2) { //fill0
553 swf_GetBits(tag, fillbits);
555 if(flags&4) { //fill1
556 swf_GetBits(tag, fillbits);
558 if(flags&8) { //linestyle
559 swf_GetBits(tag, linebits);
562 enumerateUsedIDs_styles(tag, callback, callback_data, num);
563 fillbits = swf_GetBits(tag, 4);
564 linebits = swf_GetBits(tag, 4);
567 flags = swf_GetBits(tag, 1);
568 if(flags) { //straight edge
569 int n = swf_GetBits(tag, 4) + 2;
570 if(swf_GetBits(tag, 1)) { //line flag
571 swf_GetBits(tag, n); //delta x
572 swf_GetBits(tag, n); //delta y
574 int v=swf_GetBits(tag, 1);
575 swf_GetBits(tag, n); //vert/horz
577 } else { //curved edge
578 int n = swf_GetBits(tag, 4) + 2;
593 void callbackCount(TAG * t,int pos, void*ptr)
598 void callbackFillin(TAG * t,int pos, void*ptr)
604 int swf_GetNumUsedIDs(TAG * t)
607 enumerateUsedIDs(t, 0, callbackCount, &num);
611 void swf_GetUsedIDs(TAG * t, int * positions)
613 int * ptr = positions;
614 enumerateUsedIDs(t, 0, callbackFillin, &ptr);
617 void swf_Relocate (SWF*swf, char*bitmap)
621 memset(slaveids, -1, sizeof(slaveids));
629 if(swf_isDefiningTag(tag))
634 id = swf_GetDefineID(tag); //own id
636 if(!bitmap[id]) { //free
641 for (t=1;t<65536;t++)
651 slaveids[id] = newid;
653 swf_SetDefineID(tag, newid);
656 num = swf_GetNumUsedIDs(tag);
657 ptr = malloc(sizeof(int)*num);
658 swf_GetUsedIDs(tag, ptr);
661 int id = GET16(&tag->data[ptr[t]]);
663 fprintf(stderr, "swf_Relocate: Mapping id never encountered before: %d\n", id);
667 PUT16(&tag->data[ptr[t]], id);