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 <bits/alltypes.h>
17 #include <native_drawing/drawing_image.h>
18 #include <native_drawing/drawing_mask_filter.h>
19 #include <native_drawing/drawing_point.h>
20 #include <native_drawing/drawing_text_typography.h>
21 #include "sample_bitmap.h"
22 #include "common/log_common.h"
23
SetWidth(uint64_t width)24 void SampleBitMap::SetWidth(uint64_t width) // 设置窗口宽度
25 {
26 width_ = width;
27 }
28
SetHeight(uint64_t height)29 void SampleBitMap::SetHeight(uint64_t height) //设置窗口高度
30 {
31 height_ = height;
32 }
33
SetNativeWindow(OHNativeWindow * nativeWindow)34 void SampleBitMap::SetNativeWindow(OHNativeWindow *nativeWindow) //设置窗口
35 {
36 nativeWindow_ = nativeWindow;
37 }
38
Prepare()39 void SampleBitMap::Prepare()
40 {
41 if (nativeWindow_ == nullptr) {
42 return;
43 }
44
45 // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
46 int ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer_, &fenceFd_);
47 DRAWING_LOGI("request buffer ret = %{public}d", ret);
48 // 通过 OH_NativeWindow_GetBufferHandleFromNative 获取 buffer 的 handle
49 bufferHandle_ = OH_NativeWindow_GetBufferHandleFromNative(buffer_);
50 // 使用系统mmap接口拿到bufferHandle的内存虚拟地址
51 mappedAddr_ = static_cast<uint32_t *>(
52 mmap(bufferHandle_->virAddr, bufferHandle_->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle_->fd, 0));
53 if (mappedAddr_ == MAP_FAILED) {
54 return;
55 }
56 }
57
Create()58 void SampleBitMap::Create() // 创建bitmap 和 canvas 并把它们关联
59 {
60 uint32_t width = static_cast<uint32_t>(bufferHandle_->stride / 4);
61 // 创建一个bitmap对象
62 cBitmap_ = OH_Drawing_BitmapCreate();
63 // 定义bitmap的像素格式
64 OH_Drawing_BitmapFormat cFormat{COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_OPAQUE};
65 // 构造对应格式的bitmap
66 OH_Drawing_BitmapBuild(cBitmap_, width, height_, &cFormat);
67
68 // 创建一个canvas对象
69 cCanvas_ = OH_Drawing_CanvasCreate();
70 // 将画布与bitmap绑定,画布画的内容会输出到绑定的bitmap内存中
71 OH_Drawing_CanvasBind(cCanvas_, cBitmap_);
72 // 使用白色清除画布内容
73 OH_Drawing_CanvasClear(cCanvas_, OH_Drawing_ColorSetArgb(0xFF, 0xCD, 0xCD, 0x0));
74 }
75
ConstructPath()76 void SampleBitMap::ConstructPath()
77 {
78 static int blockSize = 5;
79 static int x2Offset = 2;
80 static int x3Offset = 3;
81 static int x4Offset = 4;
82 float x1 = width_ / blockSize * x2Offset;
83 float y1 = height_ / blockSize;
84 float x2 = width_ / blockSize * x3Offset;
85 float y2 = height_ / blockSize;
86 float x3 = width_ / blockSize * x3Offset;
87 float y3 = height_ / blockSize * x2Offset;
88 float x4 = width_ / blockSize * x4Offset;
89 float y4 = height_ / blockSize * x2Offset;
90 float x5 = width_ / blockSize * x4Offset;
91 float y5 = height_ / blockSize * x3Offset;
92 float x6 = width_ / blockSize * x3Offset;
93 float y6 = height_ / blockSize * x3Offset;
94 float x7 = width_ / blockSize * x3Offset;
95 float y7 = height_ / blockSize * x4Offset;
96 float x8 = width_ / blockSize * x2Offset;
97 float y8 = height_ / blockSize * x4Offset;
98 float x9 = width_ / blockSize * x2Offset;
99 float y9 = height_ / blockSize * x3Offset;
100 float x10 = width_ / blockSize;
101 float y10 = height_ / blockSize * x3Offset;
102 float x11 = width_ / blockSize;
103 float y11 = height_ / blockSize * x2Offset;
104 float x12 = width_ / blockSize * x2Offset;
105 float y12 = height_ / blockSize * x2Offset;
106
107 cPath_ = OH_Drawing_PathCreate();
108 // 指定path的起始位置
109 OH_Drawing_PathMoveTo(cPath_, x1, y1);
110 // 用直线连接到目标点
111 OH_Drawing_PathLineTo(cPath_, x2, y2);
112 OH_Drawing_PathLineTo(cPath_, x3, y3);
113 OH_Drawing_PathLineTo(cPath_, x4, y4);
114 OH_Drawing_PathLineTo(cPath_, x5, y5);
115 OH_Drawing_PathLineTo(cPath_, x6, y6);
116 OH_Drawing_PathLineTo(cPath_, x7, y7);
117 OH_Drawing_PathLineTo(cPath_, x8, y8);
118 OH_Drawing_PathLineTo(cPath_, x9, y9);
119 OH_Drawing_PathLineTo(cPath_, x10, y10);
120 OH_Drawing_PathLineTo(cPath_, x11, y11);
121 OH_Drawing_PathLineTo(cPath_, x12, y12);
122 // 闭合形状,path绘制完毕
123 OH_Drawing_PathClose(cPath_);
124 }
125
126 // 设置画笔的宽度和颜色
SetPenAndBrush()127 void SampleBitMap::SetPenAndBrush()
128 {
129 constexpr float penWidth = 40.0f; // pen width 40.0
130
131 cPen_ = OH_Drawing_PenCreate(); // 创建一个画笔Pen对象,Pen对象用于形状的边框线绘制
132 OH_Drawing_PenSetAntiAlias(cPen_, true);
133 OH_Drawing_PenSetColor(cPen_, OH_Drawing_ColorSetArgb(0xFF, 0x0, 0x0, 0xCD));
134 OH_Drawing_PenSetWidth(cPen_, penWidth);
135 OH_Drawing_PenSetJoin(cPen_, LINE_ROUND_JOIN);
136
137 // 将Pen画笔设置到canvas中
138 OH_Drawing_CanvasAttachPen(cCanvas_, cPen_);
139 }
140
DrawPath()141 void SampleBitMap::DrawPath()
142 {
143 // 在画布上画path的形状,边框样式为pen设置,颜色填充为Brush设置
144 OH_Drawing_CanvasDrawPath(cCanvas_, cPath_);
145 }
146
DisPlay()147 void SampleBitMap::DisPlay()
148 {
149 // 画完后获取像素地址,地址指向的内存包含画布画的像素数据
150 void *bitmapAddr = OH_Drawing_BitmapGetPixels(cBitmap_);
151 uint32_t *value = static_cast<uint32_t *>(bitmapAddr);
152
153 uint32_t *pixel = static_cast<uint32_t *>(mappedAddr_); // 使用mmap获取到的地址来访问内存
154 if (pixel == nullptr) {
155 return;
156 }
157 if (value == nullptr) {
158 return;
159 }
160 uint32_t width = static_cast<uint32_t>(bufferHandle_->stride / 4); // 4 is offset
161 for (uint32_t x = 0; x < width; x++) {
162 for (uint32_t y = 0; y < height_; y++) {
163 *pixel++ = *value++;
164 }
165 }
166 // 设置刷新区域,如果Region中的Rect为nullptr,或者rectNumber为0,则认为OHNativeWindowBuffer全部有内容更改。
167 Region region {nullptr, 0};
168 // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
169 OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer_, fenceFd_, region);
170 // 内存使用完记得去掉内存映射
171 int result = munmap(mappedAddr_, bufferHandle_->size);
172 if (result == -1) {
173 return;
174 }
175 }
176
Destroy()177 void SampleBitMap::Destroy()
178 {
179 // 销毁创建的对象
180 OH_Drawing_PenDestroy(cPen_);
181 cPen_ = nullptr;
182 OH_Drawing_PathDestroy(cPath_);
183 cPath_ = nullptr;
184 // 销毁canvas对象
185 OH_Drawing_CanvasDestroy(cCanvas_);
186 cCanvas_ = nullptr;
187 // 销毁bitmap对象
188 OH_Drawing_BitmapDestroy(cBitmap_);
189 }
190
NapiDrawPattern(napi_env env,napi_callback_info info)191 napi_value SampleBitMap::NapiDrawPattern(napi_env env, napi_callback_info info)
192 {
193 DRAWING_LOGI("NapiDrawPattern");
194 if ((env == nullptr) || (info == nullptr)) {
195 return nullptr;
196 }
197
198 napi_value thisArg;
199 if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
200 return nullptr;
201 }
202
203 napi_value exportInstance;
204 if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
205 return nullptr;
206 }
207
208 OH_NativeXComponent *nativeXComponent = nullptr;
209 if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
210 return nullptr;
211 }
212
213 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
214 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
215 if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
216 return nullptr;
217 }
218 DRAWING_LOGI("ID = %{public}s", idStr);
219 std::string id(idStr);
220 SampleBitMap *render = SampleBitMap().GetInstance(id);
221 if (render != nullptr) {
222 render->Prepare();
223 render->Create();
224 render->ConstructPath();
225 render->SetPenAndBrush();
226 render->DrawPath();
227 render->DisPlay();
228 render->Destroy();
229 DRAWING_LOGI("DrawPath executed");
230 }
231 return nullptr;
232 }
233
Export(napi_env env,napi_value exports)234 void SampleBitMap::Export(napi_env env, napi_value exports) // 定义并导出接口drawPattern
235 {
236 if ((env == nullptr) || (exports == nullptr)) {
237 return;
238 }
239 napi_property_descriptor desc[] = {
240 {"drawPattern", nullptr, SampleBitMap::NapiDrawPattern, nullptr, nullptr, nullptr, napi_default, nullptr},
241 };
242 if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
243 return;
244 }
245 }
246
~SampleBitMap()247 SampleBitMap::~SampleBitMap()
248 {
249 // 销毁创建的对象
250 OH_Drawing_PenDestroy(cPen_);
251 cPen_ = nullptr;
252 OH_Drawing_PathDestroy(cPath_);
253 cPath_ = nullptr;
254 // 销毁canvas对象
255 OH_Drawing_CanvasDestroy(cCanvas_);
256 cCanvas_ = nullptr;
257 // 销毁bitmap对象
258 OH_Drawing_BitmapDestroy(cBitmap_);
259 cBitmap_ = nullptr;
260
261 buffer_ = nullptr;
262 bufferHandle_ = nullptr;
263 nativeWindow_ = nullptr;
264 mappedAddr_ = nullptr;
265 }
266
267 static std::unordered_map<std::string, SampleBitMap *> g_instance;
268
Release(std::string & id)269 void SampleBitMap::Release(std::string &id) //将该id对应的窗口释放
270 {
271 SampleBitMap *render = SampleBitMap::GetInstance(id);
272 if (render != nullptr) {
273 delete render;
274 render = nullptr;
275 g_instance.erase(g_instance.find(id));
276 }
277 }
278
GetInstance(std::string & id)279 SampleBitMap *SampleBitMap::GetInstance(std::string &id) // 通过ComponentId 获取实例,没有新建
280 {
281 if (g_instance.find(id) == g_instance.end()) {
282 SampleBitMap *render = new SampleBitMap(id);
283 g_instance[id] = render;
284 return render;
285 } else {
286 return g_instance[id];
287 }
288 }
289
OnSurfaceCreatedCB(OH_NativeXComponent * component,void * window)290 static void OnSurfaceCreatedCB(OH_NativeXComponent *component,
291 void *window) // 通过component获取ComponentId,获取实例,设置窗口及其尺寸
292 {
293 DRAWING_LOGI("OnSurfaceCreatedCB");
294 if ((component == nullptr) || (window == nullptr)) {
295 return;
296 }
297 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
298 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
299 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
300 return;
301 }
302 std::string id(idStr);
303 auto render = SampleBitMap::GetInstance(id);
304 if (render == nullptr) {
305 return;
306 }
307 OHNativeWindow *nativeWindow = static_cast<OHNativeWindow *>(window);
308 render->SetNativeWindow(nativeWindow);
309
310 uint64_t width;
311 uint64_t height;
312 int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
313 if (xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
314 render->SetHeight(height);
315 render->SetWidth(width);
316 DRAWING_LOGI("xComponent width = %{public}llu, height = %{public}llu", width, height);
317 }
318 }
319
OnSurfaceDestroyedCB(OH_NativeXComponent * component,void * window)320 static void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) // 通过component获取ComponentId,销毁实例
321 {
322 DRAWING_LOGI("OnSurfaceDestroyedCB");
323 if ((component == nullptr) || (window == nullptr)) {
324 return;
325 }
326 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
327 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
328 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
329 return;
330 }
331 std::string id(idStr);
332 SampleBitMap::Release(id);
333 }
334
RegisterCallback(OH_NativeXComponent * nativeXComponent)335 void SampleBitMap::RegisterCallback(OH_NativeXComponent *nativeXComponent) //注册nativeXComponent 回调函数
336 {
337 DRAWING_LOGI("register callback");
338 renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB;
339 renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
340 // Callback must be initialized
341 renderCallback_.DispatchTouchEvent = nullptr;
342 renderCallback_.OnSurfaceChanged = nullptr;
343 OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_);
344 }
345
346