2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / WindowsBase / System.Windows.Media / Matrix.cs
blob78f1d450916ebcef407256b2c6c0e626b17d08e6
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
22 // Authors:
23 // Chris Toshok (toshok@ximian.com)
26 using System;
27 using System.ComponentModel;
28 using System.Windows.Markup;
29 using System.Windows.Media.Converters;
30 using System.Windows.Threading;
32 namespace System.Windows.Media {
34 [Serializable]
35 [TypeConverter (typeof(MatrixConverter))]
36 [ValueSerializer (typeof (MatrixValueSerializer))]
37 public struct Matrix : IFormattable {
39 double m11;
40 double m12;
41 double m21;
42 double m22;
43 double offsetX;
44 double offsetY;
46 public Matrix (double m11,
47 double m12,
48 double m21,
49 double m22,
50 double offsetX,
51 double offsetY)
53 this.m11 = m11;
54 this.m12 = m12;
55 this.m21 = m21;
56 this.m22 = m22;
57 this.offsetX = offsetX;
58 this.offsetY = offsetY;
61 public void Append (Matrix matrix)
63 double _m11;
64 double _m21;
65 double _m12;
66 double _m22;
67 double _offsetX;
68 double _offsetY;
70 _m11 = m11 * matrix.M11 + m12 * matrix.M21;
71 _m12 = m11 * matrix.M12 + m12 * matrix.M22;
72 _m21 = m21 * matrix.M11 + m22 * matrix.M21;
73 _m22 = m21 * matrix.M12 + m22 * matrix.M22;
75 _offsetX = offsetX * matrix.M11 + offsetY * matrix.M21 + matrix.OffsetX;
76 _offsetY = offsetX * matrix.M12 + offsetY * matrix.M22 + matrix.OffsetY;
78 m11 = _m11;
79 m12 = _m12;
80 m21 = _m21;
81 m22 = _m22;
82 offsetX = _offsetX;
83 offsetY = _offsetY;
86 public bool Equals (Matrix value)
88 return (m11 == value.M11 &&
89 m12 == value.M12 &&
90 m21 == value.M21 &&
91 m22 == value.M22 &&
92 offsetX == value.OffsetX &&
93 offsetY == value.OffsetY);
96 public override bool Equals (object o)
98 if (!(o is Matrix))
99 return false;
101 return Equals ((Matrix)o);
104 public static bool Equals (Matrix matrix1,
105 Matrix matrix2)
107 return matrix1.Equals (matrix2);
110 public override int GetHashCode ()
112 throw new NotImplementedException ();
115 public void Invert ()
117 if (!HasInverse)
118 throw new InvalidOperationException ("Transform is not invertible.");
120 double d = Determinant;
122 /* 1/(ad-bc)[d -b; -c a] */
124 double _m11 = m22;
125 double _m12 = -m12;
126 double _m21 = -m21;
127 double _m22 = m11;
129 double _offsetX = m21 * offsetY - m22 * offsetX;
130 double _offsetY = m12 * offsetX - m11 * offsetY;
132 m11 = _m11 / d;
133 m12 = _m12 / d;
134 m21 = _m21 / d;
135 m22 = _m22 / d;
136 offsetX = _offsetX / d;
137 offsetY = _offsetY / d;
140 public static Matrix Multiply (Matrix trans1,
141 Matrix trans2)
143 Matrix m = trans1;
144 m.Append (trans2);
145 return m;
148 public static bool operator == (Matrix matrix1,
149 Matrix matrix2)
151 return matrix1.Equals (matrix2);
154 public static bool operator != (Matrix matrix1,
155 Matrix matrix2)
157 return !matrix1.Equals (matrix2);
160 public static Matrix operator * (Matrix trans1,
161 Matrix trans2)
163 Matrix result = trans1;
164 result.Append (trans2);
165 return result;
168 public static Matrix Parse (string source)
170 throw new NotImplementedException ();
173 public void Prepend (Matrix matrix)
175 double _m11;
176 double _m21;
177 double _m12;
178 double _m22;
179 double _offsetX;
180 double _offsetY;
182 _m11 = matrix.M11 * m11 + matrix.M12 * m21;
183 _m12 = matrix.M11 * m12 + matrix.M12 * m22;
184 _m21 = matrix.M21 * m11 + matrix.M22 * m21;
185 _m22 = matrix.M21 * m12 + matrix.M22 * m22;
187 _offsetX = matrix.OffsetX * m11 + matrix.OffsetY * m21 + offsetX;
188 _offsetY = matrix.OffsetX * m12 + matrix.OffsetY * m22 + offsetY;
190 m11 = _m11;
191 m12 = _m12;
192 m21 = _m21;
193 m22 = _m22;
194 offsetX = _offsetX;
195 offsetY = _offsetY;
198 public void Rotate (double angle)
200 // R_theta==[costheta -sintheta; sintheta costheta],
201 double theta = angle * Math.PI / 180;
203 Matrix r_theta = new Matrix (Math.Cos (theta), Math.Sin(theta),
204 -Math.Sin (theta), Math.Cos(theta),
205 0, 0);
207 Append (r_theta);
210 public void RotateAt (double angle,
211 double centerX,
212 double centerY)
214 Translate (-centerX, -centerY);
215 Rotate (angle);
216 Translate (centerX, centerY);
219 public void RotateAtPrepend (double angle,
220 double centerX,
221 double centerY)
223 Matrix m = Matrix.Identity;
224 m.RotateAt (angle, centerX, centerY);
225 Prepend (m);
228 public void RotatePrepend (double angle)
230 Matrix m = Matrix.Identity;
231 m.Rotate (angle);
232 Prepend (m);
235 public void Scale (double scaleX,
236 double scaleY)
238 Matrix scale = new Matrix (scaleX, 0,
239 0, scaleY,
240 0, 0);
242 Append (scale);
245 public void ScaleAt (double scaleX,
246 double scaleY,
247 double centerX,
248 double centerY)
250 Translate (-centerX, -centerY);
251 Scale (scaleX, scaleY);
252 Translate (centerX, centerY);
255 public void ScaleAtPrepend (double scaleX,
256 double scaleY,
257 double centerX,
258 double centerY)
260 Matrix m = Matrix.Identity;
261 m.ScaleAt (scaleX, scaleY, centerX, centerY);
262 Prepend (m);
265 public void ScalePrepend (double scaleX,
266 double scaleY)
268 Matrix m = Matrix.Identity;
269 m.Scale (scaleX, scaleY);
270 Prepend (m);
273 public void SetIdentity ()
275 m11 = m22 = 1.0;
276 m12 = m21 = 0.0;
277 offsetX = offsetY = 0.0;
280 public void Skew (double skewX,
281 double skewY)
283 Matrix skew_m = new Matrix (1, Math.Tan (skewY * Math.PI / 180),
284 Math.Tan (skewX * Math.PI / 180), 1,
285 0, 0);
286 Append (skew_m);
289 public void SkewPrepend (double skewX,
290 double skewY)
292 Matrix m = Matrix.Identity;
293 m.Skew (skewX, skewY);
294 Prepend (m);
297 string IFormattable.ToString (string format,
298 IFormatProvider provider)
300 throw new NotImplementedException ();
303 public override string ToString ()
305 if (IsIdentity)
306 return "Identity";
307 else
308 return string.Format ("{0},{1},{2},{3},{4},{5}",
309 m11, m12, m21, m22, offsetX, offsetY);
312 public string ToString (IFormatProvider provider)
314 throw new NotImplementedException ();
317 public Point Transform (Point point)
319 return Point.Multiply (point, this);
322 public void Transform (Point[] points)
324 for (int i = 0; i < points.Length; i ++)
325 points[i] = Transform (points[i]);
328 public Vector Transform (Vector vector)
330 return Vector.Multiply (vector, this);
333 public void Transform (Vector[] vectors)
335 for (int i = 0; i < vectors.Length; i ++)
336 vectors[i] = Transform (vectors[i]);
339 public void Translate (double offsetX,
340 double offsetY)
342 this.offsetX += offsetX;
343 this.offsetY += offsetY;
346 public void TranslatePrepend (double offsetX,
347 double offsetY)
349 Matrix m = Matrix.Identity;
350 m.Translate (offsetX, offsetY);
351 Prepend (m);
354 public double Determinant {
355 get { return m11 * m22 - m12 * m21; }
358 public bool HasInverse {
359 get { return Determinant != 0; }
362 public static Matrix Identity {
363 get { return new Matrix (1.0, 0.0, 0.0, 1.0, 0.0, 0.0); }
366 public bool IsIdentity {
367 get { return Equals (Matrix.Identity); }
370 public double M11 {
371 get { return m11; }
372 set { m11 = value; }
374 public double M12 {
375 get { return m12; }
376 set { m12 = value; }
378 public double M21 {
379 get { return m21; }
380 set { m21 = value; }
382 public double M22 {
383 get { return m22; }
384 set { m22 = value; }
386 public double OffsetX {
387 get { return offsetX; }
388 set { offsetX = value; }
390 public double OffsetY {
391 get { return offsetY; }
392 set { offsetY = value; }