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