Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / draw / Matrix.js
1 /*
2  * @class Ext.draw.Matrix
3  * @private
4  */
5 Ext.define('Ext.draw.Matrix', {
6
7     /* Begin Definitions */
8
9     requires: ['Ext.draw.Draw'],
10
11     /* End Definitions */
12
13     constructor: function(a, b, c, d, e, f) {
14         if (a != null) {
15             this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
16         }
17         else {
18             this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
19         }
20     },
21
22     add: function(a, b, c, d, e, f) {
23         var me = this,
24             out = [[], [], []],
25             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
26             x,
27             y,
28             z,
29             res;
30
31         for (x = 0; x < 3; x++) {
32             for (y = 0; y < 3; y++) {
33                 res = 0;
34                 for (z = 0; z < 3; z++) {
35                     res += me.matrix[x][z] * matrix[z][y];
36                 }
37                 out[x][y] = res;
38             }
39         }
40         me.matrix = out;
41     },
42
43     prepend: function(a, b, c, d, e, f) {
44         var me = this,
45             out = [[], [], []],
46             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
47             x,
48             y,
49             z,
50             res;
51
52         for (x = 0; x < 3; x++) {
53             for (y = 0; y < 3; y++) {
54                 res = 0;
55                 for (z = 0; z < 3; z++) {
56                     res += matrix[x][z] * me.matrix[z][y];
57                 }
58                 out[x][y] = res;
59             }
60         }
61         me.matrix = out;
62     },
63
64     invert: function() {
65         var matrix = this.matrix,
66             a = matrix[0][0],
67             b = matrix[1][0],
68             c = matrix[0][1],
69             d = matrix[1][1],
70             e = matrix[0][2],
71             f = matrix[1][2],
72             x = a * d - b * c;
73         return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
74     },
75
76     clone: function() {
77         var matrix = this.matrix,
78             a = matrix[0][0],
79             b = matrix[1][0],
80             c = matrix[0][1],
81             d = matrix[1][1],
82             e = matrix[0][2],
83             f = matrix[1][2];
84         return new Ext.draw.Matrix(a, b, c, d, e, f);
85     },
86
87     translate: function(x, y) {
88         this.prepend(1, 0, 0, 1, x, y);
89     },
90
91     scale: function(x, y, cx, cy) {
92         var me = this;
93         if (y == null) {
94             y = x;
95         }
96         me.add(1, 0, 0, 1, cx, cy);
97         me.add(x, 0, 0, y, 0, 0);
98         me.add(1, 0, 0, 1, -cx, -cy);
99     },
100
101     rotate: function(a, x, y) {
102         a = Ext.draw.Draw.rad(a);
103         var me = this,
104             cos = +Math.cos(a).toFixed(9),
105             sin = +Math.sin(a).toFixed(9);
106         me.add(cos, sin, -sin, cos, x, y);
107         me.add(1, 0, 0, 1, -x, -y);
108     },
109
110     x: function(x, y) {
111         var matrix = this.matrix;
112         return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
113     },
114
115     y: function(x, y) {
116         var matrix = this.matrix;
117         return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
118     },
119
120     get: function(i, j) {
121         return + this.matrix[i][j].toFixed(4);
122     },
123
124     toString: function() {
125         var me = this;
126         return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
127     },
128
129     toSvg: function() {
130         var me = this;
131         return "matrix(" + [me.get(0, 0), me.get(1, 0), me.get(0, 1), me.get(1, 1), me.get(0, 2), me.get(1, 2)].join() + ")";
132     },
133
134     toFilter: function() {
135         var me = this;
136         return "progid:DXImageTransform.Microsoft.Matrix(M11=" + me.get(0, 0) +
137             ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
138             ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
139     },
140
141     offset: function() {
142         var matrix = this.matrix;
143         return [matrix[0][2].toFixed(4), matrix[1][2].toFixed(4)];
144     },
145
146     // Split matrix into Translate Scale, Shear, and Rotate
147     split: function () {
148         function norm(a) {
149             return a[0] * a[0] + a[1] * a[1];
150         }
151         function normalize(a) {
152             var mag = Math.sqrt(norm(a));
153             a[0] /= mag;
154             a[1] /= mag;
155         }
156         var matrix = this.matrix,
157             out = {
158                 translateX: matrix[0][2],
159                 translateY: matrix[1][2]
160             },
161             row;
162
163         // scale and shear
164         row = [[matrix[0][0], matrix[0][1]], [matrix[1][1], matrix[1][1]]];
165         out.scaleX = Math.sqrt(norm(row[0]));
166         normalize(row[0]);
167
168         out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
169         row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
170
171         out.scaleY = Math.sqrt(norm(row[1]));
172         normalize(row[1]);
173         out.shear /= out.scaleY;
174
175         // rotation
176         out.rotate = Math.asin(-row[0][1]);
177
178         out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
179
180         return out;
181     }
182 });