• 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 "TextNodeJS.h"
17 
18 #include <font/implementation_uids.h>
19 #include <font/intf_font_manager.h>
20 #include <scene/ext/intf_ecs_context.h>
21 #include <scene/ext/intf_ecs_object_access.h>
22 #include <scene/interface/intf_node.h>
23 #include <scene/interface/intf_scene.h>
24 #include <scene/interface/intf_text.h>
25 
26 #include <render/implementation_uids.h>
27 
28 #include "SceneJS.h"
29 
30 namespace {
PrintFontsFromNode(const SCENE_NS::INode::Ptr & someNode)31 void PrintFontsFromNode(const SCENE_NS::INode::Ptr& someNode)
32 {
33     if (auto ecsAccess = interface_pointer_cast<SCENE_NS::IEcsObjectAccess>(someNode)) {
34         if (auto engineClassRegister = ecsAccess->GetEcsObject()->
35 	    GetScene()->GetEcsContext().GetNativeEcs()->GetClassFactory().GetInterface<CORE_NS::IClassRegister>()) {
36             if (auto* renderClassRegister = CORE_NS::GetInstance<CORE_NS::IClassRegister>(
37                     *engineClassRegister, RENDER_NS::UID_RENDER_CONTEXT)) {
38                 auto fontManager =
39                     CORE_NS::GetInstance<FONT_NS::IFontManager>(*renderClassRegister, FONT_NS::UID_FONT_MANAGER);
40 
41                 CORE_LOG_E("Fonts");
42                 for (auto& face : fontManager->GetTypeFaces()) {
43                     CORE_LOG_E("face: \"%s\" family: \"%s\"", BASE_NS::string(face.name).c_str(),
44                         BASE_NS::string(face.styleName).c_str());
45                 }
46             }
47         }
48     }
49 }
50 } // anonymous namespace
51 
Init(napi_env env,napi_value exports)52 void TextNodeJS::Init(napi_env env, napi_value exports)
53 {
54     using namespace NapiApi;
55 
56     BASE_NS::vector<napi_property_descriptor> node_props = {
57         GetSetProperty<BASE_NS::string, TextNodeJS, &TextNodeJS::GetText, &TextNodeJS::SetText>("text"),
58         GetSetProperty<BASE_NS::string, TextNodeJS, &TextNodeJS::GetFont, &TextNodeJS::SetFont>("font"),
59         GetSetProperty<NapiApi::Object, TextNodeJS, &TextNodeJS::GetColor, &TextNodeJS::SetColor>("color"),
60         GetSetProperty<float, TextNodeJS, &TextNodeJS::GetFontSize, &TextNodeJS::SetFontSize>("fontSize"),
61     };
62     NodeImpl::GetPropertyDescs(node_props);
63 
64     napi_value func;
65     auto status = napi_define_class(env, "TextNode", NAPI_AUTO_LENGTH, BaseObject::ctor<TextNodeJS>(), nullptr,
66         node_props.size(), node_props.data(), &func);
67 
68     NapiApi::MyInstanceState* mis;
69     GetInstanceData(env, (void**)&mis);
70     mis->StoreCtor("TextNode", func);
71 }
72 
TextNodeJS(napi_env e,napi_callback_info i)73 TextNodeJS::TextNodeJS(napi_env e, napi_callback_info i) : BaseObject<TextNodeJS>(e, i), NodeImpl(NodeImpl::TEXT)
74 {
75     LOG_V("TextNodeJS ++");
76 
77     NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
78     if (!fromJs) {
79         // no arguments. so internal create.
80         // expecting caller to finish initialization
81         return;
82     }
83 
84     {
85         // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed)
86         NapiApi::Object meJs(fromJs.This());
87         NapiApi::Object scene = fromJs.Arg<0>();
88         if (auto sceneJS = GetJsWrapper<SceneJS>(scene)) {
89             sceneJS->StrongDisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
90         }
91     }
92 
93     // java script call.. with arguments
94     scene_ = fromJs.Arg<0>().valueOrDefault();
95     auto scn = GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject());
96     if (scn == nullptr) {
97         // hmm..
98         LOG_F("Invalid scene for TextNodeJS!");
99         return;
100     }
101     NapiApi::Object args = fromJs.Arg<1>();
102 
103     auto obj = GetNativeObjectParam<META_NS::IObject>(args);
104     if (obj) {
105         StoreJsObj(obj, fromJs.This());
106         return;
107     }
108 
109     // collect parameters
110     NapiApi::Value<BASE_NS::string> name;
111     NapiApi::Value<BASE_NS::string> path;
112     if (auto prm = args.Get("name")) {
113         name = NapiApi::Value<BASE_NS::string>(e, prm);
114     }
115     if (auto prm = args.Get("path")) {
116         path = NapiApi::Value<BASE_NS::string>(e, prm);
117     }
118 
119     BASE_NS::string nodePath;
120 
121     if (path.IsDefined()) {
122         // create using path
123         nodePath = path.valueOrDefault("");
124     } else if (name.IsDefined()) {
125         // use the name as path (creates under root)
126         nodePath = name.valueOrDefault("");
127     }
128 
129     // Create actual node object.
130     SCENE_NS::INode::Ptr node = scn->CreateNode(nodePath, Scene::ClassId::TextNode).GetResult();
131 
132     SetNativeObject(interface_pointer_cast<META_NS::IObject>(node), false);
133     node.reset();
134     NapiApi::Object meJs(fromJs.This());
135     StoreJsObj(GetNativeObject(), meJs);
136 
137     if (name.IsDefined()) {
138         // set the name of the object. if we were given one
139         meJs.Set("name", name);
140     }
141 }
142 
~TextNodeJS()143 TextNodeJS::~TextNodeJS()
144 {
145     LOG_V("TextNodeJS --");
146 }
147 
GetInstanceImpl(uint32_t id)148 void* TextNodeJS::GetInstanceImpl(uint32_t id)
149 {
150     if (id == TextNodeJS::ID)
151         return this;
152     return NodeImpl::GetInstanceImpl(id);
153 }
154 
DisposeNative(void * sc)155 void TextNodeJS::DisposeNative(void* sc)
156 {
157     if (!disposed_) {
158         LOG_V("TextNodeJS::DisposeNative");
159         disposed_ = true;
160 
161         if (auto* sceneJS = static_cast<SceneJS*>(sc)) {
162             sceneJS->ReleaseStrongDispose(reinterpret_cast<uintptr_t>(&scene_));
163         }
164 
165         scene_.Reset();
166     }
167 }
168 
Finalize(napi_env env)169 void TextNodeJS::Finalize(napi_env env)
170 {
171     DisposeNative(GetJsWrapper<SceneJS>(scene_.GetObject()));
172     BaseObject::Finalize(env);
173 }
174 
GetText(NapiApi::FunctionContext<> & ctx)175 napi_value TextNodeJS::GetText(NapiApi::FunctionContext<>& ctx)
176 {
177     if (!validateSceneRef()) {
178         return ctx.GetUndefined();
179     }
180 
181     BASE_NS::string name;
182     auto native = GetThisNativeObject(ctx);
183     auto object = interface_pointer_cast<META_NS::IObject>(native);
184     auto node = interface_pointer_cast<SCENE_NS::INode>(native);
185     auto text = interface_pointer_cast<SCENE_NS::IText>(native);
186     if (!object || !node || !text) {
187         LOG_E("NodeImpl not a text node! %p %p %p %p", native.get(), object.get(), node.get(), text.get());
188         return ctx.GetUndefined();
189     }
190 
191     auto result = META_NS::GetValue(text->Text());
192 
193     return ctx.GetString(result);
194 }
195 
SetText(NapiApi::FunctionContext<BASE_NS::string> & ctx)196 void TextNodeJS::SetText(NapiApi::FunctionContext<BASE_NS::string>& ctx)
197 {
198     if (!validateSceneRef()) {
199         return;
200     }
201 
202     BASE_NS::string text = ctx.Arg<0>();
203 
204     if (auto textNode = interface_pointer_cast<SCENE_NS::IText>(GetThisNativeObject(ctx))) {
205         textNode->Text()->SetValue(text);
206         if (auto node = interface_pointer_cast<SCENE_NS::INode>(textNode)) {
207             PrintFontsFromNode(node);
208         }
209     } else {
210         LOG_W("Unable to set text value to TextNode");
211     }
212 }
213 
GetFont(NapiApi::FunctionContext<> & ctx)214 napi_value TextNodeJS::GetFont(NapiApi::FunctionContext<>& ctx)
215 {
216     if (!validateSceneRef()) {
217         return ctx.GetUndefined();
218     }
219 
220     auto native = GetThisNativeObject(ctx);
221     auto object = interface_pointer_cast<META_NS::IObject>(native);
222     auto node = interface_pointer_cast<SCENE_NS::INode>(native);
223     auto text = interface_pointer_cast<SCENE_NS::IText>(native);
224     if (!object || !node || !text) {
225         LOG_E("NodeImpl not a text node! %p %p %p %p", native.get(), object.get(), node.get(), text.get());
226         return ctx.GetUndefined();
227     }
228 
229     auto result = META_NS::GetValue(text->FontFamily());
230 
231     return ctx.GetString(result);
232 }
233 
SetFont(NapiApi::FunctionContext<BASE_NS::string> & ctx)234 void TextNodeJS::SetFont(NapiApi::FunctionContext<BASE_NS::string>& ctx)
235 {
236     if (!validateSceneRef()) {
237         return;
238     }
239 
240     BASE_NS::string font = ctx.Arg<0>();
241 
242     if (auto textNode = interface_pointer_cast<SCENE_NS::IText>(GetThisNativeObject(ctx))) {
243         textNode->FontFamily()->SetValue(font);
244     } else {
245         LOG_W("Unable to set font to TextNode");
246     }
247 }
248 
GetColor(NapiApi::FunctionContext<> & ctx)249 napi_value TextNodeJS::GetColor(NapiApi::FunctionContext<>& ctx)
250 {
251     if (!validateSceneRef()) {
252         return ctx.GetUndefined();
253     }
254 
255     auto native = GetThisNativeObject(ctx);
256     auto object = interface_pointer_cast<META_NS::IObject>(native);
257     auto node = interface_pointer_cast<SCENE_NS::INode>(native);
258     auto text = interface_pointer_cast<SCENE_NS::IText>(native);
259     if (!object || !node || !text) {
260         LOG_E("NodeImpl not a text node! %p %p %p %p", native.get(), object.get(), node.get(), text.get());
261         return ctx.GetUndefined();
262     }
263 
264     if (!color_) {
265         color_ = BASE_NS::make_unique<ColorProxy>(ctx.Env(), text->TextColor());
266     }
267 
268     return color_->Value();
269 }
270 
SetColor(NapiApi::FunctionContext<NapiApi::Object> & ctx)271 void TextNodeJS::SetColor(NapiApi::FunctionContext<NapiApi::Object>& ctx)
272 {
273     if (!validateSceneRef()) {
274         return;
275     }
276 
277     auto native = GetThisNativeObject(ctx);
278     auto object = interface_pointer_cast<META_NS::IObject>(native);
279     auto node = interface_pointer_cast<SCENE_NS::INode>(native);
280     auto text = interface_pointer_cast<SCENE_NS::IText>(native);
281     if (!object || !node || !text) {
282         LOG_E("NodeImpl not a text node! %p %p %p %p", native.get(), object.get(), node.get(), text.get());
283         return;
284     }
285 
286     if (!color_) {
287         color_ = BASE_NS::make_unique<ColorProxy>(ctx.Env(), text->TextColor());
288     }
289 
290     color_->SetValue(ctx.Arg<0>());
291 }
292 
GetFontSize(NapiApi::FunctionContext<> & ctx)293 napi_value TextNodeJS::GetFontSize(NapiApi::FunctionContext<>& ctx)
294 {
295     if (!validateSceneRef()) {
296         return ctx.GetUndefined();
297     }
298 
299     auto native = GetThisNativeObject(ctx);
300     auto object = interface_pointer_cast<META_NS::IObject>(native);
301     auto node = interface_pointer_cast<SCENE_NS::INode>(native);
302     auto text = interface_pointer_cast<SCENE_NS::IText>(native);
303     if (!object || !node || !text) {
304         LOG_E("NodeImpl not a text node! %p %p %p %p", native.get(), object.get(), node.get(), text.get());
305         return ctx.GetUndefined();
306     }
307 
308     auto result = META_NS::GetValue(text->FontSize());
309 
310     return ctx.GetNumber(result);
311 }
312 
SetFontSize(NapiApi::FunctionContext<float> & ctx)313 void TextNodeJS::SetFontSize(NapiApi::FunctionContext<float>& ctx)
314 {
315     if (!validateSceneRef()) {
316         return;
317     }
318 
319     float fontSize = ctx.Arg<0>();
320 
321     if (auto textNode = interface_pointer_cast<SCENE_NS::IText>(GetThisNativeObject(ctx))) {
322         textNode->FontSize()->SetValue(fontSize);
323     } else {
324         LOG_W("Unable to set font size to TextNode");
325     }
326 }
327