• 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 "canvas_napi/js_canvas.h"
17 #include "js_text_line.h"
18 #include "recording/recording_canvas.h"
19 #include "run_napi/js_run.h"
20 #include "utils/text_log.h"
21 
22 namespace OHOS::Rosen {
23 namespace {
24 const std::string CLASS_NAME = "TextLine";
25 }
26 thread_local napi_ref JsTextLine::constructor_ = nullptr;
27 
Constructor(napi_env env,napi_callback_info info)28 napi_value JsTextLine::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 napi_get_cb_info");
35         return nullptr;
36     }
37     JsTextLine *jsTextLineBase = new(std::nothrow) JsTextLine();
38     if (!jsTextLineBase) {
39         TEXT_LOGE("failed to create JsTextLine");
40         return nullptr;
41     }
42     status = napi_wrap(env, jsThis, jsTextLineBase,
43                        JsTextLine::Destructor, nullptr, nullptr);
44     if (status != napi_ok) {
45         delete jsTextLineBase;
46         TEXT_LOGE("JsTextLine::Constructor Failed to wrap native instance");
47         return nullptr;
48     }
49     return jsThis;
50 }
51 
52 
Init(napi_env env,napi_value exportObj)53 napi_value JsTextLine::Init(napi_env env, napi_value exportObj)
54 {
55     napi_property_descriptor properties[] = {
56         DECLARE_NAPI_FUNCTION("getGlyphCount", JsTextLine::GetGlyphCount),
57         DECLARE_NAPI_FUNCTION("getGlyphRuns", JsTextLine::GetGlyphRuns),
58         DECLARE_NAPI_FUNCTION("getTextRange", JsTextLine::GetTextRange),
59         DECLARE_NAPI_FUNCTION("paint", JsTextLine::Paint),
60     };
61 
62     napi_value constructor = nullptr;
63     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
64         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
65     if (status != napi_ok) {
66         TEXT_LOGE("Failed to define TextLine class");
67         return nullptr;
68     }
69 
70     status = napi_create_reference(env, constructor, 1, &constructor_);
71     if (status != napi_ok) {
72         TEXT_LOGE("Failed to create reference of constructor");
73         return nullptr;
74     }
75     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
76     if (status != napi_ok) {
77         TEXT_LOGE("Failed to set constructor");
78         return nullptr;
79     }
80     return exportObj;
81 }
82 
Destructor(napi_env env,void * nativeObject,void * finalize)83 void JsTextLine::Destructor(napi_env env, void *nativeObject, void *finalize)
84 {
85     (void)finalize;
86     if (nativeObject != nullptr) {
87         JsTextLine *napi = reinterpret_cast<JsTextLine *>(nativeObject);
88         delete napi;
89     }
90 }
91 
CreateTextLine(napi_env env,napi_callback_info info)92 napi_value JsTextLine::CreateTextLine(napi_env env, napi_callback_info info)
93 {
94     napi_value result = nullptr;
95     napi_value constructor = nullptr;
96     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
97     if (status != napi_ok) {
98         TEXT_LOGE("Failed to get the representation of constructor object");
99         return nullptr;
100     }
101 
102     status = napi_new_instance(env, constructor, 0, nullptr, &result);
103     if (status != napi_ok) {
104         TEXT_LOGE("Failed to instantiate JavaScript font instance");
105         return nullptr;
106     }
107     return result;
108 }
109 
JsTextLine()110 JsTextLine::JsTextLine()
111 {
112 }
113 
SetTextLine(std::unique_ptr<TextLineBase> textLine)114 void JsTextLine::SetTextLine(std::unique_ptr<TextLineBase> textLine)
115 {
116     textLine_ = std::move(textLine);
117 }
118 
GetGlyphCount(napi_env env,napi_callback_info info)119 napi_value JsTextLine::GetGlyphCount(napi_env env, napi_callback_info info)
120 {
121     JsTextLine* me = CheckParamsAndGetThis<JsTextLine>(env, info);
122     return (me != nullptr) ? me->OnGetGlyphCount(env, info) : nullptr;
123 }
124 
GetGlyphRuns(napi_env env,napi_callback_info info)125 napi_value JsTextLine::GetGlyphRuns(napi_env env, napi_callback_info info)
126 {
127     JsTextLine* me = CheckParamsAndGetThis<JsTextLine>(env, info);
128     return (me != nullptr) ? me->OnGetGlyphRuns(env, info) : nullptr;
129 }
130 
GetTextRange(napi_env env,napi_callback_info info)131 napi_value JsTextLine::GetTextRange(napi_env env, napi_callback_info info)
132 {
133     JsTextLine* me = CheckParamsAndGetThis<JsTextLine>(env, info);
134     return (me != nullptr) ? me->OnGetTextRange(env, info) : nullptr;
135 }
136 
Paint(napi_env env,napi_callback_info info)137 napi_value JsTextLine::Paint(napi_env env, napi_callback_info info)
138 {
139     JsTextLine* me = CheckParamsAndGetThis<JsTextLine>(env, info);
140     return (me != nullptr) ? me->OnPaint(env, info) : nullptr;
141 }
142 
OnGetGlyphCount(napi_env env,napi_callback_info info)143 napi_value JsTextLine::OnGetGlyphCount(napi_env env, napi_callback_info info)
144 {
145     if (textLine_ == nullptr) {
146         TEXT_LOGE("JsTextLine::OnGetGlyphCount textLine_ is nullptr");
147         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
148     }
149 
150     uint32_t textSize = textLine_->GetGlyphCount();
151     return CreateJsValue(env, textSize);
152 }
153 
OnGetGlyphRuns(napi_env env,napi_callback_info info)154 napi_value JsTextLine::OnGetGlyphRuns(napi_env env, napi_callback_info info)
155 {
156     if (textLine_ == nullptr) {
157         TEXT_LOGE("JsTextLine::OnGetGlyphRuns TextLine is nullptr");
158         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
159     }
160     std::vector<std::unique_ptr<Run>> runs = textLine_->GetGlyphRuns();
161     if (runs.empty()) {
162         TEXT_LOGE("JsTextLine::OnGetGlyphRuns runs is empty");
163         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
164     }
165     napi_value array = nullptr;
166     NAPI_CALL(env, napi_create_array(env, &array));
167     uint32_t index = 0;
168     for (std::unique_ptr<Run>& item : runs) {
169         napi_value itemObject = JsRun::CreateRun(env, info);
170         if (!itemObject) {
171             TEXT_LOGE("JsTextLine::OnGetGlyphRuns itemObject is null");
172             continue;
173         }
174         JsRun* jsRun = nullptr;
175         napi_unwrap(env, itemObject, reinterpret_cast<void**>(&jsRun));
176         if (!jsRun) {
177             TEXT_LOGE("JsTextLine::OnGetGlyphRuns napi_unwrap jsRun is null");
178             continue;
179         }
180         jsRun->SetRun(std::move(item));
181         jsRun->SetParagraph(paragraph_);
182         napi_set_element(env, array, index++, itemObject);
183     }
184     return array;
185 }
186 
OnGetTextRange(napi_env env,napi_callback_info info)187 napi_value JsTextLine::OnGetTextRange(napi_env env, napi_callback_info info)
188 {
189     if (textLine_ == nullptr) {
190         TEXT_LOGE("JsTextLine::OnGetTextRange TextLine is nullptr");
191         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
192     }
193 
194     Boundary boundary = textLine_->GetTextRange();
195     napi_value objValue = nullptr;
196     napi_create_object(env, &objValue);
197     if (objValue != nullptr) {
198         napi_set_named_property(env, objValue, "start", CreateJsNumber(env, boundary.leftIndex));
199         napi_set_named_property(env, objValue, "end", CreateJsNumber(env, boundary.rightIndex));
200     }
201     return objValue;
202 }
203 
OnPaint(napi_env env,napi_callback_info info)204 napi_value JsTextLine::OnPaint(napi_env env, napi_callback_info info)
205 {
206     if (textLine_ == nullptr) {
207         TEXT_LOGE("JsTextLine::OnPaint TextLine is nullptr");
208         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
209     }
210     size_t argc = ARGC_THREE;
211     napi_value argv[ARGC_THREE] = {nullptr};
212     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
213     if (status != napi_ok || argc < ARGC_THREE) {
214         TEXT_LOGE("JsTextLine::OnPaint Argc is invalid: %{public}zu", argc);
215         return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
216     }
217     if (argv[0] == nullptr) {
218         TEXT_LOGE("JsTextLine::OnPaint argv[0] is invalid");
219         return NapiGetUndefined(env);
220     }
221     Drawing::JsCanvas* jsCanvas = nullptr;
222     napi_unwrap(env, argv[0], reinterpret_cast<void**>(&jsCanvas));
223     if (!jsCanvas || !jsCanvas->GetCanvas()) {
224         TEXT_LOGE("JsTextLine::OnPaint jsCanvas is nullptr");
225         return NapiGetUndefined(env);
226     }
227     double x = 0.0;
228     double y = 0.0;
229     if (!(argv[ARGC_ONE] != nullptr && ConvertFromJsValue(env, argv[ARGC_ONE], x) &&
230         argv[ARGC_TWO] != nullptr && ConvertFromJsValue(env, argv[ARGC_TWO], y))) {
231         return NapiGetUndefined(env);
232     }
233     textLine_->Paint(jsCanvas->GetCanvas(), x, y);
234 
235     return NapiGetUndefined(env);
236 }
237 
GetTextLineBase()238 std::unique_ptr<TextLineBase> JsTextLine::GetTextLineBase()
239 {
240     return std::move(textLine_);
241 }
242 
SetParagraph(std::shared_ptr<Typography> paragraph)243 void JsTextLine::SetParagraph(std::shared_ptr<Typography> paragraph)
244 {
245     paragraph_ = paragraph;
246 }
247 } // namespace OHOS::Rosen