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