• 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 "bridge/arkts_frontend/ani_graphics_module.h"
17 
18 #include <ani.h>
19 
20 // #if !defined(PREVIEW)
21 // #include "canvas_ani/ani_canvas.h"
22 // #endif
23 
24 #include "core/components_ng/pattern/render_node/render_node_pattern.h"
25 #include "core/interfaces/native/implementation/render_node_peer_impl.h"
26 #include "core/pipeline/pipeline_base.h"
27 
28 namespace OHOS::Ace::Framework {
29 namespace {
CreateSizeObject(ani_env * env,const NG::DrawingContext & context)30 ani_object CreateSizeObject(ani_env* env, const NG::DrawingContext& context)
31 {
32     ani_status status;
33     ani_class sizeClass;
34     if ((status = env->FindClass("Larkui/Graphics/SizeInternal;", &sizeClass)) != ANI_OK) {
35         LOGE("FindClass Size failed, %{public}d", status);
36         return nullptr;
37     }
38     ani_method sizeCtor;
39     if ((status = env->Class_FindMethod(sizeClass, "<ctor>", "DD:V", &sizeCtor)) != ANI_OK) {
40         LOGE("Class_FindMethod sizeClass ctor failed, %{public}d", status);
41         return nullptr;
42     }
43     ani_object sizeObject;
44     ani_float width = PipelineBase::Px2VpWithCurrentDensity(context.height);
45     ani_float height = PipelineBase::Px2VpWithCurrentDensity(context.width);
46     if ((status = env->Object_New(sizeClass, sizeCtor, &sizeObject, width, height)) != ANI_OK) {
47         LOGE("New Size object failed, %{public}d", status);
48         return nullptr;
49     }
50     return sizeObject;
51 }
52 
CreateSizeInPixelObject(ani_env * env,const NG::DrawingContext & context)53 ani_object CreateSizeInPixelObject(ani_env* env, const NG::DrawingContext& context)
54 {
55     ani_status status;
56     ani_class sizeInPixelClass;
57     if ((status = env->FindClass("Larkui/Graphics/SizeInternal;", &sizeInPixelClass)) != ANI_OK) {
58         LOGE("FindClass Size failed, %{public}d", status);
59         return nullptr;
60     }
61     ani_method sizeInPixelCtor;
62     if ((status = env->Class_FindMethod(sizeInPixelClass, "<ctor>", "DD:V", &sizeInPixelCtor)) != ANI_OK) {
63         LOGE("Class_FindMethod sizeInPixelClass ctor failed, %{public}d", status);
64         return nullptr;
65     }
66     ani_object sizeInPixelObject;
67     ani_float widthInPixel = context.width;
68     ani_float heightInPixel = context.height;
69     if ((status = env->Object_New(
70              sizeInPixelClass, sizeInPixelCtor, &sizeInPixelObject, widthInPixel, heightInPixel)) != ANI_OK) {
71         LOGE("New SizeInPixel object failed, %{public}d", status);
72         return nullptr;
73     }
74     return sizeInPixelObject;
75 }
76 } // namespace
77 
CreateDrawingContext(ani_env * env,const NG::DrawingContext & context)78 ani_object AniGraphicsModule::CreateDrawingContext(ani_env* env, const NG::DrawingContext& context)
79 {
80     ani_status status;
81     ani_object result = nullptr;
82 
83     // DrawContext object
84     ani_class drawContextClass;
85     if ((status = env->FindClass("Larkui/Graphics/DrawContext;", &drawContextClass)) != ANI_OK) {
86         LOGE("FindClass DrawContext failed, %{public}d", status);
87         return nullptr;
88     }
89     ani_method drawContextCtor;
90     if ((status = env->Class_FindMethod(drawContextClass, "<ctor>", ":V", &drawContextCtor)) != ANI_OK) {
91         LOGE("Class_FindMethod drawContextClass ctor failed, %{public}d", status);
92         return nullptr;
93     }
94     if ((status = env->Object_New(drawContextClass, drawContextCtor, &result)) != ANI_OK) {
95         LOGE("New DrawContext object failed, %{public}d", status);
96         return nullptr;
97     }
98 
99     // Size object
100     ani_object sizeObject = CreateSizeObject(env, context);
101     env->Object_SetPropertyByName_Ref(result, "size_", (ani_ref)sizeObject);
102 
103     // sizeInPixel Object
104     ani_object sizeInPixelObject = CreateSizeInPixelObject(env, context);
105     env->Object_SetPropertyByName_Ref(result, "sizeInPixel_", (ani_ref)sizeInPixelObject);
106 
107     // canvas Object
108 #if !defined(PREVIEW)
109     // ani_object aniCanvas = OHOS::Rosen::Drawing::AniCanvas::CreateAniCanvas(env, &context.canvas);
110     // if (!aniCanvas) {
111     //     LOGE("Create AniCanvas failed !");
112     // }
113     // env->Object_SetPropertyByName_Ref(result, "canvas_", (ani_ref)aniCanvas);
114 #endif
115 
116     return result;
117 }
118 
SetDrawCallback(ani_env * env,ani_long ptr,ani_fn_object fnObj)119 void AniGraphicsModule::SetDrawCallback(ani_env* env, ani_long ptr, ani_fn_object fnObj)
120 {
121     if (fnObj == nullptr) {
122         LOGE("Draw callback is undefined.");
123         return;
124     }
125     ani_ref fnObjGlobalRef = nullptr;
126     env->GlobalReference_Create(reinterpret_cast<ani_ref>(fnObj), &fnObjGlobalRef);
127     auto drawCallbackFunc = [env, fnObjGlobalRef](const NG::DrawingContext& context) -> void {
128         auto drawingContext = CreateDrawingContext(env, context);
129         if (!drawingContext) {
130             LOGW("Create drawing context failed !");
131             return;
132         }
133         std::vector<ani_ref> params;
134         params.emplace_back((ani_ref)drawingContext);
135         ani_ref fnReturnVal;
136         env->FunctionalObject_Call(
137             reinterpret_cast<ani_fn_object>(fnObjGlobalRef), params.size(), params.data(), &fnReturnVal);
138     };
139 
140     auto* renderNodePeer = reinterpret_cast<RenderNodePeer*>(ptr);
141     CHECK_NULL_VOID(renderNodePeer);
142     auto renderNode = renderNodePeer->GetFrameNode();
143     auto pattern = renderNode->GetPattern<NG::RenderNodePattern>();
144     if (pattern) {
145         pattern->SetDrawCallback(drawCallbackFunc);
146     }
147 }
148 
Invalidate(ani_env * env,ani_long ptr)149 void AniGraphicsModule::Invalidate(ani_env* env, ani_long ptr)
150 {
151     auto* frameNode = reinterpret_cast<NG::FrameNode*>(ptr);
152     CHECK_NULL_VOID(frameNode);
153     const auto& extensionHandler = frameNode->GetExtensionHandler();
154     if (extensionHandler) {
155         extensionHandler->InvalidateRender();
156     } else {
157         frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER);
158     }
159 }
160 
SetDrawModifier(ani_env * env,ani_long ptr,ani_object drawModifierObj)161 void AniGraphicsModule::SetDrawModifier(ani_env* env, ani_long ptr, ani_object drawModifierObj)
162 {
163     if (drawModifierObj == nullptr) {
164         // drawModifierObj should not be nullptr;
165         LOGF_ABORT("DrawModifier is undefined.");
166     }
167     ani_ref modifier;
168     env->GlobalReference_Create(reinterpret_cast<ani_ref>(drawModifierObj), &modifier);
169     auto drawBehindFunc = [env, object = modifier](const NG::DrawingContext& context) {
170         auto drawingContext = Framework::AniGraphicsModule::CreateDrawingContext(env, context);
171         if (!drawingContext) {
172             return;
173         }
174         env->Object_CallMethodByName_Void(
175             reinterpret_cast<ani_fn_object>(object), "drawBehind", "Larkui/Graphics/DrawContext;:V", drawingContext);
176     };
177     auto contentModifier = [env, object = modifier](const NG::DrawingContext& context) {
178         auto drawingContext = Framework::AniGraphicsModule::CreateDrawingContext(env, context);
179         if (!drawingContext) {
180             return;
181         }
182         env->Object_CallMethodByName_Void(
183             reinterpret_cast<ani_fn_object>(object), "drawContent", "Larkui/Graphics/DrawContext;:V", drawingContext);
184     };
185     auto frontModifier = [env, object = modifier](const NG::DrawingContext& context) {
186         auto drawingContext = Framework::AniGraphicsModule::CreateDrawingContext(env, context);
187         if (!drawingContext) {
188             return;
189         }
190         env->Object_CallMethodByName_Void(
191             reinterpret_cast<ani_fn_object>(object), "drawFront", "Larkui/Graphics/DrawContext;:V", drawingContext);
192     };
193     auto* frameNode = reinterpret_cast<NG::FrameNode*>(ptr);
194     CHECK_NULL_VOID(frameNode && frameNode->IsSupportDrawModifier());
195     RefPtr<NG::DrawModifier> drawModifier = AceType::MakeRefPtr<NG::DrawModifier>();
196     drawModifier->drawBehindFunc = drawBehindFunc;
197     drawModifier->drawContentFunc = contentModifier;
198     drawModifier->drawFrontFunc = frontModifier;
199     frameNode->SetDrawModifier(drawModifier);
200     if (frameNode) {
201         const auto& extensionHandler = frameNode->GetExtensionHandler();
202         if (extensionHandler) {
203             extensionHandler->InvalidateRender();
204         } else {
205             frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER);
206         }
207     }
208 }
209 } // namespace OHOS::Ace::Framework
210