Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / draw / Matrix.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /*
16  * @class Ext.draw.Matrix
17  * @private
18  */
19 Ext.define('Ext.draw.Matrix', {
20
21     /* Begin Definitions */
22
23     requires: ['Ext.draw.Draw'],
24
25     /* End Definitions */
26
27     constructor: function(a, b, c, d, e, f) {
28         if (a != null) {
29             this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
30         }
31         else {
32             this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
33         }
34     },
35
36     add: function(a, b, c, d, e, f) {
37         var me = this,
38             out = [[], [], []],
39             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
40             x,
41             y,
42             z,
43             res;
44
45         for (x = 0; x < 3; x++) {
46             for (y = 0; y < 3; y++) {
47                 res = 0;
48                 for (z = 0; z < 3; z++) {
49                     res += me.matrix[x][z] * matrix[z][y];
50                 }
51                 out[x][y] = res;
52             }
53         }
54         me.matrix = out;
55     },
56
57     prepend: function(a, b, c, d, e, f) {
58         var me = this,
59             out = [[], [], []],
60             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
61             x,
62             y,
63             z,
64             res;
65
66         for (x = 0; x < 3; x++) {
67             for (y = 0; y < 3; y++) {
68                 res = 0;
69                 for (z = 0; z < 3; z++) {
70                     res += matrix[x][z] * me.matrix[z][y];
71                 }
72                 out[x][y] = res;
73             }
74         }
75         me.matrix = out;
76     },
77
78     invert: function() {
79         var matrix = this.matrix,
80             a = matrix[0][0],
81             b = matrix[1][0],
82             c = matrix[0][1],
83             d = matrix[1][1],
84             e = matrix[0][2],
85             f = matrix[1][2],
86             x = a * d - b * c;
87         return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
88     },
89
90     clone: function() {
91         var matrix = this.matrix,
92             a = matrix[0][0],
93             b = matrix[1][0],
94             c = matrix[0][1],
95             d = matrix[1][1],
96             e = matrix[0][2],
97             f = matrix[1][2];
98         return new Ext.draw.Matrix(a, b, c, d, e, f);
99     },
100
101     translate: function(x, y) {
102         this.prepend(1, 0, 0, 1, x, y);
103     },
104
105     scale: function(x, y, cx, cy) {
106         var me = this;
107         if (y == null) {
108             y = x;
109         }
110         me.add(1, 0, 0, 1, cx, cy);
111         me.add(x, 0, 0, y, 0, 0);
112         me.add(1, 0, 0, 1, -cx, -cy);
113     },
114
115     rotate: function(a, x, y) {
116         a = Ext.draw.Draw.rad(a);
117         var me = this,
118             cos = +Math.cos(a).toFixed(9),
119             sin = +Math.sin(a).toFixed(9);
120         me.add(cos, sin, -sin, cos, x, y);
121         me.add(1, 0, 0, 1, -x, -y);
122     },
123
124     x: function(x, y) {
125         var matrix = this.matrix;
126         return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
127     },
128
129     y: function(x, y) {
130         var matrix = this.matrix;
131         return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
132     },
133
134     get: function(i, j) {
135         return + this.matrix[i][j].toFixed(4);
136     },
137
138     toString: function() {
139         var me = this;
140         return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
141     },
142
143     toSvg: function() {
144         var me = this;
145         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() + ")";
146     },
147
148     toFilter: function() {
149         var me = this;
150         return "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand',FilterType=bilinear,M11=" + me.get(0, 0) +
151             ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
152             ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
153     },
154
155     offset: function() {
156         var matrix = this.matrix;
157         return [(matrix[0][2] || 0).toFixed(4), (matrix[1][2] || 0).toFixed(4)];
158     },
159
160     // Split matrix into Translate Scale, Shear, and Rotate
161     split: function () {
162         function norm(a) {
163             return a[0] * a[0] + a[1] * a[1];
164         }
165         function normalize(a) {
166             var mag = Math.sqrt(norm(a));
167             a[0] /= mag;
168             a[1] /= mag;
169         }
170         var matrix = this.matrix,
171             out = {
172                 translateX: matrix[0][2],
173                 translateY: matrix[1][2]
174             },
175             row;
176
177         // scale and shear
178         row = [[matrix[0][0], matrix[0][1]], [matrix[1][0], matrix[1][1]]];
179         out.scaleX = Math.sqrt(norm(row[0]));
180         normalize(row[0]);
181
182         out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
183         row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
184
185         out.scaleY = Math.sqrt(norm(row[1]));
186         normalize(row[1]);
187         out.shear /= out.scaleY;
188
189         // rotation
190         out.rotate = Math.asin(-row[0][1]);
191
192         out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
193
194         return out;
195     }
196 });
197