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 { 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 { 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 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 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 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 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 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 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 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 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 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 } // end of namespace tools 394 } // end of namespace basegfx 395 396 /////////////////////////////////////////////////////////////////////////////// 397 // eof 398