1 /*
2  * Copyright (c) 2023-2024 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 #include "drawing_matrix.h"
17 
18 #include <vector>
19 
20 #include "drawing_canvas_utils.h"
21 
22 #include "utils/matrix.h"
23 #include "utils/rect.h"
24 
25 static constexpr int POLY_POINT_COUNT_MAX = 4;
26 using namespace OHOS;
27 using namespace Rosen;
28 using namespace Drawing;
29 
CastToMatrix(OH_Drawing_Matrix * cMatrix)30 static Matrix* CastToMatrix(OH_Drawing_Matrix* cMatrix)
31 {
32     return reinterpret_cast<Matrix*>(cMatrix);
33 }
34 
CastToMatrix(const OH_Drawing_Matrix * cMatrix)35 static const Matrix* CastToMatrix(const OH_Drawing_Matrix* cMatrix)
36 {
37     return reinterpret_cast<const Matrix*>(cMatrix);
38 }
39 
CastToPoint(OH_Drawing_Point2D * cPoint)40 static Point* CastToPoint(OH_Drawing_Point2D* cPoint)
41 {
42     return reinterpret_cast<Point*>(cPoint);
43 }
44 
CastToPoint(const OH_Drawing_Point2D * cPoint)45 static const Point* CastToPoint(const OH_Drawing_Point2D* cPoint)
46 {
47     return reinterpret_cast<const Point*>(cPoint);
48 }
49 
CastToRect(OH_Drawing_Rect & cRect)50 static Rect& CastToRect(OH_Drawing_Rect& cRect)
51 {
52     return reinterpret_cast<Rect&>(cRect);
53 }
54 
CastToRect(const OH_Drawing_Rect & cRect)55 static const Rect& CastToRect(const OH_Drawing_Rect& cRect)
56 {
57     return reinterpret_cast<const Rect&>(cRect);
58 }
59 
OH_Drawing_MatrixCreate()60 OH_Drawing_Matrix* OH_Drawing_MatrixCreate()
61 {
62     return (OH_Drawing_Matrix*)new Matrix();
63 }
64 
OH_Drawing_MatrixCreateRotation(float deg,float x,float y)65 OH_Drawing_Matrix* OH_Drawing_MatrixCreateRotation(float deg, float x, float y)
66 {
67     Matrix* matrix = new Matrix();
68     matrix->Rotate(deg, x, y);
69     return (OH_Drawing_Matrix*)matrix;
70 }
71 
OH_Drawing_MatrixCreateScale(float sx,float sy,float px,float py)72 OH_Drawing_Matrix* OH_Drawing_MatrixCreateScale(float sx, float sy, float px, float py)
73 {
74     Matrix* matrix = new Matrix();
75     matrix->Scale(sx, sy, px, py);
76     return (OH_Drawing_Matrix*)matrix;
77 }
78 
OH_Drawing_MatrixCreateTranslation(float dx,float dy)79 OH_Drawing_Matrix* OH_Drawing_MatrixCreateTranslation(float dx, float dy)
80 {
81     Matrix* matrix = new Matrix();
82     matrix->Translate(dx, dy);
83     return (OH_Drawing_Matrix*)matrix;
84 }
85 
OH_Drawing_MatrixSetMatrix(OH_Drawing_Matrix * cMatrix,float scaleX,float skewX,float transX,float skewY,float scaleY,float transY,float persp0,float persp1,float persp2)86 void OH_Drawing_MatrixSetMatrix(OH_Drawing_Matrix* cMatrix, float scaleX, float skewX, float transX,
87     float skewY, float scaleY, float transY, float persp0, float persp1, float persp2)
88 {
89     Matrix* matrix = CastToMatrix(cMatrix);
90     if (matrix == nullptr) {
91         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
92         return;
93     }
94     matrix->SetMatrix(scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2);
95 }
96 
OH_Drawing_MatrixSetRectToRect(OH_Drawing_Matrix * cMatrix,const OH_Drawing_Rect * src,const OH_Drawing_Rect * dst,OH_Drawing_ScaleToFit stf)97 bool OH_Drawing_MatrixSetRectToRect(OH_Drawing_Matrix* cMatrix, const OH_Drawing_Rect* src,
98     const OH_Drawing_Rect* dst, OH_Drawing_ScaleToFit stf)
99 {
100     Matrix* matrix = CastToMatrix(cMatrix);
101     if (matrix == nullptr || src == nullptr || dst == nullptr) {
102         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
103         return false;
104     }
105     return matrix->SetRectToRect(CastToRect(*src), CastToRect(*dst), static_cast<ScaleToFit>(stf));
106 }
107 
108 
OH_Drawing_MatrixPreScale(OH_Drawing_Matrix * cMatrix,float sx,float sy,float px,float py)109 void OH_Drawing_MatrixPreScale(OH_Drawing_Matrix* cMatrix, float sx, float sy, float px, float py)
110 {
111     Matrix* matrix = CastToMatrix(cMatrix);
112     if (matrix == nullptr) {
113         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
114         return;
115     }
116     matrix->PreScale(sx, sy, px, py);
117 }
118 
OH_Drawing_MatrixPreTranslate(OH_Drawing_Matrix * cMatrix,float dx,float dy)119 void OH_Drawing_MatrixPreTranslate(OH_Drawing_Matrix* cMatrix, float dx, float dy)
120 {
121     Matrix* matrix = CastToMatrix(cMatrix);
122     if (matrix == nullptr) {
123         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
124         return;
125     }
126     matrix->PreTranslate(dx, dy);
127 }
128 
129 
OH_Drawing_MatrixPreRotate(OH_Drawing_Matrix * cMatrix,float degree,float px,float py)130 void OH_Drawing_MatrixPreRotate(OH_Drawing_Matrix* cMatrix, float degree, float px, float py)
131 {
132     Matrix* matrix = CastToMatrix(cMatrix);
133     if (matrix == nullptr) {
134         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
135         return;
136     }
137     matrix->PreRotate(degree, px, py);
138 }
139 
OH_Drawing_MatrixPostScale(OH_Drawing_Matrix * cMatrix,float sx,float sy,float px,float py)140 void OH_Drawing_MatrixPostScale(OH_Drawing_Matrix* cMatrix, float sx, float sy, float px, float py)
141 {
142     Matrix* matrix = CastToMatrix(cMatrix);
143     if (matrix == nullptr) {
144         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
145         return;
146     }
147     matrix->PostScale(sx, sy, px, py);
148 }
149 
OH_Drawing_MatrixPostTranslate(OH_Drawing_Matrix * cMatrix,float dx,float dy)150 void OH_Drawing_MatrixPostTranslate(OH_Drawing_Matrix* cMatrix, float dx, float dy)
151 {
152     Matrix* matrix = CastToMatrix(cMatrix);
153     if (matrix == nullptr) {
154         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
155         return;
156     }
157     matrix->PostTranslate(dx, dy);
158 }
159 
OH_Drawing_MatrixPostRotate(OH_Drawing_Matrix * cMatrix,float degree,float px,float py)160 void OH_Drawing_MatrixPostRotate(OH_Drawing_Matrix* cMatrix, float degree, float px, float py)
161 {
162     Matrix* matrix = CastToMatrix(cMatrix);
163     if (matrix == nullptr) {
164         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
165         return;
166     }
167     matrix->PostRotate(degree, px, py);
168 }
169 
OH_Drawing_MatrixReset(OH_Drawing_Matrix * cMatrix)170 void OH_Drawing_MatrixReset(OH_Drawing_Matrix* cMatrix)
171 {
172     Matrix* matrix = CastToMatrix(cMatrix);
173     if (matrix == nullptr) {
174         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
175         return;
176     }
177     matrix->Reset();
178 }
179 
OH_Drawing_MatrixConcat(OH_Drawing_Matrix * cTotal,const OH_Drawing_Matrix * cA,const OH_Drawing_Matrix * cB)180 void OH_Drawing_MatrixConcat(OH_Drawing_Matrix* cTotal, const OH_Drawing_Matrix* cA,
181     const OH_Drawing_Matrix* cB)
182 {
183     if (cTotal == nullptr || cA == nullptr || cB == nullptr) {
184         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
185         return;
186     }
187     Matrix* total = CastToMatrix(cTotal);
188     Matrix* a = CastToMatrix(const_cast<OH_Drawing_Matrix*>(cA));
189     Matrix* b = CastToMatrix(const_cast<OH_Drawing_Matrix*>(cB));
190     *total = *a;
191     total->PreConcat(*b);
192 }
193 
OH_Drawing_MatrixGetValue(OH_Drawing_Matrix * cMatrix,int index)194 float OH_Drawing_MatrixGetValue(OH_Drawing_Matrix* cMatrix, int index)
195 {
196     if (cMatrix == nullptr) {
197         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
198         return 0;
199     }
200 
201     // 3x3 matrix index is between 0-8
202     if (index < 0 || index > 8) {
203         g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
204         return 0;
205     }
206     Matrix* matrix = CastToMatrix(cMatrix);
207     return matrix->Get(index);
208 }
209 
OH_Drawing_MatrixRotate(OH_Drawing_Matrix * cMatrix,float degree,float px,float py)210 void OH_Drawing_MatrixRotate(OH_Drawing_Matrix* cMatrix, float degree, float px, float py)
211 {
212     Matrix* matrix = CastToMatrix(cMatrix);
213     if (matrix == nullptr) {
214         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
215         return;
216     }
217     matrix->Rotate(degree, px, py);
218 }
219 
OH_Drawing_MatrixTranslate(OH_Drawing_Matrix * cMatrix,float dx,float dy)220 void OH_Drawing_MatrixTranslate(OH_Drawing_Matrix* cMatrix, float dx, float dy)
221 {
222     Matrix* matrix = CastToMatrix(cMatrix);
223     if (matrix == nullptr) {
224         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
225         return;
226     }
227     matrix->Translate(dx, dy);
228 }
229 
OH_Drawing_MatrixScale(OH_Drawing_Matrix * cMatrix,float sx,float sy,float px,float py)230 void OH_Drawing_MatrixScale(OH_Drawing_Matrix* cMatrix, float sx, float sy, float px, float py)
231 {
232     Matrix* matrix = CastToMatrix(cMatrix);
233     if (matrix == nullptr) {
234         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
235         return;
236     }
237     matrix->Scale(sx, sy, px, py);
238 }
239 
OH_Drawing_MatrixInvert(OH_Drawing_Matrix * cMatrix,OH_Drawing_Matrix * inverse)240 bool OH_Drawing_MatrixInvert(OH_Drawing_Matrix* cMatrix, OH_Drawing_Matrix* inverse)
241 {
242     Matrix* matrix = CastToMatrix(cMatrix);
243     if (matrix == nullptr) {
244         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
245         return false;
246     }
247     Matrix* inverseMatrix = CastToMatrix(inverse);
248     if (inverseMatrix == nullptr) {
249         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
250         return false;
251     }
252     return matrix->Invert(*inverseMatrix);
253 }
254 
OH_Drawing_MatrixIsEqual(OH_Drawing_Matrix * cMatrix,OH_Drawing_Matrix * other)255 bool OH_Drawing_MatrixIsEqual(OH_Drawing_Matrix* cMatrix, OH_Drawing_Matrix* other)
256 {
257     Matrix* matrix = CastToMatrix(cMatrix);
258     if (matrix == nullptr) {
259         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
260         return false;
261     }
262     Matrix* otherMatrix = CastToMatrix(other);
263     if (otherMatrix == nullptr) {
264         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
265         return false;
266     }
267     return (*matrix == *otherMatrix);
268 }
269 
OH_Drawing_MatrixSetPolyToPoly(OH_Drawing_Matrix * cMatrix,const OH_Drawing_Point2D * src,const OH_Drawing_Point2D * dst,uint32_t count)270 bool OH_Drawing_MatrixSetPolyToPoly(OH_Drawing_Matrix* cMatrix, const OH_Drawing_Point2D* src,
271     const OH_Drawing_Point2D* dst, uint32_t count)
272 {
273     Matrix* matrix = CastToMatrix(cMatrix);
274     if (matrix == nullptr) {
275         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
276         return false;
277     }
278     if (count > POLY_POINT_COUNT_MAX) {
279         g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
280         return false;
281     }
282     return matrix->SetPolyToPoly(CastToPoint(src), CastToPoint(dst), count);
283 }
284 
OH_Drawing_MatrixMapPoints(const OH_Drawing_Matrix * cMatrix,const OH_Drawing_Point2D * src,OH_Drawing_Point2D * dst,int count)285 void OH_Drawing_MatrixMapPoints(const OH_Drawing_Matrix* cMatrix, const OH_Drawing_Point2D* src,
286     OH_Drawing_Point2D* dst, int count)
287 {
288     if (src == nullptr || dst == nullptr || count <= 0) {
289         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
290         return;
291     }
292     const Matrix* matrix = CastToMatrix(cMatrix);
293     if (matrix == nullptr) {
294         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
295         return;
296     }
297     const Point* srcTemp = CastToPoint(src);
298     Point* dstTemp = CastToPoint(dst);
299     std::vector<Point> srcPoints(count);
300     std::vector<Point> dstPoints(count);
301     for (int idx = 0; idx < count; idx++) {
302         srcPoints[idx] = srcTemp[idx];
303         dstPoints[idx] = dstTemp[idx];
304     }
305     matrix->MapPoints(dstPoints, srcPoints, count);
306     for (int idx = 0; idx < count; idx++) {
307         dstTemp[idx] = dstPoints[idx];
308     }
309 }
310 
OH_Drawing_MatrixMapRect(const OH_Drawing_Matrix * cMatrix,const OH_Drawing_Rect * src,OH_Drawing_Rect * dst)311 bool OH_Drawing_MatrixMapRect(const OH_Drawing_Matrix* cMatrix, const OH_Drawing_Rect* src, OH_Drawing_Rect* dst)
312 {
313     if (src == nullptr || dst == nullptr) {
314         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
315         return false;
316     }
317     const Matrix* matrix = CastToMatrix(cMatrix);
318     if (matrix == nullptr) {
319         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
320         return false;
321     }
322     return matrix->MapRect(CastToRect(*dst), CastToRect(*src));
323 }
324 
OH_Drawing_MatrixIsIdentity(OH_Drawing_Matrix * cMatrix)325 bool OH_Drawing_MatrixIsIdentity(OH_Drawing_Matrix* cMatrix)
326 {
327     Matrix* matrix = CastToMatrix(cMatrix);
328     if (matrix == nullptr) {
329         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
330         return false;
331     }
332     return matrix->IsIdentity();
333 }
334 
OH_Drawing_MatrixGetAll(OH_Drawing_Matrix * cMatrix,float value[9])335 OH_Drawing_ErrorCode OH_Drawing_MatrixGetAll(OH_Drawing_Matrix* cMatrix, float value[9])
336 {
337     Matrix* matrix = CastToMatrix(cMatrix);
338     if (matrix == nullptr || value == nullptr) {
339         return OH_DRAWING_ERROR_INVALID_PARAMETER;
340     }
341     std::array<float, 9> buffer; // 9:size of buffer
342     matrix->GetAll(buffer);
343     for (int i = 0; i < 9; ++i) { // 9:size of value
344         value[i] = buffer[i];
345     }
346     return OH_DRAWING_SUCCESS;
347 }
348 
OH_Drawing_MatrixDestroy(OH_Drawing_Matrix * cMatrix)349 void OH_Drawing_MatrixDestroy(OH_Drawing_Matrix* cMatrix)
350 {
351     if (!cMatrix) {
352         return;
353     }
354     delete CastToMatrix(cMatrix);
355 }
356