1 /*
2  * Copyright (C) 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 "js_matrix.h"
17 #include "js_drawing_utils.h"
18 #include "native_value.h"
19 
20 static constexpr uint32_t POLY_POINT_COUNT_MAX = 4;
21 
22 namespace OHOS::Rosen {
23 namespace Drawing {
24 thread_local napi_ref JsMatrix::constructor_ = nullptr;
25 const std::string CLASS_NAME = "Matrix";
26 
27 static const napi_property_descriptor g_properties[] = {
28     DECLARE_NAPI_FUNCTION("getValue", JsMatrix::GetValue),
29     DECLARE_NAPI_FUNCTION("postRotate", JsMatrix::PostRotate),
30     DECLARE_NAPI_FUNCTION("postTranslate", JsMatrix::PostTranslate),
31     DECLARE_NAPI_FUNCTION("preRotate", JsMatrix::PreRotate),
32     DECLARE_NAPI_FUNCTION("preScale", JsMatrix::PreScale),
33     DECLARE_NAPI_FUNCTION("preTranslate", JsMatrix::PreTranslate),
34     DECLARE_NAPI_FUNCTION("setRotation", JsMatrix::SetRotation),
35     DECLARE_NAPI_FUNCTION("setScale", JsMatrix::SetScale),
36     DECLARE_NAPI_FUNCTION("setTranslation", JsMatrix::SetTranslation),
37     DECLARE_NAPI_FUNCTION("setMatrix", JsMatrix::SetMatrix),
38     DECLARE_NAPI_FUNCTION("preConcat", JsMatrix::PreConcat),
39     DECLARE_NAPI_FUNCTION("isEqual", JsMatrix::IsEqual),
40     DECLARE_NAPI_FUNCTION("invert", JsMatrix::Invert),
41     DECLARE_NAPI_FUNCTION("isIdentity", JsMatrix::IsIdentity),
42     DECLARE_NAPI_FUNCTION("mapPoints", JsMatrix::MapPoints),
43     DECLARE_NAPI_FUNCTION("postScale", JsMatrix::PostScale),
44     DECLARE_NAPI_FUNCTION("reset", JsMatrix::Reset),
45     DECLARE_NAPI_FUNCTION("getAll", JsMatrix::GetAll),
46     DECLARE_NAPI_FUNCTION("setPolyToPoly", JsMatrix::SetPolyToPoly),
47     DECLARE_NAPI_FUNCTION("setRectToRect", JsMatrix::SetRectToRect),
48     DECLARE_NAPI_FUNCTION("mapRect", JsMatrix::MapRect),
49 };
50 
Init(napi_env env,napi_value exportObj)51 napi_value JsMatrix::Init(napi_env env, napi_value exportObj)
52 {
53     napi_value constructor = nullptr;
54     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
55         sizeof(g_properties) / sizeof(g_properties[0]), g_properties, &constructor);
56     if (status != napi_ok) {
57         ROSEN_LOGE("JsMatrix::Init Failed to define Matrix class");
58         return nullptr;
59     }
60 
61     status = napi_create_reference(env, constructor, 1, &constructor_);
62     if (status != napi_ok) {
63         ROSEN_LOGE("JsMatrix::Init Failed to create reference of constructor");
64         return nullptr;
65     }
66 
67     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
68     if (status != napi_ok) {
69         ROSEN_LOGE("JsMatrix::Init Failed to set constructor");
70         return nullptr;
71     }
72 
73     return exportObj;
74 }
75 
Constructor(napi_env env,napi_callback_info info)76 napi_value JsMatrix::Constructor(napi_env env, napi_callback_info info)
77 {
78     size_t argCount = 0;
79     napi_value jsThis = nullptr;
80     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
81     if (status != napi_ok) {
82         ROSEN_LOGE("JsMatrix::Constructor failed to napi_get_cb_info");
83         return nullptr;
84     }
85 
86     JsMatrix* jsMatrix = new JsMatrix(std::make_shared<Matrix>());
87 
88     status = napi_wrap(env, jsThis, jsMatrix, JsMatrix::Destructor, nullptr, nullptr);
89     if (status != napi_ok) {
90         delete jsMatrix;
91         ROSEN_LOGE("JsMatrix::Constructor Failed to wrap native instance");
92         return nullptr;
93     }
94     return jsThis;
95 }
96 
Destructor(napi_env env,void * nativeObject,void * finalize)97 void JsMatrix::Destructor(napi_env env, void* nativeObject, void* finalize)
98 {
99     (void)finalize;
100     if (nativeObject != nullptr) {
101         JsMatrix* napi = reinterpret_cast<JsMatrix*>(nativeObject);
102         delete napi;
103     }
104 }
105 
CreateJsMatrix(napi_env env,const std::shared_ptr<Matrix> matrix)106 napi_value JsMatrix::CreateJsMatrix(napi_env env, const std::shared_ptr<Matrix> matrix)
107 {
108     napi_value constructor = nullptr;
109     napi_value result = nullptr;
110     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
111     if (status == napi_ok) {
112         auto jsMatrix = new JsMatrix(matrix);
113         napi_create_object(env, &result);
114         if (result == nullptr) {
115             delete jsMatrix;
116             ROSEN_LOGE("JsMatrix::CreateJsMatrix Create matrix object failed!");
117             return nullptr;
118         }
119         status = napi_wrap(env, result, jsMatrix, JsMatrix::Destructor, nullptr, nullptr);
120         if (status != napi_ok) {
121             delete jsMatrix;
122             ROSEN_LOGE("JsMatrix::CreateJsMatrix failed to wrap native instance");
123             return nullptr;
124         }
125         napi_define_properties(env, result, sizeof(g_properties) / sizeof(g_properties[0]), g_properties);
126         return result;
127     }
128     return result;
129 }
130 
GetValue(napi_env env,napi_callback_info info)131 napi_value JsMatrix::GetValue(napi_env env, napi_callback_info info)
132 {
133     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
134     return (me != nullptr) ? me->OnGetValue(env, info) : nullptr;
135 }
136 
OnGetValue(napi_env env,napi_callback_info info)137 napi_value JsMatrix::OnGetValue(napi_env env, napi_callback_info info)
138 {
139     if (m_matrix == nullptr) {
140         ROSEN_LOGE("JsMatrix::OnGetValue matrix is nullptr");
141         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
142     }
143 
144     napi_value argv[ARGC_ONE] = {nullptr};
145     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
146 
147     int32_t index = -1;
148     GET_INT32_PARAM(ARGC_ZERO, index);
149 
150     if (index < 0 || index >= Matrix::MATRIX_SIZE) {
151         ROSEN_LOGE("JsMatrix::OnGetValue index is out of range");
152         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
153     }
154 
155     double value = m_matrix->Get(index);
156     return GetDoubleAndConvertToJsValue(env, value);
157 }
158 
PostRotate(napi_env env,napi_callback_info info)159 napi_value JsMatrix::PostRotate(napi_env env, napi_callback_info info)
160 {
161     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
162     return (me != nullptr) ? me->OnPostRotate(env, info) : nullptr;
163 }
164 
OnPostRotate(napi_env env,napi_callback_info info)165 napi_value JsMatrix::OnPostRotate(napi_env env, napi_callback_info info)
166 {
167     if (m_matrix == nullptr) {
168         ROSEN_LOGE("JsMatrix::OnPostRotate matrix is nullptr");
169         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
170     }
171 
172     napi_value argv[ARGC_THREE] = {nullptr};
173     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
174 
175     double degree = 0.0;
176     GET_DOUBLE_PARAM(ARGC_ZERO, degree);
177     double px = 0.0;
178     GET_DOUBLE_PARAM(ARGC_ONE, px);
179     double py = 0.0;
180     GET_DOUBLE_PARAM(ARGC_TWO, py);
181 
182     JS_CALL_DRAWING_FUNC(m_matrix->PostRotate(degree, px, py));
183 
184     return nullptr;
185 }
186 
PostTranslate(napi_env env,napi_callback_info info)187 napi_value JsMatrix::PostTranslate(napi_env env, napi_callback_info info)
188 {
189     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
190     return (me != nullptr) ? me->OnPostTranslate(env, info) : nullptr;
191 }
192 
OnPostTranslate(napi_env env,napi_callback_info info)193 napi_value JsMatrix::OnPostTranslate(napi_env env, napi_callback_info info)
194 {
195     if (m_matrix == nullptr) {
196         ROSEN_LOGE("JsMatrix::OnPostTranslate matrix is nullptr");
197         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
198     }
199 
200     napi_value argv[ARGC_TWO] = {nullptr};
201     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
202 
203     double dx = 0.0;
204     GET_DOUBLE_PARAM(ARGC_ZERO, dx);
205     double dy = 0.0;
206     GET_DOUBLE_PARAM(ARGC_ONE, dy);
207 
208     JS_CALL_DRAWING_FUNC(m_matrix->PostTranslate(dx, dy));
209     return nullptr;
210 }
211 
PreRotate(napi_env env,napi_callback_info info)212 napi_value JsMatrix::PreRotate(napi_env env, napi_callback_info info)
213 {
214     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
215     return (me != nullptr) ? me->OnPreRotate(env, info) : nullptr;
216 }
217 
OnPreRotate(napi_env env,napi_callback_info info)218 napi_value JsMatrix::OnPreRotate(napi_env env, napi_callback_info info)
219 {
220     if (m_matrix == nullptr) {
221         ROSEN_LOGE("JsMatrix::OnPreRotate matrix is nullptr");
222         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
223     }
224 
225     napi_value argv[ARGC_THREE] = {nullptr};
226     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
227 
228     double degree = 0.0;
229     GET_DOUBLE_PARAM(ARGC_ZERO, degree);
230     double px = 0.0;
231     GET_DOUBLE_PARAM(ARGC_ONE, px);
232     double py = 0.0;
233     GET_DOUBLE_PARAM(ARGC_TWO, py);
234 
235     JS_CALL_DRAWING_FUNC(m_matrix->PreRotate(degree, px, py));
236 
237     return nullptr;
238 }
239 
PreScale(napi_env env,napi_callback_info info)240 napi_value JsMatrix::PreScale(napi_env env, napi_callback_info info)
241 {
242     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
243     return (me != nullptr) ? me->OnPreScale(env, info) : nullptr;
244 }
245 
OnPreScale(napi_env env,napi_callback_info info)246 napi_value JsMatrix::OnPreScale(napi_env env, napi_callback_info info)
247 {
248     if (m_matrix == nullptr) {
249         ROSEN_LOGE("JsMatrix::OnPreScale matrix is nullptr");
250         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
251     }
252 
253     napi_value argv[ARGC_FOUR] = {nullptr};
254     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
255 
256     double sx = 0.0;
257     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
258     double sy = 0.0;
259     GET_DOUBLE_PARAM(ARGC_ONE, sy);
260     double px = 0.0;
261     GET_DOUBLE_PARAM(ARGC_TWO, px);
262     double py = 0.0;
263     GET_DOUBLE_PARAM(ARGC_THREE, py);
264 
265     JS_CALL_DRAWING_FUNC(m_matrix->PreScale(sx, sy, px, py));
266 
267     return nullptr;
268 }
269 
PreTranslate(napi_env env,napi_callback_info info)270 napi_value JsMatrix::PreTranslate(napi_env env, napi_callback_info info)
271 {
272     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
273     return (me != nullptr) ? me->OnPreTranslate(env, info) : nullptr;
274 }
275 
OnPreTranslate(napi_env env,napi_callback_info info)276 napi_value JsMatrix::OnPreTranslate(napi_env env, napi_callback_info info)
277 {
278     if (m_matrix == nullptr) {
279         ROSEN_LOGE("JsMatrix::OnPreTranslate matrix is nullptr");
280         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
281     }
282 
283     napi_value argv[ARGC_TWO] = {nullptr};
284     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
285 
286     double dx = 0.0;
287     GET_DOUBLE_PARAM(ARGC_ZERO, dx);
288     double dy = 0.0;
289     GET_DOUBLE_PARAM(ARGC_ONE, dy);
290 
291     JS_CALL_DRAWING_FUNC(m_matrix->PreTranslate(dx, dy));
292 
293     return nullptr;
294 }
295 
SetRotation(napi_env env,napi_callback_info info)296 napi_value JsMatrix::SetRotation(napi_env env, napi_callback_info info)
297 {
298     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
299     return (me != nullptr) ? me->OnSetRotation(env, info) : nullptr;
300 }
301 
OnSetRotation(napi_env env,napi_callback_info info)302 napi_value JsMatrix::OnSetRotation(napi_env env, napi_callback_info info)
303 {
304     if (m_matrix == nullptr) {
305         ROSEN_LOGE("JsMatrix::OnSetRotation matrix is nullptr");
306         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
307     }
308 
309     napi_value argv[ARGC_THREE] = {nullptr};
310     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
311 
312     double degree = 0.0;
313     GET_DOUBLE_PARAM(ARGC_ZERO, degree);
314     double px = 0.0;
315     GET_DOUBLE_PARAM(ARGC_ONE, px);
316     double py = 0.0;
317     GET_DOUBLE_PARAM(ARGC_TWO, py);
318 
319     JS_CALL_DRAWING_FUNC(m_matrix->Rotate(degree, px, py));
320     return nullptr;
321 }
322 
SetScale(napi_env env,napi_callback_info info)323 napi_value JsMatrix::SetScale(napi_env env, napi_callback_info info)
324 {
325     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
326     return (me != nullptr) ? me->OnSetScale(env, info) : nullptr;
327 }
328 
OnSetScale(napi_env env,napi_callback_info info)329 napi_value JsMatrix::OnSetScale(napi_env env, napi_callback_info info)
330 {
331     if (m_matrix == nullptr) {
332         ROSEN_LOGE("JsMatrix::OnSetScale matrix is nullptr");
333         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
334     }
335 
336     napi_value argv[ARGC_FOUR] = {nullptr};
337     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
338 
339     double sx = 0.0;
340     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
341     double sy = 0.0;
342     GET_DOUBLE_PARAM(ARGC_ONE, sy);
343     double px = 0.0;
344     GET_DOUBLE_PARAM(ARGC_TWO, px);
345     double py = 0.0;
346     GET_DOUBLE_PARAM(ARGC_THREE, py);
347 
348     JS_CALL_DRAWING_FUNC(m_matrix->Scale(sx, sy, px, py));
349     return nullptr;
350 }
351 
SetTranslation(napi_env env,napi_callback_info info)352 napi_value JsMatrix::SetTranslation(napi_env env, napi_callback_info info)
353 {
354     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
355     return (me != nullptr) ? me->OnSetTranslation(env, info) : nullptr;
356 }
357 
OnSetTranslation(napi_env env,napi_callback_info info)358 napi_value JsMatrix::OnSetTranslation(napi_env env, napi_callback_info info)
359 {
360     if (m_matrix == nullptr) {
361         ROSEN_LOGE("JsMatrix::OnSetTranslation matrix is nullptr");
362         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
363     }
364 
365     napi_value argv[ARGC_TWO] = {nullptr};
366     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
367 
368     double dx = 0.0;
369     GET_DOUBLE_PARAM(ARGC_ZERO, dx);
370     double dy = 0.0;
371     GET_DOUBLE_PARAM(ARGC_ONE, dy);
372 
373     JS_CALL_DRAWING_FUNC(m_matrix->Translate(dx, dy));
374     return nullptr;
375 }
376 
SetMatrix(napi_env env,napi_callback_info info)377 napi_value JsMatrix::SetMatrix(napi_env env, napi_callback_info info)
378 {
379     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
380     return (me != nullptr) ? me->OnSetMatrix(env, info) : nullptr;
381 }
382 
OnSetMatrix(napi_env env,napi_callback_info info)383 napi_value JsMatrix::OnSetMatrix(napi_env env, napi_callback_info info)
384 {
385     if (m_matrix == nullptr) {
386         ROSEN_LOGE("JsMatrix::OnSetMatrix matrix is nullptr");
387         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
388     }
389 
390     napi_value argv[ARGC_ONE] = {nullptr};
391     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
392 
393     uint32_t arrayLength = 0;
394     if ((napi_get_array_length(env, argv[ARGC_ZERO], &arrayLength) != napi_ok)) {
395         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid array length params.");
396     }
397 
398     if (arrayLength != ARGC_NINE) { // arrayLength must be an nine number
399         ROSEN_LOGE("JsMatrix::OnSetMatrix count of array is not nine : %{public}u", arrayLength);
400         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
401             "parameter array length verification failed.");
402     }
403 
404     scalar matrixPara[arrayLength];
405     for (size_t i = 0; i < arrayLength; i++) {
406         bool hasElement = false;
407         napi_has_element(env, argv[ARGC_ZERO], i, &hasElement);
408         if (!hasElement) {
409             ROSEN_LOGE("JsMatrix::OnSetMatrix parameter check error");
410             return nullptr;
411         }
412 
413         napi_value element = nullptr;
414         napi_get_element(env, argv[ARGC_ZERO], i, &element);
415 
416         double value = 0.0;
417         ConvertFromJsNumber(env, element, value);
418         matrixPara[i] = value;
419     }
420 
421     m_matrix->SetMatrix(matrixPara[ARGC_ZERO], matrixPara[ARGC_ONE], matrixPara[ARGC_TWO],
422         matrixPara[ARGC_THREE], matrixPara[ARGC_FOUR], matrixPara[ARGC_FIVE], matrixPara[ARGC_SIX],
423         matrixPara[ARGC_SEVEN], matrixPara[ARGC_EIGHT]);
424     return nullptr;
425 }
426 
PreConcat(napi_env env,napi_callback_info info)427 napi_value JsMatrix::PreConcat(napi_env env, napi_callback_info info)
428 {
429     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
430     return (me != nullptr) ? me->OnPreConcat(env, info) : nullptr;
431 }
432 
OnPreConcat(napi_env env,napi_callback_info info)433 napi_value JsMatrix::OnPreConcat(napi_env env, napi_callback_info info)
434 {
435     if (m_matrix == nullptr) {
436         ROSEN_LOGE("JsMatrix::OnPreConcat matrix is nullptr");
437         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
438     }
439 
440     napi_value argv[ARGC_ONE] = {nullptr};
441     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
442 
443     JsMatrix* jsMatrix = nullptr;
444     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
445 
446     if (jsMatrix->GetMatrix() == nullptr) {
447         ROSEN_LOGE("JsMatrix::OnPreConcat matrix is nullptr");
448         return nullptr;
449     }
450 
451     m_matrix->PreConcat(*jsMatrix->GetMatrix());
452     return nullptr;
453 }
454 
IsEqual(napi_env env,napi_callback_info info)455 napi_value JsMatrix::IsEqual(napi_env env, napi_callback_info info)
456 {
457     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
458     return (me != nullptr) ? me->OnIsEqual(env, info) : nullptr;
459 }
460 
OnIsEqual(napi_env env,napi_callback_info info)461 napi_value JsMatrix::OnIsEqual(napi_env env, napi_callback_info info)
462 {
463     if (m_matrix == nullptr) {
464         ROSEN_LOGE("JsMatrix::OnIsEqual matrix is nullptr");
465         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
466     }
467 
468     napi_value argv[ARGC_ONE] = {nullptr};
469     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
470 
471     JsMatrix* jsMatrix = nullptr;
472     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
473 
474     if (jsMatrix->GetMatrix() == nullptr) {
475         ROSEN_LOGE("JsMatrix::OnIsEqual matrix is nullptr");
476         return CreateJsValue(env, false);
477     }
478 
479     return CreateJsValue(env, m_matrix->operator == (*jsMatrix->GetMatrix()));
480 }
481 
Invert(napi_env env,napi_callback_info info)482 napi_value JsMatrix::Invert(napi_env env, napi_callback_info info)
483 {
484     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
485     return (me != nullptr) ? me->OnInvert(env, info) : nullptr;
486 }
487 
OnInvert(napi_env env,napi_callback_info info)488 napi_value JsMatrix::OnInvert(napi_env env, napi_callback_info info)
489 {
490     if (m_matrix == nullptr) {
491         ROSEN_LOGE("JsMatrix::OnInvert matrix is nullptr");
492         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
493     }
494 
495     napi_value argv[ARGC_ONE] = {nullptr};
496     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
497 
498     JsMatrix* jsMatrix = nullptr;
499     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
500 
501     if (jsMatrix->GetMatrix() == nullptr) {
502         ROSEN_LOGE("JsMatrix::OnInvert matrix is nullptr");
503         return nullptr;
504     }
505 
506     return CreateJsValue(env, m_matrix->Invert(*jsMatrix->GetMatrix()));
507 }
508 
IsIdentity(napi_env env,napi_callback_info info)509 napi_value JsMatrix::IsIdentity(napi_env env, napi_callback_info info)
510 {
511     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
512     return (me != nullptr) ? me->OnIsIdentity(env, info) : nullptr;
513 }
514 
OnIsIdentity(napi_env env,napi_callback_info info)515 napi_value JsMatrix::OnIsIdentity(napi_env env, napi_callback_info info)
516 {
517     if (m_matrix == nullptr) {
518         ROSEN_LOGE("JsMatrix::OnIsIdentity matrix is nullptr");
519         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
520     }
521 
522     return CreateJsValue(env, m_matrix->IsIdentity());
523 }
524 
MapPoints(napi_env env,napi_callback_info info)525 napi_value JsMatrix::MapPoints(napi_env env, napi_callback_info info)
526 {
527     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
528     return (me != nullptr) ? me->OnMapPoints(env, info) : nullptr;
529 }
530 
OnMapPoints(napi_env env,napi_callback_info info)531 napi_value JsMatrix::OnMapPoints(napi_env env, napi_callback_info info)
532 {
533     if (m_matrix == nullptr) {
534         ROSEN_LOGE("JsMatrix::OnMapPoints matrix is nullptr");
535         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
536     }
537 
538     napi_value argv[ARGC_ONE] = {nullptr};
539     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
540 
541     napi_value srcArray = argv[ARGC_ZERO];
542 
543     /* Check size */
544     uint32_t srcPointsSize = 0;
545     if (napi_get_array_length(env, srcArray, &srcPointsSize) != napi_ok || (srcPointsSize == 0)) {
546         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect src array size.");
547     }
548 
549     std::vector<Point> dstPoints(srcPointsSize);
550     std::vector<Point> srcPoints(srcPointsSize);
551     /* Fill vector with data from input array */
552     if (!ConvertFromJsPointsArray(env, srcArray, srcPoints.data(), srcPointsSize)) {
553         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect src array data.");
554     }
555 
556     JS_CALL_DRAWING_FUNC(m_matrix->MapPoints(dstPoints, srcPoints, srcPointsSize));
557 
558     napi_value resultArray = nullptr;
559     if (napi_create_array_with_length(env, dstPoints.size(), &resultArray) != napi_ok) {
560         ROSEN_LOGE("JsMatrix::OnMapPoints failed to create array");
561         return nullptr;
562     }
563     for (uint32_t idx = 0; idx < dstPoints.size(); idx++) {
564         NAPI_CALL(env, napi_set_element(env, resultArray, idx, ConvertPointToJsValue(env, dstPoints.at(idx))));
565     }
566 
567     return resultArray;
568 }
569 
PostScale(napi_env env,napi_callback_info info)570 napi_value JsMatrix::PostScale(napi_env env, napi_callback_info info)
571 {
572     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
573     return (me != nullptr) ? me->OnPostScale(env, info) : nullptr;
574 }
575 
OnPostScale(napi_env env,napi_callback_info info)576 napi_value JsMatrix::OnPostScale(napi_env env, napi_callback_info info)
577 {
578     if (m_matrix == nullptr) {
579         ROSEN_LOGE("JsMatrix::OnPostScale matrix is nullptr");
580         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
581     }
582 
583     napi_value argv[ARGC_FOUR] = {nullptr};
584     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
585 
586     double sx = 0.0;
587     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
588     double sy = 0.0;
589     GET_DOUBLE_PARAM(ARGC_ONE, sy);
590     double px = 0.0;
591     GET_DOUBLE_PARAM(ARGC_TWO, px);
592     double py = 0.0;
593     GET_DOUBLE_PARAM(ARGC_THREE, py);
594 
595     JS_CALL_DRAWING_FUNC(m_matrix->PostScale(sx, sy, px, py));
596 
597     return nullptr;
598 }
599 
Reset(napi_env env,napi_callback_info info)600 napi_value JsMatrix::Reset(napi_env env, napi_callback_info info)
601 {
602     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
603     return (me != nullptr) ? me->OnReset(env, info) : nullptr;
604 }
605 
OnReset(napi_env env,napi_callback_info info)606 napi_value JsMatrix::OnReset(napi_env env, napi_callback_info info)
607 {
608     if (m_matrix == nullptr) {
609         ROSEN_LOGE("JsMatrix::OnReset matrix is nullptr");
610         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
611     }
612 
613     m_matrix->Reset();
614     return nullptr;
615 }
616 
GetAll(napi_env env,napi_callback_info info)617 napi_value JsMatrix::GetAll(napi_env env, napi_callback_info info)
618 {
619     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
620     return (me != nullptr) ? me->OnGetAll(env, info) : nullptr;
621 }
622 
OnGetAll(napi_env env,napi_callback_info info)623 napi_value JsMatrix::OnGetAll(napi_env env, napi_callback_info info)
624 {
625     if (m_matrix == nullptr) {
626         ROSEN_LOGE("JsMatrix::OnGetAll matrix is nullptr");
627         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
628     }
629 
630     Matrix::Buffer matrData;
631     m_matrix->GetAll(matrData);
632 
633     napi_value array = nullptr;
634     NAPI_CALL(env, napi_create_array_with_length(env, Matrix::MATRIX_SIZE, &array));
635     for (int i = 0; i < Matrix::MATRIX_SIZE; ++i) {
636         NAPI_CALL(env, napi_set_element(env, array, i, CreateJsValue(env, matrData[i])));
637     }
638     return array;
639 }
640 
SetPolyToPoly(napi_env env,napi_callback_info info)641 napi_value JsMatrix::SetPolyToPoly(napi_env env, napi_callback_info info)
642 {
643     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
644     return (me != nullptr) ? me->OnSetPolyToPoly(env, info) : nullptr;
645 }
646 
OnSetPolyToPoly(napi_env env,napi_callback_info info)647 napi_value JsMatrix::OnSetPolyToPoly(napi_env env, napi_callback_info info)
648 {
649     if (m_matrix == nullptr) {
650         ROSEN_LOGE("JsMatrix::OnSetPolyToPoly matrix is nullptr");
651         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
652     }
653 
654     napi_value argv[ARGC_THREE] = {nullptr};
655     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
656 
657     uint32_t count = 0;
658     GET_UINT32_PARAM(ARGC_TWO, count);
659 
660     if (count > POLY_POINT_COUNT_MAX) {
661         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
662             "Invalid param 'count' > 4");
663     }
664 
665     Drawing::Point srcPoints[POLY_POINT_COUNT_MAX];
666     if (!ConvertFromJsPointsArray(env, argv[ARGC_ZERO], srcPoints, count)) {
667         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
668             "Invalid 'src' Array<Point> type.");
669     }
670     Drawing::Point dstPoints[POLY_POINT_COUNT_MAX];
671     if (!ConvertFromJsPointsArray(env, argv[ARGC_ONE], dstPoints, count)) {
672         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
673             "Invalid 'dst' Array<Point> type.");
674     }
675 
676     bool result = m_matrix->SetPolyToPoly(srcPoints, dstPoints, count);
677     return CreateJsValue(env, result);
678 }
679 
SetRectToRect(napi_env env,napi_callback_info info)680 napi_value JsMatrix::SetRectToRect(napi_env env, napi_callback_info info)
681 {
682     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
683     return (me != nullptr) ? me->OnSetRectToRect(env, info) : nullptr;
684 }
685 
OnSetRectToRect(napi_env env,napi_callback_info info)686 napi_value JsMatrix::OnSetRectToRect(napi_env env, napi_callback_info info)
687 {
688     if (m_matrix == nullptr) {
689         ROSEN_LOGE("JsMatrix::OnSetRectToRect matrix is nullptr");
690         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
691     }
692 
693     napi_value argv[ARGC_THREE] = {nullptr};
694     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
695 
696     double ltrb[ARGC_FOUR];
697     if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
698         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
699             "Incorrect 'src' Rect type. The type of left, top, right and bottom must be number.");
700     }
701     Drawing::Rect srcRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
702     if (!ConvertFromJsRect(env, argv[ARGC_ONE], ltrb, ARGC_FOUR)) {
703         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
704             "Incorrect 'dst' Rect type. The type of left, top, right and bottom must be number.");
705     }
706     Drawing::Rect dstRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
707 
708     int32_t stf;
709     GET_ENUM_PARAM(ARGC_TWO, stf, 0, static_cast<int32_t>(ScaleToFit::END_SCALETOFIT));
710 
711     bool result = m_matrix->SetRectToRect(srcRect, dstRect, static_cast<ScaleToFit>(stf));
712     return CreateJsValue(env, result);
713 }
714 
MapRect(napi_env env,napi_callback_info info)715 napi_value JsMatrix::MapRect(napi_env env, napi_callback_info info)
716 {
717     JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
718     return (me != nullptr) ? me->OnMapRect(env, info) : nullptr;
719 }
720 
OnMapRect(napi_env env,napi_callback_info info)721 napi_value JsMatrix::OnMapRect(napi_env env, napi_callback_info info)
722 {
723     if (m_matrix == nullptr) {
724         ROSEN_LOGE("JsMatrix::OnMapRect matrix is nullptr");
725         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
726     }
727 
728     napi_value argv[ARGC_TWO] = {nullptr};
729     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
730 
731     double src[ARGC_FOUR];
732     if (!ConvertFromJsRect(env, argv[ARGC_ONE], src, ARGC_FOUR)) {
733         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
734             "JsMatrix::OnMapRect Incorrect parameter type for src rect. The types must be numbers.");
735     }
736     Rect dstRect;
737     Rect srcRect{ src[ARGC_ZERO], src[ARGC_ONE], src[ARGC_TWO], src[ARGC_THREE]};
738     auto res = CreateJsValue(env, m_matrix->MapRect(dstRect, srcRect));
739     auto objValue = argv[ARGC_ZERO];
740     if (napi_set_named_property(env, objValue, "left", CreateJsNumber(env, dstRect.GetLeft())) != napi_ok ||
741         napi_set_named_property(env, objValue, "top",  CreateJsNumber(env, dstRect.GetTop())) != napi_ok ||
742         napi_set_named_property(env, objValue, "right", CreateJsNumber(env, dstRect.GetRight())) != napi_ok ||
743         napi_set_named_property(env, objValue, "bottom", CreateJsNumber(env, dstRect.GetBottom())) != napi_ok) {
744         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
745             "JsMatrix::OnMapRect Cannot fill 'dst' Rect type.");
746     }
747     return res;
748 }
749 
~JsMatrix()750 JsMatrix::~JsMatrix()
751 {
752     m_matrix = nullptr;
753 }
754 
GetMatrix()755 std::shared_ptr<Matrix> JsMatrix::GetMatrix()
756 {
757     return m_matrix;
758 }
759 }
760 }
761