xref: /AOO41X/main/basegfx/source/matrix/b2dhommatrixtools.cxx (revision d3e0dd8eb215533c15e891ee35bd141abe9397ee)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basegfx.hxx"
26 
27 #include <basegfx/matrix/b2dhommatrixtools.hxx>
28 #include <rtl/ustring.hxx>
29 #include <rtl/ustrbuf.hxx>
30 
31 ///////////////////////////////////////////////////////////////////////////////
32 
33 namespace basegfx
34 {
exportToSvg(const B2DHomMatrix & rMatrix)35     ::rtl::OUString exportToSvg( const B2DHomMatrix& rMatrix )
36     {
37         rtl::OUStringBuffer aStrBuf;
38         aStrBuf.appendAscii("matrix(");
39 
40         aStrBuf.append(rMatrix.get(0,0));
41         aStrBuf.appendAscii(", ");
42 
43         aStrBuf.append(rMatrix.get(1,0));
44         aStrBuf.appendAscii(", ");
45 
46         aStrBuf.append(rMatrix.get(0,1));
47         aStrBuf.appendAscii(", ");
48 
49         aStrBuf.append(rMatrix.get(1,1));
50         aStrBuf.appendAscii(", ");
51 
52         aStrBuf.append(rMatrix.get(0,2));
53         aStrBuf.appendAscii(", ");
54 
55         aStrBuf.append(rMatrix.get(1,2));
56         aStrBuf.appendAscii(")");
57 
58         return aStrBuf.makeStringAndClear();
59     }
60 
61     namespace tools
62     {
createSinCosOrthogonal(double & o_rSin,double & o_rCos,double fRadiant)63         void createSinCosOrthogonal(double& o_rSin, double& o_rCos, double fRadiant)
64         {
65             if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
66             {
67                 // determine quadrant
68                 const sal_Int32 nQuad(
69                     (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
70                 switch( nQuad )
71                 {
72                     case 0: // -2pi,0,2pi
73                         o_rSin = 0.0;
74                         o_rCos = 1.0;
75                         break;
76 
77                     case 1: // -3/2pi,1/2pi
78                         o_rSin = 1.0;
79                         o_rCos = 0.0;
80                         break;
81 
82                     case 2: // -pi,pi
83                         o_rSin = 0.0;
84                         o_rCos = -1.0;
85                         break;
86 
87                     case 3: // -1/2pi,3/2pi
88                         o_rSin = -1.0;
89                         o_rCos = 0.0;
90                         break;
91 
92                     default:
93                         OSL_ENSURE( false, "createSinCos: Impossible case reached" );
94                 }
95             }
96             else
97             {
98                 // TODO(P1): Maybe use glibc's sincos here (though
99                 // that's kinda non-portable...)
100                 o_rSin = sin(fRadiant);
101                 o_rCos = cos(fRadiant);
102             }
103         }
104 
createScaleB2DHomMatrix(double fScaleX,double fScaleY)105         B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
106         {
107             B2DHomMatrix aRetval;
108             const double fOne(1.0);
109 
110             if(!fTools::equal(fScaleX, fOne))
111             {
112                 aRetval.set(0, 0, fScaleX);
113             }
114 
115             if(!fTools::equal(fScaleY, fOne))
116             {
117                 aRetval.set(1, 1, fScaleY);
118             }
119 
120             return aRetval;
121         }
122 
createShearXB2DHomMatrix(double fShearX)123         B2DHomMatrix createShearXB2DHomMatrix(double fShearX)
124         {
125             B2DHomMatrix aRetval;
126 
127             if(!fTools::equalZero(fShearX))
128             {
129                 aRetval.set(0, 1, fShearX);
130             }
131 
132             return aRetval;
133         }
134 
createShearYB2DHomMatrix(double fShearY)135         B2DHomMatrix createShearYB2DHomMatrix(double fShearY)
136         {
137             B2DHomMatrix aRetval;
138 
139             if(!fTools::equalZero(fShearY))
140             {
141                 aRetval.set(1, 0, fShearY);
142             }
143 
144             return aRetval;
145         }
146 
createRotateB2DHomMatrix(double fRadiant)147         B2DHomMatrix createRotateB2DHomMatrix(double fRadiant)
148         {
149             B2DHomMatrix aRetval;
150 
151             if(!fTools::equalZero(fRadiant))
152             {
153                 double fSin(0.0);
154                 double fCos(1.0);
155 
156                 createSinCosOrthogonal(fSin, fCos, fRadiant);
157                 aRetval.set(0, 0, fCos);
158                 aRetval.set(1, 1, fCos);
159                 aRetval.set(1, 0, fSin);
160                 aRetval.set(0, 1, -fSin);
161             }
162 
163             return aRetval;
164         }
165 
createTranslateB2DHomMatrix(double fTranslateX,double fTranslateY)166         B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
167         {
168             B2DHomMatrix aRetval;
169 
170             if(!(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY)))
171             {
172                 aRetval.set(0, 2, fTranslateX);
173                 aRetval.set(1, 2, fTranslateY);
174             }
175 
176             return aRetval;
177         }
178 
createScaleShearXRotateTranslateB2DHomMatrix(double fScaleX,double fScaleY,double fShearX,double fRadiant,double fTranslateX,double fTranslateY)179         B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
180             double fScaleX, double fScaleY,
181             double fShearX,
182             double fRadiant,
183             double fTranslateX, double fTranslateY)
184         {
185             const double fOne(1.0);
186 
187             if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
188             {
189                 /// no scale, take shortcut
190                 return createShearXRotateTranslateB2DHomMatrix(fShearX, fRadiant, fTranslateX, fTranslateY);
191             }
192             else
193             {
194                 /// scale used
195                 if(fTools::equalZero(fShearX))
196                 {
197                     /// no shear
198                     if(fTools::equalZero(fRadiant))
199                     {
200                         /// no rotate, take shortcut
201                         return createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, fTranslateX, fTranslateY);
202                     }
203                     else
204                     {
205                         /// rotate and scale used, no shear
206                         double fSin(0.0);
207                         double fCos(1.0);
208 
209                         createSinCosOrthogonal(fSin, fCos, fRadiant);
210 
211                         B2DHomMatrix aRetval(
212                             /* Row 0, Column 0 */ fCos * fScaleX,
213                             /* Row 0, Column 1 */ fScaleY * -fSin,
214                             /* Row 0, Column 2 */ fTranslateX,
215                             /* Row 1, Column 0 */ fSin * fScaleX,
216                             /* Row 1, Column 1 */ fScaleY * fCos,
217                             /* Row 1, Column 2 */ fTranslateY);
218 
219                         return aRetval;
220                     }
221                 }
222                 else
223                 {
224                     /// scale and shear used
225                     if(fTools::equalZero(fRadiant))
226                     {
227                         /// scale and shear, but no rotate
228                         B2DHomMatrix aRetval(
229                             /* Row 0, Column 0 */ fScaleX,
230                             /* Row 0, Column 1 */ fScaleY * fShearX,
231                             /* Row 0, Column 2 */ fTranslateX,
232                             /* Row 1, Column 0 */ 0.0,
233                             /* Row 1, Column 1 */ fScaleY,
234                             /* Row 1, Column 2 */ fTranslateY);
235 
236                         return aRetval;
237                     }
238                     else
239                     {
240                         /// scale, shear and rotate used
241                         double fSin(0.0);
242                         double fCos(1.0);
243 
244                         createSinCosOrthogonal(fSin, fCos, fRadiant);
245 
246                         B2DHomMatrix aRetval(
247                             /* Row 0, Column 0 */ fCos * fScaleX,
248                             /* Row 0, Column 1 */ fScaleY * ((fCos * fShearX) - fSin),
249                             /* Row 0, Column 2 */ fTranslateX,
250                             /* Row 1, Column 0 */ fSin * fScaleX,
251                             /* Row 1, Column 1 */ fScaleY * ((fSin * fShearX) + fCos),
252                             /* Row 1, Column 2 */ fTranslateY);
253 
254                         return aRetval;
255                     }
256                 }
257             }
258         }
259 
createShearXRotateTranslateB2DHomMatrix(double fShearX,double fRadiant,double fTranslateX,double fTranslateY)260         B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
261             double fShearX,
262             double fRadiant,
263             double fTranslateX, double fTranslateY)
264         {
265             if(fTools::equalZero(fShearX))
266             {
267                 /// no shear
268                 if(fTools::equalZero(fRadiant))
269                 {
270                     /// no shear, no rotate, take shortcut
271                     return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
272                 }
273                 else
274                 {
275                     /// no shear, but rotate used
276                     double fSin(0.0);
277                     double fCos(1.0);
278 
279                     createSinCosOrthogonal(fSin, fCos, fRadiant);
280 
281                     B2DHomMatrix aRetval(
282                         /* Row 0, Column 0 */ fCos,
283                         /* Row 0, Column 1 */ -fSin,
284                         /* Row 0, Column 2 */ fTranslateX,
285                         /* Row 1, Column 0 */ fSin,
286                         /* Row 1, Column 1 */ fCos,
287                         /* Row 1, Column 2 */ fTranslateY);
288 
289                     return aRetval;
290                 }
291             }
292             else
293             {
294                 /// shear used
295                 if(fTools::equalZero(fRadiant))
296                 {
297                     /// no rotate, but shear used
298                     B2DHomMatrix aRetval(
299                         /* Row 0, Column 0 */ 1.0,
300                         /* Row 0, Column 1 */ fShearX,
301                         /* Row 0, Column 2 */ fTranslateX,
302                         /* Row 1, Column 0 */ 0.0,
303                         /* Row 1, Column 1 */ 1.0,
304                         /* Row 1, Column 2 */ fTranslateY);
305 
306                     return aRetval;
307                 }
308                 else
309                 {
310                     /// shear and rotate used
311                     double fSin(0.0);
312                     double fCos(1.0);
313 
314                     createSinCosOrthogonal(fSin, fCos, fRadiant);
315 
316                     B2DHomMatrix aRetval(
317                         /* Row 0, Column 0 */ fCos,
318                         /* Row 0, Column 1 */ (fCos * fShearX) - fSin,
319                         /* Row 0, Column 2 */ fTranslateX,
320                         /* Row 1, Column 0 */ fSin,
321                         /* Row 1, Column 1 */ (fSin * fShearX) + fCos,
322                         /* Row 1, Column 2 */ fTranslateY);
323 
324                     return aRetval;
325                 }
326             }
327         }
328 
createScaleTranslateB2DHomMatrix(double fScaleX,double fScaleY,double fTranslateX,double fTranslateY)329         B2DHomMatrix createScaleTranslateB2DHomMatrix(
330             double fScaleX, double fScaleY,
331             double fTranslateX, double fTranslateY)
332         {
333             const double fOne(1.0);
334 
335             if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
336             {
337                 /// no scale, take shortcut
338                 return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
339             }
340             else
341             {
342                 /// scale used
343                 if(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY))
344                 {
345                     /// no translate, but scale.
346                     B2DHomMatrix aRetval;
347 
348                     aRetval.set(0, 0, fScaleX);
349                     aRetval.set(1, 1, fScaleY);
350 
351                     return aRetval;
352                 }
353                 else
354                 {
355                     /// translate and scale
356                     B2DHomMatrix aRetval(
357                         /* Row 0, Column 0 */ fScaleX,
358                         /* Row 0, Column 1 */ 0.0,
359                         /* Row 0, Column 2 */ fTranslateX,
360                         /* Row 1, Column 0 */ 0.0,
361                         /* Row 1, Column 1 */ fScaleY,
362                         /* Row 1, Column 2 */ fTranslateY);
363 
364                     return aRetval;
365                 }
366             }
367         }
368 
createRotateAroundPoint(double fPointX,double fPointY,double fRadiant)369         B2DHomMatrix createRotateAroundPoint(
370             double fPointX, double fPointY,
371             double fRadiant)
372         {
373             B2DHomMatrix aRetval;
374 
375             if(!fTools::equalZero(fRadiant))
376             {
377                 double fSin(0.0);
378                 double fCos(1.0);
379 
380                 createSinCosOrthogonal(fSin, fCos, fRadiant);
381 
382                 aRetval.set3x2(
383                     /* Row 0, Column 0 */ fCos,
384                     /* Row 0, Column 1 */ -fSin,
385                     /* Row 0, Column 2 */ (fPointX * (1.0 - fCos)) + (fSin * fPointY),
386                     /* Row 1, Column 0 */ fSin,
387                     /* Row 1, Column 1 */ fCos,
388                     /* Row 1, Column 2 */ (fPointY * (1.0 - fCos)) - (fSin * fPointX));
389             }
390 
391             return aRetval;
392         }
393 
394         /// special for the case to map from source range to target range
createSourceRangeTargetRangeTransform(const B2DRange & rSourceRange,const B2DRange & rTargetRange)395         B2DHomMatrix createSourceRangeTargetRangeTransform(
396             const B2DRange& rSourceRange,
397             const B2DRange& rTargetRange)
398         {
399             B2DHomMatrix aRetval;
400 
401             if(&rSourceRange == &rTargetRange)
402             {
403                 return aRetval;
404             }
405 
406             if(!fTools::equalZero(rSourceRange.getMinX()) || !fTools::equalZero(rSourceRange.getMinY()))
407             {
408                 aRetval.set(0, 2, -rSourceRange.getMinX());
409                 aRetval.set(1, 2, -rSourceRange.getMinY());
410             }
411 
412             const double fSourceW(rSourceRange.getWidth());
413             const double fSourceH(rSourceRange.getHeight());
414             const bool bDivX(!fTools::equalZero(fSourceW) && !fTools::equal(fSourceW, 1.0));
415             const bool bDivY(!fTools::equalZero(fSourceH) && !fTools::equal(fSourceH, 1.0));
416             const double fScaleX(bDivX ? rTargetRange.getWidth() / fSourceW : rTargetRange.getWidth());
417             const double fScaleY(bDivY ? rTargetRange.getHeight() / fSourceH : rTargetRange.getHeight());
418 
419             if(!fTools::equalZero(fScaleX) || !fTools::equalZero(fScaleY))
420             {
421                 aRetval.scale(fScaleX, fScaleY);
422             }
423 
424             if(!fTools::equalZero(rTargetRange.getMinX()) || !fTools::equalZero(rTargetRange.getMinY()))
425             {
426                 aRetval.translate(
427                     rTargetRange.getMinX(),
428                     rTargetRange.getMinY());
429             }
430 
431             return aRetval;
432         }
433 
434     } // end of namespace tools
435 } // end of namespace basegfx
436 
437 ///////////////////////////////////////////////////////////////////////////////
438 // eof
439