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