initial revision
[swftools.git] / lib / modules / swftools.c
1 /* swftools.c
2
3    Math and matrix functions, misc tools
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
9  
10    This file is distributed under the GPL, see file COPYING for details 
11
12 */
13
14 // Matrix & Math tools for SWF files
15
16 #define S64 long long
17 SFIXED RFXSWF_SP(SFIXED a1,SFIXED a2,SFIXED b1,SFIXED b2)
18 { S64 a;
19   a = (S64)a1*(S64)b1+(S64)a2*(S64)b2;
20   return (SFIXED)(a>>16);
21 }
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;
25   return (SFIXED)a;
26 }
27 #undef S64
28
29 MATRIX * swf_MatrixJoin(MATRIX * d,MATRIX * s1,MATRIX * s2)
30 {        
31   if (!d) return NULL;
32   if (!s1) return (s2)?(MATRIX *)memcpy(d,s2,sizeof(MATRIX)):NULL;
33   if (!s2) return (MATRIX *)memcpy(d,s1,sizeof(MATRIX));
34   
35   d->tx = s1->tx + s2->tx;
36   d->ty = s1->ty + s2->ty;
37   
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);
42
43   //DumpMatrix(NULL,d);
44   
45   return d;
46 }
47
48 MATRIX * swf_MatrixMapTriangle(MATRIX * m,int dx,int dy,int x0,int y0,
49                                int x1,int y1,int x2,int y2)
50 { int dx1 = x1 - x0;
51   int dy1 = y1 - y0;
52   int dx2 = x2 - x0;
53   int dy2 = y2 - y0;
54   
55   if (!m) return NULL;
56   if ((!dx)||(!dy)) return NULL; // check DIV by zero
57
58   m->tx = x0;
59   m->ty = y0;
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);
64   
65   return m;
66 }
67
68 U16 swf_GetDefineID(TAG * t)
69 // up to SWF 4.0
70 { U32 oldTagPos;
71   U16 id = 0;
72
73   oldTagPos = swf_GetTagPos(t);
74   swf_SetTagPos(t,0);
75
76   switch (swf_GetTagID(t))
77   { case ST_DEFINESHAPE:
78     case ST_DEFINESHAPE2:
79     case ST_DEFINESHAPE3:
80     case ST_DEFINEMORPHSHAPE:
81     case ST_DEFINEEDITTEXT:
82     case ST_DEFINEBITS:
83     case ST_DEFINEBITSJPEG2:
84     case ST_DEFINEBITSJPEG3:
85     case ST_DEFINEBITSLOSSLESS:
86     case ST_DEFINEBITSLOSSLESS2:
87     case ST_DEFINEBUTTON:
88     case ST_DEFINEBUTTON2:
89     case ST_DEFINEBUTTONCXFORM: //pseudodefine
90     case ST_DEFINEBUTTONSOUND: //pseudodefine
91     case ST_DEFINEFONT:
92     case ST_DEFINEFONT2:
93     case ST_DEFINEFONTINFO: //pseudodefine
94     case ST_DEFINETEXT:
95     case ST_DEFINETEXT2:
96     case ST_DEFINESOUND:
97     case ST_DEFINESPRITE:
98     case ST_NAMECHARACTER: //pseudodefine
99       id = swf_GetU16(t);
100       break;
101   }
102
103   swf_SetTagPos(t,oldTagPos);
104
105   return id;
106 }
107
108 U16 swf_GetPlaceID(TAG * t)
109 // up to SWF 4.0
110 { U32 oldTagPos;
111   U16 id = 0;
112
113   oldTagPos = swf_GetTagPos(t);
114   swf_SetTagPos(t,0);
115
116   switch (swf_GetTagID(t))
117   { case ST_PLACEOBJECT:
118     case ST_REMOVEOBJECT:
119     case ST_STARTSOUND:
120       id = swf_GetU16(t);
121       break;
122
123     case ST_PLACEOBJECT2:
124     { U8 flags = swf_GetU8(t);
125       U16 d = swf_GetU16(t);
126       id = (flags&PF_CHAR)?swf_GetU16(t):id;
127     } break;
128
129   }
130
131   swf_SetTagPos(t,oldTagPos);
132
133   return id;
134 }
135
136 static int swf_definingtagids[] =
137 {ST_DEFINESHAPE,
138  ST_DEFINESHAPE2,
139  ST_DEFINESHAPE3,
140  ST_DEFINEMORPHSHAPE,
141  ST_DEFINEFONT,
142  ST_DEFINEFONT2,
143  ST_DEFINETEXT,
144  ST_DEFINETEXT2,
145  ST_DEFINEEDITTEXT,
146  ST_DEFINEBITS,
147  ST_DEFINEBITSJPEG2,
148  ST_DEFINEBITSJPEG3,
149  ST_DEFINEBITSLOSSLESS,
150  ST_DEFINEBITSLOSSLESS2,
151  ST_DEFINEMOVIE,
152  ST_DEFINESPRITE,
153  ST_DEFINEBUTTON,
154  ST_DEFINEBUTTON2,
155  ST_DEFINESOUND,
156  -1
157 };
158
159 // tags which may be used inside a sprite definition
160 static int swf_spritetagids[] =
161 {ST_SHOWFRAME,
162  ST_PLACEOBJECT,
163  ST_PLACEOBJECT2,
164  ST_REMOVEOBJECT,
165  ST_REMOVEOBJECT2, //?
166  ST_DOACTION,
167  ST_STARTSOUND,
168  ST_FRAMELABEL,
169  ST_SOUNDSTREAMHEAD,
170  ST_SOUNDSTREAMHEAD2,
171  ST_SOUNDSTREAMBLOCK,
172  ST_END,
173  -1
174 };
175
176 static int swf_pseudodefiningtagids[] = 
177 {
178  ST_DEFINEFONTINFO,
179  ST_DEFINEBUTTONCXFORM,
180  ST_DEFINEBUTTONSOUND,
181  ST_NAMECHARACTER,
182  -1
183 };
184
185 U8 swf_isAllowedSpriteTag(TAG * tag)
186 {
187     int id = tag->id;
188     int t=0;
189     while(swf_spritetagids[t]>=0)
190     {
191         if(swf_spritetagids[t] == id) 
192             return 1;
193         t++;
194     }
195     return 0; 
196 }
197
198 U8 swf_isDefiningTag(TAG * tag)
199 {
200     int id = tag->id;
201     int t=0;
202     while(swf_definingtagids[t]>=0)
203     {
204         if(swf_definingtagids[t] == id) 
205             return 1;
206         t++;
207     }
208     return 0; 
209 }
210
211 U8 swf_isPseudoDefiningTag(TAG * tag)
212 {
213     int id = tag->id;
214     int t=0;
215     while(swf_pseudodefiningtagids[t]>=0)
216     {
217         if(swf_pseudodefiningtagids[t] == id) 
218             return 1;
219         t++;
220     }
221     return 0; 
222 }
223
224 U16 swf_GetDepth(TAG * t)
225 // up to SWF 4.0
226
227   U16 depth = 0;
228   U32 oldTagPos;
229   oldTagPos = swf_GetTagPos(t);
230   swf_SetTagPos(t,0);
231
232   switch (swf_GetTagID(t))
233   { case ST_PLACEOBJECT:
234     case ST_REMOVEOBJECT:
235       swf_GetU16(t); //id
236       depth = swf_GetU16(t);
237       break;
238     case ST_REMOVEOBJECT2:
239       depth = swf_GetU16(t);
240       break;
241     case ST_PLACEOBJECT2:
242     { U8 flags = swf_GetU8(t);
243       depth = swf_GetU16(t);
244     } break;
245   }
246   swf_SetTagPos(t,oldTagPos);
247   return depth;
248 }
249
250 char* swf_GetName(TAG * t)
251 {
252     char* name = 0;
253     U32 oldTagPos;
254     MATRIX m;
255     CXFORM c;
256     oldTagPos = swf_GetTagPos(t);
257     swf_SetTagPos(t,0);
258     switch(swf_GetTagID(t))
259     {
260         case ST_FRAMELABEL:
261             name = &t->data[swf_GetTagPos(t)];
262         break;
263         case ST_PLACEOBJECT2: {   
264             U8 flags = swf_GetU8(t);
265             swf_GetU16(t); //depth;
266             if(flags&PF_CHAR) 
267               swf_GetU16(t); //id
268             if(flags&PF_MATRIX)
269               swf_GetMatrix(t, &m);
270             if(flags&PF_CXFORM)
271               swf_GetCXForm(t, &c, 1);
272             if(flags&PF_RATIO)
273               swf_GetU16(t);
274             if(flags&PF_NAME) {
275               swf_ResetReadBits(t);
276               name = &t->data[swf_GetTagPos(t)];
277             }
278         }
279         break;
280     }
281     swf_SetTagPos(t,oldTagPos);
282     return name;
283 }
284