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![onLoad](./figures/onLoad.png)
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![onDestroy](./figures/onDestroy.png)
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