• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Drawing and Display Sample
2
3## Overview
4You have learned how to call the APIs provided by **NativeDrawing** to draw 2D graphics in [Drawing Development](drawing-guidelines.md). In this topic, you will learn how to display 2D graphics on the screen by using the capabilities provided by **NativeWindow** and **\<XComponent>**.
5
6## How to Develop
7
8The following walks you through on how to use the canvas and brush of the **NativeDrawing** module to draw a basic 2D graphic, write the graphics content to the buffer provided by **NativeWindow**, and flush the buffer to the graphics queue. During this process, the **\<XComponent>** is used to connect the C++ code layer to the ArkTS layer so that the drawing and display logic is called at the ArkTS layer to display the graphic on the screen.
9
10**Adding Dynamic Link Libraries**
11
12Add the following libraries to **CMakeLists.txt**:
13```txt
14libace_napi.z.so
15libace_ndk.z.so
16libnative_window.so
17libnative_drawing.so
18```
19
20**Including Header Files**
21```c++
22#include <ace/xcomponent/native_interface_xcomponent.h>
23#include "napi/native_api.h"
24#include <native_window/external_window.h>
25#include <native_drawing/drawing_bitmap.h>
26#include <native_drawing/drawing_color.h>
27#include <native_drawing/drawing_canvas.h>
28#include <native_drawing/drawing_pen.h>
29#include <native_drawing/drawing_brush.h>
30#include <native_drawing/drawing_path.h>
31#include <cmath>
32#include <algorithm>
33#include <stdint.h>
34#include <sys/mman.h>
35```
36
371. Obtain an **OHNativeWindow** instance as the carrier for displaying the graphic.
38
39    1. Add an **\<XComponent>** to the .ets file.
40        ```ts
41        XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'entry'})
42        ```
43    2. Obtain **NativeXComponent** at the native C++ layer.
44        ```c++
45        // Obtain the ID of the <XComponent>.
46        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
47        uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
48        napi_value exportInstance = nullptr;
49        // Parse the attribute of the wrapped NativeXComponent pointer.
50        napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
51        OH_NativeXComponent *nativeXComponent = nullptr;
52        // Use the napi_unwrap API to parse the NativeXComponent instance pointer.
53        napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent));
54        ```
55     3. Define **OH_NativeXComponent_Callback**.
56        ```c++
57        // Declare a NativeXComponent callback.
58        OH_NativeXComponent_Callback callback;
59        // Register the OnSurfaceCreated callback function.
60        callback.OnSurfaceCreated = OnSurfaceCreatedCB;
61        ```
62     4. Register **OH_NativeXComponent_Callback** with **NativeXComponent**.
63        ```c++
64        // Register the callback function and implement the drawing and display logic in it. When the <XComponent> at the ArkTS layer is called, the logic is invoked through the callback function.
65        OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
66        ```
67
682. Obtain the **OHNativeWindow** instance, which is used as the carrier for displaying the graphic.
69    1. Set the attributes of an **OHNativeWindowBuffer** by using **OH_NativeWindow_NativeWindowHandleOpt**.
70        ```c++
71        // Obtain an OHNativeWindow instance.
72        OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
73
74        // Set the width and height of the OHNativeWindowBuffer.
75        int32_t code = SET_BUFFER_GEOMETRY;
76        uint64_t width;
77        uint64_t height;
78        int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
79        // The nativeWindow instance is obtained from the callback in the previous step.
80        ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
81        // Set the step of the OHNativeWindowBuffer.
82        code = SET_STRIDE;
83        int32_t stride = 0x8;
84
85        ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride);
86        ```
87    2. Request an **OHNativeWindowBuffer** from the graphics queue.
88        ```c++
89        OHNativeWindowBuffer* buffer = nullptr;
90        int fenceFd;
91        // Obtain the OHNativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer.
92        OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
93        // Obtain the buffer handle by calling OH_NativeWindow_GetBufferHandleFromNative.
94        BufferHandle* bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
95        ```
96    3. Map memory.
97        ```c++
98        // Use mmap() to obtain the memory virtual address of the buffer handle.
99        uint8_t *mappedAddr = static_cast<uint8_t *>(mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0));
100        if (mappedAddr == MAP_FAILED) {
101            // mmap failed
102        }
103        ```
104
1053. Use the APIs provided by **NativeDrawing** to draw a pentagon-shaped 2D graphic. For details, see [Drawing Development](drawing-guidelines.md).
106
1074. Use the APIs provided by **NativeWindow** to display the 2D graphic on the screen.
108    1. Write the drawing content to the **OHNativeWindowBuffer**.
109        ```c++
110        uint8_t *bitmapAddr = static_cast<uint8_t *>(OH_Drawing_BitmapGetPixels(cBitmap));
111        std::copy(bitmapAddr, bitmapAddr + (width * height * 4), mappedAddr);
112        ```
113    2. Flush the **OHNativeWindowBuffer** to the graphics queue.
114        ```c++
115        // Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the OHNativeWindowBuffer are changed.
116        Region region{nullptr, 0};
117        // Flush the buffer to the consumer through OH_NativeWindow_NativeWindowFlushBuffer, for example, by displaying it on the screen.
118        OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
119        ```
120    3. Unmap memory.
121        ```c++
122        // Unmap the memory when the memory is no longer required.
123        int result = munmap(mappedAddr, bufferHandle->size);
124        if (result == -1) {
125            // munmap failed
126        }
127        ```
128
129    The figure below shows the display effect of the graphic.
130
131    ![Drawing](figures/drawing.png)
132
133