Harmony-Friction:基于 HarmonyOS 的 2D 动画软件原生移植项目

Friction 2.5D 向 HarmonyOS(OHOS arm64)的移植源码仓库:收录上游 Friction 2.5D 源码树(基线 66ba88b,v1.6.6)与本平台适配改动,依 GPL-3.0-or-later 释出

分支1Tags0

Harmony-Friction

Friction 2.5D 向 HarmonyOS(OHOS arm64)的移植源码仓库:收录上游源码树(本平台改动已就地合入该树)与本平台用的交叉构建配置。

来源与许可

项 内容
上游项目 Friction 2.5D(兼具矢量与位图能力的 MG 动画应用)— 官网 https://friction.graphics,源码 https://github.com/friction2d/friction
收录树 sources/friction/,取自上游 2.5D 分支线 nobug-project/friction-2.5d(Friction 的公开 fork,fork 链见该仓库),版本 1.6.6(见 sources/friction/version.txt;src/cmake/friction-version.cmake 中的 1.5.0 是 CMake 侧回退值,该文件注释已说明以 version.txt 为准)
上游基线 commit 66ba88b019df9956f43d4cb5120488626d87211d(版本号升至1.6.6,2026-10-03,origin/main tip);本平台改动先锚定在 95032274d(1.4.0,2026-09-11),再与 66ba88b 三向合并
上游许可证 GPL-3.0-or-later(树内 LICENSE.md 为 GPLv3 全文;本仓库复制为根目录 LICENSE)
本仓库许可 上游树 + 我方修改/新增文件按同一 GPL-3.0-or-later 释出;sources/friction/src/skia/(Skia)为 BSD-3-Clause,见《许可证》
上游获取渠道 https://github.com/friction2d/friction、https://github.com/nobug-project/friction-2.5d;Skia 取 friction 主线 submodule 锚定 SHA b551a388(m84)
版权头 上游文件的版权头与作者署名(Copyright (c) Ole-André Rodlie and contributors 等)保持原样,未改写;我方新增文件在文件头标注许可(如 src/app/friction_ohos_entry.cpp 的 SPDX-License-Identifier: GPL-3.0-only)
无担保 按 GPL 的 WITHOUT ANY WARRANTY 条款释出,不提供任何明示或默示担保

收录形态说明:本仓库收录的是已含本平台改动的上游树,不另附 .patch 序列。原因是改动与 1.4.0→1.6.6 的上游合并相互交叠(音频抽象层、内存回调、GL 边界等冲突面),拆成独立补丁无法稳定重放;改动面全部以文件级清单与就地标记的形式在《改动指示》中公开,可与上游基线 commit 逐文件比对复核。

