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 #ifndef _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX
25 #define _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX
26 
27 #include <sal/types.h>
28 #include <basegfx/matrix/b2dhommatrix.hxx>
29 #include <basegfx/vector/b2dvector.hxx>
30 #include <basegfx/range/b2drange.hxx>
31 
32 namespace rtl { class OUString; }
33 
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 namespace basegfx
37 {
38 	namespace tools
39 	{
40 		/** If the rotation angle is an approximate multiple of pi/2,
41 			force fSin/fCos to -1/0/1, to maintain orthogonality (which
42 			might also be advantageous for the other cases, but: for
43 			multiples of pi/2, the exact values _can_ be attained. It
44 			would be largely unintuitive, if a 180 degrees rotation
45 			would introduce slight roundoff errors, instead of exactly
46 			mirroring the coordinate system)
47 		 */
48 		void createSinCosOrthogonal(double& o_rSin, double& rCos, double fRadiant);
49 
50 		/** Tooling methods for on-the-fly matrix generation e.g. for inline
51 			multiplications
52 		 */
53 		B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY);
54 		B2DHomMatrix createShearXB2DHomMatrix(double fShearX);
55 		B2DHomMatrix createShearYB2DHomMatrix(double fShearY);
56 		B2DHomMatrix createRotateB2DHomMatrix(double fRadiant);
57 		B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY);
58 
59 		/// inline versions for parameters as tuples
createScaleB2DHomMatrix(const B2DTuple & rScale)60 		inline B2DHomMatrix createScaleB2DHomMatrix(const B2DTuple& rScale)
61 		{
62 			return createScaleB2DHomMatrix(rScale.getX(), rScale.getY());
63 		}
64 
createTranslateB2DHomMatrix(const B2DTuple & rTranslate)65 		inline B2DHomMatrix createTranslateB2DHomMatrix(const B2DTuple& rTranslate)
66 		{
67 			return createTranslateB2DHomMatrix(rTranslate.getX(), rTranslate.getY());
68 		}
69 
70 		/** Tooling methods for faster completely combined matrix creation
71 			when scale, shearX, rotation and translation needs to be done in
72 			exactly that order. It's faster since it direcly calculates
73 			each matrix value based on a symbolic calculation of the three
74 			matrix multiplications.
75 			Inline versions for parameters as tuples added, too.
76 		 */
77 		B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
78 			double fScaleX, double fScaleY,
79 			double fShearX,
80 			double fRadiant,
81 			double fTranslateX, double fTranslateY);
createScaleShearXRotateTranslateB2DHomMatrix(const B2DTuple & rScale,double fShearX,double fRadiant,const B2DTuple & rTranslate)82 		inline B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
83 			const B2DTuple& rScale,
84 			double fShearX,
85 			double fRadiant,
86 			const B2DTuple& rTranslate)
87 		{
88 			return createScaleShearXRotateTranslateB2DHomMatrix(
89 				rScale.getX(), rScale.getY(),
90 				fShearX,
91 				fRadiant,
92 				rTranslate.getX(), rTranslate.getY());
93 		}
94 
95 		B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
96 			double fShearX,
97 			double fRadiant,
98 			double fTranslateX, double fTranslateY);
createShearXRotateTranslateB2DHomMatrix(double fShearX,double fRadiant,const B2DTuple & rTranslate)99 		inline B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
100 			double fShearX,
101 			double fRadiant,
102 			const B2DTuple& rTranslate)
103 		{
104 			return createShearXRotateTranslateB2DHomMatrix(
105 				fShearX,
106 				fRadiant,
107 				rTranslate.getX(), rTranslate.getY());
108 		}
109 
110 		B2DHomMatrix createScaleTranslateB2DHomMatrix(
111 			double fScaleX, double fScaleY,
112 			double fTranslateX, double fTranslateY);
createScaleTranslateB2DHomMatrix(const B2DTuple & rScale,const B2DTuple & rTranslate)113 		inline B2DHomMatrix createScaleTranslateB2DHomMatrix(
114 			const B2DTuple& rScale,
115 			const B2DTuple& rTranslate)
116 		{
117 			return createScaleTranslateB2DHomMatrix(
118 				rScale.getX(), rScale.getY(),
119 				rTranslate.getX(), rTranslate.getY());
120 		}
121 
122         /// special for the often used case of rotation around a point
123         B2DHomMatrix createRotateAroundPoint(
124             double fPointX, double fPointY,
125             double fRadiant);
createRotateAroundPoint(const B2DTuple & rPoint,double fRadiant)126         inline B2DHomMatrix createRotateAroundPoint(
127             const B2DTuple& rPoint,
128             double fRadiant)
129         {
130             return createRotateAroundPoint(
131                 rPoint.getX(), rPoint.getY(),
132                 fRadiant);
133         }
134 
135         /// special for the case to map from source range to target range
136         B2DHomMatrix createSourceRangeTargetRangeTransform(
137             const B2DRange& rSourceRange,
138             const B2DRange& rTargetRange);
139 
140     } // end of namespace tools
141 } // end of namespace basegfx
142 
143 ///////////////////////////////////////////////////////////////////////////////
144 
145 namespace basegfx
146 {
147 	namespace tools
148 	{
149 		class B2DHomMatrixBufferedDecompose
150 		{
151 		private:
152 			B2DVector              maScale;
153 			B2DVector              maTranslate;
154 			double                 mfRotate;
155 			double                 mfShearX;
156 
157 		public:
B2DHomMatrixBufferedDecompose(const B2DHomMatrix & rB2DHomMatrix=B2DHomMatrix ())158 			B2DHomMatrixBufferedDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix())
159 			:   maScale(),
160 				maTranslate(),
161 				mfRotate(0.0),
162 				mfShearX(0.0)
163 			{
164 				rB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX);
165 			}
166 
167 			// data access
getB2DHomMatrix() const168 			B2DHomMatrix getB2DHomMatrix() const
169 			{
170 				return createScaleShearXRotateTranslateB2DHomMatrix(
171 					maScale, mfShearX, mfRotate, maTranslate);
172 			}
173 
getScale() const174 			const B2DVector& getScale() const { return maScale; }
getTranslate() const175 			const B2DVector& getTranslate() const { return maTranslate; }
getRotate() const176 			double getRotate() const { return mfRotate; }
getShearX() const177 			double getShearX() const { return mfShearX; }
178 		};
179     } // end of namespace tools
180 } // end of namespace basegfx
181 
182 ///////////////////////////////////////////////////////////////////////////////
183 
184 namespace basegfx
185 {
186 	namespace tools
187 	{
188 		class B2DHomMatrixBufferedOnDemandDecompose
189 		{
190 		private:
191 			B2DHomMatrix           maB2DHomMatrix;
192 			B2DVector              maScale;
193 			B2DVector              maTranslate;
194 			double                 mfRotate;
195 			double                 mfShearX;
196 
197 			// bitfield
198 			unsigned               mbDecomposed : 1;
199 
impCheckDecompose()200 			void impCheckDecompose()
201 			{
202 				if(!mbDecomposed)
203 				{
204 					maB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX);
205 					mbDecomposed = true;
206 				}
207 			}
208 
209 		public:
B2DHomMatrixBufferedOnDemandDecompose(const B2DHomMatrix & rB2DHomMatrix=B2DHomMatrix ())210 			B2DHomMatrixBufferedOnDemandDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix())
211 			:   maB2DHomMatrix(rB2DHomMatrix),
212 				maScale(),
213 				maTranslate(),
214 				mfRotate(0.0),
215 				mfShearX(0.0),
216 				mbDecomposed(false)
217 			{
218 			}
219 
220 			// data access
getB2DHomMatrix() const221 			const B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; }
getScale() const222 			const B2DVector& getScale() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maScale; }
getTranslate() const223 			const B2DVector& getTranslate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maTranslate; }
getRotate() const224 			double getRotate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfRotate; }
getShearX() const225 			double getShearX() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfShearX; }
226 		};
227     } // end of namespace tools
228 
229     /// Returns a string with svg's "matrix(m00,m10,m01,m11,m02,m12)" representation
230     ::rtl::OUString exportToSvg( const B2DHomMatrix& rMatrix );
231 
232 } // end of namespace basegfx
233 
234 ///////////////////////////////////////////////////////////////////////////////
235 
236 #endif /* _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX */
237