1 /*
2 Ming, an SWF output library
3 Copyright (C) 2002 Opaque Industries - http://www.opaque.net/
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* $Id$ */
21
22 #ifndef __C2MAN__
23 #include <stdlib.h>
24 #include <math.h>
25 #include <float.h>
26 #include <string.h>
27 #endif
28
29 #include "error.h"
30 #include "libming.h"
31 #include "matrix.h"
32
33
34 /* scale is in FB format- i.e., lower 16 bits are on the right of the
35 decimal point.. */
36
37 #define FIXEDBITS 16
38
39 SWFMatrix
newSWFMatrix(double a,double b,double c,double d,int x,int y)40 newSWFMatrix(double a, double b, double c, double d, int x, int y)
41 {
42 SWFMatrix m = (SWFMatrix)malloc(sizeof(struct SWFMatrix_s));
43
44 /* If malloc failed, return NULL to signify this */
45 if (NULL == m)
46 return NULL;
47
48 m->scaleX = a;
49 m->rotate0 = b;
50 m->rotate1 = c;
51 m->scaleY = d;
52 m->translateX = x;
53 m->translateY = y;
54
55 return m;
56 }
57
58
59 void
SWFMatrix_set(SWFMatrix m,double a,double b,double c,double d,int x,int y)60 SWFMatrix_set(SWFMatrix m, double a, double b, double c, double d, int x, int y)
61 {
62 m->scaleX = a;
63 m->rotate0 = b;
64 m->rotate1 = c;
65 m->scaleY = d;
66 m->translateX = x;
67 m->translateY = y;
68 }
69
70
71 double
SWFMatrix_getScaleX(SWFMatrix m)72 SWFMatrix_getScaleX(SWFMatrix m)
73 {
74 return m->scaleX;
75 }
76
77
78 double
SWFMatrix_getRotate0(SWFMatrix m)79 SWFMatrix_getRotate0(SWFMatrix m)
80 {
81 return m->rotate0;
82 }
83
84
85 double
SWFMatrix_getRotate1(SWFMatrix m)86 SWFMatrix_getRotate1(SWFMatrix m)
87 {
88 return m->rotate1;
89 }
90
91
92 double
SWFMatrix_getScaleY(SWFMatrix m)93 SWFMatrix_getScaleY(SWFMatrix m)
94 {
95 return m->scaleY;
96 }
97
98
99 int
SWFMatrix_getTranslateX(SWFMatrix m)100 SWFMatrix_getTranslateX(SWFMatrix m)
101 {
102 return m->translateX;
103 }
104
105
106 int
SWFMatrix_getTranslateY(SWFMatrix m)107 SWFMatrix_getTranslateY(SWFMatrix m)
108 {
109 return m->translateY;
110 }
111
112
113 void
SWFMatrix_clearTranslate(SWFMatrix m)114 SWFMatrix_clearTranslate(SWFMatrix m)
115 {
116 m->translateX = 0;
117 m->translateY = 0;
118 }
119
120
121 void
SWFMatrix_clearTransform(SWFMatrix m)122 SWFMatrix_clearTransform(SWFMatrix m)
123 {
124 m->scaleX = 1.0;
125 m->rotate0 = 0;
126 m->rotate1 = 0;
127 m->scaleY = 1.0;
128 }
129
130
131 SWFMatrix
SWFMatrix_dup(SWFMatrix matrix)132 SWFMatrix_dup(SWFMatrix matrix)
133 {
134 SWFMatrix m = (SWFMatrix)malloc(sizeof(struct SWFMatrix_s));
135
136 /* If malloc failed, return NULL to signify this */
137 if (NULL == m)
138 return NULL;
139
140 memcpy(m, matrix, sizeof(struct SWFMatrix_s));
141 return m;
142 }
143
144
145 void
destroySWFMatrix(SWFMatrix matrix)146 destroySWFMatrix(SWFMatrix matrix)
147 {
148 free(matrix);
149 }
150
151
152 int
SWFMatrix_numBits(SWFMatrix matrix)153 SWFMatrix_numBits(SWFMatrix matrix)
154 {
155 int bits = 7;
156
157 if ( !((matrix->scaleX == 0 && matrix->scaleY == 0) ||
158 (matrix->scaleX == 1.0 && matrix->scaleY == 1.0)) )
159 {
160 bits += 5 + 2*max(SWFOutput_numSBits((int)matrix->scaleX),
161 SWFOutput_numSBits((int)matrix->scaleY));
162 }
163
164 if ( matrix->rotate0 != 0 || matrix->rotate1 != 0 )
165 {
166 bits += 5 + 2*max(SWFOutput_numSBits((int)matrix->rotate0),
167 SWFOutput_numSBits((int)matrix->rotate1));
168 }
169
170 if ( matrix->translateX != 0 || matrix->translateY != 0 )
171 {
172 bits += 2*max(SWFOutput_numSBits(matrix->translateX),
173 SWFOutput_numSBits(matrix->translateY));
174 }
175
176 return bits;
177 }
178
179
180 void
SWFOutput_writeMatrix(SWFOutput out,SWFMatrix matrix)181 SWFOutput_writeMatrix(SWFOutput out, SWFMatrix matrix)
182 {
183 int nBits;
184
185 SWFOutput_byteAlign(out);
186
187 if (matrix->scaleX == 1.0 && matrix->scaleY == 1.0)
188 {
189 SWFOutput_writeBits(out, 0, 1);
190 }
191 else
192 {
193 int xScale = (int)floor(matrix->scaleX * (1<<FIXEDBITS));
194 int yScale = (int)floor(matrix->scaleY * (1<<FIXEDBITS));
195
196 SWFOutput_writeBits(out, 1, 1);
197 nBits = max(SWFOutput_numSBits(xScale), SWFOutput_numSBits(yScale));
198 if(nBits >= 32)
199 SWF_error("SWFMatrix_scale: number is to big. "
200 " Requested %i bits\n", nBits);
201
202 SWFOutput_writeBits(out, nBits, 5);
203 SWFOutput_writeSBits(out, xScale, nBits);
204 SWFOutput_writeSBits(out, yScale, nBits);
205 }
206
207 if ( matrix->rotate0 == 0 && matrix->rotate1 == 0 )
208 {
209 SWFOutput_writeBits(out, 0, 1);
210 }
211 else
212 {
213 int rot0 = (int)floor(matrix->rotate0 * (1<<FIXEDBITS));
214 int rot1 = (int)floor(matrix->rotate1 * (1<<FIXEDBITS));
215
216 SWFOutput_writeBits(out, 1, 1);
217 nBits = max(SWFOutput_numSBits(rot0), SWFOutput_numSBits(rot1));
218 if(nBits >= 32)
219 SWF_error("SWFMatrix_rotate: number is to big. "
220 " Requested %i bits\n", nBits);
221
222 SWFOutput_writeBits(out, nBits, 5);
223 SWFOutput_writeSBits(out, rot0, nBits);
224 SWFOutput_writeSBits(out, rot1, nBits);
225 }
226
227 if ( matrix->translateX != 0 || matrix->translateY != 0 )
228 {
229 nBits = max(SWFOutput_numSBits(matrix->translateX),
230 SWFOutput_numSBits(matrix->translateY));
231
232 if(nBits >= 32)
233 SWF_error("SWFMatrix_translate: number is to big. "
234 " Requested %i bits\n", nBits);
235 }
236 else
237 nBits = 0;
238
239 SWFOutput_writeBits(out, nBits, 5);
240 SWFOutput_writeSBits(out, matrix->translateX, nBits);
241 SWFOutput_writeSBits(out, matrix->translateY, nBits);
242 }
243
244
245 void
SWFMatrix_apply(SWFMatrix m,double * x,double * y,int xlate)246 SWFMatrix_apply(SWFMatrix m, double *x, double *y, int xlate)
247 {
248 int newx, newy;
249
250 if ( m == NULL )
251 return;
252
253 newx = (int)(m->scaleX * (*x) + m->rotate0 * (*y));
254 newy = (int)(m->scaleY * (*y) + m->rotate1 * (*x));
255
256 *x = newx + (xlate ? m->translateX : 0);
257 *y = newy + (xlate ? m->translateY : 0);
258 }
259
260
261 /* | a b || e f | | ae+bg af+bh |
262 | c d || g h | = | ce+dg cf+dh | */
263
264 /* ma = ma*mb */
SWFMatrix_multiply(SWFMatrix ma,SWFMatrix mb)265 void SWFMatrix_multiply(SWFMatrix ma, SWFMatrix mb)
266 {
267 double a = ma->scaleX, b = ma->rotate0, c = ma->rotate1, d = ma->scaleY;
268 double e = mb->scaleX, f = mb->rotate0, g = mb->rotate1, h = mb->scaleY;
269 double tmp;
270
271 ma->scaleX = a*e+b*g;
272 ma->rotate0 = a*f+b*h;
273 ma->rotate1 = c*e+d*g;
274 ma->scaleY = c*f+d*h;
275
276 tmp = e*ma->translateX + g*ma->translateY + mb->translateX;
277 ma->translateY = (int)(f*ma->translateX + h*ma->translateY + mb->translateY);
278 ma->translateX = (int)tmp;
279 }
280
281
282 /* mb = ma*mb */
283 void
SWFMatrix_leftMultiply(SWFMatrix ma,SWFMatrix mb)284 SWFMatrix_leftMultiply(SWFMatrix ma, SWFMatrix mb)
285 {
286 double a = ma->scaleX, b = ma->rotate0, c = ma->rotate1, d = ma->scaleY;
287 double e = mb->scaleX, f = mb->rotate0, g = mb->rotate1, h = mb->scaleY;
288
289 mb->scaleX = a*e+b*g;
290 mb->rotate0 = a*f+b*h;
291 mb->rotate1 = c*e+d*g;
292 mb->scaleY = c*f+d*h;
293 }
294
295
296 SWFMatrix
newSWFRotateMatrix(double degrees)297 newSWFRotateMatrix(double degrees)
298 {
299 double r = degrees * M_PI/180;
300
301 return newSWFMatrix(cos(r), sin(r), -sin(r), cos(r), 0, 0);
302 }
303
304
305 void
SWFMatrix_rotate(SWFMatrix matrix,double degrees)306 SWFMatrix_rotate(SWFMatrix matrix, double degrees)
307 {
308 SWFMatrix rot = newSWFRotateMatrix(degrees);
309 SWFMatrix_leftMultiply(rot,matrix);
310 destroySWFMatrix(rot);
311 }
312
313
314 void
SWFMatrix_scaleXY(SWFMatrix matrix,double xScale,double yScale)315 SWFMatrix_scaleXY(SWFMatrix matrix, double xScale, double yScale)
316 {
317 matrix->scaleX = matrix->scaleX * xScale;
318 matrix->rotate0 = matrix->rotate0 * xScale;
319 matrix->rotate1 = matrix->rotate1 * yScale;
320 matrix->scaleY = matrix->scaleY * yScale;
321 }
322
323
324 void
SWFMatrix_scale(SWFMatrix matrix,double factor)325 SWFMatrix_scale(SWFMatrix matrix, double factor)
326 {
327 matrix->scaleX = matrix->scaleX * factor;
328 matrix->scaleY = matrix->scaleY * factor;
329 matrix->rotate0 = matrix->rotate0 * factor;
330 matrix->rotate1 = matrix->rotate1 * factor;
331 }
332
333
334 void
SWFMatrix_translate(SWFMatrix matrix,int dx,int dy)335 SWFMatrix_translate(SWFMatrix matrix, int dx, int dy)
336 {
337 matrix->translateX += dx;
338 matrix->translateY += dy;
339 }
340
341
342 void
SWFMatrix_moveTo(SWFMatrix matrix,int x,int y)343 SWFMatrix_moveTo(SWFMatrix matrix, int x, int y)
344 {
345 matrix->translateX = x;
346 matrix->translateY = y;
347 }
348
349
350 /*
351 * Local variables:
352 * tab-width: 2
353 * c-basic-offset: 2
354 * End:
355 */
356