diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 index cd0de013..739fe627 100644 --- a/entry/build-profile.json5 +++ b/entry/build-profile.json5 @@ -1,31 +1,18 @@ { "apiType": "stageMode", "buildOption": { - "resOptions": { - "copyCodeResource": { - "enable": false - }, - }, "externalNativeOptions": { "path": "./src/main/cpp/CMakeLists.txt", - "arguments": "-DCMAKE_BUILD_TYPE=Release", + "arguments": "", "cppFlags": "", "abiFilters": [ "x86_64" - ], - }, - "arkOptions": { - "runtimeOnly" : { - "packages": [ - "libopencax.so" - ] - } + ] } }, "buildOptionSet": [ { "name": "release", - "debuggable": true, "arkOptions": { "obfuscation": { "ruleOptions": { @@ -46,7 +33,7 @@ ], "targets": [ { - "name": "default", + "name": "default" }, { "name": "ohosTest", diff --git a/entry/libs/x86_64/libNativeAdd.so b/entry/libs/x86_64/libNativeAdd.so new file mode 100644 index 00000000..ddbc917e Binary files /dev/null and b/entry/libs/x86_64/libNativeAdd.so differ diff --git a/entry/libs/x86_64/libTKBO.so.7.9 b/entry/libs/x86_64/libTKBO.so.7.9 index a5693c68..beccaaf8 100644 Binary files a/entry/libs/x86_64/libTKBO.so.7.9 and b/entry/libs/x86_64/libTKBO.so.7.9 differ diff --git a/entry/libs/x86_64/libTKBRep.so.7.9 b/entry/libs/x86_64/libTKBRep.so.7.9 index c98ddc22..1c8de328 100644 Binary files a/entry/libs/x86_64/libTKBRep.so.7.9 and b/entry/libs/x86_64/libTKBRep.so.7.9 differ diff --git a/entry/libs/x86_64/libTKBin.so.7.9 b/entry/libs/x86_64/libTKBin.so.7.9 index 0b16e150..64a46c9e 100644 Binary files a/entry/libs/x86_64/libTKBin.so.7.9 and b/entry/libs/x86_64/libTKBin.so.7.9 differ diff --git a/entry/libs/x86_64/libTKBinL.so.7.9 b/entry/libs/x86_64/libTKBinL.so.7.9 index 161b676d..87da7f75 100644 Binary files a/entry/libs/x86_64/libTKBinL.so.7.9 and b/entry/libs/x86_64/libTKBinL.so.7.9 differ diff --git a/entry/libs/x86_64/libTKBinTObj.so.7.9 b/entry/libs/x86_64/libTKBinTObj.so.7.9 index 1b198d71..742c8633 100644 Binary files a/entry/libs/x86_64/libTKBinTObj.so.7.9 and b/entry/libs/x86_64/libTKBinTObj.so.7.9 differ diff --git a/entry/libs/x86_64/libTKBinXCAF.so.7.9 b/entry/libs/x86_64/libTKBinXCAF.so.7.9 index b2446939..299ea159 100644 Binary files a/entry/libs/x86_64/libTKBinXCAF.so.7.9 and b/entry/libs/x86_64/libTKBinXCAF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKBool.so.7.9 b/entry/libs/x86_64/libTKBool.so.7.9 index c620c0e4..5e6a0e3c 100644 Binary files a/entry/libs/x86_64/libTKBool.so.7.9 and b/entry/libs/x86_64/libTKBool.so.7.9 differ diff --git a/entry/libs/x86_64/libTKCAF.so.7.9 b/entry/libs/x86_64/libTKCAF.so.7.9 index 4149045a..2d6620ad 100644 Binary files a/entry/libs/x86_64/libTKCAF.so.7.9 and b/entry/libs/x86_64/libTKCAF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKCDF.so.7.9 b/entry/libs/x86_64/libTKCDF.so.7.9 index cc433e1d..c68ea848 100644 Binary files a/entry/libs/x86_64/libTKCDF.so.7.9 and b/entry/libs/x86_64/libTKCDF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDE.so.7.9 b/entry/libs/x86_64/libTKDE.so.7.9 index 0558ed88..3b9c0cfe 100644 Binary files a/entry/libs/x86_64/libTKDE.so.7.9 and b/entry/libs/x86_64/libTKDE.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDECascade.so.7.9 b/entry/libs/x86_64/libTKDECascade.so.7.9 index 89811331..0b08516e 100644 Binary files a/entry/libs/x86_64/libTKDECascade.so.7.9 and b/entry/libs/x86_64/libTKDECascade.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDEGLTF.so.7.9 b/entry/libs/x86_64/libTKDEGLTF.so.7.9 index b9f77727..dd3a061b 100644 Binary files a/entry/libs/x86_64/libTKDEGLTF.so.7.9 and b/entry/libs/x86_64/libTKDEGLTF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDEIGES.so.7.9 b/entry/libs/x86_64/libTKDEIGES.so.7.9 index fd0b3636..f270c1ec 100644 Binary files a/entry/libs/x86_64/libTKDEIGES.so.7.9 and b/entry/libs/x86_64/libTKDEIGES.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDEOBJ.so.7.9 b/entry/libs/x86_64/libTKDEOBJ.so.7.9 index 8cccb9e2..311afb6f 100644 Binary files a/entry/libs/x86_64/libTKDEOBJ.so.7.9 and b/entry/libs/x86_64/libTKDEOBJ.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDEPLY.so.7.9 b/entry/libs/x86_64/libTKDEPLY.so.7.9 index b65e667c..2acf8f54 100644 Binary files a/entry/libs/x86_64/libTKDEPLY.so.7.9 and b/entry/libs/x86_64/libTKDEPLY.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDESTEP.so.7.9 b/entry/libs/x86_64/libTKDESTEP.so.7.9 index e49e3ac6..7570bf8a 100644 Binary files a/entry/libs/x86_64/libTKDESTEP.so.7.9 and b/entry/libs/x86_64/libTKDESTEP.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDESTL.so.7.9 b/entry/libs/x86_64/libTKDESTL.so.7.9 index 255b53e5..5a667adb 100644 Binary files a/entry/libs/x86_64/libTKDESTL.so.7.9 and b/entry/libs/x86_64/libTKDESTL.so.7.9 differ diff --git a/entry/libs/x86_64/libTKDEVRML.so.7.9 b/entry/libs/x86_64/libTKDEVRML.so.7.9 index 12539208..c0367fe4 100644 Binary files a/entry/libs/x86_64/libTKDEVRML.so.7.9 and b/entry/libs/x86_64/libTKDEVRML.so.7.9 differ diff --git a/entry/libs/x86_64/libTKExpress.so.7.9 b/entry/libs/x86_64/libTKExpress.so.7.9 new file mode 100644 index 00000000..18ebd403 Binary files /dev/null and b/entry/libs/x86_64/libTKExpress.so.7.9 differ diff --git a/entry/libs/x86_64/libTKFeat.so.7.9 b/entry/libs/x86_64/libTKFeat.so.7.9 index 3cdc4196..fb1c1136 100644 Binary files a/entry/libs/x86_64/libTKFeat.so.7.9 and b/entry/libs/x86_64/libTKFeat.so.7.9 differ diff --git a/entry/libs/x86_64/libTKFillet.so.7.9 b/entry/libs/x86_64/libTKFillet.so.7.9 index 55317bfc..5d8f4f12 100644 Binary files a/entry/libs/x86_64/libTKFillet.so.7.9 and b/entry/libs/x86_64/libTKFillet.so.7.9 differ diff --git a/entry/libs/x86_64/libTKG2d.so.7.9 b/entry/libs/x86_64/libTKG2d.so.7.9 index a3cce573..3dc03b42 100644 Binary files a/entry/libs/x86_64/libTKG2d.so.7.9 and b/entry/libs/x86_64/libTKG2d.so.7.9 differ diff --git a/entry/libs/x86_64/libTKG3d.so.7.9 b/entry/libs/x86_64/libTKG3d.so.7.9 index c52c533e..21044606 100644 Binary files a/entry/libs/x86_64/libTKG3d.so.7.9 and b/entry/libs/x86_64/libTKG3d.so.7.9 differ diff --git a/entry/libs/x86_64/libTKGeomAlgo.so.7.9 b/entry/libs/x86_64/libTKGeomAlgo.so.7.9 index 130293bd..361d7a70 100644 Binary files a/entry/libs/x86_64/libTKGeomAlgo.so.7.9 and b/entry/libs/x86_64/libTKGeomAlgo.so.7.9 differ diff --git a/entry/libs/x86_64/libTKGeomBase.so.7.9 b/entry/libs/x86_64/libTKGeomBase.so.7.9 index 37260bfa..192cec2c 100644 Binary files a/entry/libs/x86_64/libTKGeomBase.so.7.9 and b/entry/libs/x86_64/libTKGeomBase.so.7.9 differ diff --git a/entry/libs/x86_64/libTKHLR.so.7.9 b/entry/libs/x86_64/libTKHLR.so.7.9 index b25c357a..fcf53d66 100644 Binary files a/entry/libs/x86_64/libTKHLR.so.7.9 and b/entry/libs/x86_64/libTKHLR.so.7.9 differ diff --git a/entry/libs/x86_64/libTKLCAF.so.7.9 b/entry/libs/x86_64/libTKLCAF.so.7.9 index 440bf9d1..4d5cf4e8 100644 Binary files a/entry/libs/x86_64/libTKLCAF.so.7.9 and b/entry/libs/x86_64/libTKLCAF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKMath.so.7.9 b/entry/libs/x86_64/libTKMath.so.7.9 index 5b94b28d..28030973 100644 Binary files a/entry/libs/x86_64/libTKMath.so.7.9 and b/entry/libs/x86_64/libTKMath.so.7.9 differ diff --git a/entry/libs/x86_64/libTKMesh.so.7.9 b/entry/libs/x86_64/libTKMesh.so.7.9 index cea5129b..8b5ee82b 100644 Binary files a/entry/libs/x86_64/libTKMesh.so.7.9 and b/entry/libs/x86_64/libTKMesh.so.7.9 differ diff --git a/entry/libs/x86_64/libTKMeshVS.so.7.9 b/entry/libs/x86_64/libTKMeshVS.so.7.9 index 97cc4a93..d2bed04f 100644 Binary files a/entry/libs/x86_64/libTKMeshVS.so.7.9 and b/entry/libs/x86_64/libTKMeshVS.so.7.9 differ diff --git a/entry/libs/x86_64/libTKOffset.so.7.9 b/entry/libs/x86_64/libTKOffset.so.7.9 index ddf08b0d..3534aef4 100644 Binary files a/entry/libs/x86_64/libTKOffset.so.7.9 and b/entry/libs/x86_64/libTKOffset.so.7.9 differ diff --git a/entry/libs/x86_64/libTKOpenGles.so.7.9 b/entry/libs/x86_64/libTKOpenGles.so.7.9 index e67563a9..5508d4e3 100644 Binary files a/entry/libs/x86_64/libTKOpenGles.so.7.9 and b/entry/libs/x86_64/libTKOpenGles.so.7.9 differ diff --git a/entry/libs/x86_64/libTKPrim.so.7.9 b/entry/libs/x86_64/libTKPrim.so.7.9 index 8fd97f4d..7e12a5f0 100644 Binary files a/entry/libs/x86_64/libTKPrim.so.7.9 and b/entry/libs/x86_64/libTKPrim.so.7.9 differ diff --git a/entry/libs/x86_64/libTKRWMesh.so.7.9 b/entry/libs/x86_64/libTKRWMesh.so.7.9 index 9dee1b75..8e45bea0 100644 Binary files a/entry/libs/x86_64/libTKRWMesh.so.7.9 and b/entry/libs/x86_64/libTKRWMesh.so.7.9 differ diff --git a/entry/libs/x86_64/libTKService.so.7.9 b/entry/libs/x86_64/libTKService.so.7.9 index 16f2b3d0..533f66c5 100644 Binary files a/entry/libs/x86_64/libTKService.so.7.9 and b/entry/libs/x86_64/libTKService.so.7.9 differ diff --git a/entry/libs/x86_64/libTKShHealing.so.7.9 b/entry/libs/x86_64/libTKShHealing.so.7.9 index 63180e86..e39efd9b 100644 Binary files a/entry/libs/x86_64/libTKShHealing.so.7.9 and b/entry/libs/x86_64/libTKShHealing.so.7.9 differ diff --git a/entry/libs/x86_64/libTKStd.so.7.9 b/entry/libs/x86_64/libTKStd.so.7.9 index f2aab953..626309ab 100644 Binary files a/entry/libs/x86_64/libTKStd.so.7.9 and b/entry/libs/x86_64/libTKStd.so.7.9 differ diff --git a/entry/libs/x86_64/libTKStdL.so.7.9 b/entry/libs/x86_64/libTKStdL.so.7.9 index ece2be82..49312d1d 100644 Binary files a/entry/libs/x86_64/libTKStdL.so.7.9 and b/entry/libs/x86_64/libTKStdL.so.7.9 differ diff --git a/entry/libs/x86_64/libTKTObj.so.7.9 b/entry/libs/x86_64/libTKTObj.so.7.9 index 1194029f..f5d58ed2 100644 Binary files a/entry/libs/x86_64/libTKTObj.so.7.9 and b/entry/libs/x86_64/libTKTObj.so.7.9 differ diff --git a/entry/libs/x86_64/libTKTopAlgo.so.7.9 b/entry/libs/x86_64/libTKTopAlgo.so.7.9 index a9fc40d1..cd89d017 100644 Binary files a/entry/libs/x86_64/libTKTopAlgo.so.7.9 and b/entry/libs/x86_64/libTKTopAlgo.so.7.9 differ diff --git a/entry/libs/x86_64/libTKV3d.so.7.9 b/entry/libs/x86_64/libTKV3d.so.7.9 index 5b319c6b..faabb5fc 100644 Binary files a/entry/libs/x86_64/libTKV3d.so.7.9 and b/entry/libs/x86_64/libTKV3d.so.7.9 differ diff --git a/entry/libs/x86_64/libTKVCAF.so.7.9 b/entry/libs/x86_64/libTKVCAF.so.7.9 index a76807fd..11f4db4f 100644 Binary files a/entry/libs/x86_64/libTKVCAF.so.7.9 and b/entry/libs/x86_64/libTKVCAF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXCAF.so.7.9 b/entry/libs/x86_64/libTKXCAF.so.7.9 index 35b8774f..490b5e12 100644 Binary files a/entry/libs/x86_64/libTKXCAF.so.7.9 and b/entry/libs/x86_64/libTKXCAF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXMesh.so.7.9 b/entry/libs/x86_64/libTKXMesh.so.7.9 index ace70a00..718409f2 100644 Binary files a/entry/libs/x86_64/libTKXMesh.so.7.9 and b/entry/libs/x86_64/libTKXMesh.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXSBase.so.7.9 b/entry/libs/x86_64/libTKXSBase.so.7.9 index 28057222..7c4b64ab 100644 Binary files a/entry/libs/x86_64/libTKXSBase.so.7.9 and b/entry/libs/x86_64/libTKXSBase.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXml.so.7.9 b/entry/libs/x86_64/libTKXml.so.7.9 index f3fedfd4..2bf83928 100644 Binary files a/entry/libs/x86_64/libTKXml.so.7.9 and b/entry/libs/x86_64/libTKXml.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXmlL.so.7.9 b/entry/libs/x86_64/libTKXmlL.so.7.9 index 16d57e49..18ba3761 100644 Binary files a/entry/libs/x86_64/libTKXmlL.so.7.9 and b/entry/libs/x86_64/libTKXmlL.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXmlTObj.so.7.9 b/entry/libs/x86_64/libTKXmlTObj.so.7.9 index 7b6282ff..2842fe48 100644 Binary files a/entry/libs/x86_64/libTKXmlTObj.so.7.9 and b/entry/libs/x86_64/libTKXmlTObj.so.7.9 differ diff --git a/entry/libs/x86_64/libTKXmlXCAF.so.7.9 b/entry/libs/x86_64/libTKXmlXCAF.so.7.9 index 89738eda..342da756 100644 Binary files a/entry/libs/x86_64/libTKXmlXCAF.so.7.9 and b/entry/libs/x86_64/libTKXmlXCAF.so.7.9 differ diff --git a/entry/libs/x86_64/libTKernel.so.7.9 b/entry/libs/x86_64/libTKernel.so.7.9 index 6a7b71ff..18a791ce 100644 Binary files a/entry/libs/x86_64/libTKernel.so.7.9 and b/entry/libs/x86_64/libTKernel.so.7.9 differ diff --git a/entry/libs/x86_64/libbrotlicommon.so.1 b/entry/libs/x86_64/libbrotlicommon.so.1 deleted file mode 100644 index 2a79804c..00000000 Binary files a/entry/libs/x86_64/libbrotlicommon.so.1 and /dev/null differ diff --git a/entry/libs/x86_64/libbrotlidec.so.1 b/entry/libs/x86_64/libbrotlidec.so.1 deleted file mode 100644 index bce04483..00000000 Binary files a/entry/libs/x86_64/libbrotlidec.so.1 and /dev/null differ diff --git a/entry/libs/x86_64/libbrotlienc.so.1 b/entry/libs/x86_64/libbrotlienc.so.1 deleted file mode 100644 index 55af6b42..00000000 Binary files a/entry/libs/x86_64/libbrotlienc.so.1 and /dev/null differ diff --git a/entry/libs/x86_64/libbz2.so.1.0 b/entry/libs/x86_64/libbz2.so.1.0 deleted file mode 100644 index e945be82..00000000 Binary files a/entry/libs/x86_64/libbz2.so.1.0 and /dev/null differ diff --git a/entry/libs/x86_64/libexpat.so.1 b/entry/libs/x86_64/libexpat.so.1 deleted file mode 100644 index a2703820..00000000 Binary files a/entry/libs/x86_64/libexpat.so.1 and /dev/null differ diff --git a/entry/libs/x86_64/libfontconfig.so.1 b/entry/libs/x86_64/libfontconfig.so.1 deleted file mode 100644 index 0480535d..00000000 Binary files a/entry/libs/x86_64/libfontconfig.so.1 and /dev/null differ diff --git a/entry/libs/x86_64/libfreetype.so.6 b/entry/libs/x86_64/libfreetype.so.6 deleted file mode 100644 index dbd514fc..00000000 Binary files a/entry/libs/x86_64/libfreetype.so.6 and /dev/null differ diff --git a/entry/libs/x86_64/libpng16.so.16 b/entry/libs/x86_64/libpng16.so.16 deleted file mode 100644 index 7664a931..00000000 Binary files a/entry/libs/x86_64/libpng16.so.16 and /dev/null differ diff --git a/entry/libs/x86_64/libz.so.1 b/entry/libs/x86_64/libz.so.1 deleted file mode 100644 index 190094a9..00000000 Binary files a/entry/libs/x86_64/libz.so.1 and /dev/null differ diff --git a/entry/obfuscation-rules.txt b/entry/obfuscation-rules.txt index c0caa13e..1e7e54e1 100644 --- a/entry/obfuscation-rules.txt +++ b/entry/obfuscation-rules.txt @@ -17,7 +17,7 @@ # -keep-property-name: specifies property names that you want to keep # -keep-global-name: specifies names that you want to keep in the global scope -#-enable-property-obfuscation -#-enable-toplevel-obfuscation -#-enable-filename-obfuscation -#-enable-export-obfuscation \ No newline at end of file +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/entry/src/main/cpp/CMakeLists.txt b/entry/src/main/cpp/CMakeLists.txt index 2f55406c..ec74098c 100644 --- a/entry/src/main/cpp/CMakeLists.txt +++ b/entry/src/main/cpp/CMakeLists.txt @@ -9,13 +9,9 @@ add_definitions(-DOHOS_PLATFORM) include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include ${NATIVERENDER_ROOT_PATH}/include/opencascade + ${NATIVERENDER_ROOT_PATH}/include/Add ) -set(CMAKE_SKIP_BUILD_RPATH FALSE) -set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -set(CMAKE_BUILD_RPATH_USE_ORIGIN "\${ORIGIN}") -set(CMAKE_INSTALL_RPATH "\${ORIGIN}") - # OCCT 库目录 set(OCCT_VERSION "7.9") set(OCCT_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}) @@ -29,28 +25,19 @@ foreach(LIB_NAME ${OCCT_CORE_LIBS}) list(APPEND OCCT_IMPORTED_LIBS ${OCCT_LIB_DIR}/lib${LIB_NAME}.so.${OCCT_VERSION}) endforeach() -#THIRD_PARTY_LIBS -set(THIRD_PARTY_LIBS - ${OCCT_LIB_DIR}/libfreetype.so.6 - ${OCCT_LIB_DIR}/libexpat.so.1 - ${OCCT_LIB_DIR}/libfontconfig.so.1 - ${OCCT_LIB_DIR}/libbrotlidec.so.1 - ${OCCT_LIB_DIR}/libbrotlicommon.so.1 - ${OCCT_LIB_DIR}/libbrotlienc.so.1 - ${OCCT_LIB_DIR}/libpng16.so.16 - ${OCCT_LIB_DIR}/libbz2.so.1.0 - ${OCCT_LIB_DIR}/libz.so.1 -) # 添加源文件 add_library(opencax SHARED # Header - EGLCore/EGLCore.h - OCCTRender/OCCTRender.h - OCCTRenderThread/OCCTRenderThread.h + NativeEGLOCCT/EGLConst.h + NativeEGLOCCT/EGLCore.h + NativeEGLOCCT/EGLRender.h + NativeEGLOCCT/NativeRender.h + NativeEGLOCCT/NativeManager.h # Cpp Src - EGLCore/EGLCore.cpp - OCCTRender/OCCTRender.cpp - OCCTRenderThread/OCCTRenderThread.cpp + NativeEGLOCCT/EGLCore.cpp + NativeEGLOCCT/EGLRender.cpp + NativeEGLOCCT/NativeRender.cpp + NativeEGLOCCT/NativeManager.cpp napi_init.cpp ) @@ -72,6 +59,6 @@ target_link_libraries(opencax PUBLIC ${GLES-lib} #OCCT核心库 ${OCCT_IMPORTED_LIBS} - ${THIRD_PARTY_LIBS} + ${OCCT_LIB_DIR}/libNativeAdd.so ) diff --git a/entry/src/main/cpp/EGLCore/EGLCore.cpp b/entry/src/main/cpp/EGLCore/EGLCore.cpp deleted file mode 100644 index be9cbb72..00000000 --- a/entry/src/main/cpp/EGLCore/EGLCore.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Created on 2026/2/18. -// -// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, -// please include "napi/native_api.h". -#include "EGLCore.h" -#include -#include - -EGLCore::EGLCore() : m_display(EGL_NO_DISPLAY), m_context(EGL_NO_CONTEXT), m_surface(EGL_NO_SURFACE) {} - -EGLCore::~EGLCore() { - release(); -} - -bool EGLCore::init(EGLNativeWindowType window) { - m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (m_display == EGL_NO_DISPLAY) return false; - - if (!eglInitialize(m_display, nullptr, nullptr)) return false; - - const EGLint attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_NONE - }; - - EGLConfig config; - EGLint numConfigs; - eglChooseConfig(m_display, attribs, &config, 1, &numConfigs); - - const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - m_context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, contextAttribs); - if (m_context == EGL_NO_CONTEXT) return false; - - m_surface = eglCreateWindowSurface(m_display, config, window, nullptr); - if (m_surface == EGL_NO_SURFACE) return false; - - m_initialized = true; - return true; -} - -void EGLCore::makeCurrent() { - if (m_initialized) { - eglMakeCurrent(m_display, m_surface, m_surface, m_context); - } -} - -void EGLCore::swapBuffers() { - if (m_initialized) { - eglSwapBuffers(m_display, m_surface); - } -} - -void EGLCore::release() { - if (m_display != EGL_NO_DISPLAY) { - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (m_context != EGL_NO_CONTEXT) eglDestroyContext(m_display, m_context); - if (m_surface != EGL_NO_SURFACE) eglDestroySurface(m_display, m_surface); - eglTerminate(m_display); - } - m_display = EGL_NO_DISPLAY; - m_context = EGL_NO_CONTEXT; - m_surface = EGL_NO_SURFACE; - m_initialized = false; -} \ No newline at end of file diff --git a/entry/src/main/cpp/EGLCore/EGLCore.h b/entry/src/main/cpp/EGLCore/EGLCore.h deleted file mode 100644 index b38f170f..00000000 --- a/entry/src/main/cpp/EGLCore/EGLCore.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created on 2026/2/18. -// -// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, -// please include "napi/native_api.h". - -#ifndef EGLCORE_H -#define EGLCORE_H -#include -#include - -class EGLCore { -public: - EGLCore(); - ~EGLCore(); - - bool init(EGLNativeWindowType window); - void makeCurrent(); - void swapBuffers(); - void release(); - -private: - EGLDisplay m_display; - EGLContext m_context; - EGLSurface m_surface; - bool m_initialized = false; -}; - -#endif // EGLCORE_H \ No newline at end of file diff --git a/entry/src/main/cpp/NativeEGLOCCT/EGLConst.h b/entry/src/main/cpp/NativeEGLOCCT/EGLConst.h new file mode 100644 index 00000000..b0739f5a --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/EGLConst.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVEXCOMPONENT_EGLCONST_H +#define NATIVEXCOMPONENT_EGLCONST_H +// [Start egl_const_h] +// EGLConst.h +#include +#include +#include + +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; + +/** + * Program 错误 + */ +const GLuint PROGRAM_ERROR = 0; + +/** + * 位置错误。 + */ +const GLint POSITION_ERROR = -1; + +/** + * 默认x坐标。 + */ +const int DEFAULT_X_POSITION = 0; + +/** + * 默认y坐标。 + */ +const int DEFAULT_Y_POSITION = 0; + +/** + * Gl 红色默认值。 + */ +const GLfloat GL_RED_DEFAULT = 0.0; + +/** + * Gl 绿色默认值。 + */ +const GLfloat GL_GREEN_DEFAULT = 0.0; + +/** + * Gl 蓝色默认值。 + */ +const GLfloat GL_BLUE_DEFAULT = 0.0; + +/** + * Gl 透明度。 + */ +const GLfloat GL_ALPHA_DEFAULT = 1.0; + +/** + * Pointer 数量。 + */ +const GLint POINTER_SIZE = 2; + +/** + * Triangle fan 尺寸。 + */ +const GLsizei TRIANGLE_FAN_SIZE = 4; + +/** + * 50%。 + */ +const float FIFTY_PERCENT = 0.5; + +/** + * 位置句柄名字。 + */ +const char POSITION_NAME[] = "a_position"; + +// [StartExclude egl_const_h] +/** + * numeric value 0. + */ +const int NUM_0 = 0; + +/** + * numeric value 4. + */ +const int NUM_4 = 4; +// [EndExclude egl_const_h] + +/** + * 背景色 #f4f4f4. + */ +const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f}; + +// [StartExclude egl_const_h] +/** + * Background color #ffffff00. + */ +const GLfloat TRANSPARENT_COLOR[] = {255.0f / 255, 255.0f / 255, 255.0f / 255, 0.0f}; +// [EndExclude egl_const_h] + +/** + * Draw 颜色 #7E8FFB. + */ +const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f}; + +/** + * Change 颜色 #92D6CC. + */ +const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f}; + +/** + * 背景区域。 + */ +const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f}; + +const EGLint ATTRIB_LIST[] = { + // 键,值。 + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + // 结束。 + EGL_NONE}; + +const EGLint CONTEXT_ATTRIBS[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + +/** + * 顶点着色器 + */ +const char VERTEX_SHADER[] = "#version 300 es\n" + "layout(location = 0) in vec4 a_position;\n" + "layout(location = 1) in vec4 a_color; \n" + "out vec4 v_color; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_color = a_color; \n" + "} \n"; + +/** + * 片元着色器。 + */ +const char FRAGMENT_SHADER[] = "#version 300 es\n" + "precision mediump float; \n" + "in vec4 v_color; \n" + "out vec4 fragColor; \n" + "void main() \n" + "{ \n" + " fragColor = v_color; \n" + "} \n"; +// [End egl_const_h] +#endif // NATIVEXCOMPONENT_EGLCONST_H diff --git a/entry/src/main/cpp/NativeEGLOCCT/EGLCore.cpp b/entry/src/main/cpp/NativeEGLOCCT/EGLCore.cpp new file mode 100644 index 00000000..8ca1e5a7 --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/EGLCore.cpp @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EGLCore.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +namespace NativeOpenCAX { +namespace { +constexpr int32_t NUM_4 = 4; +/** + * Vertex shader. + */ +const char VERTEX_SHADER[] = "#version 300 es\n" + "layout(location = 0) in vec4 a_position;\n" + "layout(location = 1) in vec4 a_color; \n" + "out vec4 v_color; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_color = a_color; \n" + "} \n"; + +/** + * Fragment shader. + */ +const char FRAGMENT_SHADER[] = "#version 300 es\n" + "precision mediump float; \n" + "in vec4 v_color; \n" + "out vec4 fragColor; \n" + "void main() \n" + "{ \n" + " fragColor = v_color; \n" + "} \n"; +// [Start native_color] +/** + * 绘制背景颜色 #f4f4f4. + */ +const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f}; + +/** + * 绘制图案颜色 #7E8FFB. + */ +const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f}; + +/** + * 绘制图案改变后的颜色 #92D6CC. + */ +const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f}; + +/** + * 绘制背景顶点 + */ +const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f, + -1.0f, -1.0f}; +// [End native_color] +/** + * Get context parameter count. + */ +const size_t GET_CONTEXT_PARAM_CNT = 1; + +/** + * Fifty percent. + */ +const float FIFTY_PERCENT = 0.5; + +/** + * Pointer size. + */ +const GLint POINTER_SIZE = 2; + +/** + * Triangle fan size. + */ +const GLsizei TRIANGLE_FAN_SIZE = 4; + +/** + * Egl red size default. + */ +const int EGL_RED_SIZE_DEFAULT = 8; + +/** + * Egl green size default. + */ +const int EGL_GREEN_SIZE_DEFAULT = 8; + +/** + * Egl blue size default. + */ +const int EGL_BLUE_SIZE_DEFAULT = 8; + +/** + * Egl alpha size default. + */ +const int EGL_ALPHA_SIZE_DEFAULT = 8; + +/** + * Default x position. + */ +const int DEFAULT_X_POSITION = 0; + +/** + * Default y position. + */ +const int DEFAULT_Y_POSITION = 0; + +/** + * Gl red default. + */ +const GLfloat GL_RED_DEFAULT = 0.0; + +/** + * Gl green default. + */ +const GLfloat GL_GREEN_DEFAULT = 0.0; + +/** + * Gl blue default. + */ +const GLfloat GL_BLUE_DEFAULT = 0.0; + +/** + * Gl alpha default. + */ +const GLfloat GL_ALPHA_DEFAULT = 1.0; + +/** + * Program error. + */ +const GLuint PROGRAM_ERROR = 0; + +/** + * Shape vertices size. + */ +const int SHAPE_VERTICES_SIZE = 8; + +/** + * Position handle name. + */ +const char POSITION_NAME[] = "a_position"; + +/** + * Position error. + */ +const GLint POSITION_ERROR = -1; + +/** + * Config attribute list. + */ +const EGLint ATTRIB_LIST[] = { + // Key,value. + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, EGL_RED_SIZE_DEFAULT, + EGL_GREEN_SIZE, EGL_GREEN_SIZE_DEFAULT, + EGL_BLUE_SIZE, EGL_BLUE_SIZE_DEFAULT, + EGL_ALPHA_SIZE, EGL_ALPHA_SIZE_DEFAULT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + // End. + EGL_NONE}; + +/** + * Context attributes. + */ +const EGLint CONTEXT_ATTRIBS[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE}; +} // namespace +// [Start native_create_context_init] +bool EGLCore::EglContextInit(void* window, int width, int height) +{ + // [StartExclude native_create_context_init] + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute"); + if ((window == nullptr) || (width <= 0) || (height <= 0)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit: param error"); + return false; + } + // [EndExclude native_create_context_init] + UpdateSize(width, height); + eglWindow_ = static_cast(window); + + // 初始化display + eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (eglDisplay_ == EGL_NO_DISPLAY) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display"); + return false; + } + // 初始化EGL + EGLint majorVersion; + EGLint minorVersion; + if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglInitialize: unable to get initialize EGL display"); + return false; + } + + // 选择配置 + const EGLint maxConfigSize = 1; + EGLint numConfigs; + if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs"); + return false; + } + // 创建环境 + return CreateEnvironment(); +} +// [End native_create_context_init] +// [Start native_create_environment] +bool EGLCore::CreateEnvironment() +{ + // 创建Surface + if (eglWindow_ == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglWindow_ is null"); + return false; + } + eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL); + if (eglSurface_ == nullptr) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglCreateWindowSurface: unable to create surface"); + return false; + } + // 创建context + eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS); + if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed"); + return false; + } + // 创建program + program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER); + if (program_ == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program"); + return false; + } + return true; +} +// [End native_create_environment] +// [Start native_background] +// 绘制背景颜色 +void EGLCore::Background() +{ + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed"); + return; + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed"); + return; + } +} +// [End native_background] +// [Start native_draw] +void EGLCore::Draw(int& hasDraw) +{ + flag_ = false; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed"); + return; + } + + // 绘制背景 + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed"); + return; + } + + // 将五角星分为五个四边形,计算其中一个四边形的四个顶点 + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // Convert DEG(54° & 18°) to RAD + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // Convert DEG(18°) to RAD + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // Convert DEG(18°) to RAD + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + + // Convert DEG(72°) to RAD + GLfloat rad = M_PI / 180 * 72; + // Rotate four times + // 在文件egl_core.cpp中定义,NUM_4的值为4 + for (int i = 0; i < NUM_4; ++i) { + // 旋转得其他四个四边形的顶点 + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + // 绘制图形 + if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + } + + // 结束绘制 + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed"); + return; + } + hasDraw = 1; + + flag_ = true; +} +// [End native_draw] +// [Start native_change_color] +void EGLCore::ChangeColor(int& hasChangeColor) +{ + if (!flag_) { + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed"); + return; + } + + // 绘制背景 + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed"); + return; + } + + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // Convert DEG(54° & 18°) to RAD + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // Convert DEG(18°) to RAD + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // Convert DEG(18°) to RAD + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + // 使用新的颜色绘制 + if (!ExecuteDrawNewStar(0, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + + // Convert DEG(72°) to RAD + GLfloat rad = M_PI / 180 * 72; + // Rotate four times + // 在文件egl_core.cpp中定义,NUM_4的值为4 + for (int i = 0; i < NUM_4; ++i) { + // 旋转得其他四个四边形的顶点 + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + // 使用新的颜色绘制 + if (!ExecuteDrawNewStar(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + } + + // 结束绘制 + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed"); + } + hasChangeColor = 1; +} +// [StartExclude native_change_color] +// [Start native_prepare_draw] +// 绘前准备,获取position,创建成功时position值从0开始 +GLint EGLCore::PrepareDraw() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) || + (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error"); + return POSITION_ERROR; + } + + // 该gl函数没有返回值。 + glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_); + glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(program_); + + return glGetAttribLocation(program_, POSITION_NAME); +} +// [End native_prepare_draw] +// [Start native_execute_draw] +// 依据传入参数在指定区域绘制指定颜色 +bool EGLCore::ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // 该gl函数没有返回值。 + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} +// [End native_execute_draw] +bool EGLCore::ExecuteDrawStar( + GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glVertexAttribPointer(1, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, color); + glEnableVertexAttribArray(position); + glEnableVertexAttribArray(1); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + glDisableVertexAttribArray(1); + + return true; +} +// [EndExclude native_change_color] +bool EGLCore::ExecuteDrawNewStar( + GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // 该gl函数没有返回值。 + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} +// [End native_change_color] +void EGLCore::Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta) +{ + GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY); + GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY); + *rotateX = tempX + centerX; + *rotateY = tempY + centerY; +} +// [Start native_finish_draw] +// 结束绘制操作 +bool EGLCore::FinishDraw() +{ + // 强制刷新缓冲 + glFlush(); + glFinish(); + return eglSwapBuffers(eglDisplay_, eglSurface_); +} +// [End native_finish_draw] +// [Start native_load_shader] +GLuint EGLCore::LoadShader(GLenum type, const char* shaderSrc) +{ + if ((type <= 0) || (shaderSrc == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader type or shaderSrc error"); + return PROGRAM_ERROR; + } + + GLuint shader = glCreateShader(type); + if (shader == 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader unable to load shader"); + return PROGRAM_ERROR; + } + + // 该gl函数没有返回值。 + glShaderSource(shader, 1, &shaderSrc, nullptr); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (compiled != 0) { + return shader; + } + + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen <= 1) { + glDeleteShader(shader); + return PROGRAM_ERROR; + } + + char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1)); + if (infoLog != nullptr) { + memset(infoLog, 0, infoLen + 1); + glGetShaderInfoLog(shader, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCompileShader error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(shader); + return PROGRAM_ERROR; +} +// [End native_load_shader] +// [Start native_create_program] +GLuint EGLCore::CreateProgram(const char* vertexShader, const char* fragShader) +{ + if ((vertexShader == nullptr) || (fragShader == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram: vertexShader or fragShader is null"); + return PROGRAM_ERROR; + } + + GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader); + if (vertex == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram vertex error"); + return PROGRAM_ERROR; + } + + GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader); + if (fragment == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram fragment error"); + return PROGRAM_ERROR; + } + + GLuint program = glCreateProgram(); + if (program == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram program error"); + glDeleteShader(vertex); + glDeleteShader(fragment); + return PROGRAM_ERROR; + } + + // 该gl函数没有返回值。 + glAttachShader(program, vertex); + glAttachShader(program, fragment); + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (linked != 0) { + glDeleteShader(vertex); + glDeleteShader(fragment); + return program; + } + + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram linked error"); + GLint infoLen = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) { + char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1)); + memset(infoLog, 0, infoLen + 1); + glGetProgramInfoLog(program, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glLinkProgram error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(vertex); + glDeleteShader(fragment); + glDeleteProgram(program); + return PROGRAM_ERROR; +} +// [End native_create_program] +// [Start native_update_size] +void EGLCore::UpdateSize(int width, int height) +{ + // width_和height_在头文件中定义 + width_ = width; + height_ = height; + if (width_ > 0) { + widthPercent_ = FIFTY_PERCENT * height_ / width_; + } +} +// [End native_update_size] +// [Start native_release] +void EGLCore::Release() +{ + // 释放Surface + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed"); + } + // 释放context + if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed"); + } + // 释放display + if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed"); + } +} +// [End native_release] +} // namespace NativeXComponentSample diff --git a/entry/src/main/cpp/NativeEGLOCCT/EGLCore.h b/entry/src/main/cpp/NativeEGLOCCT/EGLCore.h new file mode 100644 index 00000000..af9a697b --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/EGLCore.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef NATIVE_XCOMPONENT_EGL_CORE_H +#define NATIVE_XCOMPONENT_EGL_CORE_H + +#include +#include +#include +#include "string" + +namespace NativeOpenCAX { +class EGLCore { +public: + explicit EGLCore() {} + ~EGLCore() {} + bool EglContextInit(void* window, int width, int height); + bool CreateEnvironment(); + void Draw(int& hasDraw); + void Background(); + void ChangeColor(int& hasChangeColor); + void Release(); + void UpdateSize(int width, int height); + +private: + GLuint LoadShader(GLenum type, const char* shaderSrc); + GLuint CreateProgram(const char* vertexShader, const char* fragShader); + GLint PrepareDraw(); + bool ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); + bool ExecuteDrawStar(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); + bool ExecuteDrawNewStar(GLint position, const GLfloat* color, + const GLfloat shapeVertices[], unsigned long vertSize); + void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta); + bool FinishDraw(); + +private: + EGLNativeWindowType eglWindow_; + EGLDisplay eglDisplay_ = EGL_NO_DISPLAY; + EGLConfig eglConfig_ = EGL_NO_CONFIG_KHR; + EGLSurface eglSurface_ = EGL_NO_SURFACE; + EGLContext eglContext_ = EGL_NO_CONTEXT; + GLuint program_; + bool flag_ = false; + int width_; + int height_; + GLfloat widthPercent_; +}; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_EGL_CORE_H diff --git a/entry/src/main/cpp/NativeEGLOCCT/EGLRender.cpp b/entry/src/main/cpp/NativeEGLOCCT/EGLRender.cpp new file mode 100644 index 00000000..59c196e9 --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/EGLRender.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// [Start egl_render] +// EGLRender.cpp +#include "EGLRender.h" +#include "EGLConst.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat *rotateX, GLfloat *rotateY, GLfloat theta) +{ + GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY); + GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY); + *rotateX = tempX + centerX; + *rotateY = tempY + centerY; +} + +GLuint LoadShader(GLenum type, const char *shaderSrc) +{ + if ((type <= 0) || (shaderSrc == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glCreateShader type or shaderSrc error"); + return PROGRAM_ERROR; + } + + GLuint shader = glCreateShader(type); + if (shader == 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glCreateShader unable to load shader"); + return PROGRAM_ERROR; + } + + // The gl function has no return value. + glShaderSource(shader, 1, &shaderSrc, nullptr); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (compiled != 0) { + return shader; + } + + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen <= 1) { + glDeleteShader(shader); + return PROGRAM_ERROR; + } + + char *infoLog = (char *)malloc(sizeof(char) * (infoLen + 1)); + if (infoLog != nullptr) { + memset(infoLog, 0, infoLen + 1); + glGetShaderInfoLog(shader, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glCompileShader error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(shader); + return PROGRAM_ERROR; +} + +// 创建program +GLuint CreateProgram(const char *vertexShader, const char *fragShader) +{ + if ((vertexShader == nullptr) || (fragShader == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", + "createProgram: vertexShader or fragShader is null"); + return PROGRAM_ERROR; + } + + GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader); + if (vertex == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram vertex error"); + return PROGRAM_ERROR; + } + + GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader); + if (fragment == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram fragment error"); + return PROGRAM_ERROR; + } + + GLuint program = glCreateProgram(); + if (program == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram program error"); + glDeleteShader(vertex); + glDeleteShader(fragment); + return PROGRAM_ERROR; + } + + // 该gl函数没有返回值。 + glAttachShader(program, vertex); + glAttachShader(program, fragment); + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (linked != 0) { + glDeleteShader(vertex); + glDeleteShader(fragment); + return program; + } + + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "createProgram linked error"); + GLint infoLen = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) { + char *infoLog = (char *)malloc(sizeof(char) * (infoLen + 1)); + memset(infoLog, 0, infoLen + 1); + glGetProgramInfoLog(program, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "glLinkProgram error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(vertex); + glDeleteShader(fragment); + glDeleteProgram(program); + return PROGRAM_ERROR; +} +} // namespace + +bool EGLRender::SetUpEGLContext(void *window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLRender", "EglContextInit execute"); + eglWindow_ = (EGLNativeWindowType)(window); + // 初始化display。 + eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (eglDisplay_ == EGL_NO_DISPLAY) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "eglGetDisplay: unable to get EGL display"); + return false; + } + EGLint majorVersion; + EGLint minorVersion; + if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", + "eglInitialize: unable to get initialize EGL display"); + return false; + }; + // 选择配置。 + const EGLint maxConfigSize = 1; + EGLint numConfigs; + if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "eglChooseConfig: unable to choose configs"); + return false; + }; + // 创建环境。 + // 创建 Surface。 + eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL); + if (eglSurface_ == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", + "eglCreateWindowSurface: unable to create surface"); + return false; + } + if (eglSurface_ == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", + "eglCreateWindowSurface: unable to create surface"); + return false; + } + // 创建上下文。 + eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS); + if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "eglMakeCurrent failed"); + return false; + } + return true; +} + +GLint EGLRender::PrepareDraw() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) || + (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "PrepareDraw: param error"); + return POSITION_ERROR; + } + + // 该gl函数没有返回值。 + glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_); + glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(program_); + + return glGetAttribLocation(program_, POSITION_NAME); +} + +// 绘制五角星 +void EGLRender::DrawStar(bool drawColor) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLRender", "Draw"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw get position failed"); + return; + } + + // 绘制背景 + if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw execute draw background failed"); + return; + } + + // 将其划分为五个四边形,并计算其中一个四边形的顶点 + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // 将角度 54° 和 18° 转换为弧度 + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // 将角度 18° 转换为弧度 + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // 将角度 18° 转换为弧度 + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + const GLfloat shapeVertices[] = {centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_}; + auto color = drawColor ? DRAW_COLOR : CHANGE_COLOR; + if (!ExecuteDraw(position, color, shapeVertices)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw execute draw shape failed"); + return; + } + + // 将角度 72° 转换为弧度 + GLfloat rad = M_PI / 180 * 72; + // 旋转四次。 + // 在头文件EGLConst.h中定义,NUM_0的值为0,NUM_4的值为4 + for (int i = NUM_0; i < NUM_4; ++i) { + // 旋转得其他四个四边形的顶点 + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + + // 确定绘制四边形的顶点,使用绘制区域的百分比表示 + const GLfloat shapeVertices[] = {centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_}; + + // 绘制图形 + if (!ExecuteDraw(position, color, shapeVertices)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw execute draw shape failed"); + return; + } + } + // 将绘制命令提交给GPU,GPU执行完成后将渲染结果显示到屏幕 + glFlush(); + glFinish(); + if (!eglSwapBuffers(eglDisplay_, eglSurface_)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "Draw FinishDraw failed"); + return; + } +} + +// [StartExclude egl_render] +void EGLRender::Clear() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) || + (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "PrepareDraw: param error"); + return; + } + + // The gl function has no return value. + glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + glFinish(); + eglSwapBuffers(eglDisplay_, eglSurface_); +} +// [EndExclude egl_render] + +bool EGLRender::ExecuteDraw(GLint position, const GLfloat *color, const GLfloat shapeVertices[]) +{ + if ((position > 0) || (color == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLRender", "ExecuteDraw: param error"); + return false; + } + + // 该gl函数没有返回值。 + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} + +void EGLRender::SetEGLWindowSize(int width, int height) +{ + width_ = width; + height_ = height; +} + +// 释放相关资源 +void EGLRender::DestroySurface() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "EGLRender", "Release eglDestroySurface failed"); + } + + if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "EGLRender", "Release eglDestroySurface failed"); + } + + if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "EGLRender", "Release eglDestroySurface failed"); + } + eglDisplay_ = EGL_NO_DISPLAY; + eglSurface_ = EGL_NO_SURFACE; + eglContext_ = EGL_NO_CONTEXT; +} +// [End egl_render] \ No newline at end of file diff --git a/entry/src/main/cpp/NativeEGLOCCT/EGLRender.h b/entry/src/main/cpp/NativeEGLOCCT/EGLRender.h new file mode 100644 index 00000000..a4b380c7 --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/EGLRender.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVEXCOMPONENT_EGLRENDER_H +#define NATIVEXCOMPONENT_EGLRENDER_H +// [Start egl_render_h] +// EGLRender.h +#include "EGLConst.h" +#include +#include +#include +#include +#include + +class EGLRender { +public: + bool SetUpEGLContext(void *window); + void SetEGLWindowSize(int width, int height); + void DrawStar(bool drawColor); + void DestroySurface(); + // [StartExclude egl_render_h] + void Clear(); + // [EndExclude egl_render_h] + + std::string xcomponentId; + EGLNativeWindowType eglWindow_; + + EGLDisplay eglDisplay_ = EGL_NO_DISPLAY; + EGLConfig eglConfig_ = EGL_NO_CONFIG_KHR; + EGLSurface eglSurface_ = EGL_NO_SURFACE; + EGLContext eglContext_ = EGL_NO_CONTEXT; + GLuint program_; + int width_ = 0; + int height_ = 0; + +private: + GLint PrepareDraw(); + bool ExecuteDraw(GLint position, const GLfloat *color, const GLfloat shapeVertices[]); +}; +// [End egl_render_h] +#endif // NATIVEXCOMPONENT_EGLRENDER_H diff --git a/entry/src/main/cpp/NativeEGLOCCT/NativeManager.cpp b/entry/src/main/cpp/NativeEGLOCCT/NativeManager.cpp new file mode 100644 index 00000000..fa67721b --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/NativeManager.cpp @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NativeManager.h" +#include +#include +#include +#include +#include +#include "arkui/native_node.h" +#include "arkui/native_node_napi.h" +#include "arkui/native_interface.h" +#include "common.h" + +#define COLUMN_MARGIN 10 +#define XC_WIDTH 800 +#define XC_HEIGHT 600 +#define ARG_CNT 2 + +namespace NativeOpenCAX { +// [Start plugin_manager_cpp] +// plugin_manager.cpp +std::unordered_map NativeManager::nodeHandleMap_; +std::unordered_map NativeManager::callbackMap_; +std::unordered_map NativeManager::surfaceHolderMap_; +ArkUI_AccessibilityProvider *NativeManager::provider_ = nullptr; +ArkUI_NativeNodeAPI_1 *nodeAPI = reinterpret_cast( + OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")); +// [StartExclude plugin_manager_cpp] +NativeManager NativeManager::pluginManager_; +OH_NativeXComponent_Callback NativeManager::callback_; +ArkUI_NodeHandle xc; +int32_t NativeManager::hasDraw_ = 0; +int32_t NativeManager::hasChangeColor_ = 0; + +NativeManager::~NativeManager() +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeManager"); + nativeXComponentMap_.clear(); + if (eglcore_ != nullptr) { + delete eglcore_; + eglcore_ = nullptr; + } + + for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) { + if (iter->second != nullptr) { + delete iter->second; + iter->second = nullptr; + } + } + pluginManagerMap_.clear(); +} + +// [Start surface_holder] +void OnSurfaceCreatedNative(OH_ArkUI_SurfaceHolder *holder) +{ + auto window = OH_ArkUI_XComponent_GetNativeWindow(holder); // 获取native window + auto render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + render->SetUpEGLContext(window); // 初始化egl环境 +} + +void OnSurfaceChangedNative(OH_ArkUI_SurfaceHolder *holder, uint64_t width, uint64_t height) +{ + EGLRender* render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + render->SetEGLWindowSize(width, height); // 设置绘制区域大小 + render->DrawStar(true); // 绘制五角星 +} + +void OnSurfaceDestroyedNative(OH_ArkUI_SurfaceHolder *holder) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "on destroyed"); + EGLRender* render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + render->DestroySurface(); // 销毁eglSurface相关资源 +} + +void OnSurfaceShowNative(OH_ArkUI_SurfaceHolder *holder) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface show"); +} + +void OnSurfaceHideNative(OH_ArkUI_SurfaceHolder *holder) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface hide"); +} + +void OnFrameCallbackNative(ArkUI_NodeHandle node, uint64_t timestamp, uint64_t targetTimestamp) +{ + if (!NativeManager::surfaceHolderMap_.count(node)) { + return; + } + static uint64_t count = 0; + count++; + // 在头文件plugin_manager.h中定义,FRAME_COUNT的值为50 + if (count % FRAME_COUNT == 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "OnFrameCallback count = %{public}ld", count); + } +} + +void onEvent(ArkUI_NodeEvent *event) +{ + auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); // 获取组件事件类型 + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on event"); + if (eventType == NODE_TOUCH_EVENT) { + ArkUI_NodeHandle handle = OH_ArkUI_NodeEvent_GetNodeHandle(event); // 获取触发该事件的组件对象 + auto holder = NativeManager::surfaceHolderMap_[handle]; + EGLRender* render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + render->DrawStar(false); // 绘制五角星 + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch"); + } +} +// [End surface_holder] +// [EndExclude plugin_manager_cpp] +static std::string value2String(napi_env env, napi_value value) +{ + size_t stringSize = 0; + napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize); + std::string valueString; + valueString.resize(stringSize); + napi_get_value_string_utf8(env, value, &valueString[0], stringSize+1, &stringSize); + return valueString; +} +// [StartExclude plugin_manager_cpp] +napi_value NativeManager::GetXComponentStatus(napi_env env, napi_callback_info info) +{ + napi_value hasDraw; + napi_value hasChangeColor; + + napi_status ret = napi_create_int32(env, hasDraw_, &(hasDraw)); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_create_int32 hasDraw_ error"); + return nullptr; + } + ret = napi_create_int32(env, hasChangeColor_, &(hasChangeColor)); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_create_int32 hasChangeColor_ error"); + return nullptr; + } + + napi_value obj; + ret = napi_create_object(env, &obj); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_create_object error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasDraw", hasDraw); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_set_named_property hasDraw error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasChangeColor", hasChangeColor); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", + "napi_set_named_property hasChangeColor error"); + return nullptr; + } + return obj; +} +// [Start plugin_draw_pattern] +napi_value NativeManager::NapiDrawPattern(napi_env env, napi_callback_info info) +{ + // [StartExclude plugin_draw_pattern] + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern: env or info is null"); + return nullptr; + } + // [EndExclude plugin_draw_pattern] + // 获取环境变量参数 + napi_value thisArg; + if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern: napi_get_cb_info fail"); + return nullptr; + } + + auto *pluginManger = NativeManager::GetInstance(); + // 调用绘制方法 + pluginManger->eglcore_->Draw(hasDraw_); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "render->eglCore_->Draw() executed"); + + return nullptr; +} +// [End plugin_draw_pattern] +// [Start plugin_on_surface_created] +// 定义一个函数OnSurfaceCreatedCB(),封装初始化环境与绘制背景 +void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) +{ + // [StartExclude plugin_on_surface_created] + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + + std::string id(idStr); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB id=%{public}s", + id.c_str()); + // [EndExclude plugin_on_surface_created] + // 初始化环境与绘制背景 + auto *pluginManger = NativeManager::GetInstance(); + pluginManger->OnSurfaceCreated(component, window); +} +// [End plugin_on_surface_created] +// [Start plugin_on_surface_changed] +// 定义一个函数OnSurfaceChangedCB() +void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window) +{ + // [StartExclude plugin_on_surface_changed] + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceChangedCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + // [EndExclude plugin_on_surface_changed] + auto *pluginManger = NativeManager::GetInstance(); + // 封装OnSurfaceChanged方法 + pluginManger->OnSurfaceChanged(component, window); +} +// [End plugin_on_surface_changed] +// [Start plugin_on_surface_destroyed] +// 定义一个函数OnSurfaceDestroyedCB(),将NativeRender类内释放资源的方法Release()封装在其中 +void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) +{ + // [StartExclude plugin_on_surface_destroyed] + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + // [EndExclude plugin_on_surface_destroyed] + auto *pluginManger = NativeManager::GetInstance(); + pluginManger->OnSurfaceDestroyed(component, window); +} +// [End plugin_on_surface_destroyed] +// [Start plugin_dispatch_touch_event] +// 定义一个函数DispatchTouchEventCB(),响应触摸事件时触发该回调 +void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) +{ + // [StartExclude plugin_dispatch_touch_event] + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + // [EndExclude plugin_dispatch_touch_event] + auto *pluginManger = NativeManager::GetInstance(); + pluginManger->DispatchTouchEvent(component, window); +} +// [End plugin_dispatch_touch_event] +NativeManager::NativeManager() +{ + eglcore_ = new EGLCore(); + callback_.OnSurfaceCreated = OnSurfaceCreatedCB; + callback_.OnSurfaceChanged = OnSurfaceChangedCB; + callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB; + callback_.DispatchTouchEvent = DispatchTouchEventCB; +} +// [Start plugin_create_native_node] +ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) +{ + ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_RELATIVE_CONTAINER); + ArkUI_NumberValue value[] = {480}; + ArkUI_NumberValue value1[] = {{.u32 = 15}, {.f32 = 15}}; + ArkUI_AttributeItem item = {value, 1, "changeSize"}; + ArkUI_AttributeItem item1 = {value1, 2}; + nodeAPI->setAttribute(column, NODE_WIDTH, &item); + value[0].f32 = COLUMN_MARGIN; + nodeAPI->setAttribute(column, NODE_MARGIN, &item); + // 创建XComponent组件 + xc = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT); + // 设置XComponent组件属性 + value[0].u32 = ARKUI_XCOMPONENT_TYPE_SURFACE; + nodeAPI->setAttribute(xc, NODE_XCOMPONENT_TYPE, &item); + nodeAPI->setAttribute(xc, NODE_XCOMPONENT_ID, &item); + nodeAPI->setAttribute(xc, NODE_XCOMPONENT_SURFACE_SIZE, &item1); + ArkUI_NumberValue focusable[] = {1}; + focusable[0].i32 = 1; + ArkUI_AttributeItem focusableItem = {focusable, 1}; + nodeAPI->setAttribute(xc, NODE_FOCUSABLE, &focusableItem); + ArkUI_NumberValue valueSize[] = {480}; + ArkUI_AttributeItem itemSize = {valueSize, 1}; + valueSize[0].f32 = XC_WIDTH; + nodeAPI->setAttribute(xc, NODE_WIDTH, &itemSize); + valueSize[0].f32 = XC_HEIGHT; + nodeAPI->setAttribute(xc, NODE_HEIGHT, &itemSize); + ArkUI_AttributeItem item2 = {value, 1, "ndkxcomponent"}; + nodeAPI->setAttribute(xc, NODE_ID, &item2); + + auto *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(xc); + if (!nativeXComponent) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "GetNativeXComponent error"); + return column; + } + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "GetNativeXComponent success"); + // 注册XComponent回调函数 + OH_NativeXComponent_RegisterCallback(nativeXComponent, &NativeManager::callback_); + auto typeRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_TYPE); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "xcomponent type: %{public}d", + typeRet->value[0].i32); + auto idRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_ID); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "xcomponent id: %{public}s", + idRet->string); + nodeAPI->addChild(column, xc); + return column; +} + +napi_value NativeManager::createNativeNode(napi_env env, napi_callback_info info) +{ + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "CreateNativeNode env or info is null"); + return nullptr; + } + size_t argCnt = 2; + napi_value args[2] = { nullptr, nullptr }; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "CreateNativeNode napi_get_cb_info failed"); + } + if (argCnt != ARG_CNT) { + napi_throw_type_error(env, NULL, "Wrong number of arguments"); + return nullptr; + } + ArkUI_NodeContentHandle nodeContentHandle_ = nullptr; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_); + nodeAPI = reinterpret_cast( + OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1") + ); + std::string tag = value2String(env, args[1]); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "tag=%{public}s", tag.c_str()); + int32_t ret = OH_ArkUI_NodeContent_SetUserData(nodeContentHandle_, new std::string(tag)); + if (ret != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "setUserData failed error=%{public}d", ret); + } + if (nodeAPI != nullptr && nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", + "CreateNativeNode tag=%{public}s", tag.c_str()); + auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) { + ArkUI_NodeContentHandle handle = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event); + std::string *userDate = reinterpret_cast(OH_ArkUI_NodeContent_GetUserData(handle)); + if (OH_ArkUI_NodeContentEvent_GetEventType(event) == NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) { + ArkUI_NodeHandle testNode; + if (userDate) { + testNode = CreateNodeHandle(*userDate); + delete userDate; + userDate = nullptr; + } else { + testNode = CreateNodeHandle("noUserData"); + } + OH_ArkUI_NodeContent_AddNode(handle, testNode); + } + }; + OH_ArkUI_NodeContent_RegisterCallback(nodeContentHandle_, nodeContentEvent); + } + return nullptr; +} +// [End plugin_create_native_node] +void NativeManager::OnSurfaceCreated(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "NativeManager::OnSurfaceCreated"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + eglcore_->EglContextInit(window, width_, height_); + eglcore_->Background(); + } +} + +void NativeManager::OnSurfaceDestroyed(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "NativeManager::OnSurfaceDestroyed"); +} + +void NativeManager::DispatchTouchEvent(OH_NativeXComponent* component, void* window) +{ + int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + float tiltX = 2.2; + float tiltY = 2.2; + OH_NativeXComponent_TouchPointToolType toolType = + OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS; + OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); + OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX); + OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", + "Touch Info : x=%{public}f, y=%{public}f screenx=%{public}f, screeny=%{public}f," + "type=%{public}d, force=%{public}f, tiltX=%{public}f, tiltY=%{public}f, toolType=%{public}d", + touchEvent_.x, touchEvent_.y, touchEvent_.screenX, + touchEvent_.screenY, touchEvent_.type, touchEvent_.force, tiltX, tiltY, toolType); + if (touchEvent_.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) { + eglcore_->ChangeColor(hasChangeColor_); + } + } else { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "touch fail"); + } + + int32_t size = 0; + OH_NativeXComponent_HistoricalPoint *points = nullptr; + + if (OH_NativeXComponent_GetHistoricalPoints(component, window, &size, &points) == + OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", "HistoricalPoints size=%{public}d", + size); + for (auto i = 0; i < size; i++) { + auto point = points[i]; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", + "HistoricalPoint %{public}d Info : id=%{public}d, x=%{public}f, y=%{public}f, " + "type=%{public}d, timeStamp=%{public}lld, sourceTool=%{public}d", + i, point.id, point.x, point.y, point.type, point.timeStamp, point.sourceTool); + } + } +} +void NativeManager::OnSurfaceChanged(OH_NativeXComponent* component, void* window) +{ + int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", + "OnSurfaceChanged ret=%{public}d width=%{public}lu, height=%{public}lu", ret, width_, height_); +} + +napi_value NativeManager::GetContext(napi_env env, napi_callback_info info) +{ + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "GetContext env or info is null"); + return nullptr; + } + + size_t argCnt = 1; + napi_value args[1] = { nullptr }; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "GetContext napi_get_cb_info failed"); + } + + if (argCnt != 1) { + napi_throw_type_error(env, NULL, "Wrong number of arguments"); + return nullptr; + } + + napi_valuetype valuetype; + if (napi_typeof(env, args[0], &valuetype) != napi_ok) { + napi_throw_type_error(env, NULL, "napi_typeof failed"); + return nullptr; + } + + if (valuetype != napi_number) { + napi_throw_type_error(env, NULL, "Wrong type of arguments"); + return nullptr; + } + + int64_t value; + if (napi_get_value_int64(env, args[0], &value) != napi_ok) { + napi_throw_type_error(env, NULL, "napi_get_value_int64 failed"); + return nullptr; + } + + napi_value exports; + if (napi_create_object(env, &exports) != napi_ok) { + napi_throw_type_error(env, NULL, "napi_create_object failed"); + return nullptr; + } + + return exports; +} + +void NativeManager::SetNativeXComponent(std::string& id, OH_NativeXComponent* nativeXComponent) +{ + if (nativeXComponent == nullptr) { + return; + } + nativeXComponentMap_[id] = nativeXComponent; +} + +// [EndExclude plugin_manager_cpp] +napi_value NativeManager::BindNode(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + ArkUI_NodeHandle handle; + OH_ArkUI_GetNodeHandleFromNapiValue(env, args[1], &handle); // 获取 nodeHandle + OH_ArkUI_SurfaceHolder *holder = OH_ArkUI_SurfaceHolder_Create(handle); // 获取 SurfaceHolder + nodeHandleMap_[nodeId] = handle; + surfaceHolderMap_[handle] = holder; + auto callback = OH_ArkUI_SurfaceCallback_Create(); // 创建 SurfaceCallback + callbackMap_[holder] = callback; + auto render = new EGLRender(); + OH_ArkUI_SurfaceHolder_SetUserData(holder, render); // 将render保存在holder中 + OH_ArkUI_SurfaceCallback_SetSurfaceCreatedEvent(callback, OnSurfaceCreatedNative); // 注册OnSurfaceCreated回调 + OH_ArkUI_SurfaceCallback_SetSurfaceChangedEvent(callback, OnSurfaceChangedNative); // 注册OnSurfaceChanged回调 + OH_ArkUI_SurfaceCallback_SetSurfaceDestroyedEvent(callback, OnSurfaceDestroyedNative); // 注册OnSurfaceDestroyed回调 + OH_ArkUI_SurfaceCallback_SetSurfaceShowEvent(callback, OnSurfaceShowNative); // 注册OnSurfaceShow回调 + OH_ArkUI_SurfaceCallback_SetSurfaceHideEvent(callback, OnSurfaceHideNative); // 注册OnSurfaceHide回调 + OH_ArkUI_XComponent_RegisterOnFrameCallback(handle, OnFrameCallbackNative); // 注册OnFrameCallback回调 + OH_ArkUI_SurfaceHolder_AddSurfaceCallback(holder, callback); // 注册SurfaceCallback回调 + if (!nodeAPI->addNodeEventReceiver(handle, onEvent)) { // 添加事件监听,返回成功码 0 + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "addNodeEventReceiver error"); + } + if (!nodeAPI->registerNodeEvent(handle, NODE_TOUCH_EVENT, 0, nullptr)) { // 用C接口注册touch事件,返回成功码 0 + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "registerTouchEvent error"); + } + provider_ = OH_ArkUI_AccessibilityProvider_Create(handle); // 创建一个ArkUI_AccessibilityProvider类型的对象 + /** + * 获取ArkUI_AccessibilityProvider后,如果注册无障碍回调函数请参考: + * https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/ndk-accessibility-xcomponent.md + * **/ + return nullptr; +} + +napi_value NativeManager::UnbindNode(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + ArkUI_NodeHandle node; + if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error"); + return nullptr; + } + node = nodeHandleMap_[nodeId]; + OH_ArkUI_XComponent_UnregisterOnFrameCallback(node); // 解注册帧回调 + OH_ArkUI_AccessibilityProvider_Dispose(provider_); // 销毁 ArkUI_AccessibilityProvider + auto holder = surfaceHolderMap_[node]; + if (NativeManager::callbackMap_.count(holder)) { + auto callback = NativeManager::callbackMap_[holder]; + OH_ArkUI_SurfaceHolder_RemoveSurfaceCallback(holder, callback); // 移除SurfaceCallback + OH_ArkUI_SurfaceCallback_Dispose(callback); // 销毁surfaceCallback + NativeManager::callbackMap_.erase(holder); + } + auto render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + delete render; // 销毁EGLRender对象 + OH_ArkUI_SurfaceHolder_Dispose(holder); // 销毁surfaceHolder + nodeAPI->disposeNode(node); // 销毁nodeHandle + nodeHandleMap_.erase(nodeId); + return nullptr; +} + +napi_value NativeManager::SetFrameRate(napi_env env, napi_callback_info info) +{ + size_t argc = 4; + napi_value args[4] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + auto node = nodeHandleMap_[nodeId]; + + int32_t min = 0; + napi_get_value_int32(env, args[FIRST_ARG], &min); + + int32_t max = 0; + napi_get_value_int32(env, args[SECOND_ARG], &max); + + int32_t expected = 0; + napi_get_value_int32(env, args[THIRD_ARG], &expected); + OH_NativeXComponent_ExpectedRateRange range = {.min = min, .max = max, .expected = expected}; + OH_ArkUI_XComponent_SetExpectedFrameRateRange(node, range); // 设置期望帧率 + return nullptr; +} + +napi_value NativeManager::SetNeedSoftKeyboard(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + ArkUI_NodeHandle node; + if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error"); + return nullptr; + } + node = nodeHandleMap_[nodeId]; + + bool needSoftKeyboard = false; + napi_get_value_bool(env, args[1], &needSoftKeyboard); + OH_ArkUI_XComponent_SetNeedSoftKeyboard(node, needSoftKeyboard); // 设置是否需要软键盘 + return nullptr; +} +// [End plugin_manager_cpp] +napi_value NativeManager::Initialize(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + ArkUI_NodeHandle node; + if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error"); + return nullptr; + } + node = nodeHandleMap_[nodeId]; + bool autoInitialize = 1; + OH_ArkUI_XComponent_SetAutoInitialize(node, autoInitialize); + OH_ArkUI_XComponent_Initialize(node); + bool isInitialized; + OH_ArkUI_XComponent_IsInitialized(node, &isInitialized); + auto holder = surfaceHolderMap_[node]; + EGLRender* render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + render->DrawStar(true); // 绘制五角星 + return nullptr; +} + +napi_value NativeManager::Finalize(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + ArkUI_NodeHandle node; + if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error"); + return nullptr; + } + node = nodeHandleMap_[nodeId]; + auto holder = surfaceHolderMap_[node]; + EGLRender* render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + render->Clear(); + OH_ArkUI_XComponent_Finalize(node); + return nullptr; +} + +napi_value NativeManager::DrawStar(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string nodeId = value2String(env, args[0]); + ArkUI_NodeHandle node; + if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error"); + return nullptr; + } + node = nodeHandleMap_[nodeId]; + auto holder = surfaceHolderMap_[node]; + EGLRender* render = reinterpret_cast(OH_ArkUI_SurfaceHolder_GetUserData(holder)); + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "YGB DrawStar w:[%{public}d],h[%{public}d]", render->width_, + render->height_); + render->DrawStar(true); // 绘制五角星 + return nullptr; +} + +} // namespace NativeXComponentSample diff --git a/entry/src/main/cpp/NativeEGLOCCT/NativeManager.h b/entry/src/main/cpp/NativeEGLOCCT/NativeManager.h new file mode 100644 index 00000000..af8815d2 --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/NativeManager.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef NATIVE_XCOMPONENT_PLUGIN_MANAGER_H +#define NATIVE_XCOMPONENT_PLUGIN_MANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include "EGLCore.h" +#include "EGLRender.h" +#include "arkui/native_node.h" +#include "arkui/native_node_napi.h" + +#include "NativeRender.h" +// [Start plugin_manager_h_part] +// plugin_manager.h +namespace NativeOpenCAX { +// [StartExclude plugin_manager_h_part] +constexpr const int FIRST_ARG = 1; +constexpr const int SECOND_ARG = 2; +constexpr const int THIRD_ARG = 3; +constexpr const int FRAME_COUNT = 50; +// [Start plugin_manager_h] +// 在头文件中定义NativeManager类 +// [EndExclude plugin_manager_h_part] +class NativeManager { +public: + // [StartExclude plugin_manager_h_part] + static OH_NativeXComponent_Callback callback_; + NativeManager(); + ~NativeManager(); + + static NativeManager* GetInstance() + { + return &NativeManager::pluginManager_; + } + static napi_value createNativeNode(napi_env env, napi_callback_info info); + static napi_value GetXComponentStatus(napi_env env, napi_callback_info info); + static napi_value NapiDrawPattern(napi_env env, napi_callback_info info); + // [StartExclude plugin_manager_h] + static napi_value GetContext(napi_env env, napi_callback_info info); + // [EndExclude plugin_manager_h_part] + static napi_value BindNode(napi_env env, napi_callback_info info); + static napi_value UnbindNode(napi_env env, napi_callback_info info); + static napi_value SetFrameRate(napi_env env, napi_callback_info info); + static napi_value SetNeedSoftKeyboard(napi_env env, napi_callback_info info); + // [StartExclude plugin_manager_h_part] + static napi_value Initialize(napi_env env, napi_callback_info info); + static napi_value Finalize(napi_env env, napi_callback_info info); + static napi_value DrawStar(napi_env env, napi_callback_info info); + // [EndExclude plugin_manager_h] + // CApi XComponent + void OnSurfaceChanged(OH_NativeXComponent* component, void* window); + void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); + void DispatchTouchEvent(OH_NativeXComponent* component, void* window); + void OnSurfaceCreated(OH_NativeXComponent* component, void* window); + // [StartExclude plugin_manager_h] + void SetNativeXComponent(std::string& id, OH_NativeXComponent* nativeXComponent); + NativeRender* GetRender(std::string& id); + void Export(napi_env env, napi_value exports); + // [EndExclude plugin_manager_h] + +private: + static NativeManager pluginManager_; + + std::unordered_map nativeXComponentMap_; + // [StartExclude plugin_manager_h] + std::unordered_map pluginRenderMap_; + // [EndExclude plugin_manager_h] + std::unordered_map pluginManagerMap_; + // [EndExclude plugin_manager_h_part] + +public: + // [StartExclude plugin_manager_h_part] + EGLCore *eglcore_; + uint64_t width_; + uint64_t height_; + OH_NativeXComponent_TouchEvent touchEvent_; + static int32_t hasDraw_; + static int32_t hasChangeColor_; + // [EndExclude plugin_manager_h_part] + // [StartExclude plugin_manager_h] + static std::unordered_map nodeHandleMap_; + static std::unordered_map callbackMap_; + static std::unordered_map surfaceHolderMap_; + static ArkUI_AccessibilityProvider *provider_; + // [EndExclude plugin_manager_h] +}; +// [End plugin_manager_h] +} // namespace NativeXComponentSample +// [End plugin_manager_h_part] +#endif // NATIVE_XCOMPONENT_PLUGIN_MANAGER_H diff --git a/entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp b/entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp new file mode 100644 index 00000000..185b1422 --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "NativeManager.h" +#include "NativeRender.h" + +#define EXPECTED_FRAME_RATE 30 + +namespace NativeOpenCAX { +namespace { +void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB"); + if ((component == nullptr) || (window == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB: component or window is null"); + return; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB: Unable to get XComponent id"); + return; + } + + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + uint64_t width; + uint64_t height; + int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); + if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) { + if (render->eglCore_->EglContextInit(window, width, height)) { + render->eglCore_->Background(); + } + } +} + +void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChangedCB"); + if ((component == nullptr) || (window == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChangedCB: component or window is null"); + return; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChangedCB: Unable to get XComponent id"); + return; + } + + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnSurfaceChanged(component, window); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "surface changed"); + } +} + +void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB"); + if ((component == nullptr) || (window == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB: component or window is null"); + return; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB: Unable to get XComponent id"); + return; + } + + std::string id(idStr); + NativeRender::Release(id); +} + +void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB"); + if ((component == nullptr) || (window == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB: component or window is null"); + return; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB: Unable to get XComponent id"); + return; + } + + std::string id(idStr); + NativeRender* render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnTouchEvent(component, window); + } +} + +void DispatchMouseEventCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchMouseEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + OH_NativeXComponent_ExtraMouseEventInfo* mouseEventInfo = NULL; + ret = OH_NativeXComponent_GetExtraMouseEventInfo(component, &mouseEventInfo); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + uint64_t mouseKey; + ret = OH_NativeXComponent_GetMouseEventModifierKeyStates(mouseEventInfo, &mouseKey); + if (ret == OH_NATIVEXCOMPONENT_RESULT_FAILED || ret == OH_NATIVEXCOMPONENT_RESULT_BAD_PARAMETER) { + return; + } + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnMouseEvent(component, window); + } +} + +void DispatchHoverEventCB(OH_NativeXComponent* component, bool isHover) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchHoverEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnHoverEvent(component, isHover); + } +} + +void OnFocusEventCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnFocusEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnFocusEvent(component, window); + } +} + +void OnBlurEventCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnBlurEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnBlurEvent(component, window); + } +} + +void OnKeyEventCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnKeyEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + auto render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->OnKeyEvent(component, window); + } +} +} // namespace + +std::unordered_map NativeRender::instance_; +int32_t NativeRender::hasDraw_ = 0; +int32_t NativeRender::hasChangeColor_ = 0; + +NativeRender::NativeRender(std::string& id) +{ + this->id_ = id; + this->eglCore_ = new EGLCore(); +} + +NativeRender* NativeRender::GetInstance(std::string& id) +{ + if (instance_.find(id) == instance_.end()) { + NativeRender* instance = new NativeRender(id); + instance_[id] = instance; + return instance; + } else { + return instance_[id]; + } +} + +void NativeRender::Export(napi_env env, napi_value exports) +{ + if ((env == nullptr) || (exports == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "Export: env or exports is null"); + return; + } + + napi_property_descriptor desc[] = { + {"drawPatternX", nullptr, NativeRender::NapiDrawPattern, nullptr, nullptr, + nullptr, napi_default, nullptr}, + {"getStatusX", nullptr, NativeRender::TestGetXComponentStatus, nullptr, nullptr, + nullptr, napi_default, nullptr}}; + if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "Export: napi_define_properties failed"); + } +} + +// NAPI registration method type napi_callback. If no value is returned, nullptr is returned. +napi_value NativeRender::NapiDrawPattern(napi_env env, napi_callback_info info) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "NapiDrawPattern"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "NapiDrawPattern: env or info is null"); + return nullptr; + } + + napi_value thisArg; + if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "NapiDrawPattern: napi_get_cb_info fail"); + return nullptr; + } + + napi_value exportInstance; + if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "NapiDrawPattern: napi_get_named_property fail"); + return nullptr; + } + + OH_NativeXComponent* nativeXComponent = nullptr; + if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "NapiDrawPattern: napi_unwrap fail"); + return nullptr; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "NapiDrawPattern: Unable to get XComponent id"); + return nullptr; + } + + std::string id(idStr); + NativeRender* render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->eglCore_->Draw(hasDraw_); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "render->eglCore_->Draw() executed"); + } + return nullptr; +} + +void NativeRender::Release(std::string& id) +{ + NativeRender* render = NativeRender::GetInstance(id); + if (render != nullptr) { + render->eglCore_->Release(); + delete render->eglCore_; + render->eglCore_ = nullptr; + instance_.erase(instance_.find(id)); + } +} + +void NativeRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window) +{ + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChanged: Unable to get XComponent id"); + return; + } + + std::string id(idStr); + NativeRender* render = NativeRender::GetInstance(id); + double offsetX; + double offsetY; + OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OH_NativeXComponent_GetXComponentOffset", + "offsetX = %{public}lf, offsetY = %{public}lf", offsetX, offsetY); + uint64_t width; + uint64_t height; + OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); + if (render != nullptr) { + render->eglCore_->UpdateSize(width, height); + } +} + +void SampleCallback(OH_NativeXComponent* component, uint64_t timestamp, uint64_t targettimestamp) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "SampleCallback", "SampleCallback"); +} + +void SampleInputeventCallback(OH_NativeXComponent *component, ArkUI_UIInputEvent *event, ArkUI_UIInputEvent_Type type) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "SampleInputeventCallback", "SampleInputeventCallback"); +} + +HitTestMode SampleInterceptCallback(OH_NativeXComponent *component, ArkUI_UIInputEvent *event) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "SampleInterceptCallback", "SampleInterceptCallback"); + return HTM_DEFAULT; +} + +void SampleSurfaceShowCallback(OH_NativeXComponent *component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "SampleSurfaceShowCallback", "SampleSurfaceShowCallback"); +} + +bool SampleCallbackWithResult(OH_NativeXComponent *component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "SampleCallbackWithResult", "SampleCallbackWithResult"); + return false; +} + +void SampleAnalyzer(ArkUI_NodeHandle node, ArkUI_XComponent_ImageAnalyzerState statusCode, void* userData) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "SampleAnalyzer", "SampleAnalyzer"); +} + +void MyContentHandler(ArkUI_NodeContentEvent* event) +{ + // 处理内容变化 + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "MyContentHandler", "MyContentHandler"); +} + +void NativeRender::OnTouchEvent(OH_NativeXComponent* component, void* window) +{ + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' }; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB: Unable to get XComponent id"); + return; + } + OH_NativeXComponent_TouchEvent_SourceTool sourceTool = OH_NATIVEXCOMPONENT_SOURCETOOL_UNKNOWN; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent", + "touch info: OH_NATIVEXCOMPONENT_SOURCETOOL_UNKNOWN = %{public}d", sourceTool); + OH_NativeXComponent_TouchEvent touchEvent; + OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent); + std::string id(idStr); + NativeRender* render = NativeRender::GetInstance(id); + if (render != nullptr && touchEvent.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) { + render->eglCore_->ChangeColor(hasChangeColor_); + } + float tiltX = 0.0f; + float tiltY = 0.0f; + OH_NativeXComponent_TouchPointToolType toolType = + OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN; + OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); + OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX); + OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY); + float windowX = 0; + float windowY = 0; + float displayX = 0; + float displayY = 0; + OH_NativeXComponent_GetTouchPointWindowX(component, 0, &windowX); + OH_NativeXComponent_GetTouchPointWindowY(component, 0, &windowY); + OH_NativeXComponent_GetTouchPointDisplayX(component, 0, &displayX); + OH_NativeXComponent_GetTouchPointDisplayY(component, 0, &displayY); + int32_t pointId = 0; + OH_NativeXComponent_EventSourceType sourceType; + OH_NativeXComponent_GetTouchEventSourceType(component, pointId, &sourceType); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent", + "touch info: toolType = %{public}d, tiltX = %{public}lf, tiltY = %{public}lf", toolType, tiltX, tiltY); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent", + "touch info: max_touch_points_number = %{public}d", OH_MAX_TOUCH_POINTS_NUMBER); + OnTouchEventPartTwo(component, window); + ArkUI_NodeHandle node; // 此处需要绑定node + void* userData; // 此处需要绑定userData + OH_ArkUI_XComponent_StartImageAnalyzer(node, userData, SampleAnalyzer); + OH_ArkUI_XComponent_StopImageAnalyzer(node); + // ArkUI_NodeContentCallback 的具体使用请搜索 OH_ArkUI_NodeContent_RegisterCallback + // ArkUI_NodeContentCallback callback1 = MyContentHandler; + return; +} + +void NativeRender::OnTouchEventPartTwo(OH_NativeXComponent* component, void* window) +{ + int32_t min = EXPECTED_FRAME_RATE; + int32_t max = EXPECTED_FRAME_RATE; + int32_t expected = EXPECTED_FRAME_RATE; + OH_NativeXComponent_ExpectedRateRange range = {.min = min, .max = max, .expected = expected}; + OH_NativeXComponent_SetExpectedFrameRateRange(component, &range); + bool needSoftKeyboard = 0; + OH_NativeXComponent_SetNeedSoftKeyboard(component, needSoftKeyboard); + OH_NativeXComponent_RegisterOnFrameCallback(component, SampleCallback); + OH_NativeXComponent_UnregisterOnFrameCallback(component); + ArkUI_UIInputEvent_Type type = ARKUI_UIINPUTEVENT_TYPE_UNKNOWN; + OH_NativeXComponent_RegisterUIInputEventCallback(component, SampleInputeventCallback, type); + ArkUI_AccessibilityProvider* sampleHandle; // 此处需要绑定handle + OH_NativeXComponent_GetNativeAccessibilityProvider(component, &sampleHandle); + OH_NativeXComponent_RegisterOnTouchInterceptCallback(component, SampleInterceptCallback); + OH_NativeXComponent_RegisterSurfaceShowCallback(component, SampleSurfaceShowCallback); + OH_NativeXComponent_RegisterSurfaceHideCallback(component, SampleSurfaceShowCallback); + OH_NativeXComponent_RegisterKeyEventCallbackWithResult(component, SampleCallbackWithResult); + OH_NativeXComponent_RegisterKeyEventCallbackWithResult(component, SampleCallbackWithResult); + return; +} + +void NativeRender::RegisterCallback(OH_NativeXComponent* nativeXComponent) +{ + renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB; + renderCallback_.OnSurfaceChanged = OnSurfaceChangedCB; + renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB; + renderCallback_.DispatchTouchEvent = DispatchTouchEventCB; + OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_); + + mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB; + mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB; + OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback_); + + OH_NativeXComponent_RegisterFocusEventCallback(nativeXComponent, OnFocusEventCB); + OH_NativeXComponent_RegisterKeyEventCallback(nativeXComponent, OnKeyEventCB); + OH_NativeXComponent_RegisterBlurEventCallback(nativeXComponent, OnBlurEventCB); +} + +void NativeRender::OnMouseEvent(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "OnMouseEvent"); + OH_NativeXComponent_MouseEvent mouseEvent; + int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", + "MouseEvent Info: x = %{public}f, y = %{public}f, action = %{public}d, button = %{public}d", mouseEvent.x, + mouseEvent.y, mouseEvent.action, mouseEvent.button); + } else { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "GetMouseEvent error"); + } +} + +void NativeRender::OnHoverEvent(OH_NativeXComponent* component, bool isHover) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "OnHoverEvent isHover_ = %{public}d", isHover); +} + +void NativeRender::OnFocusEvent(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "OnFocusEvent"); +} + +void NativeRender::OnBlurEvent(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "OnBlurEvent"); +} + +void NativeRender::OnKeyEvent(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", "OnKeyEvent"); + + OH_NativeXComponent_KeyEvent* keyEvent = nullptr; + if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) { + OH_NativeXComponent_KeyAction action; + OH_NativeXComponent_GetKeyEventAction(keyEvent, &action); + OH_NativeXComponent_KeyCode code; + OH_NativeXComponent_GetKeyEventCode(keyEvent, &code); + OH_NativeXComponent_EventSourceType sourceType; + OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType); + int64_t deviceId; + OH_NativeXComponent_GetKeyEventDeviceId(keyEvent, &deviceId); + int64_t timeStamp; + OH_NativeXComponent_GetKeyEventTimestamp(keyEvent, &timeStamp); + uint64_t keys; + OH_NativeXComponent_GetKeyEventModifierKeyStates(keyEvent, &keys); + bool isNumLockOn; + OH_NativeXComponent_GetKeyEventNumLockState(keyEvent, &isNumLockOn); + bool isCapsLockOn; + OH_NativeXComponent_GetKeyEventCapsLockState(keyEvent, &isCapsLockOn); + bool isScrollLockOn; + OH_NativeXComponent_GetKeyEventScrollLockState(keyEvent, &isScrollLockOn); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeRender", + "KeyEvent Info: action=%{public}d, code=%{public}d, sourceType=%{public}d, deviceId=%{public}ld, " + "timeStamp=%{public}ld", + action, code, sourceType, deviceId, timeStamp); + } else { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRender", "GetKeyEvent error"); + } +} + +napi_value NativeRender::TestGetXComponentStatus(napi_env env, napi_callback_info info) +{ + napi_value hasDraw; + napi_value hasChangeColor; + + napi_status ret = napi_create_int32(env, hasDraw_, &(hasDraw)); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "TestGetXComponentStatus", "napi_create_int32 hasDraw_ error"); + return nullptr; + } + ret = napi_create_int32(env, hasChangeColor_, &(hasChangeColor)); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "TestGetXComponentStatus", "napi_create_int32 hasChangeColor_ error"); + return nullptr; + } + + napi_value obj; + ret = napi_create_object(env, &obj); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "TestGetXComponentStatus", "napi_create_object error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasDraw", hasDraw); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "TestGetXComponentStatus", "napi_set_named_property hasDraw error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasChangeColor", hasChangeColor); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "TestGetXComponentStatus", + "napi_set_named_property hasChangeColor error"); + return nullptr; + } + return obj; +} +} // namespace NativeXComponentSample diff --git a/entry/src/main/cpp/NativeEGLOCCT/NativeRender.h b/entry/src/main/cpp/NativeEGLOCCT/NativeRender.h new file mode 100644 index 00000000..621eb29c --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/NativeRender.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef NATIVE_XCOMPONENT_PLUGIN_RENDER_H +#define NATIVE_XCOMPONENT_PLUGIN_RENDER_H + +#include +#include +#include +#include + +#include "EGLCore.h" + +namespace NativeOpenCAX { +class NativeRender { +public: + explicit NativeRender(std::string& id); + ~NativeRender() + { + if (eglCore_ != nullptr) { + eglCore_->Release(); + delete eglCore_; + eglCore_ = nullptr; + } + } + static NativeRender* GetInstance(std::string& id); + static void Release(std::string& id); + static napi_value NapiDrawPattern(napi_env env, napi_callback_info info); + static napi_value TestGetXComponentStatus(napi_env env, napi_callback_info info); + void Export(napi_env env, napi_value exports); + void OnSurfaceChanged(OH_NativeXComponent* component, void* window); + void OnTouchEvent(OH_NativeXComponent* component, void* window); + void OnTouchEventPartTwo(OH_NativeXComponent* component, void* window); + void OnMouseEvent(OH_NativeXComponent* component, void* window); + void OnHoverEvent(OH_NativeXComponent* component, bool isHover); + void OnFocusEvent(OH_NativeXComponent* component, void* window); + void OnBlurEvent(OH_NativeXComponent* component, void* window); + void OnKeyEvent(OH_NativeXComponent* component, void* window); + void RegisterCallback(OH_NativeXComponent* nativeXComponent); + void ShowSample(OH_NativeXComponent* component); + +public: + static std::unordered_map instance_; + EGLCore* eglCore_; + std::string id_; + static int32_t hasDraw_; + static int32_t hasChangeColor_; + +private: + OH_NativeXComponent_Callback renderCallback_; + OH_NativeXComponent_MouseEvent_Callback mouseCallback_; +}; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_PLUGIN_RENDER_H diff --git a/entry/src/main/cpp/NativeEGLOCCT/common.h b/entry/src/main/cpp/NativeEGLOCCT/common.h new file mode 100644 index 00000000..86b27d9d --- /dev/null +++ b/entry/src/main/cpp/NativeEGLOCCT/common.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVE_XCOMPONENT_COMMON_H +#define NATIVE_XCOMPONENT_COMMON_H + +#include +#include +#include +#include +#include + +namespace NativeOpenCAX { +/** + * Log print domain. + */ +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_COMMON_H diff --git a/entry/src/main/cpp/OCCTRender/OCCTRender.cpp b/entry/src/main/cpp/OCCTRender/OCCTRender.cpp deleted file mode 100644 index 28aaf44c..00000000 --- a/entry/src/main/cpp/OCCTRender/OCCTRender.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created on 2026/2/18. -// -// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, -// please include "napi/native_api.h". -#include "OCCTRender.h" - -#include // ← 提供 glViewport, glClear 等 -#include - -// OCCT 基础 -#include -#include -#include - -// XCAF 应用框架 -#include -#include // ← 解决当前错误 -#include // ← 配套使用 - -// STEP 导入 -#include -#include - -// 可视化 -#include -#include -#include - -OCCTRender::OCCTRender(int width, int height) - : m_width(width), m_height(height) -{ - // 创建一个“虚拟”的 DisplayConnection(HarmonyOS 无 X11/Wayland) - Handle(Aspect_DisplayConnection) aDispConnection; - - // 关键:设置 OpenGl_GraphicDriver 复用当前 OpenGL context - // 第二个参数 'theIsOwnsContext' 设为 false,表示不创建新 context - Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver(aDispConnection, false); - - m_viewer = new V3d_Viewer(aDriver); - m_view = m_viewer->CreateView(); - m_context = new AIS_InteractiveContext(m_viewer); - - m_view->SetBackgroundColor(Quantity_NOC_BLACK); - m_view->Camera()->SetProjectionType(Graphic3d_Camera::Projection_Perspective); - m_view->SetImmediateUpdate(false); // 禁用自动 redraw/swap -} -OCCTRender::~OCCTRender() { - // OCCT 对象由 Handle 自动管理,通常无需手动 delete -} -void OCCTRender::render() -{ - if (m_width <= 0 || m_height <= 0) return; - - // 设置 OpenGL viewport(由 EGLCore 控制 surface,此处仅设置视口) - glViewport(0, 0, m_width, m_height); - - // 更新相机宽高比 - m_view->Camera()->SetAspect(static_cast(m_width) / m_height); - - // 让 OCCT 渲染到当前 OpenGL context 的 default framebuffer - m_view->Redraw(); - // 注意:不要调用 RedrawImmediate(),也不要 swap buffer(由 EGLCore 负责) -} -void OCCTRender::loadModel(const char* stepPath) { - m_context->RemoveAll(false); - - auto app = XCAFApp_Application::GetApplication(); - m_doc = new TDocStd_Document("XmlXCAF"); // ← 关键修改 - app->NewDocument("XmlXCAF", m_doc); // ← 保持一致 - - STEPCAFControl_Reader reader; - IFSelect_ReturnStatus status = reader.ReadFile(stepPath); - if (status == IFSelect_RetDone) { - reader.Transfer(m_doc); - Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(m_doc->Main()); - if (!shapeTool.IsNull()) { - TDF_LabelSequence labels; - shapeTool->GetFreeShapes(labels); - for (Standard_Integer i = 1; i <= labels.Length(); ++i) { - TopoDS_Shape shape; - if (shapeTool->GetShape(labels.Value(i), shape)) { - Handle(AIS_Shape) aisShape = new AIS_Shape(shape); - m_context->Display(aisShape, false); - } - } - } - } - m_view->FitAll(); -} - -void OCCTRender::rotateCamera(float deltaX, float deltaY) { - m_view->Rotate(deltaX * 0.01f, deltaY * 0.01f, 0.0f, true); // 相对旋转 -} \ No newline at end of file diff --git a/entry/src/main/cpp/OCCTRender/OCCTRender.h b/entry/src/main/cpp/OCCTRender/OCCTRender.h deleted file mode 100644 index 121eb847..00000000 --- a/entry/src/main/cpp/OCCTRender/OCCTRender.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Created on 2026/2/18. -// -// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, -// please include "napi/native_api.h". - -/* - * Copyright (c) 2026 Your Company. All rights reserved. - * Description: OCCT rendering logic encapsulation. - */ - -#ifndef OCCT_RENDER_H -#define OCCT_RENDER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class OCCTRender { -public: - OCCTRender(int width, int height); // 保持接口不变 - ~OCCTRender(); - void loadModel(const char* stepPath); - void render(); - void updateSize(int width, int height); - void rotateCamera(float deltaX, float deltaY); - -private: - Handle(V3d_Viewer) m_viewer; - Handle(V3d_View) m_view; - Handle(AIS_InteractiveContext) m_context; - Handle(TDocStd_Document) m_doc; - int m_width; - int m_height; -}; - -#endif // OCCT_RENDER_H \ No newline at end of file diff --git a/entry/src/main/cpp/OCCTRenderThread/OCCTRenderThread.cpp b/entry/src/main/cpp/OCCTRenderThread/OCCTRenderThread.cpp deleted file mode 100644 index 5b84d514..00000000 --- a/entry/src/main/cpp/OCCTRenderThread/OCCTRenderThread.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// Created on 2026/2/18. -// -// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, -// please include "napi/native_api.h". - -#include "OCCTRenderThread.h" -#include // for usleep - -OCCTRenderThread::OCCTRenderThread(EGLNativeWindowType window, int width, int height) - : m_window(window), m_width(width), m_height(height) {} - -OCCTRenderThread::~OCCTRenderThread() { - stop(); - delete m_occtRender; -} - -void OCCTRenderThread::start() { - m_running = true; - m_thread = std::thread(&OCCTRenderThread::renderLoop, this); -} - -void OCCTRenderThread::stop() { - m_running = false; - if (m_thread.joinable()) { - m_thread.join(); - } -} - -void OCCTRenderThread::loadModel(const char* path) { - std::lock_guard lock(m_mutex); - m_pendingModelPath = std::string(path); - m_hasPendingModel = true; -} - -void OCCTRenderThread::onMouseEvent(float dx, float dy) { - m_deltaX += dx; - m_deltaY += dy; - m_hasMouseInput = true; -} - -void OCCTRenderThread::renderLoop() { - if (!m_eglCore.init(m_window)) { - return; - } - m_occtRender = new OCCTRender(m_width, m_height); - - while (m_running) { - m_eglCore.makeCurrent(); - - // Handle model loading - if (m_hasPendingModel) { - std::lock_guard lock(m_mutex); - m_occtRender->loadModel(m_pendingModelPath.c_str()); - m_hasPendingModel = false; - } - - // Handle mouse rotation - if (m_hasMouseInput.exchange(false)) { - m_occtRender->rotateCamera(m_deltaX, m_deltaY); - m_deltaX = m_deltaY = 0.0f; - } - - m_occtRender->render(); - m_eglCore.swapBuffers(); - - usleep(16000); // ~60 FPS - } - - delete m_occtRender; - m_occtRender = nullptr; - m_eglCore.release(); -} \ No newline at end of file diff --git a/entry/src/main/cpp/OCCTRenderThread/OCCTRenderThread.h b/entry/src/main/cpp/OCCTRenderThread/OCCTRenderThread.h deleted file mode 100644 index 40416543..00000000 --- a/entry/src/main/cpp/OCCTRenderThread/OCCTRenderThread.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Created on 2026/2/18. -// -// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, -// please include "napi/native_api.h". - -#ifndef OCCT_RENDER_THREAD_H -#define OCCT_RENDER_THREAD_H - -#include -#include -#include -#include "EGLCore/EGLCore.h" -#include "OCCTRender/OCCTRender.h" - -class OCCTRenderThread { -public: - OCCTRenderThread(EGLNativeWindowType window, int width, int height); - ~OCCTRenderThread(); - - void start(); - void stop(); - void loadModel(const char* path); - void onMouseEvent(float dx, float dy); - -private: - void renderLoop(); - - std::thread m_thread; - std::atomic m_running{false}; - EGLNativeWindowType m_window; - int m_width, m_height; - - EGLCore m_eglCore; - OCCTRender* m_occtRender = nullptr; - - std::mutex m_mutex; - std::string m_pendingModelPath; - std::atomic m_hasPendingModel{false}; - - float m_deltaX = 0.0f, m_deltaY = 0.0f; - std::atomic m_hasMouseInput{false}; -}; - -#endif //OCCT_RENDER_THREAD_H diff --git a/entry/src/main/cpp/OCCT方案.txt b/entry/src/main/cpp/OCCT方案.txt deleted file mode 100644 index e1b6964c..00000000 --- a/entry/src/main/cpp/OCCT方案.txt +++ /dev/null @@ -1,12 +0,0 @@ -按照下面要求生成实现代码: -1-HarmonyOS API 版本:22 -2-OpenGL ES 版本:3.0 -3-OCCT 版本:7.9.3 -4-分别用类名字为EGLCore OCCTRenderThread OCCTRender实现 -5-实现主线程和渲染线程分离.渲染线程循环渲染 -6-实现通过loadmodel加载step文件进行渲染step模型 -7-实现鼠标旋转相机观察渲染的模型. -8-Arkui通过XComponent的Native进行调用实现. -9-不得使用android的实现代码.使用鸿蒙原生API实现 -10-在napi_init.cpp文件中写出给arkui调用的函数.包括回调函数 -11-在Index.d.ts文件中写出暴露给arkui调用的代码 \ No newline at end of file diff --git a/entry/src/main/cpp/include/Add/Add.h b/entry/src/main/cpp/include/Add/Add.h new file mode 100644 index 00000000..ea1e6109 --- /dev/null +++ b/entry/src/main/cpp/include/Add/Add.h @@ -0,0 +1,10 @@ +// +// Created on 2024/10/12. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef NATIVESOINTEGRATION_ADD_H +#define NATIVESOINTEGRATION_ADD_H +double Add(double a, double b); +#endif // NATIVESOINTEGRATION_ADD_H diff --git a/entry/src/main/cpp/napi_init.cpp b/entry/src/main/cpp/napi_init.cpp index 01c7103b..94580159 100644 --- a/entry/src/main/cpp/napi_init.cpp +++ b/entry/src/main/cpp/napi_init.cpp @@ -1,128 +1,73 @@ #include "napi/native_api.h" -#include "OCCTRenderThread/OCCTRenderThread.h" -#include -#include +#include "hilog/log.h" +#include "Add/Add.h" +#include "NativeEGLOCCT/common.h" +#include "NativeEGLOCCT/NativeManager.h" -#define LOG_TAG "NAPI_INIT" -#define LOGI(...) (LOG_TAG, __VA_ARGS__) - -//存储 XComponent ID 到 OCCTRenderThread 实例的映射 -static std::map g_renderThreads; - -//NAPI: 初始化渲染器(绑定 XComponent) -static napi_value InitRenderer(napi_env env, napi_callback_info info) { - size_t argc = 3; - napi_value args[3]; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - // 参数1: xcomponentId (string) - char xcompId[256]; - size_t xcompIdLen; - napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &xcompIdLen); - - // 参数2: nativeWindow (EGLNativeWindowType, 实际是 void*) - EGLNativeWindowType window = nullptr; - napi_get_value_external(env, args[1], reinterpret_cast(&window)); - - // 参数3: { width, height } - int32_t width = 0, height = 0; - napi_valuetype type; - napi_typeof(env, args[2], &type); - if (type == napi_object) { - napi_value w, h; - napi_get_named_property(env, args[2], "width", &w); - napi_get_named_property(env, args[2], "height", &h); - napi_get_value_int32(env, w, &width); - napi_get_value_int32(env, h, &height); - } - - // 创建渲染线程 - LOGI('Init RenderThread'); - auto* renderThread = new OCCTRenderThread(window, width, height); - renderThread->start(); - LOGI('Deno Init RenderThread'); - g_renderThreads[std::string(xcompId)] = renderThread; - - return nullptr; -} - -// NAPI: 加载 STEP 模型 -static napi_value LoadModel(napi_env env, napi_callback_info info) { - LOGI('Start LoadModel'); +static napi_value NativeLoadSoTest(napi_env env, napi_callback_info info) +{ size_t argc = 2; - napi_value args[2]; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - char xcompId[256]; - size_t len; - napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); - char modelPath[1024]; - size_t pathLen; - napi_get_value_string_utf8(env, args[1], modelPath, sizeof(modelPath), &pathLen); - LOGI('Find RenderThread'); - auto it = g_renderThreads.find(std::string(xcompId)); - if (it != g_renderThreads.end()) { - LOGI('LoadModel Began'); - it->second->loadModel(modelPath); - } + napi_valuetype valuetype1; + napi_typeof(env, args[1], &valuetype1); - return nullptr; + double value0; + napi_get_value_double(env, args[0], &value0); + + double value1; + napi_get_value_double(env, args[1], &value1); + + auto _sum=Add(value0,value1); + napi_value sum; + napi_create_double(env, _sum, &sum); + + return sum; } - -// NAPI: 鼠标/触摸事件(可选,用于旋转) -static napi_value OnMouseEvent(napi_env env, napi_callback_info info) { - size_t argc = 3; - napi_value args[3]; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - char xcompId[256]; - size_t len; - napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); - - double dx, dy; - napi_get_value_double(env, args[1], &dx); - napi_get_value_double(env, args[2], &dy); - - auto it = g_renderThreads.find(std::string(xcompId)); - if (it != g_renderThreads.end()) { - it->second->onMouseEvent(static_cast(dx), static_cast(dy)); - } - - return nullptr; -} - -// NAPI: 销毁渲染器 -static napi_value DestroyRenderer(napi_env env, napi_callback_info info) { - size_t argc = 1; - napi_value args[1]; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - char xcompId[256]; - size_t len; - napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); - - auto it = g_renderThreads.find(std::string(xcompId)); - if (it != g_renderThreads.end()) { - it->second->stop(); - delete it->second; - g_renderThreads.erase(it); - } - - return nullptr; -} - +namespace NativeOpenCAX { EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins"); + if ((env == nullptr) || (exports == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "env or exports is null"); + return nullptr; + } napi_property_descriptor desc[] = { - {"initRenderer", nullptr, InitRenderer,nullptr, nullptr, nullptr, napi_default, nullptr}, - {"loadModel", nullptr, LoadModel,nullptr, nullptr, nullptr, napi_default, nullptr}, - {"onMouseEvent", nullptr, OnMouseEvent,nullptr, nullptr, nullptr, napi_default, nullptr}, - {"destroyRenderer", nullptr, DestroyRenderer,nullptr, nullptr, nullptr, napi_default, nullptr}, + // [StartExclude napi_init_part] + {"createNativeNode", nullptr, NativeManager::createNativeNode, nullptr, nullptr, nullptr, + napi_default, nullptr }, + {"getStatus", nullptr, NativeManager::GetXComponentStatus, nullptr, nullptr, + nullptr, napi_default, nullptr}, + {"drawPattern", nullptr, NativeManager::NapiDrawPattern, nullptr, nullptr, + nullptr, napi_default, nullptr}, + // [StartExclude napi_init] + {"getContext", nullptr, NativeManager::GetContext, nullptr, nullptr, nullptr, + napi_default, nullptr }, + // [EndExclude napi_init_part] + {"bindNode", nullptr, NativeManager::BindNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"unbindNode", nullptr, NativeManager::UnbindNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"setFrameRate", nullptr, NativeManager::SetFrameRate, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"setNeedSoftKeyboard", nullptr, NativeManager::SetNeedSoftKeyboard, nullptr, nullptr, nullptr, napi_default, + nullptr}, + // [StartExclude napi_init_part] + {"initialize", nullptr, NativeManager::Initialize, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"finalize", nullptr, NativeManager::Finalize, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"drawStar", nullptr, NativeManager::DrawStar, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"nativeLoadTest", nullptr, NativeLoadSoTest, nullptr, nullptr, nullptr, napi_default, nullptr}, }; - napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + if (status != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "Failed to define properties."); + return nullptr; + } return exports; } + EXTERN_C_END // 编写接口的描述信息,根据实际需要可以修改对应参数 @@ -135,9 +80,9 @@ static napi_module OpenCAXModel = { .nm_priv = ((void*)0), .reserved = { 0 } }; - -extern "C" __attribute__((visibility("default"))) +} +extern "C" __attribute__((constructor)) void RegisterOpenCAXModule(void) { - napi_module_register(&OpenCAXModel); + napi_module_register(&NativeOpenCAX::OpenCAXModel); } diff --git a/entry/src/main/cpp/types/libopencax/Index.d.ts b/entry/src/main/cpp/types/libopencax/Index.d.ts index a7686267..ed3b8d30 100644 --- a/entry/src/main/cpp/types/libopencax/Index.d.ts +++ b/entry/src/main/cpp/types/libopencax/Index.d.ts @@ -1,5 +1,30 @@ -// Index.d.ts -export const initRenderer:(id: string, nativeWindow: any, size: { width: number; height: number }) => void; -export const loadModel:(id: string, modelPath: string)=> void; -export const onMouseEvent:(id: string, dx: number, dy: number)=> void; -export const destroyRenderer:(id: string)=> void; +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NodeContent } from '@ohos.arkui.node'; +type XComponentContextStatus = { + hasDraw: boolean, + hasChangeColor: boolean +}; +export const createNativeNode: (content: NodeContent, tag: string) => void; +export const getStatus: () => XComponentContextStatus; +export const drawPattern: () => void; +export const bindNode: (id: string, node: object) => void; +export const unbindNode: (id: string) => void; +export const setFrameRate: (id: string, min: number, max: number, expected: number) => void; +export const setNeedSoftKeyboard: (id: string, needSoftKeyborad: boolean) => void; +export const initialize: (id: string) => void; +export const finalize: (id: string) => void; +export const drawStar: (id: string) => void; diff --git a/entry/src/main/ets/pages/modelView.ets b/entry/src/main/ets/pages/modelView.ets index 18e61caf..2e61326f 100644 --- a/entry/src/main/ets/pages/modelView.ets +++ b/entry/src/main/ets/pages/modelView.ets @@ -1,22 +1,36 @@ import { hilog } from '@kit.PerformanceAnalysisKit'; import fs from '@ohos.file.fs'; import fileIO from '@ohos.fileio'; -import { Context } from '@kit.AbilityKit'; -//import NaviteOCCT from 'libopencax.so'; +import {NodeContent} from '@kit.ArkUI'; +import NativeOpenCAX from 'libopencax.so'; const DOMAIN = 0x0000; const TAG = 'ModelView'; +function NativeLoadModelTest(){ + try { + hilog.info(0x0000, 'ModelView', `[NDK] 模块类型: ${typeof NativeOpenCAX}`); + hilog.info(0x0000, 'ModelView', `[NDK] 模块值: ${JSON.stringify(NativeOpenCAX)}`); + hilog.info(0x0000, 'ModelView', `[NDK] 所有属性: ${Object.keys(NativeOpenCAX).join(', ')}`); + //hilog.info(0x0000, 'ModelView', `[NDK] 模块函数加法测试结果: ${NativeOpenCAX.nativeLoadTest(2, 22)}`); + if (!NativeOpenCAX) throw new Error("模块为 undefined"); + } catch (e) { + console.error(`[NDK] 加载失败: ${e.message}`, e); + // 此处会触发你看到的错误 + } +} + @Component export struct ModelView { private displayController: XComponentController = new XComponentController(); - private displayContrId: string = 'OCCTRenderer' + private displayContrId: string = 'OCCTRender'; @State modelPath: string = ''; @State modelName:string='model.step'; - @State nativeWindow:string=''; - @State loadStatus: string = '未测试'; + @State currentStatus: string = 'init'; + private nodeContent: NodeContent = new NodeContent(); aboutToAppear() { + NativeOpenCAX.createNativeNode(this.nodeContent,'CreatNativeNode'); this.copyRawFileToSandbox(); } async copyRawFileToSandbox() { @@ -52,41 +66,17 @@ export struct ModelView { Button('加载模型').onClick(()=>{ try { console.info('Model copied to:', this.modelPath); - // 调用 native 加载 - //OCCTRender.loadModel(this.displayContrId, this.modelPath); + NativeOpenCAX.drawPattern(); + //NativeOpenCAX.loadModel(this.displayContrId,this.modelPath); } catch (e) { hilog.error(0x0000, 'ModelView', `LoadModel Failed: ${JSON.stringify(e)}`); } }) - Button('测试模块加载').onClick(()=>{ - try { - const NaviteOCCT = import("libopencax.so") - console.info(`[NDK] 模块类型: ${typeof NaviteOCCT}`); - console.info(`[NDK] 模块值: ${JSON.stringify(NaviteOCCT)}`); - console.info(`[NDK] 所有属性: ${Object.keys(NaviteOCCT).join(', ')}`); - if (!NaviteOCCT) throw new Error("模块为 undefined"); - } catch (e) { - console.error(`[NDK] 加载失败: ${e.message}`, e); - // 此处会触发你看到的错误 - } - }) - Button('测试so是否存在').onClick(()=>{ - try { - fs.accessSync('libs/x86_64/libopencax.so'); - console.info("动态库存在!"); - } catch (e) { - console.error("动态库不存在!"); - } + Button('模块&&so库加载测试').onClick(()=>{ + NativeLoadModelTest(); }) } - XComponent({ - id: this.displayContrId, - type: 'surface', - controller: this.displayController - }) - .width('100%') - .height('100%') - .backgroundColor('#333333'); + ContentSlot(this.nodeContent); } .width('100%') .height('100%'); diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index de201a99..5fdc2237 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -26,7 +26,7 @@ "entity.system.home" ], "actions": [ - "ohos.want.action.home" + "action.system.home" ] } ]