移植方式

  • 形态:应用本体在 OHOS 上编为共享库 libfriction_core.so(src/app/CMakeLists.txt 的 OHOS 分支:add_library(${PROJECT_NAME} SHARED …) + OUTPUT_NAME friction_core)。桌面 main() 由 src/app/friction_ohos_entry.cpp 提供的库入口取代,初始化链对齐上游 src/app/main.cpp;不进入 QApplication::exec(),事件由导出符号 Friction_Step 按拍驱动,Qt 主线程即首次加载 Qt5Core 的线程。
  • UI/图形栈:Qt5 Widgets(Core/Gui/Widgets/OpenGL/Network/Xml/Svg/Concurrent,另需 Qml 供表达式引擎)+ Skia(GLES/EGL 光栅)+ OpenGL ES 3.0;src/ui/widgets/glwindow.cpp 内的 __OHOS__ 守卫切换到 EGL/GLES3 路径。
  • 音频:Qt Multimedia 无 OHOS 后端,改由 src/core/Sound/ohaudiooutput.{h,cpp} 实现 QAudioOutput 兼容 shim(libohaudio 经 dlopen 解析,回调拉取 + 环形缓冲;无可用设备时退化为哑设备,不阻塞主流程),audiohandler.{h,cpp} 在 OHOS 侧挂该 shim。
  • 视频/图像编解码:FFmpeg 五库(avformat/avcodec/avutil/swscale/swresample)交叉编译后由 src/cmake/friction-ffmpeg.cmake 定位(无 pkg-config 环境)。
  • 依赖栈:Qt5 5.15(Qml 由 qtdeclarative 5.15.2 源码交叉编译,仅 qml 模块)、Skia m84(随树收录于 sources/friction/src/skia/,本仓库改用纯 CMake 静态库构建)、FFmpeg(4.4.5 与 9.0.2 两版交叉库)、libpng 1.6.43(cross/libpng-mini.cmake 最小编译)、QScintilla 2.13.3、freetype / harfbuzz / fontconfig / expat / zlib / jpeg。这些依赖为上游项目各自独立发布的源码,本仓库不重复收录(Skia 除外),版本与许可见《许可证》。
  • 对外接口面:src/app/friction_ohos_entry.cpp 导出 26 个 extern "C" 符号(初始化与生命周期 Friction_Init/Friction_Step/Friction_Exit/Friction_IsRunning/Friction_PumpModal;输入注入 Friction_OnPointerEvent/Friction_OnWheelEvent/Friction_ImeCommitText/Friction_ImeKey/Friction_SetImeRequestCallback/Friction_SetImeRectCallback;菜单驱动 Friction_GetMenuJson/Friction_TriggerMenuAction/Friction_MenuWalkStart/Friction_MenuWalkStatus;项目与文件 Friction_OpenProjectFile/Friction_HandleDroppedFiles/Friction_SetDataPath;渲染与调试 Friction_GetQtWorkMutex/Friction_DumpUiGeometry/Friction_DebugNewScene/Friction_AeBatchStart/Friction_AeBatchStatus/Friction_RecordJsThread/Friction_SetTaskDrainer/airfx_stage_log)。

仓库结构

