• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <mutex>
17 #include "js_canvas.h"
18 #include "../brush_napi/js_brush.h"
19 #include "../pen_napi/js_pen.h"
20 #include "../path_napi/js_path.h"
21 #include "../text_blob_napi/js_text_blob.h"
22 #include "../js_drawing_utils.h"
23 #include "native_value.h"
24 #ifdef ROSEN_OHOS
25 #include "pixel_map.h"
26 #include "pixel_map_napi.h"
27 #endif
28 #include "draw/canvas.h"
29 #include "image/image.h"
30 #include "draw/path.h"
31 #include "text/text.h"
32 #include "text/text_blob.h"
33 #include "utils/point.h"
34 #include "utils/sampling_options.h"
35 #include "utils/rect.h"
36 
37 namespace OHOS::Rosen {
38 #ifdef ROSEN_OHOS
39 using namespace Media;
40 namespace {
ColorSpaceToDrawingColorSpace(ColorSpace colorSpace)41 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorSpace colorSpace)
42 {
43     switch (colorSpace) {
44         case ColorSpace::DISPLAY_P3:
45             return Drawing::ColorSpace::CreateRGB(
46                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
47         case ColorSpace::LINEAR_SRGB:
48             return Drawing::ColorSpace::CreateSRGBLinear();
49         case ColorSpace::SRGB:
50             return Drawing::ColorSpace::CreateSRGB();
51         default:
52             return Drawing::ColorSpace::CreateSRGB();
53     }
54 }
55 
PixelFormatToDrawingColorType(PixelFormat pixelFormat)56 static Drawing::ColorType PixelFormatToDrawingColorType(PixelFormat pixelFormat)
57 {
58     switch (pixelFormat) {
59         case PixelFormat::RGB_565:
60             return Drawing::ColorType::COLORTYPE_RGB_565;
61         case PixelFormat::RGBA_8888:
62             return Drawing::ColorType::COLORTYPE_RGBA_8888;
63         case PixelFormat::BGRA_8888:
64             return Drawing::ColorType::COLORTYPE_BGRA_8888;
65         case PixelFormat::ALPHA_8:
66             return Drawing::ColorType::COLORTYPE_ALPHA_8;
67         case PixelFormat::RGBA_F16:
68             return Drawing::ColorType::COLORTYPE_RGBA_F16;
69         case PixelFormat::UNKNOWN:
70         case PixelFormat::ARGB_8888:
71         case PixelFormat::RGB_888:
72         case PixelFormat::NV21:
73         case PixelFormat::NV12:
74         case PixelFormat::CMYK:
75         default:
76             return Drawing::ColorType::COLORTYPE_UNKNOWN;
77     }
78 }
79 
AlphaTypeToDrawingAlphaType(AlphaType alphaType)80 static Drawing::AlphaType AlphaTypeToDrawingAlphaType(AlphaType alphaType)
81 {
82     switch (alphaType) {
83         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
84             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
85         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
86             return Drawing::AlphaType::ALPHATYPE_OPAQUE;
87         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
88             return Drawing::AlphaType::ALPHATYPE_PREMUL;
89         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
90             return Drawing::AlphaType::ALPHATYPE_UNPREMUL;
91         default:
92             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
93     }
94 }
95 
96 struct PixelMapReleaseContext {
PixelMapReleaseContextOHOS::Rosen::__anonce4dcf360111::PixelMapReleaseContext97     explicit PixelMapReleaseContext(std::shared_ptr<PixelMap> pixelMap) : pixelMap_(pixelMap) {}
98 
~PixelMapReleaseContextOHOS::Rosen::__anonce4dcf360111::PixelMapReleaseContext99     ~PixelMapReleaseContext()
100     {
101         pixelMap_ = nullptr;
102     }
103 
104 private:
105     std::shared_ptr<PixelMap> pixelMap_;
106 };
107 
PixelMapReleaseProc(const void *,void * context)108 static void PixelMapReleaseProc(const void* /* pixels */, void* context)
109 {
110     PixelMapReleaseContext* ctx = static_cast<PixelMapReleaseContext*>(context);
111     if (ctx) {
112         delete ctx;
113         ctx = nullptr;
114     }
115 }
116 
ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)117 std::shared_ptr<Drawing::Image> ExtractDrawingImage(
118     std::shared_ptr<Media::PixelMap> pixelMap)
119 {
120     if (!pixelMap) {
121         ROSEN_LOGE("Drawing_napi::pixelMap fail");
122         return nullptr;
123     }
124     ImageInfo imageInfo;
125     pixelMap->GetImageInfo(imageInfo);
126     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
127         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
128         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
129         ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
130     Drawing::Pixmap imagePixmap(drawingImageInfo,
131         reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowBytes());
132     PixelMapReleaseContext* releaseContext = new PixelMapReleaseContext(pixelMap);
133     auto image = Drawing::Image::MakeFromRaster(imagePixmap, PixelMapReleaseProc, releaseContext);
134     if (!image) {
135         ROSEN_LOGE("Drawing_napi :RSPixelMapUtil::ExtractDrawingImage fail");
136         delete releaseContext;
137         releaseContext = nullptr;
138     }
139     return image;
140 }
141 
ExtracetDrawingBitmap(std::shared_ptr<Media::PixelMap> pixelMap,Drawing::Bitmap & bitmap)142 bool ExtracetDrawingBitmap(std::shared_ptr<Media::PixelMap> pixelMap, Drawing::Bitmap& bitmap)
143 {
144     if (!pixelMap) {
145         ROSEN_LOGE("Drawing_napi ::pixelMap fail");
146         return false;
147     }
148     ImageInfo imageInfo;
149     pixelMap->GetImageInfo(imageInfo);
150     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
151         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
152         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
153         ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
154     bitmap.SetInfo(drawingImageInfo);
155     bitmap.SetPixels(const_cast<void*>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
156     return true;
157 }
158 }
159 #endif
160 
161 namespace Drawing {
162 thread_local napi_ref JsCanvas::constructor_ = nullptr;
163 static std::mutex g_constructorInitMutex;
164 
165 Canvas* g_drawingCanvas = nullptr;
166 const std::string CLASS_NAME = "Canvas";
Constructor(napi_env env,napi_callback_info info)167 napi_value JsCanvas::Constructor(napi_env env, napi_callback_info info)
168 {
169     napi_value jsThis = nullptr;
170     size_t argc = ARGC_ONE;
171     napi_value argv[ARGC_ONE] = {nullptr};
172     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
173     if (status != napi_ok) {
174         ROSEN_LOGE("Drawing_napi: failed to napi_get_cb_info");
175         return nullptr;
176     }
177     if (argc == 0) {
178         if (g_drawingCanvas == nullptr) {
179             ROSEN_LOGE("Drawing_napi: m_canvas is nullptr");
180             return nullptr;
181         }
182         JsCanvas *jsCanvas = new(std::nothrow) JsCanvas(g_drawingCanvas);
183         status = napi_wrap(env, jsThis, jsCanvas, JsCanvas::Destructor, nullptr, nullptr);
184         if (status != napi_ok) {
185             delete jsCanvas;
186             ROSEN_LOGE("Drawing_napi: Failed to wrap native instance");
187             return nullptr;
188         }
189     } else {
190 #ifdef ROSEN_OHOS
191         PixelMapNapi* pixelMapNapi = nullptr;
192         napi_unwrap(env, argv[0], reinterpret_cast<void**>(&pixelMapNapi));
193         if (pixelMapNapi == nullptr) {
194             return nullptr;
195         }
196 
197         if (pixelMapNapi != nullptr && pixelMapNapi->GetPixelNapiInner() == nullptr) {
198             return nullptr;
199         }
200 
201         Bitmap bitmap;
202         if (!ExtracetDrawingBitmap(pixelMapNapi->GetPixelNapiInner(), bitmap)) {
203             return nullptr;
204         }
205 
206         Canvas* canvas = new Canvas();
207         canvas->Bind(bitmap);
208         JsCanvas *jsCanvas = new(std::nothrow) JsCanvas(canvas, true);
209         status = napi_wrap(env, jsThis, jsCanvas, JsCanvas::Destructor, nullptr, nullptr);
210         if (status != napi_ok) {
211             delete jsCanvas;
212             ROSEN_LOGE("Drawing_napi: Failed to wrap native instance");
213             return nullptr;
214         }
215 #else
216         return nullptr;
217 #endif
218     }
219     return jsThis;
220 }
221 
DeclareFuncAndCreateConstructor(napi_env env)222 bool JsCanvas::DeclareFuncAndCreateConstructor(napi_env env)
223 {
224     napi_property_descriptor properties[] = {
225         DECLARE_NAPI_FUNCTION("drawRect", JsCanvas::DrawRect),
226         DECLARE_NAPI_FUNCTION("drawCircle", JsCanvas::DrawCircle),
227         DECLARE_NAPI_FUNCTION("drawImage", JsCanvas::DrawImage),
228         DECLARE_NAPI_FUNCTION("drawColor", JsCanvas::DrawColor),
229         DECLARE_NAPI_FUNCTION("drawPoint", JsCanvas::DrawPoint),
230         DECLARE_NAPI_FUNCTION("drawPath", JsCanvas::DrawPath),
231         DECLARE_NAPI_FUNCTION("drawLine", JsCanvas::DrawLine),
232         DECLARE_NAPI_FUNCTION("drawTextBlob", JsCanvas::DrawText),
233         DECLARE_NAPI_FUNCTION("attachPen", JsCanvas::AttachPen),
234         DECLARE_NAPI_FUNCTION("attachBrush", JsCanvas::AttachBrush),
235         DECLARE_NAPI_FUNCTION("detachPen", JsCanvas::DetachPen),
236         DECLARE_NAPI_FUNCTION("detachBrush", JsCanvas::DetachBrush),
237     };
238 
239     napi_value constructor = nullptr;
240     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
241         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
242     if (status != napi_ok) {
243         ROSEN_LOGE("Drawing_napi: DeclareFuncAndCreateConstructor Failed, define class fail");
244         return false;
245     }
246 
247     status = napi_create_reference(env, constructor, 1, &constructor_);
248     if (status != napi_ok) {
249         ROSEN_LOGE("Drawing_napi: DeclareFuncAndCreateConstructor Failed, create reference fail");
250         return false;
251     }
252     return true;
253 }
254 
CreateJsCanvas(napi_env env,Canvas * canvas,float width,float height)255 napi_value JsCanvas::CreateJsCanvas(napi_env env, Canvas* canvas, float width, float height)
256 {
257     napi_value constructor = nullptr;
258     napi_value result = nullptr;
259 
260     {
261         std::lock_guard<std::mutex> lock(g_constructorInitMutex);
262         if (!constructor_) {
263             if (!DeclareFuncAndCreateConstructor(env)) {
264                 ROSEN_LOGE("Drawing_napi: DeclareFuncAndCreateConstructor Failed");
265                 return nullptr;
266             }
267         }
268     }
269 
270     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
271     if (status != napi_ok) {
272         ROSEN_LOGE("Drawing_napi: CreateJsCanvas napi_get_reference_value failed");
273         return nullptr;
274     }
275     g_drawingCanvas = canvas;
276     Rect rect(0, 0, width, height);
277     canvas->ClipRect(rect);
278     status = napi_new_instance(env, constructor, 0, nullptr, &result);
279     if (status != napi_ok) {
280         ROSEN_LOGE("Drawing_napi: New instance could not be obtained");
281         return nullptr;
282     }
283     return result;
284 }
285 
Destructor(napi_env env,void * nativeObject,void * finalize)286 void JsCanvas::Destructor(napi_env env, void *nativeObject, void *finalize)
287 {
288     (void)finalize;
289     if (nativeObject != nullptr) {
290         JsCanvas *napi = reinterpret_cast<JsCanvas *>(nativeObject);
291         delete napi;
292     }
293 }
294 
Init(napi_env env,napi_value exportObj)295 napi_value JsCanvas::Init(napi_env env, napi_value exportObj)
296 {
297     {
298         std::lock_guard<std::mutex> lock(g_constructorInitMutex);
299         if (!constructor_) {
300             if (!DeclareFuncAndCreateConstructor(env)) {
301                 ROSEN_LOGE("Drawing_napi: DeclareFuncAndCreateConstructor Failed");
302                 return nullptr;
303             }
304         }
305     }
306 
307     napi_value constructor = nullptr;
308     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
309     if (status != napi_ok) {
310         ROSEN_LOGE("Drawing_napi: napi_get_reference_value failed");
311         return nullptr;
312     }
313 
314     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
315     if (status != napi_ok) {
316         ROSEN_LOGE("Drawing_napi: Failed to set constructor");
317         return nullptr;
318     }
319     return exportObj;
320 }
321 
~JsCanvas()322 JsCanvas::~JsCanvas()
323 {
324     if (owned_) {
325         delete m_canvas;
326     }
327     m_canvas = nullptr;
328     g_drawingCanvas = nullptr;
329 }
330 
DrawRect(napi_env env,napi_callback_info info)331 napi_value JsCanvas::DrawRect(napi_env env, napi_callback_info info)
332 {
333     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
334     return (me != nullptr) ? me->OnDrawRect(env, info) : nullptr;
335 }
336 
OnDrawRect(napi_env env,napi_callback_info info)337 napi_value JsCanvas::OnDrawRect(napi_env env, napi_callback_info info)
338 {
339     if (m_canvas == nullptr) {
340         ROSEN_LOGE("JsCanvas::OnDrawRect canvas is nullptr");
341         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
342     }
343 
344     size_t argc = ARGC_ONE;
345     napi_value argv[ARGC_ONE] = {nullptr};
346     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
347     if (status != napi_ok || argc < ARGC_ONE) {
348         ROSEN_LOGE("JsCanvas::OnDrawRect Argc is invalid: %{public}zu", argc);
349         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
350     }
351 
352     napi_valuetype valueType = napi_undefined;
353     if (argv[0] == nullptr || napi_typeof(env, argv[0], &valueType) != napi_ok || valueType != napi_object) {
354         ROSEN_LOGE("JsCanvas::OnDrawRect Argv[0] is invalid");
355         return NapiGetUndefined(env);
356     }
357 
358     napi_value tempValue = nullptr;
359     double left = 0.0;
360     double top = 0.0;
361     double right = 0.0;
362     double bottom = 0.0;
363     napi_get_named_property(env, argv[0], "left", &tempValue);
364     bool isLeftOk = ConvertFromJsValue(env, tempValue, left);
365     napi_get_named_property(env, argv[0], "right", &tempValue);
366     bool isRightOk = ConvertFromJsValue(env, tempValue, right);
367     napi_get_named_property(env, argv[0], "top", &tempValue);
368     bool isTopOk = ConvertFromJsValue(env, tempValue, top);
369     napi_get_named_property(env, argv[0], "bottom", &tempValue);
370     bool isBottomOk = ConvertFromJsValue(env, tempValue, bottom);
371     if (!(isLeftOk && isRightOk && isTopOk && isBottomOk)) {
372         ROSEN_LOGE("JsCanvas::OnDrawRect Argv[0] is invalid");
373         return NapiGetUndefined(env);
374     }
375 
376     Drawing::Rect drawingRect = Drawing::Rect(left, top, right, bottom);
377     m_canvas->DrawRect(drawingRect);
378     return NapiGetUndefined(env);
379 }
380 
DrawCircle(napi_env env,napi_callback_info info)381 napi_value JsCanvas::DrawCircle(napi_env env, napi_callback_info info)
382 {
383     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
384     return (me != nullptr) ? me->OnDrawCircle(env, info) : nullptr;
385 }
386 
OnDrawCircle(napi_env env,napi_callback_info info)387 napi_value JsCanvas::OnDrawCircle(napi_env env, napi_callback_info info)
388 {
389     if (m_canvas == nullptr) {
390         ROSEN_LOGE("JsCanvas::OnDrawCircle canvas is null");
391         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
392     }
393     size_t argc = ARGC_THREE;
394     napi_value argv[ARGC_THREE] = {nullptr};
395     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
396     if (status != napi_ok || argc < ARGC_THREE) {
397         ROSEN_LOGE("JsCanvas::OnDrawCircle Argc is invalid: %{public}zu", argc);
398         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
399     }
400 
401     double x = 0.0;
402     double y = 0.0;
403     double radius = 0.0;
404     if (!(ConvertFromJsValue(env, argv[0], x) && ConvertFromJsValue(env, argv[ARGC_ONE], y) &&
405         ConvertFromJsValue(env, argv[ARGC_TWO], radius))) {
406         ROSEN_LOGE("JsCanvas::OnDrawCircle Argv is invalid");
407         return NapiGetUndefined(env);
408     }
409 
410     Drawing::Point centerPt = Drawing::Point(x, y);
411     m_canvas->DrawCircle(centerPt, radius);
412     return NapiGetUndefined(env);
413 }
414 
DrawImage(napi_env env,napi_callback_info info)415 napi_value JsCanvas::DrawImage(napi_env env, napi_callback_info info)
416 {
417     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
418     return (me != nullptr) ? me->OnDrawImage(env, info) : nullptr;
419 }
420 
OnDrawImage(napi_env env,napi_callback_info info)421 napi_value JsCanvas::OnDrawImage(napi_env env, napi_callback_info info)
422 {
423 #ifdef ROSEN_OHOS
424     if (m_canvas == nullptr) {
425         ROSEN_LOGE("JsCanvas::OnDrawImage canvas is nullptr");
426         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
427     }
428     size_t argc = ARGC_THREE;
429     napi_value argv[ARGC_THREE] = {nullptr};
430     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
431     if (status != napi_ok || argc < ARGC_THREE) {
432         ROSEN_LOGE("JsCanvas::OnDrawImage Argc is invalid: %{public}zu", argc);
433         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
434     }
435 
436     PixelMapNapi* pixelMapNapi = nullptr;
437     double px = 0.0;
438     double py = 0.0;
439     napi_unwrap(env, argv[0], reinterpret_cast<void**>(&pixelMapNapi));
440     if (pixelMapNapi == nullptr ||
441         !(ConvertFromJsValue(env, argv[ARGC_ONE], px) && ConvertFromJsValue(env, argv[ARGC_TWO], py))) {
442         ROSEN_LOGE("JsCanvas::OnDrawImage Argv is invalid");
443         return NapiGetUndefined(env);
444     }
445 
446     if (pixelMapNapi->GetPixelNapiInner() == nullptr) {
447         ROSEN_LOGE("JsCanvas::OnDrawImage pixelmap GetPixelNapiInner is nullptr");
448         return NapiGetUndefined(env);
449     }
450 
451     std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixelMapNapi->GetPixelNapiInner());
452     if (image == nullptr) {
453         ROSEN_LOGE("JsCanvas::OnDrawImage image is nullptr");
454         return NapiGetUndefined(env);
455     }
456 
457     m_canvas->DrawImage(*image, px, py, Drawing::SamplingOptions());
458 #endif
459     return NapiGetUndefined(env);
460 }
461 
DrawColor(napi_env env,napi_callback_info info)462 napi_value JsCanvas::DrawColor(napi_env env, napi_callback_info info)
463 {
464     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
465     return (me != nullptr) ? me->OnDrawColor(env, info) : nullptr;
466 }
467 
OnDrawColor(napi_env env,napi_callback_info info)468 napi_value JsCanvas::OnDrawColor(napi_env env, napi_callback_info info)
469 {
470     if (m_canvas == nullptr) {
471         ROSEN_LOGE("JsCanvas::OnDrawColor canvas is nullptr");
472         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
473     }
474     size_t argc = ARGC_TWO;
475     napi_value argv[ARGC_TWO] = {nullptr};
476     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
477     if (status != napi_ok || argc < ARGC_ONE || argc > ARGC_TWO) {
478         ROSEN_LOGE("JsCanvas::OnDrawColor Argc is invalid: %{public}zu", argc);
479         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
480     }
481 
482     napi_value tempValue = nullptr;
483     int32_t alpha = 0;
484     int32_t red = 0;
485     int32_t green = 0;
486     int32_t blue = 0;
487     napi_get_named_property(env, argv[0], "alpha", &tempValue);
488     bool isAlphaOk = ConvertClampFromJsValue(env, tempValue, alpha, 0, Color::RGB_MAX);
489     napi_get_named_property(env, argv[0], "red", &tempValue);
490     bool isRedOk = ConvertClampFromJsValue(env, tempValue, red, 0, Color::RGB_MAX);
491     napi_get_named_property(env, argv[0], "green", &tempValue);
492     bool isGreenOk = ConvertClampFromJsValue(env, tempValue, green, 0, Color::RGB_MAX);
493     napi_get_named_property(env, argv[0], "blue", &tempValue);
494     bool isBlueOk = ConvertClampFromJsValue(env, tempValue, blue, 0, Color::RGB_MAX);
495     if (!(isAlphaOk && isRedOk && isGreenOk && isBlueOk)) {
496         ROSEN_LOGE("JsCanvas::OnDrawColor Argv[0] is invalid");
497         return NapiGetUndefined(env);
498     }
499 
500     auto color = Color::ColorQuadSetARGB(alpha, red, green, blue);
501     if (argc == ARGC_ONE) {
502         m_canvas->DrawColor(color);
503     } else {
504         uint32_t jsMode = 0;
505         if (!ConvertFromJsValue(env, argv[1], jsMode)) {
506             ROSEN_LOGE("JsCanvas::OnDrawColor Argv[1] is invalid");
507             return NapiGetUndefined(env);
508         }
509         m_canvas->DrawColor(color, BlendMode(jsMode));
510     }
511     return NapiGetUndefined(env);
512 }
513 
DrawPoint(napi_env env,napi_callback_info info)514 napi_value JsCanvas::DrawPoint(napi_env env, napi_callback_info info)
515 {
516     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
517     return (me != nullptr) ? me->OnDrawPoint(env, info) : nullptr;
518 }
519 
OnDrawPoint(napi_env env,napi_callback_info info)520 napi_value JsCanvas::OnDrawPoint(napi_env env, napi_callback_info info)
521 {
522     if (m_canvas == nullptr) {
523         ROSEN_LOGE("JsCanvas::OnDrawPoint canvas is nullptr");
524         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
525     }
526     size_t argc = ARGC_TWO;
527     napi_value argv[ARGC_TWO] = {nullptr};
528     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
529     if (status != napi_ok || argc < ARGC_TWO) {
530         ROSEN_LOGE("JsCanvas::OnDrawPoint Argc is invalid: %{public}zu", argc);
531         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
532     }
533     double px = 0.0;
534     double py = 0.0;
535     if (!(ConvertFromJsValue(env, argv[0], px) && ConvertFromJsValue(env, argv[1], py))) {
536         ROSEN_LOGE("JsCanvas::OnDrawPoint Argv is invalid");
537         return NapiGetUndefined(env);
538     }
539 
540     m_canvas->DrawPoint(Point(px, py));
541     return NapiGetUndefined(env);
542 }
543 
DrawPath(napi_env env,napi_callback_info info)544 napi_value JsCanvas::DrawPath(napi_env env, napi_callback_info info)
545 {
546     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
547     return (me != nullptr) ? me->OnDrawPath(env, info) : nullptr;
548 }
549 
OnDrawPath(napi_env env,napi_callback_info info)550 napi_value JsCanvas::OnDrawPath(napi_env env, napi_callback_info info)
551 {
552     if (m_canvas == nullptr) {
553         ROSEN_LOGE("JsCanvas::OnDrawPath canvas is nullptr");
554         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
555     }
556     size_t argc = ARGC_ONE;
557     napi_value argv[ARGC_ONE] = {nullptr};
558     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
559     if (status != napi_ok || argc < ARGC_ONE) {
560         ROSEN_LOGE("JsCanvas::OnDrawPath Argc is invalid: %{public}zu", argc);
561         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
562     }
563 
564     JsPath* jsPath = nullptr;
565     napi_unwrap(env, argv[0], reinterpret_cast<void**>(&jsPath));
566     if (jsPath == nullptr) {
567         ROSEN_LOGE("JsCanvas::OnDrawPath jsPath is nullptr");
568         return NapiGetUndefined(env);
569     }
570 
571     if (jsPath->GetPath() == nullptr) {
572         ROSEN_LOGE("JsCanvas::OnDrawPath path is nullptr");
573         return NapiGetUndefined(env);
574     }
575 
576     m_canvas->DrawPath(*jsPath->GetPath());
577     return NapiGetUndefined(env);
578 }
579 
DrawLine(napi_env env,napi_callback_info info)580 napi_value JsCanvas::DrawLine(napi_env env, napi_callback_info info)
581 {
582     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
583     return (me != nullptr) ? me->OnDrawLine(env, info) : nullptr;
584 }
585 
OnDrawLine(napi_env env,napi_callback_info info)586 napi_value JsCanvas::OnDrawLine(napi_env env, napi_callback_info info)
587 {
588     if (m_canvas == nullptr) {
589         ROSEN_LOGE("JsCanvas::OnDrawLine canvas is nullptr");
590         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
591     }
592     size_t argc = ARGC_FOUR;
593     napi_value argv[ARGC_FOUR] = {nullptr};
594     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
595     if (status != napi_ok || argc < ARGC_FOUR) {
596         ROSEN_LOGE("JsCanvas::OnDrawLine Argc is invalid: %{public}zu", argc);
597         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
598     }
599 
600     double startPx = 0.0;
601     double startPy = 0.0;
602     double endPx = 0.0;
603     double endPy = 0.0;
604     if (!(ConvertFromJsValue(env, argv[0], startPx) && ConvertFromJsValue(env, argv[ARGC_ONE], startPy) &&
605         ConvertFromJsValue(env, argv[ARGC_TWO], endPx) && ConvertFromJsValue(env, argv[ARGC_THREE], endPy))) {
606         ROSEN_LOGE("JsCanvas::OnDrawLine Argv is invalid");
607         return NapiGetUndefined(env);
608     }
609 
610     m_canvas->DrawLine(Point(startPx, startPy), Point(endPx, endPy));
611     return NapiGetUndefined(env);
612 }
613 
DrawText(napi_env env,napi_callback_info info)614 napi_value JsCanvas::DrawText(napi_env env, napi_callback_info info)
615 {
616     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
617     return (me != nullptr) ? me->OnDrawText(env, info) : nullptr;
618 }
619 
OnDrawText(napi_env env,napi_callback_info info)620 napi_value JsCanvas::OnDrawText(napi_env env, napi_callback_info info)
621 {
622     if (m_canvas == nullptr) {
623         ROSEN_LOGE("JsCanvas::OnDrawText canvas is null");
624         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
625     }
626     size_t argc = ARGC_THREE;
627     napi_value argv[ARGC_THREE] = {nullptr};
628     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
629     if (status != napi_ok || argc < ARGC_THREE) {
630         ROSEN_LOGE("JsCanvas::OnDrawText Argc is invalid: %{public}zu", argc);
631         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
632     }
633 
634     JsTextBlob* jsTextBlob = nullptr;
635     double x = 0.0;
636     double y = 0.0;
637     napi_unwrap(env, argv[0], reinterpret_cast<void **>(&jsTextBlob));
638     if (jsTextBlob == nullptr ||
639         !(ConvertFromJsValue(env, argv[ARGC_ONE], x) && ConvertFromJsValue(env, argv[ARGC_TWO], y))) {
640         ROSEN_LOGE("JsCanvas::OnDrawText Argv is invalid");
641         return NapiGetUndefined(env);
642     }
643 
644     m_canvas->DrawTextBlob(jsTextBlob->GetTextBlob().get(), x, y);
645     return NapiGetUndefined(env);
646 }
647 
AttachPen(napi_env env,napi_callback_info info)648 napi_value JsCanvas::AttachPen(napi_env env, napi_callback_info info)
649 {
650     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
651     if (me == nullptr) {
652         return nullptr;
653     }
654     Canvas* canvas = me->GetCanvas();
655     if (canvas == nullptr) {
656         ROSEN_LOGE("JsCanvas::AttachPen canvas is nullptr");
657         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
658     }
659     size_t argc = ARGC_ONE;
660     napi_value argv[ARGC_ONE] = {nullptr};
661     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
662     if (status != napi_ok || argc < ARGC_ONE) {
663         ROSEN_LOGE("JsCanvas::AttachPen Argc is invalid: %{public}zu", argc);
664         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
665     }
666 
667     JsPen* jsPen = nullptr;
668     napi_unwrap(env, argv[0], reinterpret_cast<void **>(&jsPen));
669     if (jsPen == nullptr) {
670         ROSEN_LOGE("JsCanvas::AttachPen jsPen is nullptr");
671         return NapiGetUndefined(env);
672     }
673     if (jsPen->GetPen() == nullptr) {
674         ROSEN_LOGE("JsCanvas::AttachPen pen is nullptr");
675         return NapiGetUndefined(env);
676     }
677     canvas->AttachPen(*jsPen->GetPen());
678     return NapiGetUndefined(env);
679 }
680 
AttachBrush(napi_env env,napi_callback_info info)681 napi_value JsCanvas::AttachBrush(napi_env env, napi_callback_info info)
682 {
683     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
684     if (me == nullptr) {
685         return nullptr;
686     }
687     Canvas* canvas = me->GetCanvas();
688     if (canvas == nullptr) {
689         ROSEN_LOGE("JsCanvas::AttachBrush canvas is nullptr");
690         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
691     }
692     size_t argc = ARGC_ONE;
693     napi_value argv[ARGC_ONE] = {nullptr};
694     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
695     if (status != napi_ok || argc < ARGC_ONE) {
696         ROSEN_LOGE("JsCanvas::AttachBrush Argc is invalid: %{public}zu", argc);
697         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
698     }
699 
700     JsBrush* jsBrush = nullptr;
701     napi_unwrap(env, argv[0], reinterpret_cast<void **>(&jsBrush));
702     if (jsBrush == nullptr) {
703         ROSEN_LOGE("JsCanvas::AttachBrush jsBrush is nullptr");
704         return NapiGetUndefined(env);
705     }
706     if (jsBrush->GetBrush() == nullptr) {
707         ROSEN_LOGE("JsCanvas::AttachBrush brush is nullptr");
708         return NapiGetUndefined(env);
709     }
710     canvas->AttachBrush(*jsBrush->GetBrush());
711     return NapiGetUndefined(env);
712 }
713 
DetachPen(napi_env env,napi_callback_info info)714 napi_value JsCanvas::DetachPen(napi_env env, napi_callback_info info)
715 {
716     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
717     if (me == nullptr) {
718         return nullptr;
719     }
720     Canvas* canvas = me->GetCanvas();
721     if (canvas == nullptr) {
722         ROSEN_LOGE("JsCanvas::DetachPen canvas is null");
723         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
724     }
725     canvas->DetachPen();
726     return NapiGetUndefined(env);
727 }
728 
DetachBrush(napi_env env,napi_callback_info info)729 napi_value JsCanvas::DetachBrush(napi_env env, napi_callback_info info)
730 {
731     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
732     if (me == nullptr) {
733         return nullptr;
734     }
735     Canvas* canvas = me->GetCanvas();
736     if (canvas == nullptr) {
737         ROSEN_LOGE("JsCanvas::DetachBrush canvas is null");
738         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
739     }
740     canvas->DetachBrush();
741     return NapiGetUndefined(env);
742 }
743 
GetCanvas()744 Canvas* JsCanvas::GetCanvas()
745 {
746     return m_canvas;
747 }
748 
ResetCanvas()749 void JsCanvas::ResetCanvas()
750 {
751     g_drawingCanvas = nullptr;
752     m_canvas = nullptr;
753 }
754 } // namespace Drawing
755 } // namespace OHOS::Rosen
756