• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "typography_types.h"
23 
24 namespace OHOS::Rosen {
25 std::mutex JsRun::constructorMutex_;
26 thread_local napi_ref JsRun::constructor_ = nullptr;
27 const std::string CLASS_NAME = "Run";
Constructor(napi_env env,napi_callback_info info)28 napi_value JsRun::Constructor(napi_env env, napi_callback_info info)
29 {
30     size_t argCount = 0;
31     napi_value jsThis = nullptr;
32     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
33     if (status != napi_ok) {
34         TEXT_LOGE("Failed to get parameter, ret %{public}d", status);
35         return nullptr;
36     }
37 
38     JsRun* jsRun = new(std::nothrow) JsRun();
39     if (!jsRun) {
40         TEXT_LOGE("Failed to new run");
41         return nullptr;
42     }
43 
44     status = napi_wrap(env, jsThis, jsRun,
45         JsRun::Destructor, nullptr, nullptr);
46     if (status != napi_ok) {
47         delete jsRun;
48         TEXT_LOGE("Failed to wrap run, ret %{public}d", status);
49         return nullptr;
50     }
51 
52     return jsThis;
53 }
54 
Init(napi_env env,napi_value exportObj)55 napi_value JsRun::Init(napi_env env, napi_value exportObj)
56 {
57     if (!CreateConstructor(env)) {
58         TEXT_LOGE("Failed to create constructor");
59         return nullptr;
60     }
61     napi_value constructor = nullptr;
62     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
63     if (status != napi_ok) {
64         TEXT_LOGE("Failed to get reference, ret %{public}d", status);
65         return nullptr;
66     }
67 
68     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
69     if (status != napi_ok) {
70         TEXT_LOGE("Failed to set named property, ret %{public}d", status);
71         return nullptr;
72     }
73 
74     return exportObj;
75 }
76 
CreateConstructor(napi_env env)77 bool JsRun::CreateConstructor(napi_env env)
78 {
79     std::lock_guard<std::mutex> lock(constructorMutex_);
80     if (constructor_) {
81         return true;
82     }
83     napi_property_descriptor properties[] = {
84         DECLARE_NAPI_FUNCTION("getGlyphCount", JsRun::GetGlyphCount),
85         DECLARE_NAPI_FUNCTION("getGlyphs", JsRun::GetGlyphs),
86         DECLARE_NAPI_FUNCTION("getPositions", JsRun::GetPositions),
87         DECLARE_NAPI_FUNCTION("getOffsets", JsRun::GetOffsets),
88         DECLARE_NAPI_FUNCTION("getFont", JsRun::GetFont),
89         DECLARE_NAPI_FUNCTION("getStringRange", JsRun::GetStringRange),
90         DECLARE_NAPI_FUNCTION("getStringIndices", JsRun::GetStringIndices),
91         DECLARE_NAPI_FUNCTION("getImageBounds", JsRun::GetImageBounds),
92         DECLARE_NAPI_FUNCTION("getTypographicBounds", JsRun::GetTypographicBounds),
93         DECLARE_NAPI_FUNCTION("paint", JsRun::Paint),
94         DECLARE_NAPI_FUNCTION("getTextDirection", JsRun::GetTextDirection),
95         DECLARE_NAPI_FUNCTION("getAdvances", JsRun::GetAdvances),
96     };
97 
98     napi_value constructor = nullptr;
99     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
100         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
101     if (status != napi_ok) {
102         TEXT_LOGE("Failed to define class, ret %{public}d", status);
103         return false;
104     }
105 
106     status = napi_create_reference(env, constructor, 1, &constructor_);
107     if (status != napi_ok) {
108         TEXT_LOGE("Failed to create reference, ret %{public}d", status);
109         return false;
110     }
111     return true;
112 }
113 
Destructor(napi_env env,void * nativeObject,void * finalize)114 void JsRun::Destructor(napi_env env, void* nativeObject, void* finalize)
115 {
116     (void)finalize;
117     if (nativeObject != nullptr) {
118         JsRun* jsRun = reinterpret_cast<JsRun*>(nativeObject);
119         delete jsRun;
120     }
121 }
122 
CreateRun(napi_env env,napi_callback_info info)123 napi_value JsRun::CreateRun(napi_env env, napi_callback_info info)
124 {
125     if (!CreateConstructor(env)) {
126         TEXT_LOGE("Failed to create constructor");
127         return nullptr;
128     }
129     napi_value result = nullptr;
130     napi_value constructor = nullptr;
131     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
132     if (status != napi_ok) {
133         TEXT_LOGE("Failed to get reference, ret %{public}d", status);
134         return nullptr;
135     }
136 
137     status = napi_new_instance(env, constructor, 0, nullptr, &result);
138     if (status != napi_ok) {
139         TEXT_LOGE("Failed to new instance, ret %{public}d", status);
140         return nullptr;
141     }
142     return result;
143 }
144 
JsRun()145 JsRun::JsRun()
146 {
147 }
148 
SetRun(std::unique_ptr<Run> run)149 void JsRun::SetRun(std::unique_ptr<Run> run)
150 {
151     run_ = std::move(run);
152 }
153 
GetGlyphCount(napi_env env,napi_callback_info info)154 napi_value JsRun::GetGlyphCount(napi_env env, napi_callback_info info)
155 {
156     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
157     return (me != nullptr) ? me->OnGetGlyphCount(env, info) : nullptr;
158 }
159 
OnGetGlyphCount(napi_env env,napi_callback_info info)160 napi_value JsRun::OnGetGlyphCount(napi_env env, napi_callback_info info)
161 {
162     if (!run_) {
163         TEXT_LOGE("Null run");
164         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetGlyphCount run is nullptr.");
165     }
166     int64_t count = static_cast<int64_t>(run_->GetGlyphCount());
167     return CreateJsNumber(env, count);
168 }
169 
GetGlyphs(napi_env env,napi_callback_info info)170 napi_value JsRun::GetGlyphs(napi_env env, napi_callback_info info)
171 {
172     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
173     return (me != nullptr) ? me->OnGetGlyphs(env, info) : nullptr;
174 }
175 
OnGetGlyphs(napi_env env,napi_callback_info info)176 napi_value JsRun::OnGetGlyphs(napi_env env, napi_callback_info info)
177 {
178     if (!run_) {
179         TEXT_LOGE("Null run");
180         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr");
181     }
182 
183     size_t argc = ARGC_ONE;
184     int64_t start = 0;
185     int64_t end = 0;
186     napi_value argv[ARGC_ONE] = {nullptr};
187     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
188     if (status != napi_ok) {
189         TEXT_LOGE("Failed to get parameter, ret %{public}d", static_cast<int>(status));
190         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
191     } else if (argc == ARGC_ONE) {
192         if (!GetStartEndParams(env, argv[0], start, end)) {
193             return NapiGetUndefined(env);
194         }
195     }
196 
197     std::vector<uint16_t> glyphs = run_->GetGlyphs(start, end);
198     napi_value napiGlyphs = nullptr;
199     NAPI_CALL(env, napi_create_array(env, &napiGlyphs));
200     size_t glyphSize = glyphs.size();
201     for (size_t index = 0; index < glyphSize; ++index) {
202         NAPI_CALL(env, napi_set_element(env, napiGlyphs, index,
203             CreateJsNumber(env, static_cast<uint32_t>(glyphs.at(index)))));
204     }
205     return napiGlyphs;
206 }
207 
GetPositions(napi_env env,napi_callback_info info)208 napi_value JsRun::GetPositions(napi_env env, napi_callback_info info)
209 {
210     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
211     return (me != nullptr) ? me->OnGetPositions(env, info) : nullptr;
212 }
213 
OnGetPositions(napi_env env,napi_callback_info info)214 napi_value JsRun::OnGetPositions(napi_env env, napi_callback_info info)
215 {
216     if (!run_) {
217         TEXT_LOGE("Null run");
218         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr.");
219     }
220 
221     size_t argc = ARGC_ONE;
222     int64_t start = 0;
223     int64_t end = 0;
224     napi_value argv[ARGC_ONE] = {nullptr};
225     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
226     if (status != napi_ok) {
227         TEXT_LOGE("Failed to get the info");
228         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
229     } else if (argc == ARGC_ONE) {
230         if (!GetStartEndParams(env, argv[0], start, end)) {
231             return NapiGetUndefined(env);
232         }
233     }
234 
235     std::vector<Drawing::Point> positions = run_->GetPositions(start, end);
236     napi_value napiPositions = nullptr;
237     NAPI_CALL(env, napi_create_array(env, &napiPositions));
238     size_t positionSize = positions.size();
239     for (size_t index = 0; index < positionSize; ++index) {
240         NAPI_CALL(env, napi_set_element(env, napiPositions, index,
241             GetPointAndConvertToJsValue(env, positions.at(index))));
242     }
243     return napiPositions;
244 }
245 
GetAdvances(napi_env env,napi_callback_info info)246 napi_value JsRun::GetAdvances(napi_env env, napi_callback_info info)
247 {
248     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
249     return (me != nullptr) ? me->OnGetAdvances(env, info) : nullptr;
250 }
251 
OnGetAdvances(napi_env env,napi_callback_info info)252 napi_value JsRun::OnGetAdvances(napi_env env, napi_callback_info info)
253 {
254     if (!run_) {
255         TEXT_LOGE("Failed run is nullptr");
256         return NapiGetUndefined(env);
257     }
258 
259     size_t argc = ARGC_ONE;
260     int64_t start = 0;
261     int64_t end = 0;
262     napi_value argv[ARGC_ONE] = {nullptr};
263     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
264     if (status != napi_ok || argc < ARGC_ONE) {
265         TEXT_LOGE("Failed to get parameter, argc %{public}zu, ret %{public}d", argc, status);
266         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
267     }
268     if (!GetStartEndParams(env, argv[0], start, end)) {
269         return NapiGetUndefined(env);
270     }
271 
272     std::vector<Drawing::Point> advances = run_->GetAdvances(start, end);
273     napi_value napiAdvances = nullptr;
274     NAPI_CALL(env, napi_create_array(env, &napiAdvances));
275     size_t advanceSize = advances.size();
276     for (size_t index = 0; index < advanceSize; ++index) {
277         NAPI_CALL(env, napi_set_element(env, napiAdvances, index,
278             GetPointAndConvertToJsValue(env, advances.at(index))));
279     }
280     return napiAdvances;
281 }
282 
GetTextDirection(napi_env env,napi_callback_info info)283 napi_value JsRun::GetTextDirection(napi_env env, napi_callback_info info)
284 {
285     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
286     return (me != nullptr) ? me->OnGetTextDirection(env, info) : nullptr;
287 }
288 
OnGetTextDirection(napi_env env,napi_callback_info info)289 napi_value JsRun::OnGetTextDirection(napi_env env, napi_callback_info info)
290 {
291     if (!run_) {
292         TEXT_LOGE("Failed run is nullptr");
293         return NapiGetUndefined(env);
294     }
295 
296     TextDirection textDirection = run_->GetTextDirection();
297     return CreateJsNumber(env, (int)textDirection);
298 }
299 
GetOffsets(napi_env env,napi_callback_info info)300 napi_value JsRun::GetOffsets(napi_env env, napi_callback_info info)
301 {
302     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
303     return (me != nullptr) ? me->OnGetOffsets(env, info) : nullptr;
304 }
305 
OnGetOffsets(napi_env env,napi_callback_info info)306 napi_value JsRun::OnGetOffsets(napi_env env, napi_callback_info info)
307 {
308     if (!run_) {
309         TEXT_LOGE("Null run");
310         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetOffsets run is nullptr.");
311     }
312 
313     std::vector<Drawing::Point> offsets = run_->GetOffsets();
314     napi_value napiOffsets = nullptr;
315     NAPI_CALL(env, napi_create_array(env, &napiOffsets));
316     size_t offsetSize = offsets.size();
317     for (size_t index = 0; index < offsetSize; ++index) {
318         NAPI_CALL(env, napi_set_element(env, napiOffsets, index,
319             GetPointAndConvertToJsValue(env, offsets.at(index))));
320     }
321     return napiOffsets;
322 }
323 
GetFont(napi_env env,napi_callback_info info)324 napi_value JsRun::GetFont(napi_env env, napi_callback_info info)
325 {
326     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
327     return (me != nullptr) ? me->OnGetFont(env, info) : nullptr;
328 }
329 
OnGetFont(napi_env env,napi_callback_info info)330 napi_value JsRun::OnGetFont(napi_env env, napi_callback_info info)
331 {
332     if (!run_) {
333         TEXT_LOGE("Null run");
334         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetFont run is nullptr.");
335     }
336 
337     std::shared_ptr<Drawing::Font> fontPtr = std::make_shared<Drawing::Font>(run_->GetFont());
338     if (!fontPtr) {
339         TEXT_LOGE("Null font");
340         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnGetFont fontPtr is nullptr.");
341     }
342 
343     napi_value resultValue  = Drawing::JsFont::CreateFont(env, info);
344     if (!resultValue) {
345         TEXT_LOGE("Failed to create font");
346         return nullptr;
347     }
348     Drawing::JsFont* jsFont = nullptr;
349     napi_unwrap(env, resultValue, reinterpret_cast<void**>(&jsFont));
350     if (!jsFont) {
351         TEXT_LOGE("Failed to unwrap font");
352         return nullptr;
353     }
354     jsFont->SetFont(fontPtr);
355     return resultValue;
356 }
357 
Paint(napi_env env,napi_callback_info info)358 napi_value JsRun::Paint(napi_env env, napi_callback_info info)
359 {
360     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
361     return (me != nullptr) ? me->OnPaint(env, info) : nullptr;
362 }
363 
OnPaint(napi_env env,napi_callback_info info)364 napi_value JsRun::OnPaint(napi_env env, napi_callback_info info)
365 {
366     if (run_ == nullptr) {
367         TEXT_LOGE("Null run");
368         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "JsRun::OnPaint run is nullptr.");
369     }
370     size_t argc = ARGC_THREE;
371     napi_value argv[ARGC_THREE] = {nullptr};
372     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
373     if (status != napi_ok || argc < ARGC_THREE) {
374         TEXT_LOGE("Failed to get parameter, argc %{public}zu, ret %{public}d", argc, status);
375         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
376     }
377     if (argv[0] == nullptr) {
378         TEXT_LOGE("Invalid argv[0]");
379         return NapiGetUndefined(env);
380     }
381     Drawing::JsCanvas* jsCanvas = nullptr;
382     double x = 0.0;
383     double y = 0.0;
384     napi_unwrap(env, argv[0], reinterpret_cast<void **>(&jsCanvas));
385     if (!jsCanvas || !jsCanvas->GetCanvas() ||
386         !(argv[ARGC_ONE] != nullptr && ConvertFromJsValue(env, argv[ARGC_ONE], x) &&
387         argv[ARGC_TWO] != nullptr && ConvertFromJsValue(env, argv[ARGC_TWO], y))) {
388         TEXT_LOGE("Failed to get paint parameter");
389         return NapiGetUndefined(env);
390     }
391     run_->Paint(jsCanvas->GetCanvas(), x, y);
392 
393     return NapiGetUndefined(env);
394 }
395 
SetParagraph(std::shared_ptr<Typography> paragraph)396 void JsRun::SetParagraph(std::shared_ptr<Typography> paragraph)
397 {
398     paragraph_ = paragraph;
399 }
400 
GetStringRange(napi_env env,napi_callback_info info)401 napi_value JsRun::GetStringRange(napi_env env, napi_callback_info info)
402 {
403     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
404     return (me != nullptr) ? me->OnGetStringRange(env, info) : nullptr;
405 }
406 
OnGetStringRange(napi_env env,napi_callback_info info)407 napi_value JsRun::OnGetStringRange(napi_env env, napi_callback_info info)
408 {
409     if (!run_) {
410         TEXT_LOGE("Null run");
411         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr.");
412     }
413     uint64_t location = 0;
414     uint64_t length = 0;
415     run_->GetStringRange(&location, &length);
416     napi_value objValue = nullptr;
417     napi_create_object(env, &objValue);
418     if (objValue != nullptr) {
419         napi_status status = napi_set_named_property(env, objValue, "start", CreateJsNumber(env, location));
420         if (status != napi_ok) {
421             TEXT_LOGE("Failed to set named property, ret %{public}d", status);
422             return nullptr;
423         }
424         status = napi_set_named_property(env, objValue, "end", CreateJsNumber(env, length));
425         if (status != napi_ok) {
426             TEXT_LOGE("Failed to set named property, ret %{public}d", status);
427             return nullptr;
428         }
429     }
430     return objValue;
431 }
432 
GetStringIndices(napi_env env,napi_callback_info info)433 napi_value JsRun::GetStringIndices(napi_env env, napi_callback_info info)
434 {
435     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
436     return (me != nullptr) ? me->OnGetStringIndices(env, info) : nullptr;
437 }
438 
OnGetStringIndices(napi_env env,napi_callback_info info)439 napi_value JsRun::OnGetStringIndices(napi_env env, napi_callback_info info)
440 {
441     if (!run_) {
442         TEXT_LOGE("Null run");
443         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr.");
444     }
445 
446     size_t argc = ARGC_ONE;
447     int64_t start = 0;
448     int64_t end = 0;
449     napi_value argv[ARGC_ONE] = {nullptr};
450     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
451     if (status != napi_ok) {
452         TEXT_LOGE("Failed to get the info");
453         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
454     } else if (argc == ARGC_ONE) {
455         if (!GetStartEndParams(env, argv[0], start, end)) {
456             TEXT_LOGE("Failed to GetStringIndices: invalid start and end");
457             return NapiGetUndefined(env);
458         }
459     }
460 
461     std::vector<uint64_t> stringIndices = run_->GetStringIndices(start, end);
462     napi_value napiStringIndices = nullptr;
463     NAPI_CALL(env, napi_create_array(env, &napiStringIndices));
464     size_t stringIndicesSize = stringIndices.size();
465     for (size_t index = 0; index < stringIndicesSize; ++index) {
466         NAPI_CALL(env, napi_set_element(env, napiStringIndices, index,
467             CreateJsNumber(env, stringIndices.at(index))));
468     }
469     return napiStringIndices;
470 }
471 
GetImageBounds(napi_env env,napi_callback_info info)472 napi_value JsRun::GetImageBounds(napi_env env, napi_callback_info info)
473 {
474     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
475     return (me != nullptr) ? me->OnGetImageBounds(env, info) : nullptr;
476 }
477 
OnGetImageBounds(napi_env env,napi_callback_info info)478 napi_value JsRun::OnGetImageBounds(napi_env env, napi_callback_info info)
479 {
480     if (!run_) {
481         TEXT_LOGE("Null run");
482         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr.");
483     }
484     Drawing::Rect imageBounds = run_->GetImageBounds();
485     return GetRectAndConvertToJsValue(env, imageBounds);
486 }
487 
GetTypographicBounds(napi_env env,napi_callback_info info)488 napi_value JsRun::GetTypographicBounds(napi_env env, napi_callback_info info)
489 {
490     JsRun* me = CheckParamsAndGetThis<JsRun>(env, info);
491     return (me != nullptr) ? me->OnGetTypographicBounds(env, info) : nullptr;
492 }
493 
OnGetTypographicBounds(napi_env env,napi_callback_info info)494 napi_value JsRun::OnGetTypographicBounds(napi_env env, napi_callback_info info)
495 {
496     if (!run_) {
497         TEXT_LOGE("Null run");
498         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Failed run is nullptr.");
499     }
500 
501     float ascent = 0.0;
502     float descent = 0.0;
503     float leading = 0.0;
504     float width = run_->GetTypographicBounds(&ascent, &descent, &leading);
505     return GetTypographicBoundsAndConvertToJsValue(env, ascent, descent, leading, width);
506 }
507 } // namespace OHOS::Rosen
508