• 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 "js_canvas.h"
17 
18 #include <mutex>
19 
20 #include "src/utils/SkUTF.h"
21 
22 #ifdef ROSEN_OHOS
23 #include "pixel_map_napi.h"
24 #endif
25 #include "native_value.h"
26 #include "draw/canvas.h"
27 #include "draw/path.h"
28 #include "image/image.h"
29 #include "render/rs_pixel_map_shader.h"
30 #include "text/text.h"
31 #include "text/text_blob.h"
32 #include "utils/point.h"
33 #include "utils/rect.h"
34 #include "utils/sampling_options.h"
35 #include "utils/vertices.h"
36 
37 #include "brush_napi/js_brush.h"
38 #include "font_napi/js_font.h"
39 #include "matrix_napi/js_matrix.h"
40 #include "pen_napi/js_pen.h"
41 #include "path_napi/js_path.h"
42 #include "region_napi/js_region.h"
43 #include "sampling_options_napi/js_sampling_options.h"
44 #include "text_blob_napi/js_text_blob.h"
45 #include "roundRect_napi/js_roundrect.h"
46 #include "js_drawing_utils.h"
47 #include "utils/performanceCaculate.h"
48 #ifdef OHOS_PLATFORM
49 #include "pipeline/rs_recording_canvas.h"
50 #endif
51 
52 namespace OHOS::Rosen {
53 #ifdef ROSEN_OHOS
54 using namespace Media;
55 namespace {
ColorSpaceToDrawingColorSpace(ColorSpace colorSpace)56 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorSpace colorSpace)
57 {
58     switch (colorSpace) {
59         case ColorSpace::DISPLAY_P3:
60             return Drawing::ColorSpace::CreateRGB(
61                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
62         case ColorSpace::LINEAR_SRGB:
63             return Drawing::ColorSpace::CreateSRGBLinear();
64         case ColorSpace::SRGB:
65             return Drawing::ColorSpace::CreateSRGB();
66         default:
67             return Drawing::ColorSpace::CreateSRGB();
68     }
69 }
70 
PixelFormatToDrawingColorType(PixelFormat pixelFormat)71 static Drawing::ColorType PixelFormatToDrawingColorType(PixelFormat pixelFormat)
72 {
73     switch (pixelFormat) {
74         case PixelFormat::RGB_565:
75             return Drawing::ColorType::COLORTYPE_RGB_565;
76         case PixelFormat::RGBA_8888:
77             return Drawing::ColorType::COLORTYPE_RGBA_8888;
78         case PixelFormat::BGRA_8888:
79             return Drawing::ColorType::COLORTYPE_BGRA_8888;
80         case PixelFormat::ALPHA_8:
81             return Drawing::ColorType::COLORTYPE_ALPHA_8;
82         case PixelFormat::RGBA_F16:
83             return Drawing::ColorType::COLORTYPE_RGBA_F16;
84         case PixelFormat::UNKNOWN:
85         case PixelFormat::ARGB_8888:
86         case PixelFormat::RGB_888:
87         case PixelFormat::NV21:
88         case PixelFormat::NV12:
89         case PixelFormat::CMYK:
90         default:
91             return Drawing::ColorType::COLORTYPE_UNKNOWN;
92     }
93 }
94 
AlphaTypeToDrawingAlphaType(AlphaType alphaType)95 static Drawing::AlphaType AlphaTypeToDrawingAlphaType(AlphaType alphaType)
96 {
97     switch (alphaType) {
98         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
99             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
100         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
101             return Drawing::AlphaType::ALPHATYPE_OPAQUE;
102         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
103             return Drawing::AlphaType::ALPHATYPE_PREMUL;
104         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
105             return Drawing::AlphaType::ALPHATYPE_UNPREMUL;
106         default:
107             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
108     }
109 }
110 
111 struct PixelMapReleaseContext {
PixelMapReleaseContextOHOS::Rosen::__anon6f3281770111::PixelMapReleaseContext112     explicit PixelMapReleaseContext(std::shared_ptr<PixelMap> pixelMap) : pixelMap_(pixelMap) {}
113 
~PixelMapReleaseContextOHOS::Rosen::__anon6f3281770111::PixelMapReleaseContext114     ~PixelMapReleaseContext()
115     {
116         pixelMap_ = nullptr;
117     }
118 
119 private:
120     std::shared_ptr<PixelMap> pixelMap_;
121 };
122 
PixelMapReleaseProc(const void *,void * context)123 static void PixelMapReleaseProc(const void* /* pixels */, void* context)
124 {
125     PixelMapReleaseContext* ctx = static_cast<PixelMapReleaseContext*>(context);
126     if (ctx) {
127         delete ctx;
128         ctx = nullptr;
129     }
130 }
131 
ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)132 std::shared_ptr<Drawing::Image> ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)
133 {
134     if (!pixelMap) {
135         ROSEN_LOGE("Drawing_napi::pixelMap fail");
136         return nullptr;
137     }
138     ImageInfo imageInfo;
139     pixelMap->GetImageInfo(imageInfo);
140     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
141         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
142         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
143         ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
144     Drawing::Pixmap imagePixmap(drawingImageInfo,
145         reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowStride());
146     PixelMapReleaseContext* releaseContext = new PixelMapReleaseContext(pixelMap);
147     auto image = Drawing::Image::MakeFromRaster(imagePixmap, PixelMapReleaseProc, releaseContext);
148     if (!image) {
149         ROSEN_LOGE("Drawing_napi :RSPixelMapUtil::ExtractDrawingImage fail");
150         delete releaseContext;
151         releaseContext = nullptr;
152     }
153     return image;
154 }
155 
ExtracetDrawingBitmap(std::shared_ptr<Media::PixelMap> pixelMap,Drawing::Bitmap & bitmap)156 bool ExtracetDrawingBitmap(std::shared_ptr<Media::PixelMap> pixelMap, Drawing::Bitmap& bitmap)
157 {
158     if (!pixelMap) {
159         ROSEN_LOGE("Drawing_napi ::pixelMap fail");
160         return false;
161     }
162     ImageInfo imageInfo;
163     pixelMap->GetImageInfo(imageInfo);
164     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
165         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
166         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
167         ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
168     bitmap.Build(drawingImageInfo, pixelMap->GetRowStride());
169     bitmap.SetPixels(const_cast<void*>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
170     return true;
171 }
172 
DrawingPixelMapMesh(std::shared_ptr<Media::PixelMap> pixelMap,int column,int row,float * vertices,uint32_t * colors,Drawing::Canvas * m_canvas)173 void DrawingPixelMapMesh(std::shared_ptr<Media::PixelMap> pixelMap, int column, int row,
174     float* vertices, uint32_t* colors, Drawing::Canvas* m_canvas)
175 {
176     const int vertCounts = (column + 1) * (row + 1);
177     int32_t size = 6; // triangle * 2
178     const int indexCount = column * row * size;
179     uint32_t flags = Drawing::BuilderFlags::HAS_TEXCOORDS_BUILDER_FLAG;
180     if (colors) {
181         flags |= Drawing::BuilderFlags::HAS_COLORS_BUILDER_FLAG;
182     }
183     Drawing::Vertices::Builder builder(Drawing::VertexMode::TRIANGLES_VERTEXMODE, vertCounts, indexCount, flags);
184     if (memcpy_s(builder.Positions(), vertCounts * sizeof(Drawing::Point),
185         vertices, vertCounts * sizeof(Drawing::Point)) != 0) {
186         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh memcpy points failed");
187         return;
188     }
189     int32_t colorSize = 4; // size of color
190     if (colors && (memcpy_s(builder.Colors(), vertCounts * colorSize, colors, vertCounts * colorSize) != 0)) {
191         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh memcpy colors failed");
192         return;
193     }
194     Drawing::Point* texsPoint = builder.TexCoords();
195     uint16_t* indices = builder.Indices();
196 
197     const float height = static_cast<float>(pixelMap->GetHeight());
198     const float width = static_cast<float>(pixelMap->GetWidth());
199 
200     if (column == 0 || row == 0) {
201         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh column or row is invalid");
202         return;
203     }
204     const float dy = height / row;
205     const float dx = width / column;
206 
207     Drawing::Point* texsPit = texsPoint;
208     float y = 0;
209     for (int i = 0; i <= row; i++) {
210         if (i == row) {
211             y = height;
212         }
213         float x = 0;
214         for (int j = 0; j < column; j++) {
215             texsPit->Set(x, y);
216             texsPit += 1;
217             x += dx;
218         }
219         texsPit->Set(width, y);
220         texsPit += 1;
221         y += dy;
222     }
223 
224     uint16_t* dexIndices = indices;
225     int indexIndices = 0;
226     for (int i = 0; i < row; i++) {
227         for (int j = 0; j < column; j++) {
228             *dexIndices++ = indexIndices;
229             *dexIndices++ = indexIndices + column + 1;
230             *dexIndices++ = indexIndices + column + 2; // 2 means the third index of the triangle
231 
232             *dexIndices++ = indexIndices;
233             *dexIndices++ = indexIndices + column + 2; // 2 means the third index of the triangle
234             *dexIndices++ = indexIndices + 1;
235 
236             indexIndices += 1;
237         }
238         indexIndices += 1;
239     }
240 
241     if (!m_canvas->GetMutableBrush().IsValid()) {
242         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh paint is invalid");
243         return;
244     }
245     if (m_canvas->GetDrawingType() != Drawing::DrawingType::RECORDING) {
246         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixelMap);
247         if (image == nullptr) {
248             ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh image is nullptr");
249             return;
250         }
251         auto shader = Drawing::ShaderEffect::CreateImageShader(*image,
252             Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, Drawing::SamplingOptions(), Drawing::Matrix());
253         m_canvas->GetMutableBrush().SetShaderEffect(shader);
254     } else {
255         auto shader = Drawing::ShaderEffect::CreateExtendShader(std::make_shared<RSPixelMapShader>(pixelMap,
256             Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, Drawing::SamplingOptions(), Drawing::Matrix()));
257         m_canvas->GetMutableBrush().SetShaderEffect(shader);
258     }
259     JS_CALL_DRAWING_FUNC(
260         m_canvas->DrawVertices(*builder.Detach(), Drawing::BlendMode::MODULATE));
261 }
262 }
263 #endif
264 
265 namespace Drawing {
266 thread_local napi_ref JsCanvas::constructor_ = nullptr;
267 static std::mutex g_constructorInitMutex;
268 const std::string CLASS_NAME = "Canvas";
269 
270 static const napi_property_descriptor g_properties[] = {
271     DECLARE_NAPI_FUNCTION("clear", JsCanvas::Clear),
272     DECLARE_NAPI_FUNCTION("drawArc", JsCanvas::DrawArc),
273     DECLARE_NAPI_FUNCTION("drawRect", JsCanvas::DrawRect),
274     DECLARE_NAPI_FUNCTION("drawCircle", JsCanvas::DrawCircle),
275     DECLARE_NAPI_FUNCTION("drawImage", JsCanvas::DrawImage),
276     DECLARE_NAPI_FUNCTION("drawImageRect", JsCanvas::DrawImageRect),
277     DECLARE_NAPI_FUNCTION("drawImageRectWithSrc", JsCanvas::DrawImageRectWithSrc),
278     DECLARE_NAPI_FUNCTION("drawColor", JsCanvas::DrawColor),
279     DECLARE_NAPI_FUNCTION("drawOval", JsCanvas::DrawOval),
280     DECLARE_NAPI_FUNCTION("drawPoint", JsCanvas::DrawPoint),
281     DECLARE_NAPI_FUNCTION("drawPoints", JsCanvas::DrawPoints),
282     DECLARE_NAPI_FUNCTION("drawPath", JsCanvas::DrawPath),
283     DECLARE_NAPI_FUNCTION("drawLine", JsCanvas::DrawLine),
284     DECLARE_NAPI_FUNCTION("drawTextBlob", JsCanvas::DrawText),
285     DECLARE_NAPI_FUNCTION("drawSingleCharacter", JsCanvas::DrawSingleCharacter),
286     DECLARE_NAPI_FUNCTION("getTotalMatrix", JsCanvas::GetTotalMatrix),
287     DECLARE_NAPI_FUNCTION("getLocalClipBounds", JsCanvas::GetLocalClipBounds),
288     DECLARE_NAPI_FUNCTION("drawPixelMapMesh", JsCanvas::DrawPixelMapMesh),
289     DECLARE_NAPI_FUNCTION("drawRegion", JsCanvas::DrawRegion),
290     DECLARE_NAPI_FUNCTION("drawShadow", JsCanvas::DrawShadow),
291     DECLARE_NAPI_FUNCTION("drawBackground", JsCanvas::DrawBackground),
292     DECLARE_NAPI_FUNCTION("drawRoundRect", JsCanvas::DrawRoundRect),
293     DECLARE_NAPI_FUNCTION("drawNestedRoundRect", JsCanvas::DrawNestedRoundRect),
294     DECLARE_NAPI_FUNCTION("attachPen", JsCanvas::AttachPen),
295     DECLARE_NAPI_FUNCTION("attachBrush", JsCanvas::AttachBrush),
296     DECLARE_NAPI_FUNCTION("detachPen", JsCanvas::DetachPen),
297     DECLARE_NAPI_FUNCTION("detachBrush", JsCanvas::DetachBrush),
298     DECLARE_NAPI_FUNCTION("skew", JsCanvas::Skew),
299     DECLARE_NAPI_FUNCTION("rotate", JsCanvas::Rotate),
300     DECLARE_NAPI_FUNCTION("getSaveCount", JsCanvas::GetSaveCount),
301     DECLARE_NAPI_FUNCTION("getWidth", JsCanvas::GetWidth),
302     DECLARE_NAPI_FUNCTION("getHeight", JsCanvas::GetHeight),
303     DECLARE_NAPI_FUNCTION("save", JsCanvas::Save),
304     DECLARE_NAPI_FUNCTION("saveLayer", JsCanvas::SaveLayer),
305     DECLARE_NAPI_FUNCTION("restore", JsCanvas::Restore),
306     DECLARE_NAPI_FUNCTION("restoreToCount", JsCanvas::RestoreToCount),
307     DECLARE_NAPI_FUNCTION("scale", JsCanvas::Scale),
308     DECLARE_NAPI_FUNCTION("clipPath", JsCanvas::ClipPath),
309     DECLARE_NAPI_FUNCTION("clipRegion", JsCanvas::ClipRegion),
310     DECLARE_NAPI_FUNCTION("clipRect", JsCanvas::ClipRect),
311     DECLARE_NAPI_FUNCTION("concatMatrix", JsCanvas::ConcatMatrix),
312     DECLARE_NAPI_FUNCTION("clipRoundRect", JsCanvas::ClipRoundRect),
313     DECLARE_NAPI_FUNCTION("setMatrix", JsCanvas::SetMatrix),
314     DECLARE_NAPI_FUNCTION("resetMatrix", JsCanvas::ResetMatrix),
315     DECLARE_NAPI_FUNCTION("translate", JsCanvas::Translate),
316     DECLARE_NAPI_FUNCTION("isClipEmpty", JsCanvas::IsClipEmpty),
317 };
318 
Constructor(napi_env env,napi_callback_info info)319 napi_value JsCanvas::Constructor(napi_env env, napi_callback_info info)
320 {
321     DRAWING_PERFORMANCE_START_CACULATE;
322     napi_value jsThis = nullptr;
323     size_t argc = ARGC_ONE;
324     napi_value argv[ARGC_ONE] = {nullptr};
325     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
326     if (status != napi_ok) {
327         ROSEN_LOGE("Drawing_napi: failed to napi_get_cb_info");
328         return nullptr;
329     }
330 
331 #ifdef ROSEN_OHOS
332     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
333 
334     PixelMapNapi* pixelMapNapi = nullptr;
335     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi);
336 
337     if (pixelMapNapi->GetPixelNapiInner() == nullptr) {
338         return nullptr;
339     }
340 
341     Bitmap bitmap;
342     if (!ExtracetDrawingBitmap(pixelMapNapi->GetPixelNapiInner(), bitmap)) {
343         return nullptr;
344     }
345 
346     Canvas* canvas = new Canvas();
347     canvas->Bind(bitmap);
348     JsCanvas *jsCanvas = new JsCanvas(canvas, true);
349     jsCanvas->mPixelMap_ = pixelMapNapi->GetPixelNapiInner();
350     status = napi_wrap(env, jsThis, jsCanvas, JsCanvas::Destructor, nullptr, nullptr);
351     if (status != napi_ok) {
352         delete jsCanvas;
353         ROSEN_LOGE("Drawing_napi: Failed to wrap native instance");
354         return nullptr;
355     }
356 #else
357     return nullptr;
358 #endif
359     return jsThis;
360 }
361 
CreateConstructor(napi_env env)362 bool JsCanvas::CreateConstructor(napi_env env)
363 {
364     napi_value constructor = nullptr;
365     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
366         sizeof(g_properties) / sizeof(g_properties[0]), g_properties, &constructor);
367     if (status != napi_ok) {
368         ROSEN_LOGE("Drawing_napi: CreateConstructor Failed, define class fail");
369         return false;
370     }
371 
372     status = napi_create_reference(env, constructor, 1, &constructor_);
373     if (status != napi_ok) {
374         ROSEN_LOGE("Drawing_napi: CreateConstructor Failed, create reference fail");
375         return false;
376     }
377     return true;
378 }
379 
CreateJsCanvas(napi_env env,Canvas * canvas)380 napi_value JsCanvas::CreateJsCanvas(napi_env env, Canvas* canvas)
381 {
382     napi_value constructor = nullptr;
383     napi_value result = nullptr;
384 
385     {
386         std::lock_guard<std::mutex> lock(g_constructorInitMutex);
387         if (!constructor_) {
388             if (!CreateConstructor(env)) {
389                 ROSEN_LOGE("Drawing_napi: CreateConstructor Failed");
390                 return nullptr;
391             }
392         }
393     }
394 
395     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
396     if (status != napi_ok) {
397         ROSEN_LOGE("Drawing_napi: CreateJsCanvas napi_get_reference_value failed");
398         return nullptr;
399     }
400 
401     if (canvas == nullptr) {
402         ROSEN_LOGE("Drawing_napi: canvas is nullptr");
403         return nullptr;
404     }
405     JsCanvas *jsCanvas = new JsCanvas(canvas);
406     napi_create_object(env, &result);
407     if (result == nullptr) {
408         delete jsCanvas;
409         ROSEN_LOGE("jsCanvas::CreateJsCanvas Create canvas object failed!");
410         return nullptr;
411     }
412     status = napi_wrap(env, result, jsCanvas, JsCanvas::Destructor, nullptr, nullptr);
413     if (status != napi_ok) {
414         delete jsCanvas;
415         ROSEN_LOGE("Drawing_napi: Failed to wrap native instance");
416         return nullptr;
417     }
418     napi_define_properties(env, result, sizeof(g_properties) / sizeof(g_properties[0]), g_properties);
419     return result;
420 }
421 
Destructor(napi_env env,void * nativeObject,void * finalize)422 void JsCanvas::Destructor(napi_env env, void *nativeObject, void *finalize)
423 {
424     DRAWING_PERFORMANCE_STOP_CACULATE;
425     (void)finalize;
426     if (nativeObject != nullptr) {
427         JsCanvas *napi = reinterpret_cast<JsCanvas *>(nativeObject);
428         delete napi;
429     }
430 }
431 
Init(napi_env env,napi_value exportObj)432 napi_value JsCanvas::Init(napi_env env, napi_value exportObj)
433 {
434     {
435         std::lock_guard<std::mutex> lock(g_constructorInitMutex);
436         if (!constructor_) {
437             if (!CreateConstructor(env)) {
438                 ROSEN_LOGE("Drawing_napi: CreateConstructor Failed");
439                 return nullptr;
440             }
441         }
442     }
443 
444     napi_value constructor = nullptr;
445     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
446     if (status != napi_ok) {
447         ROSEN_LOGE("Drawing_napi: napi_get_reference_value failed");
448         return nullptr;
449     }
450 
451     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
452     if (status != napi_ok) {
453         ROSEN_LOGE("Drawing_napi: Failed to set constructor");
454         return nullptr;
455     }
456     return exportObj;
457 }
458 
~JsCanvas()459 JsCanvas::~JsCanvas()
460 {
461     if (owned_) {
462         delete m_canvas;
463     }
464     m_canvas = nullptr;
465 }
466 
Clear(napi_env env,napi_callback_info info)467 napi_value JsCanvas::Clear(napi_env env, napi_callback_info info)
468 {
469     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
470     return (me != nullptr) ? me->OnClear(env, info) : nullptr;
471 }
472 
OnClear(napi_env env,napi_callback_info info)473 napi_value JsCanvas::OnClear(napi_env env, napi_callback_info info)
474 {
475     if (m_canvas == nullptr) {
476         ROSEN_LOGE("JsCanvas::OnClear canvas is null");
477         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
478     }
479 
480     napi_value argv[ARGC_ONE] = {nullptr};
481     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
482 
483     int32_t argb[ARGC_FOUR] = {0};
484     if (!ConvertFromJsColor(env, argv[ARGC_ZERO], argb, ARGC_FOUR)) {
485         ROSEN_LOGE("JsCanvas::OnClear Argv[0] is invalid");
486         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
487             "Parameter verification failed. The range of color channels must be [0, 255].");
488     }
489     auto color = Color::ColorQuadSetARGB(argb[ARGC_ZERO], argb[ARGC_ONE], argb[ARGC_TWO], argb[ARGC_THREE]);
490 
491     JS_CALL_DRAWING_FUNC(m_canvas->Clear(color));
492 #ifdef ROSEN_OHOS
493     if (mPixelMap_ != nullptr) {
494         mPixelMap_->MarkDirty();
495     }
496 #endif
497     return nullptr;
498 }
499 
DrawShadow(napi_env env,napi_callback_info info)500 napi_value JsCanvas::DrawShadow(napi_env env, napi_callback_info info)
501 {
502     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
503     return (me != nullptr) ? me->OnDrawShadow(env, info) : nullptr;
504 }
505 
OnDrawShadow(napi_env env,napi_callback_info info)506 napi_value JsCanvas::OnDrawShadow(napi_env env, napi_callback_info info)
507 {
508     if (m_canvas == nullptr) {
509         ROSEN_LOGE("JsCanvas::OnDrawShadow canvas is null.");
510         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
511     }
512     napi_value argv[ARGC_SEVEN] = { nullptr };
513     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_SEVEN);
514     JsPath* jsPath = nullptr;
515     GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
516 
517     Point3 offset;
518     Point3 lightPos;
519     if (!ConvertFromJsPoint3d(env, argv[ARGC_ONE], offset) || !ConvertFromJsPoint3d(env, argv[ARGC_TWO], lightPos)) {
520         ROSEN_LOGE("JsCanvas::OnDrawShadow argv[ARGC_ONE] or argv[ARGC_TWO] is invalid.");
521         return nullptr;
522     }
523 
524     double lightRadius = 0.0f;
525     GET_DOUBLE_PARAM(ARGC_THREE, lightRadius);
526     int32_t ambientColor[ARGC_FOUR] = {0};
527     int32_t spotColor[ARGC_FOUR] = {0};
528     if (!ConvertFromJsColor(env, argv[ARGC_FOUR], ambientColor, ARGC_FOUR) ||
529         !ConvertFromJsColor(env, argv[ARGC_FIVE], spotColor, ARGC_FOUR)) {
530         ROSEN_LOGE("JsCanvas::OnDrawShadow argv[ARGC_FOUR] or argv[ARGC_FIVE] is invalid.");
531         return nullptr;
532     }
533 
534     int32_t shadowFlag = 0;
535     GET_ENUM_PARAM(ARGC_SIX, shadowFlag, 0, static_cast<int32_t>(ShadowFlags::ALL));
536     OHOS::Rosen::Drawing::ShadowFlags shadowFlags = static_cast<OHOS::Rosen::Drawing::ShadowFlags>(shadowFlag);
537     if (!ConvertFromJsShadowFlag(env, argv[ARGC_SIX], shadowFlags)) {
538         ROSEN_LOGE("JsCanvas::OnDrawShadow argv[ARGC_SIX] is invalid.");
539         return nullptr;
540     }
541     if (jsPath->GetPath() == nullptr) {
542         ROSEN_LOGE("JsCanvas::OnDrawShadow GetPath is nullptr.");
543         return nullptr;
544     }
545 
546     auto ambientColorPara = Color::ColorQuadSetARGB(ambientColor[ARGC_ZERO], ambientColor[ARGC_ONE],
547         ambientColor[ARGC_TWO], ambientColor[ARGC_THREE]);
548     auto spotColorPara = Color::ColorQuadSetARGB(spotColor[ARGC_ZERO], spotColor[ARGC_ONE],
549         spotColor[ARGC_TWO], spotColor[ARGC_THREE]);
550     m_canvas->DrawShadow(*jsPath->GetPath(), offset, lightPos, lightRadius, ambientColorPara, spotColorPara,
551         static_cast<ShadowFlags>(shadowFlag));
552 #ifdef ROSEN_OHOS
553     if (mPixelMap_ != nullptr) {
554         mPixelMap_->MarkDirty();
555     }
556 #endif
557     return nullptr;
558 }
559 
DrawArc(napi_env env,napi_callback_info info)560 napi_value JsCanvas::DrawArc(napi_env env, napi_callback_info info)
561 {
562     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
563     return (me != nullptr) ? me->OnDrawArc(env, info) : nullptr;
564 }
565 
OnDrawArc(napi_env env,napi_callback_info info)566 napi_value JsCanvas::OnDrawArc(napi_env env, napi_callback_info info)
567 {
568     if (m_canvas == nullptr) {
569         ROSEN_LOGE("JsCanvas::OnDrawArc canvas is null");
570         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
571     }
572 
573     napi_value argv[ARGC_THREE] = {nullptr};
574     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
575 
576     double ltrb[ARGC_FOUR] = {0};
577     if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
578         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
579             "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
580     }
581     Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
582 
583     double startAngle = 0.0;
584     GET_DOUBLE_PARAM(ARGC_ONE, startAngle);
585     double sweepAngle = 0.0;
586     GET_DOUBLE_PARAM(ARGC_TWO, sweepAngle);
587 
588     JS_CALL_DRAWING_FUNC(m_canvas->DrawArc(drawingRect, startAngle, sweepAngle));
589 #ifdef ROSEN_OHOS
590     if (mPixelMap_ != nullptr) {
591         mPixelMap_->MarkDirty();
592     }
593 #endif
594     return nullptr;
595 }
596 
DrawRect(napi_env env,napi_callback_info info)597 napi_value JsCanvas::DrawRect(napi_env env, napi_callback_info info)
598 {
599     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
600     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
601     return (me != nullptr) ? me->OnDrawRect(env, info) : nullptr;
602 }
603 
OnDrawRect(napi_env env,napi_callback_info info)604 napi_value JsCanvas::OnDrawRect(napi_env env, napi_callback_info info)
605 {
606     if (m_canvas == nullptr) {
607         ROSEN_LOGE("JsCanvas::OnDrawRect canvas is nullptr");
608         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
609     }
610 
611     size_t argc = ARGC_FOUR;
612     napi_value argv[ARGC_FOUR] = {nullptr};
613     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_FOUR);
614     Drawing::Rect drawingRect;
615     if (argc == ARGC_ONE) {
616         double ltrb[ARGC_FOUR] = {0};
617         if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
618             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
619                 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
620         }
621 
622         drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
623     } else if (argc == ARGC_FOUR) {
624         double left = 0.0;
625         GET_DOUBLE_PARAM(ARGC_ZERO, left);
626         double top = 0.0;
627         GET_DOUBLE_PARAM(ARGC_ONE, top);
628         double right = 0.0;
629         GET_DOUBLE_PARAM(ARGC_TWO, right);
630         double bottom = 0.0;
631         GET_DOUBLE_PARAM(ARGC_THREE, bottom);
632         drawingRect = Drawing::Rect(left, top, right, bottom);
633     } else {
634         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
635     }
636 
637     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
638     m_canvas->DrawRect(drawingRect);
639 #ifdef ROSEN_OHOS
640     if (mPixelMap_ != nullptr) {
641         mPixelMap_->MarkDirty();
642     }
643 #endif
644     return nullptr;
645 }
646 
DrawCircle(napi_env env,napi_callback_info info)647 napi_value JsCanvas::DrawCircle(napi_env env, napi_callback_info info)
648 {
649     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
650     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
651     return (me != nullptr) ? me->OnDrawCircle(env, info) : nullptr;
652 }
653 
OnDrawCircle(napi_env env,napi_callback_info info)654 napi_value JsCanvas::OnDrawCircle(napi_env env, napi_callback_info info)
655 {
656     if (m_canvas == nullptr) {
657         ROSEN_LOGE("JsCanvas::OnDrawCircle canvas is null");
658         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
659     }
660 
661     napi_value argv[ARGC_THREE] = {nullptr};
662     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
663 
664     double x = 0.0;
665     GET_DOUBLE_PARAM(ARGC_ZERO, x);
666     double y = 0.0;
667     GET_DOUBLE_PARAM(ARGC_ONE, y);
668     double radius = 0.0;
669     GET_DOUBLE_PARAM(ARGC_TWO, radius);
670 
671     Drawing::Point centerPt = Drawing::Point(x, y);
672     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
673     m_canvas->DrawCircle(centerPt, radius);
674 #ifdef ROSEN_OHOS
675     if (mPixelMap_ != nullptr) {
676         mPixelMap_->MarkDirty();
677     }
678 #endif
679     return nullptr;
680 }
681 
DrawImage(napi_env env,napi_callback_info info)682 napi_value JsCanvas::DrawImage(napi_env env, napi_callback_info info)
683 {
684     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
685     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
686     return (me != nullptr) ? me->OnDrawImage(env, info) : nullptr;
687 }
688 
OnDrawImage(napi_env env,napi_callback_info info)689 napi_value JsCanvas::OnDrawImage(napi_env env, napi_callback_info info)
690 {
691 #ifdef ROSEN_OHOS
692     if (m_canvas == nullptr) {
693         ROSEN_LOGE("JsCanvas::OnDrawImage canvas is nullptr");
694         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
695     }
696     size_t argc = ARGC_FOUR;
697     napi_value argv[ARGC_FOUR] = {nullptr};
698     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_THREE, ARGC_FOUR);
699 
700     double px = 0.0;
701     GET_DOUBLE_PARAM(ARGC_ONE, px);
702     double py = 0.0;
703     GET_DOUBLE_PARAM(ARGC_TWO, py);
704     PixelMapNapi* pixelMapNapi = nullptr;
705     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi);
706 
707     auto pixel = pixelMapNapi->GetPixelNapiInner();
708     if (pixel == nullptr) {
709         ROSEN_LOGE("JsCanvas::OnDrawImage pixelmap GetPixelNapiInner is nullptr");
710         return nullptr;
711     }
712 
713     std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
714     if (image == nullptr) {
715         ROSEN_LOGE("JsCanvas::OnDrawImage image is nullptr");
716         return nullptr;
717     }
718 
719     if (argc == ARGC_THREE) {
720         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
721         if (m_canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
722             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(m_canvas);
723             Drawing::Rect src(0, 0, pixel->GetWidth(), pixel->GetHeight());
724             Drawing::Rect dst(px, py, px + pixel->GetWidth(), py + pixel->GetHeight());
725             canvas_->DrawPixelMapRect(pixel, src, dst, Drawing::SamplingOptions());
726             return nullptr;
727         }
728         m_canvas->DrawImage(*image, px, py, Drawing::SamplingOptions());
729     } else {
730         JsSamplingOptions* jsSamplingOptions = nullptr;
731         GET_UNWRAP_PARAM(ARGC_THREE, jsSamplingOptions);
732 
733         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
734         if (samplingOptions == nullptr) {
735             ROSEN_LOGE("JsCanvas::OnDrawImage get samplingOptions is nullptr");
736             return nullptr;
737         }
738         if (m_canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
739             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(m_canvas);
740             Drawing::Rect src(0, 0, pixel->GetWidth(), pixel->GetHeight());
741             Drawing::Rect dst(px, py, px + pixel->GetWidth(), py + pixel->GetHeight());
742             canvas_->DrawPixelMapRect(pixel, src, dst, *samplingOptions.get());
743             return nullptr;
744         }
745         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
746         m_canvas->DrawImage(*image, px, py, *samplingOptions.get());
747     }
748 
749     if (mPixelMap_ != nullptr) {
750         mPixelMap_->MarkDirty();
751     }
752 #endif
753     return nullptr;
754 }
755 
DrawColor(napi_env env,napi_callback_info info)756 napi_value JsCanvas::DrawColor(napi_env env, napi_callback_info info)
757 {
758     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
759     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
760     return (me != nullptr) ? me->OnDrawColor(env, info) : nullptr;
761 }
762 
OnDrawColor(napi_env env,napi_callback_info info)763 napi_value JsCanvas::OnDrawColor(napi_env env, napi_callback_info info)
764 {
765     if (m_canvas == nullptr) {
766         ROSEN_LOGE("JsCanvas::OnDrawColor canvas is nullptr");
767         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
768     }
769 
770     size_t argc = ARGC_FIVE;
771     napi_value argv[ARGC_FIVE] = {nullptr};
772     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_FIVE);
773 
774     if (argc == ARGC_ONE || argc == ARGC_TWO) {
775         int32_t argb[ARGC_FOUR] = {0};
776         if (!ConvertFromJsColor(env, argv[ARGC_ZERO], argb, ARGC_FOUR)) {
777             ROSEN_LOGE("JsCanvas::OnDrawColor Argv[0] is invalid");
778             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
779                 "Parameter verification failed. The range of color channels must be [0, 255].");
780         }
781         auto color = Color::ColorQuadSetARGB(argb[ARGC_ZERO], argb[ARGC_ONE], argb[ARGC_TWO], argb[ARGC_THREE]);
782         if (argc == ARGC_ONE) {
783             DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
784             m_canvas->DrawColor(color);
785         } else {
786             int32_t jsMode = 0;
787             GET_ENUM_PARAM(ARGC_ONE, jsMode, 0, static_cast<int32_t>(BlendMode::LUMINOSITY));
788             DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
789             m_canvas->DrawColor(color, static_cast<BlendMode>(jsMode));
790         }
791     } else if (argc == ARGC_FOUR || argc == ARGC_FIVE) {
792         int32_t alpha = 0;
793         GET_COLOR_PARAM(ARGC_ZERO, alpha);
794         int32_t red = 0;
795         GET_COLOR_PARAM(ARGC_ONE, red);
796         int32_t green = 0;
797         GET_COLOR_PARAM(ARGC_TWO, green);
798         int32_t blue = 0;
799         GET_COLOR_PARAM(ARGC_THREE, blue);
800         auto color = Color::ColorQuadSetARGB(alpha, red, green, blue);
801         if (argc == ARGC_FOUR) {
802             DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
803             m_canvas->DrawColor(color);
804         } else {
805             int32_t jsMode = 0;
806             GET_ENUM_PARAM(ARGC_FOUR, jsMode, 0, static_cast<int32_t>(BlendMode::LUMINOSITY));
807             DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
808             m_canvas->DrawColor(color, static_cast<BlendMode>(jsMode));
809         }
810     } else {
811         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
812     }
813 
814 #ifdef ROSEN_OHOS
815     if (mPixelMap_ != nullptr) {
816         mPixelMap_->MarkDirty();
817     }
818 #endif
819     return nullptr;
820 }
821 
DrawOval(napi_env env,napi_callback_info info)822 napi_value JsCanvas::DrawOval(napi_env env, napi_callback_info info)
823 {
824     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
825     return (me != nullptr) ? me->OnDrawOval(env, info) : nullptr;
826 }
827 
OnDrawOval(napi_env env,napi_callback_info info)828 napi_value JsCanvas::OnDrawOval(napi_env env, napi_callback_info info)
829 {
830     if (m_canvas == nullptr) {
831         ROSEN_LOGE("JsCanvas::OnDrawOval canvas is null");
832         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
833     }
834     napi_value argv[ARGC_ONE] = {nullptr};
835     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
836 
837     double ltrb[ARGC_FOUR] = {0};
838     if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
839         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
840             "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
841     }
842     Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
843 
844     JS_CALL_DRAWING_FUNC(m_canvas->DrawOval(drawingRect));
845 #ifdef ROSEN_OHOS
846     if (mPixelMap_ != nullptr) {
847         mPixelMap_->MarkDirty();
848     }
849 #endif
850     return nullptr;
851 }
852 
DrawPoint(napi_env env,napi_callback_info info)853 napi_value JsCanvas::DrawPoint(napi_env env, napi_callback_info info)
854 {
855     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
856     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
857     return (me != nullptr) ? me->OnDrawPoint(env, info) : nullptr;
858 }
859 
OnDrawPoint(napi_env env,napi_callback_info info)860 napi_value JsCanvas::OnDrawPoint(napi_env env, napi_callback_info info)
861 {
862     if (m_canvas == nullptr) {
863         ROSEN_LOGE("JsCanvas::OnDrawPoint canvas is nullptr");
864         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
865     }
866 
867     napi_value argv[ARGC_TWO] = {nullptr};
868     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
869 
870     double px = 0.0;
871     GET_DOUBLE_PARAM(ARGC_ZERO, px);
872     double py = 0.0;
873     GET_DOUBLE_PARAM(ARGC_ONE, py);
874 
875     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
876     m_canvas->DrawPoint(Point(px, py));
877 #ifdef ROSEN_OHOS
878     if (mPixelMap_ != nullptr) {
879         mPixelMap_->MarkDirty();
880     }
881 #endif
882     return nullptr;
883 }
884 
OnMakePoints(napi_env & env,Point * point,uint32_t size,napi_value & array)885 static bool OnMakePoints(napi_env& env, Point* point, uint32_t size, napi_value& array)
886 {
887     for (uint32_t i = 0; i < size; i++) {
888         napi_value tempNumber = nullptr;
889         napi_get_element(env, array, i, &tempNumber);
890         napi_value tempValue = nullptr;
891         double pointX = 0.0;
892         double pointY = 0.0;
893         napi_get_named_property(env, tempNumber, "x", &tempValue);
894         bool isPointXOk = ConvertFromJsValue(env, tempValue, pointX);
895         napi_get_named_property(env, tempNumber, "y", &tempValue);
896         bool isPointYOk = ConvertFromJsValue(env, tempValue, pointY);
897         if (!(isPointXOk && isPointYOk)) {
898             return false;
899         }
900         point[i] = Point(pointX, pointY);
901     }
902     return true;
903 }
904 
DrawPoints(napi_env env,napi_callback_info info)905 napi_value JsCanvas::DrawPoints(napi_env env, napi_callback_info info)
906 {
907     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
908     return (me != nullptr) ? me->OnDrawPoints(env, info) : nullptr;
909 }
910 
OnDrawPoints(napi_env env,napi_callback_info info)911 napi_value JsCanvas::OnDrawPoints(napi_env env, napi_callback_info info)
912 {
913     if (m_canvas == nullptr) {
914         ROSEN_LOGE("JsCanvas::OnDrawPoints canvas is nullptr");
915         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
916     }
917     size_t argc = ARGC_TWO;
918     napi_value argv[ARGC_TWO] = {nullptr};
919     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
920     napi_value array = argv[ARGC_ZERO];
921     uint32_t size = 0;
922     if (napi_get_array_length(env, array, &size) != napi_ok || (size == 0)) {
923         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect src array size.");
924     }
925     if (argc == ARGC_ONE) {
926         Point* points = new(std::nothrow) Point[size];
927         if (points == nullptr) {
928             return nullptr;
929         }
930         if (!OnMakePoints(env, points, size, array)) {
931             delete [] points;
932             ROSEN_LOGE("JsCanvas::OnDrawPoints Argv[ARGC_ZERO] is invalid");
933             return nullptr;
934         }
935         JS_CALL_DRAWING_FUNC(m_canvas->DrawPoints(PointMode::POINTS_POINTMODE, size, points));
936 #ifdef ROSEN_OHOS
937         if (mPixelMap_ != nullptr) {
938             mPixelMap_->MarkDirty();
939         }
940 #endif
941         delete [] points;
942         return nullptr;
943     }
944 
945     int32_t pointMode = 0;
946     GET_ENUM_PARAM(ARGC_ONE, pointMode, 0, static_cast<int32_t>(PointMode::POLYGON_POINTMODE));
947     Point* points = new(std::nothrow) Point[size];
948     if (points == nullptr) {
949         return nullptr;
950     }
951     if (!OnMakePoints(env, points, size, array)) {
952         delete [] points;
953         ROSEN_LOGE("JsCanvas::OnDrawPoints Argv[ARGC_ZERO] is invalid");
954         return nullptr;
955     }
956     JS_CALL_DRAWING_FUNC(m_canvas->DrawPoints(static_cast<PointMode>(pointMode), size, points));
957 #ifdef ROSEN_OHOS
958     if (mPixelMap_ != nullptr) {
959         mPixelMap_->MarkDirty();
960     }
961 #endif
962     delete [] points;
963     return nullptr;
964 }
965 
DrawPath(napi_env env,napi_callback_info info)966 napi_value JsCanvas::DrawPath(napi_env env, napi_callback_info info)
967 {
968     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
969     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
970     return (me != nullptr) ? me->OnDrawPath(env, info) : nullptr;
971 }
972 
OnDrawPath(napi_env env,napi_callback_info info)973 napi_value JsCanvas::OnDrawPath(napi_env env, napi_callback_info info)
974 {
975     if (m_canvas == nullptr) {
976         ROSEN_LOGE("JsCanvas::OnDrawPath canvas is nullptr");
977         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
978     }
979 
980     napi_value argv[ARGC_ONE] = {nullptr};
981     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
982 
983     JsPath* jsPath = nullptr;
984     GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
985 
986     if (jsPath->GetPath() == nullptr) {
987         ROSEN_LOGE("JsCanvas::OnDrawPath path is nullptr");
988         return nullptr;
989     }
990 
991     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
992     m_canvas->DrawPath(*jsPath->GetPath());
993 #ifdef ROSEN_OHOS
994     if (mPixelMap_ != nullptr) {
995         mPixelMap_->MarkDirty();
996     }
997 #endif
998     return nullptr;
999 }
1000 
DrawLine(napi_env env,napi_callback_info info)1001 napi_value JsCanvas::DrawLine(napi_env env, napi_callback_info info)
1002 {
1003     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1004     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1005     return (me != nullptr) ? me->OnDrawLine(env, info) : nullptr;
1006 }
1007 
OnDrawLine(napi_env env,napi_callback_info info)1008 napi_value JsCanvas::OnDrawLine(napi_env env, napi_callback_info info)
1009 {
1010     if (m_canvas == nullptr) {
1011         ROSEN_LOGE("JsCanvas::OnDrawLine canvas is nullptr");
1012         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1013     }
1014 
1015     napi_value argv[ARGC_FOUR] = {nullptr};
1016     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
1017 
1018     double startPx = 0.0;
1019     GET_DOUBLE_PARAM(ARGC_ZERO, startPx);
1020     double startPy = 0.0;
1021     GET_DOUBLE_PARAM(ARGC_ONE, startPy);
1022     double endPx = 0.0;
1023     GET_DOUBLE_PARAM(ARGC_TWO, endPx);
1024     double endPy = 0.0;
1025     GET_DOUBLE_PARAM(ARGC_THREE, endPy);
1026 
1027     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1028     m_canvas->DrawLine(Point(startPx, startPy), Point(endPx, endPy));
1029 #ifdef ROSEN_OHOS
1030     if (mPixelMap_ != nullptr) {
1031         mPixelMap_->MarkDirty();
1032     }
1033 #endif
1034     return nullptr;
1035 }
1036 
DrawText(napi_env env,napi_callback_info info)1037 napi_value JsCanvas::DrawText(napi_env env, napi_callback_info info)
1038 {
1039     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1040     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1041     return (me != nullptr) ? me->OnDrawText(env, info) : nullptr;
1042 }
1043 
OnDrawText(napi_env env,napi_callback_info info)1044 napi_value JsCanvas::OnDrawText(napi_env env, napi_callback_info info)
1045 {
1046     if (m_canvas == nullptr) {
1047         ROSEN_LOGE("JsCanvas::OnDrawText canvas is null");
1048         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1049     }
1050 
1051     napi_value argv[ARGC_THREE] = {nullptr};
1052     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
1053 
1054     JsTextBlob* jsTextBlob = nullptr;
1055     GET_UNWRAP_PARAM(ARGC_ZERO, jsTextBlob);
1056     double x = 0.0;
1057     GET_DOUBLE_PARAM(ARGC_ONE, x);
1058     double y = 0.0;
1059     GET_DOUBLE_PARAM(ARGC_TWO, y);
1060 
1061     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1062     m_canvas->DrawTextBlob(jsTextBlob->GetTextBlob().get(), x, y);
1063 #ifdef ROSEN_OHOS
1064     if (mPixelMap_ != nullptr) {
1065         mPixelMap_->MarkDirty();
1066     }
1067 #endif
1068     return nullptr;
1069 }
1070 
DrawSingleCharacter(napi_env env,napi_callback_info info)1071 napi_value JsCanvas::DrawSingleCharacter(napi_env env, napi_callback_info info)
1072 {
1073     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1074     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1075     return (me != nullptr) ? me->OnDrawSingleCharacter(env, info) : nullptr;
1076 }
1077 
OnDrawSingleCharacter(napi_env env,napi_callback_info info)1078 napi_value JsCanvas::OnDrawSingleCharacter(napi_env env, napi_callback_info info)
1079 {
1080     if (m_canvas == nullptr) {
1081         ROSEN_LOGE("JsCanvas::OnDrawSingleCharacter canvas is null");
1082         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1083     }
1084 
1085     napi_value argv[ARGC_FOUR] = {nullptr};
1086     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
1087 
1088     size_t len = 0;
1089     if (napi_get_value_string_utf8(env, argv[ARGC_ZERO], nullptr, 0, &len) != napi_ok) {
1090         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
1091     }
1092     if (len == 0 || len > 4) { // 4 is the maximum length of a character encoded in UTF8.
1093         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1094             "Parameter verification failed. Input parameter0 should be single character.");
1095     }
1096     char str[len + 1];
1097     if (napi_get_value_string_utf8(env, argv[ARGC_ZERO], str, len + 1, &len) != napi_ok) {
1098         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
1099     }
1100 
1101     JsFont* jsFont = nullptr;
1102     GET_UNWRAP_PARAM(ARGC_ONE, jsFont);
1103     double x = 0.0;
1104     GET_DOUBLE_PARAM(ARGC_TWO, x);
1105     double y = 0.0;
1106     GET_DOUBLE_PARAM(ARGC_THREE, y);
1107 
1108     std::shared_ptr<Font> font = jsFont->GetFont();
1109     if (font == nullptr) {
1110         ROSEN_LOGE("JsCanvas::OnDrawSingleCharacter font is nullptr");
1111         return nullptr;
1112     }
1113     std::shared_ptr<Font> themeFont = GetThemeFont(font);
1114     if (themeFont != nullptr) {
1115         font = themeFont;
1116     }
1117 
1118     const char* currentStr = str;
1119     int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
1120     size_t byteLen = currentStr - str;
1121     if (byteLen != len) {
1122         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1123             "Parameter verification failed. Input parameter0 should be single character.");
1124     }
1125     m_canvas->DrawSingleCharacter(unicode, *font, x, y);
1126 #ifdef ROSEN_OHOS
1127     if (mPixelMap_ != nullptr) {
1128         mPixelMap_->MarkDirty();
1129     }
1130 #endif
1131     return nullptr;
1132 }
1133 
DrawPixelMapMesh(napi_env env,napi_callback_info info)1134 napi_value JsCanvas::DrawPixelMapMesh(napi_env env, napi_callback_info info)
1135 {
1136     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1137     return (me != nullptr) ? me->OnDrawPixelMapMesh(env, info) : nullptr;
1138 }
1139 
OnDrawPixelMapMesh(napi_env env,napi_callback_info info)1140 napi_value JsCanvas::OnDrawPixelMapMesh(napi_env env, napi_callback_info info)
1141 {
1142 #ifdef ROSEN_OHOS
1143     if (m_canvas == nullptr) {
1144         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh canvas is null");
1145         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1146     }
1147 
1148     napi_value argv[ARGC_SEVEN] = {nullptr};
1149     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_SEVEN);
1150 
1151     PixelMapNapi* pixelMapNapi = nullptr;
1152     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi);
1153 
1154     if (pixelMapNapi->GetPixelNapiInner() == nullptr) {
1155         ROSEN_LOGE("Drawing_napi::pixelMap pixelmap getPixelNapiInner is nullptr");
1156         return nullptr;
1157     }
1158     std::shared_ptr<Media::PixelMap> pixelMap = pixelMapNapi->GetPixelNapiInner();
1159 
1160     int32_t column = 0;
1161     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, column);
1162     int32_t row = 0;
1163     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_TWO, row);
1164     int32_t vertOffset = 0;
1165     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_FOUR, vertOffset);
1166     int32_t colorOffset = 0;
1167     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_SIX, colorOffset);
1168 
1169     if (column == 0 || row == 0) {
1170         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh column or row is invalid");
1171         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid column or row params.");
1172     }
1173 
1174     napi_value verticesArray = argv[ARGC_THREE];
1175     uint32_t verticesSize = 0;
1176     napi_get_array_length(env, verticesArray, &verticesSize);
1177     int64_t tempVerticesSize = ((column + 1) * (row + 1) + vertOffset) * 2; // x and y two coordinates
1178     if (verticesSize != tempVerticesSize) {
1179         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh vertices are invalid");
1180         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter3 type.");
1181     }
1182 
1183     auto vertices = new (std::nothrow) float[verticesSize];
1184     if (!vertices) {
1185         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh create array with size of vertices failed");
1186         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Size of vertices exceed memory limit.");
1187     }
1188 
1189     for (uint32_t i = 0; i < verticesSize; i++) {
1190         napi_value tempVertex = nullptr;
1191         napi_get_element(env, verticesArray, i, &tempVertex);
1192         double vertex = 0.f;
1193         if (napi_get_value_double(env, tempVertex, &vertex) != napi_ok) {
1194             ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh vertex is invalid");
1195             delete []vertices;
1196             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1197                 "Incorrect DrawPixelMapMesh parameter vertex type.");
1198         }
1199         vertices[i] = vertex;
1200     }
1201     float* verticesMesh = verticesSize ? (vertices + vertOffset * 2) : nullptr; // offset two coordinates
1202 
1203     napi_value colorsArray = argv[ARGC_FIVE];
1204     uint32_t colorsSize = 0;
1205     napi_get_array_length(env, colorsArray, &colorsSize);
1206     int64_t tempColorsSize = (column + 1) * (row + 1) + colorOffset;
1207 
1208     if (colorsSize != 0 && colorsSize != tempColorsSize) {
1209         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh colors are invalid");
1210         delete []vertices;
1211         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter5 type.");
1212     }
1213 
1214     if (colorsSize == 0) {
1215         DrawingPixelMapMesh(pixelMap, column, row, verticesMesh, nullptr, m_canvas);
1216         if (mPixelMap_ != nullptr) {
1217             mPixelMap_->MarkDirty();
1218         }
1219         delete []vertices;
1220         return nullptr;
1221     }
1222 
1223     auto colors = new (std::nothrow) uint32_t[colorsSize];
1224     if (!colors) {
1225         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh create array with size of colors failed");
1226         delete []vertices;
1227         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Size of colors exceed memory limit.");
1228     }
1229     for (uint32_t i = 0; i < colorsSize; i++) {
1230         napi_value tempColor = nullptr;
1231         napi_get_element(env, colorsArray, i, &tempColor);
1232         uint32_t color = 0;
1233         if (napi_get_value_uint32(env, tempColor, &color) != napi_ok) {
1234             ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh color is invalid");
1235             delete []vertices;
1236             delete []colors;
1237             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1238                 "Incorrect DrawPixelMapMesh parameter color type.");
1239         }
1240         colors[i] = color;
1241     }
1242     uint32_t* colorsMesh = colors + colorOffset;
1243 
1244     DrawingPixelMapMesh(pixelMap, column, row, verticesMesh, colorsMesh, m_canvas);
1245     if (mPixelMap_ != nullptr) {
1246         mPixelMap_->MarkDirty();
1247     }
1248     delete []vertices;
1249     delete []colors;
1250     return nullptr;
1251 #else
1252     return nullptr;
1253 #endif
1254 }
1255 
DrawRegion(napi_env env,napi_callback_info info)1256 napi_value JsCanvas::DrawRegion(napi_env env, napi_callback_info info)
1257 {
1258     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1259     return (me != nullptr) ? me->OnDrawRegion(env, info) : nullptr;
1260 }
1261 
OnDrawRegion(napi_env env,napi_callback_info info)1262 napi_value JsCanvas::OnDrawRegion(napi_env env, napi_callback_info info)
1263 {
1264     if (m_canvas == nullptr) {
1265         ROSEN_LOGE("JsCanvas::OnDrawRegion canvas is nullptr");
1266         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1267     }
1268     napi_value argv[ARGC_ONE] = {nullptr};
1269     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1270 
1271     JsRegion* jsRegion = nullptr;
1272     GET_UNWRAP_PARAM(ARGC_ZERO, jsRegion);
1273     if (jsRegion->GetRegion() == nullptr) {
1274         ROSEN_LOGE("JsCanvas::OnDrawRegion region is nullptr");
1275         return nullptr;
1276     }
1277     JS_CALL_DRAWING_FUNC(m_canvas->DrawRegion(*jsRegion->GetRegion()));
1278 #ifdef ROSEN_OHOS
1279     if (mPixelMap_ != nullptr) {
1280         mPixelMap_->MarkDirty();
1281     }
1282 #endif
1283     return nullptr;
1284 }
1285 
DrawBackground(napi_env env,napi_callback_info info)1286 napi_value JsCanvas::DrawBackground(napi_env env, napi_callback_info info)
1287 {
1288     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1289     return (me != nullptr) ? me->OnDrawBackground(env, info) : nullptr;
1290 }
1291 
OnDrawBackground(napi_env env,napi_callback_info info)1292 napi_value JsCanvas::OnDrawBackground(napi_env env, napi_callback_info info)
1293 {
1294     if (m_canvas == nullptr) {
1295         ROSEN_LOGE("JsCanvas::OnDrawBackground canvas is nullptr");
1296         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1297     }
1298 
1299     napi_value argv[ARGC_ONE] = {nullptr};
1300     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1301 
1302     JsBrush* jsBrush = nullptr;
1303     GET_UNWRAP_PARAM(ARGC_ZERO, jsBrush);
1304     if (jsBrush->GetBrush() == nullptr) {
1305         ROSEN_LOGE("JsCanvas::OnDrawBackground brush is nullptr");
1306         return nullptr;
1307     }
1308 
1309     m_canvas->DrawBackground(*jsBrush->GetBrush());
1310 #ifdef ROSEN_OHOS
1311     if (mPixelMap_ != nullptr) {
1312         mPixelMap_->MarkDirty();
1313     }
1314 #endif
1315     return nullptr;
1316 }
1317 
DrawRoundRect(napi_env env,napi_callback_info info)1318 napi_value JsCanvas::DrawRoundRect(napi_env env, napi_callback_info info)
1319 {
1320     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1321     return (me != nullptr) ? me->OnDrawRoundRect(env, info) : nullptr;
1322 }
1323 
OnDrawRoundRect(napi_env env,napi_callback_info info)1324 napi_value JsCanvas::OnDrawRoundRect(napi_env env, napi_callback_info info)
1325 {
1326     if (m_canvas == nullptr) {
1327         ROSEN_LOGE("JsCanvas::OnDrawRoundRect canvas is nullptr");
1328         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1329     }
1330 
1331     napi_value argv[ARGC_ONE] = {nullptr};
1332     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1333 
1334     JsRoundRect* jsRoundRect = nullptr;
1335     GET_UNWRAP_PARAM(ARGC_ZERO, jsRoundRect);
1336 
1337     m_canvas->DrawRoundRect(jsRoundRect->GetRoundRect());
1338 #ifdef ROSEN_OHOS
1339     if (mPixelMap_ != nullptr) {
1340         mPixelMap_->MarkDirty();
1341     }
1342 #endif
1343     return nullptr;
1344 }
1345 
DrawNestedRoundRect(napi_env env,napi_callback_info info)1346 napi_value JsCanvas::DrawNestedRoundRect(napi_env env, napi_callback_info info)
1347 {
1348     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1349     return (me != nullptr) ? me->OnDrawNestedRoundRect(env, info) : nullptr;
1350 }
1351 
OnDrawNestedRoundRect(napi_env env,napi_callback_info info)1352 napi_value JsCanvas::OnDrawNestedRoundRect(napi_env env, napi_callback_info info)
1353 {
1354     if (m_canvas == nullptr) {
1355         ROSEN_LOGE("JsCanvas::OnDrawNestedRoundRect canvas is nullptr");
1356         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1357     }
1358 
1359     napi_value argv[ARGC_TWO] = {nullptr};
1360     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1361 
1362     JsRoundRect* jsOuter = nullptr;
1363     GET_UNWRAP_PARAM(ARGC_ZERO, jsOuter);
1364 
1365     JsRoundRect* jsInner = nullptr;
1366     GET_UNWRAP_PARAM(ARGC_ONE, jsInner);
1367 
1368     m_canvas->DrawNestedRoundRect(jsOuter->GetRoundRect(), jsInner->GetRoundRect());
1369 #ifdef ROSEN_OHOS
1370     if (mPixelMap_ != nullptr) {
1371         mPixelMap_->MarkDirty();
1372     }
1373 #endif
1374     return nullptr;
1375 }
1376 
GetTotalMatrix(napi_env env,napi_callback_info info)1377 napi_value JsCanvas::GetTotalMatrix(napi_env env, napi_callback_info info)
1378 {
1379     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1380     return (me != nullptr) ? me->OnGetTotalMatrix(env, info) : nullptr;
1381 }
1382 
OnGetTotalMatrix(napi_env env,napi_callback_info info)1383 napi_value JsCanvas::OnGetTotalMatrix(napi_env env, napi_callback_info info)
1384 {
1385     if (m_canvas == nullptr) {
1386         ROSEN_LOGE("JsCanvas::GetTotalMatrix canvas is null");
1387         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1388     }
1389 
1390     Matrix matrix = m_canvas->GetTotalMatrix();
1391     std::shared_ptr<Matrix> matrixPtr = std::make_shared<Matrix>(matrix);
1392 
1393     return JsMatrix::CreateJsMatrix(env, matrixPtr);
1394 }
1395 
AttachPen(napi_env env,napi_callback_info info)1396 napi_value JsCanvas::AttachPen(napi_env env, napi_callback_info info)
1397 {
1398     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1399     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1400     if (me == nullptr) {
1401         return nullptr;
1402     }
1403     Canvas* canvas = me->GetCanvas();
1404     if (canvas == nullptr) {
1405         ROSEN_LOGE("JsCanvas::AttachPen canvas is nullptr");
1406         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1407     }
1408 
1409     napi_value argv[ARGC_ONE] = {nullptr};
1410     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1411 
1412     JsPen* jsPen = nullptr;
1413     GET_UNWRAP_PARAM(ARGC_ZERO, jsPen);
1414 
1415     if (jsPen->GetPen() == nullptr) {
1416         ROSEN_LOGE("JsCanvas::AttachPen pen is nullptr");
1417         return nullptr;
1418     }
1419     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1420     canvas->AttachPen(*jsPen->GetPen());
1421     return nullptr;
1422 }
1423 
AttachBrush(napi_env env,napi_callback_info info)1424 napi_value JsCanvas::AttachBrush(napi_env env, napi_callback_info info)
1425 {
1426     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1427     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1428     if (me == nullptr) {
1429         return nullptr;
1430     }
1431     Canvas* canvas = me->GetCanvas();
1432     if (canvas == nullptr) {
1433         ROSEN_LOGE("JsCanvas::AttachBrush canvas is nullptr");
1434         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1435     }
1436 
1437     napi_value argv[ARGC_ONE] = {nullptr};
1438     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1439 
1440     JsBrush* jsBrush = nullptr;
1441     GET_UNWRAP_PARAM(ARGC_ZERO, jsBrush);
1442 
1443     if (jsBrush->GetBrush() == nullptr) {
1444         ROSEN_LOGE("JsCanvas::AttachBrush brush is nullptr");
1445         return nullptr;
1446     }
1447     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1448     canvas->AttachBrush(*jsBrush->GetBrush());
1449     return nullptr;
1450 }
1451 
DetachPen(napi_env env,napi_callback_info info)1452 napi_value JsCanvas::DetachPen(napi_env env, napi_callback_info info)
1453 {
1454     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1455     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1456     if (me == nullptr) {
1457         return nullptr;
1458     }
1459     Canvas* canvas = me->GetCanvas();
1460     if (canvas == nullptr) {
1461         ROSEN_LOGE("JsCanvas::DetachPen canvas is null");
1462         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1463     }
1464     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1465     canvas->DetachPen();
1466     return nullptr;
1467 }
1468 
DetachBrush(napi_env env,napi_callback_info info)1469 napi_value JsCanvas::DetachBrush(napi_env env, napi_callback_info info)
1470 {
1471     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1472     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1473     if (me == nullptr) {
1474         return nullptr;
1475     }
1476     Canvas* canvas = me->GetCanvas();
1477     if (canvas == nullptr) {
1478         ROSEN_LOGE("JsCanvas::DetachBrush canvas is null");
1479         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1480     }
1481     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1482     canvas->DetachBrush();
1483     return nullptr;
1484 }
1485 
Skew(napi_env env,napi_callback_info info)1486 napi_value JsCanvas::Skew(napi_env env, napi_callback_info info)
1487 {
1488     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1489     return (me != nullptr) ? me->OnSkew(env, info) : nullptr;
1490 }
1491 
OnSkew(napi_env env,napi_callback_info info)1492 napi_value JsCanvas::OnSkew(napi_env env, napi_callback_info info)
1493 {
1494     if (m_canvas == nullptr) {
1495         ROSEN_LOGE("JsCanvas::OnSkew m_canvas is null");
1496         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1497     }
1498 
1499     napi_value argv[ARGC_TWO] = {nullptr};
1500     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1501 
1502     double sx = 0.0;
1503     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
1504     double sy = 0.0;
1505     GET_DOUBLE_PARAM(ARGC_ONE, sy);
1506 
1507     m_canvas->Shear(sx, sy);
1508     return nullptr;
1509 }
1510 
Rotate(napi_env env,napi_callback_info info)1511 napi_value JsCanvas::Rotate(napi_env env, napi_callback_info info)
1512 {
1513     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1514     return (me != nullptr) ? me->OnRotate(env, info) : nullptr;
1515 }
1516 
OnRotate(napi_env env,napi_callback_info info)1517 napi_value JsCanvas::OnRotate(napi_env env, napi_callback_info info)
1518 {
1519     if (m_canvas == nullptr) {
1520         ROSEN_LOGE("JsCanvas::OnRotate m_canvas is null");
1521         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1522     }
1523 
1524     napi_value argv[ARGC_THREE] = {nullptr};
1525     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
1526 
1527     double degree = 0.0;
1528     GET_DOUBLE_PARAM(ARGC_ZERO, degree);
1529     double sx = 0.0;
1530     GET_DOUBLE_PARAM(ARGC_ONE, sx);
1531     double sy = 0.0;
1532     GET_DOUBLE_PARAM(ARGC_TWO, sy);
1533 
1534     m_canvas->Rotate(degree, sx, sy);
1535     return nullptr;
1536 }
1537 
GetSaveCount(napi_env env,napi_callback_info info)1538 napi_value JsCanvas::GetSaveCount(napi_env env, napi_callback_info info)
1539 {
1540     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1541     return (me != nullptr) ? me->OnGetSaveCount(env, info) : nullptr;
1542 }
1543 
OnGetSaveCount(napi_env env,napi_callback_info info)1544 napi_value JsCanvas::OnGetSaveCount(napi_env env, napi_callback_info info)
1545 {
1546     if (m_canvas == nullptr) {
1547         ROSEN_LOGE("JsCanvas::OnGetSaveCount canvas is null");
1548         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1549     }
1550     return CreateJsNumber(env, m_canvas->GetSaveCount());
1551 }
1552 
GetWidth(napi_env env,napi_callback_info info)1553 napi_value JsCanvas::GetWidth(napi_env env, napi_callback_info info)
1554 {
1555     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1556     return (me != nullptr) ? me->OnGetWidth(env, info) : nullptr;
1557 }
1558 
OnGetWidth(napi_env env,napi_callback_info info)1559 napi_value JsCanvas::OnGetWidth(napi_env env, napi_callback_info info)
1560 {
1561     if (m_canvas == nullptr) {
1562         ROSEN_LOGE("JsCanvas::OnGetWidth canvas is null");
1563         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1564     }
1565     return CreateJsNumber(env, m_canvas->GetWidth());
1566 }
1567 
GetHeight(napi_env env,napi_callback_info info)1568 napi_value JsCanvas::GetHeight(napi_env env, napi_callback_info info)
1569 {
1570     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1571     return (me != nullptr) ? me->OnGetHeight(env, info) : nullptr;
1572 }
1573 
OnGetHeight(napi_env env,napi_callback_info info)1574 napi_value JsCanvas::OnGetHeight(napi_env env, napi_callback_info info)
1575 {
1576     if (m_canvas == nullptr) {
1577         ROSEN_LOGE("JsCanvas::OnGetHeight canvas is null");
1578         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1579     }
1580     return CreateJsNumber(env, m_canvas->GetHeight());
1581 }
1582 
ClipPath(napi_env env,napi_callback_info info)1583 napi_value JsCanvas::ClipPath(napi_env env, napi_callback_info info)
1584 {
1585     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1586     return (me != nullptr) ? me->OnClipPath(env, info) : nullptr;
1587 }
1588 
OnClipPath(napi_env env,napi_callback_info info)1589 napi_value JsCanvas::OnClipPath(napi_env env, napi_callback_info info)
1590 {
1591     if (m_canvas == nullptr) {
1592         ROSEN_LOGE("JsCanvas::OnClipPath m_canvas is nullptr");
1593         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1594     }
1595     size_t argc = ARGC_THREE;
1596     napi_value argv[ARGC_THREE] = {nullptr};
1597     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_THREE);
1598 
1599     JsPath* jsPath = nullptr;
1600     GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
1601 
1602     Path* path = jsPath->GetPath();
1603     if (path == nullptr) {
1604         ROSEN_LOGE("JsCanvas::OnClipPath path is nullptr");
1605         return nullptr;
1606     }
1607     if (argc == ARGC_ONE) {
1608         m_canvas->ClipPath(*path);
1609         return nullptr;
1610     }
1611 
1612     int32_t jsClipOp = 0;
1613     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, jsClipOp);
1614 
1615     if (argc == ARGC_TWO) {
1616         m_canvas->ClipPath(*path, static_cast<ClipOp>(jsClipOp));
1617         return nullptr;
1618     }
1619 
1620     bool jsDoAntiAlias = false;
1621     GET_BOOLEAN_PARAM(ARGC_TWO, jsDoAntiAlias);
1622 
1623     m_canvas->ClipPath(*path, static_cast<ClipOp>(jsClipOp), jsDoAntiAlias);
1624     return nullptr;
1625 }
1626 
ClipRegion(napi_env env,napi_callback_info info)1627 napi_value JsCanvas::ClipRegion(napi_env env, napi_callback_info info)
1628 {
1629     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1630     return (me != nullptr) ? me->OnClipRegion(env, info) : nullptr;
1631 }
1632 
OnClipRegion(napi_env env,napi_callback_info info)1633 napi_value JsCanvas::OnClipRegion(napi_env env, napi_callback_info info)
1634 {
1635     if (m_canvas == nullptr) {
1636         ROSEN_LOGE("JsCanvas::OnClipRegion m_canvas is nullptr");
1637         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1638     }
1639     size_t argc = ARGC_TWO;
1640     napi_value argv[ARGC_TWO] = {nullptr};
1641     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
1642 
1643     JsRegion* jsRegion = nullptr;
1644     GET_UNWRAP_PARAM(ARGC_ZERO, jsRegion);
1645 
1646     Region* region = jsRegion->GetRegion();
1647     if (region == nullptr) {
1648         ROSEN_LOGE("JsCanvas::OnClipRegion region is nullptr");
1649         return nullptr;
1650     }
1651     if (argc == ARGC_ONE) {
1652         m_canvas->ClipRegion(*region);
1653         return nullptr;
1654     }
1655 
1656     int32_t jsClipOp = 0;
1657     GET_ENUM_PARAM(ARGC_ONE, jsClipOp, 0, static_cast<int32_t>(ClipOp::INTERSECT));
1658 
1659     m_canvas->ClipRegion(*region, static_cast<ClipOp>(jsClipOp));
1660     return nullptr;
1661 }
1662 
Translate(napi_env env,napi_callback_info info)1663 napi_value JsCanvas::Translate(napi_env env, napi_callback_info info)
1664 {
1665     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1666     return (me != nullptr) ? me->OnTranslate(env, info) : nullptr;
1667 }
1668 
OnTranslate(napi_env env,napi_callback_info info)1669 napi_value JsCanvas::OnTranslate(napi_env env, napi_callback_info info)
1670 {
1671     if (m_canvas == nullptr) {
1672         ROSEN_LOGE("JsCanvas::OnTranslate m_canvas is null");
1673         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1674     }
1675 
1676     napi_value argv[ARGC_TWO] = {nullptr};
1677     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1678 
1679     double dx = 0.0;
1680     GET_DOUBLE_PARAM(ARGC_ZERO, dx);
1681     double dy = 0.0;
1682     GET_DOUBLE_PARAM(ARGC_ONE, dy);
1683 
1684     m_canvas->Translate(dx, dy);
1685     return nullptr;
1686 }
1687 
Save(napi_env env,napi_callback_info info)1688 napi_value JsCanvas::Save(napi_env env, napi_callback_info info)
1689 {
1690     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1691     return (me != nullptr) ? me->OnSave(env, info) : nullptr;
1692 }
1693 
OnSave(napi_env env,napi_callback_info info)1694 napi_value JsCanvas::OnSave(napi_env env, napi_callback_info info)
1695 {
1696     if (m_canvas == nullptr) {
1697         ROSEN_LOGE("JsCanvas::OnSave canvas is null");
1698         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1699     }
1700     return CreateJsNumber(env, m_canvas->Save());
1701 }
1702 
SaveLayer(napi_env env,napi_callback_info info)1703 napi_value JsCanvas::SaveLayer(napi_env env, napi_callback_info info)
1704 {
1705     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1706     return (me != nullptr) ? me->OnSaveLayer(env, info) : nullptr;
1707 }
1708 
OnSaveLayer(napi_env env,napi_callback_info info)1709 napi_value JsCanvas::OnSaveLayer(napi_env env, napi_callback_info info)
1710 {
1711     if (m_canvas == nullptr) {
1712         ROSEN_LOGE("JsCanvas::OnSaveLayer canvas is null");
1713         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1714     }
1715     size_t argc = ARGC_TWO;
1716     napi_value argv[ARGC_TWO] = {nullptr};
1717     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ZERO, ARGC_TWO);
1718 
1719     uint32_t ret = 0;
1720     if (argc == ARGC_ZERO) {
1721         ret = m_canvas->GetSaveCount();
1722         m_canvas->SaveLayer(SaveLayerOps());
1723         return CreateJsNumber(env, ret);
1724     }
1725 
1726     napi_valuetype valueType = napi_undefined;
1727     if (napi_typeof(env, argv[ARGC_ZERO], &valueType) != napi_ok ||
1728         (valueType != napi_null && valueType != napi_object)) {
1729         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnSaveLayer parameter0 type.");
1730     }
1731     Drawing::Rect* drawingRectPtr = nullptr;
1732     double ltrb[ARGC_FOUR] = {0};
1733     if (valueType == napi_object) {
1734         if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1735             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1736                 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1737         }
1738         drawingRectPtr = new Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1739     }
1740 
1741     if (argc == ARGC_ONE) {
1742         ret = m_canvas->GetSaveCount();
1743         m_canvas->SaveLayer(SaveLayerOps(drawingRectPtr, nullptr));
1744         if (drawingRectPtr != nullptr) {
1745             delete drawingRectPtr;
1746         }
1747         return CreateJsNumber(env, ret);
1748     }
1749 
1750     if (napi_typeof(env, argv[ARGC_ONE], &valueType) != napi_ok ||
1751         (valueType != napi_null && valueType != napi_object)) {
1752         if (drawingRectPtr != nullptr) {
1753             delete drawingRectPtr;
1754         }
1755         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnSaveLayer parameter1 type.");
1756     }
1757     Drawing::Brush* drawingBrushPtr = nullptr;
1758     if (valueType == napi_object) {
1759         JsBrush* jsBrush = nullptr;
1760         napi_status status = napi_unwrap(env, argv[ARGC_ONE], reinterpret_cast<void**>(&jsBrush));
1761         if (status != napi_ok || jsBrush == nullptr) {
1762             if (drawingRectPtr != nullptr) {
1763                 delete drawingRectPtr;
1764             }
1765             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1766                 std::string("Incorrect ") + __FUNCTION__ + " parameter" + std::to_string(ARGC_ONE) + " type.");
1767         }
1768         drawingBrushPtr = jsBrush->GetBrush();
1769     }
1770     ret = m_canvas->GetSaveCount();
1771     SaveLayerOps saveLayerOps = SaveLayerOps(drawingRectPtr, drawingBrushPtr);
1772     m_canvas->SaveLayer(saveLayerOps);
1773     if (drawingRectPtr != nullptr) {
1774         delete drawingRectPtr;
1775     }
1776     return CreateJsNumber(env, ret);
1777 }
1778 
RestoreToCount(napi_env env,napi_callback_info info)1779 napi_value JsCanvas::RestoreToCount(napi_env env, napi_callback_info info)
1780 {
1781     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1782     return (me != nullptr) ? me->OnRestoreToCount(env, info) : nullptr;
1783 }
1784 
OnRestoreToCount(napi_env env,napi_callback_info info)1785 napi_value JsCanvas::OnRestoreToCount(napi_env env, napi_callback_info info)
1786 {
1787     if (m_canvas == nullptr) {
1788         ROSEN_LOGE("JsCanvas::OnRestoreToCount canvas is nullptr");
1789         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1790     }
1791 
1792     napi_value argv[ARGC_ONE] = {nullptr};
1793     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1794 
1795     int32_t count = 0;
1796     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ZERO, count);
1797 
1798     m_canvas->RestoreToCount(count);
1799     return nullptr;
1800 }
1801 
Restore(napi_env env,napi_callback_info info)1802 napi_value JsCanvas::Restore(napi_env env, napi_callback_info info)
1803 {
1804     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1805     return (me != nullptr) ? me->OnRestore(env, info) : nullptr;
1806 }
1807 
OnRestore(napi_env env,napi_callback_info info)1808 napi_value JsCanvas::OnRestore(napi_env env, napi_callback_info info)
1809 {
1810     if (m_canvas == nullptr) {
1811         ROSEN_LOGE("JsCanvas::OnRestore m_canvas is null");
1812         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1813     }
1814     m_canvas->Restore();
1815     return nullptr;
1816 }
1817 
ClipRect(napi_env env,napi_callback_info info)1818 napi_value JsCanvas::ClipRect(napi_env env, napi_callback_info info)
1819 {
1820     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1821     return (me != nullptr) ? me->OnClipRect(env, info) : nullptr;
1822 }
1823 
OnClipRect(napi_env env,napi_callback_info info)1824 napi_value JsCanvas::OnClipRect(napi_env env, napi_callback_info info)
1825 {
1826     if (m_canvas == nullptr) {
1827         ROSEN_LOGE("JsCanvas::OnClipRect m_canvas is nullptr");
1828         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1829     }
1830     size_t argc = ARGC_THREE;
1831     napi_value argv[ARGC_THREE] = {nullptr};
1832     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_THREE);
1833 
1834     double ltrb[ARGC_FOUR] = {0};
1835     if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1836         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1837             "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1838     }
1839     Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1840 
1841     if (argc == ARGC_ONE) {
1842         m_canvas->ClipRect(drawingRect);
1843         return nullptr;
1844     }
1845 
1846     int32_t clipOpInt = 0;
1847     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, clipOpInt);
1848 
1849     if (argc == ARGC_TWO) {
1850         m_canvas->ClipRect(drawingRect, static_cast<ClipOp>(clipOpInt));
1851         return nullptr;
1852     }
1853 
1854     bool doAntiAlias = false;
1855     GET_BOOLEAN_PARAM(ARGC_TWO, doAntiAlias);
1856 
1857     m_canvas->ClipRect(drawingRect, static_cast<ClipOp>(clipOpInt), doAntiAlias);
1858     return nullptr;
1859 }
1860 
ClipRoundRect(napi_env env,napi_callback_info info)1861 napi_value JsCanvas::ClipRoundRect(napi_env env, napi_callback_info info)
1862 {
1863     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1864     return (me != nullptr) ? me->OnClipRoundRect(env, info) : nullptr;
1865 }
1866 
OnClipRoundRect(napi_env env,napi_callback_info info)1867 napi_value JsCanvas::OnClipRoundRect(napi_env env, napi_callback_info info)
1868 {
1869     if (m_canvas == nullptr) {
1870         ROSEN_LOGE("JsCanvas::OnClipRoundRect m_canvas is nullptr");
1871         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1872     }
1873 
1874     size_t argc = ARGC_THREE;
1875     napi_value argv[ARGC_THREE] = {nullptr};
1876     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_THREE);
1877 
1878     JsRoundRect* jsRoundRect = nullptr;
1879     GET_UNWRAP_PARAM(ARGC_ZERO, jsRoundRect);
1880     if (jsRoundRect == nullptr) {
1881         ROSEN_LOGE("JsCanvas::OnDrawRegion jsRoundRect is nullptr");
1882         return nullptr;
1883     }
1884 
1885     if (argc == ARGC_ONE) {
1886         m_canvas->ClipRoundRect(jsRoundRect->GetRoundRect());
1887         return nullptr;
1888     }
1889 
1890     int32_t clipOpInt = 0;
1891     GET_ENUM_PARAM(ARGC_ONE, clipOpInt, 0, static_cast<int32_t>(ClipOp::INTERSECT));
1892 
1893     if (argc == ARGC_TWO) {
1894         m_canvas->ClipRoundRect(jsRoundRect->GetRoundRect(), static_cast<ClipOp>(clipOpInt));
1895         return nullptr;
1896     }
1897 
1898     bool doAntiAlias = false;
1899     GET_BOOLEAN_PARAM(ARGC_TWO, doAntiAlias);
1900 
1901     m_canvas->ClipRoundRect(jsRoundRect->GetRoundRect(), static_cast<ClipOp>(clipOpInt), doAntiAlias);
1902     return nullptr;
1903 }
1904 
SetMatrix(napi_env env,napi_callback_info info)1905 napi_value JsCanvas::SetMatrix(napi_env env, napi_callback_info info)
1906 {
1907     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1908     return (me != nullptr) ? me->OnSetMatrix(env, info) : nullptr;
1909 }
1910 
OnSetMatrix(napi_env env,napi_callback_info info)1911 napi_value JsCanvas::OnSetMatrix(napi_env env, napi_callback_info info)
1912 {
1913     if (m_canvas == nullptr) {
1914         ROSEN_LOGE("JsCanvas::OnSetMatrix canvas is nullptr");
1915         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1916     }
1917 
1918     napi_value argv[ARGC_ONE] = {nullptr};
1919     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1920 
1921     JsMatrix* jsMatrix = nullptr;
1922     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
1923 
1924     if (jsMatrix->GetMatrix() == nullptr) {
1925         ROSEN_LOGE("JsCanvas::OnSetMatrix matrix is nullptr");
1926         return nullptr;
1927     }
1928 
1929     JS_CALL_DRAWING_FUNC(m_canvas->SetMatrix(*jsMatrix->GetMatrix()));
1930     return nullptr;
1931 }
1932 
Scale(napi_env env,napi_callback_info info)1933 napi_value JsCanvas::Scale(napi_env env, napi_callback_info info)
1934 {
1935     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1936     return (me != nullptr) ? me->OnScale(env, info) : nullptr;
1937 }
1938 
OnScale(napi_env env,napi_callback_info info)1939 napi_value JsCanvas::OnScale(napi_env env, napi_callback_info info)
1940 {
1941     if (m_canvas == nullptr) {
1942         ROSEN_LOGE("JsCanvas::OnScale canvas is nullptr");
1943         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1944     }
1945 
1946     napi_value argv[ARGC_TWO] = {nullptr};
1947     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1948 
1949     double sx = 0.0;
1950     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
1951     double sy = 0.0;
1952     GET_DOUBLE_PARAM(ARGC_ONE, sy);
1953 
1954     m_canvas->Scale(sx, sy);
1955     return nullptr;
1956 }
1957 
ConcatMatrix(napi_env env,napi_callback_info info)1958 napi_value JsCanvas::ConcatMatrix(napi_env env, napi_callback_info info)
1959 {
1960     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1961     return (me != nullptr) ? me->OnConcatMatrix(env, info) : nullptr;
1962 }
1963 
OnConcatMatrix(napi_env env,napi_callback_info info)1964 napi_value JsCanvas::OnConcatMatrix(napi_env env, napi_callback_info info)
1965 {
1966     if (m_canvas == nullptr) {
1967         ROSEN_LOGE("JsCanvas::OnConcatMatrix canvas is nullptr");
1968         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1969     }
1970 
1971     napi_value argv[ARGC_ONE] = {nullptr};
1972     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1973 
1974     JsMatrix* jsMatrix = nullptr;
1975     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
1976 
1977     if (jsMatrix->GetMatrix() == nullptr) {
1978         ROSEN_LOGE("JsCanvas::OnConcatMatrix matrix is nullptr");
1979         return nullptr;
1980     }
1981 
1982     JS_CALL_DRAWING_FUNC(m_canvas->ConcatMatrix(*jsMatrix->GetMatrix()));
1983     return nullptr;
1984 }
1985 
IsClipEmpty(napi_env env,napi_callback_info info)1986 napi_value JsCanvas::IsClipEmpty(napi_env env, napi_callback_info info)
1987 {
1988     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1989     return (me != nullptr) ? me->OnIsClipEmpty(env, info) : nullptr;
1990 }
1991 
OnIsClipEmpty(napi_env env,napi_callback_info info)1992 napi_value JsCanvas::OnIsClipEmpty(napi_env env, napi_callback_info info)
1993 {
1994     if (m_canvas == nullptr) {
1995         ROSEN_LOGE("JsCanvas::OnIsClipEmpty canvas is nullptr");
1996         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1997     }
1998 
1999     return CreateJsValue(env, m_canvas->IsClipEmpty());
2000 }
2001 
GetLocalClipBounds(napi_env env,napi_callback_info info)2002 napi_value JsCanvas::GetLocalClipBounds(napi_env env, napi_callback_info info)
2003 {
2004     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2005     return (me != nullptr) ? me->OnGetLocalClipBounds(env, info) : nullptr;
2006 }
2007 
OnGetLocalClipBounds(napi_env env,napi_callback_info info)2008 napi_value JsCanvas::OnGetLocalClipBounds(napi_env env, napi_callback_info info)
2009 {
2010     if (m_canvas == nullptr) {
2011         ROSEN_LOGE("JsCanvas::OnGetLocalClipBounds canvas is nullptr");
2012         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2013     }
2014 
2015     Rect rect = m_canvas->GetLocalClipBounds();
2016     std::shared_ptr<Rect> rectPtr = std::make_shared<Rect>(rect.GetLeft(),
2017         rect.GetTop(), rect.GetRight(), rect.GetBottom());
2018 
2019     return GetRectAndConvertToJsValue(env, rectPtr);
2020 }
2021 
GetCanvas()2022 Canvas* JsCanvas::GetCanvas()
2023 {
2024     return m_canvas;
2025 }
2026 
ResetCanvas()2027 void JsCanvas::ResetCanvas()
2028 {
2029     m_canvas = nullptr;
2030 }
2031 
ClipCanvas(float width,float height)2032 void JsCanvas::ClipCanvas(float width, float height)
2033 {
2034     if (m_canvas) {
2035         Rect rect(0, 0, width, height);
2036         JS_CALL_DRAWING_FUNC(m_canvas->ClipRect(rect));
2037     }
2038 }
2039 
SaveCanvas()2040 void JsCanvas::SaveCanvas()
2041 {
2042     if (m_canvas) {
2043         JS_CALL_DRAWING_FUNC(m_canvas->Save());
2044     }
2045 }
2046 
RestoreCanvas()2047 void JsCanvas::RestoreCanvas()
2048 {
2049     if (m_canvas) {
2050         JS_CALL_DRAWING_FUNC(m_canvas->Restore());
2051     }
2052 }
2053 
DrawImageRect(napi_env env,napi_callback_info info)2054 napi_value JsCanvas::DrawImageRect(napi_env env, napi_callback_info info)
2055 {
2056     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2057     return (me != nullptr) ? me->OnDrawImageRect(env, info) : nullptr;
2058 }
2059 
OnDrawImageRect(napi_env env,napi_callback_info info)2060 napi_value JsCanvas::OnDrawImageRect(napi_env env, napi_callback_info info)
2061 {
2062 #ifdef ROSEN_OHOS
2063     if (m_canvas == nullptr) {
2064         ROSEN_LOGE("JsCanvas::OnDrawImageRect canvas is nullptr");
2065         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2066     }
2067 
2068     size_t argc = ARGC_THREE;
2069     napi_value argv[ARGC_THREE] = {nullptr};
2070     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_TWO, ARGC_THREE);
2071 
2072     PixelMapNapi* pixelMapNapi = nullptr;
2073     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi); // arg #0: pixelmap/image
2074     auto pixel = pixelMapNapi->GetPixelNapiInner();
2075     if (pixel == nullptr) {
2076         ROSEN_LOGE("JsCanvas::OnDrawImageRect pixelmap GetPixelNapiInner is nullptr");
2077         return nullptr;
2078     }
2079 
2080     double ltrb[ARGC_FOUR] = {0};
2081     if (!ConvertFromJsRect(env, argv[ARGC_ONE], ltrb, ARGC_FOUR)) { // arg #1: dstRect
2082         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
2083             "Incorrect rect dst parameter type. The type of left, top, right and bottom must be number.");
2084     }
2085     Drawing::Rect dstRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
2086 
2087     if (argc == ARGC_TWO) { // without (optional) arg #2: samplingOptions
2088         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2089         if (m_canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
2090             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(m_canvas);
2091             Drawing::Rect srcRect(0, 0, pixel->GetWidth(), pixel->GetHeight());
2092             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, Drawing::SamplingOptions(),
2093                 SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
2094             return nullptr;
2095         }
2096         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2097         if (image == nullptr) {
2098             ROSEN_LOGE("JsCanvas::OnDrawImageRect image is nullptr");
2099             return nullptr;
2100         }
2101         m_canvas->DrawImageRect(*image, dstRect, Drawing::SamplingOptions());
2102     } else {
2103         JsSamplingOptions* jsSamplingOptions = nullptr;
2104         GET_UNWRAP_PARAM(ARGC_TWO, jsSamplingOptions); // (optional) arg #2: samplingOptions
2105         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
2106         if (samplingOptions == nullptr) {
2107             ROSEN_LOGE("JsCanvas::OnDrawImageRect get samplingOptions is nullptr");
2108             return nullptr;
2109         }
2110         if (m_canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
2111             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(m_canvas);
2112             Drawing::Rect srcRect(0, 0, pixel->GetWidth(), pixel->GetHeight());
2113             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, *samplingOptions.get(),
2114                 SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
2115             return nullptr;
2116         }
2117         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2118         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2119         if (image == nullptr) {
2120             ROSEN_LOGE("JsCanvas::OnDrawImageRect image is nullptr");
2121             return nullptr;
2122         }
2123         m_canvas->DrawImageRect(*image, dstRect, *samplingOptions.get());
2124     }
2125     if (mPixelMap_ != nullptr) {
2126         mPixelMap_->MarkDirty();
2127     }
2128 #endif
2129     return nullptr;
2130 }
2131 
DrawImageRectWithSrc(napi_env env,napi_callback_info info)2132 napi_value JsCanvas::DrawImageRectWithSrc(napi_env env, napi_callback_info info)
2133 {
2134     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2135     return (me != nullptr) ? me->OnDrawImageRectWithSrc(env, info) : nullptr;
2136 }
2137 
2138 #ifdef ROSEN_OHOS
OnDrawingImageRectWithSrc(napi_env env,napi_value * argv,size_t argc,Canvas & canvas,const std::shared_ptr<Media::PixelMap> pixel,const Rect & srcRect,const Rect & dstRect)2139 static napi_value OnDrawingImageRectWithSrc(napi_env env, napi_value* argv, size_t argc, Canvas& canvas,
2140                                             const std::shared_ptr<Media::PixelMap> pixel,
2141                                             const Rect& srcRect, const Rect& dstRect)
2142 {
2143     if (argc == ARGC_THREE) { // without optional arg #3 (samplingOptions) and arg #4 (constraint):
2144         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2145         if (canvas.GetDrawingType() == Drawing::DrawingType::RECORDING) {
2146             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(&canvas);
2147             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, Drawing::SamplingOptions());
2148             return nullptr;
2149         }
2150         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2151         if (image == nullptr) {
2152             ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc image is nullptr");
2153             return nullptr;
2154         }
2155         canvas.DrawImageRect(*image, srcRect, dstRect, Drawing::SamplingOptions());
2156     } else if (argc == ARGC_FOUR) { // without optional arg #4 (constraint):
2157         JsSamplingOptions* jsSamplingOptions = nullptr;
2158         GET_UNWRAP_PARAM(ARGC_THREE, jsSamplingOptions);
2159         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
2160         if (samplingOptions == nullptr) {
2161             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect samplingOptions parameter.");
2162         }
2163         if (canvas.GetDrawingType() == Drawing::DrawingType::RECORDING) {
2164             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(&canvas);
2165             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, *samplingOptions.get());
2166             return nullptr;
2167         }
2168         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2169         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2170         if (image == nullptr) {
2171             ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc image is nullptr");
2172             return nullptr;
2173         }
2174         canvas.DrawImageRect(*image, srcRect, dstRect, *samplingOptions.get());
2175     } else if (argc == ARGC_FIVE) {  // with optional arg #3 (samplingOptions) and arg #4 (constraint):
2176         JsSamplingOptions* jsSamplingOptions = nullptr;
2177         GET_UNWRAP_PARAM(ARGC_THREE, jsSamplingOptions);
2178         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
2179         if (samplingOptions == nullptr) {
2180             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect samplingOptions parameter.");
2181         }
2182         int32_t constraint = 0;
2183         GET_ENUM_PARAM(ARGC_FOUR,
2184             constraint,
2185             static_cast<int32_t>(SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT),
2186             static_cast<int32_t>(SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT));
2187         if (canvas.GetDrawingType() == Drawing::DrawingType::RECORDING) {
2188             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(&canvas);
2189             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect,
2190                 *samplingOptions.get(), static_cast<SrcRectConstraint>(constraint));
2191             return nullptr;
2192         }
2193         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2194         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2195         if (image == nullptr) {
2196             ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc image is nullptr");
2197             return nullptr;
2198         }
2199         canvas.DrawImageRect(*image, srcRect, dstRect,
2200             *samplingOptions.get(), static_cast<SrcRectConstraint>(constraint));
2201     } else { // argc > 5:
2202         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "More than 5 parameters are not supported");
2203     }
2204     return nullptr;
2205 }
2206 #endif
2207 
OnDrawImageRectWithSrc(napi_env env,napi_callback_info info)2208 napi_value JsCanvas::OnDrawImageRectWithSrc(napi_env env, napi_callback_info info)
2209 {
2210 #ifdef ROSEN_OHOS
2211     if (m_canvas == nullptr) {
2212         ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc canvas is nullptr");
2213         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2214     }
2215 
2216     size_t argc = ARGC_FIVE;
2217     napi_value argv[ARGC_FIVE] = {nullptr};
2218     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_THREE, ARGC_FIVE);
2219 
2220     PixelMapNapi* pixelMapNapi = nullptr;
2221     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi); // arg #0: pixelmap/image
2222     auto pixel = pixelMapNapi->GetPixelNapiInner();
2223     if (pixel == nullptr) {
2224         ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc pixelmap GetPixelNapiInner is nullptr");
2225         return nullptr;
2226     }
2227 
2228     double ltrb[ARGC_FOUR] = {0};
2229     if (!ConvertFromJsRect(env, argv[ARGC_ONE], ltrb, ARGC_FOUR)) { // arg #1: srcRect
2230         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
2231             "Incorrect rect src parameter type. The type of left, top, right and bottom must be number.");
2232     }
2233     Drawing::Rect srcRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
2234 
2235     if (!ConvertFromJsRect(env, argv[ARGC_TWO], ltrb, ARGC_FOUR)) { // arg #2: dstRect
2236         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
2237             "Incorrect rect dst parameter type. The type of left, top, right and bottom must be number.");
2238     }
2239     Drawing::Rect dstRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
2240 
2241     napi_value result = OnDrawingImageRectWithSrc(env, argv, argc, *m_canvas, pixel, srcRect, dstRect);
2242     if (mPixelMap_ != nullptr) {
2243         mPixelMap_->MarkDirty();
2244     }
2245     return result;
2246 #else
2247     return nullptr;
2248 #endif
2249 }
2250 
ResetMatrix(napi_env env,napi_callback_info info)2251 napi_value JsCanvas::ResetMatrix(napi_env env, napi_callback_info info)
2252 {
2253     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2254     return (me != nullptr) ? me->OnResetMatrix(env, info) : nullptr;
2255 }
2256 
OnResetMatrix(napi_env env,napi_callback_info info)2257 napi_value JsCanvas::OnResetMatrix(napi_env env, napi_callback_info info)
2258 {
2259     if (m_canvas == nullptr) {
2260         ROSEN_LOGE("JsCanvas::OnResetMatrix m_canvas is null");
2261         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2262     }
2263     m_canvas->ResetMatrix();
2264     return nullptr;
2265 }
2266 
2267 } // namespace Drawing
2268 } // namespace OHOS::Rosen
2269