1e41f4b71Sopenharmony_ci# Native XComponent 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## When to Use 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci**NativeXComponent** provides an instance for the **\<XComponent>** at the native layer, which can be used as a bridge for binding with the **\<XComponent>** at the JS layer. The NDK APIs provided by the **\<XComponent>** depend on this instance. The provided APIs include those for obtaining a native window, obtaining the layout or event information of the **\<XComponent>**, registering the lifecycle callbacks of the **\<XComponent>**, and registering the callbacks for the touch, mouse, and key events of the **\<XComponent>**. You can use the provided APIs in the following scenarios: 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci- Register the lifecycle and event callbacks of the **\<XComponent>**. 8e41f4b71Sopenharmony_ci- Initialize the environment, obtain the current state, and respond to various events via these callbacks. 9e41f4b71Sopenharmony_ci- Use the native window and EGL APIs to develop custom drawing content, and apply for and submit buffers to the graphics queue. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci## Available APIs 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci| API| Description| 14e41f4b71Sopenharmony_ci| -------- | -------- | 15e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetXComponentId(OH_NativeXComponent* component, char* id, uint64_t* size)|Obtains the ID of an **\<XComponent>**.| 16e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetXComponentSize(OH_NativeXComponent* component, const void* window, uint64_t* width, uint64_t* height)|Obtains the size of the surface held by an **\<XComponent>**.| 17e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetXComponentOffset(OH_NativeXComponent* component, const void* window, double* x, double* y)|Obtains the offset of the surface held by an **\<XComponent>** relative to the upper left corner of the window.| 18e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetTouchEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_TouchEvent* touchEvent)|Obtains the touch event triggered by an **\<XComponent>**. For details about the attribute values in **touchEvent**, see [OH_NativeXComponent_TouchEvent](../reference/apis-arkui/_o_h___native_x_component___touch_event.md).| 19e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetTouchPointToolType(OH_NativeXComponent* component, uint32_t pointIndex, OH_NativeXComponent_TouchPointToolType* toolType)|Obtains the tool type of an **\<XComponent>** touch point.| 20e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetTouchPointTiltX(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltX)|Obtains the tilt of an **\<XComponent>** touch point relative to the x-axis.| 21e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetTouchPointTiltY(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltY)|Obtains the tilt of an **\<XComponent>** touch point relative to the y-axis.| 22e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetMouseEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_MouseEvent* mouseEvent)|Obtains the mouse event triggered by an **\<XComponent>**.| 23e41f4b71Sopenharmony_ci|OH_NativeXComponent_RegisterCallback(OH_NativeXComponent* component, OH_NativeXComponent_Callback* callback)|Registers a lifecycle or touch event callback for an **OH_NativeXComponent** instance.| 24e41f4b71Sopenharmony_ci|OH_NativeXComponent_RegisterMouseEventCallback(OH_NativeXComponent* component, OH_NativeXComponent_MouseEvent_Callback* callback)|Registers the mouse event callback for an **OH_NativeXComponent** instance.| 25e41f4b71Sopenharmony_ci|OH_NativeXComponent_RegisterFocusEventCallback(OH_NativeXComponent* component, void (\*callback)(OH_NativeXComponent* component, void* window))|Registers the focus obtaining event callback for an **OH_NativeXComponent** instance.| 26e41f4b71Sopenharmony_ci|OH_NativeXComponent_RegisterKeyEventCallback(OH_NativeXComponent* component, void (\*callback)(OH_NativeXComponent* component, void* window))|Registers the key event callback for an **OH_NativeXComponent** instance.| 27e41f4b71Sopenharmony_ci|OH_NativeXComponent_RegisterBlurEventCallback(OH_NativeXComponent* component, void (\*callback)(OH_NativeXComponent* component, void* window))|Registers the focus loss event callback for an **OH_NativeXComponent** instance.| 28e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetKeyEvent(OH_NativeXComponent* component, OH_NativeXComponent_KeyEvent\** keyEvent)|Obtains the key event triggered by an **\<XComponent>**.| 29e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetKeyEventAction(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyAction* action)|Obtains the action of a key event.| 30e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetKeyEventCode(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyCode* code)|Obtains the key code value of a key event.| 31e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetKeyEventSourceType(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_EventSourceType* sourceType)|Obtains the input source type of a key event.| 32e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetKeyEventDeviceId(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* deviceId)|Obtains the device ID of a key event.| 33e41f4b71Sopenharmony_ci|OH_NativeXComponent_GetKeyEventTimestamp(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* timestamp)|Obtains the timestamp of a key event.| 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci## Lifecycle Description 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ciYou can use the **\<XComponent>** to develop EGL/OpenGL ES rendering by using the following ArkTS code: 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci```typescript 40e41f4b71Sopenharmony_ci@Builder 41e41f4b71Sopenharmony_cifunction myComponent() { 42e41f4b71Sopenharmony_ci XComponent({ id: 'xcomponentId1', type: 'surface', libraryname: 'nativerender' }) 43e41f4b71Sopenharmony_ci .onLoad((context) => {}) 44e41f4b71Sopenharmony_ci .onDestroy(() => {}) 45e41f4b71Sopenharmony_ci} 46e41f4b71Sopenharmony_ci``` 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci### **onLoad** Event 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ciTrigger time: when the surface of the **\<XComponent>** is ready. 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ci**context** parameter: where the native API exposed on the module is mounted. Its usage is similar to the usage of a **context** instance obtained after the module is directly loaded using **import context from "libnativerender.so"**. 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ciTime sequence: subject to the surface. The figure below shows the time sequence of the **onLoad** event and the **OnSurfaceCreated** event at the native layer. 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci 58e41f4b71Sopenharmony_ci### **onDestroy** Event 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ciTrigger time: when the **\<XComponent>** is destroyed, in the same manner as that when an ArkUI component is destroyed. The figure below shows the time sequence of the **onDestroy** event and the **OnSurfaceDestroyed** event at the native layer. 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ci## How to Develop 65e41f4b71Sopenharmony_ciThe following describes how to use the **\<XComponent>** to call the native APIs to create the EGL/OpenGL ES environment, draw graphics on the main page, and change graphics colors. 66e41f4b71Sopenharmony_ci 67e41f4b71Sopenharmony_ci1. Define the **\<XComponent>** on the GUI. 68e41f4b71Sopenharmony_ci 69e41f4b71Sopenharmony_ci ```typescript 70e41f4b71Sopenharmony_ci @Entry 71e41f4b71Sopenharmony_ci @Component 72e41f4b71Sopenharmony_ci struct Index { 73e41f4b71Sopenharmony_ci @State message: string = 'Hello World' 74e41f4b71Sopenharmony_ci xComponentContext: object | undefined = undefined; 75e41f4b71Sopenharmony_ci xComponentAttrs: XComponentAttrs = { 76e41f4b71Sopenharmony_ci id: 'xcomponentId', 77e41f4b71Sopenharmony_ci type: XComponentType.SURFACE, 78e41f4b71Sopenharmony_ci libraryname: 'nativerender' 79e41f4b71Sopenharmony_ci } 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci build() { 82e41f4b71Sopenharmony_ci Row() { 83e41f4b71Sopenharmony_ci // ... 84e41f4b71Sopenharmony_ci // Define XComponent in an .ets file. 85e41f4b71Sopenharmony_ci XComponent(this.xComponentAttrs) 86e41f4b71Sopenharmony_ci .focusable(true) // Set the component to be able to respond to key events. 87e41f4b71Sopenharmony_ci .onLoad((xComponentContext) => { 88e41f4b71Sopenharmony_ci this.xComponentContext = xComponentContext; 89e41f4b71Sopenharmony_ci }) 90e41f4b71Sopenharmony_ci .onDestroy(() => { 91e41f4b71Sopenharmony_ci console.log("onDestroy"); 92e41f4b71Sopenharmony_ci }) 93e41f4b71Sopenharmony_ci // ... 94e41f4b71Sopenharmony_ci } 95e41f4b71Sopenharmony_ci .height('100%') 96e41f4b71Sopenharmony_ci } 97e41f4b71Sopenharmony_ci } 98e41f4b71Sopenharmony_ci 99e41f4b71Sopenharmony_ci interface XComponentAttrs { 100e41f4b71Sopenharmony_ci id: string; 101e41f4b71Sopenharmony_ci type: number; 102e41f4b71Sopenharmony_ci libraryname: string; 103e41f4b71Sopenharmony_ci } 104e41f4b71Sopenharmony_ci ``` 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci2. Register the Node-API module. For details, see [Node-API Development Specifications](../napi/napi-guidelines.md). 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ci ```c++ 109e41f4b71Sopenharmony_ci // In the napi_init.cpp file, use the Init method to register the target function to pass in the encapsulated C++ methods for the JS method to call. 110e41f4b71Sopenharmony_ci EXTERN_C_START 111e41f4b71Sopenharmony_ci static napi_value Init(napi_env env, napi_value exports) 112e41f4b71Sopenharmony_ci { 113e41f4b71Sopenharmony_ci // ... 114e41f4b71Sopenharmony_ci // Expose the getContext() API to the JS code. 115e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = { 116e41f4b71Sopenharmony_ci { "getContext", nullptr, PluginManager::GetContext, nullptr, nullptr, nullptr, napi_default, nullptr } 117e41f4b71Sopenharmony_ci }; 118e41f4b71Sopenharmony_ci if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { 119e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed"); 120e41f4b71Sopenharmony_ci return nullptr; 121e41f4b71Sopenharmony_ci } 122e41f4b71Sopenharmony_ci // Check whether the environment variables in the method contain the <XComponent> instance. If the instance exists, register the drawing-related API. 123e41f4b71Sopenharmony_ci PluginManager::GetInstance()->Export(env, exports); 124e41f4b71Sopenharmony_ci return exports; 125e41f4b71Sopenharmony_ci } 126e41f4b71Sopenharmony_ci EXTERN_C_END 127e41f4b71Sopenharmony_ci 128e41f4b71Sopenharmony_ci // Write the API description. You can modify parameters as required. 129e41f4b71Sopenharmony_ci static napi_module nativerenderModule = { 130e41f4b71Sopenharmony_ci .nm_version = 1, 131e41f4b71Sopenharmony_ci .nm_flags = 0, 132e41f4b71Sopenharmony_ci .nm_filename = nullptr, 133e41f4b71Sopenharmony_ci // Entry point function 134e41f4b71Sopenharmony_ci .nm_register_func = Init, 135e41f4b71Sopenharmony_ci // Module name 136e41f4b71Sopenharmony_ci .nm_modname = "nativerender", 137e41f4b71Sopenharmony_ci .nm_priv = ((void *)0), 138e41f4b71Sopenharmony_ci .reserved = { 0 } 139e41f4b71Sopenharmony_ci }; 140e41f4b71Sopenharmony_ci 141e41f4b71Sopenharmony_ci // The method decorated by __attribute__((constructor)) is automatically called by the system. The Node-API napi_module_register() is used to pass in the module description for module registration. 142e41f4b71Sopenharmony_ci extern "C" __attribute__((constructor)) void RegisterModule(void) 143e41f4b71Sopenharmony_ci { 144e41f4b71Sopenharmony_ci napi_module_register(&nativerenderModule); 145e41f4b71Sopenharmony_ci } 146e41f4b71Sopenharmony_ci 147e41f4b71Sopenharmony_ci // Use the napi_define_properties method to expose the drawPattern() method to the JS code and call the JS drawPattern() method to draw content. 148e41f4b71Sopenharmony_ci void PluginRender::Export(napi_env env, napi_value exports) 149e41f4b71Sopenharmony_ci { 150e41f4b71Sopenharmony_ci // ... 151e41f4b71Sopenharmony_ci // Register the function as the JS API drawPattern. 152e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = { 153e41f4b71Sopenharmony_ci { "drawPattern", nullptr, PluginRender::NapiDrawPattern, nullptr, nullptr, nullptr, napi_default, nullptr } 154e41f4b71Sopenharmony_ci }; 155e41f4b71Sopenharmony_ci if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { 156e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: napi_define_properties failed"); 157e41f4b71Sopenharmony_ci } 158e41f4b71Sopenharmony_ci } 159e41f4b71Sopenharmony_ci ``` 160e41f4b71Sopenharmony_ci 161e41f4b71Sopenharmony_ci3. Register the **\<XComponent>** event callback and use the Node-API to implement it. 162e41f4b71Sopenharmony_ci 163e41f4b71Sopenharmony_ci (1) Define the callbacks for the touch event of the **\<XComponent>** and for when a surface is successfully created, changed, or destroyed. 164e41f4b71Sopenharmony_ci 165e41f4b71Sopenharmony_ci ```c++ 166e41f4b71Sopenharmony_ci // Define the OnSurfaceCreatedCB() function to encapsulate the initialization environment and drawing background. 167e41f4b71Sopenharmony_ci void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) 168e41f4b71Sopenharmony_ci { 169e41f4b71Sopenharmony_ci // ... 170e41f4b71Sopenharmony_ci // Obtain the ID of the <XComponent>, that is, the id parameter in the <XComponent> struct in the JS code. 171e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; 172e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 173e41f4b71Sopenharmony_ci if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 174e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 175e41f4b71Sopenharmony_ci "OnSurfaceCreatedCB: Unable to get XComponent id"); 176e41f4b71Sopenharmony_ci return; 177e41f4b71Sopenharmony_ci } 178e41f4b71Sopenharmony_ci 179e41f4b71Sopenharmony_ci // Initialize the environment and draw the background. 180e41f4b71Sopenharmony_ci std::string id(idStr); 181e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 182e41f4b71Sopenharmony_ci uint64_t width; 183e41f4b71Sopenharmony_ci uint64_t height; 184e41f4b71Sopenharmony_ci // Obtain the size of the surface held by the <XComponent>. 185e41f4b71Sopenharmony_ci int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); 186e41f4b71Sopenharmony_ci if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) { 187e41f4b71Sopenharmony_ci if (render->eglCore_->EglContextInit(window, width, height)) { 188e41f4b71Sopenharmony_ci render->eglCore_->Background(); 189e41f4b71Sopenharmony_ci } 190e41f4b71Sopenharmony_ci } 191e41f4b71Sopenharmony_ci } 192e41f4b71Sopenharmony_ci 193e41f4b71Sopenharmony_ci // Define the OnSurfaceChangedCB() function. 194e41f4b71Sopenharmony_ci void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) 195e41f4b71Sopenharmony_ci { 196e41f4b71Sopenharmony_ci // ... 197e41f4b71Sopenharmony_ci // Obtain the ID of the <XComponent>. 198e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; 199e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 200e41f4b71Sopenharmony_ci if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 201e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 202e41f4b71Sopenharmony_ci "OnSurfaceChangedCB: Unable to get XComponent id"); 203e41f4b71Sopenharmony_ci return; 204e41f4b71Sopenharmony_ci } 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci std::string id(idStr); 207e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 208e41f4b71Sopenharmony_ci if (render != nullptr) { 209e41f4b71Sopenharmony_ci // Encapsulate the OnSurfaceChanged method. 210e41f4b71Sopenharmony_ci render->OnSurfaceChanged(component, window); 211e41f4b71Sopenharmony_ci } 212e41f4b71Sopenharmony_ci } 213e41f4b71Sopenharmony_ci 214e41f4b71Sopenharmony_ci // Define the OnSurfaceDestroyedCB() function and encapsulate in it the Release() method in the PluginRender class for releasing resources. 215e41f4b71Sopenharmony_ci void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) 216e41f4b71Sopenharmony_ci { 217e41f4b71Sopenharmony_ci // ... 218e41f4b71Sopenharmony_ci // Obtain the ID of the <XComponent>. 219e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; 220e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 221e41f4b71Sopenharmony_ci if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 222e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 223e41f4b71Sopenharmony_ci "OnSurfaceDestroyedCB: Unable to get XComponent id"); 224e41f4b71Sopenharmony_ci return; 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci 227e41f4b71Sopenharmony_ci std::string id(idStr); 228e41f4b71Sopenharmony_ci // Release resources. 229e41f4b71Sopenharmony_ci PluginRender::Release(id); 230e41f4b71Sopenharmony_ci } 231e41f4b71Sopenharmony_ci 232e41f4b71Sopenharmony_ci // Define the DispatchTouchEventCB() function, which is triggered to respond to a touch event. 233e41f4b71Sopenharmony_ci void DispatchTouchEventCB(OH_NativeXComponent *component, void *window) 234e41f4b71Sopenharmony_ci { 235e41f4b71Sopenharmony_ci // ... 236e41f4b71Sopenharmony_ci // Obtain the ID of the <XComponent>. 237e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; 238e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 239e41f4b71Sopenharmony_ci if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 240e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 241e41f4b71Sopenharmony_ci "DispatchTouchEventCB: Unable to get XComponent id"); 242e41f4b71Sopenharmony_ci return; 243e41f4b71Sopenharmony_ci } 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci std::string id(idStr); 246e41f4b71Sopenharmony_ci PluginRender *render = PluginRender::GetInstance(id); 247e41f4b71Sopenharmony_ci if (render != nullptr) { 248e41f4b71Sopenharmony_ci // Encapsulate the OnTouchEvent method. 249e41f4b71Sopenharmony_ci render->OnTouchEvent(component, window); 250e41f4b71Sopenharmony_ci } 251e41f4b71Sopenharmony_ci } 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci // Define the DispatchMouseEventCB() function, which is triggered when a mouse event is responded to. 254e41f4b71Sopenharmony_ci void DispatchMouseEventCB(OH_NativeXComponent *component, void *window) { 255e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchMouseEventCB"); 256e41f4b71Sopenharmony_ci int32_t ret; 257e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; 258e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 259e41f4b71Sopenharmony_ci ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); 260e41f4b71Sopenharmony_ci if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 261e41f4b71Sopenharmony_ci return; 262e41f4b71Sopenharmony_ci } 263e41f4b71Sopenharmony_ci 264e41f4b71Sopenharmony_ci std::string id(idStr); 265e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 266e41f4b71Sopenharmony_ci if (render) { 267e41f4b71Sopenharmony_ci // Encapsulate the OnMouseEvent method. 268e41f4b71Sopenharmony_ci render->OnMouseEvent(component, window); 269e41f4b71Sopenharmony_ci } 270e41f4b71Sopenharmony_ci } 271e41f4b71Sopenharmony_ci 272e41f4b71Sopenharmony_ci // Define the DispatchHoverEventCB() function, which is triggered when the mouse pointer hover event is responded to. 273e41f4b71Sopenharmony_ci void DispatchHoverEventCB(OH_NativeXComponent *component, bool isHover) { 274e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchHoverEventCB"); 275e41f4b71Sopenharmony_ci int32_t ret; 276e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; 277e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 278e41f4b71Sopenharmony_ci ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); 279e41f4b71Sopenharmony_ci if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 280e41f4b71Sopenharmony_ci return; 281e41f4b71Sopenharmony_ci } 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ci std::string id(idStr); 284e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 285e41f4b71Sopenharmony_ci if (render) { 286e41f4b71Sopenharmony_ci // Encapsulate the OnHoverEvent method. 287e41f4b71Sopenharmony_ci render->OnHoverEvent(component, isHover); 288e41f4b71Sopenharmony_ci } 289e41f4b71Sopenharmony_ci } 290e41f4b71Sopenharmony_ci 291e41f4b71Sopenharmony_ci // Define the OnFocusEventCB() function, which is triggered when a focus obtaining event is responded to. 292e41f4b71Sopenharmony_ci void OnFocusEventCB(OH_NativeXComponent *component, void *window) { 293e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnFocusEventCB"); 294e41f4b71Sopenharmony_ci int32_t ret; 295e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; 296e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 297e41f4b71Sopenharmony_ci ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); 298e41f4b71Sopenharmony_ci if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 299e41f4b71Sopenharmony_ci return; 300e41f4b71Sopenharmony_ci } 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ci std::string id(idStr); 303e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 304e41f4b71Sopenharmony_ci if (render) { 305e41f4b71Sopenharmony_ci // Encapsulate the OnFocusEvent method. 306e41f4b71Sopenharmony_ci render->OnFocusEvent(component, window); 307e41f4b71Sopenharmony_ci } 308e41f4b71Sopenharmony_ci } 309e41f4b71Sopenharmony_ci 310e41f4b71Sopenharmony_ci // Define the OnBlurEventCB() function, which is triggered when the focus loss event is responded to. 311e41f4b71Sopenharmony_ci void OnBlurEventCB(OH_NativeXComponent *component, void *window) { 312e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnBlurEventCB"); 313e41f4b71Sopenharmony_ci int32_t ret; 314e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; 315e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 316e41f4b71Sopenharmony_ci ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); 317e41f4b71Sopenharmony_ci if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 318e41f4b71Sopenharmony_ci return; 319e41f4b71Sopenharmony_ci } 320e41f4b71Sopenharmony_ci 321e41f4b71Sopenharmony_ci std::string id(idStr); 322e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 323e41f4b71Sopenharmony_ci if (render) { 324e41f4b71Sopenharmony_ci // Encapsulate the OnBlurEvent method. 325e41f4b71Sopenharmony_ci render->OnBlurEvent(component, window); 326e41f4b71Sopenharmony_ci } 327e41f4b71Sopenharmony_ci } 328e41f4b71Sopenharmony_ci 329e41f4b71Sopenharmony_ci // Define the OnKeyEventCB() function, which is triggered when a key event is responded to. 330e41f4b71Sopenharmony_ci void OnKeyEventCB(OH_NativeXComponent *component, void *window) { 331e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnKeyEventCB"); 332e41f4b71Sopenharmony_ci int32_t ret; 333e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; 334e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 335e41f4b71Sopenharmony_ci ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); 336e41f4b71Sopenharmony_ci if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 337e41f4b71Sopenharmony_ci return; 338e41f4b71Sopenharmony_ci } 339e41f4b71Sopenharmony_ci std::string id(idStr); 340e41f4b71Sopenharmony_ci auto render = PluginRender::GetInstance(id); 341e41f4b71Sopenharmony_ci if (render) { 342e41f4b71Sopenharmony_ci // Encapsulate the OnKeyEvent method. 343e41f4b71Sopenharmony_ci render->OnKeyEvent(component, window); 344e41f4b71Sopenharmony_ci } 345e41f4b71Sopenharmony_ci } 346e41f4b71Sopenharmony_ci 347e41f4b71Sopenharmony_ci // Define an OnSurfaceChanged() method. 348e41f4b71Sopenharmony_ci void PluginRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window) 349e41f4b71Sopenharmony_ci { 350e41f4b71Sopenharmony_ci // ... 351e41f4b71Sopenharmony_ci std::string id(idStr); 352e41f4b71Sopenharmony_ci PluginRender* render = PluginRender::GetInstance(id); 353e41f4b71Sopenharmony_ci double offsetX; 354e41f4b71Sopenharmony_ci double offsetY; 355e41f4b71Sopenharmony_ci // Obtain the offset of the surface held by an <XComponent> relative to the upper left corner of the window. 356e41f4b71Sopenharmony_ci OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY); 357e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OH_NativeXComponent_GetXComponentOffset", 358e41f4b71Sopenharmony_ci "offsetX = %{public}lf, offsetY = %{public}lf", offsetX, offsetY); 359e41f4b71Sopenharmony_ci uint64_t width; 360e41f4b71Sopenharmony_ci uint64_t height; 361e41f4b71Sopenharmony_ci OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); 362e41f4b71Sopenharmony_ci if (render != nullptr) { 363e41f4b71Sopenharmony_ci render->eglCore_->UpdateSize(width, height); 364e41f4b71Sopenharmony_ci } 365e41f4b71Sopenharmony_ci } 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ci // Define an OnTouchEvent() method. 368e41f4b71Sopenharmony_ci void PluginRender::OnTouchEvent(OH_NativeXComponent* component, void* window) 369e41f4b71Sopenharmony_ci { 370e41f4b71Sopenharmony_ci // ... 371e41f4b71Sopenharmony_ci OH_NativeXComponent_TouchEvent touchEvent; 372e41f4b71Sopenharmony_ci // Obtain the touch event triggered by the <XComponent>. 373e41f4b71Sopenharmony_ci OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent); 374e41f4b71Sopenharmony_ci // Obtain the x coordinate of the <XComponent> touch point relative to the left edge of the <XComponent> and the y coordinate of the <XComponent> touch point relative to the upper edge of the <XComponent>. 375e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent", 376e41f4b71Sopenharmony_ci "touch info: x = %{public}lf, y = %{public}lf", touchEvent.x, touchEvent.y); 377e41f4b71Sopenharmony_ci // Obtain the x coordinate and y-coordinate of the <XComponent> touch point relative to the upper left corner of the application window where the <XComponent> is located. 378e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent", 379e41f4b71Sopenharmony_ci "touch info: screenX = %{public}lf, screenY = %{public}lf", touchEvent.screenX, touchEvent.screenY); 380e41f4b71Sopenharmony_ci std::string id(idStr); 381e41f4b71Sopenharmony_ci PluginRender* render = PluginRender::GetInstance(id); 382e41f4b71Sopenharmony_ci if (render != nullptr && touchEvent.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) { 383e41f4b71Sopenharmony_ci render->eglCore_->ChangeColor(); 384e41f4b71Sopenharmony_ci hasChangeColor_ = 1; 385e41f4b71Sopenharmony_ci } 386e41f4b71Sopenharmony_ci float tiltX = 0.0f; 387e41f4b71Sopenharmony_ci float tiltY = 0.0f; 388e41f4b71Sopenharmony_ci OH_NativeXComponent_TouchPointToolType toolType = 389e41f4b71Sopenharmony_ci OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN; 390e41f4b71Sopenharmony_ci // Obtain the tool type of the <XComponent> touch point. 391e41f4b71Sopenharmony_ci OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); 392e41f4b71Sopenharmony_ci // Obtain the tilt of the <XComponent> touch point relative to the x-axis. 393e41f4b71Sopenharmony_ci OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX); 394e41f4b71Sopenharmony_ci // Obtain the tilt of the <XComponent> touch point relative to the y-axis. 395e41f4b71Sopenharmony_ci OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY); 396e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent", 397e41f4b71Sopenharmony_ci "touch info: toolType = %{public}d, tiltX = %{public}lf, tiltY = %{public}lf", toolType, tiltX, tiltY); 398e41f4b71Sopenharmony_ci } 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci // Define an OnMouseEvent() method. 401e41f4b71Sopenharmony_ci void PluginRender::OnMouseEvent(OH_NativeXComponent *component, void *window) { 402e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnMouseEvent"); 403e41f4b71Sopenharmony_ci OH_NativeXComponent_MouseEvent mouseEvent; 404e41f4b71Sopenharmony_ci // Obtain the mouse event triggered by the <XComponent>. 405e41f4b71Sopenharmony_ci int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent); 406e41f4b71Sopenharmony_ci if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 407e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "MouseEvent Info: x = %{public}f, y = %{public}f, action = %{public}d, button = %{public}d", mouseEvent.x, mouseEvent.y, mouseEvent.action, mouseEvent.button); 408e41f4b71Sopenharmony_ci } else { 409e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetMouseEvent error"); 410e41f4b71Sopenharmony_ci } 411e41f4b71Sopenharmony_ci } 412e41f4b71Sopenharmony_ci 413e41f4b71Sopenharmony_ci // Define an OnMouseEvent() method. 414e41f4b71Sopenharmony_ci void PluginRender::OnKeyEvent(OH_NativeXComponent *component, void *window) { 415e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnKeyEvent"); 416e41f4b71Sopenharmony_ci 417e41f4b71Sopenharmony_ci OH_NativeXComponent_KeyEvent *keyEvent = nullptr; 418e41f4b71Sopenharmony_ci // Obtain the key event triggered by the <XComponent>. 419e41f4b71Sopenharmony_ci if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) { 420e41f4b71Sopenharmony_ci OH_NativeXComponent_KeyAction action; 421e41f4b71Sopenharmony_ci // Obtain the action of a key event. 422e41f4b71Sopenharmony_ci OH_NativeXComponent_GetKeyEventAction(keyEvent, &action); 423e41f4b71Sopenharmony_ci OH_NativeXComponent_KeyCode code; 424e41f4b71Sopenharmony_ci // Obtain the key code value of a key event. 425e41f4b71Sopenharmony_ci OH_NativeXComponent_GetKeyEventCode(keyEvent, &code); 426e41f4b71Sopenharmony_ci OH_NativeXComponent_EventSourceType sourceType; 427e41f4b71Sopenharmony_ci // Obtain the input source type of a key event. 428e41f4b71Sopenharmony_ci OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType); 429e41f4b71Sopenharmony_ci int64_t deviceId; 430e41f4b71Sopenharmony_ci // Obtain the device ID of a key event. 431e41f4b71Sopenharmony_ci OH_NativeXComponent_GetKeyEventDeviceId(keyEvent, &deviceId); 432e41f4b71Sopenharmony_ci int64_t timeStamp; 433e41f4b71Sopenharmony_ci // Obtain the timestamp of a key event. 434e41f4b71Sopenharmony_ci OH_NativeXComponent_GetKeyEventTimestamp(keyEvent, &timeStamp); 435e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "KeyEvent Info: action=%{public}d, code=%{public}d, sourceType=%{public}d, deviceId=%{public}ld, timeStamp=%{public}ld", action, code, sourceType, deviceId, timeStamp); 436e41f4b71Sopenharmony_ci } else { 437e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetKeyEvent error"); 438e41f4b71Sopenharmony_ci } 439e41f4b71Sopenharmony_ci } 440e41f4b71Sopenharmony_ci ``` 441e41f4b71Sopenharmony_ci 442e41f4b71Sopenharmony_ci (2) Register the **\<XComponent>** event callback and call the method defined in step 3.1 when the **\<XComponent>** event is triggered. 443e41f4b71Sopenharmony_ci 444e41f4b71Sopenharmony_ci ```c++ 445e41f4b71Sopenharmony_ci void PluginRender::RegisterCallback(OH_NativeXComponent *nativeXComponent) { 446e41f4b71Sopenharmony_ci // Set the callback of the component creation event. When the component is created, related operations are triggered to initialize the environment and draw the background. 447e41f4b71Sopenharmony_ci renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB; 448e41f4b71Sopenharmony_ci // Set the callback of the component change event. When the component changes, related operations are triggered. 449e41f4b71Sopenharmony_ci renderCallback_.OnSurfaceChanged = OnSurfaceChangedCB; 450e41f4b71Sopenharmony_ci // Set the callback of the component destruction event. When the component is destroyed, related operations are triggered to release the requested resources. 451e41f4b71Sopenharmony_ci renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB; 452e41f4b71Sopenharmony_ci // Set the callback of the touch event. When the touch event is triggered, the Node-API is called to invoke the embedded C++ method. 453e41f4b71Sopenharmony_ci renderCallback_.DispatchTouchEvent = DispatchTouchEventCB; 454e41f4b71Sopenharmony_ci // Register OH_NativeXComponent_Callback with NativeXComponent. 455e41f4b71Sopenharmony_ci OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_); 456e41f4b71Sopenharmony_ci 457e41f4b71Sopenharmony_ci // Set the callback of the mouse event. When the event is triggered, the Node-API is called to call the original C++ method. 458e41f4b71Sopenharmony_ci mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB; 459e41f4b71Sopenharmony_ci // Set the callback of the mouse pointer hover event. When the event is triggered, the Node-API is called to call the original C++ method. 460e41f4b71Sopenharmony_ci mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB; 461e41f4b71Sopenharmony_ci // Register OH_NativeXComponent_MouseEvent_Callback with NativeXComponent. 462e41f4b71Sopenharmony_ci OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback_); 463e41f4b71Sopenharmony_ci 464e41f4b71Sopenharmony_ci // Register the OnFocusEventCB method with NativeXComponent. 465e41f4b71Sopenharmony_ci OH_NativeXComponent_RegisterFocusEventCallback(nativeXComponent, OnFocusEventCB); 466e41f4b71Sopenharmony_ci // Register the OnKeyEventCB method with NativeXComponent. 467e41f4b71Sopenharmony_ci OH_NativeXComponent_RegisterKeyEventCallback(nativeXComponent, OnKeyEventCB); 468e41f4b71Sopenharmony_ci // Register the OnBlurEventCB method with NativeXComponent. 469e41f4b71Sopenharmony_ci OH_NativeXComponent_RegisterBlurEventCallback(nativeXComponent, OnBlurEventCB); 470e41f4b71Sopenharmony_ci } 471e41f4b71Sopenharmony_ci ``` 472e41f4b71Sopenharmony_ci 473e41f4b71Sopenharmony_ci (3) Define the **NapiDrawPattern** method, which will be called by the **drawPattern()** method exposed to the JS code. 474e41f4b71Sopenharmony_ci 475e41f4b71Sopenharmony_ci ```c++ 476e41f4b71Sopenharmony_ci napi_value PluginRender::NapiDrawPattern(napi_env env, napi_callback_info info) 477e41f4b71Sopenharmony_ci { 478e41f4b71Sopenharmony_ci // ... 479e41f4b71Sopenharmony_ci // Obtain environment variables. 480e41f4b71Sopenharmony_ci napi_value thisArg; 481e41f4b71Sopenharmony_ci if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) { 482e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_get_cb_info fail"); 483e41f4b71Sopenharmony_ci return nullptr; 484e41f4b71Sopenharmony_ci } 485e41f4b71Sopenharmony_ci 486e41f4b71Sopenharmony_ci // Obtain the XComponent instance from the environment variables. 487e41f4b71Sopenharmony_ci napi_value exportInstance; 488e41f4b71Sopenharmony_ci if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { 489e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", 490e41f4b71Sopenharmony_ci "NapiDrawPattern: napi_get_named_property fail"); 491e41f4b71Sopenharmony_ci return nullptr; 492e41f4b71Sopenharmony_ci } 493e41f4b71Sopenharmony_ci 494e41f4b71Sopenharmony_ci // Use napi_unwrap to obtain the pointer to the XComponent instance. 495e41f4b71Sopenharmony_ci OH_NativeXComponent *nativeXComponent = nullptr; 496e41f4b71Sopenharmony_ci if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) { 497e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_unwrap fail"); 498e41f4b71Sopenharmony_ci return nullptr; 499e41f4b71Sopenharmony_ci } 500e41f4b71Sopenharmony_ci 501e41f4b71Sopenharmony_ci // Obtain the ID of the XComponent. 502e41f4b71Sopenharmony_ci char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; 503e41f4b71Sopenharmony_ci uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 504e41f4b71Sopenharmony_ci if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { 505e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", 506e41f4b71Sopenharmony_ci "NapiDrawPattern: Unable to get XComponent id"); 507e41f4b71Sopenharmony_ci return nullptr; 508e41f4b71Sopenharmony_ci } 509e41f4b71Sopenharmony_ci 510e41f4b71Sopenharmony_ci std::string id(idStr); 511e41f4b71Sopenharmony_ci PluginRender *render = PluginRender::GetInstance(id); 512e41f4b71Sopenharmony_ci if (render) { 513e41f4b71Sopenharmony_ci // Call the drawing method. 514e41f4b71Sopenharmony_ci render->eglCore_->Draw(); 515e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->eglCore_->Draw() executed"); 516e41f4b71Sopenharmony_ci } 517e41f4b71Sopenharmony_ci return nullptr; 518e41f4b71Sopenharmony_ci } 519e41f4b71Sopenharmony_ci ``` 520e41f4b71Sopenharmony_ci 521e41f4b71Sopenharmony_ci4. Initialize the environment, including initializing the available EGLDisplay, determining the available surface configuration, creating the rendering area surface, and creating and associating the context. 522e41f4b71Sopenharmony_ci 523e41f4b71Sopenharmony_ci ```c++ 524e41f4b71Sopenharmony_ci void EGLCore::UpdateSize(int width, int height) 525e41f4b71Sopenharmony_ci { 526e41f4b71Sopenharmony_ci width_ = width; 527e41f4b71Sopenharmony_ci height_ = height; 528e41f4b71Sopenharmony_ci if (width_ > 0) { 529e41f4b71Sopenharmony_ci // Calculate the width percentage of the drawn rectangle. 530e41f4b71Sopenharmony_ci width_Percent_ = FIFTY_PERCENT * height_ / width_; 531e41f4b71Sopenharmony_ci } 532e41f4b71Sopenharmony_ci } 533e41f4b71Sopenharmony_ci 534e41f4b71Sopenharmony_ci bool EGLCore::EglContextInit(void *window, int width, int height) 535e41f4b71Sopenharmony_ci { 536e41f4b71Sopenharmony_ci // ... 537e41f4b71Sopenharmony_ci UpdateSize(width, height); 538e41f4b71Sopenharmony_ci eglWindow_ = static_cast<EGLNativeWindowType>(window); 539e41f4b71Sopenharmony_ci 540e41f4b71Sopenharmony_ci // Initialize the display. 541e41f4b71Sopenharmony_ci eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); 542e41f4b71Sopenharmony_ci if (eglDisplay_ == EGL_NO_DISPLAY) { 543e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display"); 544e41f4b71Sopenharmony_ci return false; 545e41f4b71Sopenharmony_ci } 546e41f4b71Sopenharmony_ci 547e41f4b71Sopenharmony_ci // Initialize the EGL. 548e41f4b71Sopenharmony_ci EGLint majorVersion; 549e41f4b71Sopenharmony_ci EGLint minorVersion; 550e41f4b71Sopenharmony_ci if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) { 551e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", 552e41f4b71Sopenharmony_ci "eglInitialize: unable to get initialize EGL display"); 553e41f4b71Sopenharmony_ci return false; 554e41f4b71Sopenharmony_ci } 555e41f4b71Sopenharmony_ci 556e41f4b71Sopenharmony_ci // Select the configuration. 557e41f4b71Sopenharmony_ci const EGLint maxConfigSize = 1; 558e41f4b71Sopenharmony_ci EGLint numConfigs; 559e41f4b71Sopenharmony_ci if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) { 560e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs"); 561e41f4b71Sopenharmony_ci return false; 562e41f4b71Sopenharmony_ci } 563e41f4b71Sopenharmony_ci 564e41f4b71Sopenharmony_ci // Create an environment. 565e41f4b71Sopenharmony_ci return CreateEnvironment(); 566e41f4b71Sopenharmony_ci } 567e41f4b71Sopenharmony_ci ``` 568e41f4b71Sopenharmony_ci 569e41f4b71Sopenharmony_ci ```c++ 570e41f4b71Sopenharmony_ci bool EGLCore::CreateEnvironment() 571e41f4b71Sopenharmony_ci { 572e41f4b71Sopenharmony_ci // ... 573e41f4b71Sopenharmony_ci // Create a surface. 574e41f4b71Sopenharmony_ci eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL); 575e41f4b71Sopenharmony_ci 576e41f4b71Sopenharmony_ci // ... 577e41f4b71Sopenharmony_ci // Create a context. 578e41f4b71Sopenharmony_ci eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS); 579e41f4b71Sopenharmony_ci if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) { 580e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed"); 581e41f4b71Sopenharmony_ci return false; 582e41f4b71Sopenharmony_ci } 583e41f4b71Sopenharmony_ci 584e41f4b71Sopenharmony_ci // Create a program. 585e41f4b71Sopenharmony_ci program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER); 586e41f4b71Sopenharmony_ci if (program_ == PROGRAM_ERROR) { 587e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program"); 588e41f4b71Sopenharmony_ci return false; 589e41f4b71Sopenharmony_ci } 590e41f4b71Sopenharmony_ci return true; 591e41f4b71Sopenharmony_ci } 592e41f4b71Sopenharmony_ci ``` 593e41f4b71Sopenharmony_ci 594e41f4b71Sopenharmony_ci5. Implement the rendering function. 595e41f4b71Sopenharmony_ci 596e41f4b71Sopenharmony_ci (1) Draw the background. 597e41f4b71Sopenharmony_ci 598e41f4b71Sopenharmony_ci ```c++ 599e41f4b71Sopenharmony_ci // Draw the background color #f4f4f4. 600e41f4b71Sopenharmony_ci const GLfloat BACKGROUND_COLOR[] = { 244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f }; 601e41f4b71Sopenharmony_ci 602e41f4b71Sopenharmony_ci // Draw the background vertex. 603e41f4b71Sopenharmony_ci const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = { 604e41f4b71Sopenharmony_ci -1.0f, 1.0f, 605e41f4b71Sopenharmony_ci 1.0f, 1.0f, 606e41f4b71Sopenharmony_ci 1.0f, -1.0f, 607e41f4b71Sopenharmony_ci -1.0f, -1.0f 608e41f4b71Sopenharmony_ci }; 609e41f4b71Sopenharmony_ci ``` 610e41f4b71Sopenharmony_ci 611e41f4b71Sopenharmony_ci ```c++ 612e41f4b71Sopenharmony_ci // Draw the background color. 613e41f4b71Sopenharmony_ci void EGLCore::Background() 614e41f4b71Sopenharmony_ci { 615e41f4b71Sopenharmony_ci GLint position = PrepareDraw(); 616e41f4b71Sopenharmony_ci if (position == POSITION_ERROR) { 617e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed"); 618e41f4b71Sopenharmony_ci return; 619e41f4b71Sopenharmony_ci } 620e41f4b71Sopenharmony_ci 621e41f4b71Sopenharmony_ci if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES, 622e41f4b71Sopenharmony_ci sizeof(BACKGROUND_RECTANGLE_VERTICES))) { 623e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed"); 624e41f4b71Sopenharmony_ci return; 625e41f4b71Sopenharmony_ci } 626e41f4b71Sopenharmony_ci 627e41f4b71Sopenharmony_ci if (!FinishDraw()) { 628e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed"); 629e41f4b71Sopenharmony_ci return; 630e41f4b71Sopenharmony_ci } 631e41f4b71Sopenharmony_ci } 632e41f4b71Sopenharmony_ci 633e41f4b71Sopenharmony_ci // Prepare for drawing and obtain the value of position. When the creation is successful, the value of position starts from 0. 634e41f4b71Sopenharmony_ci GLint EGLCore::PrepareDraw() 635e41f4b71Sopenharmony_ci { 636e41f4b71Sopenharmony_ci if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) || 637e41f4b71Sopenharmony_ci (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) { 638e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error"); 639e41f4b71Sopenharmony_ci return POSITION_ERROR; 640e41f4b71Sopenharmony_ci } 641e41f4b71Sopenharmony_ci 642e41f4b71Sopenharmony_ci glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_); 643e41f4b71Sopenharmony_ci glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT); 644e41f4b71Sopenharmony_ci glClear(GL_COLOR_BUFFER_BIT); 645e41f4b71Sopenharmony_ci glUseProgram(program_); 646e41f4b71Sopenharmony_ci 647e41f4b71Sopenharmony_ci return glGetAttribLocation(program_, POSITION_NAME); 648e41f4b71Sopenharmony_ci } 649e41f4b71Sopenharmony_ci 650e41f4b71Sopenharmony_ci // Draw a specified color in the specified area based on the input parameters. 651e41f4b71Sopenharmony_ci bool EGLCore::ExecuteDraw(GLint position, const GLfloat *color, const GLfloat shapeVertices[], 652e41f4b71Sopenharmony_ci unsigned long vertSize) 653e41f4b71Sopenharmony_ci { 654e41f4b71Sopenharmony_ci if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0]) != SHAPE_VERTICES_SIZE)) { 655e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); 656e41f4b71Sopenharmony_ci return false; 657e41f4b71Sopenharmony_ci } 658e41f4b71Sopenharmony_ci 659e41f4b71Sopenharmony_ci glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); 660e41f4b71Sopenharmony_ci glEnableVertexAttribArray(position); 661e41f4b71Sopenharmony_ci glVertexAttrib4fv(1, color); 662e41f4b71Sopenharmony_ci glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); 663e41f4b71Sopenharmony_ci glDisableVertexAttribArray(position); 664e41f4b71Sopenharmony_ci 665e41f4b71Sopenharmony_ci return true; 666e41f4b71Sopenharmony_ci } 667e41f4b71Sopenharmony_ci 668e41f4b71Sopenharmony_ci // End the drawing operation. 669e41f4b71Sopenharmony_ci bool EGLCore::FinishDraw() 670e41f4b71Sopenharmony_ci { 671e41f4b71Sopenharmony_ci // Forcibly flush the buffer. 672e41f4b71Sopenharmony_ci glFlush(); 673e41f4b71Sopenharmony_ci glFinish(); 674e41f4b71Sopenharmony_ci return eglSwapBuffers(eglDisplay_, eglSurface_); 675e41f4b71Sopenharmony_ci } 676e41f4b71Sopenharmony_ci ``` 677e41f4b71Sopenharmony_ci 678e41f4b71Sopenharmony_ci (2) Draw the shape. 679e41f4b71Sopenharmony_ci 680e41f4b71Sopenharmony_ci ```c++ 681e41f4b71Sopenharmony_ci void EGLCore::Draw() 682e41f4b71Sopenharmony_ci { 683e41f4b71Sopenharmony_ci flag_ = false; 684e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw"); 685e41f4b71Sopenharmony_ci GLint position = PrepareDraw(); 686e41f4b71Sopenharmony_ci if (position == POSITION_ERROR) { 687e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed"); 688e41f4b71Sopenharmony_ci return; 689e41f4b71Sopenharmony_ci } 690e41f4b71Sopenharmony_ci 691e41f4b71Sopenharmony_ci // Draw the background. 692e41f4b71Sopenharmony_ci if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES, 693e41f4b71Sopenharmony_ci sizeof(BACKGROUND_RECTANGLE_VERTICES))) { 694e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed"); 695e41f4b71Sopenharmony_ci return; 696e41f4b71Sopenharmony_ci } 697e41f4b71Sopenharmony_ci 698e41f4b71Sopenharmony_ci // Divide the pentagon into five quadrilaterals and calculate the four vertices of one of the quadrilaterals. 699e41f4b71Sopenharmony_ci GLfloat rotateX = 0; 700e41f4b71Sopenharmony_ci GLfloat rotateY = FIFTY_PERCENT * height_; 701e41f4b71Sopenharmony_ci GLfloat centerX = 0; 702e41f4b71Sopenharmony_ci GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); 703e41f4b71Sopenharmony_ci GLfloat leftX = -rotateY * (M_PI / 180 * 18); 704e41f4b71Sopenharmony_ci GLfloat leftY = 0; 705e41f4b71Sopenharmony_ci GLfloat rightX = rotateY * (M_PI / 180 * 18); 706e41f4b71Sopenharmony_ci GLfloat rightY = 0; 707e41f4b71Sopenharmony_ci 708e41f4b71Sopenharmony_ci // Determine the vertices for drawing the quadrilateral, which are represented by the percentages of the drawing area. 709e41f4b71Sopenharmony_ci const GLfloat shapeVertices[] = { 710e41f4b71Sopenharmony_ci centerX / width_, centerY / height_, 711e41f4b71Sopenharmony_ci leftX / width_, leftY / height_, 712e41f4b71Sopenharmony_ci rotateX / width_, rotateY / height_, 713e41f4b71Sopenharmony_ci rightX / width_, rightY / height_ 714e41f4b71Sopenharmony_ci }; 715e41f4b71Sopenharmony_ci 716e41f4b71Sopenharmony_ci if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { 717e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed"); 718e41f4b71Sopenharmony_ci return; 719e41f4b71Sopenharmony_ci } 720e41f4b71Sopenharmony_ci 721e41f4b71Sopenharmony_ci GLfloat rad = M_PI / 180 * 72; 722e41f4b71Sopenharmony_ci for (int i = 0; i < 4; ++i) 723e41f4b71Sopenharmony_ci { 724e41f4b71Sopenharmony_ci // Obtain the vertices of the other four quadrilaterals through rotation. 725e41f4b71Sopenharmony_ci rotate2d(centerX, centerY, &rotateX, &rotateY,rad); 726e41f4b71Sopenharmony_ci rotate2d(centerX, centerY, &leftX, &leftY,rad); 727e41f4b71Sopenharmony_ci rotate2d(centerX, centerY, &rightX, &rightY,rad); 728e41f4b71Sopenharmony_ci 729e41f4b71Sopenharmony_ci // Determine the vertices for drawing the quadrilateral, which are represented by the percentages of the drawing area. 730e41f4b71Sopenharmony_ci const GLfloat shapeVertices[] = { 731e41f4b71Sopenharmony_ci centerX / width_, centerY / height_, 732e41f4b71Sopenharmony_ci leftX / width_, leftY / height_, 733e41f4b71Sopenharmony_ci rotateX / width_, rotateY / height_, 734e41f4b71Sopenharmony_ci rightX / width_, rightY / height_ 735e41f4b71Sopenharmony_ci }; 736e41f4b71Sopenharmony_ci 737e41f4b71Sopenharmony_ci // Draw the shape. 738e41f4b71Sopenharmony_ci if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { 739e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed"); 740e41f4b71Sopenharmony_ci return; 741e41f4b71Sopenharmony_ci } 742e41f4b71Sopenharmony_ci } 743e41f4b71Sopenharmony_ci 744e41f4b71Sopenharmony_ci // End drawing. 745e41f4b71Sopenharmony_ci if (!FinishDraw()) { 746e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed"); 747e41f4b71Sopenharmony_ci return; 748e41f4b71Sopenharmony_ci } 749e41f4b71Sopenharmony_ci 750e41f4b71Sopenharmony_ci flag_ = true; 751e41f4b71Sopenharmony_ci } 752e41f4b71Sopenharmony_ci ``` 753e41f4b71Sopenharmony_ci 754e41f4b71Sopenharmony_ci (3) Change the colors, by drawing a new shape with the same size but different colors and replacing the original shape with the new shape. 755e41f4b71Sopenharmony_ci 756e41f4b71Sopenharmony_ci ```c++ 757e41f4b71Sopenharmony_ci void EGLCore::ChangeColor() 758e41f4b71Sopenharmony_ci { 759e41f4b71Sopenharmony_ci if (!flag_) { 760e41f4b71Sopenharmony_ci return; 761e41f4b71Sopenharmony_ci } 762e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor"); 763e41f4b71Sopenharmony_ci GLint position = PrepareDraw(); 764e41f4b71Sopenharmony_ci if (position == POSITION_ERROR) { 765e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed"); 766e41f4b71Sopenharmony_ci return; 767e41f4b71Sopenharmony_ci } 768e41f4b71Sopenharmony_ci 769e41f4b71Sopenharmony_ci // Draw the background. 770e41f4b71Sopenharmony_ci if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES, 771e41f4b71Sopenharmony_ci sizeof(BACKGROUND_RECTANGLE_VERTICES))) { 772e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed"); 773e41f4b71Sopenharmony_ci return; 774e41f4b71Sopenharmony_ci } 775e41f4b71Sopenharmony_ci 776e41f4b71Sopenharmony_ci // Determine the vertices for drawing the quadrilateral, which are represented by the percentages of the drawing area. 777e41f4b71Sopenharmony_ci GLfloat rotateX = 0; 778e41f4b71Sopenharmony_ci GLfloat rotateY = FIFTY_PERCENT * height_; 779e41f4b71Sopenharmony_ci GLfloat centerX = 0; 780e41f4b71Sopenharmony_ci GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); 781e41f4b71Sopenharmony_ci GLfloat leftX = -rotateY * (M_PI / 180 * 18); 782e41f4b71Sopenharmony_ci GLfloat leftY = 0; 783e41f4b71Sopenharmony_ci GLfloat rightX = rotateY * (M_PI / 180 * 18); 784e41f4b71Sopenharmony_ci GLfloat rightY = 0; 785e41f4b71Sopenharmony_ci 786e41f4b71Sopenharmony_ci // Determine the vertices for drawing the quadrilateral, which are represented by the percentages of the drawing area. 787e41f4b71Sopenharmony_ci const GLfloat shapeVertices[] = { 788e41f4b71Sopenharmony_ci centerX / width_, centerY / height_, 789e41f4b71Sopenharmony_ci leftX / width_, leftY / height_, 790e41f4b71Sopenharmony_ci rotateX / width_, rotateY / height_, 791e41f4b71Sopenharmony_ci rightX / width_, rightY / height_ 792e41f4b71Sopenharmony_ci }; 793e41f4b71Sopenharmony_ci 794e41f4b71Sopenharmony_ci // Use the new colors for drawing. 795e41f4b71Sopenharmony_ci if (!ExecuteDrawStar2(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { 796e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed"); 797e41f4b71Sopenharmony_ci return; 798e41f4b71Sopenharmony_ci } 799e41f4b71Sopenharmony_ci 800e41f4b71Sopenharmony_ci GLfloat rad = M_PI / 180 * 72; 801e41f4b71Sopenharmony_ci for (int i = 0; i < 4; ++i) 802e41f4b71Sopenharmony_ci { 803e41f4b71Sopenharmony_ci // Obtain the vertices of the other four quadrilaterals through rotation. 804e41f4b71Sopenharmony_ci rotate2d(centerX, centerY, &rotateX, &rotateY,rad); 805e41f4b71Sopenharmony_ci rotate2d(centerX, centerY, &leftX, &leftY,rad); 806e41f4b71Sopenharmony_ci rotate2d(centerX, centerY, &rightX, &rightY,rad); 807e41f4b71Sopenharmony_ci 808e41f4b71Sopenharmony_ci // Determine the vertices for drawing the quadrilateral, which are represented by the percentages of the drawing area. 809e41f4b71Sopenharmony_ci const GLfloat shapeVertices[] = { 810e41f4b71Sopenharmony_ci centerX / width_, centerY / height_, 811e41f4b71Sopenharmony_ci leftX / width_, leftY / height_, 812e41f4b71Sopenharmony_ci rotateX / width_, rotateY / height_, 813e41f4b71Sopenharmony_ci rightX / width_, rightY / height_ 814e41f4b71Sopenharmony_ci }; 815e41f4b71Sopenharmony_ci 816e41f4b71Sopenharmony_ci // Use the new colors for drawing. 817e41f4b71Sopenharmony_ci if (!ExecuteDrawStar2(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { 818e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed"); 819e41f4b71Sopenharmony_ci return; 820e41f4b71Sopenharmony_ci } 821e41f4b71Sopenharmony_ci } 822e41f4b71Sopenharmony_ci 823e41f4b71Sopenharmony_ci // End drawing. 824e41f4b71Sopenharmony_ci if (!FinishDraw()) { 825e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed"); 826e41f4b71Sopenharmony_ci } 827e41f4b71Sopenharmony_ci } 828e41f4b71Sopenharmony_ci ``` 829e41f4b71Sopenharmony_ci 830e41f4b71Sopenharmony_ci6. Release related resources. 831e41f4b71Sopenharmony_ci 832e41f4b71Sopenharmony_ci (1) Create the **Release()** method in the **EGLCore** class to release the resources requested during environment initialization, including the window display, rendering area surface, and environment context. 833e41f4b71Sopenharmony_ci 834e41f4b71Sopenharmony_ci ```c++ 835e41f4b71Sopenharmony_ci void EGLCore::Release() 836e41f4b71Sopenharmony_ci { 837e41f4b71Sopenharmony_ci // Release the surface. 838e41f4b71Sopenharmony_ci if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) { 839e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed"); 840e41f4b71Sopenharmony_ci } 841e41f4b71Sopenharmony_ci // Release the context. 842e41f4b71Sopenharmony_ci if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) { 843e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed"); 844e41f4b71Sopenharmony_ci } 845e41f4b71Sopenharmony_ci // Release the display. 846e41f4b71Sopenharmony_ci if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) { 847e41f4b71Sopenharmony_ci OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed"); 848e41f4b71Sopenharmony_ci } 849e41f4b71Sopenharmony_ci } 850e41f4b71Sopenharmony_ci ``` 851e41f4b71Sopenharmony_ci 852e41f4b71Sopenharmony_ci (2) Add the **Release()** method to the **PluginRender** class to release the **EGLCore** and **PluginRender** instances. 853e41f4b71Sopenharmony_ci 854e41f4b71Sopenharmony_ci ```c++ 855e41f4b71Sopenharmony_ci void PluginRender::Release(std::string &id) 856e41f4b71Sopenharmony_ci { 857e41f4b71Sopenharmony_ci PluginRender *render = PluginRender::GetInstance(id); 858e41f4b71Sopenharmony_ci if (render != nullptr) { 859e41f4b71Sopenharmony_ci render->eglCore_->Release(); 860e41f4b71Sopenharmony_ci delete render->eglCore_; 861e41f4b71Sopenharmony_ci render->eglCore_ = nullptr; 862e41f4b71Sopenharmony_ci delete render; 863e41f4b71Sopenharmony_ci render = nullptr; 864e41f4b71Sopenharmony_ci instance_.erase(instance_.find(id)); 865e41f4b71Sopenharmony_ci } 866e41f4b71Sopenharmony_ci } 867e41f4b71Sopenharmony_ci ``` 868e41f4b71Sopenharmony_ci 869e41f4b71Sopenharmony_ci7. Use the CMake toolchain to compile the C++ source code into a dynamic link library (DLL) file. 870e41f4b71Sopenharmony_ci 871e41f4b71Sopenharmony_ci ```CMake 872e41f4b71Sopenharmony_ci # Set the minimum CMake version. 873e41f4b71Sopenharmony_ci cmake_minimum_required(VERSION 3.4.1) 874e41f4b71Sopenharmony_ci # Project name 875e41f4b71Sopenharmony_ci project(XComponent) 876e41f4b71Sopenharmony_ci 877e41f4b71Sopenharmony_ci set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 878e41f4b71Sopenharmony_ci add_definitions(-DOHOS_PLATFORM) 879e41f4b71Sopenharmony_ci # Set the header file search directory. 880e41f4b71Sopenharmony_ci include_directories( 881e41f4b71Sopenharmony_ci ${NATIVERENDER_ROOT_PATH} 882e41f4b71Sopenharmony_ci ${NATIVERENDER_ROOT_PATH}/include 883e41f4b71Sopenharmony_ci ) 884e41f4b71Sopenharmony_ci # Add the **nativerender** dynamic library, with the **libnativerender.so** library file. Add the .cpp files. 885e41f4b71Sopenharmony_ci add_library(nativerender SHARED 886e41f4b71Sopenharmony_ci render/egl_core.cpp 887e41f4b71Sopenharmony_ci render/plugin_render.cpp 888e41f4b71Sopenharmony_ci manager/plugin_manager.cpp 889e41f4b71Sopenharmony_ci napi_init.cpp 890e41f4b71Sopenharmony_ci ) 891e41f4b71Sopenharmony_ci 892e41f4b71Sopenharmony_ci find_library( 893e41f4b71Sopenharmony_ci EGL-lib 894e41f4b71Sopenharmony_ci EGL 895e41f4b71Sopenharmony_ci ) 896e41f4b71Sopenharmony_ci 897e41f4b71Sopenharmony_ci find_library( 898e41f4b71Sopenharmony_ci GLES-lib 899e41f4b71Sopenharmony_ci GLESv3 900e41f4b71Sopenharmony_ci ) 901e41f4b71Sopenharmony_ci 902e41f4b71Sopenharmony_ci find_library( 903e41f4b71Sopenharmony_ci hilog-lib 904e41f4b71Sopenharmony_ci hilog_ndk.z 905e41f4b71Sopenharmony_ci ) 906e41f4b71Sopenharmony_ci 907e41f4b71Sopenharmony_ci find_library( 908e41f4b71Sopenharmony_ci libace-lib 909e41f4b71Sopenharmony_ci ace_ndk.z 910e41f4b71Sopenharmony_ci ) 911e41f4b71Sopenharmony_ci 912e41f4b71Sopenharmony_ci find_library( 913e41f4b71Sopenharmony_ci libnapi-lib 914e41f4b71Sopenharmony_ci ace_napi.z 915e41f4b71Sopenharmony_ci ) 916e41f4b71Sopenharmony_ci 917e41f4b71Sopenharmony_ci find_library( 918e41f4b71Sopenharmony_ci libuv-lib 919e41f4b71Sopenharmony_ci uv 920e41f4b71Sopenharmony_ci ) 921e41f4b71Sopenharmony_ci # Add the libraries to be linked. 922e41f4b71Sopenharmony_ci target_link_libraries(nativerender PUBLIC 923e41f4b71Sopenharmony_ci ${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib}) 924e41f4b71Sopenharmony_ci ``` 925e41f4b71Sopenharmony_ci 926