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_run.h"
17 #include "napi_common.h"
18 #include "utils/text_log.h"
19 #include "canvas_napi/js_canvas.h"
20 #include "font_napi/js_font.h"
21 #include "recording/recording_canvas.h"
22
23 namespace OHOS::Rosen {
24 thread_local napi_ref JsRun::constructor_ = nullptr;
25 const std::string CLASS_NAME = "Run";
Constructor(napi_env env,napi_callback_info info)26 napi_value JsRun::Constructor(napi_env env, napi_callback_info info)
27 {
28 size_t argCount = 0;
29 napi_value jsThis = nullptr;
30 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
31 if (status != napi_ok) {
32 TEXT_LOGE("JsRun::Constructor failed to napi_get_cb_info");
33 return nullptr;
34 }
35
36 JsRun* jsRun = new(std::nothrow) JsRun();
37 if (!jsRun) {
38 TEXT_LOGE("JsRun::Constructor failed to create JsRun");
39 return nullptr;
40 }
41
42 status = napi_wrap(env, jsThis, jsRun,
43 JsRun::Destructor, nullptr, nullptr);
44 if (status != napi_ok) {
45 delete jsRun;
46 TEXT_LOGE("JsRun::Constructor Failed to wrap native instance");
47 return nullptr;
48 }
49
50 return jsThis;
51 }
52
Init(napi_env env,napi_value exportObj)53 napi_value JsRun::Init(napi_env env, napi_value exportObj)
54 {
55 napi_property_descriptor properties[] = {
56 DECLARE_NAPI_FUNCTION("getGlyphCount", JsRun::GetGlyphCount),
57 DECLARE_NAPI_FUNCTION("getGlyphs", JsRun::GetGlyphs),
58 DECLARE_NAPI_FUNCTION("getPositions", JsRun::GetPositions),
59 DECLARE_NAPI_FUNCTION("getOffsets", JsRun::GetOffsets),
60 DECLARE_NAPI_FUNCTION("getFont", JsRun::GetFont),
61 DECLARE_NAPI_FUNCTION("paint", JsRun::Paint),
62 };
63
64 napi_value constructor = nullptr;
65 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
66 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
67 if (status != napi_ok) {
68 TEXT_LOGE("JsRun::Init Failed to define JsRun class");
69 return nullptr;
70 }
71
72 status = napi_create_reference(env, constructor, 1, &constructor_);
73 if (status != napi_ok) {
74 TEXT_LOGE("JsRun::Init Failed to create reference of constructor");
75 return nullptr;
76 }
77
78 status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
79 if (status != napi_ok) {
80 TEXT_LOGE("JsRun::Init Failed to set constructor");
81 return nullptr;
82 }
83
84 return exportObj;
85 }
86
Destructor(napi_env env,void * nativeObject,void * finalize)87 void JsRun::Destructor(napi_env env, void* nativeObject, void* finalize)
88 {
89 (void)finalize;
90 if (nativeObject != nullptr) {
91 JsRun* jsRun = reinterpret_cast<JsRun*>(nativeObject);
92 delete jsRun;
93 }
94 }
95
CreateRun(napi_env env,napi_callback_info info)96 napi_value JsRun::CreateRun(napi_env env, napi_callback_info info)
97 {
98 napi_value result = nullptr;
99 napi_value constructor = nullptr;
100 napi_status status = napi_get_reference_value(env, constructor_, &constructor);
101 if (status != napi_ok) {
102 TEXT_LOGE("Failed to get the representation of constructor object");
103 return nullptr;
104 }
105
106 status = napi_new_instance(env, constructor, 0, nullptr, &result);
107 if (status != napi_ok) {
108 TEXT_LOGE("Failed to instantiate JavaScript font instance");
109 return nullptr;
110 }
111 return result;
112 }
113
JsRun()114 JsRun::JsRun()
115 {
116 }
117
SetRun(std::unique_ptr<Run> run)118 void JsRun::SetRun(std::unique_ptr<Run> run)
119 {
120 run_ = std::move(run);
121 }
122
GetGlyphCount(napi_env env,napi_callback_info info)123 napi_value JsRun::GetGlyphCount(napi_env env, napi_callback_info info)
124 {
125 JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
126 return (me != nullptr) ? me->OnGetGlyphCount(env, info) : nullptr;
127 }
128
OnGetGlyphCount(napi_env env,napi_callback_info info)129 napi_value JsRun::OnGetGlyphCount(napi_env env, napi_callback_info info)
130 {
131 if (!run_) {
132 TEXT_LOGE("JsRun::OnGetGlyphCount run is nullptr");
133 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetGlyphCount run is nullptr.");
134 }
135 int64_t count = static_cast<int64_t>(run_->GetGlyphCount());
136 return CreateJsNumber(env, count);
137 }
138
GetGlyphs(napi_env env,napi_callback_info info)139 napi_value JsRun::GetGlyphs(napi_env env, napi_callback_info info)
140 {
141 JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
142 return (me != nullptr) ? me->OnGetGlyphs(env, info) : nullptr;
143 }
144
OnGetGlyphs(napi_env env,napi_callback_info info)145 napi_value JsRun::OnGetGlyphs(napi_env env, napi_callback_info info)
146 {
147 if (!run_) {
148 TEXT_LOGE("Failed run is nullptr");
149 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr");
150 }
151
152 std::vector<uint16_t> glyphs = run_->GetGlyphs();
153 napi_value napiGlyphs = nullptr;
154 NAPI_CALL(env, napi_create_array(env, &napiGlyphs));
155 size_t glyphSize = glyphs.size();
156 for (size_t index = 0; index < glyphSize; ++index) {
157 NAPI_CALL(env, napi_set_element(env, napiGlyphs, index,
158 CreateJsNumber(env, static_cast<uint32_t>(glyphs.at(index)))));
159 }
160 return napiGlyphs;
161 }
162
GetPositions(napi_env env,napi_callback_info info)163 napi_value JsRun::GetPositions(napi_env env, napi_callback_info info)
164 {
165 JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
166 return (me != nullptr) ? me->OnGetPositions(env, info) : nullptr;
167 }
168
OnGetPositions(napi_env env,napi_callback_info info)169 napi_value JsRun::OnGetPositions(napi_env env, napi_callback_info info)
170 {
171 if (!run_) {
172 TEXT_LOGE("Failed run is nullptr");
173 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr.");
174 }
175
176 std::vector<Drawing::Point> positions = run_->GetPositions();
177 napi_value napiPositions = nullptr;
178 NAPI_CALL(env, napi_create_array(env, &napiPositions));
179 size_t positionSize = positions.size();
180 for (size_t index = 0; index < positionSize; ++index) {
181 NAPI_CALL(env, napi_set_element(env, napiPositions, index,
182 GetPointAndConvertToJsValue(env, positions.at(index))));
183 }
184 return napiPositions;
185 }
186
GetOffsets(napi_env env,napi_callback_info info)187 napi_value JsRun::GetOffsets(napi_env env, napi_callback_info info)
188 {
189 JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
190 return (me != nullptr) ? me->OnGetOffsets(env, info) : nullptr;
191 }
192
OnGetOffsets(napi_env env,napi_callback_info info)193 napi_value JsRun::OnGetOffsets(napi_env env, napi_callback_info info)
194 {
195 if (!run_) {
196 TEXT_LOGE("JsRun::OnGetOffsets run is nullptr");
197 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetOffsets run is nullptr.");
198 }
199
200 std::vector<Drawing::Point> offsets = run_->GetOffsets();
201 napi_value napiOffsets = nullptr;
202 NAPI_CALL(env, napi_create_array(env, &napiOffsets));
203 size_t offsetSize = offsets.size();
204 for (size_t index = 0; index < offsetSize; ++index) {
205 NAPI_CALL(env, napi_set_element(env, napiOffsets, index,
206 GetPointAndConvertToJsValue(env, offsets.at(index))));
207 }
208 return napiOffsets;
209 }
210
GetFont(napi_env env,napi_callback_info info)211 napi_value JsRun::GetFont(napi_env env, napi_callback_info info)
212 {
213 JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
214 return (me != nullptr) ? me->OnGetFont(env, info) : nullptr;
215 }
216
OnGetFont(napi_env env,napi_callback_info info)217 napi_value JsRun::OnGetFont(napi_env env, napi_callback_info info)
218 {
219 if (!run_) {
220 TEXT_LOGE("JsRun::OnGetFont run is nullptr");
221 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetFont run is nullptr.");
222 }
223
224 std::shared_ptr<Drawing::Font> fontPtr = std::make_shared<Drawing::Font>(run_->GetFont());
225 if (!fontPtr) {
226 TEXT_LOGE("JsRun::OnGetFont fontPtr is nullptr");
227 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetFont fontPtr is nullptr.");
228 }
229
230 napi_value resultValue = Drawing::JsFont::CreateFont(env, info);
231 if (!resultValue) {
232 TEXT_LOGE("JsRun::OnGetFont JsFont::CreateFont resultValue is null");
233 return nullptr;
234 }
235 Drawing::JsFont* jsFont = nullptr;
236 napi_unwrap(env, resultValue, reinterpret_cast<void**>(&jsFont));
237 if (!jsFont) {
238 TEXT_LOGE("JsRun::OnGetFont napi_unwrap jsFont is null");
239 return nullptr;
240 }
241 jsFont->SetFont(fontPtr);
242 return resultValue;
243 }
244
Paint(napi_env env,napi_callback_info info)245 napi_value JsRun::Paint(napi_env env, napi_callback_info info)
246 {
247 JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
248 return (me != nullptr) ? me->OnPaint(env, info) : nullptr;
249 }
250
OnPaint(napi_env env,napi_callback_info info)251 napi_value JsRun::OnPaint(napi_env env, napi_callback_info info)
252 {
253 if (run_ == nullptr) {
254 TEXT_LOGE("JsRun::OnPaint run is nullptr");
255 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnPaint run is nullptr.");
256 }
257 size_t argc = ARGC_THREE;
258 napi_value argv[ARGC_THREE] = {nullptr};
259 napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
260 if (status != napi_ok || argc < ARGC_THREE) {
261 TEXT_LOGE("JsRun::OnPaint Argc is invalid: %{public}zu", argc);
262 return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
263 }
264 if (argv[0] == nullptr) {
265 TEXT_LOGE("JsRun::OnPaint argv[0] is invalid");
266 return NapiGetUndefined(env);
267 }
268 Drawing::JsCanvas* jsCanvas = nullptr;
269 double x = 0.0;
270 double y = 0.0;
271 napi_unwrap(env, argv[0], reinterpret_cast<void **>(&jsCanvas));
272 if (!jsCanvas || !jsCanvas->GetCanvas() ||
273 !(argv[ARGC_ONE] != nullptr && ConvertFromJsValue(env, argv[ARGC_ONE], x) &&
274 argv[ARGC_TWO] != nullptr && ConvertFromJsValue(env, argv[ARGC_TWO], y))) {
275 TEXT_LOGE("JsRun::OnPaint Argv is invalid");
276 return NapiGetUndefined(env);
277 }
278 run_->Paint(jsCanvas->GetCanvas(), x, y);
279
280 return NapiGetUndefined(env);
281 }
282
SetParagraph(std::shared_ptr<Typography> paragraph)283 void JsRun::SetParagraph(std::shared_ptr<Typography> paragraph)
284 {
285 paragraph_ = paragraph;
286 }
287 } // namespace OHOS::Rosen
288