rfxswf cleanups: TAG structure and ResetWriteBits/ResetReadBits
[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_DEFINEBITS:
82     case ST_DEFINEBITSJPEG2:
83     case ST_DEFINEBITSJPEG3:
84     case ST_DEFINEBITSLOSSLESS:
85     case ST_DEFINEBITSLOSSLESS2:
86     case ST_DEFINEBUTTON:
87     case ST_DEFINEBUTTON2:
88     case ST_DEFINEBUTTONCXFORM:
89     case ST_DEFINEBUTTONSOUND:
90     case ST_DEFINEFONT:
91     case ST_DEFINEFONT2:
92     case ST_DEFINEFONTINFO:
93     case ST_DEFINETEXT:
94     case ST_DEFINETEXT2:
95     case ST_DEFINESOUND:
96     case ST_DEFINESPRITE:
97       id = swf_GetU16(t);
98       break;
99   }
100
101   swf_SetTagPos(t,oldTagPos);
102
103   return id;
104 }
105
106 U16 swf_GetPlaceID(TAG * t)
107 // up to SWF 4.0
108 { U32 oldTagPos;
109   U16 id = 0;
110
111   oldTagPos = swf_GetTagPos(t);
112   swf_SetTagPos(t,0);
113
114   switch (swf_GetTagID(t))
115   { case ST_PLACEOBJECT:
116     case ST_REMOVEOBJECT:
117     case ST_STARTSOUND:
118       id = swf_GetU16(t);
119       break;
120
121     case ST_PLACEOBJECT2:
122     { U8 flags = swf_GetU8(t);
123       U16 d = swf_GetU16(t);
124       id = (flags&PF_CHAR)?swf_GetU16(t):id;
125     } break;
126
127   }
128
129   swf_SetTagPos(t,oldTagPos);
130
131   return id;
132 }
133
134 int definingtagids[] =
135 {ST_DEFINESHAPE,
136  ST_DEFINESHAPE2,
137  ST_DEFINESHAPE3,
138  ST_DEFINEMORPHSHAPE,
139  ST_DEFINEFONT,
140  ST_DEFINEFONT2,
141  ST_DEFINETEXT,
142  ST_DEFINETEXT2,
143  ST_DEFINEEDITTEXT,
144  ST_DEFINEBITS,
145  ST_DEFINEBITSJPEG2,
146  ST_DEFINEBITSJPEG3,
147  ST_DEFINEBITSLOSSLESS,
148  ST_DEFINEBITSLOSSLESS2,
149  ST_DEFINEMOVIE,
150  ST_DEFINESPRITE,
151  ST_DEFINEBUTTON,
152  ST_DEFINEBUTTON2,
153  ST_DEFINESOUND,
154  -1
155 };
156
157 // tags which may be used inside a sprite definition
158 int spritetagids[] =
159 {ST_SHOWFRAME,
160  ST_PLACEOBJECT,
161  ST_PLACEOBJECT2,
162  ST_REMOVEOBJECT,
163  ST_REMOVEOBJECT2, //?
164  ST_DOACTION,
165  ST_STARTSOUND,
166  ST_FRAMELABEL,
167  ST_SOUNDSTREAMHEAD,
168  ST_SOUNDSTREAMHEAD2,
169  ST_SOUNDSTREAMBLOCK,
170  ST_END,
171  -1
172 };
173
174 U8 swf_isAllowedSpriteTag(TAG * tag)
175 {
176     int id = tag->id;
177     int t=0;
178     while(spritetagids[t]>=0)
179     {
180         if(spritetagids[t] == id) 
181             return 1;
182         t++;
183     }
184     return 0; 
185 }
186
187 U8 swf_isDefiningTag(TAG * tag)
188 {
189     int id = tag->id;
190     int t=0;
191     while(definingtagids[t]>=0)
192     {
193         if(definingtagids[t] == id) 
194             return 1;
195         t++;
196     }
197     return 0; 
198 }
199
200 U16 swf_GetDepth(TAG * t)
201 // up to SWF 4.0
202
203   U16 depth = 0;
204   U32 oldTagPos;
205   oldTagPos = swf_GetTagPos(t);
206   swf_SetTagPos(t,0);
207
208   switch (swf_GetTagID(t))
209   { case ST_PLACEOBJECT:
210     case ST_REMOVEOBJECT:
211       swf_GetU16(t); //id
212       depth = swf_GetU16(t);
213       break;
214     case ST_REMOVEOBJECT2:
215       depth = swf_GetU16(t);
216       break;
217     case ST_PLACEOBJECT2:
218     { U8 flags = swf_GetU8(t);
219       depth = swf_GetU16(t);
220     } break;
221   }
222   swf_SetTagPos(t,oldTagPos);
223   return depth;
224 }
225
226 char* swf_GetName(TAG * t)
227 {
228     char* name = 0;
229     U32 oldTagPos;
230     MATRIX m;
231     CXFORM c;
232     oldTagPos = swf_GetTagPos(t);
233     swf_SetTagPos(t,0);
234     switch(swf_GetTagID(t))
235     {
236         case ST_FRAMELABEL:
237             name = &t->data[swf_GetTagPos(t)];
238         break;
239         case ST_PLACEOBJECT2: {   
240             U8 flags = swf_GetU8(t);
241             swf_GetU16(t); //depth;
242             if(flags&PF_CHAR) 
243               swf_GetU16(t); //id
244             if(flags&PF_MATRIX)
245               swf_GetMatrix(t, &m);
246             if(flags&PF_CXFORM)
247               swf_GetCXForm(t, &c, 1);
248             if(flags&PF_RATIO)
249               swf_GetU16(t);
250             if(flags&PF_NAME) {
251               swf_ResetReadBits(t);
252               name = &t->data[swf_GetTagPos(t)];
253             }
254         }
255         break;
256     }
257     swf_SetTagPos(t,oldTagPos);
258     return name;
259 }
260