• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "ani_canvas.h"
17 #include "brush_ani/ani_brush.h"
18 #include "effect/color_space.h"
19 #include "pixel_map_taihe_ani.h"
20 #include "image/image.h"
21 #include "pen_ani/ani_pen.h"
22 #include "sampling_options_ani/ani_sampling_options.h"
23 
24 namespace OHOS::Rosen {
25 using namespace Media;
26 #ifdef ROSEN_OHOS
27 namespace {
ColorSpaceToDrawingColorSpace(ColorSpace colorSpace)28 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorSpace colorSpace)
29 {
30     switch (colorSpace) {
31         case ColorSpace::DISPLAY_P3:
32             return Drawing::ColorSpace::CreateRGB(
33                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
34         case ColorSpace::LINEAR_SRGB:
35             return Drawing::ColorSpace::CreateSRGBLinear();
36         case ColorSpace::SRGB:
37             return Drawing::ColorSpace::CreateSRGB();
38         default:
39             return Drawing::ColorSpace::CreateSRGB();
40     }
41 }
42 
PixelFormatToDrawingColorType(PixelFormat pixelFormat)43 static Drawing::ColorType PixelFormatToDrawingColorType(PixelFormat pixelFormat)
44 {
45     switch (pixelFormat) {
46         case PixelFormat::RGB_565:
47             return Drawing::ColorType::COLORTYPE_RGB_565;
48         case PixelFormat::RGBA_8888:
49             return Drawing::ColorType::COLORTYPE_RGBA_8888;
50         case PixelFormat::BGRA_8888:
51             return Drawing::ColorType::COLORTYPE_BGRA_8888;
52         case PixelFormat::ALPHA_8:
53             return Drawing::ColorType::COLORTYPE_ALPHA_8;
54         case PixelFormat::RGBA_F16:
55             return Drawing::ColorType::COLORTYPE_RGBA_F16;
56         case PixelFormat::UNKNOWN:
57         case PixelFormat::ARGB_8888:
58         case PixelFormat::RGB_888:
59         case PixelFormat::NV21:
60         case PixelFormat::NV12:
61         case PixelFormat::CMYK:
62         default:
63             return Drawing::ColorType::COLORTYPE_UNKNOWN;
64     }
65 }
66 
AlphaTypeToDrawingAlphaType(AlphaType alphaType)67 static Drawing::AlphaType AlphaTypeToDrawingAlphaType(AlphaType alphaType)
68 {
69     switch (alphaType) {
70         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
71             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
72         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
73             return Drawing::AlphaType::ALPHATYPE_OPAQUE;
74         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
75             return Drawing::AlphaType::ALPHATYPE_PREMUL;
76         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
77             return Drawing::AlphaType::ALPHATYPE_UNPREMUL;
78         default:
79             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
80     }
81 }
82 
83 struct PixelMapReleaseContext {
PixelMapReleaseContextOHOS::Rosen::__anon0b41d5650111::PixelMapReleaseContext84     explicit PixelMapReleaseContext(std::shared_ptr<PixelMap> pixelMap) : pixelMap_(pixelMap) {}
85 
~PixelMapReleaseContextOHOS::Rosen::__anon0b41d5650111::PixelMapReleaseContext86     ~PixelMapReleaseContext()
87     {
88         pixelMap_ = nullptr;
89     }
90 
91 private:
92     std::shared_ptr<PixelMap> pixelMap_;
93 };
94 
PixelMapReleaseProc(const void *,void * context)95 static void PixelMapReleaseProc(const void* /* pixels */, void* context)
96 {
97     PixelMapReleaseContext* ctx = static_cast<PixelMapReleaseContext*>(context);
98     if (ctx) {
99         delete ctx;
100         ctx = nullptr;
101     }
102 }
103 
ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)104 std::shared_ptr<Drawing::Image> ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)
105 {
106     if (!pixelMap) {
107         ROSEN_LOGE("Drawing_napi::pixelMap fail");
108         return nullptr;
109     }
110     ImageInfo imageInfo;
111     pixelMap->GetImageInfo(imageInfo);
112     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
113         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
114         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
115         ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
116     Drawing::Pixmap imagePixmap(drawingImageInfo,
117         reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowStride());
118     PixelMapReleaseContext* releaseContext = new PixelMapReleaseContext(pixelMap);
119     auto image = Drawing::Image::MakeFromRaster(imagePixmap, PixelMapReleaseProc, releaseContext);
120     if (!image) {
121         ROSEN_LOGE("Drawing_napi :RSPixelMapUtil::ExtractDrawingImage fail");
122         delete releaseContext;
123         releaseContext = nullptr;
124     }
125     return image;
126 }
127 
ExtracetDrawingBitmap(std::shared_ptr<Media::PixelMap> pixelMap,Drawing::Bitmap & bitmap)128 bool ExtracetDrawingBitmap(std::shared_ptr<Media::PixelMap> pixelMap, Drawing::Bitmap& bitmap)
129 {
130     if (!pixelMap) {
131         ROSEN_LOGE("Drawing_napi ::pixelMap fail");
132         return false;
133     }
134     ImageInfo imageInfo;
135     pixelMap->GetImageInfo(imageInfo);
136     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
137         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
138         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
139         ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
140     bitmap.Build(drawingImageInfo, pixelMap->GetRowStride());
141     bitmap.SetPixels(const_cast<void*>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
142     return true;
143 }
144 
DrawingPixelMapMesh(std::shared_ptr<Media::PixelMap> pixelMap,int column,int row,float * vertices,uint32_t * colors,Drawing::Canvas * m_canvas)145 void DrawingPixelMapMesh(std::shared_ptr<Media::PixelMap> pixelMap, int column, int row,
146     float* vertices, uint32_t* colors, Drawing::Canvas* m_canvas)
147 {
148     const int vertCounts = (column + 1) * (row + 1);
149     int32_t size = 6; // triangle * 2
150     const int indexCount = column * row * size;
151     uint32_t flags = Drawing::BuilderFlags::HAS_TEXCOORDS_BUILDER_FLAG;
152     if (colors) {
153         flags |= Drawing::BuilderFlags::HAS_COLORS_BUILDER_FLAG;
154     }
155     Drawing::Vertices::Builder builder(Drawing::VertexMode::TRIANGLES_VERTEXMODE, vertCounts, indexCount, flags);
156     if (memcpy_s(builder.Positions(), vertCounts * sizeof(Drawing::Point),
157         vertices, vertCounts * sizeof(Drawing::Point)) != 0) {
158         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh memcpy points failed");
159         return;
160     }
161     int32_t colorSize = 4; // size of color
162     if (colors && (memcpy_s(builder.Colors(), vertCounts * colorSize, colors, vertCounts * colorSize) != 0)) {
163         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh memcpy colors failed");
164         return;
165     }
166     Drawing::Point* texsPoint = builder.TexCoords();
167     uint16_t* indices = builder.Indices();
168     if (!texsPoint || !indices) {
169         ROSEN_LOGE("DrawingPixelMapMesh: texsPoint or indices is nullptr");
170         return;
171     }
172 
173     const float height = static_cast<float>(pixelMap->GetHeight());
174     const float width = static_cast<float>(pixelMap->GetWidth());
175 
176     if (column == 0 || row == 0) {
177         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh column or row is invalid");
178         return;
179     }
180     const float dy = height / row;
181     const float dx = width / column;
182 
183     Drawing::Point* texsPit = texsPoint;
184     float y = 0;
185     for (int i = 0; i <= row; i++) {
186         if (i == row) {
187             y = height;
188         }
189         float x = 0;
190         for (int j = 0; j < column; j++) {
191             texsPit->Set(x, y);
192             texsPit += 1;
193             x += dx;
194         }
195         texsPit->Set(width, y);
196         texsPit += 1;
197         y += dy;
198     }
199 
200     uint16_t* dexIndices = indices;
201     int indexIndices = 0;
202     for (int i = 0; i < row; i++) {
203         for (int j = 0; j < column; j++) {
204             *dexIndices++ = indexIndices;
205             *dexIndices++ = indexIndices + column + 1;
206             *dexIndices++ = indexIndices + column + 2; // 2 means the third index of the triangle
207 
208             *dexIndices++ = indexIndices;
209             *dexIndices++ = indexIndices + column + 2; // 2 means the third index of the triangle
210             *dexIndices++ = indexIndices + 1;
211 
212             indexIndices += 1;
213         }
214         indexIndices += 1;
215     }
216 
217     if (!m_canvas->GetMutableBrush().IsValid()) {
218         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh paint is invalid");
219         return;
220     }
221     std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixelMap);
222     if (image == nullptr) {
223         ROSEN_LOGE("Drawing_napi::DrawingPixelMapMesh image is nullptr");
224         return;
225     }
226     auto shader = Drawing::ShaderEffect::CreateImageShader(*image,
227         Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, Drawing::SamplingOptions(), Drawing::Matrix());
228     m_canvas->GetMutableBrush().SetShaderEffect(shader);
229     m_canvas->DrawVertices(*builder.Detach(), Drawing::BlendMode::MODULATE);
230 }
231 }
232 #endif
233 
234 namespace Drawing {
235 const char* ANI_CLASS_CANVAS_NAME = "L@ohos/graphics/drawing/drawing/Canvas;";
AniInit(ani_env * env)236 ani_status AniCanvas::AniInit(ani_env *env)
237 {
238     ani_class cls = nullptr;
239     ani_status ret = env->FindClass(ANI_CLASS_CANVAS_NAME, &cls);
240     if (ret != ANI_OK) {
241         ROSEN_LOGE("[ANI] can't find class: %{public}s", ANI_CLASS_CANVAS_NAME);
242         return ANI_NOT_FOUND;
243     }
244 
245     std::array methods = {
246         ani_native_function { "constructorNative", nullptr, reinterpret_cast<void*>(Constructor) },
247         ani_native_function { "drawRect", "L@ohos/graphics/common2D/common2D/Rect;:V",
248             reinterpret_cast<void*>(DrawRectWithRect) },
249         ani_native_function { "drawRect", "DDDD:V", reinterpret_cast<void*>(DrawRect) },
250         ani_native_function { "drawImageRect", nullptr, reinterpret_cast<void*>(DrawImageRect) },
251         ani_native_function { "drawPixelMapMesh", nullptr, reinterpret_cast<void*>(DrawPixelMapMesh) },
252         ani_native_function { "attachPen", nullptr, reinterpret_cast<void*>(AttachPen) },
253         ani_native_function { "attachBrush", nullptr, reinterpret_cast<void*>(AttachBrush) },
254         ani_native_function { "detachPen", nullptr, reinterpret_cast<void*>(DetachPen) },
255         ani_native_function { "detachBrush", nullptr, reinterpret_cast<void*>(DetachBrush) },
256         ani_native_function { "save", nullptr, reinterpret_cast<void*>(Save) },
257         ani_native_function { "saveLayer", nullptr, reinterpret_cast<void*>(SaveLayer) },
258         ani_native_function { "restore", nullptr, reinterpret_cast<void*>(Restore) },
259         ani_native_function { "getSaveCount", nullptr, reinterpret_cast<void*>(GetSaveCount) },
260         ani_native_function { "rotate", nullptr, reinterpret_cast<void*>(Rotate) },
261     };
262 
263     ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
264     if (ret != ANI_OK) {
265         ROSEN_LOGE("[ANI] bind methods fail: %{public}s", ANI_CLASS_CANVAS_NAME);
266         return ANI_NOT_FOUND;
267     }
268 
269     return ANI_OK;
270 }
271 
NotifyDirty()272 void AniCanvas::NotifyDirty()
273 {
274 #ifdef ROSEN_OHOS
275     if (mPixelMap_ != nullptr) {
276         mPixelMap_->MarkDirty();
277     }
278 #endif
279 }
280 
Constructor(ani_env * env,ani_object obj,ani_object pixelmapObj)281 void AniCanvas::Constructor(ani_env* env, ani_object obj, ani_object pixelmapObj)
282 {
283     if (pixelmapObj == nullptr) {
284         AniCanvas *aniCanvas = new AniCanvas();
285         if (ANI_OK != env->Object_SetFieldByName_Long(obj, NATIVE_OBJ, reinterpret_cast<ani_long>(aniCanvas))) {
286             ROSEN_LOGE("AniCanvas::Constructor failed create AniCanvas with nullptr");
287             delete aniCanvas;
288         }
289         return;
290     }
291 #ifdef ROSEN_OHOS
292     std::shared_ptr<PixelMap> pixelMap = PixelMapTaiheAni::GetNativePixelMap(env, pixelmapObj);
293     if (!pixelMap) {
294         ROSEN_LOGE("AniCanvas::Constructor get pixelMap failed");
295         AniThrowError(env, "Invalid params.");
296         return;
297     }
298     Bitmap bitmap;
299     if (!ExtracetDrawingBitmap(pixelMap, bitmap)) {
300         return;
301     }
302 
303     Canvas* canvas = new Canvas();
304     canvas->Bind(bitmap);
305     AniCanvas *aniCanvas = new AniCanvas(canvas, true);
306     aniCanvas->mPixelMap_ = pixelMap;
307 
308     if (ANI_OK != env->Object_SetFieldByName_Long(obj, NATIVE_OBJ, reinterpret_cast<ani_long>(aniCanvas))) {
309         ROSEN_LOGE("AniCanvas::Constructor failed create aniCanvas");
310         delete aniCanvas;
311         return;
312     }
313 #endif
314 }
315 
DrawRect(ani_env * env,ani_object obj,ani_double left,ani_double top,ani_double right,ani_double bottom)316 void AniCanvas::DrawRect(ani_env* env, ani_object obj,
317     ani_double left, ani_double top, ani_double right, ani_double bottom)
318 {
319     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
320     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
321         AniThrowError(env, "Invalid params.");
322         return;
323     }
324 
325     Drawing::Rect drawingRect = Drawing::Rect(left, top, right, bottom);
326     Canvas* canvas = aniCanvas->GetCanvas();
327     canvas->DrawRect(drawingRect);
328 
329     aniCanvas->NotifyDirty();
330 }
331 
DrawRectWithRect(ani_env * env,ani_object obj,ani_object aniRect)332 void AniCanvas::DrawRectWithRect(ani_env* env, ani_object obj, ani_object aniRect)
333 {
334     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
335     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
336         AniThrowError(env, "Invalid params.");
337         return;
338     }
339 
340     Drawing::Rect drawingRect;
341     if (!GetRectFromAniRectObj(env, aniRect, drawingRect)) {
342         ROSEN_LOGE("AniCanvas::DrawRectWithRect get drawingRect failed");
343         AniThrowError(env, "Invalid params.");
344         return;
345     }
346     Canvas* canvas = aniCanvas->GetCanvas();
347     canvas->DrawRect(drawingRect);
348 
349     aniCanvas->NotifyDirty();
350 }
351 
DrawImageRect(ani_env * env,ani_object obj,ani_object pixelmapObj,ani_object rectObj,ani_object samplingOptionsObj)352 void AniCanvas::DrawImageRect(ani_env* env, ani_object obj,
353     ani_object pixelmapObj, ani_object rectObj, ani_object samplingOptionsObj)
354 {
355     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
356     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
357         AniThrowError(env, "Invalid params.");
358         return;
359     }
360 #ifdef ROSEN_OHOS
361     std::shared_ptr<PixelMap> pixelMap = PixelMapTaiheAni::GetNativePixelMap(env, pixelmapObj);
362     if (!pixelMap) {
363         ROSEN_LOGE("AniCanvas::DrawImageRect get pixelMap failed");
364         AniThrowError(env, "Invalid params.");
365         return;
366     }
367     Drawing::Rect drawingRect;
368     if (!GetRectFromAniRectObj(env, rectObj, drawingRect)) {
369         ROSEN_LOGE("AniCanvas::DrawImageRect get drawingRect failed");
370         AniThrowError(env, "Invalid params.");
371         return;
372     }
373 
374     AniSamplingOptions* aniSamplingOptions = nullptr;
375     ani_boolean isUndefined;
376     env->Reference_IsUndefined(samplingOptionsObj, &isUndefined);
377     if (!isUndefined) {
378         aniSamplingOptions = GetNativeFromObj<AniSamplingOptions>(env, samplingOptionsObj);
379         if (aniSamplingOptions == nullptr || aniSamplingOptions->GetSamplingOptions() == nullptr) {
380             AniThrowError(env, "Invalid params.");
381             return;
382         }
383     }
384     aniCanvas->DrawImageRectInner(pixelMap, drawingRect, aniSamplingOptions);
385     aniCanvas->NotifyDirty();
386 #endif
387 }
388 
389 #ifdef ROSEN_OHOS
DrawImageRectInner(std::shared_ptr<Media::PixelMap> pixelmap,Drawing::Rect & rect,AniSamplingOptions * samplingOptions)390 void AniCanvas::DrawImageRectInner(std::shared_ptr<Media::PixelMap> pixelmap,
391     Drawing::Rect& rect, AniSamplingOptions* samplingOptions)
392 {
393     if (!m_canvas) {
394         return;
395     }
396     std::shared_ptr<Drawing::Image> image = ExtractDrawingImage(pixelmap);
397     if (image == nullptr) {
398         ROSEN_LOGE("AniCanvas::DrawImageRectInner image is nullptr");
399         return;
400     }
401     if (samplingOptions && samplingOptions->GetSamplingOptions()) {
402         m_canvas->DrawImageRect(*image, rect, *samplingOptions->GetSamplingOptions());
403     } else {
404         m_canvas->DrawImageRect(*image, rect, Drawing::SamplingOptions());
405     }
406 }
407 #endif
408 
DrawPixelMapMesh(ani_env * env,ani_object obj,ani_object pixelmapObj,ani_double aniMeshWidth,ani_double aniMeshHeight,ani_object verticesObj,ani_double aniVertOffset,ani_object colorsObj,ani_double aniColorOffset)409 void AniCanvas::DrawPixelMapMesh(ani_env* env, ani_object obj,
410     ani_object pixelmapObj, ani_double aniMeshWidth, ani_double aniMeshHeight,
411     ani_object verticesObj, ani_double aniVertOffset, ani_object colorsObj, ani_double aniColorOffset)
412 {
413     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
414     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
415         AniThrowError(env, "Invalid params.");
416         return;
417     }
418 #ifdef ROSEN_OHOS
419     std::shared_ptr<PixelMap> pixelMap = PixelMapTaiheAni::GetNativePixelMap(env, pixelmapObj);
420     if (!pixelMap) {
421         ROSEN_LOGE("AniCanvas::DrawImageRect get pixelMap failed");
422         AniThrowError(env, "Invalid params.");
423         return;
424     }
425 
426     int32_t column = aniMeshWidth;
427     int32_t row = aniMeshHeight;
428     int32_t vertOffset = aniVertOffset;
429     int32_t colorOffset = aniColorOffset;
430     if (column == 0 || row == 0) {
431         ROSEN_LOGE("AniCanvas::DrawPixelMapMesh column or row is invalid");
432         AniThrowError(env, "Invalid column or row params.");
433         return;
434     }
435 
436     ani_double aniLength;
437     if (ANI_OK != env->Object_GetPropertyByName_Double(verticesObj, "length", &aniLength)) {
438         AniThrowError(env, "Invalid params.");
439         return;
440     }
441 
442     uint32_t verticesSize = aniLength;
443     int64_t tempVerticesSize = ((column + 1) * (row + 1) + vertOffset) * 2; // x and y two coordinates
444     if (verticesSize != tempVerticesSize) {
445         ROSEN_LOGE("AniCanvas::DrawPixelMapMesh vertices are invalid");
446         AniThrowError(env, "Incorrect parameter3 type.");
447         return;
448     }
449 
450     auto vertices = new (std::nothrow) float[verticesSize];
451     if (!vertices) {
452         ROSEN_LOGE("AniCanvas::DrawPixelMapMesh create array with size of vertices failed");
453         AniThrowError(env, "Size of vertices exceed memory limit.");
454         return;
455     }
456     for (uint32_t i = 0; i < verticesSize; i++) {
457         ani_double vertex;
458         ani_ref vertexRef;
459         if (ANI_OK !=  env->Object_CallMethodByName_Ref(
460             verticesObj, "$_get", "I:Lstd/core/Object;", &vertexRef, (ani_int)i) ||
461             ANI_OK !=  env->Object_CallMethodByName_Double(
462                 static_cast<ani_object>(vertexRef), "unboxed", ":D", &vertex)) {
463             delete []vertices;
464             AniThrowError(env, "Incorrect DrawPixelMapMesh parameter vertex type.");
465             return;
466         }
467         vertices[i] = vertex;
468     }
469 
470     float* verticesMesh = verticesSize ? (vertices + vertOffset * 2) : nullptr; // offset two coordinates
471 
472     if (ANI_OK != env->Object_GetPropertyByName_Double(colorsObj, "length", &aniLength)) {
473         delete []vertices;
474         AniThrowError(env, "Invalid params.");
475         return;
476     }
477     uint32_t colorsSize = aniLength;
478     int64_t tempColorsSize = (column + 1) * (row + 1) + colorOffset;
479     if (colorsSize != 0 && colorsSize != tempColorsSize) {
480         ROSEN_LOGE("AniCanvas::DrawPixelMapMesh colors are invalid");
481         delete []vertices;
482         AniThrowError(env, "Incorrect parameter5 type");
483         return;
484     }
485 
486     if (colorsSize == 0) {
487         DrawingPixelMapMesh(pixelMap, column, row, verticesMesh, nullptr, aniCanvas->GetCanvas());
488         aniCanvas->NotifyDirty();
489         delete []vertices;
490         return;
491     }
492 
493     auto colors = new (std::nothrow) uint32_t[colorsSize];
494     if (!colors) {
495         ROSEN_LOGE("AniCanvas::DrawPixelMapMesh create array with size of colors failed");
496         delete []vertices;
497         AniThrowError(env, "Size of colors exceed memory limit.");
498         return;
499     }
500     for (uint32_t i = 0; i < colorsSize; i++) {
501         ani_double color;
502         ani_ref colorRef;
503         if (ANI_OK !=  env->Object_CallMethodByName_Ref(
504             colorsObj, "$_get", "I:Lstd/core/Object;", &colorRef, (ani_int)i) ||
505             ANI_OK !=  env->Object_CallMethodByName_Double(
506                 static_cast<ani_object>(colorRef), "unboxed", ":D", &color)) {
507             delete []vertices;
508             delete []colors;
509             AniThrowError(env, "Incorrect DrawPixelMapMesh parameter color type.");
510             return;
511         }
512         colors[i] = color;
513     }
514     uint32_t* colorsMesh = colors + colorOffset;
515     DrawingPixelMapMesh(pixelMap, column, row, verticesMesh, colorsMesh, aniCanvas->GetCanvas());
516     aniCanvas->NotifyDirty();
517     delete []vertices;
518     delete []colors;
519 #endif
520 }
521 
AttachBrush(ani_env * env,ani_object obj,ani_object brushObj)522 void AniCanvas::AttachBrush(ani_env* env, ani_object obj, ani_object brushObj)
523 {
524     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
525     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
526         AniThrowError(env, "Invalid params.");
527         return;
528     }
529 
530     auto aniBrush = GetNativeFromObj<AniBrush>(env, brushObj);
531     if (aniBrush == nullptr) {
532         AniThrowError(env, "Invalid params.");
533         return;
534     }
535     Canvas* canvas = aniCanvas->GetCanvas();
536     canvas->AttachBrush(aniBrush->GetBrush());
537 }
538 
AttachPen(ani_env * env,ani_object obj,ani_object penObj)539 void AniCanvas::AttachPen(ani_env* env, ani_object obj, ani_object penObj)
540 {
541     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
542     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
543         AniThrowError(env, "Invalid params.");
544         return;
545     }
546 
547     auto aniPen = GetNativeFromObj<AniPen>(env, penObj);
548     if (aniPen == nullptr) {
549         AniThrowError(env, "Invalid params.");
550         return;
551     }
552     Canvas* canvas = aniCanvas->GetCanvas();
553     canvas->AttachPen(aniPen->GetPen());
554 }
555 
DetachBrush(ani_env * env,ani_object obj)556 void AniCanvas::DetachBrush(ani_env* env, ani_object obj)
557 {
558     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
559     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
560         AniThrowError(env, "Invalid params.");
561         return;
562     }
563     Canvas* canvas = aniCanvas->GetCanvas();
564     canvas->DetachBrush();
565 }
566 
DetachPen(ani_env * env,ani_object obj)567 void AniCanvas::DetachPen(ani_env* env, ani_object obj)
568 {
569     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
570     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
571         AniThrowError(env, "Invalid params.");
572         return;
573     }
574     Canvas* canvas = aniCanvas->GetCanvas();
575     canvas->DetachPen();
576 }
577 
Save(ani_env * env,ani_object obj)578 ani_double AniCanvas::Save(ani_env* env, ani_object obj)
579 {
580     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
581     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
582         AniThrowError(env, "Invalid params.");
583         return -1;
584     }
585     Canvas* canvas = aniCanvas->GetCanvas();
586     return canvas->Save();
587 }
588 
589 
SaveLayer(ani_env * env,ani_object obj,ani_object rectObj,ani_object brushObj)590 ani_double AniCanvas::SaveLayer(ani_env* env, ani_object obj, ani_object rectObj, ani_object brushObj)
591 {
592     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
593     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
594         AniThrowError(env, "Invalid params.");
595         return -1;
596     }
597     Canvas* canvas = aniCanvas->GetCanvas();
598 
599     ani_boolean rectIsUndefined = ANI_TRUE;
600     env->Reference_IsUndefined(rectObj, &rectIsUndefined);
601     if (rectIsUndefined) {
602         ani_double ret = canvas->GetSaveCount();
603         canvas->SaveLayer(SaveLayerOps());
604         return ret;
605     }
606 
607     ani_boolean brushIsUndefined = ANI_TRUE;
608     env->Reference_IsUndefined(brushObj, &brushIsUndefined);
609 
610     Drawing::Rect drawingRect;
611     Drawing::Rect* drawingRectPtr = GetRectFromAniRectObj(env, rectObj, drawingRect) ?  &drawingRect : nullptr;
612 
613     if (brushIsUndefined) {
614         ani_double ret = canvas->GetSaveCount();
615         canvas->SaveLayer(SaveLayerOps(drawingRectPtr, nullptr));
616         return ret;
617     }
618 
619     Drawing::AniBrush* aniBrush = GetNativeFromObj<AniBrush>(env, brushObj);
620     Drawing::Brush* drawingBrushPtr = aniBrush ? &aniBrush->GetBrush() : nullptr;
621 
622     ani_double ret = canvas->GetSaveCount();
623     SaveLayerOps saveLayerOps = SaveLayerOps(drawingRectPtr, drawingBrushPtr);
624     canvas->SaveLayer(saveLayerOps);
625     return ret;
626 }
627 
Restore(ani_env * env,ani_object obj)628 void AniCanvas::Restore(ani_env* env, ani_object obj)
629 {
630     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
631     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
632         AniThrowError(env, "Invalid params.");
633         return;
634     }
635     Canvas* canvas = aniCanvas->GetCanvas();
636     canvas->Restore();
637 }
638 
GetSaveCount(ani_env * env,ani_object obj)639 ani_double AniCanvas::GetSaveCount(ani_env* env, ani_object obj)
640 {
641     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
642     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
643         AniThrowError(env, "Invalid params.");
644         return -1;
645     }
646     Canvas* canvas = aniCanvas->GetCanvas();
647     return canvas->GetSaveCount();
648 }
649 
Rotate(ani_env * env,ani_object obj,ani_double degrees,ani_double sx,ani_double sy)650 void AniCanvas::Rotate(ani_env* env, ani_object obj, ani_double degrees, ani_double sx, ani_double sy)
651 {
652     auto aniCanvas = GetNativeFromObj<AniCanvas>(env, obj);
653     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
654         AniThrowError(env, "Invalid params.");
655         return;
656     }
657     Canvas* canvas = aniCanvas->GetCanvas();
658     canvas->Rotate(degrees, sx, sy);
659 }
660 
GetCanvas()661 Canvas* AniCanvas::GetCanvas()
662 {
663     return m_canvas;
664 }
665 
CreateAniCanvas(ani_env * env,Canvas * canvas)666 ani_object AniCanvas::CreateAniCanvas(ani_env* env, Canvas* canvas)
667 {
668     if (canvas == nullptr) {
669         ROSEN_LOGE("CreateAniCanvas failed, canvas is nullptr!");
670         return CreateAniUndefined(env);
671     }
672 
673     auto aniCanvas = new AniCanvas(canvas);
674     ani_object aniObj = CreateAniObject(env, ANI_CLASS_CANVAS_NAME, nullptr, nullptr);
675     if (ANI_OK != env->Object_SetFieldByName_Long(aniObj,
676         NATIVE_OBJ, reinterpret_cast<ani_long>(aniCanvas))) {
677         ROSEN_LOGE("aniCanvas failed cause by Object_SetFieldByName_Long");
678         delete aniCanvas;
679         return CreateAniUndefined(env);
680     }
681     return aniObj;
682 }
683 
~AniCanvas()684 AniCanvas::~AniCanvas()
685 {
686     if (owned_) {
687         delete m_canvas;
688     }
689     m_canvas = nullptr;
690 }
691 } // namespace Drawing
692 } // namespace OHOS::Rosen
693