1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basegfx.hxx"
30 
31 #include <basegfx/matrix/b2dhommatrixtools.hxx>
32 #include <rtl/ustring.hxx>
33 #include <rtl/ustrbuf.hxx>
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 
37 namespace basegfx
38 {
39     ::rtl::OUString exportToSvg( const B2DHomMatrix& rMatrix )
40     {
41         rtl::OUStringBuffer aStrBuf;
42         aStrBuf.appendAscii("matrix(");
43 
44         aStrBuf.append(rMatrix.get(0,0));
45         aStrBuf.appendAscii(", ");
46 
47         aStrBuf.append(rMatrix.get(1,0));
48         aStrBuf.appendAscii(", ");
49 
50         aStrBuf.append(rMatrix.get(0,1));
51         aStrBuf.appendAscii(", ");
52 
53         aStrBuf.append(rMatrix.get(1,1));
54         aStrBuf.appendAscii(", ");
55 
56         aStrBuf.append(rMatrix.get(0,2));
57         aStrBuf.appendAscii(", ");
58 
59         aStrBuf.append(rMatrix.get(1,2));
60         aStrBuf.appendAscii(")");
61 
62         return aStrBuf.makeStringAndClear();
63     }
64 
65 	namespace tools
66 	{
67 		void createSinCosOrthogonal(double& o_rSin, double& o_rCos, double fRadiant)
68 		{
69 			if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
70 			{
71 				// determine quadrant
72 				const sal_Int32 nQuad(
73 					(4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
74 				switch( nQuad )
75 				{
76 					case 0: // -2pi,0,2pi
77 						o_rSin = 0.0;
78 						o_rCos = 1.0;
79 						break;
80 
81 					case 1: // -3/2pi,1/2pi
82 						o_rSin = 1.0;
83 						o_rCos = 0.0;
84 						break;
85 
86 					case 2: // -pi,pi
87 						o_rSin = 0.0;
88 						o_rCos = -1.0;
89 						break;
90 
91 					case 3: // -1/2pi,3/2pi
92 						o_rSin = -1.0;
93 						o_rCos = 0.0;
94 						break;
95 
96 					default:
97 						OSL_ENSURE( false, "createSinCos: Impossible case reached" );
98 				}
99 			}
100 			else
101 			{
102 				// TODO(P1): Maybe use glibc's sincos here (though
103 				// that's kinda non-portable...)
104 				o_rSin = sin(fRadiant);
105 				o_rCos = cos(fRadiant);
106 			}
107 		}
108 
109 		B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
110 		{
111 			B2DHomMatrix aRetval;
112 			const double fOne(1.0);
113 
114 			if(!fTools::equal(fScaleX, fOne))
115 			{
116 				aRetval.set(0, 0, fScaleX);
117 			}
118 
119 			if(!fTools::equal(fScaleY, fOne))
120 			{
121 				aRetval.set(1, 1, fScaleY);
122 			}
123 
124 			return aRetval;
125 		}
126 
127 		B2DHomMatrix createShearXB2DHomMatrix(double fShearX)
128 		{
129 			B2DHomMatrix aRetval;
130 
131 			if(!fTools::equalZero(fShearX))
132 			{
133 				aRetval.set(0, 1, fShearX);
134 			}
135 
136 			return aRetval;
137 		}
138 
139 		B2DHomMatrix createShearYB2DHomMatrix(double fShearY)
140 		{
141 			B2DHomMatrix aRetval;
142 
143 			if(!fTools::equalZero(fShearY))
144 			{
145 				aRetval.set(1, 0, fShearY);
146 			}
147 
148 			return aRetval;
149 		}
150 
151 		B2DHomMatrix createRotateB2DHomMatrix(double fRadiant)
152 		{
153 			B2DHomMatrix aRetval;
154 
155 			if(!fTools::equalZero(fRadiant))
156 			{
157 				double fSin(0.0);
158 				double fCos(1.0);
159 
160 				createSinCosOrthogonal(fSin, fCos, fRadiant);
161 				aRetval.set(0, 0, fCos);
162 				aRetval.set(1, 1, fCos);
163 				aRetval.set(1, 0, fSin);
164 				aRetval.set(0, 1, -fSin);
165 			}
166 
167 			return aRetval;
168 		}
169 
170 		B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
171 		{
172 			B2DHomMatrix aRetval;
173 
174 			if(!(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY)))
175 			{
176 				aRetval.set(0, 2, fTranslateX);
177 				aRetval.set(1, 2, fTranslateY);
178 			}
179 
180 			return aRetval;
181 		}
182 
183 		B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
184 			double fScaleX, double fScaleY,
185 			double fShearX,
186 			double fRadiant,
187 			double fTranslateX, double fTranslateY)
188 		{
189 			const double fOne(1.0);
190 
191 			if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
192 			{
193 				/// no scale, take shortcut
194 				return createShearXRotateTranslateB2DHomMatrix(fShearX, fRadiant, fTranslateX, fTranslateY);
195 			}
196 			else
197 			{
198 				/// scale used
199 				if(fTools::equalZero(fShearX))
200 				{
201 					/// no shear
202 					if(fTools::equalZero(fRadiant))
203 					{
204 						/// no rotate, take shortcut
205 						return createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, fTranslateX, fTranslateY);
206 					}
207 					else
208 					{
209 						/// rotate and scale used, no shear
210 						double fSin(0.0);
211 						double fCos(1.0);
212 
213 						createSinCosOrthogonal(fSin, fCos, fRadiant);
214 
215 						B2DHomMatrix aRetval(
216 							/* Row 0, Column 0 */ fCos * fScaleX,
217 							/* Row 0, Column 1 */ fScaleY * -fSin,
218 							/* Row 0, Column 2 */ fTranslateX,
219 							/* Row 1, Column 0 */ fSin * fScaleX,
220 							/* Row 1, Column 1 */ fScaleY * fCos,
221 							/* Row 1, Column 2 */ fTranslateY);
222 
223 						return aRetval;
224 					}
225 				}
226 				else
227 				{
228 					/// scale and shear used
229 					if(fTools::equalZero(fRadiant))
230 					{
231 						/// scale and shear, but no rotate
232 						B2DHomMatrix aRetval(
233 							/* Row 0, Column 0 */ fScaleX,
234 							/* Row 0, Column 1 */ fScaleY * fShearX,
235 							/* Row 0, Column 2 */ fTranslateX,
236 							/* Row 1, Column 0 */ 0.0,
237 							/* Row 1, Column 1 */ fScaleY,
238 							/* Row 1, Column 2 */ fTranslateY);
239 
240 						return aRetval;
241 					}
242 					else
243 					{
244 						/// scale, shear and rotate used
245 						double fSin(0.0);
246 						double fCos(1.0);
247 
248 						createSinCosOrthogonal(fSin, fCos, fRadiant);
249 
250 						B2DHomMatrix aRetval(
251 							/* Row 0, Column 0 */ fCos * fScaleX,
252 							/* Row 0, Column 1 */ fScaleY * ((fCos * fShearX) - fSin),
253 							/* Row 0, Column 2 */ fTranslateX,
254 							/* Row 1, Column 0 */ fSin * fScaleX,
255 							/* Row 1, Column 1 */ fScaleY * ((fSin * fShearX) + fCos),
256 							/* Row 1, Column 2 */ fTranslateY);
257 
258 						return aRetval;
259 					}
260 				}
261 			}
262 		}
263 
264 		B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
265 			double fShearX,
266 			double fRadiant,
267 			double fTranslateX, double fTranslateY)
268 		{
269 			if(fTools::equalZero(fShearX))
270 			{
271 				/// no shear
272 				if(fTools::equalZero(fRadiant))
273 				{
274 					/// no shear, no rotate, take shortcut
275 					return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
276 				}
277 				else
278 				{
279 					/// no shear, but rotate used
280 					double fSin(0.0);
281 					double fCos(1.0);
282 
283 					createSinCosOrthogonal(fSin, fCos, fRadiant);
284 
285 					B2DHomMatrix aRetval(
286 						/* Row 0, Column 0 */ fCos,
287 						/* Row 0, Column 1 */ -fSin,
288 						/* Row 0, Column 2 */ fTranslateX,
289 						/* Row 1, Column 0 */ fSin,
290 						/* Row 1, Column 1 */ fCos,
291 						/* Row 1, Column 2 */ fTranslateY);
292 
293 					return aRetval;
294 				}
295 			}
296 			else
297 			{
298 				/// shear used
299 				if(fTools::equalZero(fRadiant))
300 				{
301 					/// no rotate, but shear used
302 					B2DHomMatrix aRetval(
303 						/* Row 0, Column 0 */ 1.0,
304 						/* Row 0, Column 1 */ fShearX,
305 						/* Row 0, Column 2 */ fTranslateX,
306 						/* Row 1, Column 0 */ 0.0,
307 						/* Row 1, Column 1 */ 1.0,
308 						/* Row 1, Column 2 */ fTranslateY);
309 
310 					return aRetval;
311 				}
312 				else
313 				{
314 					/// shear and rotate used
315 					double fSin(0.0);
316 					double fCos(1.0);
317 
318 					createSinCosOrthogonal(fSin, fCos, fRadiant);
319 
320 					B2DHomMatrix aRetval(
321 						/* Row 0, Column 0 */ fCos,
322 						/* Row 0, Column 1 */ (fCos * fShearX) - fSin,
323 						/* Row 0, Column 2 */ fTranslateX,
324 						/* Row 1, Column 0 */ fSin,
325 						/* Row 1, Column 1 */ (fSin * fShearX) + fCos,
326 						/* Row 1, Column 2 */ fTranslateY);
327 
328 					return aRetval;
329 				}
330 			}
331 		}
332 
333 		B2DHomMatrix createScaleTranslateB2DHomMatrix(
334 			double fScaleX, double fScaleY,
335 			double fTranslateX, double fTranslateY)
336 		{
337 			const double fOne(1.0);
338 
339 			if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
340 			{
341 				/// no scale, take shortcut
342 				return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
343 			}
344 			else
345 			{
346 				/// scale used
347 				if(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY))
348 				{
349 					/// no translate, but scale.
350 					B2DHomMatrix aRetval;
351 
352 					aRetval.set(0, 0, fScaleX);
353 					aRetval.set(1, 1, fScaleY);
354 
355 					return aRetval;
356 				}
357 				else
358 				{
359 					/// translate and scale
360 					B2DHomMatrix aRetval(
361 						/* Row 0, Column 0 */ fScaleX,
362 						/* Row 0, Column 1 */ 0.0,
363 						/* Row 0, Column 2 */ fTranslateX,
364 						/* Row 1, Column 0 */ 0.0,
365 						/* Row 1, Column 1 */ fScaleY,
366 						/* Row 1, Column 2 */ fTranslateY);
367 
368 					return aRetval;
369 				}
370 			}
371 		}
372 
373         B2DHomMatrix createRotateAroundPoint(
374             double fPointX, double fPointY,
375             double fRadiant)
376         {
377 			B2DHomMatrix aRetval;
378 
379 			if(!fTools::equalZero(fRadiant))
380 			{
381                 double fSin(0.0);
382 				double fCos(1.0);
383 
384 				createSinCosOrthogonal(fSin, fCos, fRadiant);
385 
386                 aRetval.set3x2(
387 					/* Row 0, Column 0 */ fCos,
388 					/* Row 0, Column 1 */ -fSin,
389 					/* Row 0, Column 2 */ (fPointX * (1.0 - fCos)) + (fSin * fPointY),
390 					/* Row 1, Column 0 */ fSin,
391 					/* Row 1, Column 1 */ fCos,
392 					/* Row 1, Column 2 */ (fPointY * (1.0 - fCos)) - (fSin * fPointX));
393             }
394 
395             return aRetval;
396         }
397     } // end of namespace tools
398 } // end of namespace basegfx
399 
400 ///////////////////////////////////////////////////////////////////////////////
401 // eof
402