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