1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef MMI_MATRIX3_H
17 #define MMI_MATRIX3_H
18 
19 #define USE_MATH_DEFINES
20 #include <cmath>
21 #include <vector>
22 
23 #include "mmi_vector2.h"
24 #include "mmi_vector3.h"
25 
26 // column-major order
27 namespace OHOS {
28 namespace MMI {
29 inline constexpr int32_t MATRIX3_SIZE { 9 };
30 template<typename T>
31 class Matrix3 {
32 public:
33     static const Matrix3 ZERO;
34     static const Matrix3 IDENTITY;
35     Matrix3();
36     Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22);
37     Matrix3(std::vector<T> M);
38 
39     Matrix3(const Matrix3& matrix) noexcept = default;
40 
41     explicit Matrix3(const T* v);
42 
43     ~Matrix3();
44     T Trace() const;
45     static int Index(int row, int col);
46     void SetIdentity();
47     void SetZero();
48     bool IsIdentity() const;
49     Matrix3 Inverse() const;
50     Matrix3 Multiply(const Matrix3& other) const;
51 
52     Matrix3 operator+(const Matrix3& other) const;
53     Matrix3 operator-(const Matrix3& other) const;
54     Matrix3 operator-() const;
55     Matrix3 operator*(const Matrix3& other) const;
56     Vector3<T> operator*(const Vector3<T>& other) const;
57     Matrix3 operator*(T scale) const;
58     T* operator[](int col);
59     Matrix3& operator=(const Matrix3& other);
60     Matrix3& operator+=(const Matrix3& other);
61     Matrix3& operator-=(const Matrix3& other);
62     Matrix3& operator*=(const Matrix3& other);
63     Matrix3& operator*=(T scale);
64     bool operator==(const Matrix3& other) const;
65     bool operator!=(const Matrix3& other) const;
66     bool IsNearEqual(const Matrix3& other, T threshold = std::numeric_limits<T>::epsilon()) const;
67     T* GetData();
68     const T* GetConstData() const;
69     T Determinant() const;
70     Matrix3 Transpose() const;
71     Matrix3 Translate(const Vector2<T>& vec) const;
72     Matrix3 Rotate(T angle) const;
73     Matrix3 Rotate(T angle, T pivotx, T pivoty) const;
74     Matrix3 Scale(const Vector2<T>& vec) const;
75     Matrix3 Scale(const Vector2<T>& vec, T pivotx, T pivoty) const;
76     Matrix3 ShearX(T y) const;
77     Matrix3 ShearY(T x) const;
78 
79 protected:
80     T data_[MATRIX3_SIZE] = { 0 };
81 };
82 
83 typedef Matrix3<float> Matrix3f;
84 typedef Matrix3<double> Matrix3d;
85 
86 template<typename T>
87 const Matrix3<T> Matrix3<T>::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0);
88 
89 template<typename T>
90 const Matrix3<T> Matrix3<T>::IDENTITY(1, 0, 0, 0, 1, 0, 0, 0, 1);
91 
92 template<typename T>
Matrix3()93 Matrix3<T>::Matrix3()
94 {}
95 
96 template<typename T>
Matrix3(T m00,T m01,T m02,T m10,T m11,T m12,T m20,T m21,T m22)97 Matrix3<T>::Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22)
98 {
99     data_[0] = m00;
100     data_[1] = m01;
101     data_[2] = m02;
102 
103     data_[3] = m10;
104     data_[4] = m11;
105     data_[5] = m12;
106 
107     data_[6] = m20;
108     data_[7] = m21;
109     data_[8] = m22;
110 }
111 
112 template<typename T>
Matrix3(std::vector<T> matrix)113 Matrix3<T>::Matrix3(std::vector<T> matrix)
114 {
115     if (matrix.size() != MATRIX3_SIZE) {
116         Matrix3();
117     } else {
118         for (size_t i = 0; i < MATRIX3_SIZE; i++) {
119             data_[i] = matrix[i];
120         }
121     }
122 }
123 
124 template<typename T>
Matrix3(const T * v)125 Matrix3<T>::Matrix3(const T* v)
126 {
127     std::copy_n(v, std::size(data_), data_);
128 }
129 
130 template<typename T>
~Matrix3()131 Matrix3<T>::~Matrix3()
132 {}
133 
134 template<typename T>
Trace()135 T Matrix3<T>::Trace() const
136 {
137     T rTrace = 0.0;
138     rTrace += data_[0];
139     rTrace += data_[4];
140     rTrace += data_[8];
141     return rTrace;
142 }
143 
144 template<typename T>
Index(int row,int col)145 int Matrix3<T>::Index(int row, int col)
146 {
147     return (col * 3) + row;
148 }
149 
150 template<typename T>
SetIdentity()151 void Matrix3<T>::SetIdentity()
152 {
153     *this = IDENTITY;
154 }
155 
156 template<typename T>
SetZero()157 void Matrix3<T>::SetZero()
158 {
159     *this = ZERO;
160 }
161 
162 template<typename T>
IsIdentity()163 bool Matrix3<T>::IsIdentity() const
164 {
165     return (MMI_EQ<T>(data_[0], 1.0)) && (MMI_EQ<T>(data_[1], 0.0)) && (MMI_EQ<T>(data_[2], 0.0)) &&
166            (MMI_EQ<T>(data_[3], 0.0)) && (MMI_EQ<T>(data_[4], 1.0)) && (MMI_EQ<T>(data_[5], 0.0)) &&
167            (MMI_EQ<T>(data_[6], 0.0)) && (MMI_EQ<T>(data_[7], 0.0)) && (MMI_EQ<T>(data_[8], 1.0));
168 }
169 
170 template<typename T>
Inverse()171 Matrix3<T> Matrix3<T>::Inverse() const
172 {
173     T det = Determinant();
174     if (MMI_EQ<T>(det, 0.0)) {
175         return Matrix3<T>(*this);
176     }
177 
178     const T invDet = 1.0f / det;
179     const T* data = data_;
180 
181     T iX = invDet * (data[4] * data[8] - data[5] * data[7]);
182     T iY = invDet * (data[2] * data[7] - data[1] * data[8]);
183     T iZ = invDet * (data[1] * data[5] - data[2] * data[4]);
184     T jX = invDet * (data[5] * data[6] - data[3] * data[8]);
185     T jY = invDet * (data[0] * data[8] - data[2] * data[6]);
186     T jZ = invDet * (data[2] * data[3] - data[0] * data[5]);
187     T kX = invDet * (data[3] * data[7] - data[4] * data[6]);
188     T kY = invDet * (data[1] * data[6] - data[0] * data[7]);
189     T kZ = invDet * (data[0] * data[4] - data[1] * data[3]);
190 
191     return Matrix3<T>(iX, iY, iZ, jX, jY, jZ, kX, kY, kZ);
192 }
193 
194 template<typename T>
Multiply(const Matrix3<T> & other)195 Matrix3<T> Matrix3<T>::Multiply(const Matrix3<T>& other) const
196 {
197     Matrix3<T> rMulti;
198     T* rData = rMulti.data_;
199     const T* oData = other.data_;
200 
201     rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
202     rData[3] = data_[0] * oData[3] + data_[3] * oData[4] + data_[6] * oData[5];
203     rData[6] = data_[0] * oData[6] + data_[3] * oData[7] + data_[6] * oData[8];
204 
205     rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
206     rData[4] = data_[1] * oData[3] + data_[4] * oData[4] + data_[7] * oData[5];
207     rData[7] = data_[1] * oData[6] + data_[4] * oData[7] + data_[7] * oData[8];
208 
209     rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
210     rData[5] = data_[2] * oData[3] + data_[5] * oData[4] + data_[8] * oData[5];
211     rData[8] = data_[2] * oData[6] + data_[5] * oData[7] + data_[8] * oData[8];
212     return rMulti;
213 }
214 
215 template<typename T>
216 Matrix3<T> Matrix3<T>::operator+(const Matrix3<T>& other) const
217 {
218     Matrix3<T> rMat3Add;
219     T* rMat3Data = rMat3Add.data_;
220     const T* oData = other.data_;
221 
222     rMat3Data[0] = data_[0] + oData[0];
223     rMat3Data[1] = data_[1] + oData[1];
224     rMat3Data[2] = data_[2] + oData[2];
225     rMat3Data[3] = data_[3] + oData[3];
226     rMat3Data[4] = data_[4] + oData[4];
227     rMat3Data[5] = data_[5] + oData[5];
228     rMat3Data[6] = data_[6] + oData[6];
229     rMat3Data[7] = data_[7] + oData[7];
230     rMat3Data[8] = data_[8] + oData[8];
231 
232     return rMat3Add;
233 }
234 
235 template<typename T>
236 Matrix3<T> Matrix3<T>::operator-(const Matrix3<T>& other) const
237 {
238     return *this + (-other);
239 }
240 
241 template<typename T>
242 Matrix3<T> Matrix3<T>::operator-() const
243 {
244     Matrix3<T> rMat3Sub;
245     T* rMat3Data = rMat3Sub.data_;
246 
247     rMat3Data[0] = -data_[0];
248     rMat3Data[1] = -data_[1];
249     rMat3Data[2] = -data_[2];
250     rMat3Data[3] = -data_[3];
251     rMat3Data[4] = -data_[4];
252     rMat3Data[5] = -data_[5];
253     rMat3Data[6] = -data_[6];
254     rMat3Data[7] = -data_[7];
255     rMat3Data[8] = -data_[8];
256 
257     return rMat3Sub;
258 }
259 
260 template<typename T>
261 Matrix3<T> Matrix3<T>::operator*(const Matrix3<T>& other) const
262 {
263     return Multiply(other);
264 }
265 
266 template<typename T>
267 Vector3<T> Matrix3<T>::operator*(const Vector3<T>& other) const
268 {
269     Vector3<T> rMulti;
270     T* rData = rMulti.data_;
271     const T* oData = other.data_;
272     rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
273 
274     rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
275 
276     rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
277     return rMulti;
278 }
279 
280 template<typename T>
281 Matrix3<T> Matrix3<T>::operator*(T scale) const
282 {
283     Matrix3<T> rMulti;
284     T* rData = rMulti.data_;
285     rData[0] = data_[0] * scale;
286     rData[1] = data_[1] * scale;
287     rData[2] = data_[2] * scale;
288     rData[3] = data_[3] * scale;
289     rData[4] = data_[4] * scale;
290     rData[5] = data_[5] * scale;
291     rData[6] = data_[6] * scale;
292     rData[7] = data_[7] * scale;
293     rData[8] = data_[8] * scale;
294 
295     return rMulti;
296 }
297 
298 template<typename T>
299 T* Matrix3<T>::operator[](int col)
300 {
301     return &data_[col * 3];
302 }
303 
304 template<typename T>
305 Matrix3<T>& Matrix3<T>::operator=(const Matrix3<T>& other)
306 {
307     const T* oMat3Data = other.data_;
308     data_[0] = oMat3Data[0];
309     data_[1] = oMat3Data[1];
310     data_[2] = oMat3Data[2];
311     data_[3] = oMat3Data[3];
312     data_[4] = oMat3Data[4];
313     data_[5] = oMat3Data[5];
314     data_[6] = oMat3Data[6];
315     data_[7] = oMat3Data[7];
316     data_[8] = oMat3Data[8];
317 
318     return *this;
319 }
320 
321 template<typename T>
322 Matrix3<T>& Matrix3<T>::operator+=(const Matrix3<T>& other)
323 {
324     const T* oData = other.data_;
325 
326     data_[0] += oData[0];
327     data_[1] += oData[1];
328     data_[2] += oData[2];
329     data_[3] += oData[3];
330     data_[4] += oData[4];
331     data_[5] += oData[5];
332     data_[6] += oData[6];
333     data_[7] += oData[7];
334     data_[8] += oData[8];
335 
336     return *this;
337 }
338 
339 template<typename T>
340 Matrix3<T>& Matrix3<T>::operator-=(const Matrix3<T>& other)
341 {
342     const T* oData = other.data_;
343 
344     data_[0] -= oData[0];
345     data_[1] -= oData[1];
346     data_[2] -= oData[2];
347     data_[3] -= oData[3];
348     data_[4] -= oData[4];
349     data_[5] -= oData[5];
350     data_[6] -= oData[6];
351     data_[7] -= oData[7];
352     data_[8] -= oData[8];
353 
354     return *this;
355 }
356 
357 template<typename T>
358 Matrix3<T>& Matrix3<T>::operator*=(const Matrix3<T>& other)
359 {
360     return (*this = *this * other);
361 }
362 
363 template<typename T>
364 Matrix3<T>& Matrix3<T>::operator*=(T scale)
365 {
366     data_[0] *= scale;
367     data_[1] *= scale;
368     data_[2] *= scale;
369     data_[3] *= scale;
370     data_[4] *= scale;
371     data_[5] *= scale;
372     data_[6] *= scale;
373     data_[7] *= scale;
374     data_[8] *= scale;
375     return *this;
376 }
377 
378 template<typename T>
379 bool Matrix3<T>::operator==(const Matrix3& other) const
380 {
381     const T* oData = other.data_;
382 
383     return (MMI_EQ<T>(data_[0], oData[0])) && (MMI_EQ<T>(data_[1], oData[1])) &&
384            (MMI_EQ<T>(data_[2], oData[2])) && (MMI_EQ<T>(data_[3], oData[3])) &&
385            (MMI_EQ<T>(data_[4], oData[4])) && (MMI_EQ<T>(data_[5], oData[5])) &&
386            (MMI_EQ<T>(data_[6], oData[6])) && (MMI_EQ<T>(data_[7], oData[7])) && (MMI_EQ<T>(data_[8], oData[8]));
387 }
388 
389 template<typename T>
390 bool Matrix3<T>::operator!=(const Matrix3& other) const
391 {
392     return !operator==(other);
393 }
394 
395 template<typename T>
IsNearEqual(const Matrix3 & other,T threshold)396 bool Matrix3<T>::IsNearEqual(const Matrix3& other, T threshold) const
397 {
398     const T* otherData = other.data_;
399     auto result = std::equal(data_, data_ + 8, otherData,
400         [&threshold](const T& left, const T& right) { return MMI_EQ<T>(left, right, threshold); });
401     return result;
402 }
403 
404 template<typename T>
GetData()405 inline T* Matrix3<T>::GetData()
406 {
407     return data_;
408 }
409 
410 template<typename T>
GetConstData()411 const T* Matrix3<T>::GetConstData() const
412 {
413     return data_;
414 }
415 
416 template<typename T>
Determinant()417 T Matrix3<T>::Determinant() const
418 {
419     T x = data_[0] * ((data_[4] * data_[8]) - (data_[5] * data_[7]));
420     T y = data_[1] * ((data_[3] * data_[8]) - (data_[5] * data_[6]));
421     T z = data_[2] * ((data_[3] * data_[7]) - (data_[4] * data_[6]));
422     return x - y + z;
423 }
424 
425 template<typename T>
Transpose()426 Matrix3<T> Matrix3<T>::Transpose() const
427 {
428     Matrix3<T> rTrans;
429     T* rData = rTrans.data_;
430     rData[0] = data_[0];
431     rData[1] = data_[3];
432     rData[2] = data_[6];
433     rData[3] = data_[1];
434     rData[4] = data_[4];
435     rData[5] = data_[7];
436     rData[6] = data_[2];
437     rData[7] = data_[5];
438     rData[8] = data_[8];
439     return rTrans;
440 }
441 
442 template<typename T>
Translate(const Vector2<T> & vec)443 Matrix3<T> Matrix3<T>::Translate(const Vector2<T>& vec) const
444 {
445     Matrix3<T> rTrans(*this);
446     T* rData = rTrans.data_;
447 
448     rData[6] = data_[0] * vec[0] + data_[3] * vec[1] + data_[6];
449     rData[7] = data_[1] * vec[0] + data_[4] * vec[1] + data_[7];
450     rData[8] = data_[2] * vec[0] + data_[5] * vec[1] + data_[8];
451     return rTrans;
452 }
453 
454 template<typename T>
Rotate(T angle)455 Matrix3<T> Matrix3<T>::Rotate(T angle) const
456 {
457     T a = angle;
458     T c = cos(a);
459     T s = sin(a);
460 
461     Matrix3<T> rRotate(*this);
462     T* rData = rRotate.data_;
463     rData[0] = data_[0] * c + data_[3] * s;
464     rData[1] = data_[1] * c + data_[4] * s;
465     rData[2] = data_[2] * c + data_[5] * s;
466 
467     rData[3] = data_[0] * -s + data_[3] * c;
468     rData[4] = data_[1] * -s + data_[4] * c;
469     rData[5] = data_[2] * -s + data_[5] * c;
470     return rRotate;
471 }
472 
473 template<typename T>
Rotate(T angle,T pivotx,T pivoty)474 Matrix3<T> Matrix3<T>::Rotate(T angle, T pivotx, T pivoty) const
475 {
476     T a = angle;
477     T c = cos(a);
478     T s = sin(a);
479     T dx = s * pivoty + (1 - c) * pivotx;
480     T dy = -s * pivotx + (1 - c) * pivoty;
481 
482     Matrix3<T> rRotate(*this);
483     T* rData = rRotate.data_;
484     rData[0] = data_[0] * c + data_[3] * s;
485     rData[1] = data_[1] * c + data_[4] * s;
486     rData[2] = data_[2] * c + data_[5] * s;
487 
488     rData[3] = data_[0] * -s + data_[3] * c;
489     rData[4] = data_[1] * -s + data_[4] * c;
490     rData[5] = data_[2] * -s + data_[5] * c;
491 
492     rData[6] = data_[0] * dx + data_[3] * dy + data_[6];
493     rData[7] = data_[1] * dx + data_[4] * dy + data_[7];
494     rData[8] = data_[2] * dx + data_[5] * dy + data_[8];
495     return rRotate;
496 }
497 
498 template<typename T>
Scale(const Vector2<T> & vec)499 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& vec) const
500 {
501     Matrix3<T> rScale(*this);
502     T* rData = rScale.data_;
503     rData[0] = data_[0] * vec[0];
504     rData[1] = data_[1] * vec[0];
505     rData[2] = data_[2] * vec[0];
506 
507     rData[3] = data_[3] * vec[1];
508     rData[4] = data_[4] * vec[1];
509     rData[5] = data_[5] * vec[1];
510     return rScale;
511 }
512 
513 template<typename T>
Scale(const Vector2<T> & vec,T pivotx,T pivoty)514 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& vec, T pivotx, T pivoty) const
515 {
516     T dx = pivotx - vec[0] * pivotx;
517     T dy = pivoty - vec[1] * pivoty;
518 
519     Matrix3<T> rScale(*this);
520     T* rData = rScale.data_;
521     rData[0] = data_[0] * vec[0];
522     rData[1] = data_[1] * vec[0];
523     rData[2] = data_[2] * vec[0];
524 
525     rData[3] = data_[3] * vec[1];
526     rData[4] = data_[4] * vec[1];
527     rData[5] = data_[5] * vec[1];
528 
529     rData[6] = data_[0] * dx + data_[3] * dy + data_[6];
530     rData[7] = data_[1] * dx + data_[4] * dy + data_[7];
531     rData[8] = data_[2] * dx + data_[5] * dy + data_[8];
532     return rScale;
533 }
534 
535 template<typename T>
ShearX(T y)536 Matrix3<T> Matrix3<T>::ShearX(T y) const
537 {
538     Matrix3<T> rShear(Matrix3<T>::IDENTITY);
539     rShear.data_[1] = y;
540     return (*this) * rShear;
541 }
542 
543 template<typename T>
ShearY(T x)544 Matrix3<T> Matrix3<T>::ShearY(T x) const
545 {
546     Matrix3<T> rShear(Matrix3<T>::IDENTITY);
547     rShear.data_[3] = x;
548     return (*this) * rShear;
549 }
550 } // namespace Rosen
551 } // namespace OHOS
552 #endif // RENDER_SERVICE_CLIENT_CORE_COMMON_RS_MATRIX3_H
553