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 "ImageJS.h"
17 
18 #include <scene_plugin/interface/intf_scene.h>
19 #include "SceneJS.h"
20 
21 using namespace SCENE_NS;
22 
Init(napi_env env,napi_value exports)23 void ImageJS::Init(napi_env env, napi_value exports)
24 {
25     using namespace NapiApi;
26     // clang-format off
27     BASE_NS::vector<napi_property_descriptor> props;
28     SceneResourceImpl::GetPropertyDescs(props);
29     props.emplace_back(GetProperty<uint32_t, ImageJS, &ImageJS::GetWidth>("width"));
30     props.emplace_back(GetProperty<uint32_t, ImageJS, &ImageJS::GetHeight>("height"));
31 
32     // clang-format on
33 
34     napi_value func;
35     auto status = napi_define_class(
36         env, "Image", NAPI_AUTO_LENGTH, BaseObject::ctor<ImageJS>(), nullptr, props.size(), props.data(), &func);
37 
38     NapiApi::MyInstanceState* mis;
39     napi_get_instance_data(env, (void**)&mis);
40     mis->StoreCtor("Image", func);
41 }
42 
DisposeNative()43 void ImageJS::DisposeNative()
44 {
45     if (!disposed_) {
46         disposed_ = true;
47         LOG_F("ImageJS::DisposeNative");
48         NapiApi::Object obj = scene_.GetObject();
49         auto* tro = obj.Native<TrueRootObject>();
50         SceneJS* sceneJS;
51         if (tro) {
52             sceneJS = ((SceneJS*)tro->GetInstanceImpl(SceneJS::ID));
53             sceneJS->ReleaseDispose((uintptr_t)&scene_);
54         }
55         // reset the native object refs
56         if (auto bitmap = interface_pointer_cast<IBitmap>(GetNativeObject())) {
57             SetNativeObject(nullptr, false);
58             SetNativeObject(nullptr, true);
59             if (obj) {
60                 BASE_NS::string uri = FetchResourceOrUri(obj.GetEnv(), uriRef_.GetObject());
61                 ExecSyncTask([uri, sceneJS]() -> META_NS::IAny::Ptr {
62                     sceneJS->StoreBitmap(uri, nullptr);
63                     return {};
64                 });
65             }
66         } else {
67             SetNativeObject(nullptr, false);
68         }
69         scene_.Reset();
70     }
71 }
GetInstanceImpl(uint32_t id)72 void* ImageJS::GetInstanceImpl(uint32_t id)
73 {
74     if (id == ImageJS::ID) {
75         return this;
76     }
77     return SceneResourceImpl::GetInstanceImpl(id);
78 }
Finalize(napi_env env)79 void ImageJS::Finalize(napi_env env)
80 {
81     DisposeNative();
82     BaseObject<ImageJS>::Finalize(env);
83 }
84 
ImageJS(napi_env e,napi_callback_info i)85 ImageJS::ImageJS(napi_env e, napi_callback_info i)
86     : BaseObject<ImageJS>(e, i), SceneResourceImpl(SceneResourceType::IMAGE)
87 {
88     NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
89     NapiApi::Object meJs(e, fromJs.This());
90     NapiApi::Object scene = fromJs.Arg<0>(); // access to owning scene...
91     scene_ = { scene };
92     if (!GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject())) {
93         CORE_LOG_F("INVALID SCENE!");
94     }
95 
96     auto* tro = scene.Native<TrueRootObject>();
97     auto* sceneJS = ((SceneJS*)tro->GetInstanceImpl(SceneJS::ID));
98     NapiApi::Object args = fromJs.Arg<1>();
99 
100     SCENE_NS::IBitmap::Ptr bitmap;
101 
102     // check if we got the NativeObject as parameter.
103     bitmap = GetNativeObjectParam<SCENE_NS::IBitmap>(args);
104 
105     if (auto prm = args.Get("uri")) {
106         uriRef_ = { e, prm };
107         BASE_NS::string uri = FetchResourceOrUri(e, prm);
108         if (!uri.empty()) {
109             SetUri(uriRef_);
110         }
111         if (!bitmap) {
112             // if we did not receive it already...
113             bitmap = sceneJS->FetchBitmap(uri);
114         }
115     }
116     sceneJS->DisposeHook((uintptr_t)&scene_, meJs);
117     auto obj = interface_pointer_cast<META_NS::IObject>(bitmap);
118     SetNativeObject(obj, false);
119     StoreJsObj(obj, meJs);
120 
121     BASE_NS::string name;
122     if (auto prm = args.Get<BASE_NS::string>("name")) {
123         name = prm;
124     } else {
125         if (auto named = interface_cast<META_NS::INamed>(obj)) {
126             name = named->Name()->GetValue();
127         }
128     }
129     meJs.Set("name", name);
130 }
131 
~ImageJS()132 ImageJS::~ImageJS()
133 {
134     DisposeNative();
135 }
136 
GetWidth(NapiApi::FunctionContext<> & ctx)137 napi_value ImageJS::GetWidth(NapiApi::FunctionContext<>& ctx)
138 {
139     uint32_t width = 0;
140     if (auto env = interface_cast<IBitmap>(GetNativeObject())) {
141         ExecSyncTask([env, &width]() {
142             width = env->Size()->GetValue().x;
143             return META_NS::IAny::Ptr {};
144         });
145     }
146     napi_value value;
147     napi_create_uint32(ctx, width, &value);
148     return value;
149 }
150 
GetHeight(NapiApi::FunctionContext<> & ctx)151 napi_value ImageJS::GetHeight(NapiApi::FunctionContext<>& ctx)
152 {
153     uint32_t height = 0;
154     if (auto env = interface_cast<IBitmap>(GetNativeObject())) {
155         ExecSyncTask([env, &height]() {
156             height = env->Size()->GetValue().y;
157             return META_NS::IAny::Ptr {};
158         });
159     }
160     napi_value value;
161     napi_create_uint32(ctx, height, &value);
162     return value;
163 }
164