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 #include "ImageJS.h"
16
17 #include <scene/interface/intf_scene.h>
18
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 GetInstanceData(env, (void**)&mis);
40 mis->StoreCtor("Image", func);
41 }
42
DisposeNative(void * sc)43 void ImageJS::DisposeNative(void* sc)
44 {
45 if (!disposed_) {
46 disposed_ = true;
47 LOG_V("ImageJS::DisposeNative");
48 NapiApi::Object obj = scene_.GetObject();
49 SceneJS* sceneJS = nullptr;
50 if (sc) {
51 sceneJS = static_cast<SceneJS*>(sc);
52 } else {
53 auto* tro = obj.Native<TrueRootObject>();
54 if (tro) {
55 sceneJS = static_cast<SceneJS*>(tro->GetInstanceImpl(SceneJS::ID));
56 }
57 }
58 if (sc) {
59 sceneJS->ReleaseDispose(reinterpret_cast<uintptr_t>(&scene_));
60 }
61 // reset the native object refs
62 if (auto bitmap = interface_pointer_cast<IBitmap>(GetNativeObject())) {
63 SetNativeObject(nullptr, false);
64 SetNativeObject(nullptr, true);
65 if (obj) {
66 BASE_NS::string uri =
67 FetchResourceOrUri(uri_.GetEnv(), uri_.GetObject().ToNapiValue());
68 ExecSyncTask([uri, sceneJS]() -> META_NS::IAny::Ptr {
69 if (sceneJS) {
70 sceneJS->StoreBitmap(uri, nullptr);
71 }
72 return {};
73 });
74 }
75 } else {
76 SetNativeObject(nullptr, false);
77 }
78 scene_.Reset();
79 }
80 }
GetInstanceImpl(uint32_t id)81 void* ImageJS::GetInstanceImpl(uint32_t id)
82 {
83 if (id == ImageJS::ID)
84 return this;
85 return SceneResourceImpl::GetInstanceImpl(id);
86 }
Finalize(napi_env env)87 void ImageJS::Finalize(napi_env env)
88 {
89 DisposeNative(nullptr);
90 BaseObject<ImageJS>::Finalize(env);
91 }
92
ImageJS(napi_env e,napi_callback_info i)93 ImageJS::ImageJS(napi_env e, napi_callback_info i)
94 : BaseObject<ImageJS>(e, i), SceneResourceImpl(SceneResourceType::IMAGE)
95 {
96 NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
97 NapiApi::Object meJs(fromJs.This());
98 NapiApi::Object scene = fromJs.Arg<0>(); // access to owning scene...
99 scene_ = { scene };
100 if (!GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject())) {
101 LOG_F("INVALID SCENE!");
102 }
103
104 SceneJS* sceneJS = nullptr;
105 auto* tro = scene.Native<TrueRootObject>();
106 if (tro) {
107 sceneJS = static_cast<SceneJS*>(tro->GetInstanceImpl(SceneJS::ID));
108 }
109 NapiApi::Object args = fromJs.Arg<1>();
110
111 SCENE_NS::IBitmap::Ptr bitmap;
112
113 // check if we got the NativeObject as parameter.
114 bitmap = GetNativeObjectParam<SCENE_NS::IBitmap>(args);
115
116 if (auto prm = args.Get("uri")) {
117 NapiApi::Object resType = args.Get<NapiApi::Object>("uri");
118 BASE_NS::string uriType = args.Get<BASE_NS::string>("uri");
119
120 BASE_NS::string uri = FetchResourceOrUri(args.GetEnv(), prm);
121 if (!uri.empty()) {
122 if (!resType) {
123 // raw string then.. make it "resource" / "rawfile" if possible.
124 if (uri.find("OhosRawFile://") == 0) {
125 // we can only convert "OhosRawFile://" type uris back to "resource" objects.
126 NapiApi::Env env(e);
127 napi_value global;
128 napi_get_global(env, &global);
129 NapiApi::Object g(env, global);
130 napi_value func = g.Get("$rawfile");
131 NapiApi::Function f(env, func);
132 if (f) {
133 BASE_NS::string noschema(uri.substr(14)); // 14: length
134 napi_value arg = env.GetString(noschema);
135 napi_value res = f.Invoke(g, 1, &arg);
136 SetUri(NapiApi::StrongRef(env, res));
137 }
138 }
139 } else {
140 SetUri(NapiApi::StrongRef(resType));
141 }
142 }
143 if (!bitmap) {
144 // if we did not receive it already...
145 if (sceneJS) {
146 bitmap = sceneJS->FetchBitmap(uri);
147 }
148 }
149 }
150 if (sceneJS) {
151 sceneJS->DisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
152 }
153 auto obj = interface_pointer_cast<META_NS::IObject>(bitmap);
154 SetNativeObject(obj, false);
155 StoreJsObj(obj, meJs);
156
157 BASE_NS::string name;
158 if (auto prm = args.Get<BASE_NS::string>("name"); prm.IsDefined()) {
159 name = prm;
160 } else {
161 if (auto named = interface_cast<META_NS::IObject>(obj)) {
162 name = named->GetName();
163 }
164 }
165 meJs.Set("name", name);
166 }
167
~ImageJS()168 ImageJS::~ImageJS()
169 {
170 DisposeNative(nullptr);
171 }
172
GetWidth(NapiApi::FunctionContext<> & ctx)173 napi_value ImageJS::GetWidth(NapiApi::FunctionContext<>& ctx)
174 {
175 if (!validateSceneRef()) {
176 return ctx.GetUndefined();
177 }
178 uint32_t width = 0;
179 if (auto env = interface_cast<IBitmap>(GetNativeObject())) {
180 width = env->Size()->GetValue().x;
181 }
182 return ctx.GetNumber(width);
183 }
184
GetHeight(NapiApi::FunctionContext<> & ctx)185 napi_value ImageJS::GetHeight(NapiApi::FunctionContext<>& ctx)
186 {
187 if (!validateSceneRef()) {
188 return ctx.GetUndefined();
189 }
190 uint32_t height = 0;
191 if (auto env = interface_cast<IBitmap>(GetNativeObject())) {
192 height = env->Size()->GetValue().y;
193 }
194 return ctx.GetNumber(height);
195 }
196