| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basegfx.hxx" |
| |
| #include <basegfx/matrix/b2dhommatrixtools.hxx> |
| #include <rtl/ustring.hxx> |
| #include <rtl/ustrbuf.hxx> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| namespace basegfx |
| { |
| ::rtl::OUString exportToSvg( const B2DHomMatrix& rMatrix ) |
| { |
| rtl::OUStringBuffer aStrBuf; |
| aStrBuf.appendAscii("matrix("); |
| |
| aStrBuf.append(rMatrix.get(0,0)); |
| aStrBuf.appendAscii(", "); |
| |
| aStrBuf.append(rMatrix.get(1,0)); |
| aStrBuf.appendAscii(", "); |
| |
| aStrBuf.append(rMatrix.get(0,1)); |
| aStrBuf.appendAscii(", "); |
| |
| aStrBuf.append(rMatrix.get(1,1)); |
| aStrBuf.appendAscii(", "); |
| |
| aStrBuf.append(rMatrix.get(0,2)); |
| aStrBuf.appendAscii(", "); |
| |
| aStrBuf.append(rMatrix.get(1,2)); |
| aStrBuf.appendAscii(")"); |
| |
| return aStrBuf.makeStringAndClear(); |
| } |
| |
| namespace tools |
| { |
| void createSinCosOrthogonal(double& o_rSin, double& o_rCos, double fRadiant) |
| { |
| if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) ) |
| { |
| // determine quadrant |
| const sal_Int32 nQuad( |
| (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 ); |
| switch( nQuad ) |
| { |
| case 0: // -2pi,0,2pi |
| o_rSin = 0.0; |
| o_rCos = 1.0; |
| break; |
| |
| case 1: // -3/2pi,1/2pi |
| o_rSin = 1.0; |
| o_rCos = 0.0; |
| break; |
| |
| case 2: // -pi,pi |
| o_rSin = 0.0; |
| o_rCos = -1.0; |
| break; |
| |
| case 3: // -1/2pi,3/2pi |
| o_rSin = -1.0; |
| o_rCos = 0.0; |
| break; |
| |
| default: |
| OSL_ENSURE( false, "createSinCos: Impossible case reached" ); |
| } |
| } |
| else |
| { |
| // TODO(P1): Maybe use glibc's sincos here (though |
| // that's kinda non-portable...) |
| o_rSin = sin(fRadiant); |
| o_rCos = cos(fRadiant); |
| } |
| } |
| |
| B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY) |
| { |
| B2DHomMatrix aRetval; |
| const double fOne(1.0); |
| |
| if(!fTools::equal(fScaleX, fOne)) |
| { |
| aRetval.set(0, 0, fScaleX); |
| } |
| |
| if(!fTools::equal(fScaleY, fOne)) |
| { |
| aRetval.set(1, 1, fScaleY); |
| } |
| |
| return aRetval; |
| } |
| |
| B2DHomMatrix createShearXB2DHomMatrix(double fShearX) |
| { |
| B2DHomMatrix aRetval; |
| |
| if(!fTools::equalZero(fShearX)) |
| { |
| aRetval.set(0, 1, fShearX); |
| } |
| |
| return aRetval; |
| } |
| |
| B2DHomMatrix createShearYB2DHomMatrix(double fShearY) |
| { |
| B2DHomMatrix aRetval; |
| |
| if(!fTools::equalZero(fShearY)) |
| { |
| aRetval.set(1, 0, fShearY); |
| } |
| |
| return aRetval; |
| } |
| |
| B2DHomMatrix createRotateB2DHomMatrix(double fRadiant) |
| { |
| B2DHomMatrix aRetval; |
| |
| if(!fTools::equalZero(fRadiant)) |
| { |
| double fSin(0.0); |
| double fCos(1.0); |
| |
| createSinCosOrthogonal(fSin, fCos, fRadiant); |
| aRetval.set(0, 0, fCos); |
| aRetval.set(1, 1, fCos); |
| aRetval.set(1, 0, fSin); |
| aRetval.set(0, 1, -fSin); |
| } |
| |
| return aRetval; |
| } |
| |
| B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY) |
| { |
| B2DHomMatrix aRetval; |
| |
| if(!(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY))) |
| { |
| aRetval.set(0, 2, fTranslateX); |
| aRetval.set(1, 2, fTranslateY); |
| } |
| |
| return aRetval; |
| } |
| |
| B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix( |
| double fScaleX, double fScaleY, |
| double fShearX, |
| double fRadiant, |
| double fTranslateX, double fTranslateY) |
| { |
| const double fOne(1.0); |
| |
| if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne)) |
| { |
| /// no scale, take shortcut |
| return createShearXRotateTranslateB2DHomMatrix(fShearX, fRadiant, fTranslateX, fTranslateY); |
| } |
| else |
| { |
| /// scale used |
| if(fTools::equalZero(fShearX)) |
| { |
| /// no shear |
| if(fTools::equalZero(fRadiant)) |
| { |
| /// no rotate, take shortcut |
| return createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, fTranslateX, fTranslateY); |
| } |
| else |
| { |
| /// rotate and scale used, no shear |
| double fSin(0.0); |
| double fCos(1.0); |
| |
| createSinCosOrthogonal(fSin, fCos, fRadiant); |
| |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ fCos * fScaleX, |
| /* Row 0, Column 1 */ fScaleY * -fSin, |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ fSin * fScaleX, |
| /* Row 1, Column 1 */ fScaleY * fCos, |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| } |
| else |
| { |
| /// scale and shear used |
| if(fTools::equalZero(fRadiant)) |
| { |
| /// scale and shear, but no rotate |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ fScaleX, |
| /* Row 0, Column 1 */ fScaleY * fShearX, |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ 0.0, |
| /* Row 1, Column 1 */ fScaleY, |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| else |
| { |
| /// scale, shear and rotate used |
| double fSin(0.0); |
| double fCos(1.0); |
| |
| createSinCosOrthogonal(fSin, fCos, fRadiant); |
| |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ fCos * fScaleX, |
| /* Row 0, Column 1 */ fScaleY * ((fCos * fShearX) - fSin), |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ fSin * fScaleX, |
| /* Row 1, Column 1 */ fScaleY * ((fSin * fShearX) + fCos), |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| } |
| } |
| } |
| |
| B2DHomMatrix createShearXRotateTranslateB2DHomMatrix( |
| double fShearX, |
| double fRadiant, |
| double fTranslateX, double fTranslateY) |
| { |
| if(fTools::equalZero(fShearX)) |
| { |
| /// no shear |
| if(fTools::equalZero(fRadiant)) |
| { |
| /// no shear, no rotate, take shortcut |
| return createTranslateB2DHomMatrix(fTranslateX, fTranslateY); |
| } |
| else |
| { |
| /// no shear, but rotate used |
| double fSin(0.0); |
| double fCos(1.0); |
| |
| createSinCosOrthogonal(fSin, fCos, fRadiant); |
| |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ fCos, |
| /* Row 0, Column 1 */ -fSin, |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ fSin, |
| /* Row 1, Column 1 */ fCos, |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| } |
| else |
| { |
| /// shear used |
| if(fTools::equalZero(fRadiant)) |
| { |
| /// no rotate, but shear used |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ 1.0, |
| /* Row 0, Column 1 */ fShearX, |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ 0.0, |
| /* Row 1, Column 1 */ 1.0, |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| else |
| { |
| /// shear and rotate used |
| double fSin(0.0); |
| double fCos(1.0); |
| |
| createSinCosOrthogonal(fSin, fCos, fRadiant); |
| |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ fCos, |
| /* Row 0, Column 1 */ (fCos * fShearX) - fSin, |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ fSin, |
| /* Row 1, Column 1 */ (fSin * fShearX) + fCos, |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| } |
| } |
| |
| B2DHomMatrix createScaleTranslateB2DHomMatrix( |
| double fScaleX, double fScaleY, |
| double fTranslateX, double fTranslateY) |
| { |
| const double fOne(1.0); |
| |
| if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne)) |
| { |
| /// no scale, take shortcut |
| return createTranslateB2DHomMatrix(fTranslateX, fTranslateY); |
| } |
| else |
| { |
| /// scale used |
| if(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY)) |
| { |
| /// no translate, but scale. |
| B2DHomMatrix aRetval; |
| |
| aRetval.set(0, 0, fScaleX); |
| aRetval.set(1, 1, fScaleY); |
| |
| return aRetval; |
| } |
| else |
| { |
| /// translate and scale |
| B2DHomMatrix aRetval( |
| /* Row 0, Column 0 */ fScaleX, |
| /* Row 0, Column 1 */ 0.0, |
| /* Row 0, Column 2 */ fTranslateX, |
| /* Row 1, Column 0 */ 0.0, |
| /* Row 1, Column 1 */ fScaleY, |
| /* Row 1, Column 2 */ fTranslateY); |
| |
| return aRetval; |
| } |
| } |
| } |
| |
| B2DHomMatrix createRotateAroundPoint( |
| double fPointX, double fPointY, |
| double fRadiant) |
| { |
| B2DHomMatrix aRetval; |
| |
| if(!fTools::equalZero(fRadiant)) |
| { |
| double fSin(0.0); |
| double fCos(1.0); |
| |
| createSinCosOrthogonal(fSin, fCos, fRadiant); |
| |
| aRetval.set3x2( |
| /* Row 0, Column 0 */ fCos, |
| /* Row 0, Column 1 */ -fSin, |
| /* Row 0, Column 2 */ (fPointX * (1.0 - fCos)) + (fSin * fPointY), |
| /* Row 1, Column 0 */ fSin, |
| /* Row 1, Column 1 */ fCos, |
| /* Row 1, Column 2 */ (fPointY * (1.0 - fCos)) - (fSin * fPointX)); |
| } |
| |
| return aRetval; |
| } |
| |
| /// special for the case to map from source range to target range |
| B2DHomMatrix createSourceRangeTargetRangeTransform( |
| const B2DRange& rSourceRange, |
| const B2DRange& rTargetRange) |
| { |
| B2DHomMatrix aRetval; |
| |
| if(&rSourceRange == &rTargetRange) |
| { |
| return aRetval; |
| } |
| |
| if(!fTools::equalZero(rSourceRange.getMinX()) || !fTools::equalZero(rSourceRange.getMinY())) |
| { |
| aRetval.set(0, 2, -rSourceRange.getMinX()); |
| aRetval.set(1, 2, -rSourceRange.getMinY()); |
| } |
| |
| const double fSourceW(rSourceRange.getWidth()); |
| const double fSourceH(rSourceRange.getHeight()); |
| const bool bDivX(!fTools::equalZero(fSourceW) && !fTools::equal(fSourceW, 1.0)); |
| const bool bDivY(!fTools::equalZero(fSourceH) && !fTools::equal(fSourceH, 1.0)); |
| const double fScaleX(bDivX ? rTargetRange.getWidth() / fSourceW : rTargetRange.getWidth()); |
| const double fScaleY(bDivY ? rTargetRange.getHeight() / fSourceH : rTargetRange.getHeight()); |
| |
| if(!fTools::equalZero(fScaleX) || !fTools::equalZero(fScaleY)) |
| { |
| aRetval.scale(fScaleX, fScaleY); |
| } |
| |
| if(!fTools::equalZero(rTargetRange.getMinX()) || !fTools::equalZero(rTargetRange.getMinY())) |
| { |
| aRetval.translate( |
| rTargetRange.getMinX(), |
| rTargetRange.getMinY()); |
| } |
| |
| return aRetval; |
| } |
| |
| } // end of namespace tools |
| } // end of namespace basegfx |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // eof |