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::__anon6f2d5c6d0110::PixelMapReleaseContext112     explicit PixelMapReleaseContext(std::shared_ptr<PixelMap> pixelMap) : pixelMap_(pixelMap) {}
113 
~PixelMapReleaseContextOHOS::Rosen::__anon6f2d5c6d0110::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 
1114     const char* currentStr = str;
1115     int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
1116     size_t byteLen = currentStr - str;
1117     if (byteLen != len) {
1118         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1119             "Parameter verification failed. Input parameter0 should be single character.");
1120     }
1121     m_canvas->DrawSingleCharacter(unicode, *font, x, y);
1122 #ifdef ROSEN_OHOS
1123     if (mPixelMap_ != nullptr) {
1124         mPixelMap_->MarkDirty();
1125     }
1126 #endif
1127     return nullptr;
1128 }
1129 
DrawPixelMapMesh(napi_env env,napi_callback_info info)1130 napi_value JsCanvas::DrawPixelMapMesh(napi_env env, napi_callback_info info)
1131 {
1132     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1133     return (me != nullptr) ? me->OnDrawPixelMapMesh(env, info) : nullptr;
1134 }
1135 
OnDrawPixelMapMesh(napi_env env,napi_callback_info info)1136 napi_value JsCanvas::OnDrawPixelMapMesh(napi_env env, napi_callback_info info)
1137 {
1138 #ifdef ROSEN_OHOS
1139     if (m_canvas == nullptr) {
1140         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh canvas is null");
1141         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1142     }
1143 
1144     napi_value argv[ARGC_SEVEN] = {nullptr};
1145     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_SEVEN);
1146 
1147     PixelMapNapi* pixelMapNapi = nullptr;
1148     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi);
1149 
1150     if (pixelMapNapi->GetPixelNapiInner() == nullptr) {
1151         ROSEN_LOGE("Drawing_napi::pixelMap pixelmap getPixelNapiInner is nullptr");
1152         return nullptr;
1153     }
1154     std::shared_ptr<Media::PixelMap> pixelMap = pixelMapNapi->GetPixelNapiInner();
1155 
1156     int32_t column = 0;
1157     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, column);
1158     int32_t row = 0;
1159     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_TWO, row);
1160     int32_t vertOffset = 0;
1161     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_FOUR, vertOffset);
1162     int32_t colorOffset = 0;
1163     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_SIX, colorOffset);
1164 
1165     if (column == 0 || row == 0) {
1166         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh column or row is invalid");
1167         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid column or row params.");
1168     }
1169 
1170     napi_value verticesArray = argv[ARGC_THREE];
1171     uint32_t verticesSize = 0;
1172     napi_get_array_length(env, verticesArray, &verticesSize);
1173     int64_t tempVerticesSize = ((column + 1) * (row + 1) + vertOffset) * 2; // x and y two coordinates
1174     if (verticesSize != tempVerticesSize) {
1175         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh vertices are invalid");
1176         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter3 type.");
1177     }
1178 
1179     auto vertices = new (std::nothrow) float[verticesSize];
1180     if (!vertices) {
1181         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh create array with size of vertices failed");
1182         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Size of vertices exceed memory limit.");
1183     }
1184 
1185     for (uint32_t i = 0; i < verticesSize; i++) {
1186         napi_value tempVertex = nullptr;
1187         napi_get_element(env, verticesArray, i, &tempVertex);
1188         double vertex = 0.f;
1189         if (napi_get_value_double(env, tempVertex, &vertex) != napi_ok) {
1190             ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh vertex is invalid");
1191             delete []vertices;
1192             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1193                 "Incorrect DrawPixelMapMesh parameter vertex type.");
1194         }
1195         vertices[i] = vertex;
1196     }
1197     float* verticesMesh = verticesSize ? (vertices + vertOffset * 2) : nullptr; // offset two coordinates
1198 
1199     napi_value colorsArray = argv[ARGC_FIVE];
1200     uint32_t colorsSize = 0;
1201     napi_get_array_length(env, colorsArray, &colorsSize);
1202     int64_t tempColorsSize = (column + 1) * (row + 1) + colorOffset;
1203 
1204     if (colorsSize != 0 && colorsSize != tempColorsSize) {
1205         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh colors are invalid");
1206         delete []vertices;
1207         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter5 type.");
1208     }
1209 
1210     if (colorsSize == 0) {
1211         DrawingPixelMapMesh(pixelMap, column, row, verticesMesh, nullptr, m_canvas);
1212         if (mPixelMap_ != nullptr) {
1213             mPixelMap_->MarkDirty();
1214         }
1215         delete []vertices;
1216         return nullptr;
1217     }
1218 
1219     auto colors = new (std::nothrow) uint32_t[colorsSize];
1220     if (!colors) {
1221         ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh create array with size of colors failed");
1222         delete []vertices;
1223         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Size of colors exceed memory limit.");
1224     }
1225     for (uint32_t i = 0; i < colorsSize; i++) {
1226         napi_value tempColor = nullptr;
1227         napi_get_element(env, colorsArray, i, &tempColor);
1228         uint32_t color = 0;
1229         if (napi_get_value_uint32(env, tempColor, &color) != napi_ok) {
1230             ROSEN_LOGE("JsCanvas::OnDrawPixelMapMesh color is invalid");
1231             delete []vertices;
1232             delete []colors;
1233             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1234                 "Incorrect DrawPixelMapMesh parameter color type.");
1235         }
1236         colors[i] = color;
1237     }
1238     uint32_t* colorsMesh = colors + colorOffset;
1239 
1240     DrawingPixelMapMesh(pixelMap, column, row, verticesMesh, colorsMesh, m_canvas);
1241     if (mPixelMap_ != nullptr) {
1242         mPixelMap_->MarkDirty();
1243     }
1244     delete []vertices;
1245     delete []colors;
1246     return nullptr;
1247 #else
1248     return nullptr;
1249 #endif
1250 }
1251 
DrawRegion(napi_env env,napi_callback_info info)1252 napi_value JsCanvas::DrawRegion(napi_env env, napi_callback_info info)
1253 {
1254     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1255     return (me != nullptr) ? me->OnDrawRegion(env, info) : nullptr;
1256 }
1257 
OnDrawRegion(napi_env env,napi_callback_info info)1258 napi_value JsCanvas::OnDrawRegion(napi_env env, napi_callback_info info)
1259 {
1260     if (m_canvas == nullptr) {
1261         ROSEN_LOGE("JsCanvas::OnDrawRegion canvas is nullptr");
1262         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1263     }
1264     napi_value argv[ARGC_ONE] = {nullptr};
1265     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1266 
1267     JsRegion* jsRegion = nullptr;
1268     GET_UNWRAP_PARAM(ARGC_ZERO, jsRegion);
1269     if (jsRegion->GetRegion() == nullptr) {
1270         ROSEN_LOGE("JsCanvas::OnDrawRegion region is nullptr");
1271         return nullptr;
1272     }
1273     JS_CALL_DRAWING_FUNC(m_canvas->DrawRegion(*jsRegion->GetRegion()));
1274 #ifdef ROSEN_OHOS
1275     if (mPixelMap_ != nullptr) {
1276         mPixelMap_->MarkDirty();
1277     }
1278 #endif
1279     return nullptr;
1280 }
1281 
DrawBackground(napi_env env,napi_callback_info info)1282 napi_value JsCanvas::DrawBackground(napi_env env, napi_callback_info info)
1283 {
1284     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1285     return (me != nullptr) ? me->OnDrawBackground(env, info) : nullptr;
1286 }
1287 
OnDrawBackground(napi_env env,napi_callback_info info)1288 napi_value JsCanvas::OnDrawBackground(napi_env env, napi_callback_info info)
1289 {
1290     if (m_canvas == nullptr) {
1291         ROSEN_LOGE("JsCanvas::OnDrawBackground canvas is nullptr");
1292         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1293     }
1294 
1295     napi_value argv[ARGC_ONE] = {nullptr};
1296     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1297 
1298     JsBrush* jsBrush = nullptr;
1299     GET_UNWRAP_PARAM(ARGC_ZERO, jsBrush);
1300     if (jsBrush->GetBrush() == nullptr) {
1301         ROSEN_LOGE("JsCanvas::OnDrawBackground brush is nullptr");
1302         return nullptr;
1303     }
1304 
1305     m_canvas->DrawBackground(*jsBrush->GetBrush());
1306 #ifdef ROSEN_OHOS
1307     if (mPixelMap_ != nullptr) {
1308         mPixelMap_->MarkDirty();
1309     }
1310 #endif
1311     return nullptr;
1312 }
1313 
DrawRoundRect(napi_env env,napi_callback_info info)1314 napi_value JsCanvas::DrawRoundRect(napi_env env, napi_callback_info info)
1315 {
1316     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1317     return (me != nullptr) ? me->OnDrawRoundRect(env, info) : nullptr;
1318 }
1319 
OnDrawRoundRect(napi_env env,napi_callback_info info)1320 napi_value JsCanvas::OnDrawRoundRect(napi_env env, napi_callback_info info)
1321 {
1322     if (m_canvas == nullptr) {
1323         ROSEN_LOGE("JsCanvas::OnDrawRoundRect canvas is nullptr");
1324         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1325     }
1326 
1327     napi_value argv[ARGC_ONE] = {nullptr};
1328     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1329 
1330     JsRoundRect* jsRoundRect = nullptr;
1331     GET_UNWRAP_PARAM(ARGC_ZERO, jsRoundRect);
1332 
1333     m_canvas->DrawRoundRect(jsRoundRect->GetRoundRect());
1334 #ifdef ROSEN_OHOS
1335     if (mPixelMap_ != nullptr) {
1336         mPixelMap_->MarkDirty();
1337     }
1338 #endif
1339     return nullptr;
1340 }
1341 
DrawNestedRoundRect(napi_env env,napi_callback_info info)1342 napi_value JsCanvas::DrawNestedRoundRect(napi_env env, napi_callback_info info)
1343 {
1344     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1345     return (me != nullptr) ? me->OnDrawNestedRoundRect(env, info) : nullptr;
1346 }
1347 
OnDrawNestedRoundRect(napi_env env,napi_callback_info info)1348 napi_value JsCanvas::OnDrawNestedRoundRect(napi_env env, napi_callback_info info)
1349 {
1350     if (m_canvas == nullptr) {
1351         ROSEN_LOGE("JsCanvas::OnDrawNestedRoundRect canvas is nullptr");
1352         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1353     }
1354 
1355     napi_value argv[ARGC_TWO] = {nullptr};
1356     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1357 
1358     JsRoundRect* jsOuter = nullptr;
1359     GET_UNWRAP_PARAM(ARGC_ZERO, jsOuter);
1360 
1361     JsRoundRect* jsInner = nullptr;
1362     GET_UNWRAP_PARAM(ARGC_ONE, jsInner);
1363 
1364     m_canvas->DrawNestedRoundRect(jsOuter->GetRoundRect(), jsInner->GetRoundRect());
1365 #ifdef ROSEN_OHOS
1366     if (mPixelMap_ != nullptr) {
1367         mPixelMap_->MarkDirty();
1368     }
1369 #endif
1370     return nullptr;
1371 }
1372 
GetTotalMatrix(napi_env env,napi_callback_info info)1373 napi_value JsCanvas::GetTotalMatrix(napi_env env, napi_callback_info info)
1374 {
1375     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1376     return (me != nullptr) ? me->OnGetTotalMatrix(env, info) : nullptr;
1377 }
1378 
OnGetTotalMatrix(napi_env env,napi_callback_info info)1379 napi_value JsCanvas::OnGetTotalMatrix(napi_env env, napi_callback_info info)
1380 {
1381     if (m_canvas == nullptr) {
1382         ROSEN_LOGE("JsCanvas::GetTotalMatrix canvas is null");
1383         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1384     }
1385 
1386     Matrix matrix = m_canvas->GetTotalMatrix();
1387     std::shared_ptr<Matrix> matrixPtr = std::make_shared<Matrix>(matrix);
1388 
1389     return JsMatrix::CreateJsMatrix(env, matrixPtr);
1390 }
1391 
AttachPen(napi_env env,napi_callback_info info)1392 napi_value JsCanvas::AttachPen(napi_env env, napi_callback_info info)
1393 {
1394     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1395     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1396     if (me == nullptr) {
1397         return nullptr;
1398     }
1399     Canvas* canvas = me->GetCanvas();
1400     if (canvas == nullptr) {
1401         ROSEN_LOGE("JsCanvas::AttachPen canvas is nullptr");
1402         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1403     }
1404 
1405     napi_value argv[ARGC_ONE] = {nullptr};
1406     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1407 
1408     JsPen* jsPen = nullptr;
1409     GET_UNWRAP_PARAM(ARGC_ZERO, jsPen);
1410 
1411     if (jsPen->GetPen() == nullptr) {
1412         ROSEN_LOGE("JsCanvas::AttachPen pen is nullptr");
1413         return nullptr;
1414     }
1415     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1416     canvas->AttachPen(*jsPen->GetPen());
1417     return nullptr;
1418 }
1419 
AttachBrush(napi_env env,napi_callback_info info)1420 napi_value JsCanvas::AttachBrush(napi_env env, napi_callback_info info)
1421 {
1422     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1423     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1424     if (me == nullptr) {
1425         return nullptr;
1426     }
1427     Canvas* canvas = me->GetCanvas();
1428     if (canvas == nullptr) {
1429         ROSEN_LOGE("JsCanvas::AttachBrush canvas is nullptr");
1430         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1431     }
1432 
1433     napi_value argv[ARGC_ONE] = {nullptr};
1434     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1435 
1436     JsBrush* jsBrush = nullptr;
1437     GET_UNWRAP_PARAM(ARGC_ZERO, jsBrush);
1438 
1439     if (jsBrush->GetBrush() == nullptr) {
1440         ROSEN_LOGE("JsCanvas::AttachBrush brush is nullptr");
1441         return nullptr;
1442     }
1443     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1444     canvas->AttachBrush(*jsBrush->GetBrush());
1445     return nullptr;
1446 }
1447 
DetachPen(napi_env env,napi_callback_info info)1448 napi_value JsCanvas::DetachPen(napi_env env, napi_callback_info info)
1449 {
1450     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1451     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1452     if (me == nullptr) {
1453         return nullptr;
1454     }
1455     Canvas* canvas = me->GetCanvas();
1456     if (canvas == nullptr) {
1457         ROSEN_LOGE("JsCanvas::DetachPen canvas is null");
1458         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1459     }
1460     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1461     canvas->DetachPen();
1462     return nullptr;
1463 }
1464 
DetachBrush(napi_env env,napi_callback_info info)1465 napi_value JsCanvas::DetachBrush(napi_env env, napi_callback_info info)
1466 {
1467     DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
1468     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1469     if (me == nullptr) {
1470         return nullptr;
1471     }
1472     Canvas* canvas = me->GetCanvas();
1473     if (canvas == nullptr) {
1474         ROSEN_LOGE("JsCanvas::DetachBrush canvas is null");
1475         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1476     }
1477     DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1478     canvas->DetachBrush();
1479     return nullptr;
1480 }
1481 
Skew(napi_env env,napi_callback_info info)1482 napi_value JsCanvas::Skew(napi_env env, napi_callback_info info)
1483 {
1484     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1485     return (me != nullptr) ? me->OnSkew(env, info) : nullptr;
1486 }
1487 
OnSkew(napi_env env,napi_callback_info info)1488 napi_value JsCanvas::OnSkew(napi_env env, napi_callback_info info)
1489 {
1490     if (m_canvas == nullptr) {
1491         ROSEN_LOGE("JsCanvas::OnSkew m_canvas is null");
1492         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1493     }
1494 
1495     napi_value argv[ARGC_TWO] = {nullptr};
1496     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1497 
1498     double sx = 0.0;
1499     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
1500     double sy = 0.0;
1501     GET_DOUBLE_PARAM(ARGC_ONE, sy);
1502 
1503     m_canvas->Shear(sx, sy);
1504     return nullptr;
1505 }
1506 
Rotate(napi_env env,napi_callback_info info)1507 napi_value JsCanvas::Rotate(napi_env env, napi_callback_info info)
1508 {
1509     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1510     return (me != nullptr) ? me->OnRotate(env, info) : nullptr;
1511 }
1512 
OnRotate(napi_env env,napi_callback_info info)1513 napi_value JsCanvas::OnRotate(napi_env env, napi_callback_info info)
1514 {
1515     if (m_canvas == nullptr) {
1516         ROSEN_LOGE("JsCanvas::OnRotate m_canvas is null");
1517         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1518     }
1519 
1520     napi_value argv[ARGC_THREE] = {nullptr};
1521     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
1522 
1523     double degree = 0.0;
1524     GET_DOUBLE_PARAM(ARGC_ZERO, degree);
1525     double sx = 0.0;
1526     GET_DOUBLE_PARAM(ARGC_ONE, sx);
1527     double sy = 0.0;
1528     GET_DOUBLE_PARAM(ARGC_TWO, sy);
1529 
1530     m_canvas->Rotate(degree, sx, sy);
1531     return nullptr;
1532 }
1533 
GetSaveCount(napi_env env,napi_callback_info info)1534 napi_value JsCanvas::GetSaveCount(napi_env env, napi_callback_info info)
1535 {
1536     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1537     return (me != nullptr) ? me->OnGetSaveCount(env, info) : nullptr;
1538 }
1539 
OnGetSaveCount(napi_env env,napi_callback_info info)1540 napi_value JsCanvas::OnGetSaveCount(napi_env env, napi_callback_info info)
1541 {
1542     if (m_canvas == nullptr) {
1543         ROSEN_LOGE("JsCanvas::OnGetSaveCount canvas is null");
1544         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1545     }
1546     return CreateJsNumber(env, m_canvas->GetSaveCount());
1547 }
1548 
GetWidth(napi_env env,napi_callback_info info)1549 napi_value JsCanvas::GetWidth(napi_env env, napi_callback_info info)
1550 {
1551     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1552     return (me != nullptr) ? me->OnGetWidth(env, info) : nullptr;
1553 }
1554 
OnGetWidth(napi_env env,napi_callback_info info)1555 napi_value JsCanvas::OnGetWidth(napi_env env, napi_callback_info info)
1556 {
1557     if (m_canvas == nullptr) {
1558         ROSEN_LOGE("JsCanvas::OnGetWidth canvas is null");
1559         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1560     }
1561     return CreateJsNumber(env, m_canvas->GetWidth());
1562 }
1563 
GetHeight(napi_env env,napi_callback_info info)1564 napi_value JsCanvas::GetHeight(napi_env env, napi_callback_info info)
1565 {
1566     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1567     return (me != nullptr) ? me->OnGetHeight(env, info) : nullptr;
1568 }
1569 
OnGetHeight(napi_env env,napi_callback_info info)1570 napi_value JsCanvas::OnGetHeight(napi_env env, napi_callback_info info)
1571 {
1572     if (m_canvas == nullptr) {
1573         ROSEN_LOGE("JsCanvas::OnGetHeight canvas is null");
1574         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1575     }
1576     return CreateJsNumber(env, m_canvas->GetHeight());
1577 }
1578 
ClipPath(napi_env env,napi_callback_info info)1579 napi_value JsCanvas::ClipPath(napi_env env, napi_callback_info info)
1580 {
1581     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1582     return (me != nullptr) ? me->OnClipPath(env, info) : nullptr;
1583 }
1584 
OnClipPath(napi_env env,napi_callback_info info)1585 napi_value JsCanvas::OnClipPath(napi_env env, napi_callback_info info)
1586 {
1587     if (m_canvas == nullptr) {
1588         ROSEN_LOGE("JsCanvas::OnClipPath m_canvas is nullptr");
1589         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1590     }
1591     size_t argc = ARGC_THREE;
1592     napi_value argv[ARGC_THREE] = {nullptr};
1593     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_THREE);
1594 
1595     JsPath* jsPath = nullptr;
1596     GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
1597 
1598     Path* path = jsPath->GetPath();
1599     if (path == nullptr) {
1600         ROSEN_LOGE("JsCanvas::OnClipPath path is nullptr");
1601         return nullptr;
1602     }
1603     if (argc == ARGC_ONE) {
1604         m_canvas->ClipPath(*path);
1605         return nullptr;
1606     }
1607 
1608     int32_t jsClipOp = 0;
1609     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, jsClipOp);
1610 
1611     if (argc == ARGC_TWO) {
1612         m_canvas->ClipPath(*path, static_cast<ClipOp>(jsClipOp));
1613         return nullptr;
1614     }
1615 
1616     bool jsDoAntiAlias = false;
1617     GET_BOOLEAN_PARAM(ARGC_TWO, jsDoAntiAlias);
1618 
1619     m_canvas->ClipPath(*path, static_cast<ClipOp>(jsClipOp), jsDoAntiAlias);
1620     return nullptr;
1621 }
1622 
ClipRegion(napi_env env,napi_callback_info info)1623 napi_value JsCanvas::ClipRegion(napi_env env, napi_callback_info info)
1624 {
1625     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1626     return (me != nullptr) ? me->OnClipRegion(env, info) : nullptr;
1627 }
1628 
OnClipRegion(napi_env env,napi_callback_info info)1629 napi_value JsCanvas::OnClipRegion(napi_env env, napi_callback_info info)
1630 {
1631     if (m_canvas == nullptr) {
1632         ROSEN_LOGE("JsCanvas::OnClipRegion m_canvas is nullptr");
1633         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1634     }
1635     size_t argc = ARGC_TWO;
1636     napi_value argv[ARGC_TWO] = {nullptr};
1637     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
1638 
1639     JsRegion* jsRegion = nullptr;
1640     GET_UNWRAP_PARAM(ARGC_ZERO, jsRegion);
1641 
1642     Region* region = jsRegion->GetRegion();
1643     if (region == nullptr) {
1644         ROSEN_LOGE("JsCanvas::OnClipRegion region is nullptr");
1645         return nullptr;
1646     }
1647     if (argc == ARGC_ONE) {
1648         m_canvas->ClipRegion(*region);
1649         return nullptr;
1650     }
1651 
1652     int32_t jsClipOp = 0;
1653     GET_ENUM_PARAM(ARGC_ONE, jsClipOp, 0, static_cast<int32_t>(ClipOp::INTERSECT));
1654 
1655     m_canvas->ClipRegion(*region, static_cast<ClipOp>(jsClipOp));
1656     return nullptr;
1657 }
1658 
Translate(napi_env env,napi_callback_info info)1659 napi_value JsCanvas::Translate(napi_env env, napi_callback_info info)
1660 {
1661     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1662     return (me != nullptr) ? me->OnTranslate(env, info) : nullptr;
1663 }
1664 
OnTranslate(napi_env env,napi_callback_info info)1665 napi_value JsCanvas::OnTranslate(napi_env env, napi_callback_info info)
1666 {
1667     if (m_canvas == nullptr) {
1668         ROSEN_LOGE("JsCanvas::OnTranslate m_canvas is null");
1669         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1670     }
1671 
1672     napi_value argv[ARGC_TWO] = {nullptr};
1673     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1674 
1675     double dx = 0.0;
1676     GET_DOUBLE_PARAM(ARGC_ZERO, dx);
1677     double dy = 0.0;
1678     GET_DOUBLE_PARAM(ARGC_ONE, dy);
1679 
1680     m_canvas->Translate(dx, dy);
1681     return nullptr;
1682 }
1683 
Save(napi_env env,napi_callback_info info)1684 napi_value JsCanvas::Save(napi_env env, napi_callback_info info)
1685 {
1686     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1687     return (me != nullptr) ? me->OnSave(env, info) : nullptr;
1688 }
1689 
OnSave(napi_env env,napi_callback_info info)1690 napi_value JsCanvas::OnSave(napi_env env, napi_callback_info info)
1691 {
1692     if (m_canvas == nullptr) {
1693         ROSEN_LOGE("JsCanvas::OnSave canvas is null");
1694         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1695     }
1696     return CreateJsNumber(env, m_canvas->Save());
1697 }
1698 
SaveLayer(napi_env env,napi_callback_info info)1699 napi_value JsCanvas::SaveLayer(napi_env env, napi_callback_info info)
1700 {
1701     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1702     return (me != nullptr) ? me->OnSaveLayer(env, info) : nullptr;
1703 }
1704 
OnSaveLayer(napi_env env,napi_callback_info info)1705 napi_value JsCanvas::OnSaveLayer(napi_env env, napi_callback_info info)
1706 {
1707     if (m_canvas == nullptr) {
1708         ROSEN_LOGE("JsCanvas::OnSaveLayer canvas is null");
1709         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1710     }
1711     size_t argc = ARGC_TWO;
1712     napi_value argv[ARGC_TWO] = {nullptr};
1713     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ZERO, ARGC_TWO);
1714 
1715     uint32_t ret = 0;
1716     if (argc == ARGC_ZERO) {
1717         ret = m_canvas->GetSaveCount();
1718         m_canvas->SaveLayer(SaveLayerOps());
1719         return CreateJsNumber(env, ret);
1720     }
1721 
1722     napi_valuetype valueType = napi_undefined;
1723     if (napi_typeof(env, argv[ARGC_ZERO], &valueType) != napi_ok ||
1724         (valueType != napi_null && valueType != napi_object)) {
1725         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnSaveLayer parameter0 type.");
1726     }
1727     Drawing::Rect* drawingRectPtr = nullptr;
1728     double ltrb[ARGC_FOUR] = {0};
1729     if (valueType == napi_object) {
1730         if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1731             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1732                 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1733         }
1734         drawingRectPtr = new Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1735     }
1736 
1737     if (argc == ARGC_ONE) {
1738         ret = m_canvas->GetSaveCount();
1739         m_canvas->SaveLayer(SaveLayerOps(drawingRectPtr, nullptr));
1740         if (drawingRectPtr != nullptr) {
1741             delete drawingRectPtr;
1742         }
1743         return CreateJsNumber(env, ret);
1744     }
1745 
1746     if (napi_typeof(env, argv[ARGC_ONE], &valueType) != napi_ok ||
1747         (valueType != napi_null && valueType != napi_object)) {
1748         if (drawingRectPtr != nullptr) {
1749             delete drawingRectPtr;
1750         }
1751         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnSaveLayer parameter1 type.");
1752     }
1753     Drawing::Brush* drawingBrushPtr = nullptr;
1754     if (valueType == napi_object) {
1755         JsBrush* jsBrush = nullptr;
1756         napi_status status = napi_unwrap(env, argv[ARGC_ONE], reinterpret_cast<void**>(&jsBrush));
1757         if (status != napi_ok || jsBrush == nullptr) {
1758             if (drawingRectPtr != nullptr) {
1759                 delete drawingRectPtr;
1760             }
1761             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1762                 std::string("Incorrect ") + __FUNCTION__ + " parameter" + std::to_string(ARGC_ONE) + " type.");
1763         }
1764         drawingBrushPtr = jsBrush->GetBrush();
1765     }
1766     ret = m_canvas->GetSaveCount();
1767     SaveLayerOps saveLayerOps = SaveLayerOps(drawingRectPtr, drawingBrushPtr);
1768     m_canvas->SaveLayer(saveLayerOps);
1769     if (drawingRectPtr != nullptr) {
1770         delete drawingRectPtr;
1771     }
1772     return CreateJsNumber(env, ret);
1773 }
1774 
RestoreToCount(napi_env env,napi_callback_info info)1775 napi_value JsCanvas::RestoreToCount(napi_env env, napi_callback_info info)
1776 {
1777     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1778     return (me != nullptr) ? me->OnRestoreToCount(env, info) : nullptr;
1779 }
1780 
OnRestoreToCount(napi_env env,napi_callback_info info)1781 napi_value JsCanvas::OnRestoreToCount(napi_env env, napi_callback_info info)
1782 {
1783     if (m_canvas == nullptr) {
1784         ROSEN_LOGE("JsCanvas::OnRestoreToCount canvas is nullptr");
1785         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1786     }
1787 
1788     napi_value argv[ARGC_ONE] = {nullptr};
1789     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1790 
1791     int32_t count = 0;
1792     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ZERO, count);
1793 
1794     m_canvas->RestoreToCount(count);
1795     return nullptr;
1796 }
1797 
Restore(napi_env env,napi_callback_info info)1798 napi_value JsCanvas::Restore(napi_env env, napi_callback_info info)
1799 {
1800     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1801     return (me != nullptr) ? me->OnRestore(env, info) : nullptr;
1802 }
1803 
OnRestore(napi_env env,napi_callback_info info)1804 napi_value JsCanvas::OnRestore(napi_env env, napi_callback_info info)
1805 {
1806     if (m_canvas == nullptr) {
1807         ROSEN_LOGE("JsCanvas::OnRestore m_canvas is null");
1808         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1809     }
1810     m_canvas->Restore();
1811     return nullptr;
1812 }
1813 
ClipRect(napi_env env,napi_callback_info info)1814 napi_value JsCanvas::ClipRect(napi_env env, napi_callback_info info)
1815 {
1816     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1817     return (me != nullptr) ? me->OnClipRect(env, info) : nullptr;
1818 }
1819 
OnClipRect(napi_env env,napi_callback_info info)1820 napi_value JsCanvas::OnClipRect(napi_env env, napi_callback_info info)
1821 {
1822     if (m_canvas == nullptr) {
1823         ROSEN_LOGE("JsCanvas::OnClipRect m_canvas is nullptr");
1824         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1825     }
1826     size_t argc = ARGC_THREE;
1827     napi_value argv[ARGC_THREE] = {nullptr};
1828     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_THREE);
1829 
1830     double ltrb[ARGC_FOUR] = {0};
1831     if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1832         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1833             "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1834     }
1835     Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1836 
1837     if (argc == ARGC_ONE) {
1838         m_canvas->ClipRect(drawingRect);
1839         return nullptr;
1840     }
1841 
1842     int32_t clipOpInt = 0;
1843     GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, clipOpInt);
1844 
1845     if (argc == ARGC_TWO) {
1846         m_canvas->ClipRect(drawingRect, static_cast<ClipOp>(clipOpInt));
1847         return nullptr;
1848     }
1849 
1850     bool doAntiAlias = false;
1851     GET_BOOLEAN_PARAM(ARGC_TWO, doAntiAlias);
1852 
1853     m_canvas->ClipRect(drawingRect, static_cast<ClipOp>(clipOpInt), doAntiAlias);
1854     return nullptr;
1855 }
1856 
ClipRoundRect(napi_env env,napi_callback_info info)1857 napi_value JsCanvas::ClipRoundRect(napi_env env, napi_callback_info info)
1858 {
1859     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1860     return (me != nullptr) ? me->OnClipRoundRect(env, info) : nullptr;
1861 }
1862 
OnClipRoundRect(napi_env env,napi_callback_info info)1863 napi_value JsCanvas::OnClipRoundRect(napi_env env, napi_callback_info info)
1864 {
1865     if (m_canvas == nullptr) {
1866         ROSEN_LOGE("JsCanvas::OnClipRoundRect m_canvas is nullptr");
1867         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1868     }
1869 
1870     size_t argc = ARGC_THREE;
1871     napi_value argv[ARGC_THREE] = {nullptr};
1872     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_THREE);
1873 
1874     JsRoundRect* jsRoundRect = nullptr;
1875     GET_UNWRAP_PARAM(ARGC_ZERO, jsRoundRect);
1876     if (jsRoundRect == nullptr) {
1877         ROSEN_LOGE("JsCanvas::OnDrawRegion jsRoundRect is nullptr");
1878         return nullptr;
1879     }
1880 
1881     if (argc == ARGC_ONE) {
1882         m_canvas->ClipRoundRect(jsRoundRect->GetRoundRect());
1883         return nullptr;
1884     }
1885 
1886     int32_t clipOpInt = 0;
1887     GET_ENUM_PARAM(ARGC_ONE, clipOpInt, 0, static_cast<int32_t>(ClipOp::INTERSECT));
1888 
1889     if (argc == ARGC_TWO) {
1890         m_canvas->ClipRoundRect(jsRoundRect->GetRoundRect(), static_cast<ClipOp>(clipOpInt));
1891         return nullptr;
1892     }
1893 
1894     bool doAntiAlias = false;
1895     GET_BOOLEAN_PARAM(ARGC_TWO, doAntiAlias);
1896 
1897     m_canvas->ClipRoundRect(jsRoundRect->GetRoundRect(), static_cast<ClipOp>(clipOpInt), doAntiAlias);
1898     return nullptr;
1899 }
1900 
SetMatrix(napi_env env,napi_callback_info info)1901 napi_value JsCanvas::SetMatrix(napi_env env, napi_callback_info info)
1902 {
1903     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1904     return (me != nullptr) ? me->OnSetMatrix(env, info) : nullptr;
1905 }
1906 
OnSetMatrix(napi_env env,napi_callback_info info)1907 napi_value JsCanvas::OnSetMatrix(napi_env env, napi_callback_info info)
1908 {
1909     if (m_canvas == nullptr) {
1910         ROSEN_LOGE("JsCanvas::OnSetMatrix canvas is nullptr");
1911         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1912     }
1913 
1914     napi_value argv[ARGC_ONE] = {nullptr};
1915     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1916 
1917     JsMatrix* jsMatrix = nullptr;
1918     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
1919 
1920     if (jsMatrix->GetMatrix() == nullptr) {
1921         ROSEN_LOGE("JsCanvas::OnSetMatrix matrix is nullptr");
1922         return nullptr;
1923     }
1924 
1925     JS_CALL_DRAWING_FUNC(m_canvas->SetMatrix(*jsMatrix->GetMatrix()));
1926     return nullptr;
1927 }
1928 
Scale(napi_env env,napi_callback_info info)1929 napi_value JsCanvas::Scale(napi_env env, napi_callback_info info)
1930 {
1931     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1932     return (me != nullptr) ? me->OnScale(env, info) : nullptr;
1933 }
1934 
OnScale(napi_env env,napi_callback_info info)1935 napi_value JsCanvas::OnScale(napi_env env, napi_callback_info info)
1936 {
1937     if (m_canvas == nullptr) {
1938         ROSEN_LOGE("JsCanvas::OnScale canvas is nullptr");
1939         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1940     }
1941 
1942     napi_value argv[ARGC_TWO] = {nullptr};
1943     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1944 
1945     double sx = 0.0;
1946     GET_DOUBLE_PARAM(ARGC_ZERO, sx);
1947     double sy = 0.0;
1948     GET_DOUBLE_PARAM(ARGC_ONE, sy);
1949 
1950     m_canvas->Scale(sx, sy);
1951     return nullptr;
1952 }
1953 
ConcatMatrix(napi_env env,napi_callback_info info)1954 napi_value JsCanvas::ConcatMatrix(napi_env env, napi_callback_info info)
1955 {
1956     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1957     return (me != nullptr) ? me->OnConcatMatrix(env, info) : nullptr;
1958 }
1959 
OnConcatMatrix(napi_env env,napi_callback_info info)1960 napi_value JsCanvas::OnConcatMatrix(napi_env env, napi_callback_info info)
1961 {
1962     if (m_canvas == nullptr) {
1963         ROSEN_LOGE("JsCanvas::OnConcatMatrix canvas is nullptr");
1964         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1965     }
1966 
1967     napi_value argv[ARGC_ONE] = {nullptr};
1968     CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1969 
1970     JsMatrix* jsMatrix = nullptr;
1971     GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
1972 
1973     if (jsMatrix->GetMatrix() == nullptr) {
1974         ROSEN_LOGE("JsCanvas::OnConcatMatrix matrix is nullptr");
1975         return nullptr;
1976     }
1977 
1978     JS_CALL_DRAWING_FUNC(m_canvas->ConcatMatrix(*jsMatrix->GetMatrix()));
1979     return nullptr;
1980 }
1981 
IsClipEmpty(napi_env env,napi_callback_info info)1982 napi_value JsCanvas::IsClipEmpty(napi_env env, napi_callback_info info)
1983 {
1984     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
1985     return (me != nullptr) ? me->OnIsClipEmpty(env, info) : nullptr;
1986 }
1987 
OnIsClipEmpty(napi_env env,napi_callback_info info)1988 napi_value JsCanvas::OnIsClipEmpty(napi_env env, napi_callback_info info)
1989 {
1990     if (m_canvas == nullptr) {
1991         ROSEN_LOGE("JsCanvas::OnIsClipEmpty canvas is nullptr");
1992         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1993     }
1994 
1995     return CreateJsValue(env, m_canvas->IsClipEmpty());
1996 }
1997 
GetLocalClipBounds(napi_env env,napi_callback_info info)1998 napi_value JsCanvas::GetLocalClipBounds(napi_env env, napi_callback_info info)
1999 {
2000     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2001     return (me != nullptr) ? me->OnGetLocalClipBounds(env, info) : nullptr;
2002 }
2003 
OnGetLocalClipBounds(napi_env env,napi_callback_info info)2004 napi_value JsCanvas::OnGetLocalClipBounds(napi_env env, napi_callback_info info)
2005 {
2006     if (m_canvas == nullptr) {
2007         ROSEN_LOGE("JsCanvas::OnGetLocalClipBounds canvas is nullptr");
2008         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2009     }
2010 
2011     Rect rect = m_canvas->GetLocalClipBounds();
2012     std::shared_ptr<Rect> rectPtr = std::make_shared<Rect>(rect.GetLeft(),
2013         rect.GetTop(), rect.GetRight(), rect.GetBottom());
2014 
2015     return GetRectAndConvertToJsValue(env, rectPtr);
2016 }
2017 
GetCanvas()2018 Canvas* JsCanvas::GetCanvas()
2019 {
2020     return m_canvas;
2021 }
2022 
ResetCanvas()2023 void JsCanvas::ResetCanvas()
2024 {
2025     m_canvas = nullptr;
2026 }
2027 
ClipCanvas(float width,float height)2028 void JsCanvas::ClipCanvas(float width, float height)
2029 {
2030     if (m_canvas) {
2031         Rect rect(0, 0, width, height);
2032         JS_CALL_DRAWING_FUNC(m_canvas->ClipRect(rect));
2033     }
2034 }
2035 
SaveCanvas()2036 void JsCanvas::SaveCanvas()
2037 {
2038     if (m_canvas) {
2039         JS_CALL_DRAWING_FUNC(m_canvas->Save());
2040     }
2041 }
2042 
RestoreCanvas()2043 void JsCanvas::RestoreCanvas()
2044 {
2045     if (m_canvas) {
2046         JS_CALL_DRAWING_FUNC(m_canvas->Restore());
2047     }
2048 }
2049 
DrawImageRect(napi_env env,napi_callback_info info)2050 napi_value JsCanvas::DrawImageRect(napi_env env, napi_callback_info info)
2051 {
2052     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2053     return (me != nullptr) ? me->OnDrawImageRect(env, info) : nullptr;
2054 }
2055 
OnDrawImageRect(napi_env env,napi_callback_info info)2056 napi_value JsCanvas::OnDrawImageRect(napi_env env, napi_callback_info info)
2057 {
2058 #ifdef ROSEN_OHOS
2059     if (m_canvas == nullptr) {
2060         ROSEN_LOGE("JsCanvas::OnDrawImageRect canvas is nullptr");
2061         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2062     }
2063 
2064     size_t argc = ARGC_THREE;
2065     napi_value argv[ARGC_THREE] = {nullptr};
2066     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_TWO, ARGC_THREE);
2067 
2068     PixelMapNapi* pixelMapNapi = nullptr;
2069     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi); // arg #0: pixelmap/image
2070     auto pixel = pixelMapNapi->GetPixelNapiInner();
2071     if (pixel == nullptr) {
2072         ROSEN_LOGE("JsCanvas::OnDrawImageRect pixelmap GetPixelNapiInner is nullptr");
2073         return nullptr;
2074     }
2075 
2076     double ltrb[ARGC_FOUR] = {0};
2077     if (!ConvertFromJsRect(env, argv[ARGC_ONE], ltrb, ARGC_FOUR)) { // arg #1: dstRect
2078         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
2079             "Incorrect rect dst parameter type. The type of left, top, right and bottom must be number.");
2080     }
2081     Drawing::Rect dstRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
2082 
2083     if (argc == ARGC_TWO) { // without (optional) arg #2: samplingOptions
2084         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2085         if (m_canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
2086             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(m_canvas);
2087             Drawing::Rect srcRect(0, 0, pixel->GetWidth(), pixel->GetHeight());
2088             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, Drawing::SamplingOptions(),
2089                 SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
2090             return nullptr;
2091         }
2092         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2093         if (image == nullptr) {
2094             ROSEN_LOGE("JsCanvas::OnDrawImageRect image is nullptr");
2095             return nullptr;
2096         }
2097         m_canvas->DrawImageRect(*image, dstRect, Drawing::SamplingOptions());
2098     } else {
2099         JsSamplingOptions* jsSamplingOptions = nullptr;
2100         GET_UNWRAP_PARAM(ARGC_TWO, jsSamplingOptions); // (optional) arg #2: samplingOptions
2101         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
2102         if (samplingOptions == nullptr) {
2103             ROSEN_LOGE("JsCanvas::OnDrawImageRect get samplingOptions is nullptr");
2104             return nullptr;
2105         }
2106         if (m_canvas->GetDrawingType() == Drawing::DrawingType::RECORDING) {
2107             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(m_canvas);
2108             Drawing::Rect srcRect(0, 0, pixel->GetWidth(), pixel->GetHeight());
2109             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, *samplingOptions.get(),
2110                 SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
2111             return nullptr;
2112         }
2113         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2114         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2115         if (image == nullptr) {
2116             ROSEN_LOGE("JsCanvas::OnDrawImageRect image is nullptr");
2117             return nullptr;
2118         }
2119         m_canvas->DrawImageRect(*image, dstRect, *samplingOptions.get());
2120     }
2121     if (mPixelMap_ != nullptr) {
2122         mPixelMap_->MarkDirty();
2123     }
2124 #endif
2125     return nullptr;
2126 }
2127 
DrawImageRectWithSrc(napi_env env,napi_callback_info info)2128 napi_value JsCanvas::DrawImageRectWithSrc(napi_env env, napi_callback_info info)
2129 {
2130     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2131     return (me != nullptr) ? me->OnDrawImageRectWithSrc(env, info) : nullptr;
2132 }
2133 
2134 #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)2135 static napi_value OnDrawingImageRectWithSrc(napi_env env, napi_value* argv, size_t argc, Canvas& canvas,
2136                                             const std::shared_ptr<Media::PixelMap> pixel,
2137                                             const Rect& srcRect, const Rect& dstRect)
2138 {
2139     if (argc == ARGC_THREE) { // without optional arg #3 (samplingOptions) and arg #4 (constraint):
2140         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2141         if (canvas.GetDrawingType() == Drawing::DrawingType::RECORDING) {
2142             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(&canvas);
2143             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, Drawing::SamplingOptions());
2144             return nullptr;
2145         }
2146         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2147         if (image == nullptr) {
2148             ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc image is nullptr");
2149             return nullptr;
2150         }
2151         canvas.DrawImageRect(*image, srcRect, dstRect, Drawing::SamplingOptions());
2152     } else if (argc == ARGC_FOUR) { // without optional arg #4 (constraint):
2153         JsSamplingOptions* jsSamplingOptions = nullptr;
2154         GET_UNWRAP_PARAM(ARGC_THREE, jsSamplingOptions);
2155         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
2156         if (samplingOptions == nullptr) {
2157             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect samplingOptions parameter.");
2158         }
2159         if (canvas.GetDrawingType() == Drawing::DrawingType::RECORDING) {
2160             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(&canvas);
2161             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect, *samplingOptions.get());
2162             return nullptr;
2163         }
2164         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2165         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2166         if (image == nullptr) {
2167             ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc image is nullptr");
2168             return nullptr;
2169         }
2170         canvas.DrawImageRect(*image, srcRect, dstRect, *samplingOptions.get());
2171     } else if (argc == ARGC_FIVE) {  // with optional arg #3 (samplingOptions) and arg #4 (constraint):
2172         JsSamplingOptions* jsSamplingOptions = nullptr;
2173         GET_UNWRAP_PARAM(ARGC_THREE, jsSamplingOptions);
2174         std::shared_ptr<SamplingOptions> samplingOptions = jsSamplingOptions->GetSamplingOptions();
2175         if (samplingOptions == nullptr) {
2176             return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect samplingOptions parameter.");
2177         }
2178         int32_t constraint = 0;
2179         GET_ENUM_PARAM(ARGC_FOUR,
2180             constraint,
2181             static_cast<int32_t>(SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT),
2182             static_cast<int32_t>(SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT));
2183         if (canvas.GetDrawingType() == Drawing::DrawingType::RECORDING) {
2184             ExtendRecordingCanvas* canvas_ = reinterpret_cast<ExtendRecordingCanvas*>(&canvas);
2185             canvas_->DrawPixelMapRect(pixel, srcRect, dstRect,
2186                 *samplingOptions.get(), static_cast<SrcRectConstraint>(constraint));
2187             return nullptr;
2188         }
2189         DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
2190         std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixel);
2191         if (image == nullptr) {
2192             ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc image is nullptr");
2193             return nullptr;
2194         }
2195         canvas.DrawImageRect(*image, srcRect, dstRect,
2196             *samplingOptions.get(), static_cast<SrcRectConstraint>(constraint));
2197     } else { // argc > 5:
2198         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "More than 5 parameters are not supported");
2199     }
2200     return nullptr;
2201 }
2202 #endif
2203 
OnDrawImageRectWithSrc(napi_env env,napi_callback_info info)2204 napi_value JsCanvas::OnDrawImageRectWithSrc(napi_env env, napi_callback_info info)
2205 {
2206 #ifdef ROSEN_OHOS
2207     if (m_canvas == nullptr) {
2208         ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc canvas is nullptr");
2209         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2210     }
2211 
2212     size_t argc = ARGC_FIVE;
2213     napi_value argv[ARGC_FIVE] = {nullptr};
2214     CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_THREE, ARGC_FIVE);
2215 
2216     PixelMapNapi* pixelMapNapi = nullptr;
2217     GET_UNWRAP_PARAM(ARGC_ZERO, pixelMapNapi); // arg #0: pixelmap/image
2218     auto pixel = pixelMapNapi->GetPixelNapiInner();
2219     if (pixel == nullptr) {
2220         ROSEN_LOGE("JsCanvas::OnDrawImageRectWithSrc pixelmap GetPixelNapiInner is nullptr");
2221         return nullptr;
2222     }
2223 
2224     double ltrb[ARGC_FOUR] = {0};
2225     if (!ConvertFromJsRect(env, argv[ARGC_ONE], ltrb, ARGC_FOUR)) { // arg #1: srcRect
2226         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
2227             "Incorrect rect src parameter type. The type of left, top, right and bottom must be number.");
2228     }
2229     Drawing::Rect srcRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
2230 
2231     if (!ConvertFromJsRect(env, argv[ARGC_TWO], ltrb, ARGC_FOUR)) { // arg #2: dstRect
2232         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
2233             "Incorrect rect dst parameter type. The type of left, top, right and bottom must be number.");
2234     }
2235     Drawing::Rect dstRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
2236 
2237     napi_value result = OnDrawingImageRectWithSrc(env, argv, argc, *m_canvas, pixel, srcRect, dstRect);
2238     if (mPixelMap_ != nullptr) {
2239         mPixelMap_->MarkDirty();
2240     }
2241     return result;
2242 #else
2243     return nullptr;
2244 #endif
2245 }
2246 
ResetMatrix(napi_env env,napi_callback_info info)2247 napi_value JsCanvas::ResetMatrix(napi_env env, napi_callback_info info)
2248 {
2249     JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
2250     return (me != nullptr) ? me->OnResetMatrix(env, info) : nullptr;
2251 }
2252 
OnResetMatrix(napi_env env,napi_callback_info info)2253 napi_value JsCanvas::OnResetMatrix(napi_env env, napi_callback_info info)
2254 {
2255     if (m_canvas == nullptr) {
2256         ROSEN_LOGE("JsCanvas::OnResetMatrix m_canvas is null");
2257         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
2258     }
2259     m_canvas->ResetMatrix();
2260     return nullptr;
2261 }
2262 
2263 } // namespace Drawing
2264 } // namespace OHOS::Rosen
2265