xref: /trunk/main/basegfx/source/matrix/b2dhommatrixtools.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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