• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1describe('CanvasKit\'s Matrix Helpers', () => {
2
3  beforeEach(async () => {
4    await LoadCanvasKit;
5  });
6
7  const expectArrayCloseTo = (a, b, precision) => {
8    precision = precision || 14; // digits of precision in base 10
9    expect(a.length).toEqual(b.length);
10    for (let i=0; i<a.length; i++) {
11      expect(a[i]).toBeCloseTo(b[i], precision);
12    }
13  };
14
15  describe('3x3 matrices', () => {
16
17    it('can make a translated 3x3 matrix', () => {
18      expectArrayCloseTo(
19        CanvasKit.Matrix.translated(5, -1),
20          [1, 0,  5,
21           0, 1, -1,
22           0, 0,  1]);
23    });
24
25    it('can make a scaled 3x3 matrix', () => {
26      expectArrayCloseTo(
27        CanvasKit.Matrix.scaled(2, 3),
28          [2, 0, 0,
29           0, 3, 0,
30           0, 0, 1]);
31    });
32
33    it('can make a rotated 3x3 matrix', () => {
34      expectArrayCloseTo(
35        CanvasKit.Matrix.rotated(Math.PI, 9, 9),
36          [-1,  0, 18,
37            0, -1, 18,
38            0,  0,  1]);
39    });
40
41    it('can make a skewed 3x3 matrix', () => {
42      expectArrayCloseTo(
43        CanvasKit.Matrix.skewed(4, 3, 2, 1),
44          [1, 4, -8,
45           3, 1, -3,
46           0, 0,  1]);
47    });
48
49    it('can multiply 3x3 matrices', () => {
50      const a = [
51         0.1,  0.2,  0.3,
52         0.0,  0.6,  0.7,
53         0.9, -0.9, -0.8,
54      ];
55      const b = [
56         2.0,  3.0,  4.0,
57        -3.0, -4.0, -5.0,
58         7.0,  8.0,  9.0,
59      ];
60      const expected = [
61         1.7,  1.9,  2.1,
62         3.1,  3.2,  3.3,
63        -1.1, -0.1,  0.9,
64      ];
65      expectArrayCloseTo(
66        CanvasKit.Matrix.multiply(a, b),
67        expected);
68    });
69
70    it('satisfies the inverse rule for 3x3 matrics', () => {
71      // a matrix times its inverse is the identity matrix.
72      const a = [
73         0.1,  0.2,  0.3,
74         0.0,  0.6,  0.7,
75         0.9, -0.9, -0.8,
76      ];
77      const b = CanvasKit.Matrix.invert(a);
78      expectArrayCloseTo(
79        CanvasKit.Matrix.multiply(a, b),
80        CanvasKit.Matrix.identity());
81    });
82
83    it('maps 2D points correctly with a 3x3 matrix', () => {
84        const a = [
85           3,  0, -4,
86           0,  2, 4,
87           0,  0, 1,
88        ];
89        const points = [
90          0, 0,
91          1, 1,
92        ];
93        const expected = [
94          -4, 4,
95          -1, 6,
96        ];
97        expectArrayCloseTo(
98          CanvasKit.Matrix.mapPoints(a, points),
99          expected);
100    });
101
102  }); // describe 3x3
103  describe('4x4 matrices', () => {
104
105    it('can make a translated 4x4 matrix', () => {
106      expectArrayCloseTo(
107        CanvasKit.M44.translated([5, 6, 7]),
108          [1, 0, 0, 5,
109           0, 1, 0, 6,
110           0, 0, 1, 7,
111           0, 0, 0, 1]);
112    });
113
114    it('can make a scaled 4x4 matrix', () => {
115      expectArrayCloseTo(
116        CanvasKit.M44.scaled([5, 6, 7]),
117          [5, 0, 0, 0,
118           0, 6, 0, 0,
119           0, 0, 7, 0,
120           0, 0, 0, 1]);
121    });
122
123    it('can make a rotated 4x4 matrix', () => {
124      expectArrayCloseTo(
125        CanvasKit.M44.rotated([1,1,1], Math.PI),
126          [-1/3,  2/3,  2/3, 0,
127            2/3, -1/3,  2/3, 0,
128            2/3,  2/3, -1/3, 0,
129              0,    0,    0, 1]);
130    });
131
132    it('can make a 4x4 matrix looking from eye to center', () => {
133      eye = [1, 0, 0];
134      center = [1, 0, 1];
135      up = [0, 1, 0]
136      expectArrayCloseTo(
137        CanvasKit.M44.lookat(eye, center, up),
138          [-1,  0,  0,  1,
139            0,  1,  0,  0,
140            0,  0, -1,  0,
141            0,  0,  0,  1]);
142    });
143
144    it('can make a 4x4 prespective matrix', () => {
145      expectArrayCloseTo(
146        CanvasKit.M44.perspective(2, 10, Math.PI/2),
147          [1, 0,   0, 0,
148           0, 1,   0, 0,
149           0, 0, 1.5, 5,
150           0, 0,  -1, 1]);
151    });
152
153    it('can multiply 4x4 matrices', () => {
154      const a = [
155         0.1,  0.2,  0.3,  0.4,
156         0.0,  0.6,  0.7,  0.8,
157         0.9, -0.9, -0.8, -0.7,
158        -0.6, -0.5, -0.4, -0.3,
159      ];
160      const b = [
161         2.0,  3.0,  4.0,  5.0,
162        -3.0, -4.0, -5.0, -6.0,
163         7.0,  8.0,  9.0, 10.0,
164        -4.0, -3.0, -2.0, -1.0,
165      ];
166      const expected = [
167         0.1,  0.7,  1.3,  1.9,
168        -0.1,  0.8,  1.7,  2.6,
169         1.7,  2.0,  2.3,  2.6,
170        -1.3, -2.1, -2.9, -3.7,
171      ];
172      expectArrayCloseTo(
173        CanvasKit.M44.multiply(a, b),
174        expected);
175    });
176
177    it('satisfies the identity rule for 4x4 matrices', () => {
178      const a = [
179         0.1,  0.2,  0.3,  0.4,
180         0.0,  0.6,  0.7,  0.8,
181         0.9,  0.9, -0.8, -0.7,
182        -0.6, -0.5, -0.4, -0.3,
183      ];
184      const b = CanvasKit.M44.invert(a)
185      expectArrayCloseTo(
186        CanvasKit.M44.multiply(a, b),
187        CanvasKit.M44.identity());
188    });
189
190    it('can create a camera setup matrix', () => {
191      const camAngle = Math.PI / 12;
192      const cam = {
193        'eye'  : [0, 0, 1 / Math.tan(camAngle/2) - 1],
194        'coa'  : [0, 0, 0],
195        'up'   : [0, 1, 0],
196        'near' : 0.02,
197        'far'  : 4,
198        'angle': camAngle,
199      };
200      const mat = CanvasKit.M44.setupCamera(CanvasKit.LTRBRect(0, 0, 200, 200), 200, cam);
201      // these values came from an invocation of setupCamera visually inspected.
202      const expected = [
203          7.595754, 0, -0.5, 0,
204          0, 7.595754, -0.5, 0,
205          0, 0, 1.010050, -1324.368418,
206          0, 0, -0.005, 7.595754];
207      expectArrayCloseTo(mat, expected, 5);
208    });
209  }); // describe 4x4
210});
211