• 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_paragraph.h"
17 #include "canvas_napi/js_canvas.h"
18 #include "draw/canvas.h"
19 #include "napi_common.h"
20 #include "paragraph_builder_napi/js_paragraph_builder.h"
21 #include "path_napi/js_path.h"
22 #include "text_line_napi/js_text_line.h"
23 #include "utils/text_log.h"
24 
25 namespace OHOS::Rosen {
26 namespace {
27 const std::string CLASS_NAME = "Paragraph";
28 }
29 
30 std::unique_ptr<Typography> JsParagraph::g_Typography = nullptr;
31 thread_local napi_ref JsParagraph::constructor_ = nullptr;
32 
Constructor(napi_env env,napi_callback_info info)33 napi_value JsParagraph::Constructor(napi_env env, napi_callback_info info)
34 {
35     size_t argCount = 0;
36     napi_value jsThis = nullptr;
37     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
38     if (status != napi_ok) {
39         TEXT_LOGE("JsParagraph::Constructor failed to napi_get_cb_info");
40         return nullptr;
41     }
42 
43     if (!g_Typography) {
44         TEXT_LOGE("Typography is null");
45         return nullptr;
46     }
47 
48     JsParagraph *jsParagraph = new(std::nothrow) JsParagraph(std::move(g_Typography));
49     if (jsParagraph == nullptr) {
50         return nullptr;
51     }
52 
53     status = napi_wrap(env, jsThis, jsParagraph,
54         JsParagraph::Destructor, nullptr, nullptr);
55     if (status != napi_ok) {
56         delete jsParagraph;
57         TEXT_LOGE("JsParagraph::Constructor failed to wrap native instance");
58         return nullptr;
59     }
60     return jsThis;
61 }
62 
Init(napi_env env,napi_value exportObj)63 napi_value JsParagraph::Init(napi_env env, napi_value exportObj)
64 {
65     napi_property_descriptor properties[] = {
66         DECLARE_NAPI_FUNCTION("layoutSync", JsParagraph::Layout),
67         DECLARE_NAPI_FUNCTION("paint", JsParagraph::Paint),
68         DECLARE_NAPI_FUNCTION("paintOnPath", JsParagraph::PaintOnPath),
69         DECLARE_NAPI_FUNCTION("getMaxWidth", JsParagraph::GetMaxWidth),
70         DECLARE_NAPI_FUNCTION("getHeight", JsParagraph::GetHeight),
71         DECLARE_NAPI_FUNCTION("getLongestLine", JsParagraph::GetLongestLine),
72         DECLARE_NAPI_FUNCTION("getLongestLineWithIndent", JsParagraph::GetLongestLineWithIndent),
73         DECLARE_NAPI_FUNCTION("getMinIntrinsicWidth", JsParagraph::GetMinIntrinsicWidth),
74         DECLARE_NAPI_FUNCTION("getMaxIntrinsicWidth", JsParagraph::GetMaxIntrinsicWidth),
75         DECLARE_NAPI_FUNCTION("getAlphabeticBaseline", JsParagraph::GetAlphabeticBaseline),
76         DECLARE_NAPI_FUNCTION("getIdeographicBaseline", JsParagraph::GetIdeographicBaseline),
77         DECLARE_NAPI_FUNCTION("getRectsForRange", JsParagraph::GetRectsForRange),
78         DECLARE_NAPI_FUNCTION("getRectsForPlaceholders", JsParagraph::GetRectsForPlaceholders),
79         DECLARE_NAPI_FUNCTION("getGlyphPositionAtCoordinate", JsParagraph::GetGlyphPositionAtCoordinate),
80         DECLARE_NAPI_FUNCTION("getWordBoundary", JsParagraph::GetWordBoundary),
81         DECLARE_NAPI_FUNCTION("getLineCount", JsParagraph::GetLineCount),
82         DECLARE_NAPI_FUNCTION("getLineHeight", JsParagraph::GetLineHeight),
83         DECLARE_NAPI_FUNCTION("getLineWidth", JsParagraph::GetLineWidth),
84         DECLARE_NAPI_FUNCTION("didExceedMaxLines", JsParagraph::DidExceedMaxLines),
85         DECLARE_NAPI_FUNCTION("getTextLines", JsParagraph::GetTextLines),
86         DECLARE_NAPI_FUNCTION("getActualTextRange", JsParagraph::GetActualTextRange),
87         DECLARE_NAPI_FUNCTION("getLineMetrics", JsParagraph::GetLineMetrics),
88     };
89     napi_value constructor = nullptr;
90     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
91         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
92     if (status != napi_ok) {
93         TEXT_LOGE("Failed to define Paragraph class");
94         return nullptr;
95     }
96 
97     status = napi_create_reference(env, constructor, 1, &constructor_);
98     if (status != napi_ok) {
99         TEXT_LOGE("Failed to create reference of result");
100         return nullptr;
101     }
102 
103     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
104     if (status != napi_ok) {
105         TEXT_LOGE("Failed to set result");
106         return nullptr;
107     }
108     return exportObj;
109 }
110 
111 
Destructor(napi_env env,void * nativeObject,void * finalize)112 void JsParagraph::Destructor(napi_env env, void *nativeObject, void *finalize)
113 {
114     (void)finalize;
115     if (nativeObject != nullptr) {
116         JsParagraph *napi = reinterpret_cast<JsParagraph *>(nativeObject);
117         delete napi;
118     }
119 }
120 
Layout(napi_env env,napi_callback_info info)121 napi_value JsParagraph::Layout(napi_env env, napi_callback_info info)
122 {
123     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
124     return (me != nullptr) ? me->OnLayout(env, info) : nullptr;
125 }
126 
OnLayout(napi_env env,napi_callback_info info)127 napi_value JsParagraph::OnLayout(napi_env env, napi_callback_info info)
128 {
129     if (paragraph_ == nullptr) {
130         TEXT_LOGE("JsParagraph::OnLayout paragraph_ is nullptr");
131         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
132     }
133     size_t argc = ARGC_ONE;
134     napi_value argv[ARGC_ONE] = {nullptr};
135     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
136     if (status != napi_ok || argc < ARGC_ONE) {
137         TEXT_LOGE("JsParagraph::OnLayout Argc is invalid: %{public}zu", argc);
138         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
139     }
140     double width = 0.0;
141     if (!(argv[0] != nullptr && ConvertFromJsValue(env, argv[0], width))) {
142         TEXT_LOGE("JsParagraph::OnLayout Argv is invalid");
143         return NapiGetUndefined(env);
144     }
145 
146     paragraph_->Layout(width);
147     return NapiGetUndefined(env);
148 }
149 
Paint(napi_env env,napi_callback_info info)150 napi_value JsParagraph::Paint(napi_env env, napi_callback_info info)
151 {
152     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
153     return (me != nullptr) ? me->OnPaint(env, info) : nullptr;
154 }
155 
OnPaint(napi_env env,napi_callback_info info)156 napi_value JsParagraph::OnPaint(napi_env env, napi_callback_info info)
157 {
158     if (paragraph_ == nullptr) {
159         TEXT_LOGE("JsParagraph::OnPaint paragraph_ is nullptr");
160         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
161     }
162     size_t argc = ARGC_THREE;
163     napi_value argv[ARGC_THREE] = {nullptr};
164     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
165     if (status != napi_ok || argc < ARGC_THREE) {
166         TEXT_LOGE("JsParagraph::OnPaint Argc is invalid: %{public}zu", argc);
167         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
168     }
169     if (argv[0] == nullptr) {
170         TEXT_LOGE("Argv is invalid");
171         return NapiGetUndefined(env);
172     }
173     Drawing::JsCanvas* jsCanvas = nullptr;
174     double x = 0.0;
175     double y = 0.0;
176     napi_unwrap(env, argv[0], reinterpret_cast<void **>(&jsCanvas));
177     if (!jsCanvas || !jsCanvas->GetCanvas() ||
178         !(argv[ARGC_ONE] != nullptr && ConvertFromJsValue(env, argv[ARGC_ONE], x) &&
179          argv[ARGC_TWO] != nullptr && ConvertFromJsValue(env, argv[ARGC_TWO], y))) {
180         TEXT_LOGE("JsParagraph::OnPaint Argv is invalid");
181         return NapiGetUndefined(env);
182     }
183     paragraph_->Paint(jsCanvas->GetCanvas(), x, y);
184 
185     return NapiGetUndefined(env);
186 }
187 
PaintOnPath(napi_env env,napi_callback_info info)188 napi_value JsParagraph::PaintOnPath(napi_env env, napi_callback_info info)
189 {
190     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
191     return (me != nullptr) ? me->OnPaintOnPath(env, info) : nullptr;
192 }
193 
OnPaintOnPath(napi_env env,napi_callback_info info)194 napi_value JsParagraph::OnPaintOnPath(napi_env env, napi_callback_info info)
195 {
196     if (paragraph_ == nullptr) {
197         TEXT_LOGE("JsParagraph::OnPaintOnPath paragraph_ is nullptr");
198         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
199     }
200     size_t argc = ARGC_FOUR;
201     napi_value argv[ARGC_FOUR] = { nullptr };
202     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
203     if (status != napi_ok || argc < ARGC_FOUR) {
204         TEXT_LOGE("JsParagraph::OnPaintOnPath Argc is invalid: %{public}zu", argc);
205         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
206     }
207     Drawing::JsCanvas* jsCanvas = nullptr;
208     Drawing::JsPath* jsPath = nullptr;
209     double hOffset = 0.0;
210     double vOffset = 0.0;
211     napi_unwrap(env, argv[0], reinterpret_cast<void**>(&jsCanvas));
212     GET_UNWRAP_PARAM(ARGC_ONE, jsPath);
213     if (!jsCanvas || !jsCanvas->GetCanvas() || !jsPath || !jsPath->GetPath() ||
214         !(ConvertFromJsValue(env, argv[ARGC_TWO], hOffset) && ConvertFromJsValue(env, argv[ARGC_THREE], vOffset))) {
215         TEXT_LOGE("JsParagraph::OnPaintOnPath Argv is invalid");
216         return NapiGetUndefined(env);
217     }
218     paragraph_->Paint(jsCanvas->GetCanvas(), jsPath->GetPath(), hOffset, vOffset);
219 
220     return NapiGetUndefined(env);
221 }
222 
GetMaxWidth(napi_env env,napi_callback_info info)223 napi_value JsParagraph::GetMaxWidth(napi_env env, napi_callback_info info)
224 {
225     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
226     return (me != nullptr) ? me->OnGetMaxWidth(env, info) : nullptr;
227 }
228 
OnGetMaxWidth(napi_env env,napi_callback_info info)229 napi_value JsParagraph::OnGetMaxWidth(napi_env env, napi_callback_info info)
230 {
231     if (paragraph_ == nullptr) {
232         TEXT_LOGE("JsParagraph::OnGetMaxWidth paragraph_ is nullptr");
233         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
234     }
235     double maxWidth = paragraph_->GetMaxWidth();
236     return CreateJsNumber(env, maxWidth);
237 }
238 
GetHeight(napi_env env,napi_callback_info info)239 napi_value JsParagraph::GetHeight(napi_env env, napi_callback_info info)
240 {
241     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
242     return (me != nullptr) ? me->OnGetHeight(env, info) : nullptr;
243 }
244 
OnGetHeight(napi_env env,napi_callback_info info)245 napi_value JsParagraph::OnGetHeight(napi_env env, napi_callback_info info)
246 {
247     if (paragraph_ == nullptr) {
248         TEXT_LOGE("JsParagraph::OnGetHeight paragraph_ is nullptr");
249         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
250     }
251     double height = paragraph_->GetHeight();
252     return CreateJsNumber(env, height);
253 }
254 
GetLongestLine(napi_env env,napi_callback_info info)255 napi_value JsParagraph::GetLongestLine(napi_env env, napi_callback_info info)
256 {
257     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
258     return (me != nullptr) ? me->OnGetLongestLine(env, info) : nullptr;
259 }
260 
OnGetLongestLine(napi_env env,napi_callback_info info)261 napi_value JsParagraph::OnGetLongestLine(napi_env env, napi_callback_info info)
262 {
263     if (paragraph_ == nullptr) {
264         TEXT_LOGE("JsParagraph::OnGetLongestLine paragraph_ is nullptr");
265         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
266     }
267     double longestLine = paragraph_->GetActualWidth();
268     return CreateJsNumber(env, longestLine);
269 }
270 
GetLongestLineWithIndent(napi_env env,napi_callback_info info)271 napi_value JsParagraph::GetLongestLineWithIndent(napi_env env, napi_callback_info info)
272 {
273     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
274     return (me != nullptr) ? me->OnGetLongestLineWithIndent(env, info) : nullptr;
275 }
276 
OnGetLongestLineWithIndent(napi_env env,napi_callback_info info)277 napi_value JsParagraph::OnGetLongestLineWithIndent(napi_env env, napi_callback_info info)
278 {
279     if (paragraph_ == nullptr) {
280         TEXT_LOGE("Paragraph is nullptr");
281         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
282     }
283     double longestLine = paragraph_->GetLongestLineWithIndent();
284     return CreateJsNumber(env, longestLine);
285 }
286 
GetMinIntrinsicWidth(napi_env env,napi_callback_info info)287 napi_value JsParagraph::GetMinIntrinsicWidth(napi_env env, napi_callback_info info)
288 {
289     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
290     return (me != nullptr) ? me->OnGetMinIntrinsicWidth(env, info) : nullptr;
291 }
292 
OnGetMinIntrinsicWidth(napi_env env,napi_callback_info info)293 napi_value JsParagraph::OnGetMinIntrinsicWidth(napi_env env, napi_callback_info info)
294 {
295     if (paragraph_ == nullptr) {
296         TEXT_LOGE("JsParagraph::OnGetMinIntrinsicWidth paragraph_ is nullptr");
297         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
298     }
299     double minIntrinsicWidth = paragraph_->GetMinIntrinsicWidth();
300     return CreateJsNumber(env, minIntrinsicWidth);
301 }
302 
GetMaxIntrinsicWidth(napi_env env,napi_callback_info info)303 napi_value JsParagraph::GetMaxIntrinsicWidth(napi_env env, napi_callback_info info)
304 {
305     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
306     return (me != nullptr) ? me->OnGetMaxIntrinsicWidth(env, info) : nullptr;
307 }
308 
OnGetMaxIntrinsicWidth(napi_env env,napi_callback_info info)309 napi_value JsParagraph::OnGetMaxIntrinsicWidth(napi_env env, napi_callback_info info)
310 {
311     if (paragraph_ == nullptr) {
312         TEXT_LOGE("JsParagraph::OnGetMaxIntrinsicWidth paragraph_ is nullptr");
313         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
314     }
315     double maxIntrinsicWidth = paragraph_->GetMaxIntrinsicWidth();
316     return CreateJsNumber(env, maxIntrinsicWidth);
317 }
318 
GetAlphabeticBaseline(napi_env env,napi_callback_info info)319 napi_value JsParagraph::GetAlphabeticBaseline(napi_env env, napi_callback_info info)
320 {
321     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
322     return (me != nullptr) ? me->OnGetAlphabeticBaseline(env, info) : nullptr;
323 }
324 
OnGetAlphabeticBaseline(napi_env env,napi_callback_info info)325 napi_value JsParagraph::OnGetAlphabeticBaseline(napi_env env, napi_callback_info info)
326 {
327     if (paragraph_ == nullptr) {
328         TEXT_LOGE("JsParagraph::OnGetAlphabeticBaseline paragraph_ is nullptr");
329         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
330     }
331     double alphabeticBaseline = paragraph_->GetAlphabeticBaseline();
332     return CreateJsNumber(env, alphabeticBaseline);
333 }
334 
GetIdeographicBaseline(napi_env env,napi_callback_info info)335 napi_value JsParagraph::GetIdeographicBaseline(napi_env env, napi_callback_info info)
336 {
337     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
338     return (me != nullptr) ? me->OnGetIdeographicBaseline(env, info) : nullptr;
339 }
340 
OnGetIdeographicBaseline(napi_env env,napi_callback_info info)341 napi_value JsParagraph::OnGetIdeographicBaseline(napi_env env, napi_callback_info info)
342 {
343     if (paragraph_ == nullptr) {
344         TEXT_LOGE("JsParagraph::OnGetIdeographicBaseline paragraph_ is nullptr");
345         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
346     }
347     double ideographicBaseline = paragraph_->GetIdeographicBaseline();
348     return CreateJsNumber(env, ideographicBaseline);
349 }
350 
GetRectsForRange(napi_env env,napi_callback_info info)351 napi_value JsParagraph::GetRectsForRange(napi_env env, napi_callback_info info)
352 {
353     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
354     return (me != nullptr) ? me->OnGetRectsForRange(env, info) : nullptr;
355 }
356 
OnGetRectsForRange(napi_env env,napi_callback_info info)357 napi_value JsParagraph::OnGetRectsForRange(napi_env env, napi_callback_info info)
358 {
359     if (paragraph_ == nullptr) {
360         TEXT_LOGE("JsParagraph::OnGetRectsForRange paragraph_ is nullptr");
361         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
362     }
363     size_t argc = ARGC_THREE;
364     napi_value argv[ARGC_THREE] = {nullptr};
365     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
366     if (status != napi_ok || argc < ARGC_THREE) {
367         TEXT_LOGE("JsParagraph::OnGetRectsForRange Argc is invalid: %{public}zu", argc);
368         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
369     }
370     napi_valuetype valueType = napi_undefined;
371     if (argv[0] == nullptr || napi_typeof(env, argv[0], &valueType) != napi_ok || valueType != napi_object) {
372         TEXT_LOGE("JsParagraph::OnGetRectsForRange Argv[0] is invalid");
373         return NapiGetUndefined(env);
374     }
375     napi_value tempValue = nullptr;
376     size_t start = 0;
377     size_t end = 0;
378     TextRectWidthStyle wstyle;
379     TextRectHeightStyle hstyle;
380     napi_get_named_property(env, argv[0], "start", &tempValue);
381     if (tempValue == nullptr) {
382         TEXT_LOGE("Get start property failed");
383         return NapiGetUndefined(env);
384     }
385     bool isStartOk = ConvertFromJsValue(env, tempValue, start);
386     tempValue = nullptr;
387     napi_get_named_property(env, argv[0], "end", &tempValue);
388     if (tempValue == nullptr) {
389         TEXT_LOGE("Get end property failed");
390         return NapiGetUndefined(env);
391     }
392     bool isEndOk = ConvertFromJsValue(env, tempValue, end);
393     if (!(isStartOk && isEndOk && argv[ARGC_ONE] != nullptr && ConvertFromJsValue(env, argv[ARGC_ONE], wstyle) &&
394         argv[ARGC_TWO] != nullptr && ConvertFromJsValue(env, argv[ARGC_TWO], hstyle))) {
395         TEXT_LOGE("JsParagraph::OnGetRectsForRange Argv is invalid");
396         return NapiGetUndefined(env);
397     }
398     std::vector<TextRect> rectsForRange = paragraph_->GetTextRectsByBoundary(start, end, hstyle, wstyle);
399     napi_value returnrectsForRange = nullptr;
400     NAPI_CALL(env, napi_create_array(env, &returnrectsForRange));
401     int num = static_cast<int>(rectsForRange.size());
402     for (int index = 0; index < num; ++index) {
403         napi_value tempValue2 = CreateTextRectJsValue(env, rectsForRange[index]);
404         NAPI_CALL(env, napi_set_element(env, returnrectsForRange, index, tempValue2));
405     }
406     return returnrectsForRange;
407 }
408 
GetRectsForPlaceholders(napi_env env,napi_callback_info info)409 napi_value JsParagraph::GetRectsForPlaceholders(napi_env env, napi_callback_info info)
410 {
411     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
412     return (me != nullptr) ? me->OnGetRectsForPlaceholders(env, info) : nullptr;
413 }
414 
OnGetRectsForPlaceholders(napi_env env,napi_callback_info info)415 napi_value JsParagraph::OnGetRectsForPlaceholders(napi_env env, napi_callback_info info)
416 {
417     if (paragraph_ == nullptr) {
418         TEXT_LOGE("JsParagraph::OnGetRectsForPlaceholders paragraph_ is nullptr");
419         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
420     }
421     std::vector<TextRect> rectsForPlaceholders = paragraph_->GetTextRectsOfPlaceholders();
422     napi_value returnPlaceholders = nullptr;
423     NAPI_CALL(env, napi_create_array(env, &returnPlaceholders));
424     int num = static_cast<int>(rectsForPlaceholders.size());
425     for (int index = 0; index < num; ++index) {
426         napi_value tempValue = CreateTextRectJsValue(env, rectsForPlaceholders[index]);
427         if (tempValue != nullptr) {
428             NAPI_CALL(env, napi_set_element(env, returnPlaceholders, index, tempValue));
429         }
430     }
431     return returnPlaceholders;
432 }
433 
GetGlyphPositionAtCoordinate(napi_env env,napi_callback_info info)434 napi_value JsParagraph::GetGlyphPositionAtCoordinate(napi_env env, napi_callback_info info)
435 {
436     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
437     return (me != nullptr) ? me->OnGetGlyphPositionAtCoordinate(env, info) : nullptr;
438 }
439 
OnGetGlyphPositionAtCoordinate(napi_env env,napi_callback_info info)440 napi_value JsParagraph::OnGetGlyphPositionAtCoordinate(napi_env env, napi_callback_info info)
441 {
442     if (paragraph_ == nullptr) {
443         TEXT_LOGE("JsParagraph::OnGetGlyphPositionAtCoordinate paragraph_ is nullptr");
444         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
445     }
446     size_t argc = ARGC_TWO;
447     napi_value argv[ARGC_TWO] = {nullptr};
448     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
449     if (status != napi_ok || argc < ARGC_TWO) {
450         TEXT_LOGE("JsParagraph::OnGetGlyphPositionAtCoordinate Argc is invalid: %{public}zu", argc);
451         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
452     }
453     double dx = 0.0;
454     double dy = 0.0;
455     if (!(argv[0] != nullptr && ConvertFromJsValue(env, argv[0], dx) && argv[1] != nullptr &&
456          ConvertFromJsValue(env, argv[1], dy))) {
457         TEXT_LOGE("JsParagraph::OnGetGlyphPositionAtCoordinate Argv is invalid");
458         return NapiGetUndefined(env);
459     }
460     IndexAndAffinity positionWithAffinity = paragraph_->GetGlyphIndexByCoordinate(dx, dy);
461     return GetPositionWithAffinityAndConvertToJsValue(env, &positionWithAffinity);
462 }
463 
GetWordBoundary(napi_env env,napi_callback_info info)464 napi_value JsParagraph::GetWordBoundary(napi_env env, napi_callback_info info)
465 {
466     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
467     return (me != nullptr) ? me->OnGetWordBoundary(env, info) : nullptr;
468 }
469 
OnGetWordBoundary(napi_env env,napi_callback_info info)470 napi_value JsParagraph::OnGetWordBoundary(napi_env env, napi_callback_info info)
471 {
472     if (paragraph_ == nullptr) {
473         TEXT_LOGE("JsParagraph::OnGetWordBoundary paragraph_ is nullptr");
474         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
475     }
476     size_t argc = ARGC_ONE;
477     napi_value argv[ARGC_ONE] = {nullptr};
478     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
479     if (status != napi_ok || argc < ARGC_ONE) {
480         TEXT_LOGE("JsParagraph::OnGetWordBoundary Argc is invalid: %{public}zu", argc);
481         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
482     }
483     size_t offset = 0;
484     if (!(argv[0] != nullptr && ConvertFromJsValue(env, argv[0], offset))) {
485         TEXT_LOGE("JsParagraph::OnGetWordBoundary Argv is invalid");
486         return NapiGetUndefined(env);
487     }
488     Boundary range = paragraph_->GetWordBoundaryByIndex(offset);
489     return GetRangeAndConvertToJsValue(env, &range);
490 }
491 
GetLineCount(napi_env env,napi_callback_info info)492 napi_value JsParagraph::GetLineCount(napi_env env, napi_callback_info info)
493 {
494     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
495     return (me != nullptr) ? me->OnGetLineCount(env, info) : nullptr;
496 }
497 
OnGetLineCount(napi_env env,napi_callback_info info)498 napi_value JsParagraph::OnGetLineCount(napi_env env, napi_callback_info info)
499 {
500     if (paragraph_ == nullptr) {
501         TEXT_LOGE("JsParagraph::OnGetLineCount paragraph_ is nullptr");
502         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
503     }
504     size_t lineCount = static_cast<size_t>(paragraph_->GetLineCount());
505     return CreateJsNumber(env, lineCount);
506 }
507 
GetLineHeight(napi_env env,napi_callback_info info)508 napi_value JsParagraph::GetLineHeight(napi_env env, napi_callback_info info)
509 {
510     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
511     return (me != nullptr) ? me->OnGetLineHeight(env, info) : nullptr;
512 }
513 
OnGetLineHeight(napi_env env,napi_callback_info info)514 napi_value JsParagraph::OnGetLineHeight(napi_env env, napi_callback_info info)
515 {
516     if (paragraph_ == nullptr) {
517         TEXT_LOGE("JsParagraph::OnGetLineHeight paragraph_ is nullptr");
518         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
519     }
520     size_t argc = ARGC_ONE;
521     napi_value argv[ARGC_ONE] = {nullptr};
522     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
523     if (status != napi_ok || argc < ARGC_ONE) {
524         TEXT_LOGE("JsParagraph::OnGetLineHeight Argc is invalid: %{public}zu", argc);
525         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
526     }
527     int lineNumber = 0;
528     if (!(argv[0] != nullptr && ConvertFromJsValue(env, argv[0], lineNumber))) {
529         TEXT_LOGE("JsParagraph::OnGetLineHeight Argv is invalid");
530         return NapiGetUndefined(env);
531     }
532     double lineHeight = paragraph_->GetLineHeight(lineNumber);
533     return CreateJsNumber(env, lineHeight);
534 }
535 
GetLineWidth(napi_env env,napi_callback_info info)536 napi_value JsParagraph::GetLineWidth(napi_env env, napi_callback_info info)
537 {
538     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
539     return (me != nullptr) ? me->OnGetLineWidth(env, info) : nullptr;
540 }
541 
OnGetLineWidth(napi_env env,napi_callback_info info)542 napi_value JsParagraph::OnGetLineWidth(napi_env env, napi_callback_info info)
543 {
544     if (paragraph_ == nullptr) {
545         TEXT_LOGE("JsParagraph::OnGetLineWidth paragraph_ is nullptr");
546         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
547     }
548     size_t argc = ARGC_ONE;
549     napi_value argv[ARGC_ONE] = {nullptr};
550     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
551     if (status != napi_ok || argc < ARGC_ONE) {
552         TEXT_LOGE("JsParagraph::OnGetLineWidth Argc is invalid: %{public}zu", argc);
553         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
554     }
555     int lineNumber = 0;
556     if (!(argv[0] != nullptr && ConvertFromJsValue(env, argv[0], lineNumber))) {
557         TEXT_LOGE("JsParagraph::OnGetLineWidth Argv is invalid");
558         return NapiGetUndefined(env);
559     }
560     double lineWidth = paragraph_->GetLineWidth(lineNumber);
561     return CreateJsNumber(env, lineWidth);
562 }
563 
DidExceedMaxLines(napi_env env,napi_callback_info info)564 napi_value JsParagraph::DidExceedMaxLines(napi_env env, napi_callback_info info)
565 {
566     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
567     return (me != nullptr) ? me->OnDidExceedMaxLines(env, info) : nullptr;
568 }
569 
OnDidExceedMaxLines(napi_env env,napi_callback_info info)570 napi_value JsParagraph::OnDidExceedMaxLines(napi_env env, napi_callback_info info)
571 {
572     if (paragraph_ == nullptr) {
573         TEXT_LOGE("JsParagraph::OnDidExceedMaxLines paragraph_ is nullptr");
574         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
575     }
576     bool didExceedMaxLines = paragraph_->DidExceedMaxLines();
577     return CreateJsValue(env, didExceedMaxLines);
578 }
579 
GetActualTextRange(napi_env env,napi_callback_info info)580 napi_value JsParagraph::GetActualTextRange(napi_env env, napi_callback_info info)
581 {
582     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
583     return (me != nullptr) ? me->OnGetActualTextRange(env, info) : nullptr;
584 }
585 
OnGetActualTextRange(napi_env env,napi_callback_info info)586 napi_value JsParagraph::OnGetActualTextRange(napi_env env, napi_callback_info info)
587 {
588     if (paragraph_ == nullptr) {
589         TEXT_LOGE("JsParagraph::OnGetActualTextRange paragraph_ is nullptr");
590         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
591     }
592 
593     size_t argc = ARGC_TWO;
594     napi_value argv[ARGC_TWO] = {nullptr};
595     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
596     if (status != napi_ok || argc < ARGC_TWO) {
597         TEXT_LOGE("JsParagraph::OnGetActualTextRange Argc is invalid: %{public}zu", argc);
598         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
599     }
600     int lineNumber = 0;
601     if (!(ConvertFromJsValue(env, argv[0], lineNumber))) {
602         TEXT_LOGE("JsParagraph::OnGetActualTextRange Argv is invalid");
603         return NapiGetUndefined(env);
604     }
605     bool includeSpaces = false;
606     if (!(ConvertFromJsValue(env, argv[1], includeSpaces))) {
607         TEXT_LOGE("JsParagraph::OnGetActualTextRange Argv is invalid");
608         return NapiGetUndefined(env);
609     }
610     OHOS::Rosen::Boundary range = paragraph_->GetActualTextRange(lineNumber, includeSpaces);
611     return GetRangeAndConvertToJsValue(env, &range);
612 }
613 
GetLineMetrics(napi_env env,napi_callback_info info)614 napi_value JsParagraph::GetLineMetrics(napi_env env, napi_callback_info info)
615 {
616     size_t argc = ARGC_ONE;
617     napi_value argv[ARGC_ONE] = {nullptr};
618     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
619     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
620     if (status == napi_ok && argc < ARGC_ONE) {
621         return (me != nullptr) ? me->OnGetLineMetrics(env, info) : nullptr;
622     }
623     return (me != nullptr) ? me->OnGetLineMetricsAt(env, info) : nullptr;
624 }
625 
OnGetLineMetrics(napi_env env,napi_callback_info info)626 napi_value JsParagraph::OnGetLineMetrics(napi_env env, napi_callback_info info)
627 {
628     if (paragraph_ == nullptr) {
629         TEXT_LOGE("JsParagraph::OnGetLineMetrics paragraph_ is nullptr");
630         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
631     }
632     std::vector<LineMetrics> vectorLineMetrics = paragraph_->GetLineMetrics();
633     napi_value returnLineMetrics = nullptr;
634     NAPI_CALL(env, napi_create_array(env, &returnLineMetrics));
635     int num = static_cast<int>(vectorLineMetrics.size());
636     for (int index = 0; index < num; ++index) {
637         napi_value tempValue = CreateLineMetricsJsValue(env, vectorLineMetrics[index]);
638         napi_set_element(env, returnLineMetrics, index, tempValue);
639     }
640     return returnLineMetrics;
641 }
642 
OnGetLineMetricsAt(napi_env env,napi_callback_info info)643 napi_value JsParagraph::OnGetLineMetricsAt(napi_env env, napi_callback_info info)
644 {
645     if (paragraph_ == nullptr) {
646         TEXT_LOGE("JsParagraph::OnGetLineMetricsAt paragraph_ is nullptr");
647         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
648     }
649     size_t argc = ARGC_ONE;
650     napi_value argv[ARGC_ONE] = {nullptr};
651     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
652     if (status != napi_ok || argc < ARGC_ONE) {
653         TEXT_LOGE("JsParagraph::OnLayout Argc is invalid: %{public}zu", argc);
654         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
655     }
656     int lineNumber = 0;
657     if (!(ConvertFromJsValue(env, argv[0], lineNumber))) {
658         TEXT_LOGE("JsParagraph::OnGetLineMetricsAt Argv is invalid");
659         return NapiGetUndefined(env);
660     }
661     LineMetrics lineMetrics;
662     if (!paragraph_->GetLineMetricsAt(lineNumber, &lineMetrics)) {
663         return nullptr;
664     }
665     return CreateLineMetricsJsValue(env, lineMetrics);
666 }
667 
JsParagraph(std::shared_ptr<Typography> typography)668 JsParagraph::JsParagraph(std::shared_ptr<Typography> typography)
669     : paragraph_(typography)
670 {
671 }
672 
~JsParagraph()673 JsParagraph::~JsParagraph()
674 {
675 }
676 
GetParagraph()677 std::shared_ptr<Typography> JsParagraph::GetParagraph()
678 {
679     std::shared_ptr<Typography> typography = std::move(paragraph_);
680     return typography;
681 }
682 
CreateJsTypography(napi_env env,std::unique_ptr<Typography> typography)683 napi_value JsParagraph::CreateJsTypography(napi_env env, std::unique_ptr<Typography> typography)
684 {
685     napi_value constructor = nullptr;
686     napi_value result = nullptr;
687     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
688     if (status == napi_ok) {
689         g_Typography = std::move(typography);
690         status = napi_new_instance(env, constructor, 0, nullptr, &result);
691         if (status == napi_ok) {
692             return result;
693         } else {
694             TEXT_LOGE("CreateJsTypography: New instance could not be obtained");
695         }
696     }
697     return result;
698 }
699 
GetTextLines(napi_env env,napi_callback_info info)700 napi_value JsParagraph::GetTextLines(napi_env env, napi_callback_info info)
701 {
702     JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
703     return (me != nullptr) ? me->OnGetTextLines(env, info) : nullptr;
704 }
705 
OnGetTextLines(napi_env env,napi_callback_info info)706 napi_value JsParagraph::OnGetTextLines(napi_env env, napi_callback_info info)
707 {
708     if (!paragraph_) {
709         TEXT_LOGE("JsParagraph::OnGetTextLines paragraph_ is nullptr");
710         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
711     }
712 
713     std::shared_ptr<Typography> paragraphCopy = paragraph_->CloneSelf();
714     if (!paragraphCopy) {
715         TEXT_LOGE("JsParagraph::OnGetTextLines paragraphCopy is nullptr");
716         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
717     }
718 
719     std::vector<std::unique_ptr<TextLineBase>> textlineArr = paragraphCopy->GetTextLines();
720     napi_value array = nullptr;
721     NAPI_CALL(env, napi_create_array(env, &array));
722     uint32_t index = 0;
723     for (std::unique_ptr<TextLineBase>& item : textlineArr) {
724         napi_value itemObject = JsTextLine::CreateTextLine(env, info);
725         if (!itemObject) {
726             TEXT_LOGE("JsParagraph::OnGetTextLines itemObject is null");
727             continue;
728         }
729         JsTextLine* jsTextLine = nullptr;
730         napi_unwrap(env, itemObject, reinterpret_cast<void**>(&jsTextLine));
731         if (!jsTextLine) {
732             TEXT_LOGE("JsParagraph::OnGetTextLines napi_unwrap jsTextLine is null");
733             continue;
734         }
735         jsTextLine->SetTextLine(std::move(item));
736         jsTextLine->SetParagraph(paragraphCopy);
737 
738         napi_set_element(env, array, index++, itemObject);
739     }
740     return array;
741 }
742 } // namespace OHOS::Rosen
743