1 /*
2  * Copyright (C) 2022 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 "sendable_pixel_map_napi.h"
17 #include <mutex>
18 #include "media_errors.h"
19 #include "image_log.h"
20 #include "image_napi_utils.h"
21 #include "image_pixel_map_napi.h"
22 #include "image_trace.h"
23 #include "log_tags.h"
24 #include "color_space_object_convertor.h"
25 #include "napi_message_sequence.h"
26 #include "hitrace_meter.h"
27 #include "pixel_map.h"
28 #include "transaction/rs_interfaces.h"
29 
30 #undef LOG_DOMAIN
31 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
32 
33 #undef LOG_TAG
34 #define LOG_TAG "SendablePixelMapNapi"
35 
36 namespace {
37     constexpr uint32_t NUM_0 = 0;
38     constexpr uint32_t NUM_1 = 1;
39     constexpr uint32_t NUM_2 = 2;
40     constexpr uint32_t NUM_3 = 3;
41     constexpr uint32_t NUM_4 = 4;
42 }
43 
44 namespace OHOS {
45 namespace Media {
46 static const std::string CREATE_PIXEL_MAP_FROM_PARCEL = "CreateSendablPixelMapFromParcel";
47 static const std::string MARSHALLING = "marshalling";
48 static const std::map<std::string, std::set<uint32_t>> ETS_API_ERROR_CODE = {
49     {CREATE_PIXEL_MAP_FROM_PARCEL, {62980096, 62980105, 62980115, 62980097,
50         62980177, 62980178, 62980179, 62980180, 62980246}},
51     {MARSHALLING, {62980115, 62980097, 62980096}}
52 };
53 static const std::string CLASS_NAME = "SendablePixelMap";
54 static const std::int32_t NEW_INSTANCE_ARGC = 1;
55 thread_local napi_ref SendablePixelMapNapi::sConstructor_ = nullptr;
56 NAPI_MessageSequence* napi_messageSequence_sendable = nullptr;
57 
58 std::shared_mutex SendablePixelMapNapi::mutex_;
59 static std::mutex pixelMapCrossThreadMutex_;
60 struct PositionArea {
61     void* pixels;
62     size_t size;
63     uint32_t offset;
64     uint32_t stride;
65     Rect region;
66 };
67 
68 struct PixelMapAsyncContext {
69     napi_env env;
70     napi_async_work work;
71     napi_deferred deferred;
72     napi_ref callbackRef;
73     napi_ref error = nullptr;
74     uint32_t status;
75     SendablePixelMapNapi *nConstructor;
76     void* colorsBuffer;
77     size_t colorsBufferSize;
78     InitializationOptions opts;
79     PositionArea area;
80     std::shared_ptr<PixelMap> rPixelMap;
81     std::shared_ptr<PixelMap> alphaMap;
82     std::shared_ptr<PixelMap> wPixelMap;
83     double alpha = -1;
84     uint32_t resultUint32;
85     ImageInfo imageInfo;
86     double xArg = 0;
87     double yArg = 0;
88     bool xBarg = false;
89     bool yBarg = false;
90     std::shared_ptr<OHOS::ColorManager::ColorSpace> colorSpace;
91     std::string surfaceId;
92 };
93 
ParsePixlForamt(int32_t val)94 static PixelFormat ParsePixlForamt(int32_t val)
95 {
96     if (val <= static_cast<int32_t>(PixelFormat::CMYK)) {
97         return PixelFormat(val);
98     }
99 
100     return PixelFormat::UNKNOWN;
101 }
102 
ParseAlphaType(int32_t val)103 static AlphaType ParseAlphaType(int32_t val)
104 {
105     if (val <= static_cast<int32_t>(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
106         return AlphaType(val);
107     }
108 
109     return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
110 }
111 
ParseScaleMode(int32_t val)112 static ScaleMode ParseScaleMode(int32_t val)
113 {
114     if (val <= static_cast<int32_t>(ScaleMode::CENTER_CROP)) {
115         return ScaleMode(val);
116     }
117 
118     return ScaleMode::FIT_TARGET_SIZE;
119 }
120 
parseSize(napi_env env,napi_value root,Size * size)121 static bool parseSize(napi_env env, napi_value root, Size* size)
122 {
123     if (size == nullptr) {
124         return false;
125     }
126 
127     if (!GET_INT32_BY_NAME(root, "height", size->height)) {
128         return false;
129     }
130 
131     if (!GET_INT32_BY_NAME(root, "width", size->width)) {
132         return false;
133     }
134 
135     return true;
136 }
137 
parseInitializationOptions(napi_env env,napi_value root,InitializationOptions * opts)138 static bool parseInitializationOptions(napi_env env, napi_value root, InitializationOptions* opts)
139 {
140     uint32_t tmpNumber = 0;
141     napi_value tmpValue = nullptr;
142 
143     if (opts == nullptr) {
144         return false;
145     }
146 
147     if (!GET_BOOL_BY_NAME(root, "editable", opts->editable)) {
148         opts->editable = true;
149     }
150 
151     if (!GET_UINT32_BY_NAME(root, "alphaType", tmpNumber)) {
152         IMAGE_LOGI("no alphaType in initialization options");
153     }
154     opts->alphaType = ParseAlphaType(tmpNumber);
155 
156     tmpNumber = 0;
157     if (!GET_UINT32_BY_NAME(root, "pixelFormat", tmpNumber)) {
158         IMAGE_LOGI("no pixelFormat in initialization options");
159     }
160     opts->pixelFormat = ParsePixlForamt(tmpNumber);
161 
162     tmpNumber = 0;
163     if (!GET_UINT32_BY_NAME(root, "srcPixelFormat", tmpNumber)) {
164         IMAGE_LOGI("no srcPixelFormat in initialization options");
165     }
166     opts->srcPixelFormat = ParsePixlForamt(tmpNumber);
167 
168     tmpNumber = 0;
169     if (!GET_UINT32_BY_NAME(root, "scaleMode", tmpNumber)) {
170         IMAGE_LOGI("no scaleMode in initialization options");
171     }
172     opts->scaleMode = ParseScaleMode(tmpNumber);
173 
174     if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
175         return false;
176     }
177 
178     if (!parseSize(env, tmpValue, &(opts->size))) {
179         return false;
180     }
181     return true;
182 }
183 
ParserImageType(napi_env env,napi_value argv)184 ImageType SendablePixelMapNapi::ParserImageType(napi_env env, napi_value argv)
185 {
186     napi_value constructor = nullptr;
187     napi_value global = nullptr;
188     bool isInstance = false;
189     napi_status ret = napi_invalid_arg;
190 
191     napi_get_global(env, &global);
192 
193     ret = napi_get_named_property(env, global, "PixelMap", &constructor);
194     if (ret != napi_ok) {
195         IMAGE_LOGI("Get SendablePixelMapNapi property failed!");
196     }
197 
198     ret = napi_instanceof(env, argv, constructor, &isInstance);
199     if (ret == napi_ok && isInstance) {
200         return ImageType::TYPE_PIXEL_MAP;
201     }
202 
203     IMAGE_LOGI("InValued type!");
204     return ImageType::TYPE_UNKNOWN;
205 }
206 
parseRegion(napi_env env,napi_value root,Rect * region)207 static bool parseRegion(napi_env env, napi_value root, Rect* region)
208 {
209     napi_value tmpValue = nullptr;
210 
211     if (region == nullptr) {
212         return false;
213     }
214 
215     if (!GET_INT32_BY_NAME(root, "x", region->left)) {
216         return false;
217     }
218 
219     if (!GET_INT32_BY_NAME(root, "y", region->top)) {
220         return false;
221     }
222 
223     if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
224         return false;
225     }
226 
227     if (!GET_INT32_BY_NAME(tmpValue, "height", region->height)) {
228         return false;
229     }
230 
231     if (!GET_INT32_BY_NAME(tmpValue, "width", region->width)) {
232         return false;
233     }
234 
235     return true;
236 }
237 
parsePositionArea(napi_env env,napi_value root,PositionArea * area)238 static bool parsePositionArea(napi_env env, napi_value root, PositionArea* area)
239 {
240     napi_value tmpValue = nullptr;
241 
242     if (area == nullptr) {
243         return false;
244     }
245 
246     if (!GET_BUFFER_BY_NAME(root, "pixels", area->pixels, area->size)) {
247         return false;
248     }
249 
250     if (!GET_UINT32_BY_NAME(root, "offset", area->offset)) {
251         return false;
252     }
253 
254     if (!GET_UINT32_BY_NAME(root, "stride", area->stride)) {
255         return false;
256     }
257 
258     if (!GET_NODE_BY_NAME(root, "region", tmpValue)) {
259         return false;
260     }
261 
262     if (!parseRegion(env, tmpValue, &(area->region))) {
263         return false;
264     }
265     return true;
266 }
267 
CommonCallbackRoutine(napi_env env,PixelMapAsyncContext * & asyncContext,const napi_value & valueParam)268 static void CommonCallbackRoutine(napi_env env, PixelMapAsyncContext* &asyncContext, const napi_value &valueParam)
269 {
270     napi_value result[NUM_2] = {0};
271     napi_value retVal;
272     napi_value callback = nullptr;
273 
274     napi_get_undefined(env, &result[NUM_0]);
275     napi_get_undefined(env, &result[NUM_1]);
276 
277     napi_handle_scope scope = nullptr;
278     napi_open_handle_scope(env, &scope);
279     if (scope == nullptr) {
280         return;
281     }
282 
283     if (asyncContext == nullptr) {
284         napi_close_handle_scope(env, scope);
285         return;
286     }
287     if (asyncContext->status == SUCCESS) {
288         result[NUM_1] = valueParam;
289     } else if (asyncContext->error != nullptr) {
290         napi_get_reference_value(env, asyncContext->error, &result[NUM_0]);
291         napi_delete_reference(env, asyncContext->error);
292     } else {
293         napi_create_uint32(env, asyncContext->status, &result[NUM_0]);
294     }
295 
296     if (asyncContext->deferred) {
297         if (asyncContext->status == SUCCESS) {
298             napi_resolve_deferred(env, asyncContext->deferred, result[NUM_1]);
299         } else {
300             napi_reject_deferred(env, asyncContext->deferred, result[NUM_0]);
301         }
302     } else {
303         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
304         napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
305         napi_delete_reference(env, asyncContext->callbackRef);
306     }
307 
308     napi_delete_async_work(env, asyncContext->work);
309     napi_close_handle_scope(env, scope);
310 
311     delete asyncContext;
312     asyncContext = nullptr;
313 }
314 
STATIC_COMPLETE_FUNC(EmptyResult)315 STATIC_COMPLETE_FUNC(EmptyResult)
316 {
317     napi_value result = nullptr;
318     napi_get_undefined(env, &result);
319 
320     auto context = static_cast<PixelMapAsyncContext*>(data);
321 
322     CommonCallbackRoutine(env, context, result);
323 }
324 
STATIC_COMPLETE_FUNC(GeneralError)325 STATIC_COMPLETE_FUNC(GeneralError)
326 {
327     napi_value result = nullptr;
328     napi_get_undefined(env, &result);
329     auto context = static_cast<PixelMapAsyncContext*>(data);
330     context->status = ERR_RESOURCE_UNAVAILABLE;
331     CommonCallbackRoutine(env, context, result);
332 }
333 
SendablePixelMapNapi()334 SendablePixelMapNapi::SendablePixelMapNapi():env_(nullptr)
335 {
336     static std::atomic<uint32_t> currentId = 0;
337     uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed);
338 }
339 
~SendablePixelMapNapi()340 SendablePixelMapNapi::~SendablePixelMapNapi()
341 {
342     release();
343 }
344 
DoInitAfter(napi_env env,napi_value exports,napi_value constructor,size_t property_count,const napi_property_descriptor * properties)345 static napi_value DoInitAfter(napi_env env,
346                               napi_value exports,
347                               napi_value constructor,
348                               size_t property_count,
349                               const napi_property_descriptor* properties)
350 {
351     napi_value global = nullptr;
352     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
353         napi_get_global(env, &global)),
354         nullptr, IMAGE_LOGE("Init:get global fail")
355     );
356 
357     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
358         napi_set_named_property(env, global, CLASS_NAME.c_str(), constructor)),
359         nullptr, IMAGE_LOGE("Init:set global named property fail")
360     );
361 
362     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
363         napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
364         nullptr, IMAGE_LOGE("set named property fail")
365     );
366 
367     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
368         napi_define_properties(env, exports, property_count, properties)),
369         nullptr, IMAGE_LOGE("define properties fail")
370     );
371     return exports;
372 }
373 
Init(napi_env env,napi_value exports)374 napi_value SendablePixelMapNapi::Init(napi_env env, napi_value exports)
375 {
376     napi_property_descriptor props[] = {
377         DECLARE_NAPI_FUNCTION("readPixelsToBuffer", ReadPixelsToBuffer),
378         DECLARE_NAPI_FUNCTION("readPixelsToBufferSync", ReadPixelsToBufferSync),
379         DECLARE_NAPI_FUNCTION("readPixels", ReadPixels),
380         DECLARE_NAPI_FUNCTION("readPixelsSync", ReadPixelsSync),
381         DECLARE_NAPI_FUNCTION("writePixels", WritePixels),
382         DECLARE_NAPI_FUNCTION("writePixelsSync", WritePixelsSync),
383         DECLARE_NAPI_FUNCTION("writeBufferToPixels", WriteBufferToPixels),
384         DECLARE_NAPI_FUNCTION("writeBufferToPixelsSync", WriteBufferToPixelsSync),
385         DECLARE_NAPI_FUNCTION("getImageInfo", GetImageInfo),
386         DECLARE_NAPI_FUNCTION("getImageInfoSync", GetImageInfoSync),
387         DECLARE_NAPI_FUNCTION("getBytesNumberPerRow", GetBytesNumberPerRow),
388         DECLARE_NAPI_FUNCTION("getPixelBytesNumber", GetPixelBytesNumber),
389         DECLARE_NAPI_FUNCTION("isSupportAlpha", IsSupportAlpha),
390         DECLARE_NAPI_FUNCTION("setAlphaAble", SetAlphaAble),
391         DECLARE_NAPI_FUNCTION("createAlphaPixelmap", CreateAlphaPixelmap),
392         DECLARE_NAPI_FUNCTION("createAlphaPixelmapSync", CreateAlphaPixelmapSync),
393         DECLARE_NAPI_FUNCTION("getDensity", GetDensity),
394         DECLARE_NAPI_FUNCTION("setDensity", SetDensity),
395         DECLARE_NAPI_FUNCTION("opacity", SetAlpha),
396         DECLARE_NAPI_FUNCTION("opacitySync", SetAlphaSync),
397         DECLARE_NAPI_FUNCTION("release", Release),
398         DECLARE_NAPI_FUNCTION("scale", Scale),
399         DECLARE_NAPI_FUNCTION("scaleSync", ScaleSync),
400         DECLARE_NAPI_FUNCTION("translate", Translate),
401         DECLARE_NAPI_FUNCTION("translateSync", TranslateSync),
402         DECLARE_NAPI_FUNCTION("rotate", Rotate),
403         DECLARE_NAPI_FUNCTION("rotateSync", RotateSync),
404         DECLARE_NAPI_FUNCTION("flip", Flip),
405         DECLARE_NAPI_FUNCTION("flipSync", FlipSync),
406         DECLARE_NAPI_FUNCTION("crop", Crop),
407         DECLARE_NAPI_FUNCTION("cropSync", CropSync),
408         DECLARE_NAPI_FUNCTION("getColorSpace", GetColorSpace),
409         DECLARE_NAPI_FUNCTION("setColorSpace", SetColorSpace),
410         DECLARE_NAPI_FUNCTION("applyColorSpace", ApplyColorSpace),
411         DECLARE_NAPI_FUNCTION("marshalling", Marshalling),
412         DECLARE_NAPI_FUNCTION("unmarshalling", Unmarshalling),
413         DECLARE_NAPI_GETTER("isEditable", GetIsEditable),
414         DECLARE_NAPI_GETTER("isStrideAlignment", GetIsStrideAlignment),
415     };
416 
417     napi_property_descriptor static_prop[] = {
418         DECLARE_NAPI_STATIC_FUNCTION("createPixelMap", CreateSendablePixelMap),
419         DECLARE_NAPI_STATIC_FUNCTION("createPremultipliedPixelMap", CreatePremultipliedSendablePixelMap),
420         DECLARE_NAPI_STATIC_FUNCTION("createUnpremultipliedPixelMap", CreateUnpremultipliedSendablePixelMap),
421         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapSync", CreateSendablePixelMapSync),
422         DECLARE_NAPI_STATIC_FUNCTION("unmarshalling", Unmarshalling),
423         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapFromParcel", CreateSendablPixelMapFromParcel),
424         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapFromSurface", CreateSendablePixelMapFromSurface),
425         DECLARE_NAPI_STATIC_FUNCTION("convertFromPixelMap", ConvertFromPixelMap),
426         DECLARE_NAPI_STATIC_FUNCTION("convertToPixelMap", ConvertToPixelMap),
427     };
428 
429     napi_value constructor = nullptr;
430 
431     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
432         napi_define_sendable_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
433             Constructor, nullptr, IMG_ARRAY_SIZE(props), props, nullptr, &constructor)),
434         nullptr, IMAGE_LOGE("define class fail")
435     );
436 
437     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
438         napi_create_reference(env, constructor, 1, &sConstructor_)),
439         nullptr, IMAGE_LOGE("create reference fail")
440     );
441 
442     auto result = DoInitAfter(env, exports, constructor,
443         IMG_ARRAY_SIZE(static_prop), static_prop);
444 
445     IMAGE_LOGD("Init success");
446     return result;
447 }
448 
NapiUnwrap(napi_env env,napi_value object,void ** result,bool isSendable=true)449 static napi_status NapiUnwrap(napi_env env, napi_value object, void** result, bool isSendable = true)
450 {
451     napi_status status = napi_invalid_arg;
452     if (isSendable) {
453         status = napi_unwrap_sendable(env, object, result);
454         if (!IMG_IS_OK(status)) {
455             IMAGE_LOGE("NapiUnwrap napi_unwrap_sendable failed");
456         }
457     } else {
458         status = napi_unwrap(env, object, result);
459         if (!IMG_IS_OK(status)) {
460             IMAGE_LOGE("NapiUnwrap napi_unwrap failed");
461         }
462     }
463     return status;
464 }
465 
GetSendablePixelMap(napi_env env,napi_value pixelmap)466 std::shared_ptr<PixelMap> SendablePixelMapNapi::GetSendablePixelMap(napi_env env, napi_value pixelmap)
467 {
468     std::unique_ptr<SendablePixelMapNapi> pixelMapNapi = nullptr;
469 
470     napi_status status = NapiUnwrap(env, pixelmap, reinterpret_cast<void**>(&pixelMapNapi));
471     if (!IMG_IS_OK(status)) {
472         IMAGE_LOGE("GetPixelMap napi unwrap failed");
473         return nullptr;
474     }
475     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(pixelMapNapi), nullptr,
476         IMAGE_LOGE("GetPixelMap pixmapNapi is nullptr"));
477 
478     auto pixelmapNapiPtr = pixelMapNapi.release();
479     if (pixelmapNapiPtr == nullptr) {
480         IMAGE_LOGE("GetPixelMap SendablePixelMapNapi is nullptr");
481         return nullptr;
482     }
483     return pixelmapNapiPtr->nativePixelMap_;
484 }
485 
IsLockPixelMap()486 bool SendablePixelMapNapi::IsLockPixelMap()
487 {
488     return (lockCount > 0);
489 }
490 
LockPixelMap()491 bool SendablePixelMapNapi::LockPixelMap()
492 {
493     lockCount++;
494     return true;
495 }
496 
UnlockPixelMap()497 void SendablePixelMapNapi::UnlockPixelMap()
498 {
499     if (lockCount > 0) {
500         lockCount--;
501     }
502 }
503 
NewPixelNapiInstance(napi_env & env,napi_value & constructor,std::shared_ptr<PixelMap> & pixelMap,napi_value & result)504 static napi_status NewPixelNapiInstance(napi_env &env, napi_value &constructor,
505     std::shared_ptr<PixelMap> &pixelMap, napi_value &result)
506 {
507     napi_status status;
508     if (pixelMap == nullptr) {
509         status = napi_invalid_arg;
510         IMAGE_LOGE("NewPixelNapiInstance pixelMap is nullptr");
511         return status;
512     }
513     size_t argc = NEW_INSTANCE_ARGC;
514     napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
515     napi_create_int32(env, pixelMap->GetUniqueId(), &argv[0]);
516     PixelMapContainer::GetInstance().Insert(pixelMap->GetUniqueId(), pixelMap);
517     status = napi_new_instance(env, constructor, argc, argv, &result);
518     return status;
519 }
520 
Constructor(napi_env env,napi_callback_info info)521 napi_value SendablePixelMapNapi::Constructor(napi_env env, napi_callback_info info)
522 {
523     napi_value undefineVar = nullptr;
524     napi_get_undefined(env, &undefineVar);
525 
526     napi_status status;
527     napi_value thisVar = nullptr;
528     napi_get_undefined(env, &thisVar);
529     size_t argc = NEW_INSTANCE_ARGC;
530     napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
531     IMAGE_LOGD("Constructor IN");
532     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
533     IMG_NAPI_CHECK_RET(IMG_IS_READY(status, thisVar), undefineVar);
534     uint32_t pixelMapId = 0;
535     napi_get_value_uint32(env, argv[0], &pixelMapId);
536     std::unique_ptr<SendablePixelMapNapi> pPixelMapNapi = std::make_unique<SendablePixelMapNapi>();
537 
538     IMG_NAPI_CHECK_RET(IMG_NOT_NULL(pPixelMapNapi), undefineVar);
539 
540     pPixelMapNapi->env_ = env;
541     if (PixelMapContainer::GetInstance().Find(pixelMapId)) {
542         pPixelMapNapi->nativePixelMap_ = PixelMapContainer::GetInstance()[pixelMapId];
543         IMAGE_LOGD("Constructor in napi_id:%{public}d, id:%{public}d",
544             pPixelMapNapi->GetUniqueId(), pPixelMapNapi->nativePixelMap_->GetUniqueId());
545     } else {
546         IMAGE_LOGE("Constructor nativePixelMap is nullptr");
547     }
548 
549     status = napi_wrap_sendable(env, thisVar, reinterpret_cast<void*>(pPixelMapNapi.get()),
550         SendablePixelMapNapi::Destructor, nullptr);
551     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), undefineVar, IMAGE_LOGE("Failure wrapping js to native napi"));
552 
553     pPixelMapNapi.release();
554     PixelMapContainer::GetInstance().Erase(pixelMapId);
555     return thisVar;
556 }
557 
Destructor(napi_env env,void * nativeObject,void * finalize)558 void SendablePixelMapNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
559 {
560     if (nativeObject != nullptr) {
561         std::lock_guard<std::mutex> lock(pixelMapCrossThreadMutex_);
562         IMAGE_LOGD("Destructor SendablePixelMapNapi");
563         delete reinterpret_cast<SendablePixelMapNapi*>(nativeObject);
564         nativeObject = nullptr;
565     }
566 }
567 
BuildContextError(napi_env env,napi_ref & error,const std::string errMsg,const int32_t errCode)568 static void BuildContextError(napi_env env, napi_ref &error, const std::string errMsg, const int32_t errCode)
569 {
570     IMAGE_LOGE("%{public}s", errMsg.c_str());
571     napi_value tmpError;
572     ImageNapiUtils::CreateErrorObj(env, tmpError, errCode, errMsg);
573     napi_create_reference(env, tmpError, NUM_1, &(error));
574 }
575 
STATIC_EXEC_FUNC(CreateSendablePixelMap)576 STATIC_EXEC_FUNC(CreateSendablePixelMap)
577 {
578     auto context = static_cast<PixelMapAsyncContext*>(data);
579     auto colors = static_cast<uint32_t*>(context->colorsBuffer);
580     if (context->opts.pixelFormat == PixelFormat::RGBA_1010102 ||
581         context->opts.pixelFormat == PixelFormat::YCBCR_P010 ||
582         context->opts.pixelFormat == PixelFormat::YCRCB_P010) {
583         context->rPixelMap = nullptr;
584     } else {
585         if (colors == nullptr) {
586             auto pixelmap = PixelMap::Create(context->opts);
587             context->rPixelMap = std::move(pixelmap);
588         } else {
589             auto pixelmap = PixelMap::Create(colors, context->colorsBufferSize, context->opts);
590             context->rPixelMap = std::move(pixelmap);
591         }
592     }
593 
594     if (IMG_NOT_NULL(context->rPixelMap)) {
595         context->status = SUCCESS;
596     } else {
597         context->status = ERROR;
598     }
599 }
600 
CreateSendablePixelMapComplete(napi_env env,napi_status status,void * data)601 void SendablePixelMapNapi::CreateSendablePixelMapComplete(napi_env env, napi_status status, void *data)
602 {
603     napi_value constructor = nullptr;
604     napi_value result = nullptr;
605 
606     IMAGE_LOGD("CreatePixelMapComplete IN");
607     auto context = static_cast<PixelMapAsyncContext*>(data);
608     status = napi_get_reference_value(env, sConstructor_, &constructor);
609     if (IMG_IS_OK(status)) {
610         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
611     }
612     if (!IMG_IS_OK(status)) {
613         context->status = ERROR;
614         IMAGE_LOGE("New instance could not be obtained");
615         napi_get_undefined(env, &result);
616     }
617     CommonCallbackRoutine(env, context, result);
618 }
619 
STATIC_EXEC_FUNC(CreatePremultipliedPixelMap)620 STATIC_EXEC_FUNC(CreatePremultipliedPixelMap)
621 {
622     auto context = static_cast<PixelMapAsyncContext*>(data);
623     if (IMG_NOT_NULL(context->rPixelMap) && IMG_NOT_NULL(context->wPixelMap)) {
624         bool isPremul = true;
625         if (context->wPixelMap->IsEditable()) {
626             context->status = context->rPixelMap->ConvertAlphaFormat(*context->wPixelMap.get(), isPremul);
627         } else {
628             context->status = ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
629         }
630     } else {
631         context->status = ERR_IMAGE_READ_PIXELMAP_FAILED;
632     }
633 }
634 
STATIC_EXEC_FUNC(CreateUnpremultipliedPixelMap)635 STATIC_EXEC_FUNC(CreateUnpremultipliedPixelMap)
636 {
637     auto context = static_cast<PixelMapAsyncContext*>(data);
638     if (IMG_NOT_NULL(context->rPixelMap) && IMG_NOT_NULL(context->wPixelMap)) {
639         bool isPremul = false;
640         if (context->wPixelMap->IsEditable()) {
641             context->status = context->rPixelMap->ConvertAlphaFormat(*context->wPixelMap.get(), isPremul);
642         } else {
643             context->status = ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
644         }
645     } else {
646         context->status = ERR_IMAGE_READ_PIXELMAP_FAILED;
647     }
648 }
649 
CreatePremultipliedSendablePixelMap(napi_env env,napi_callback_info info)650 napi_value SendablePixelMapNapi::CreatePremultipliedSendablePixelMap(napi_env env, napi_callback_info info)
651 {
652     napi_value result = nullptr;
653     napi_get_undefined(env, &result);
654     int32_t refCount = 1;
655     napi_status status;
656     napi_value thisVar = nullptr;
657     napi_value argValue[NUM_3] = {0};
658     size_t argCount = NUM_3;
659     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
660 
661     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
662     IMG_NAPI_CHECK_RET_D(argCount >= NUM_2,
663         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
664         "Invalid args count"),
665         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
666     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
667 
668     if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP &&
669         ParserImageType(env, argValue[NUM_1]) == ImageType::TYPE_PIXEL_MAP) {
670         asyncContext->rPixelMap = GetSendablePixelMap(env, argValue[NUM_0]);
671         asyncContext->wPixelMap = GetSendablePixelMap(env, argValue[NUM_1]);
672         if (asyncContext->rPixelMap == nullptr || asyncContext->wPixelMap == nullptr) {
673             BuildContextError(env, asyncContext->error, "input image type mismatch", ERR_IMAGE_GET_DATA_ABNORMAL);
674         }
675     } else {
676         BuildContextError(env, asyncContext->error, "input image type mismatch",
677             ERR_IMAGE_GET_DATA_ABNORMAL);
678     }
679 
680     IMG_NAPI_CHECK_RET_D(asyncContext->error == nullptr, nullptr, IMAGE_LOGE("input image type mismatch"));
681     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
682         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
683     }
684     if (asyncContext->callbackRef == nullptr) {
685         napi_create_promise(env, &(asyncContext->deferred), &result);
686     }
687 
688     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->error == nullptr,
689         BuildContextError(env, asyncContext->error, "CreatePremultipliedPixelMapError", ERR_IMAGE_GET_DATA_ABNORMAL),
690         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePremultipliedPixelMapGeneralError",
691         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
692         result);
693 
694     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePremultipliedPixelMap",
695         CreatePremultipliedPixelMapExec, EmptyResultComplete, asyncContext, asyncContext->work);
696 
697     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
698         nullptr, IMAGE_LOGE("fail to create async work"));
699     return result;
700 }
701 
CreateUnpremultipliedSendablePixelMap(napi_env env,napi_callback_info info)702 napi_value SendablePixelMapNapi::CreateUnpremultipliedSendablePixelMap(napi_env env, napi_callback_info info)
703 {
704     napi_value result = nullptr;
705     napi_get_undefined(env, &result);
706     int32_t refCount = 1;
707     napi_status status;
708     napi_value thisVar = nullptr;
709     napi_value argValue[NUM_3] = {0};
710     size_t argCount = NUM_3;
711     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
712 
713     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
714     IMG_NAPI_CHECK_RET_D(argCount >= NUM_2,
715         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
716         "Invalid args count"),
717         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
718     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
719 
720     if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP &&
721         ParserImageType(env, argValue[NUM_1]) == ImageType::TYPE_PIXEL_MAP) {
722         asyncContext->rPixelMap = GetSendablePixelMap(env, argValue[NUM_0]);
723         asyncContext->wPixelMap = GetSendablePixelMap(env, argValue[NUM_1]);
724         if (asyncContext->rPixelMap == nullptr || asyncContext->wPixelMap == nullptr) {
725             BuildContextError(env, asyncContext->error, "input image type mismatch", ERR_IMAGE_GET_DATA_ABNORMAL);
726         }
727     } else {
728         BuildContextError(env, asyncContext->error, "input image type mismatch",
729             ERR_IMAGE_GET_DATA_ABNORMAL);
730     }
731 
732     IMG_NAPI_CHECK_RET_D(asyncContext->error == nullptr, nullptr, IMAGE_LOGE("input image type mismatch"));
733     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
734         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
735     }
736     if (asyncContext->callbackRef == nullptr) {
737         napi_create_promise(env, &(asyncContext->deferred), &result);
738     }
739 
740     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->error == nullptr,
741         BuildContextError(env, asyncContext->error, "CreateUnpremultipliedPixelMapError", ERR_IMAGE_GET_DATA_ABNORMAL),
742         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateUnpremultipliedPixelMapGeneralError",
743         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
744         result);
745 
746     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateUnpremultipliedPixelMap",
747         CreateUnpremultipliedPixelMapExec, EmptyResultComplete, asyncContext, asyncContext->work);
748 
749     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
750         nullptr, IMAGE_LOGE("fail to create async work"));
751     return result;
752 }
753 
CreateSendablePixelMap(napi_env env,napi_callback_info info)754 napi_value SendablePixelMapNapi::CreateSendablePixelMap(napi_env env, napi_callback_info info)
755 {
756     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
757         napi_value exports = nullptr;
758         napi_create_object(env, &exports);
759         SendablePixelMapNapi::Init(env, exports);
760     }
761 
762     napi_value result = nullptr;
763     napi_get_undefined(env, &result);
764 
765     int32_t refCount = 1;
766 
767     napi_status status;
768     napi_value thisVar = nullptr;
769     napi_value argValue[NUM_4] = {0};
770     size_t argCount = NUM_4;
771     IMAGE_LOGD("CreateSendablePixelMap IN");
772 
773     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
774 
775     // we are static method!
776     // thisVar is nullptr here
777     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
778     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
779 
780     status = napi_get_arraybuffer_info(env, argValue[NUM_0], &(asyncContext->colorsBuffer),
781         &(asyncContext->colorsBufferSize));
782 
783     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
784 
785     IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[1], &(asyncContext->opts)),
786         nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
787 
788     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
789         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
790     }
791 
792     if (asyncContext->callbackRef == nullptr) {
793         napi_create_promise(env, &(asyncContext->deferred), &result);
794     } else {
795         napi_get_undefined(env, &result);
796     }
797 
798     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateSendablePixelMap",
799         CreateSendablePixelMapExec, CreateSendablePixelMapComplete, asyncContext, asyncContext->work);
800 
801     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
802         nullptr, IMAGE_LOGE("fail to create async work"));
803     return result;
804 }
805 
ConvertFromPixelMap(napi_env env,napi_callback_info info)806 napi_value SendablePixelMapNapi::ConvertFromPixelMap(napi_env env, napi_callback_info info)
807 {
808     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
809         napi_value exports = nullptr;
810         napi_create_object(env, &exports);
811         SendablePixelMapNapi::Init(env, exports);
812     }
813 
814     napi_value result = nullptr;
815     napi_get_undefined(env, &result);
816     napi_status status;
817     napi_value thisVar = nullptr;
818     napi_value argValue[NUM_2] = {0};
819     size_t argCount = NUM_2;
820     IMAGE_LOGD("ConvertFromPixelMap IN2");
821     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
822     if (!IMG_IS_OK(status)) {
823         return ImageNapiUtils::ThrowExceptionError(env,
824             COMMON_ERR_INVALID_PARAMETER, "ConvertFromPixelMap Invalid parameter");
825     }
826     PixelMapNapi* pixelMapNapi = nullptr;
827     NapiUnwrap(env, argValue[0], reinterpret_cast<void**>(&pixelMapNapi), false);
828     if (!(IMG_NOT_NULL(pixelMapNapi) && IMG_NOT_NULL(pixelMapNapi->GetPixelNapiInner()))) {
829         return ImageNapiUtils::ThrowExceptionError(env,
830             ERR_IMAGE_INIT_ABNORMAL, "ConvertFromPixelMap napi_unwrap failed");
831     }
832 
833     std::shared_ptr<PixelMap> nativePixelMap = pixelMapNapi->GetPixelNapiInner();
834     pixelMapNapi->ReleasePixelNapiInner();
835     result = CreateSendablePixelMap(env, nativePixelMap);
836     if (!IMG_NOT_NULL(result)) {
837         return ImageNapiUtils::ThrowExceptionError(env,
838             ERR_IMAGE_INIT_ABNORMAL, "ConvertFromPixelMap wrap failed");
839     }
840     return result;
841 }
842 
ConvertToPixelMap(napi_env env,napi_callback_info info)843 napi_value SendablePixelMapNapi::ConvertToPixelMap(napi_env env, napi_callback_info info)
844 {
845     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
846         napi_value exports = nullptr;
847         napi_create_object(env, &exports);
848         SendablePixelMapNapi::Init(env, exports);
849     }
850 
851     napi_value result = nullptr;
852     napi_get_undefined(env, &result);
853     napi_status status;
854     napi_value thisVar = nullptr;
855     napi_value argValue[NUM_2] = {0};
856     size_t argCount = NUM_2;
857     IMAGE_LOGD("ConvertToPixelMap IN");
858     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
859     if (!IMG_IS_OK(status)) {
860         return ImageNapiUtils::ThrowExceptionError(env,
861             COMMON_ERR_INVALID_PARAMETER, "ConvertToPixelMap Invalid parameter");
862     }
863     SendablePixelMapNapi* pixelMapNapi = nullptr;
864     NapiUnwrap(env, argValue[0], reinterpret_cast<void**>(&pixelMapNapi));
865     if (!(IMG_NOT_NULL(pixelMapNapi) && IMG_NOT_NULL(pixelMapNapi->nativePixelMap_))) {
866         return ImageNapiUtils::ThrowExceptionError(env,
867             ERR_IMAGE_INIT_ABNORMAL, "ConvertToPixelMap napi_unwrap failed");
868     }
869 
870     std::shared_ptr<PixelMap> nativePixelMap = pixelMapNapi->nativePixelMap_;
871     pixelMapNapi->ReleasePixelNapiInner();
872     result = PixelMapNapi::CreatePixelMap(env, nativePixelMap);
873     if (!IMG_NOT_NULL(result)) {
874         return ImageNapiUtils::ThrowExceptionError(env,
875             ERR_IMAGE_INIT_ABNORMAL, "ConvertToPixelMap wrap failed");
876     }
877     return result;
878 }
879 
CreateSendablePixelMapSync(napi_env env,napi_callback_info info)880 napi_value SendablePixelMapNapi::CreateSendablePixelMapSync(napi_env env, napi_callback_info info)
881 {
882     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
883         napi_value exports = nullptr;
884         napi_create_object(env, &exports);
885         SendablePixelMapNapi::Init(env, exports);
886     }
887 
888     napi_value result = nullptr;
889     napi_get_undefined(env, &result);
890     napi_value constructor = nullptr;
891     napi_status status;
892     napi_value thisVar = nullptr;
893     napi_value argValue[NUM_2] = {0};
894     size_t argCount = NUM_2;
895     IMAGE_LOGD("CreatePixelMap IN");
896 
897     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
898 
899     // we are static method!
900     // thisVar is nullptr here
901     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
902 
903     IMG_NAPI_CHECK_RET_D(argCount == NUM_2 || argCount == NUM_1,
904         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
905         "Invalid args count"),
906         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
907     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
908 
909     if (argCount == NUM_2) {
910         status = napi_get_arraybuffer_info(env, argValue[NUM_0], &(asyncContext->colorsBuffer),
911         &(asyncContext->colorsBufferSize));
912         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
913         IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[1], &(asyncContext->opts)),
914             nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
915     } else if (argCount == NUM_1) {
916         IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[NUM_0], &(asyncContext->opts)),
917             nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
918     }
919     CreateSendablePixelMapExec(env, static_cast<void*>((asyncContext).get()));
920     status = napi_get_reference_value(env, sConstructor_, &constructor);
921     if (IMG_IS_OK(status)) {
922         status = NewPixelNapiInstance(env, constructor, asyncContext->rPixelMap, result);
923     }
924     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create pixel map sync"));
925     return result;
926 }
927 
928 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
STATIC_EXEC_FUNC(CreateSendablePixelMapFromSurface)929 STATIC_EXEC_FUNC(CreateSendablePixelMapFromSurface)
930 {
931     auto context = static_cast<PixelMapAsyncContext*>(data);
932     IMAGE_LOGD("CreateSendablePixelMapFromSurface id:%{public}s,area:%{public}d,%{public}d,%{public}d,%{public}d",
933         context->surfaceId.c_str(), context->area.region.left, context->area.region.top,
934         context->area.region.height, context->area.region.width);
935 
936     auto &rsClient = Rosen::RSInterfaces::GetInstance();
937     OHOS::Rect r = {
938         .x = context->area.region.left,
939         .y = context->area.region.top,
940         .w = context->area.region.width,
941         .h = context->area.region.height,
942     };
943     std::shared_ptr<Media::PixelMap> pixelMap =
944         rsClient.CreatePixelMapFromSurfaceId(std::stoull(context->surfaceId), r);
945     context->rPixelMap = std::move(pixelMap);
946 
947     if (IMG_NOT_NULL(context->rPixelMap)) {
948         context->status = SUCCESS;
949     } else {
950         context->status = ERR_IMAGE_INVALID_PARAMETER;
951     }
952 }
953 
CreateSendablePixelMapFromSurfaceComplete(napi_env env,napi_status status,void * data)954 void SendablePixelMapNapi::CreateSendablePixelMapFromSurfaceComplete(napi_env env, napi_status status, void *data)
955 {
956     napi_value constructor = nullptr;
957     napi_value result = nullptr;
958 
959     IMAGE_LOGD("CreateSendablePixelMapFromSurface IN");
960     auto context = static_cast<PixelMapAsyncContext*>(data);
961     status = napi_get_reference_value(env, sConstructor_, &constructor);
962     if (IMG_IS_OK(status)) {
963         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
964     }
965     if (!IMG_IS_OK(status)) {
966         context->status = ERR_IMAGE_PIXELMAP_CREATE_FAILED;
967         IMAGE_LOGE("New instance could not be obtained");
968         napi_get_undefined(env, &result);
969     }
970     CommonCallbackRoutine(env, context, result);
971 }
972 
GetStringArgument(napi_env env,napi_value value)973 static std::string GetStringArgument(napi_env env, napi_value value)
974 {
975     std::string strValue = "";
976     size_t bufLength = 0;
977     napi_status status = napi_get_value_string_utf8(env, value, nullptr, NUM_0, &bufLength);
978     if (status == napi_ok && bufLength > NUM_0 && bufLength < PATH_MAX) {
979         char *buffer = reinterpret_cast<char *>(malloc((bufLength + NUM_1) * sizeof(char)));
980         if (buffer == nullptr) {
981             IMAGE_LOGE("No memory");
982             return strValue;
983         }
984 
985         status = napi_get_value_string_utf8(env, value, buffer, bufLength + NUM_1, &bufLength);
986         if (status == napi_ok) {
987             IMAGE_LOGD("Get Success");
988             strValue.assign(buffer, 0, bufLength + NUM_1);
989         }
990         if (buffer != nullptr) {
991             free(buffer);
992             buffer = nullptr;
993         }
994     }
995     return strValue;
996 }
997 
CreateSendablePixelMapFromSurface(napi_env env,napi_callback_info info)998 napi_value SendablePixelMapNapi::CreateSendablePixelMapFromSurface(napi_env env, napi_callback_info info)
999 {
1000     napi_value globalValue;
1001     napi_get_global(env, &globalValue);
1002     napi_value func;
1003     napi_get_named_property(env, globalValue, "requireNapi", &func);
1004 
1005     napi_value imageInfo;
1006     napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
1007     napi_value funcArgv[1] = { imageInfo };
1008     napi_value returnValue;
1009     napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
1010 
1011     napi_value result = nullptr;
1012     napi_get_undefined(env, &result);
1013     int32_t refCount = 1;
1014     napi_status status;
1015     napi_value thisVar = nullptr;
1016     napi_value argValue[NUM_4] = {0};
1017     size_t argCount = NUM_4;
1018     IMAGE_LOGD("CreateSendablePixelMapFromSurface IN");
1019     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1020     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1021     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1022     asyncContext->surfaceId = GetStringArgument(env, argValue[NUM_0]);
1023     bool ret = parseRegion(env, argValue[NUM_1], &(asyncContext->area.region));
1024     IMAGE_LOGD("CreateSendablePixelMapFromSurface get data: %{public}d", ret);
1025     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1026         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1027     }
1028     if (asyncContext->callbackRef == nullptr) {
1029         napi_create_promise(env, &(asyncContext->deferred), &result);
1030     } else {
1031         napi_get_undefined(env, &result);
1032     }
1033     IMG_NAPI_CHECK_BUILD_ERROR(ret,
1034         BuildContextError(env, asyncContext->error, "image invalid parameter", ERR_IMAGE_GET_DATA_ABNORMAL),
1035         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateSendablePixelMapFromSurfaceGeneralError",
1036         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1037         result);
1038     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateSendablePixelMapFromSurface",
1039         CreateSendablePixelMapFromSurfaceExec, CreateSendablePixelMapFromSurfaceComplete,
1040         asyncContext, asyncContext->work);
1041     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1042         nullptr, IMAGE_LOGE("fail to create async work"));
1043     return result;
1044 }
1045 #endif
CreateSendablePixelMap(napi_env env,std::shared_ptr<PixelMap> pixelmap)1046 napi_value SendablePixelMapNapi::CreateSendablePixelMap(napi_env env, std::shared_ptr<PixelMap> pixelmap)
1047 
1048 {
1049     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
1050         napi_value exports = nullptr;
1051         napi_create_object(env, &exports);
1052         SendablePixelMapNapi::Init(env, exports);
1053     }
1054     napi_value constructor = nullptr;
1055     napi_value result = nullptr;
1056     napi_status status;
1057     IMAGE_LOGD("CreatePixelMap IN");
1058     status = napi_get_reference_value(env, sConstructor_, &constructor);
1059     if (IMG_IS_OK(status)) {
1060         status = NewPixelNapiInstance(env, constructor, pixelmap, result);
1061     }
1062     if (!IMG_IS_OK(status)) {
1063         IMAGE_LOGE("CreatePixelMap | New instance could not be obtained");
1064         napi_get_undefined(env, &result);
1065     }
1066     return result;
1067 }
1068 
STATIC_EXEC_FUNC(Unmarshalling)1069 STATIC_EXEC_FUNC(Unmarshalling)
1070 {
1071     auto context = static_cast<PixelMapAsyncContext*>(data);
1072 
1073     auto messageParcel = napi_messageSequence_sendable->GetMessageParcel();
1074     auto pixelmap = PixelMap::Unmarshalling(*messageParcel);
1075     std::unique_ptr<OHOS::Media::PixelMap> pixelmap_ptr(pixelmap);
1076 
1077     context->rPixelMap = std::move(pixelmap_ptr);
1078 
1079     if (IMG_NOT_NULL(context->rPixelMap)) {
1080         context->status = SUCCESS;
1081     } else {
1082         context->status = ERROR;
1083     }
1084 }
1085 
UnmarshallingComplete(napi_env env,napi_status status,void * data)1086 void SendablePixelMapNapi::UnmarshallingComplete(napi_env env, napi_status status, void *data)
1087 {
1088     napi_value constructor = nullptr;
1089     napi_value result = nullptr;
1090 
1091     IMAGE_LOGD("UnmarshallingComplete IN");
1092     auto context = static_cast<PixelMapAsyncContext*>(data);
1093 
1094     status = napi_get_reference_value(env, sConstructor_, &constructor);
1095     if (IMG_IS_OK(status)) {
1096         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
1097     }
1098 
1099     if (!IMG_IS_OK(status)) {
1100         context->status = ERROR;
1101         IMAGE_LOGE("New instance could not be obtained");
1102         napi_get_undefined(env, &result);
1103     }
1104 
1105     CommonCallbackRoutine(env, context, result);
1106 }
1107 
Unmarshalling(napi_env env,napi_callback_info info)1108 napi_value SendablePixelMapNapi::Unmarshalling(napi_env env, napi_callback_info info)
1109 {
1110     std::unique_lock<std::shared_mutex> lock(mutex_);
1111     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
1112         napi_value exports = nullptr;
1113         napi_create_object(env, &exports);
1114         SendablePixelMapNapi::Init(env, exports);
1115     }
1116     napi_value result = nullptr;
1117     napi_get_undefined(env, &result);
1118     int32_t refCount = 1;
1119     napi_status status;
1120     napi_value thisVar = nullptr;
1121     napi_value argValue[NUM_4] = {0};
1122     size_t argCount = NUM_4;
1123     IMAGE_LOGD("Unmarshalling IN");
1124     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1125     // we are static method!
1126     // thisVar is nullptr here
1127     if (!IMG_IS_OK(status)) {
1128         return ImageNapiUtils::ThrowExceptionError(
1129             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to napi_get_cb_info");
1130     }
1131     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1132 
1133     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1134         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1135     }
1136 
1137     NapiUnwrap(env, argValue[NUM_0], (void **)&napi_messageSequence_sendable, false);
1138     if (napi_messageSequence_sendable == nullptr) {
1139         return ImageNapiUtils::ThrowExceptionError(
1140             env, ERROR, "napi_messageSequence_sendable unwrapped is nullptr");
1141     }
1142 
1143     if (asyncContext->callbackRef == nullptr) {
1144         napi_create_promise(env, &(asyncContext->deferred), &result);
1145     } else {
1146         napi_get_undefined(env, &result);
1147     }
1148 
1149     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Unmarshalling",
1150         UnmarshallingExec, UnmarshallingComplete, asyncContext, asyncContext->work);
1151 
1152     if (!IMG_IS_OK(status)) {
1153         return ImageNapiUtils::ThrowExceptionError(
1154             env, ERROR, "Fail to create async work");
1155     }
1156     return result;
1157 }
1158 
ThrowExceptionError(napi_env env,const std::string & tag,const std::uint32_t & code,const std::string & info)1159 napi_value SendablePixelMapNapi::ThrowExceptionError(napi_env env,
1160     const std::string &tag, const std::uint32_t &code, const std::string &info)
1161 {
1162     auto errNode = ETS_API_ERROR_CODE.find(tag);
1163     if (errNode != ETS_API_ERROR_CODE.end() &&
1164         errNode->second.find(code) != errNode->second.end()) {
1165         return ImageNapiUtils::ThrowExceptionError(env, code, info);
1166     }
1167     return ImageNapiUtils::ThrowExceptionError(env, ERROR, "Operation failed");
1168 }
1169 
CreateSendablPixelMapFromParcel(napi_env env,napi_callback_info info)1170 napi_value SendablePixelMapNapi::CreateSendablPixelMapFromParcel(napi_env env, napi_callback_info info)
1171 {
1172     if (SendablePixelMapNapi::GetConstructor() == nullptr) {
1173         napi_value exports = nullptr;
1174         napi_create_object(env, &exports);
1175         SendablePixelMapNapi::Init(env, exports);
1176     }
1177     napi_value result = nullptr;
1178     napi_get_undefined(env, &result);
1179     napi_status status;
1180     napi_value thisVar = nullptr;
1181     napi_value argValue[NUM_1] = {0};
1182     size_t argCount = NUM_1;
1183     IMAGE_LOGD("CreateSendablPixelMapFromParcel IN");
1184     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1185     if (!IMG_IS_OK(status) || argCount != NUM_1) {
1186         return SendablePixelMapNapi::ThrowExceptionError(env,
1187             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IMAGE_INVALID_PARAMETER, "Fail to napi_get_cb_info");
1188     }
1189     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1190     NapiUnwrap(env, argValue[NUM_0], (void **)&napi_messageSequence_sendable, false);
1191     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(napi_messageSequence_sendable), result,
1192         IMAGE_LOGE("CreateSendablPixelMapFromParcel pixmapNapi unwrapped is nullptr"));
1193     auto messageParcel = napi_messageSequence_sendable->GetMessageParcel();
1194     if (messageParcel == nullptr) {
1195         return SendablePixelMapNapi::ThrowExceptionError(env,
1196             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IPC, "get pacel failed");
1197     }
1198     PIXEL_MAP_ERR error;
1199     auto pixelmap = PixelMap::Unmarshalling(*messageParcel, error);
1200     if (!IMG_NOT_NULL(pixelmap)) {
1201         return SendablePixelMapNapi::ThrowExceptionError(env,
1202             CREATE_PIXEL_MAP_FROM_PARCEL, error.errorCode, error.errorInfo);
1203     }
1204     std::shared_ptr<OHOS::Media::PixelMap> pixelPtr(pixelmap);
1205     napi_value constructor = nullptr;
1206     status = napi_get_reference_value(env, sConstructor_, &constructor);
1207     if (IMG_IS_OK(status)) {
1208         status = NewPixelNapiInstance(env, constructor, pixelPtr, result);
1209     }
1210     if (!IMG_IS_OK(status)) {
1211         IMAGE_LOGE("New instance could not be obtained");
1212         return SendablePixelMapNapi::ThrowExceptionError(env,
1213             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IMAGE_NAPI_ERROR, "New instance could not be obtained");
1214     }
1215     return result;
1216 }
1217 
GetIsEditable(napi_env env,napi_callback_info info)1218 napi_value SendablePixelMapNapi::GetIsEditable(napi_env env, napi_callback_info info)
1219 {
1220     std::shared_lock<std::shared_mutex> lock(mutex_);
1221     napi_value result = nullptr;
1222     napi_get_undefined(env, &result);
1223 
1224     napi_status status;
1225     napi_value thisVar = nullptr;
1226     size_t argCount = 0;
1227     IMAGE_LOGD("GetIsEditable IN");
1228 
1229     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1230 
1231     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1232 
1233     SendablePixelMapNapi* pixelMapNapi = nullptr;
1234     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1235     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1236         IMAGE_LOGE("GetIsEditable fail to unwrap context"));
1237     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(pixelMapNapi), result,
1238         IMAGE_LOGE("SendablePixelMapNapi unwrapped is nullptr"));
1239     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(pixelMapNapi->nativePixelMap_), result,
1240         IMAGE_LOGE("nativePixelMap_ is nullptr"));
1241     bool isEditable = pixelMapNapi->nativePixelMap_->IsEditable();
1242 
1243     napi_get_boolean(env, isEditable, &result);
1244 
1245     return result;
1246 }
1247 
GetIsStrideAlignment(napi_env env,napi_callback_info info)1248 napi_value SendablePixelMapNapi::GetIsStrideAlignment(napi_env env, napi_callback_info info)
1249 {
1250     std::shared_lock<std::shared_mutex> lock(mutex_);
1251     napi_value result = nullptr;
1252     napi_get_undefined(env, &result);
1253 
1254     napi_status status;
1255     napi_value thisVar = nullptr;
1256     size_t argCount = 0;
1257     IMAGE_LOGD("GetIsStrideAlignment IN");
1258 
1259     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1260 
1261     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1262 
1263     SendablePixelMapNapi* pixelMapNapi = nullptr;
1264     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1265     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi),
1266         result, IMAGE_LOGE("GetIsStrideAlignment fail to unwrap context"));
1267     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(pixelMapNapi), result,
1268         IMAGE_LOGE("fail to unwrap context"));
1269     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(pixelMapNapi->nativePixelMap_), result,
1270         IMAGE_LOGE("SendablePixelMapNapi->nativePixelMap_ is nullptr"));
1271     bool isDMA = pixelMapNapi->nativePixelMap_->IsStrideAlignment();
1272     napi_get_boolean(env, isDMA, &result);
1273     return result;
1274 }
1275 
ReadPixelsToBuffer(napi_env env,napi_callback_info info)1276 napi_value SendablePixelMapNapi::ReadPixelsToBuffer(napi_env env, napi_callback_info info)
1277 {
1278     std::shared_lock<std::shared_mutex> lock(mutex_);
1279     ImageTrace imageTrace("SendablePixelMapNapi::ReadPixelsToBuffer");
1280     napi_value result = nullptr;
1281     napi_get_undefined(env, &result);
1282 
1283     int32_t refCount = 1;
1284     napi_status status;
1285     napi_value thisVar = nullptr;
1286     napi_value argValue[NUM_2] = {0};
1287     size_t argCount = NUM_2;
1288 
1289     IMAGE_LOGD("ReadPixelsToBuffer IN");
1290     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1291 
1292     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1293 
1294     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1295     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1296     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1297         nullptr, IMAGE_LOGE("ReadPixelsToBuffer fail to unwrap context"));
1298     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1299 
1300     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1301         nullptr, IMAGE_LOGE("empty native pixelmap"));
1302 
1303     status = napi_get_arraybuffer_info(env, argValue[NUM_0],
1304         &(asyncContext->colorsBuffer), &(asyncContext->colorsBufferSize));
1305 
1306     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
1307 
1308     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1309         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1310     }
1311 
1312     if (asyncContext->callbackRef == nullptr) {
1313         napi_create_promise(env, &(asyncContext->deferred), &result);
1314     } else {
1315         napi_get_undefined(env, &result);
1316     }
1317 
1318     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1319         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . ReadPixelsToBuffer failed",
1320         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixelsToBufferGeneralError",
1321         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1322         result);
1323     IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "ReadPixelsToBuffer",
1324         [](napi_env env, void *data) {
1325             auto context = static_cast<PixelMapAsyncContext*>(data);
1326             context->status = context->rPixelMap->ReadPixels(
1327                 context->colorsBufferSize, static_cast<uint8_t*>(context->colorsBuffer));
1328         }, EmptyResultComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
1329 
1330     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1331         nullptr, IMAGE_LOGE("fail to create async work"));
1332     return result;
1333 }
1334 
ReadPixelsToBufferSync(napi_env env,napi_callback_info info)1335 napi_value SendablePixelMapNapi::ReadPixelsToBufferSync(napi_env env, napi_callback_info info)
1336 {
1337     std::shared_lock<std::shared_mutex> lock(mutex_);
1338     ImageTrace imageTrace("SendablePixelMapNapi::ReadPixelsToBufferSync");
1339     napi_value result = nullptr;
1340     napi_get_undefined(env, &result);
1341     napi_status napiStatus;
1342     uint32_t status = SUCCESS;
1343     napi_value thisVar = nullptr;
1344     size_t argCount = NUM_1;
1345     napi_value argValue[NUM_1] = {0};
1346     void* colorsBuffer = nullptr;
1347     size_t colorsBufferSize = 0;
1348 
1349     IMAGE_LOGD("ReadPixelsToBuffeSync IN");
1350     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
1351     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1352     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1353         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1354         "ReadPixelsToBuffeSync failed"),
1355         IMAGE_LOGE("ReadPixelsToBuffeSync failed, invalid parameter"));
1356 
1357     napiStatus = napi_get_arraybuffer_info(env, argValue[NUM_0],
1358         &colorsBuffer, &colorsBufferSize);
1359     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
1360 
1361     SendablePixelMapNapi* pixelMapNapi = nullptr;
1362     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1363     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1364         IMAGE_LOGE("ReadPixelsToBufferSync fail to unwrap context"));
1365     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1366         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1367         "Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"),
1368         IMAGE_LOGE("Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"));
1369 
1370     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1371         status = pixelMapNapi->nativePixelMap_->ReadPixels(
1372             colorsBufferSize, static_cast<uint8_t*>(colorsBuffer));
1373         if (status != SUCCESS) {
1374             IMAGE_LOGE("ReadPixels failed");
1375         }
1376     } else {
1377         IMAGE_LOGE("Null native ref");
1378     }
1379     return result;
1380 }
1381 
ReadPixels(napi_env env,napi_callback_info info)1382 napi_value SendablePixelMapNapi::ReadPixels(napi_env env, napi_callback_info info)
1383 {
1384     std::shared_lock<std::shared_mutex> lock(mutex_);
1385     napi_value result = nullptr;
1386     napi_get_undefined(env, &result);
1387 
1388     int32_t refCount = 1;
1389     napi_status status;
1390     napi_value thisVar = nullptr;
1391     napi_value argValue[NUM_2] = {0};
1392     size_t argCount = NUM_2;
1393 
1394     IMAGE_LOGD("ReadPixels IN");
1395     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1396 
1397     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1398 
1399     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1400     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1401     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1402         nullptr, IMAGE_LOGE("ReadPixels fail to unwrap context"));
1403 
1404     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1405 
1406     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1407         nullptr, IMAGE_LOGE("empty native pixelmap"));
1408 
1409     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &(asyncContext->area)),
1410         nullptr, IMAGE_LOGE("fail to parse position area"));
1411 
1412     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1413         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1414     }
1415 
1416     if (asyncContext->callbackRef == nullptr) {
1417         napi_create_promise(env, &(asyncContext->deferred), &result);
1418     } else {
1419         napi_get_undefined(env, &result);
1420     }
1421 
1422     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1423         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . ReadPixels failed",
1424         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixelsGeneralError",
1425         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1426         result);
1427     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixels",
1428         [](napi_env env, void *data) {
1429             auto context = static_cast<PixelMapAsyncContext*>(data);
1430             auto area = context->area;
1431             context->status = context->rPixelMap->ReadPixels(
1432                 area.size, area.offset, area.stride, area.region, static_cast<uint8_t*>(area.pixels));
1433         }, EmptyResultComplete, asyncContext, asyncContext->work);
1434 
1435     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1436         nullptr, IMAGE_LOGE("fail to create async work"));
1437     return result;
1438 }
1439 
ReadPixelsSync(napi_env env,napi_callback_info info)1440 napi_value SendablePixelMapNapi::ReadPixelsSync(napi_env env, napi_callback_info info)
1441 {
1442     std::shared_lock<std::shared_mutex> lock(mutex_);
1443     napi_value result = nullptr;
1444     napi_get_undefined(env, &result);
1445 
1446     napi_status status;
1447     napi_value thisVar = nullptr;
1448     napi_value argValue[NUM_1] = {0};
1449     size_t argCount = NUM_1;
1450     PositionArea area;
1451     IMAGE_LOGD("ReadPixelsSync IN");
1452     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1453 
1454     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1455     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1456         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1457         "Invalid args count"),
1458         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1459     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &area),
1460         nullptr, IMAGE_LOGE("fail to parse position area"));
1461 
1462     SendablePixelMapNapi* pixelMapNapi = nullptr;
1463     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1464     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1465         IMAGE_LOGE("ReadPixelsSync fail to unwrap context"));
1466     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1467         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1468         "Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"),
1469         IMAGE_LOGE("Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"));
1470 
1471     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi->nativePixelMap_),
1472         nullptr, IMAGE_LOGE("empty native pixelmap"));
1473 
1474     auto nativeStatus = pixelMapNapi->nativePixelMap_->ReadPixels(
1475         area.size, area.offset, area.stride, area.region, static_cast<uint8_t*>(area.pixels));
1476 
1477     IMG_NAPI_CHECK_RET_D(nativeStatus == SUCCESS,
1478         nullptr, IMAGE_LOGE("fail to read pixels"));
1479     return result;
1480 }
1481 
WritePixels(napi_env env,napi_callback_info info)1482 napi_value SendablePixelMapNapi::WritePixels(napi_env env, napi_callback_info info)
1483 {
1484     std::unique_lock<std::shared_mutex> lock(mutex_);
1485     napi_value result = nullptr;
1486     napi_get_undefined(env, &result);
1487 
1488     int32_t refCount = 1;
1489     napi_status status;
1490     napi_value thisVar = nullptr;
1491     napi_value argValue[NUM_2] = {0};
1492     size_t argCount = NUM_2;
1493 
1494     IMAGE_LOGD("WritePixels IN");
1495     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1496 
1497     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1498 
1499     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1500     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1501     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1502         nullptr, IMAGE_LOGE("WritePixels fail to unwrap context"));
1503     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1504 
1505     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1506         nullptr, IMAGE_LOGE("empty native pixelmap"));
1507 
1508     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &(asyncContext->area)),
1509         nullptr, IMAGE_LOGE("fail to parse position area"));
1510 
1511     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1512         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1513     }
1514 
1515     if (asyncContext->callbackRef == nullptr) {
1516         napi_create_promise(env, &(asyncContext->deferred), &result);
1517     } else {
1518         napi_get_undefined(env, &result);
1519     }
1520     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1521         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . WritePixels failed",
1522         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WritePixelsGeneralError",
1523         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1524         result);
1525     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WritePixels",
1526         [](napi_env env, void *data) {
1527             auto context = static_cast<PixelMapAsyncContext*>(data);
1528             auto area = context->area;
1529             context->status = context->rPixelMap->WritePixels(
1530                 static_cast<uint8_t*>(area.pixels), area.size, area.offset, area.stride, area.region);
1531         }, EmptyResultComplete, asyncContext, asyncContext->work);
1532 
1533     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1534         nullptr, IMAGE_LOGE("fail to create async work"));
1535     return result;
1536 }
1537 
WritePixelsSync(napi_env env,napi_callback_info info)1538 napi_value SendablePixelMapNapi::WritePixelsSync(napi_env env, napi_callback_info info)
1539 {
1540     std::unique_lock<std::shared_mutex> lock(mutex_);
1541     napi_value result = nullptr;
1542     napi_get_undefined(env, &result);
1543     napi_status napiStatus;
1544     uint32_t status = SUCCESS;
1545     napi_value thisVar = nullptr;
1546     size_t argCount = NUM_1;
1547     napi_value argValue[NUM_1] = {0};
1548     PositionArea area;
1549     IMAGE_LOGD("WritePixelsSyncIN");
1550     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
1551     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
1552     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1553         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1554         "Invalid args count"),
1555         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1556     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &area),
1557         nullptr, IMAGE_LOGE("fail to parse position area"));
1558 
1559     SendablePixelMapNapi* pixelMapNapi = nullptr;
1560     napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1561     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result,
1562         IMAGE_LOGE("WritePixelsSync fail to unwrap context"));
1563     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1564         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1565         "Pixelmap has crossed threads . WritePixelsSync failed"),
1566         IMAGE_LOGE("Pixelmap has crossed threads . WritePixelsSync failed"));
1567 
1568     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1569         status = pixelMapNapi->nativePixelMap_->WritePixels(
1570             static_cast<uint8_t*>(area.pixels), area.size, area.offset, area.stride, area.region);
1571         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr,
1572             IMAGE_LOGE("fail to write pixels"));
1573     } else {
1574         IMAGE_LOGE("Null native ref");
1575     }
1576     return result;
1577 }
1578 
WriteBufferToPixels(napi_env env,napi_callback_info info)1579 napi_value SendablePixelMapNapi::WriteBufferToPixels(napi_env env, napi_callback_info info)
1580 {
1581     std::unique_lock<std::shared_mutex> lock(mutex_);
1582     ImageTrace imageTrace("SendablePixelMapNapi::WriteBufferToPixels");
1583     napi_value result = nullptr;
1584     napi_get_undefined(env, &result);
1585 
1586     int32_t refCount = 1;
1587     napi_status status;
1588     napi_value thisVar = nullptr;
1589     napi_value argValue[NUM_2] = {0};
1590     size_t argCount = NUM_2;
1591 
1592     IMAGE_LOGD("WriteBufferToPixels IN");
1593     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1594 
1595     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1596 
1597     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1598     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1599     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1600         nullptr, IMAGE_LOGE("WriteBufferToPixels fail to unwrap context"));
1601 
1602     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1603 
1604     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1605         nullptr, IMAGE_LOGE("empty native pixelmap"));
1606     status = napi_get_arraybuffer_info(env, argValue[NUM_0],
1607         &(asyncContext->colorsBuffer), &(asyncContext->colorsBufferSize));
1608 
1609     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1610         nullptr, IMAGE_LOGE("fail to get buffer info"));
1611 
1612     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1613         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1614     }
1615 
1616     if (asyncContext->callbackRef == nullptr) {
1617         napi_create_promise(env, &(asyncContext->deferred), &result);
1618     } else {
1619         napi_get_undefined(env, &result);
1620     }
1621     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1622         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . WriteBufferToPixels failed",
1623         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WriteBufferToPixelsGeneralError",
1624         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1625         result);
1626     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WriteBufferToPixels",
1627         [](napi_env env, void *data) {
1628             auto context = static_cast<PixelMapAsyncContext*>(data);
1629             context->status = context->rPixelMap->WritePixels(static_cast<uint8_t*>(context->colorsBuffer),
1630                 context->colorsBufferSize);
1631         }, EmptyResultComplete, asyncContext, asyncContext->work);
1632 
1633     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1634         nullptr, IMAGE_LOGE("fail to create async work"));
1635     return result;
1636 }
1637 
WriteBufferToPixelsSync(napi_env env,napi_callback_info info)1638 napi_value SendablePixelMapNapi::WriteBufferToPixelsSync(napi_env env, napi_callback_info info)
1639 {
1640     std::unique_lock<std::shared_mutex> lock(mutex_);
1641     ImageTrace imageTrace("SendablePixelMapNapi::WriteBufferToPixelsSync");
1642     napi_value result = nullptr;
1643     napi_get_undefined(env, &result);
1644     napi_status napiStatus;
1645     uint32_t status = SUCCESS;
1646     napi_value thisVar = nullptr;
1647     size_t argCount = NUM_1;
1648     napi_value argValue[NUM_1] = {0};
1649     void* colorsBuffer = nullptr;
1650     size_t colorsBufferSize = 0;
1651 
1652     IMAGE_LOGD("WriteBufferToPixelsSync IN");
1653     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
1654     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1655     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1656         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1657         "WriteBufferToPixelsSync failed"),
1658         IMAGE_LOGE("WriteBufferToPixelsSync failed, invalid parameter"));
1659 
1660     napiStatus = napi_get_arraybuffer_info(env, argValue[NUM_0],
1661         &colorsBuffer, &colorsBufferSize);
1662     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
1663 
1664     SendablePixelMapNapi* pixelMapNapi = nullptr;
1665     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1666     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1667         IMAGE_LOGE("WriteBufferToPixelsSync fail to unwrap context"));
1668     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1669         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1670         "Pixelmap has crossed threads . WriteBufferToPixelsSync failed"),
1671         IMAGE_LOGE("Pixelmap has crossed threads . WriteBufferToPixelsSync failed"));
1672 
1673     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1674         status = pixelMapNapi->nativePixelMap_->WritePixels(
1675             static_cast<uint8_t*>(colorsBuffer), colorsBufferSize);
1676         if (status != SUCCESS) {
1677             IMAGE_LOGE("WritePixels failed");
1678         }
1679     } else {
1680         IMAGE_LOGE("Null native ref");
1681     }
1682     return result;
1683 }
1684 
STATIC_NAPI_VALUE_FUNC(GetImageInfo)1685 STATIC_NAPI_VALUE_FUNC(GetImageInfo)
1686 {
1687     IMAGE_LOGD("[PixelMap]GetImageInfoNapiValue IN");
1688     napi_value result = nullptr;
1689     napi_create_object(env, &result);
1690     auto imageInfo = static_cast<ImageInfo*>(data);
1691     auto rPixelMap = static_cast<PixelMap*>(ptr);
1692     napi_value size = nullptr;
1693     napi_create_object(env, &size);
1694     napi_value sizeWith = nullptr;
1695     napi_create_int32(env, imageInfo->size.width, &sizeWith);
1696     napi_set_named_property(env, size, "width", sizeWith);
1697     napi_value sizeHeight = nullptr;
1698     napi_create_int32(env, imageInfo->size.height, &sizeHeight);
1699     napi_set_named_property(env, size, "height", sizeHeight);
1700     napi_set_named_property(env, result, "size", size);
1701     napi_value pixelFormatValue = nullptr;
1702     napi_create_int32(env, static_cast<int32_t>(imageInfo->pixelFormat), &pixelFormatValue);
1703     napi_set_named_property(env, result, "pixelFormat", pixelFormatValue);
1704     napi_value colorSpaceValue = nullptr;
1705     napi_create_int32(env, static_cast<int32_t>(imageInfo->colorSpace), &colorSpaceValue);
1706     napi_set_named_property(env, result, "colorSpace", colorSpaceValue);
1707     napi_value alphaTypeValue = nullptr;
1708     napi_create_int32(env, static_cast<int32_t>(imageInfo->alphaType), &alphaTypeValue);
1709     napi_set_named_property(env, result, "alphaType", alphaTypeValue);
1710     napi_value densityValue = nullptr;
1711     napi_create_int32(env, static_cast<int32_t>(imageInfo->baseDensity), &densityValue);
1712     napi_set_named_property(env, result, "density", densityValue);
1713     napi_value strideValue = nullptr;
1714     napi_create_int32(env, static_cast<int32_t>(rPixelMap->GetRowStride()), &strideValue);
1715     napi_set_named_property(env, result, "stride", strideValue);
1716     napi_value encodedFormatValue = nullptr;
1717     napi_create_string_utf8(env, imageInfo->encodedFormat.c_str(),
1718         imageInfo->encodedFormat.length(), &encodedFormatValue);
1719     napi_set_named_property(env, result, "mimeType", encodedFormatValue);
1720     napi_value isHdrValue = nullptr;
1721     napi_get_boolean(env, rPixelMap->IsHdr(), &isHdrValue);
1722     napi_set_named_property(env, result, "isHdr", isHdrValue);
1723     return result;
1724 }
1725 
STATIC_COMPLETE_FUNC(GetImageInfo)1726 STATIC_COMPLETE_FUNC(GetImageInfo)
1727 {
1728     IMAGE_LOGD("[PixelMap]GetImageInfoComplete IN");
1729     auto context = static_cast<PixelMapAsyncContext*>(data);
1730     napi_value result = GetImageInfoNapiValue(env, &(context->imageInfo), context->rPixelMap.get());
1731 
1732     if (!IMG_IS_OK(status)) {
1733         context->status = ERROR;
1734         IMAGE_LOGE("napi_create_int32 failed!");
1735         napi_get_undefined(env, &result);
1736     } else {
1737         context->status = SUCCESS;
1738     }
1739     IMAGE_LOGD("[PixelMap]GetImageInfoComplete OUT");
1740     CommonCallbackRoutine(env, context, result);
1741 }
GetImageInfo(napi_env env,napi_callback_info info)1742 napi_value SendablePixelMapNapi::GetImageInfo(napi_env env, napi_callback_info info)
1743 {
1744     std::shared_lock<std::shared_mutex> lock(mutex_);
1745     napi_value result = nullptr;
1746     napi_get_undefined(env, &result);
1747     int32_t refCount = 1;
1748     napi_status status;
1749     napi_value thisVar = nullptr;
1750     napi_value argValue[NUM_1] = {0};
1751     size_t argCount = 1;
1752     IMAGE_LOGD("GetImageInfo IN");
1753     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1754     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1755     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1756     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1757     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1758         nullptr, IMAGE_LOGE("GetImageInfo fail to unwrap context"));
1759     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1760     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1761         nullptr, IMAGE_LOGE("empty native pixelmap"));
1762     if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1763         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1764     }
1765     if (asyncContext->callbackRef == nullptr) {
1766         napi_create_promise(env, &(asyncContext->deferred), &result);
1767     } else {
1768         napi_get_undefined(env, &result);
1769     }
1770     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1771         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . GetImageInfo failed",
1772         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfoGeneralError",
1773         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1774         result);
1775     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfo",
1776         [](napi_env env, void *data) {
1777             auto context = static_cast<PixelMapAsyncContext*>(data);
1778             context->rPixelMap->GetImageInfo(context->imageInfo);
1779             context->status = SUCCESS;
1780         }, GetImageInfoComplete, asyncContext, asyncContext->work);
1781     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1782         nullptr, IMAGE_LOGE("fail to create async work"));
1783     return result;
1784 }
1785 
GetImageInfoSync(napi_env env,napi_callback_info info)1786 napi_value SendablePixelMapNapi::GetImageInfoSync(napi_env env, napi_callback_info info)
1787 {
1788     std::shared_lock<std::shared_mutex> lock(mutex_);
1789     napi_value result = nullptr;
1790     napi_get_undefined(env, &result);
1791     napi_status napiStatus;
1792     napi_value thisVar = nullptr;
1793     size_t argCount = NUM_0;
1794 
1795     IMAGE_LOGD("GetImageInfoSync IN");
1796     IMG_JS_ARGS(env, info, napiStatus, argCount, nullptr, thisVar);
1797     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
1798 
1799     SendablePixelMapNapi* pixelMapNapi = nullptr;
1800     napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1801     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result,
1802         IMAGE_LOGE("GetImageInfoSync fail to unwrap context"));
1803     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1804         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1805         "Pixelmap has crossed threads . GetImageInfoSync failed"),
1806         IMAGE_LOGE("Pixelmap has crossed threads . GetImageInfoSync failed"));
1807 
1808     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1809         ImageInfo imageinfo;
1810         pixelMapNapi->nativePixelMap_->GetImageInfo(imageinfo);
1811         result = GetImageInfoNapiValue(env, &imageinfo, pixelMapNapi->nativePixelMap_.get());
1812     } else {
1813         IMAGE_LOGE("native pixelmap is nullptr!");
1814     }
1815     return result;
1816 }
1817 
GetBytesNumberPerRow(napi_env env,napi_callback_info info)1818 napi_value SendablePixelMapNapi::GetBytesNumberPerRow(napi_env env, napi_callback_info info)
1819 {
1820     std::shared_lock<std::shared_mutex> lock(mutex_);
1821     ImageTrace imageTrace("SendablePixelMapNapi::GetBytesNumberPerRow");
1822     napi_value result = nullptr;
1823     napi_get_undefined(env, &result);
1824 
1825     napi_status status;
1826     napi_value thisVar = nullptr;
1827     size_t argCount = 0;
1828 
1829     IMAGE_LOGD("GetBytesNumberPerRow IN");
1830     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1831 
1832     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1833 
1834     SendablePixelMapNapi* pixelMapNapi = nullptr;
1835     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1836     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1837         IMAGE_LOGE("fail to unwrap context"));
1838     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1839         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1840         "Pixelmap has crossed threads . GetBytesNumberPerRow failed"),
1841         IMAGE_LOGE("Pixelmap has crossed threads . GetBytesNumberPerRow failed"));
1842 
1843     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1844         uint32_t rowBytes = pixelMapNapi->nativePixelMap_->GetRowBytes();
1845         status = napi_create_int32(env, rowBytes, &result);
1846         if (!IMG_IS_OK(status)) {
1847             IMAGE_LOGE("napi_create_int32 failed!");
1848         }
1849     } else {
1850         IMAGE_LOGE("native pixelmap is nullptr!");
1851     }
1852     return result;
1853 }
1854 
GetPixelBytesNumber(napi_env env,napi_callback_info info)1855 napi_value SendablePixelMapNapi::GetPixelBytesNumber(napi_env env, napi_callback_info info)
1856 {
1857     std::shared_lock<std::shared_mutex> lock(mutex_);
1858     ImageTrace imageTrace("SendablePixelMapNapi::GetPixelBytesNumber");
1859     napi_value result = nullptr;
1860     napi_get_undefined(env, &result);
1861 
1862     napi_status status;
1863     napi_value thisVar = nullptr;
1864     size_t argCount = 0;
1865 
1866     IMAGE_LOGD("GetPixelBytesNumber IN");
1867     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1868 
1869     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1870 
1871     SendablePixelMapNapi* pixelMapNapi = nullptr;
1872     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1873     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1874         IMAGE_LOGE("GetPixelBytesNumber fail to unwrap context"));
1875     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1876         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1877         "Pixelmap has crossed threads . GetPixelBytesNumber failed"),
1878         IMAGE_LOGE("Pixelmap has crossed threads . GetPixelBytesNumber failed"));
1879 
1880     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1881         uint32_t byteCount = pixelMapNapi->nativePixelMap_->GetByteCount();
1882         status = napi_create_int32(env, byteCount, &result);
1883         if (!IMG_IS_OK(status)) {
1884             IMAGE_LOGE("napi_create_int32 failed!");
1885         }
1886     } else {
1887         IMAGE_LOGE("native pixelmap is nullptr!");
1888     }
1889     return result;
1890 }
1891 
IsSupportAlpha(napi_env env,napi_callback_info info)1892 napi_value SendablePixelMapNapi::IsSupportAlpha(napi_env env, napi_callback_info info)
1893 {
1894     std::shared_lock<std::shared_mutex> lock(mutex_);
1895     napi_value result = nullptr;
1896     napi_get_undefined(env, &result);
1897 
1898     napi_status status;
1899     napi_value thisVar = nullptr;
1900     size_t argCount = NUM_0;
1901 
1902     IMAGE_LOGD("IsSupportAlpha IN");
1903     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1904 
1905     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1906 
1907     SendablePixelMapNapi* pixelMapNapi = nullptr;
1908     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1909     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1910         IMAGE_LOGE("IsSupportAlpha fail to unwrap context"));
1911     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1912         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1913         "Pixelmap has crossed threads . IsSupportAlpha failed"),
1914         IMAGE_LOGE("Pixelmap has crossed threads . IsSupportAlpha failed"));
1915 
1916     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1917         AlphaType alphaType = pixelMapNapi->nativePixelMap_->GetAlphaType();
1918         bool isSupportAlpha = !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
1919         status = napi_get_boolean(env, isSupportAlpha, &result);
1920         if (!IMG_IS_OK(status)) {
1921             IMAGE_LOGE("napi_create_bool failed!");
1922         }
1923     } else {
1924         IMAGE_LOGE("native pixelmap is nullptr!");
1925     }
1926     return result;
1927 }
1928 
SetAlphaAble(napi_env env,napi_callback_info info)1929 napi_value SendablePixelMapNapi::SetAlphaAble(napi_env env, napi_callback_info info)
1930 {
1931     std::unique_lock<std::shared_mutex> lock(mutex_);
1932     napi_value result = nullptr;
1933     napi_get_undefined(env, &result);
1934 
1935     napi_status status;
1936     napi_value thisVar = nullptr;
1937     napi_value argValue[NUM_1] = {0};
1938     size_t argCount = NUM_1;
1939     bool isAlphaAble = false;
1940 
1941     IMAGE_LOGD("SetAlphaAble IN");
1942     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1943 
1944     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1945     NAPI_ASSERT(env, argCount > NUM_0, "Invalid input");
1946     NAPI_ASSERT(env, ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_boolean, "Invalid input type");
1947     NAPI_ASSERT(env, napi_get_value_bool(env, argValue[NUM_0], &isAlphaAble) == napi_ok, "Parse input error");
1948 
1949     SendablePixelMapNapi* pixelMapNapi = nullptr;
1950     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1951     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
1952         IMAGE_LOGE("SetAlphaAble fail to unwrap context"));
1953     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1954         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1955         "Pixelmap has crossed threads . SetAlphaAble failed"),
1956         IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaAble failed"));
1957     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1958         AlphaType alphaType = pixelMapNapi->nativePixelMap_->GetAlphaType();
1959         if (isAlphaAble && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
1960             pixelMapNapi->nativePixelMap_->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
1961         } else if ((!isAlphaAble) && !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
1962             pixelMapNapi->nativePixelMap_->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
1963         }
1964     } else {
1965         IMAGE_LOGE("native pixelmap is nullptr!");
1966     }
1967     return result;
1968 }
1969 
CreateAlphaPixelmapComplete(napi_env env,napi_status status,void * data)1970 static void CreateAlphaPixelmapComplete(napi_env env, napi_status status, void *data)
1971 {
1972     napi_value result = nullptr;
1973     napi_get_undefined(env, &result);
1974     auto context = static_cast<PixelMapAsyncContext*>(data);
1975 
1976     if (context->alphaMap != nullptr) {
1977         result = SendablePixelMapNapi::CreateSendablePixelMap(env, context->alphaMap);
1978         context->status = SUCCESS;
1979     } else {
1980         context->status = ERROR;
1981     }
1982     CommonCallbackRoutine(env, context, result);
1983 }
1984 
CreateAlphaPixelmap(napi_env env,napi_callback_info info)1985 napi_value SendablePixelMapNapi::CreateAlphaPixelmap(napi_env env, napi_callback_info info)
1986 {
1987     std::unique_lock<std::shared_mutex> lock(mutex_);
1988     napi_value result = nullptr;
1989     napi_get_undefined(env, &result);
1990     int32_t refCount = 1;
1991     napi_status status;
1992     napi_value thisVar = nullptr;
1993     napi_value argValue[NUM_1] = {0};
1994     size_t argCount = 1;
1995     IMAGE_LOGD("CreateAlphaPixelmap IN");
1996     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1997     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1998     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1999     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
2000     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
2001         nullptr, IMAGE_LOGE("CreateAlphaPixelmap fail to unwrap context"));
2002     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
2003     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
2004         nullptr, IMAGE_LOGE("empty native pixelmap"));
2005     if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2006         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
2007     }
2008     if (asyncContext->callbackRef == nullptr) {
2009         napi_create_promise(env, &(asyncContext->deferred), &result);
2010     } else {
2011         napi_get_undefined(env, &result);
2012     }
2013     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
2014         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . CreateAlphaPixelmap failed",
2015         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateAlphaPixelmapGeneralError",
2016         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
2017         result);
2018     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateAlphaPixelmap",
2019         [](napi_env env, void *data) {
2020             auto context = static_cast<PixelMapAsyncContext*>(data);
2021             InitializationOptions opts;
2022             opts.pixelFormat = PixelFormat::ALPHA_8;
2023             auto tmpPixelMap = PixelMap::Create(*(context->rPixelMap), opts);
2024             context->alphaMap = std::move(tmpPixelMap);
2025             context->status = SUCCESS;
2026         }, CreateAlphaPixelmapComplete, asyncContext, asyncContext->work);
2027     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2028         nullptr, IMAGE_LOGE("fail to create async work"));
2029     return result;
2030 }
2031 
CreateAlphaPixelmapSync(napi_env env,napi_callback_info info)2032 napi_value SendablePixelMapNapi::CreateAlphaPixelmapSync(napi_env env, napi_callback_info info)
2033 {
2034     std::unique_lock<std::shared_mutex> lock(mutex_);
2035     napi_value result = nullptr;
2036     napi_get_undefined(env, &result);
2037     napi_status napiStatus;
2038     napi_value thisVar = nullptr;
2039     size_t argCount = NUM_0;
2040 
2041     IMAGE_LOGD("CreateAlphaPixelmapSync IN");
2042     IMG_JS_ARGS(env, info, napiStatus, argCount, nullptr, thisVar);
2043     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2044     IMG_NAPI_CHECK_RET_D(argCount == NUM_0,
2045         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2046         "CreateAlphaPixelmapSync failed"),
2047         IMAGE_LOGE("CreateAlphaPixelmapSync failed, invalid parameter"));
2048 
2049     SendablePixelMapNapi* pixelMapNapi = nullptr;
2050     napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2051     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result,
2052         IMAGE_LOGE("CreateAlphaPixelmapSync fail to unwrap context"));
2053     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2054         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2055         "Pixelmap has crossed threads . CreateAlphaPixelmapSync failed"),
2056         IMAGE_LOGE("Pixelmap has crossed threads . CreateAlphaPixelmapSync failed"));
2057 
2058     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2059         InitializationOptions opts;
2060         opts.pixelFormat = PixelFormat::ALPHA_8;
2061         auto tmpPixelMap = PixelMap::Create(*(pixelMapNapi->nativePixelMap_), opts);
2062         result = SendablePixelMapNapi::CreateSendablePixelMap(env, std::move(tmpPixelMap));
2063     } else {
2064         IMAGE_LOGE("Null native ref");
2065     }
2066     return result;
2067 }
2068 
GetDensity(napi_env env,napi_callback_info info)2069 napi_value SendablePixelMapNapi::GetDensity(napi_env env, napi_callback_info info)
2070 {
2071     std::shared_lock<std::shared_mutex> lock(mutex_);
2072     napi_value result = nullptr;
2073     napi_get_undefined(env, &result);
2074 
2075     napi_status status;
2076     napi_value thisVar = nullptr;
2077     size_t argCount = 0;
2078 
2079     IMAGE_LOGD("GetDensity IN");
2080     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
2081 
2082     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2083 
2084     SendablePixelMapNapi* pixelMapNapi = nullptr;
2085     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2086     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
2087         IMAGE_LOGE("GetDensity fail to unwrap context"));
2088     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2089         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2090         "Pixelmap has crossed threads . GetDensity failed"),
2091         IMAGE_LOGE("Pixelmap has crossed threads . GetDensity failed"));
2092 
2093     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2094         uint32_t baseDensity = pixelMapNapi->nativePixelMap_->GetBaseDensity();
2095         status = napi_create_int32(env, baseDensity, &result);
2096         if (!IMG_IS_OK(status)) {
2097             IMAGE_LOGE("napi_create_int32 failed!");
2098         }
2099     } else {
2100         IMAGE_LOGE("native pixelmap is nullptr!");
2101     }
2102     return result;
2103 }
2104 
SetDensity(napi_env env,napi_callback_info info)2105 napi_value SendablePixelMapNapi::SetDensity(napi_env env, napi_callback_info info)
2106 {
2107     std::unique_lock<std::shared_mutex> lock(mutex_);
2108     napi_value result = nullptr;
2109     napi_get_undefined(env, &result);
2110 
2111     napi_status status;
2112     napi_value thisVar = nullptr;
2113     napi_value argValue[NUM_1] = {0};
2114     size_t argCount = NUM_1;
2115     uint32_t density = 0;
2116 
2117     IMAGE_LOGD("SetDensity IN");
2118     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2119     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2120 
2121     NAPI_ASSERT(env,
2122         (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number),
2123         "Density input mismatch");
2124     NAPI_ASSERT(env, napi_get_value_uint32(env, argValue[NUM_0], &density) == napi_ok, "Could not parse density");
2125 
2126     SendablePixelMapNapi* pixelMapNapi = nullptr;
2127     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2128     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
2129         IMAGE_LOGE("SetDensity fail to unwrap context"));
2130     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2131         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2132         "Pixelmap has crossed threads . SetDensity failed"),
2133         IMAGE_LOGE("Pixelmap has crossed threads . SetDensity failed"));
2134     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2135         ImageInfo imageinfo;
2136         pixelMapNapi->nativePixelMap_->GetImageInfo(imageinfo);
2137         imageinfo.baseDensity = density;
2138         pixelMapNapi->nativePixelMap_->SetImageInfo(imageinfo, true);
2139     } else {
2140         IMAGE_LOGE("native pixelmap is nullptr!");
2141     }
2142     return result;
2143 }
2144 
Release(napi_env env,napi_callback_info info)2145 napi_value SendablePixelMapNapi::Release(napi_env env, napi_callback_info info)
2146 {
2147     std::unique_lock<std::shared_mutex> lock(mutex_);
2148     napi_value result = nullptr;
2149     napi_get_undefined(env, &result);
2150 
2151     int32_t refCount = 1;
2152     napi_status status;
2153     napi_value thisVar = nullptr;
2154     napi_value argValue[1] = {0};
2155     size_t argCount = 1;
2156 
2157     IMAGE_LOGD("Release IN");
2158     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2159 
2160     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2161 
2162     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
2163     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
2164     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
2165         nullptr, IMAGE_LOGE("Release fail to unwrap context"));
2166 
2167     if (argCount == 1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2168         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
2169     }
2170 
2171     if (asyncContext->callbackRef == nullptr) {
2172         napi_create_promise(env, &(asyncContext->deferred), &result);
2173     } else {
2174         napi_get_undefined(env, &result);
2175     }
2176     if (asyncContext->nConstructor->IsLockPixelMap()) {
2177         asyncContext->status = ERROR;
2178     } else {
2179         if (asyncContext->nConstructor->nativePixelMap_ != nullptr) {
2180             IMAGE_LOGD("Release in napi_id:%{public}d, id:%{public}d",
2181                 asyncContext->nConstructor->GetUniqueId(),
2182                 asyncContext->nConstructor->nativePixelMap_->GetUniqueId());
2183             asyncContext->nConstructor->nativePixelMap_.reset();
2184         }
2185         asyncContext->status = SUCCESS;
2186     }
2187     IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "Release",
2188         [](napi_env env, void *data) {
2189         }, EmptyResultComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
2190 
2191     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2192         nullptr, IMAGE_LOGE("fail to create async work"));
2193     return result;
2194 }
2195 
2196 struct NapiValues {
2197     napi_status status;
2198     napi_value thisVar = nullptr;
2199     napi_value result = nullptr;
2200     napi_value* argv = nullptr;
2201     size_t argc;
2202     int32_t refCount = 1;
2203     std::unique_ptr<PixelMapAsyncContext> context;
2204 };
2205 
prepareNapiEnv(napi_env env,napi_callback_info info,struct NapiValues * nVal)2206 static bool prepareNapiEnv(napi_env env, napi_callback_info info, struct NapiValues* nVal)
2207 {
2208     napi_get_undefined(env, &(nVal->result));
2209     nVal->status = napi_get_cb_info(env, info, &(nVal->argc), nVal->argv, &(nVal->thisVar), nullptr);
2210     if (nVal->status != napi_ok) {
2211         IMAGE_LOGE("fail to napi_get_cb_info");
2212         return false;
2213     }
2214     nVal->context = std::make_unique<PixelMapAsyncContext>();
2215     nVal->status = NapiUnwrap(env, nVal->thisVar, reinterpret_cast<void**>(&(nVal->context->nConstructor)));
2216     if (nVal->status != napi_ok || nVal->context->nConstructor == nullptr) {
2217         IMAGE_LOGE("fail to unwrap context");
2218         return false;
2219     }
2220     nVal->context->status = SUCCESS;
2221     return true;
2222 }
2223 
SetAlphaExec(napi_env env,PixelMapAsyncContext * context)2224 static void SetAlphaExec(napi_env env, PixelMapAsyncContext* context)
2225 {
2226     if (context == nullptr) {
2227         IMAGE_LOGE("Null context");
2228         return;
2229     }
2230     if (context->status == SUCCESS) {
2231         if (context->rPixelMap != nullptr) {
2232             context->status = context->rPixelMap->SetAlpha(
2233                 static_cast<float>(context->alpha));
2234         } else {
2235             IMAGE_LOGE("Null native ref");
2236             context->status = ERR_IMAGE_INIT_ABNORMAL;
2237         }
2238     } else {
2239         IMAGE_LOGD("Scale has failed. do nothing");
2240     }
2241 }
2242 
SetAlpha(napi_env env,napi_callback_info info)2243 napi_value SendablePixelMapNapi::SetAlpha(napi_env env, napi_callback_info info)
2244 {
2245     std::unique_lock<std::shared_mutex> lock(mutex_);
2246     NapiValues nVal;
2247     nVal.argc = NUM_2;
2248     napi_value argValue[NUM_2] = {0};
2249     nVal.argv = argValue;
2250 
2251     IMAGE_LOGD("SetAlpha IN");
2252     if (!prepareNapiEnv(env, info, &nVal)) {
2253         return nVal.result;
2254     }
2255     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2256 
2257     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2258         IMAGE_LOGE("Invalid args count %{public}zu", nVal.argc);
2259         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2260     } else {
2261         if (napi_ok !=
2262             napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->alpha))) {
2263             IMAGE_LOGE("Arg 0 type mismatch");
2264             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2265         }
2266     }
2267     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2268         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2269     }
2270 
2271     if (nVal.context->callbackRef == nullptr) {
2272         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2273     }
2274     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2275         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . SetAlpha failed",
2276         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "SetAlphaGeneralError",
2277         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2278         nVal.result);
2279     napi_value _resource = nullptr;
2280     napi_create_string_utf8(env, "SetAlpha", NAPI_AUTO_LENGTH, &_resource);
2281     nVal.status = napi_create_async_work(env, nullptr, _resource,
2282         [](napi_env env, void *data) {
2283             auto context = static_cast<PixelMapAsyncContext*>(data);
2284             SetAlphaExec(env, context);
2285         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2286 
2287     if (nVal.status == napi_ok) {
2288         nVal.status = napi_queue_async_work(env, nVal.context->work);
2289         if (nVal.status == napi_ok) {
2290             nVal.context.release();
2291         }
2292     }
2293     return nVal.result;
2294 }
2295 
SetAlphaSync(napi_env env,napi_callback_info info)2296 napi_value SendablePixelMapNapi::SetAlphaSync(napi_env env, napi_callback_info info)
2297 {
2298     std::unique_lock<std::shared_mutex> lock(mutex_);
2299     napi_value result = nullptr;
2300     napi_get_undefined(env, &result);
2301     napi_status napiStatus;
2302     uint32_t status = SUCCESS;
2303     napi_value thisVar = nullptr;
2304     size_t argCount = NUM_1;
2305     napi_value argValue[NUM_1] = {0};
2306     double alpha = 0;
2307 
2308     IMAGE_LOGD("SetAlphaSync IN");
2309     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2310     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2311     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
2312         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2313         "SetAlphaSync failed"),
2314         IMAGE_LOGE("SetAlphaSync failed, invalid parameter"));
2315     napiStatus= napi_get_value_double(env, argValue[NUM_0], &alpha);
2316 
2317     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
2318 
2319     SendablePixelMapNapi* pixelMapNapi = nullptr;
2320     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2321     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
2322         IMAGE_LOGE("SetAlphaSync fail to unwrap context"));
2323     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2324         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2325         "Pixelmap has crossed threads . SetAlphaSync failed"),
2326         IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaSync failed"));
2327 
2328     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2329         status = pixelMapNapi->nativePixelMap_->SetAlpha(
2330             static_cast<float>(alpha));
2331         if (status != SUCCESS) {
2332             IMAGE_LOGE("SetAlphaSync failed");
2333         }
2334     } else {
2335         IMAGE_LOGE("Null native ref");
2336     }
2337     return result;
2338 }
2339 
ScaleExec(napi_env env,PixelMapAsyncContext * context)2340 static void ScaleExec(napi_env env, PixelMapAsyncContext* context)
2341 {
2342     if (context == nullptr) {
2343         IMAGE_LOGE("Null context");
2344         return;
2345     }
2346     if (context->status == SUCCESS) {
2347         if (context->rPixelMap != nullptr) {
2348             context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg));
2349             context->status = SUCCESS;
2350         } else {
2351             IMAGE_LOGE("Null native ref");
2352             context->status = ERR_IMAGE_INIT_ABNORMAL;
2353         }
2354     } else {
2355         IMAGE_LOGD("Scale has failed. do nothing");
2356     }
2357 }
2358 
Scale(napi_env env,napi_callback_info info)2359 napi_value SendablePixelMapNapi::Scale(napi_env env, napi_callback_info info)
2360 {
2361     std::unique_lock<std::shared_mutex> lock(mutex_);
2362     NapiValues nVal;
2363     nVal.argc = NUM_3;
2364     napi_value argValue[NUM_3] = {0};
2365     nVal.argv = argValue;
2366     IMAGE_LOGD("Scale IN");
2367     if (!prepareNapiEnv(env, info, &nVal)) {
2368         return nVal.result;
2369     }
2370     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2371 
2372     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2373         IMAGE_LOGE("Invalid args count %{public}zu", nVal.argc);
2374         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2375     } else {
2376         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2377             IMAGE_LOGE("Arg 0 type mismatch");
2378             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2379         }
2380         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_1], &(nVal.context->yArg))) {
2381             IMAGE_LOGE("Arg 1 type mismatch");
2382             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2383         }
2384     }
2385     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2386         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2387     }
2388 
2389     if (nVal.context->callbackRef == nullptr) {
2390         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2391     }
2392     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2393         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Scale failed",
2394         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "ScaleGeneralError",
2395         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2396         nVal.result);
2397     napi_value _resource = nullptr;
2398     napi_create_string_utf8(env, "Scale", NAPI_AUTO_LENGTH, &_resource);
2399     nVal.status = napi_create_async_work(env, nullptr, _resource,
2400         [](napi_env env, void *data) {
2401             auto context = static_cast<PixelMapAsyncContext*>(data);
2402             ScaleExec(env, context);
2403         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2404 
2405     if (nVal.status == napi_ok) {
2406         nVal.status = napi_queue_async_work_with_qos(env, nVal.context->work, napi_qos_user_initiated);
2407         if (nVal.status == napi_ok) {
2408             nVal.context.release();
2409         }
2410     }
2411     return nVal.result;
2412 }
2413 
ScaleSync(napi_env env,napi_callback_info info)2414 napi_value SendablePixelMapNapi::ScaleSync(napi_env env, napi_callback_info info)
2415 {
2416     std::unique_lock<std::shared_mutex> lock(mutex_);
2417     napi_value result = nullptr;
2418     napi_get_undefined(env, &result);
2419     napi_status napiStatus;
2420     napi_value thisVar = nullptr;
2421     size_t argCount = NUM_2;
2422     napi_value argValue[NUM_2] = {0};
2423     double xArg = 0;
2424     double yArg = 0;
2425     IMAGE_LOGD("ScaleSync IN");
2426     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2427 
2428     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
2429 
2430     IMG_NAPI_CHECK_RET_D(argCount == NUM_2,
2431         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2432         "Invalid args count"),
2433         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
2434     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_0], &xArg)),
2435         result, IMAGE_LOGE("Arg 0 type mismatch"));
2436     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_1], &yArg)),
2437         result, IMAGE_LOGE("Arg 1 type mismatch"));
2438     SendablePixelMapNapi* pixelMapNapi = nullptr;
2439     napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2440     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result,
2441         IMAGE_LOGE("ScaleSync fail to unwrap context"));
2442     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2443         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2444         "Pixelmap has crossed threads . ScaleSync failed"),
2445         IMAGE_LOGE("Pixelmap has crossed threads . ScaleSync failed"));
2446 
2447     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2448         pixelMapNapi->nativePixelMap_->scale(static_cast<float>(xArg), static_cast<float>(yArg));
2449     } else {
2450         IMAGE_LOGE("Null native ref");
2451     }
2452     return result;
2453 }
2454 
TranslateExec(napi_env env,PixelMapAsyncContext * context)2455 static void TranslateExec(napi_env env, PixelMapAsyncContext* context)
2456 {
2457     if (context == nullptr) {
2458         IMAGE_LOGE("Null context");
2459         return;
2460     }
2461     if (context->status == SUCCESS) {
2462         if (context->rPixelMap != nullptr) {
2463             context->rPixelMap->translate(static_cast<float>(context->xArg), static_cast<float>(context->yArg));
2464             context->status = SUCCESS;
2465         } else {
2466             IMAGE_LOGE("Null native ref");
2467             context->status = ERR_IMAGE_INIT_ABNORMAL;
2468         }
2469     } else {
2470         IMAGE_LOGD("Translate has failed. do nothing");
2471     }
2472 }
2473 
Translate(napi_env env,napi_callback_info info)2474 napi_value SendablePixelMapNapi::Translate(napi_env env, napi_callback_info info)
2475 {
2476     std::unique_lock<std::shared_mutex> lock(mutex_);
2477     NapiValues nVal;
2478     nVal.argc = NUM_3;
2479     napi_value argValue[NUM_3] = {0};
2480     nVal.argv = argValue;
2481     IMAGE_LOGD("Translate IN");
2482     if (!prepareNapiEnv(env, info, &nVal)) {
2483         return nVal.result;
2484     }
2485     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2486 
2487     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2488         IMAGE_LOGE("Invalid args count");
2489         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2490     } else {
2491         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2492             IMAGE_LOGE("Arg 0 type mismatch");
2493             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2494         }
2495         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_1], &(nVal.context->yArg))) {
2496             IMAGE_LOGE("Arg 1 type mismatch");
2497             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2498         }
2499     }
2500     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2501         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2502     }
2503 
2504     if (nVal.context->callbackRef == nullptr) {
2505         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2506     }
2507     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2508         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Translate failed",
2509         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "TranslateGeneralError",
2510         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2511         nVal.result);
2512     napi_value _resource = nullptr;
2513     napi_create_string_utf8(env, "Translate", NAPI_AUTO_LENGTH, &_resource);
2514     nVal.status = napi_create_async_work(env, nullptr, _resource,
2515         [](napi_env env, void *data) {
2516             auto context = static_cast<PixelMapAsyncContext*>(data);
2517             TranslateExec(env, context);
2518         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2519 
2520     if (nVal.status == napi_ok) {
2521         nVal.status = napi_queue_async_work(env, nVal.context->work);
2522         if (nVal.status == napi_ok) {
2523             nVal.context.release();
2524         }
2525     }
2526     return nVal.result;
2527 }
2528 
TranslateSync(napi_env env,napi_callback_info info)2529 napi_value SendablePixelMapNapi::TranslateSync(napi_env env, napi_callback_info info)
2530 {
2531     std::unique_lock<std::shared_mutex> lock(mutex_);
2532     napi_value result = nullptr;
2533     napi_get_undefined(env, &result);
2534     napi_status napiStatus;
2535     napi_value thisVar = nullptr;
2536     size_t argCount = NUM_2;
2537     napi_value argValue[NUM_2] = {0};
2538     double x = 0;
2539     double y = 0;
2540 
2541     IMAGE_LOGD("TranslateSync IN");
2542     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2543     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2544     IMG_NAPI_CHECK_RET_D(argCount == NUM_2,
2545         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2546         "TranslateSync failed"),
2547         IMAGE_LOGE("TranslateSync failed, invalid parameter"));
2548 
2549     if (napi_ok != napi_get_value_double(env, argValue[NUM_0], &x) ||
2550         napi_ok != napi_get_value_double(env, argValue[NUM_1], &y)) {
2551         IMAGE_LOGE("get arraybuffer info failed");
2552         return result;
2553     }
2554 
2555     SendablePixelMapNapi* pixelMapNapi = nullptr;
2556     napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2557     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result,
2558         IMAGE_LOGE("TranslateSync fail to unwrap context"));
2559     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2560         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2561         "Pixelmap has crossed threads . TranslateSync failed"),
2562         IMAGE_LOGE("Pixelmap has crossed threads . TranslateSync failed"));
2563 
2564     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2565         pixelMapNapi->nativePixelMap_->translate(static_cast<float>(x), static_cast<float>(y));
2566     } else {
2567         IMAGE_LOGE("Null native ref");
2568     }
2569     return result;
2570 }
2571 
RotateExec(napi_env env,PixelMapAsyncContext * context)2572 static void RotateExec(napi_env env, PixelMapAsyncContext* context)
2573 {
2574     if (context == nullptr) {
2575         IMAGE_LOGE("Null context");
2576         return;
2577     }
2578     if (context->status == SUCCESS) {
2579         if (context->rPixelMap != nullptr) {
2580             context->rPixelMap->rotate(context->xArg);
2581             context->status = SUCCESS;
2582         } else {
2583             IMAGE_LOGE("Null native ref");
2584             context->status = ERR_IMAGE_INIT_ABNORMAL;
2585         }
2586     } else {
2587         IMAGE_LOGD("Rotate has failed. do nothing");
2588     }
2589 }
2590 
Rotate(napi_env env,napi_callback_info info)2591 napi_value SendablePixelMapNapi::Rotate(napi_env env, napi_callback_info info)
2592 {
2593     std::unique_lock<std::shared_mutex> lock(mutex_);
2594     NapiValues nVal;
2595     nVal.argc = NUM_2;
2596     napi_value argValue[NUM_2] = {0};
2597     nVal.argv = argValue;
2598     IMAGE_LOGD("Rotate IN");
2599     if (!prepareNapiEnv(env, info, &nVal)) {
2600         return nVal.result;
2601     }
2602     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2603 
2604     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2605         IMAGE_LOGE("Invalid args count");
2606         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2607     } else {
2608         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2609             IMAGE_LOGE("Arg 0 type mismatch");
2610             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2611         }
2612     }
2613     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2614         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2615     }
2616 
2617     if (nVal.context->callbackRef == nullptr) {
2618         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2619     }
2620     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2621         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Rotate failed",
2622         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "RotateGeneralError",
2623         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2624         nVal.result);
2625     napi_value _resource = nullptr;
2626     napi_create_string_utf8(env, "Rotate", NAPI_AUTO_LENGTH, &_resource);
2627     nVal.status = napi_create_async_work(env, nullptr, _resource,
2628         [](napi_env env, void *data) {
2629             auto context = static_cast<PixelMapAsyncContext*>(data);
2630             RotateExec(env, context);
2631         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2632 
2633     if (nVal.status == napi_ok) {
2634         nVal.status = napi_queue_async_work(env, nVal.context->work);
2635         if (nVal.status == napi_ok) {
2636             nVal.context.release();
2637         }
2638     }
2639     return nVal.result;
2640 }
2641 
RotateSync(napi_env env,napi_callback_info info)2642 napi_value SendablePixelMapNapi::RotateSync(napi_env env, napi_callback_info info)
2643 {
2644     std::unique_lock<std::shared_mutex> lock(mutex_);
2645     napi_value result = nullptr;
2646     napi_get_undefined(env, &result);
2647     napi_status napiStatus;
2648     napi_value thisVar = nullptr;
2649     size_t argCount = NUM_1;
2650     napi_value argValue[NUM_1] = {0};
2651     double angle = 0;
2652 
2653     IMAGE_LOGD("RotateSync IN");
2654     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2655     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2656     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
2657         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2658         "RotateSync failed"),
2659         IMAGE_LOGE("RotateSync failed, invalid parameter"));
2660     napiStatus = napi_get_value_double(env, argValue[NUM_0], &angle);
2661     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
2662 
2663     SendablePixelMapNapi* pixelMapNapi = nullptr;
2664     napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2665     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result,
2666         IMAGE_LOGE("RotateSync fail to unwrap context"));
2667     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2668         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2669         "Pixelmap has crossed threads . RotateSync failed"),
2670         IMAGE_LOGE("Pixelmap has crossed threads . RotateSync failed"));
2671 
2672     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2673         pixelMapNapi->nativePixelMap_->rotate(static_cast<float>(angle));
2674     } else {
2675         IMAGE_LOGE("Null native ref");
2676     }
2677     return result;
2678 }
FlipExec(napi_env env,PixelMapAsyncContext * context)2679 static void FlipExec(napi_env env, PixelMapAsyncContext* context)
2680 {
2681     if (context == nullptr) {
2682         IMAGE_LOGE("Null context");
2683         return;
2684     }
2685     if (context->status == SUCCESS) {
2686         if (context->rPixelMap != nullptr) {
2687             context->rPixelMap->flip(context->xBarg, context->yBarg);
2688             context->status = SUCCESS;
2689         } else {
2690             IMAGE_LOGE("Null native ref");
2691             context->status = ERR_IMAGE_INIT_ABNORMAL;
2692         }
2693     } else {
2694         IMAGE_LOGD("Flip has failed. do nothing");
2695     }
2696 }
2697 
Flip(napi_env env,napi_callback_info info)2698 napi_value SendablePixelMapNapi::Flip(napi_env env, napi_callback_info info)
2699 {
2700     std::unique_lock<std::shared_mutex> lock(mutex_);
2701     NapiValues nVal;
2702     nVal.argc = NUM_3;
2703     napi_value argValue[NUM_3] = {0};
2704     nVal.argv = argValue;
2705     IMAGE_LOGD("Flip IN");
2706     if (!prepareNapiEnv(env, info, &nVal)) {
2707         return nVal.result;
2708     }
2709     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2710 
2711     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2712         IMAGE_LOGE("Invalid args count");
2713         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2714     } else {
2715         if (napi_ok != napi_get_value_bool(env, nVal.argv[NUM_0], &(nVal.context->xBarg))) {
2716             IMAGE_LOGE("Arg 0 type mismatch");
2717             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2718         }
2719         if (napi_ok != napi_get_value_bool(env, nVal.argv[NUM_1], &(nVal.context->yBarg))) {
2720             IMAGE_LOGE("Arg 1 type mismatch");
2721             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2722         }
2723     }
2724     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2725         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2726     }
2727 
2728     if (nVal.context->callbackRef == nullptr) {
2729         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2730     }
2731     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2732         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Flip failed",
2733         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "FlipGeneralError",
2734         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2735         nVal.result);
2736     napi_value _resource = nullptr;
2737     napi_create_string_utf8(env, "Flip", NAPI_AUTO_LENGTH, &_resource);
2738     nVal.status = napi_create_async_work(env, nullptr, _resource,
2739         [](napi_env env, void *data) {
2740             auto context = static_cast<PixelMapAsyncContext*>(data);
2741             FlipExec(env, context);
2742         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2743 
2744     if (nVal.status == napi_ok) {
2745         nVal.status = napi_queue_async_work(env, nVal.context->work);
2746         if (nVal.status == napi_ok) {
2747             nVal.context.release();
2748         }
2749     }
2750     return nVal.result;
2751 }
2752 
FlipSync(napi_env env,napi_callback_info info)2753 napi_value SendablePixelMapNapi::FlipSync(napi_env env, napi_callback_info info)
2754 {
2755     std::unique_lock<std::shared_mutex> lock(mutex_);
2756     napi_value result = nullptr;
2757     napi_get_undefined(env, &result);
2758     napi_status napiStatus;
2759     uint32_t status = SUCCESS;
2760     napi_value thisVar = nullptr;
2761     size_t argCount = NUM_2;
2762     napi_value argValue[NUM_2] = {0};
2763     bool xBarg = 0;
2764     bool yBarg = 0;
2765 
2766     IMAGE_LOGD("FlipSync IN");
2767     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2768     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2769     IMG_NAPI_CHECK_RET_D(argCount == NUM_2,
2770         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2771         "FlipSync failed"),
2772         IMAGE_LOGE("FlipSync failed, invalid parameter"));
2773 
2774     if (napi_ok != napi_get_value_bool(env, argValue[NUM_0], &xBarg)) {
2775         IMAGE_LOGE("Arg 0 type mismatch");
2776         status = COMMON_ERR_INVALID_PARAMETER;
2777     }
2778     if (napi_ok != napi_get_value_bool(env, argValue[NUM_1], &yBarg)) {
2779         IMAGE_LOGE("Arg 1 type mismatch");
2780         status = COMMON_ERR_INVALID_PARAMETER;
2781     }
2782 
2783     IMG_NAPI_CHECK_RET_D(status == SUCCESS, result, IMAGE_LOGE("FlipSync failed, invalid parameter"));
2784 
2785     SendablePixelMapNapi* pixelMapNapi = nullptr;
2786     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2787     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
2788         IMAGE_LOGE("FlipSync fail to unwrap context"));
2789     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2790         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2791         "Pixelmap has crossed threads . FlipSync failed"),
2792         IMAGE_LOGE("Pixelmap has crossed threads . FlipSync failed"));
2793 
2794     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2795         pixelMapNapi->nativePixelMap_->flip(xBarg, yBarg);
2796     } else {
2797         IMAGE_LOGE("Null native ref");
2798     }
2799     return result;
2800 }
2801 
CropExec(napi_env env,PixelMapAsyncContext * context)2802 static void CropExec(napi_env env, PixelMapAsyncContext* context)
2803 {
2804     if (context == nullptr) {
2805         IMAGE_LOGE("Null context");
2806         return;
2807     }
2808     if (context->status == SUCCESS) {
2809         if (context->rPixelMap != nullptr) {
2810             context->status = context->rPixelMap->crop(context->area.region);
2811         } else {
2812             IMAGE_LOGE("Null native ref");
2813             context->status = ERR_IMAGE_INIT_ABNORMAL;
2814         }
2815     } else {
2816         IMAGE_LOGD("Crop has failed. do nothing");
2817     }
2818 }
2819 
Crop(napi_env env,napi_callback_info info)2820 napi_value SendablePixelMapNapi::Crop(napi_env env, napi_callback_info info)
2821 {
2822     std::unique_lock<std::shared_mutex> lock(mutex_);
2823     NapiValues nVal;
2824     nVal.argc = NUM_2;
2825     napi_value argValue[NUM_2] = {0};
2826     nVal.argv = argValue;
2827     IMAGE_LOGD("Crop IN");
2828     if (!prepareNapiEnv(env, info, &nVal)) {
2829         return nVal.result;
2830     }
2831     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2832 
2833     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2834         IMAGE_LOGE("Invalid args count");
2835         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2836     } else {
2837         if (!parseRegion(env, nVal.argv[NUM_0], &(nVal.context->area.region))) {
2838             IMAGE_LOGE("Region type mismatch");
2839             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2840         }
2841     }
2842     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2843         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2844     }
2845 
2846     if (nVal.context->callbackRef == nullptr) {
2847         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2848     }
2849     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2850         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Crop failed",
2851         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "CropGeneralError",
2852         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2853         nVal.result);
2854     napi_value _resource = nullptr;
2855     napi_create_string_utf8(env, "CropExec", NAPI_AUTO_LENGTH, &_resource);
2856     nVal.status = napi_create_async_work(env, nullptr, _resource,
2857         [](napi_env env, void *data) {
2858             auto context = static_cast<PixelMapAsyncContext*>(data);
2859             CropExec(env, context);
2860         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2861 
2862     if (nVal.status == napi_ok) {
2863         nVal.status = napi_queue_async_work(env, nVal.context->work);
2864         if (nVal.status == napi_ok) {
2865             nVal.context.release();
2866         }
2867     }
2868     return nVal.result;
2869 }
2870 
CropSync(napi_env env,napi_callback_info info)2871 napi_value SendablePixelMapNapi::CropSync(napi_env env, napi_callback_info info)
2872 {
2873     std::unique_lock<std::shared_mutex> lock(mutex_);
2874     napi_value result = nullptr;
2875     napi_get_undefined(env, &result);
2876     napi_status napiStatus;
2877     uint32_t status = SUCCESS;
2878     napi_value thisVar = nullptr;
2879     size_t argCount = NUM_1;
2880     napi_value argValue[NUM_1] = {0};
2881     Rect region;
2882 
2883     IMAGE_LOGD("CropSync IN");
2884     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2885     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2886     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
2887         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2888         "CropSync failed"),
2889         IMAGE_LOGE("CropSync failed, invalid parameter"));
2890     if (!parseRegion(env, argValue[NUM_0], &region)) {
2891         IMAGE_LOGE("Region type mismatch");
2892         return result;
2893     }
2894 
2895     SendablePixelMapNapi* pixelMapNapi = nullptr;
2896     status = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2897     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result,
2898         IMAGE_LOGE("CropSync fail to unwrap context"));
2899     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2900         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2901         "Pixelmap has crossed threads . CropSync failed"),
2902         IMAGE_LOGE("Pixelmap has crossed threads . CropSync failed"));
2903 
2904     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2905         status = pixelMapNapi->nativePixelMap_->crop(region);
2906         if (status != SUCCESS) {
2907             IMAGE_LOGE("CropSync failed");
2908         }
2909     } else {
2910         IMAGE_LOGE("Null native ref");
2911     }
2912     return result;
2913 }
2914 
GetColorSpace(napi_env env,napi_callback_info info)2915 napi_value SendablePixelMapNapi::GetColorSpace(napi_env env, napi_callback_info info)
2916 {
2917     std::shared_lock<std::shared_mutex> lock(mutex_);
2918     NapiValues nVal;
2919     nVal.argc = NUM_0;
2920     IMAGE_LOGD("GetColorSpace IN");
2921     napi_get_undefined(env, &nVal.result);
2922     if (!prepareNapiEnv(env, info, &nVal)) {
2923         return ImageNapiUtils::ThrowExceptionError(
2924             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
2925     }
2926     if (nVal.argc != NUM_0) {
2927         return ImageNapiUtils::ThrowExceptionError(
2928             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
2929     }
2930     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
2931         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2932         "Pixelmap has crossed threads . GetColorSpace failed"),
2933         IMAGE_LOGE("Pixelmap has crossed threads . GetColorSpace failed"));
2934 #ifdef IMAGE_COLORSPACE_FLAG
2935     if (nVal.context->nConstructor->nativePixelMap_ == nullptr) {
2936         return ImageNapiUtils::ThrowExceptionError(
2937             env, ERR_IMAGE_DATA_ABNORMAL, "Invalid native pixelmap");
2938     }
2939     auto grCS = nVal.context->nConstructor->nativePixelMap_->InnerGetGrColorSpacePtr();
2940     if (grCS == nullptr) {
2941         return ImageNapiUtils::ThrowExceptionError(
2942             env, ERR_IMAGE_DATA_UNSUPPORT, "No colorspace in pixelmap");
2943     }
2944     auto resultValue = ColorManager::CreateJsColorSpaceObject(env, grCS);
2945     nVal.result = reinterpret_cast<napi_value>(resultValue);
2946 #else
2947     return ImageNapiUtils::ThrowExceptionError(
2948         env, ERR_INVALID_OPERATION, "Unsupported operation");
2949 #endif
2950     return nVal.result;
2951 }
2952 
SetColorSpace(napi_env env,napi_callback_info info)2953 napi_value SendablePixelMapNapi::SetColorSpace(napi_env env, napi_callback_info info)
2954 {
2955     std::unique_lock<std::shared_mutex> lock(mutex_);
2956     NapiValues nVal;
2957     nVal.argc = NUM_1;
2958     napi_value argValue[NUM_1] = {0};
2959     nVal.argv = argValue;
2960     IMAGE_LOGD("SetColorSpace IN");
2961     napi_get_undefined(env, &nVal.result);
2962     if (!prepareNapiEnv(env, info, &nVal)) {
2963         return ImageNapiUtils::ThrowExceptionError(
2964             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
2965     }
2966     if (nVal.argc != NUM_1) {
2967         return ImageNapiUtils::ThrowExceptionError(
2968             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
2969     }
2970     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
2971         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2972         "Pixelmap has crossed threads . SetColorSpace failed"),
2973         IMAGE_LOGE("Pixelmap has crossed threads . SetColorSpace failed"));
2974 #ifdef IMAGE_COLORSPACE_FLAG
2975     nVal.context->colorSpace = ColorManager::GetColorSpaceByJSObject(env, nVal.argv[NUM_0]);
2976     if (nVal.context->colorSpace == nullptr) {
2977         return ImageNapiUtils::ThrowExceptionError(
2978             env, ERR_IMAGE_INVALID_PARAMETER, "ColorSpace mismatch");
2979     }
2980     nVal.context->nConstructor->nativePixelMap_->InnerSetColorSpace(*(nVal.context->colorSpace));
2981 #else
2982     return ImageNapiUtils::ThrowExceptionError(
2983         env, ERR_INVALID_OPERATION, "Unsupported operation");
2984 #endif
2985     return nVal.result;
2986 }
2987 
Marshalling(napi_env env,napi_callback_info info)2988 napi_value SendablePixelMapNapi::Marshalling(napi_env env, napi_callback_info info)
2989 {
2990     std::unique_lock<std::shared_mutex> lock(mutex_);
2991     NapiValues nVal;
2992     nVal.argc = NUM_1;
2993     napi_value argValue[NUM_1] = {0};
2994     nVal.argv = argValue;
2995     IMAGE_LOGD("Marshalling IN");
2996 
2997     if (!prepareNapiEnv(env, info, &nVal)) {
2998         return ImageNapiUtils::ThrowExceptionError(
2999             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
3000     }
3001     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3002     if (nVal.argc != NUM_0 && nVal.argc != NUM_1) {
3003         return ImageNapiUtils::ThrowExceptionError(
3004             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
3005     }
3006     NAPI_MessageSequence *napiSequence = nullptr;
3007     napi_get_cb_info(env, info, &nVal.argc, nVal.argv, nullptr, nullptr);
3008     NapiUnwrap(env, nVal.argv[0], reinterpret_cast<void**>(&napiSequence));
3009     IMG_NAPI_CHECK_RET_D(IMG_NOT_NULL(napiSequence), nullptr,
3010         IMAGE_LOGE("Marshalling fail to unwrap context"));
3011     auto messageParcel = napiSequence->GetMessageParcel();
3012     bool st = nVal.context->rPixelMap->Marshalling(*messageParcel);
3013     if (!st) {
3014         return ImageNapiUtils::ThrowExceptionError(
3015             env, ERR_IPC, "marshalling pixel map to parcel failed.");
3016     }
3017     return nVal.result;
3018 }
3019 
ApplyColorSpaceExec(napi_env env,PixelMapAsyncContext * context)3020 static void ApplyColorSpaceExec(napi_env env, PixelMapAsyncContext* context)
3021 {
3022     if (context == nullptr) {
3023         IMAGE_LOGE("Null context");
3024         return;
3025     }
3026     if (context->status != SUCCESS) {
3027         IMAGE_LOGD("ApplyColorSpace has failed. do nothing");
3028         return;
3029     }
3030     if (context->rPixelMap == nullptr || context->colorSpace == nullptr) {
3031         context->status = ERR_IMAGE_INIT_ABNORMAL;
3032         IMAGE_LOGE("ApplyColorSpace Null native ref");
3033         return;
3034     }
3035     context->status = context->rPixelMap->ApplyColorSpace(*(context->colorSpace));
3036 }
3037 
ParseColorSpaceVal(napi_env env,napi_value val,PixelMapAsyncContext * context)3038 static void ParseColorSpaceVal(napi_env env, napi_value val, PixelMapAsyncContext* context)
3039 {
3040     if (context == nullptr) {
3041         IMAGE_LOGE("Null context");
3042         return;
3043     }
3044 
3045 #ifdef IMAGE_COLORSPACE_FLAG
3046     context->colorSpace = ColorManager::GetColorSpaceByJSObject(env, val);
3047     if (context->colorSpace == nullptr) {
3048         context->status = ERR_IMAGE_INVALID_PARAMETER;
3049     }
3050 #else
3051     Val.context->status = ERR_IMAGE_DATA_UNSUPPORT;
3052 #endif
3053 }
3054 
ApplyColorSpace(napi_env env,napi_callback_info info)3055 napi_value SendablePixelMapNapi::ApplyColorSpace(napi_env env, napi_callback_info info)
3056 {
3057     std::unique_lock<std::shared_mutex> lock(mutex_);
3058     NapiValues nVal;
3059     nVal.argc = NUM_2;
3060     napi_value argValue[NUM_2] = {0};
3061     nVal.argv = argValue;
3062     IMAGE_LOGD("ApplyColorSpace IN");
3063     if (!prepareNapiEnv(env, info, &nVal)) {
3064         return nVal.result;
3065     }
3066     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3067 
3068     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
3069         IMAGE_LOGE("Invalid args count");
3070         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3071     } else {
3072         ParseColorSpaceVal(env, nVal.argv[NUM_0], nVal.context.get());
3073     }
3074     if (nVal.argc >= NUM_1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
3075         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
3076     }
3077 
3078     if (nVal.context->callbackRef == nullptr) {
3079         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3080     }
3081     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
3082         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . ApplyColorSpace failed",
3083         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "ApplyColorSpaceGeneralError",
3084         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
3085         nVal.result);
3086     napi_value _resource = nullptr;
3087     napi_create_string_utf8(env, "ApplyColorSpace", NAPI_AUTO_LENGTH, &_resource);
3088     nVal.status = napi_create_async_work(env, nullptr, _resource, [](napi_env env, void *data) {
3089             auto context = static_cast<PixelMapAsyncContext*>(data);
3090             ApplyColorSpaceExec(env, context);
3091         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
3092 
3093     if (nVal.status == napi_ok) {
3094         nVal.status = napi_queue_async_work(env, nVal.context->work);
3095         if (nVal.status == napi_ok) {
3096             nVal.context.release();
3097         }
3098     }
3099     return nVal.result;
3100 }
3101 
release()3102 void SendablePixelMapNapi::release()
3103 {
3104     if (!isRelease) {
3105         if (nativePixelMap_ != nullptr) {
3106             nativePixelMap_.reset();
3107         }
3108         isRelease = true;
3109     }
3110 }
3111 }  // namespace Media
3112 }  // namespace OHOS
3113