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