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