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_roundrect.h"
17 #include "js_common.h"
18 #include "js_drawing_utils.h"
19 #include "native_value.h"
20 
21 namespace OHOS::Rosen {
22 namespace Drawing {
23 thread_local napi_ref JsRoundRect::constructor_ = nullptr;
24 const std::string CLASS_NAME = "RoundRect";
Init(napi_env env,napi_value exportObj)25 napi_value JsRoundRect::Init(napi_env env, napi_value exportObj)
26 {
27     napi_property_descriptor properties[] = {
28         DECLARE_NAPI_FUNCTION("setCorner", JsRoundRect::SetCorner),
29         DECLARE_NAPI_FUNCTION("getCorner", JsRoundRect::GetCorner),
30         DECLARE_NAPI_FUNCTION("offset", JsRoundRect::Offset),
31     };
32 
33     napi_value constructor = nullptr;
34     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
35                                            sizeof(properties) / sizeof(properties[0]), properties, &constructor);
36     if (status != napi_ok) {
37         ROSEN_LOGE("JsRoundRect::Init Failed to define RoundRect class");
38         return nullptr;
39     }
40 
41     status = napi_create_reference(env, constructor, 1, &constructor_);
42     if (status != napi_ok) {
43         ROSEN_LOGE("JsRoundRect::Init Failed to create reference of constructor");
44         return nullptr;
45     }
46 
47     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
48     if (status != napi_ok) {
49         ROSEN_LOGE("JsRoundRect::Init Failed to set constructor");
50         return nullptr;
51     }
52 
53     return exportObj;
54 }
55 
Constructor(napi_env env,napi_callback_info info)56 napi_value JsRoundRect::Constructor(napi_env env, napi_callback_info info)
57 {
58     size_t argCount = ARGC_THREE;
59     napi_value jsThis = nullptr;
60     napi_value argv[ARGC_THREE] = {nullptr};
61     napi_status status = napi_get_cb_info(env, info, &argCount, argv, &jsThis, nullptr);
62     if (status != napi_ok) {
63         ROSEN_LOGE("JsRoundRect::Constructor failed to napi_get_cb_info");
64         return nullptr;
65     }
66 
67     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
68     napi_valuetype valueType = napi_undefined;
69     if (argv[0] == nullptr || napi_typeof(env, argv[0], &valueType) != napi_ok || valueType != napi_object) {
70         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
71             "JsRoundRect::Constructor Argv[0] is invalid.");
72     }
73 
74     double ltrb[ARGC_FOUR] = {0};
75     if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
76         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
77             "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
78     }
79     Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
80 
81     double xRad = 0.0;
82     GET_DOUBLE_PARAM(ARGC_ONE, xRad);
83     double yRad = 0.0;
84     GET_DOUBLE_PARAM(ARGC_TWO, yRad);
85 
86     JsRoundRect* jsRoundRect = new JsRoundRect(drawingRect, xRad, yRad);
87     status = napi_wrap(env, jsThis, jsRoundRect,
88                        JsRoundRect::Destructor, nullptr, nullptr);
89     if (status != napi_ok) {
90         delete jsRoundRect;
91         ROSEN_LOGE("JsRoundRect::Constructor Failed to wrap native instance");
92         return nullptr;
93     }
94 
95     return jsThis;
96 }
97 
Destructor(napi_env env,void * nativeObject,void * finalize)98 void JsRoundRect::Destructor(napi_env env, void* nativeObject, void* finalize)
99 {
100     (void)finalize;
101     if (nativeObject != nullptr) {
102         JsRoundRect* napi = reinterpret_cast<JsRoundRect*>(nativeObject);
103         delete napi;
104     }
105 }
106 
SetCorner(napi_env env,napi_callback_info info)107 napi_value JsRoundRect ::SetCorner(napi_env env, napi_callback_info info)
108 {
109     JsRoundRect* rect = CheckParamsAndGetThis<JsRoundRect>(env, info);
110     return (rect != nullptr) ? rect->OnSetCorner(env, info) : nullptr;
111 }
112 
OnSetCorner(napi_env env,napi_callback_info info)113 napi_value JsRoundRect ::OnSetCorner(napi_env env, napi_callback_info info)
114 {
115     napi_value argv[ARGC_THREE] = { nullptr };
116     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
117     int32_t pos = 0;
118     GET_ENUM_PARAM(ARGC_ZERO, pos, 0, static_cast<int32_t>(RoundRect::CornerPos::BOTTOM_LEFT_POS));
119     double x = 0;
120     GET_DOUBLE_PARAM(ARGC_ONE, x);
121     double y = 0;
122     GET_DOUBLE_PARAM(ARGC_TWO, y);
123 
124     m_roundRect.SetCornerRadius(static_cast<RoundRect::CornerPos>(pos), x, y);
125 
126     return nullptr;
127 }
128 
GetCorner(napi_env env,napi_callback_info info)129 napi_value JsRoundRect ::GetCorner(napi_env env, napi_callback_info info)
130 {
131     JsRoundRect* rect = CheckParamsAndGetThis<JsRoundRect>(env, info);
132     return (rect != nullptr) ? rect->OnGetCorner(env, info) : nullptr;
133 }
134 
OnGetCorner(napi_env env,napi_callback_info info)135 napi_value JsRoundRect ::OnGetCorner(napi_env env, napi_callback_info info)
136 {
137     napi_value argv[ARGC_ONE] = { nullptr };
138     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
139     int32_t pos = 0;
140     GET_ENUM_PARAM(ARGC_ZERO, pos, 0, static_cast<int32_t>(RoundRect::CornerPos::BOTTOM_LEFT_POS));
141     auto point = m_roundRect.GetCornerRadius(static_cast<RoundRect::CornerPos>(pos));
142     return ConvertPointToJsValue(env, point);
143 }
144 
Offset(napi_env env,napi_callback_info info)145 napi_value JsRoundRect ::Offset(napi_env env, napi_callback_info info)
146 {
147     JsRoundRect* rect = CheckParamsAndGetThis<JsRoundRect>(env, info);
148     return (rect != nullptr) ? rect->OnOffset(env, info) : nullptr;
149 }
150 
OnOffset(napi_env env,napi_callback_info info)151 napi_value JsRoundRect ::OnOffset(napi_env env, napi_callback_info info)
152 {
153     napi_value argv[ARGC_TWO] = { nullptr };
154     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
155     double dx = 0;
156     GET_DOUBLE_PARAM(ARGC_ZERO, dx);
157     double dy = 0;
158     GET_DOUBLE_PARAM(ARGC_ONE, dy);
159 
160     m_roundRect.Offset(dx, dy);
161 
162     return nullptr;
163 }
164 
GetRoundRect()165 const RoundRect& JsRoundRect::GetRoundRect()
166 {
167     return m_roundRect;
168 }
169 } // namespace Drawing
170 } // namespace OHOS::Rosen
171