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  132 133