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 "core/interfaces/native/node/extension_companion_node.h"
17 
18 #include "core/interfaces/arkoala/arkoala_api.h"
19 #include "core/interfaces/native/node/node_api.h"
20 #include "core/interfaces/native/node/view_model.h"
21 
22 namespace {
23 
24 constexpr int NUM_0 = 0;
25 constexpr int NUM_1 = 1;
26 constexpr int NUM_2 = 2;
27 constexpr int NUM_3 = 3;
28 constexpr int NUM_4 = 4;
29 constexpr int NUM_5 = 5;
30 constexpr int NUM_32 = 32;
31 
32 } // namespace
33 
34 namespace OHOS::Ace::NG {
35 
36 const std::vector<ArkUIAPINodeFlags> NODE_FLAGS = { ArkUIAPINodeFlags::CUSTOM_MEASURE, ArkUIAPINodeFlags::CUSTOM_LAYOUT,
37     ArkUIAPINodeFlags::CUSTOM_DRAW, ArkUIAPINodeFlags::CUSTOM_FOREGROUND_DRAW, ArkUIAPINodeFlags::CUSTOM_OVERLAY_DRAW };
38 
GetCanvas()39 ArkUICanvasHandle ExtensionCompanionNode::GetCanvas()
40 {
41     return reinterpret_cast<ArkUICanvasHandle>(0x123456789aLL);
42 }
43 
Arg(ArkUI_Float32 f32)44 ArkUIEventCallbackArg ExtensionCompanionNode::Arg(ArkUI_Float32 f32)
45 {
46     ArkUIEventCallbackArg result;
47     result.f32 = f32;
48     return result;
49 }
50 
Arg(ArkUI_Int32 i32)51 ArkUIEventCallbackArg ExtensionCompanionNode::Arg(ArkUI_Int32 i32)
52 {
53     ArkUIEventCallbackArg result;
54     result.i32 = i32;
55     return result;
56 }
57 
GetPeerId() const58 ArkUI_Int32 ExtensionCompanionNode::GetPeerId() const
59 {
60     return peerId_;
61 }
62 
GetCallbackId() const63 ArkUI_Int32 ExtensionCompanionNode::GetCallbackId() const
64 {
65     return customCallbackId_;
66 }
67 
SetCallbackId(ArkUIVMContext context,int id)68 void ExtensionCompanionNode::SetCallbackId(ArkUIVMContext context, int id)
69 {
70     context_ = context;
71     customCallbackId_ = id;
72 }
73 
SetExtraParam(ArkUI_Int32 type,void * extraParam)74 void ExtensionCompanionNode::SetExtraParam(ArkUI_Int32 type, void* extraParam)
75 {
76     for (const auto& flag : NODE_FLAGS) {
77         if (static_cast<uint32_t>(type) & flag) {
78             auto it = extraParamMap_.find(flag);
79             if (it != extraParamMap_.end()) {
80                 it->second = extraParam;
81             } else {
82                 extraParamMap_.emplace(flag, extraParam);
83             }
84         }
85     }
86 }
87 
GetExtraParam(ArkUI_Int32 type)88 ArkUI_Int64 ExtensionCompanionNode::GetExtraParam(ArkUI_Int32 type)
89 {
90     auto it = extraParamMap_.find(type);
91     if (it != extraParamMap_.end()) {
92         return reinterpret_cast<ArkUI_Int64>(it->second);
93     }
94     return reinterpret_cast<ArkUI_Int64>(nullptr);
95 }
96 
EraseExtraParam(ArkUI_Int32 type)97 void ExtensionCompanionNode::EraseExtraParam(ArkUI_Int32 type)
98 {
99     for (const auto& flag : NODE_FLAGS) {
100         if (static_cast<uint32_t>(type) & flag) {
101             auto it = extraParamMap_.find(type);
102             if (it != extraParamMap_.end()) {
103                 extraParamMap_.erase(it);
104             }
105         }
106     }
107 }
108 
OnMeasure(const ExtensionLayoutConstraint & layoutConstraint)109 void ExtensionCompanionNode::OnMeasure(const ExtensionLayoutConstraint& layoutConstraint)
110 {
111     if (flags_ & ArkUIAPINodeFlags::CUSTOM_MEASURE) {
112         // call extension logic to manager side.
113         ArkUICustomNodeEvent event;
114         event.kind = ArkUIAPINodeFlags::CUSTOM_MEASURE;
115         event.extraParam = GetExtraParam(static_cast<ArkUI_Int32>(ArkUIAPINodeFlags::CUSTOM_MEASURE));
116         event.data[NUM_0] = layoutConstraint.minWidth;
117         event.data[NUM_1] = layoutConstraint.minHeight;
118         event.data[NUM_2] = layoutConstraint.maxWidth;
119         event.data[NUM_3] = layoutConstraint.maxHeight;
120         event.data[NUM_4] = layoutConstraint.parentIdealWidth;
121         event.data[NUM_5] = layoutConstraint.parentIdealHeight;
122         SendArkUIAsyncCustomEvent(&event);
123     } else {
124         // call origin measure.
125         InnerMeasure(layoutConstraint);
126     }
127 }
128 
OnLayout(int32_t width,int32_t height,int32_t positionX,int32_t positionY)129 void ExtensionCompanionNode::OnLayout(int32_t width, int32_t height, int32_t positionX, int32_t positionY)
130 {
131     if (flags_ & ArkUIAPINodeFlags::CUSTOM_LAYOUT) {
132         ArkUICustomNodeEvent event;
133         event.kind = ArkUIAPINodeFlags::CUSTOM_LAYOUT;
134         event.extraParam = GetExtraParam(static_cast<ArkUI_Int32>(ArkUIAPINodeFlags::CUSTOM_LAYOUT));
135         event.data[NUM_0] = positionX;
136         event.data[NUM_1] = positionY;
137         event.data[NUM_2] = width;
138         event.data[NUM_3] = height;
139         SendArkUIAsyncCustomEvent(&event);
140     } else {
141         InnerLayout(width, height, positionX, positionY);
142     }
143 }
144 
OnDraw(DrawingContext & context)145 void ExtensionCompanionNode::OnDraw(DrawingContext& context)
146 {
147     if (flags_ & ArkUIAPINodeFlags::CUSTOM_DRAW) {
148         // call extension logic to manager side.
149         auto canvas = reinterpret_cast<uintptr_t>(&context.canvas);
150         ArkUICustomNodeEvent event;
151         event.kind = ArkUIAPINodeFlags::CUSTOM_DRAW;
152         event.extraParam = GetExtraParam(static_cast<ArkUI_Int32>(ArkUIAPINodeFlags::CUSTOM_DRAW));
153         event.data[NUM_0] = (ArkUI_Int32)(canvas & 0xffffffff);
154         event.data[NUM_1] =
155             (ArkUI_Int32)((static_cast<uint64_t>(canvas) >> NUM_32) & 0xffffffff);
156         event.data[NUM_2] = context.width;
157         event.data[NUM_3] = context.height;
158         event.canvas = reinterpret_cast<intptr_t>(&context.canvas);
159         SendArkUIAsyncCustomEvent(&event);
160     } else {
161         InnerDraw(context);
162     }
163 }
164 
OnForegroundDraw(DrawingContext & context)165 void ExtensionCompanionNode::OnForegroundDraw(DrawingContext& context)
166 {
167     if (flags_ & ArkUIAPINodeFlags::CUSTOM_FOREGROUND_DRAW) {
168         // call extension logic to manager side.
169         auto canvas = reinterpret_cast<uintptr_t>(&context.canvas);
170         ArkUICustomNodeEvent event;
171         event.kind = ArkUIAPINodeFlags::CUSTOM_FOREGROUND_DRAW;
172         event.extraParam = GetExtraParam(static_cast<ArkUI_Int32>(ArkUIAPINodeFlags::CUSTOM_FOREGROUND_DRAW));
173         event.data[NUM_0] = (ArkUI_Int32)(canvas & 0xffffffff);
174         event.data[NUM_1] =
175             (ArkUI_Int32)((static_cast<uint64_t>(canvas) >> NUM_32) & 0xffffffff);
176         event.data[NUM_2] = context.width;
177         event.data[NUM_3] = context.height;
178         event.canvas = reinterpret_cast<intptr_t>(&context.canvas);
179         SendArkUIAsyncCustomEvent(&event);
180     } else {
181         InnerForegroundDraw(context);
182     }
183 }
184 
OnOverlayDraw(DrawingContext & context)185 void ExtensionCompanionNode::OnOverlayDraw(DrawingContext& context)
186 {
187     if (flags_ & ArkUIAPINodeFlags::CUSTOM_OVERLAY_DRAW) {
188         // call extension logic to manager side.
189         auto canvas = reinterpret_cast<uintptr_t>(&context.canvas);
190         ArkUICustomNodeEvent event;
191         event.kind = ArkUIAPINodeFlags::CUSTOM_OVERLAY_DRAW;
192         event.extraParam = GetExtraParam(static_cast<ArkUI_Int32>(ArkUIAPINodeFlags::CUSTOM_OVERLAY_DRAW));
193         event.data[NUM_0] = (ArkUI_Int32)(canvas & 0xffffffff);
194         event.data[NUM_1] =
195             (ArkUI_Int32)((static_cast<uint64_t>(canvas) >> NUM_32) & 0xffffffff);
196         event.data[NUM_2] = context.width;
197         event.data[NUM_3] = context.height;
198         event.canvas = reinterpret_cast<intptr_t>(&context.canvas);
199         SendArkUIAsyncCustomEvent(&event);
200     } else {
201         InnerOverlayDraw(context);
202     }
203 }
204 
HasCustomerMeasure() const205 bool ExtensionCompanionNode::HasCustomerMeasure() const
206 {
207     return (flags_ & ArkUIAPINodeFlags::CUSTOM_MEASURE) != 0;
208 }
209 
HasCustomerLayout() const210 bool ExtensionCompanionNode::HasCustomerLayout() const
211 {
212     return (flags_ & ArkUIAPINodeFlags::CUSTOM_LAYOUT) != 0;
213 }
214 
NeedRender() const215 bool ExtensionCompanionNode::NeedRender() const
216 {
217     ArkUI_Uint32 mask = ArkUIAPINodeFlags::CUSTOM_OVERLAY_DRAW | ArkUIAPINodeFlags::CUSTOM_FOREGROUND_DRAW |
218         ArkUIAPINodeFlags::CUSTOM_DRAW;
219     return (flags_ & mask) != 0;
220 }
221 } // namespace OHOS::Ace::NG