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