路径 内容
README.md 本文件(来源、许可、改动指示)
LICENSE GPLv3 全文(取自上游树内 LICENSE.md,未手打)
.gitignore 构建产物与本机噪声(/build、/install、*.log、.DS_Store、__pycache__、*.o、*.so)
sources/friction/ 上游 Friction 2.5D 源码树(含就地合入的本平台改动;src/skia/ 为随树解引用收录的 Skia m84 源码)
sources/friction/src/skia/CMakeLists.txt 我方新增:Skia 纯 CMake 交叉构建封装(替代上游 GN 路线)
sources/friction/src/skia_cmake_sources.txt 我方新增:由 cross/extract_skia_sources.py 生成的 Skia 源文件清单(src/skia/CMakeLists.txt 以 ${SKIA_ROOT}/../skia_cmake_sources.txt 读取)
cross/libpng-mini.cmake libpng 1.6.43 面向 OHOS arm64 的最小编译配置(产出 libpng16)
cross/extract_skia_sources.py 从 Skia gn/*.gni 提取并裁剪源清单的生成器

sources/friction/README.md、AGENTS.md、skills/、.agents/、.github/ 为上游分支线自带文件,随树原样收录,本仓库不改动其内容。

改动指示

按 GPL-3.0 §5a 履行"标注改动与日期"义务:以下统计均可在仓库根目录复现。

grep -rl "__OHOS__" sources/friction | wc -l                 # 29  —— 预处理级平台守卫
grep -rl "OHOS"     sources/friction | wc -l                 # 36  —— 含 CMake 分支与注释
grep -rl "AIRFX"    sources/friction --exclude-dir=skia | wc -l  # 44 —— 就地注释前缀 AIRFX(<编号/主题>)

相对上游基线 66ba88b 的文件级改动面(克隆上游仓库后 git diff --stat 66ba88b <合并态> 可复核):45 个文件,+4213 / −122 行;新增 3 个、修改 42 个、删除 0 个。

新增文件:

  • src/app/friction_ohos_entry.cpp — OHOS 库入口与平台适配层
  • src/core/Sound/ohaudiooutput.h、src/core/Sound/ohaudiooutput.cpp — OHAudio 音频 shim

修改文件(42 个,按主题归类):

主题 文件 改动要点
库形态与事件循环 src/app/friction_ohos_entry.cpp(新增)、src/app/CMakeLists.txt、src/app/evfileio.cpp 桌面 main() → 共享库入口;被领养的渲染线程补装 Qt 事件分发器(QWSI/QEventDispatcherUNIX 私有头);app.exec() 不进入,按拍泵事件
音频后端 src/core/Sound/audiohandler.{h,cpp}、ohaudiooutput.{h,cpp}(新增) 上游 Qt5/Qt6 音频抽象层的 typedef 上挂 OHAudio shim;回调拉取模型 + 软件音量缩放;哑设备退化
GL/GLES 边界 src/ui/widgets/glwindow.cpp、src/core/skia/skiahelpers.cpp GLES 缺失的桌面 GL 查询(glGetTexLevelParameteriv)改为 id-only 比对 + 每帧 resetContext;OHOS 花屏根修的 FBO 守卫(与上游 1.6.6 采纳的同一逻辑)
内存治理 src/app/memorychecker.cpp、src/app/memoryhandler.cpp、src/core/memorydatahandler.{h,cpp}、src/core/smartPointers/ememory.h、src/core/exceptions.cpp OHOS 内存等级回调不暂停进程的语义收进 updateTimerState 单点;与上游 critical 迟滞逻辑合并;缓存随压力回收
输入法 src/app/friction_ohos_entry.cpp IME 候选矩形回调/提交注入、软键盘按压门控、模态期任务桥排水(Friction_PumpModal、Friction_SetTaskDrainer)
对话框与键盘避让 src/ui/dialogs/scenesettingsdialog.cpp、src/ui/dialogs/exportsvgdialog.cpp、src/ui/dialogs/commandpalette.cpp、src/ui/dialogs/welcomedialog.cpp、src/app/GUI/Expressions/expressiondialog.cpp、src/app/GUI/Settings/aiagentsettingswidget.cpp 高度超限时收缩对话框(固定尺寸策略改写)、布局重建时序修正(实测崩溃根修)、对话框路径改走外置钩子
文件/字体/设置对话框外置 src/core/appsupport.{h,cpp}、src/ui/widgets/fontswidget.cpp、src/core/Private/esettings.cpp appsupport.h 中的对话框钩子命名空间(Hooks:openFile/openFiles/saveFile)由调用方注册,替代平台原生文件对话框;偏好与收藏路径按平台数据目录改写
指针与画布输入 src/app/GUI/mainwindow.{cpp,h}、src/app/GUI/canvaswindow.cpp、src/app/GUI/topviewwindow.cpp、src/app/GUI/RenderWidgets/renderinstancewidget.cpp、src/app/GUI/BoxesList/boxsinglewidget.cpp、src/app/GUI/timelinedockwidget.cpp、src/core/canvas.cpp、src/app/renderhandler.cpp 统一指针/滚轮注入入口(窗口原生像素坐标)、触摸与鼠标同源、绘制线程与上下文串行化
菜单与命令驱动 src/app/GUI/menu.cpp、src/app/GUI/mainwindow.{cpp,h} 菜单树 JSON 导出与按 id 触发动作;工作区菜单在构造期急切构建(dock 未建时 toggleViewAction 崩溃的根修)
缓存与媒体解码 src/core/FileCacheHandlers/videocachehandler.cpp、src/core/CacheHandlers/imagedatahandler.cpp、src/core/CacheHandlers/cachecontainer.h、src/core/filesourcescache.cpp、src/app/eimporters.h FFmpeg 交叉库解码路径、图像/视频缓存句柄在平台线程模型下的边界处理
AI/脚本接口 src/app/AI/mcpserver.cpp、src/app/GUI/Settings/aiagentsettingswidget.cpp 本地 socket 绑定与线程生命周期按 OHOS 沙箱网络约束加守卫
构建系统 CMakeLists.txt、src/app/CMakeLists.txt、src/core/CMakeLists.txt、src/cmake/friction-common.cmake、src/cmake/friction-ffmpeg.cmake、src/skottie-ffi/CMakeLists.txt、src/skia/CMakeLists.txt(新增)、src/skia_cmake_sources.txt(新增) OHOS 分支:C++17(Skia 头需 std::optional/void_t)、不构建 gperftools 与 libunwind、effects_test 以空 INTERFACE 目标吸收引用、docs 资源不随包、整体输出为共享库、Skia 由 GN 改纯 CMake 静态库、FFmpeg 走 AIRFX_FFMPEG_PREFIX 直定位
UI 细节 src/ui/widgets/colortoolbar.cpp、src/app/GUI/BoxesList/boxsinglewidget.cpp 触控尺寸与工具条布局在 arm64 设备上的适配

功能状态 / 已知限制

只述本树可构建出的能力与树内可见的限制:

  • 可构建出 libfriction_core.so(Qt5 Widgets + Skia GLES 光栅的完整应用本体),并通过上述 26 个导出符号被驱动:初始化/步进/退出、指针与滚轮注入、IME 提交、菜单遍历与触发、打开项目文件、批渲染任务状态查询。
  • 以下限制在树内配置中显式声明:Skia 侧 WebP 关闭(SK_LIB_WEBP_SUPPORT=0,无 libwebp 依赖)、PDF 与打印关闭(SK_SUPPORT_PDF=0/SK_NO_PRINTING=1)、Vulkan/Metal/D3D/Dawn/Graphite 后端未编入;gperftools(tcmalloc)与 libunwind 不参与 OHOS 构建(UNIX AND NOT APPLE AND NOT OHOS 条件);effects_test 目标不构建;docs submodule 内容不随包。
  • FFmpeg 版本闸门为树内既有逻辑(src/core/appsupport.cpp 的 checkFFmpeg):放行 avutil major 55/56/61,即 FFmpeg 4.x 与 9.0.x;本移植的交叉库为 4.4.5 与 9.0.2。

交叉构建

以下开关与变量均为仓库内文件的真实内容(逐条可在树内核对),不含本仓库之外的工程参数:

  • 平台分支总开关:CMake 变量 OHOS,配置时置 -DOHOS=ON。正向分支 if(OHOS) 出现在 src/app/CMakeLists.txt(共享库形态、manual/manual.qrc 手册资源、docs 不随包、effects_test 改为空 INTERFACE 目标、NDK sysroot 直连 EGL/GLESv3)、src/cmake/friction-common.cmake(C++17、静态 Skia 绝对路径链接)、src/skottie-ffi/CMakeLists.txt(补链 fontconfig/freetype);反向排除 if(UNIX AND NOT APPLE AND NOT OHOS) 出现在顶层 CMakeLists.txt(不加入 src/gperftools)、src/cmake/friction-common.cmake(不查 libunwind/tcmalloc)、src/app/CMakeLists.txt(不装 desktop 文件与 INSTALL_DOCS、不链 GPERF_LIBRARIES)。
  • 工具链与依赖查找:由调用方提供 OHOS NDK clang 交叉工具链与 sysroot;src/skia/CMakeLists.txt 头部注释原文要求"系统库 zlib/freetype/png16/jpeg/fontconfig/expat/harfbuzz 由调用方 -DCMAKE_FIND_ROOT_PATH 传入",其内部以 find_path(... REQUIRED) / find_library(... REQUIRED) 定位。
  • Skia:-DBUILD_SKIA=ON(默认 ON,add_subdirectory(src/skia))产出静态 libskia.a;编译宏 SKIA_IMPLEMENTATION=1 SK_GANESH SK_GL SK_ENABLE_SKSL SK_BUILD_FOR_UNIX SK_SUPPORT_PDF=0 SK_NO_PRINTING=1 SK_FONTMGR_FONTCONFIG=1 SK_LIB_PNG_SUPPORT=1 SK_LIB_JPEG_SUPPORT=1 SK_LIB_WEBP_SUPPORT=0 SK_DISABLE_TRACING=1 SK_USE_PERFETTO=0,并 CMAKE_POSITION_INDEPENDENT_CODE ON、CMAKE_CXX_STANDARD 17。
  • 链接预编译 Skia 时:-DSKIA_STATIC=ON + -DSKIA_LIB_PATH=<前缀>(friction-common.cmake 拼 ${SKIA_LIB_PATH}/lib/libskia.a,其余依赖用 find_library 取 png16/jpeg/freetype/harfbuzz/fontconfig/expat/z);SKIA_LIB_PATH 为 CACHE STRING,默认 /mnt/skia。
  • GLES:option(USE_GLES "Use OpenGL ES 3.0 (experimental)" OFF),OHOS 目标需开启。
  • FFmpeg:环境变量 AIRFX_FFMPEG_PREFIX(src/cmake/friction-ffmpeg.cmake 用 ${PREFIX}/include 与 ${PREFIX}/lib,链 avformat avcodec avutil swscale swresample)。
  • libpng:cmake -C/-S 指向 cross/libpng-mini.cmake 所在源码目录构建共享库 png16,其定义为 -DPNG_ARM_NEON_OPT=2 -DPNG_NO_CONFIG_H,源清单为该文件内列举的 15 个 .c 与 3 个 arm NEON 文件。
  • Skia 源清单再生成:python3 cross/extract_skia_sources.py(脚本以自身所在目录下的 skia-b551 为 Skia 根,即上游 submodule SHA b551a388 的检出名),输出即 sources/friction/src/skia_cmake_sources.txt 的内容。

相关资源

许可证

组件 许可
sources/friction/(除 src/skia/)—— 上游 Friction 2.5D 树与我方改动 GPL-3.0-or-later(LICENSE)
sources/friction/src/skia/ —— Skia(Google,BSD 3-Clause,src/skia/LICENSE 与 src/skia/AUTHORS 随树保留) BSD-3-Clause
sources/friction/src/app/icons/ —— 上游 src/app/icons submodule(hicolor 图标主题,7134 个文件)随树解引用收录;docs、src/gperftools 两个 submodule 未初始化(本地为空目录,故不入 git) 图标主题按其仓库自身许可,文件内声明保持原样
cross/libpng-mini.cmake、cross/extract_skia_sources.py、src/skia/CMakeLists.txt、src/skia_cmake_sources.txt —— 我方构建配置 GPL-3.0-or-later(作为整体工程的构成部分释出)
未随树收录的依赖(构建本仓库需要另行获取):Qt5 5.15 与 qtdeclarative 5.15.2、qtmultimedia 5.15.2、QScintilla 2.13.3、FFmpeg 4.4.5、libpng 1.6.43、freetype / harfbuzz / fontconfig / expat / zlib / jpeg 各以上游项目随附许可文本为准(Qt 模块为 LGPL-3.0/GPL-2.0 系,FFmpeg 依构建配置为 LGPL-2.1+/GPL-2+,libpng 为 libpng 许可证,QScintilla 为 GPL-3.0)

各组件著作权归其上游项目与原作者所有;本仓库仅主张我方修改与新增文件在 GPL-3.0-or-later 下的授权。上游文件的版权头、SPDX 与署名一律保留。

项目介绍

Friction 2.5D 向 HarmonyOS(OHOS arm64)的移植源码仓库:收录上游 Friction 2.5D 源码树(基线 66ba88b,v1.6.6)与本平台适配改动,依 GPL-3.0-or-later 释出

定制我的领域