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_image_filter.h"
17 
18 #include "native_value.h"
19 
20 #include "js_drawing_utils.h"
21 
22 namespace OHOS::Rosen {
23 namespace Drawing {
24 const std::string CLASS_NAME = "ImageFilter";
25 thread_local napi_ref JsImageFilter::constructor_ = nullptr;
Init(napi_env env,napi_value exportObj)26 napi_value JsImageFilter::Init(napi_env env, napi_value exportObj)
27 {
28     napi_property_descriptor properties[] = {
29         DECLARE_NAPI_STATIC_FUNCTION("createBlurImageFilter", JsImageFilter::CreateBlurImageFilter),
30         DECLARE_NAPI_STATIC_FUNCTION("createFromColorFilter", JsImageFilter::CreateFromColorFilter),
31     };
32 
33     napi_value constructor = nullptr;
34     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
35                                            sizeof(properties) / sizeof(properties[0]), properties, &constructor);
36     if (status != napi_ok) {
37         ROSEN_LOGE("JsImageFilter::Init Failed to define jsImageFilter class");
38         return nullptr;
39     }
40 
41     status = napi_create_reference(env, constructor, 1, &constructor_);
42     if (status != napi_ok) {
43         ROSEN_LOGE("JsImageFilter::Init Failed to create reference of constructor");
44         return nullptr;
45     }
46 
47     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
48     if (status != napi_ok) {
49         ROSEN_LOGE("JsImageFilter::Init Failed to set constructor");
50         return nullptr;
51     }
52 
53     status = napi_define_properties(env, exportObj, sizeof(properties) / sizeof(properties[0]), properties);
54     if (status != napi_ok) {
55         ROSEN_LOGE("JsImageFilter::Init Failed to define static function");
56         return nullptr;
57     }
58     return exportObj;
59 }
60 
Finalizer(napi_env env,void * data,void * hint)61 void JsImageFilter::Finalizer(napi_env env, void* data, void* hint)
62 {
63     std::unique_ptr<JsImageFilter>(static_cast<JsImageFilter*>(data));
64 }
65 
~JsImageFilter()66 JsImageFilter::~JsImageFilter()
67 {
68     m_ImageFilter = nullptr;
69 }
70 
Constructor(napi_env env,napi_callback_info info)71 napi_value JsImageFilter::Constructor(napi_env env, napi_callback_info info)
72 {
73     size_t argCount = 0;
74     napi_value jsThis = nullptr;
75     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
76     if (status != napi_ok) {
77         ROSEN_LOGE("JsImageFilter::Constructor failed to napi_get_cb_info");
78         return nullptr;
79     }
80 
81     JsImageFilter *jsImageFilter = new JsImageFilter();
82 
83     status = napi_wrap(env, jsThis, jsImageFilter, JsImageFilter::Destructor, nullptr, nullptr);
84     if (status != napi_ok) {
85         delete jsImageFilter;
86         ROSEN_LOGE("JsImageFilter::Constructor Failed to wrap native instance");
87         return nullptr;
88     }
89     return jsThis;
90 }
91 
Destructor(napi_env env,void * nativeObject,void * finalize)92 void JsImageFilter::Destructor(napi_env env, void *nativeObject, void *finalize)
93 {
94     (void)finalize;
95     if (nativeObject != nullptr) {
96         JsImageFilter *napi = reinterpret_cast<JsImageFilter *>(nativeObject);
97         delete napi;
98     }
99 }
100 
CreateBlurImageFilter(napi_env env,napi_callback_info info)101 napi_value JsImageFilter::CreateBlurImageFilter(napi_env env, napi_callback_info info)
102 {
103     size_t argc = ARGC_FOUR;
104     napi_value argv[ARGC_FOUR] = {nullptr};
105     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_THREE, ARGC_FOUR);
106 
107     double sigmaX = 0;
108     GET_DOUBLE_CHECK_GT_ZERO_PARAM(ARGC_ZERO, sigmaX);
109 
110     double sigmaY = 0;
111     GET_DOUBLE_CHECK_GT_ZERO_PARAM(ARGC_ONE, sigmaY);
112 
113     int32_t tMode = 0;
114     GET_ENUM_PARAM(ARGC_TWO, tMode, 0, static_cast<int32_t>(TileMode::DECAL));
115 
116     JsImageFilter *jsImageFilter = nullptr;
117     if (argc > ARGC_THREE) {
118         GET_UNWRAP_PARAM_OR_NULL(ARGC_THREE, jsImageFilter);
119     }
120 
121     std::shared_ptr<ImageFilter> imageFilter = (jsImageFilter == nullptr) ?
122         nullptr : jsImageFilter->GetImageFilter();
123 
124     std::shared_ptr<ImageFilter> imgFilter = ImageFilter::CreateBlurImageFilter(sigmaX, sigmaY,
125         static_cast<TileMode>(tMode), imageFilter, ImageBlurType::GAUSS);
126     return JsImageFilter::Create(env, imgFilter);
127 }
128 
CreateFromColorFilter(napi_env env,napi_callback_info info)129 napi_value JsImageFilter::CreateFromColorFilter(napi_env env, napi_callback_info info)
130 {
131     size_t argc = ARGC_TWO;
132     napi_value argv[ARGC_TWO] = {nullptr};
133     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
134 
135     JsColorFilter *jsColorFilter = nullptr;
136     GET_UNWRAP_PARAM(ARGC_ZERO, jsColorFilter);
137 
138     JsImageFilter *jsImageFilter = nullptr;
139     if (argc > ARGC_ONE) {
140         GET_UNWRAP_PARAM_OR_NULL(ARGC_ONE, jsImageFilter);
141     }
142 
143     std::shared_ptr<ColorFilter> colorFilter = jsColorFilter->GetColorFilter();
144     std::shared_ptr<ImageFilter> imageFilter = (jsImageFilter == nullptr) ?
145         nullptr : jsImageFilter->GetImageFilter();
146 
147     std::shared_ptr<ImageFilter> imgFilter = ImageFilter::CreateColorFilterImageFilter(*colorFilter, imageFilter);
148     return JsImageFilter::Create(env, imgFilter);
149 }
150 
Create(napi_env env,const std::shared_ptr<ImageFilter> imageFilter)151 napi_value JsImageFilter::Create(napi_env env, const std::shared_ptr<ImageFilter> imageFilter)
152 {
153     napi_value objValue = nullptr;
154     napi_create_object(env, &objValue);
155     if (objValue == nullptr) {
156         ROSEN_LOGE("JsImageFilter::Create objValue is null!");
157         return nullptr;
158     }
159 
160     std::unique_ptr<JsImageFilter> jsImageFilter = std::make_unique<JsImageFilter>(imageFilter);
161     napi_wrap(env, objValue, jsImageFilter.release(), JsImageFilter::Finalizer, nullptr, nullptr);
162 
163     return objValue;
164 }
165 
GetImageFilter()166 std::shared_ptr<ImageFilter> JsImageFilter::GetImageFilter()
167 {
168     return m_ImageFilter;
169 }
170 } // namespace Drawing
171 } // namespace OHOS::Rosen
172