Air 系列应用交流/轻矢|AirVector · 鸿蒙 PC 适配全记录

轻矢|AirVector · 鸿蒙 PC 适配全记录

【Air 系列 · 鸿蒙 PC 适配全记录】52 / 56

■ 应用:轻矢(AirVector)
■ 定位:矢量绘图编辑器:图层、编组
■ 上游:Inkscape 1.5 fork | 路线:GTK4+GDK OHOS | 版本:2.1.0
■ 市场状态:已上架 AGC 应用页: https://appgallery.huawei.com/app/6917605141803612592
■ 官网(免费下载): https://www.shunidc.cn/

————————————————————
开源鸿蒙 PC 社区: https://harmonypc.csdn.net/

PC 社区项目申请: https://atomgit.com/OpenHarmonyPCDeveloper

适配开源地址:(AtomGit 仓库建立后回填)

环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743

▍一、为什么要适配 轻矢

矢量编辑器是桌面创作工具里门槛最高的一类:钢笔与贝塞尔、路径布尔运算、节点编辑、渐变与网格、专业文件格式的导入导出,每一项都是多年工程积累。轻矢(AirVector)的目标是把 Inkscape 级的专业矢量能力与 Illustrator(.ai)文件支持带到鸿蒙 PC,工程自称的定位是"Inkustrator"——Inkscape 引擎加 AI 专业文件支持。

这个工程最值得记录的不是从零移植,而是一次彻底的引擎换代。v1.1.0 时代的轻矢走的是自绘路线:约 2.96 万行 ArkTS 自绘界面(VectorCanvas.ets 单文件 2143 行、26 个工具)加约 3.4 万行 C++ 自研引擎(libairvector.so,40 余个 NAPI 接口),其中 AI 导入靠 3530 行手写解析器,git 历史上六成提交都在修颜色反转、XObject、色彩空间类缺陷。2026-09-28 的方案调研文档(docs/2026-09-28-AirScape-Inkustrator-移植方案调研.md)对比了 A 整体移植、B 双引擎共存、C 增量替换导入三条路线后,选定了 A:把同工作区 AirScape 工程(Inkscape 1.5.0-dev on HarmonyOS,S17 稳定性打磨期)已成熟的整条 GTK4/Inkscape 移植链注入轻矢品牌,旧自绘引擎整体归档。

当前鸿蒙工程版本为 2.0.0,包名 com.airvector.app 不变,中文名轻矢,支持 phone、tablet 与 2in1 并固定横屏,协议为 GPL-3.0-or-later(Inkscape 传染所致,仓库含 LICENSE 与 THIRD_PARTY.md)。compatibleSdkVersion 6.1.0(23)、targetSdkVersion 26.0.0,产物 HAP 约 59 MB(compressNativeLibs 开启,65 个动态库)。权限仅声明 READ_PASTEBOARD 一项,另注册了 general.image 的查看与分享入口(最多 8 文件)。主验证机为 HUAWEI MatePad 11.5(TXZ-W20,2456x1529)。

▍二、先划清边界:不把引擎跑起来当成适配完成

引擎换代最容易产生的错觉是"窗口画出来了就等于换完了"。工程把边界定在品牌、数据、布局、输入四个维度:二进制里不能残留供体品牌串,模板与自动保存要落到轻矢自己的目录,停靠面板布局要符合 AI 工作区习惯,点击行为不能被隐藏控件劫持。这些都在 PORTING.md 的验证状态一节逐项登记,未闭环的如实留在遗留清单。

层次 原项目实现(v1.1.0 自绘引擎) 鸿蒙侧当前方案(v2.0.0 原生引擎)
界面层 ArkUI Canvas 自绘,2.96 万行 ets GTK 4.14.5 完整栈渲染真实 Inkscape 窗口,XComponent(TEXTURE)承载
编辑引擎 自研 C++ 引擎 3.4 万行(libairvector.so) Inkscape 1.5.0-dev 原生引擎(libinkscape_base.so)
AI/PDF 导入 3530 行手写解析器,缺陷缠身 poppler 26.07 上游原生导入(多页与裁剪框)
依赖形态 17 个静态 .a 共 53 MB 入库 65 个动态 .so,来自 gtk4-stack 共享栈
菜单体系 ArkTS EditorMenuBar 自绘 GMenuModel 到 JSON 桥,ArkTS 菜单栏回注
停靠面板 ArkTS 三面板 Inkscape 原生 dock,dialogs-state-ex.ini 为布局权威
文件支持 位图为主,AI 导入调试中 SVG/AI/PDF/CDR/VSD/DXF/EMF 全族导入,PDF/PS/EPS/ODG 导出

引擎切换同时是一次许可转换:与 Inkscape 同进程动态链接构成衍生作品,工程从无 LICENSE 声明转为 GPL-3.0-or-later。这条边界写进了 README 的归属一节,也是选型时明确评估过的代价。

▍三、鸿蒙版的整体架构

v2.0.0 的架构与 AirScape 同源:ArkTS 薄壳负责菜单、选择器、闪屏、剪贴板与分享;libgtkbridge.so 是薄 NAPI 层,按拓扑序 dlopen 59 个动态库;libairvector_core.so 充当 GTK 线程宿主并构造 InkscapeWindow;真正的编辑能力全部来自 libinkscape_base.so。XComponent 采用 TEXTURE 模式,使 ArkUI 弹层可以浮于 GTK 画面之上。

text
ArkTS 壳(entry/src/main/ets)
├── pages/Index.ets # XComponent 宿主页与顶部菜单栏
├── pages/DialogPage.ets # 原生对话框的 ArkTS 宿主
├── utils/FileManager.ets # 系统文件选择器
├── utils/ImportManager.ets # 碰一碰/附近设备/分享导入
├── utils/KeysPresetManager.ets# 快捷键方案(默认 adobe-illustrator-cc2024)
└── components/SubWindowManager
▼ libgtkbridge.so(薄 NAPI,拓扑 dlopen 59 .so)
libairvector_core.so(GTK 线程宿主 + InkscapeWindow + OHOS GDK 后端)
├── GTK 4.14.5 栈(gtk4-stack 共享前缀,757M/69 库,只读)
├── libinkscape_base.so(Inkscape 1.5.0-dev)
└── poppler 26.07(AI/PDF 导入链)


主要目录如下:

text
AirVector/
├── PORTING.md # 移植地图(唯一权威入口)
├── docs/ # 引擎路线方案调研
├── native/
│ ├── scripts/ # env.sh / build_gtk_with_gl.sh / build_inkscape.sh / deploy
│ ├── patches/airvector-inkscape-local/ # 品牌分叉唯一载体(clone+overlay)
│ ├── install -> Frameworks/prebuilt/gtk4-stack # 共享栈只读 symlink
│ └── BUILD.md # 八步构建链全景
├── entry/src/main/
│ ├── module.json5 # 横屏、单权限、图片分享入口
│ ├── ets/ # ArkTS 壳
│ ├── cpp/ # 桥与 core、GDK 后端补丁、ELF 工具族
│ │ └── libs/arm64-v8a/ # 65 个打包 .so(构建产物)
│ └── resources/rawfile/inkscape-share/ # Inkscape 数据 30 MB
└── tests/samples/ # .ai 回归样本


▍四、核心适配过程

### 1. 三路线决策:为什么整体移植而不是双引擎

调研文档对 B 路线(双引擎共存)的否决理由至今有参考价值:自绘引擎静态嵌入了 cairo/poppler/freetype/lcms2 符号,GTK4 栈的 65 个动态 .so 含同名库不同版本,musl 下 RTLD_GLOBAL 加载后导出的静态符号会互相截获,版本错位即随机崩溃;再加双 FreeType/双 fontconfig 状态并存与三线程模型交互无先例,工作量估计 60 至 90 人日且风险不可控。A 路线以 30 至 45 人日获得 AirScape 已打磨的 S17 水准体验,回退性由 git 分支保障(旧引擎归档于 legacy/selfdrawn-engine 分支,基线 tag v1.1.0-selfdrawn-final)。

### 2. 供体资产复用与跨二进制契约名

libinkscape_base.so、libgtk-4.so 与全部依赖 .so 直接复用 AirScape staged 成品(md5 逐一核对一致,含其 S15 至 S17 修复)。移植中最贵的一课是跨二进制契约名不得改动:.so 内写死读取的环境变量 AIRSCAPE_AUTOSAVE_DIR、AIRSCAPE_OHOS,dlsym 符号 airscape_ohos_pick_file、airscape_ohos_finalize_save、airscape_ohos_fetch_pasteboard_image、airscape_ohos_show_error_toast,以及 hilog 探针串 AIRSCAPE-PERF/AIRSCAPE-FRAME,全部保持原名——一次批量 sed 改名曾导致文件打开、保存与贴图静默失效,事后以 strings 验证固化为部署检查项。

### 3. clone+overlay 构建与共享栈纪律

品牌定制不能写进共享树。build_inkscape.sh 自 2026-09-28 起改为 clone+overlay 模式:APFS 克隆共享树到 native/build/inkscape-src-air,再叠加 native/patches/airvector-inkscape-local/(品牌分叉的唯一载体:自动保存 fallback 目录 Download/AirVector、hilog tag AirVectorKnock,其余文件与 AirScape patches 字节级同源),产物装入私有前缀 install-inkscape 防止污染共享栈。依赖库(非 Inkscape 主体)继续以只读的 Frameworks/prebuilt/gtk4-stack symlink 为准,与 AirBrake、AirScape 共链零改写。po 翻译文件也曾因只存在于会被重克隆的 build 树而险些丢失,现已入镜像并由 build_inkscape.sh overlay 增补。

### 4. ArkTS 壳的系统能力接线

ArkTS 侧保留了轻矢自有的壳能力:系统 DocumentViewPicker 文件打开与 native 侧经 req/complete_pick 闭环;剪贴板经 UDMF 与 GTK 侧互通;自动保存目录经 setDownloadDir 注入 Download/com.airvector.app;碰一碰与附近设备导入由 ImportManager.ets 承担;分享入口接收最多 8 张图片。快捷键方案按用户决策跳过首启向导,native prefs 种子每次启动无条件写入 adobe-illustrator-cc2024.xml 默认 AI 键位,手动切换入口保留在文件菜单。

### 5. 布局与汉化的数据层定制

停靠面板布局的权威文件是 Inkscape 1.5 运行期读写的 dialogs-state-ex.ini(仓库里数字码格式的 dialogs-state.ini 是 1.3.x 遗物,无人读取)。工程以 rawfile 携带 ex.ini 写入面板字符串名,并引入版本哨兵 .inkustrator_layout_v3:无哨兵即铺默认布局(对齐 Adobe AI 的填充与描边、图层与对象两面板),同版本内保留用户回写。汉化走数据层零重编路径:zh_CN.po 回收 500 条因 msgid 大小写漂移而变 fuzzy、被 msgfmt 默认丢弃的条目,编译出的 mo 含 10657 条翻译经 rawfile 通道部署,且以 msgunfmt 回验后才允许上线。

▍五、适配中遇到的几个难点

### 难点一:幽灵模板框与陈旧合成缓冲(P1)

首启模板对话框取消后画布上残留半个对话框。根因在 GDK 合成层:浮层模式对话框内容经内联合成写入全屏缓冲 s_screen,取消后的重绘帧命中 comp/blit 快路径跳过合成,后续因软光标在场禁用快路径的帧只重写本帧 dirty 区,区外沿用陈旧内容随全幅 blit 上屏。修复为三处改动:s_screen_stale 标记、hide/destroy/popup-hide 挂接失效、stale 帧禁快路径并全幅重建,行为签名是 hilog 出现 screen cache stale -> full rebuild。连点 12 次零复现,同款缺陷同步修入 AirScape 源码。后续 P5 的 dock 页切换残片同源,以"快路径帧把 dirty 并入 pending 记账、合成帧按 pending 并集重画"统一解决。

### 难点二:GtkNotebook 隐藏页劫持点击(IME 桥)

变换面板的错切/矩阵标签点击必弹软键盘且吞掉触摸。根因是 IME 桥的几何兜底逻辑遍历全部 visible 编辑器,而 GtkNotebook 非活动页子件的 visible 恒为 TRUE 且 allocation 保留——隐藏页一个 180x26 的 GtkText 矩形恰好罩住标签点击区,容差命中即拉起键盘。修复是兜底遍历加 gtk_widget_get_mapped 判定:控件层 map 不经窗口管理器,与窗口层的同款坑不同源。两轮验证五个标签零误弹。

### 难点三:GTK4 CSS 的两条新坑

FillStroke 子页签文字截断的修复暴露了本 GTK4 栈的两条行为:notebook>header>tabs>tab 直接子代选择器静默不匹配,必须用纯后代选择器;-gtk-icon-size 一旦改尺寸,multicolor 图标整体变纯红 RGB(204,0,0),只能禁用。最终方案是 po 四条译文去掉助记符后缀加 user.css 的 10px 字号规则(容器名经 DialogBase 的 set_name 对话框类型挂接),图标尺寸一律不动。

### 难点四:模板自带的视口存档

新建文档偶发页面在视口外。根因在 rawfile 模板 SVG 里:模板作者保存时把自己的视口(zoom、cx、cy、window 属性)存进了文件,新建文档时 sp_namedview_zoom_and_view_from_document 走"有存档则跳到作者视口"分支,页面位置全看作者当时滚到哪。修复是剥离 9 个模板共 36 个视口属性,强制落入 zoomToSelectedPage 兜底,新建文档、US Letter、A4 横向三路验证全部页面对中。同批还把模板自带的西语默认图层名改为图层 1。

### 难点五:翻译链的静默回退

汉化缺陷大多不是"没翻译",而是翻译被静默丢弃:msgfmt 默认丢弃 fuzzy 条目,msgid 漂移或错译的旧条目直接回退英文;一次 msgfmt 在错误工作目录失败后 mo 未重生即部署,浪费一轮验证。工程由此确立两条流程纪律——fuzzy 条目逐条回收而非整批保留,mo 必须经 msgunfmt 回验再部署。最终状态栏、搜索栏、模板分类全中文,模板名 A4/US Letter 作为上游专名保留原文。

▍六、编译、安装与启动

日常迭代(仅改 ArkTS 或桥)直接两步,README 给出的流程:

bash
source native/scripts/env.sh # 工具链环境(依赖库由共享栈提供)
devecocli build # HAP → entry/build/default/outputs/default/


涉及 GDK 或 Inkscape 定制时,按 native/BUILD.md 八步链先重建(依赖库一步跳过,gtk4-stack 已含全部):

bash
bash native/scripts/build_gtk_with_gl.sh # 仅 GDK 定制变更时
bash native/scripts/build_inkscape.sh configure && ninja -C native/build/inkscape inkscape_base -jN
bash native/scripts/deploy_inkscape_libs.sh # 注意保持 airscape_ohos_* 契约名
python3 entry/src/main/cpp/patch_libs.py <entry libs> native/install/lib


打包与安装启动:

bash
export JAVA_HOME=/Applications/DevEco-Studio.app/Contents/jbr/Contents/Home
export DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk

hvigorw --mode module -p module=entry assembleHap --no-daemon


签名产物位于 entry/build/default/outputs/default/entry-default-signed.hap。连接设备后:

bash
hdc install -r entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.airvector.app


PORTING.md 记载的最近验证(2026-09-28 至 09-29,MatePad 11.5):首屏 Inkscape 编辑器完整渲染(菜单、工具箱、A4 画布、停靠栏、调色板),品牌零 AirScape 残留,文件选择器闭环,P1 至 P5 全部修复,S1 至 S14 自动化回归项全过,冷启动 2.67 秒,59 个 .so 与 AirScape 金标准库集一致;另完成了 v1.1.0 到 v2.0.0 的覆盖安装兼容实测(旧沙箱原样保留、首启资产重拷 0.7 秒无感知、二启恢复 up-to-date)。

▍七、当前功能边界

当前已覆盖的能力:

- Inkscape 1.5.0-dev 完整工具链:钢笔、形状、文字、路径运算、渐变、节点编辑、对齐分布;
- 全族文件支持:SVG/SVGZ、AI/PDF(poppler 原生)、CDR/CDT/CCX、VSD/VDX/VSDX、WPG、DXF、EMF/WMF 及位图导入,SVG/PDF/PS/EPS/PNG/EMF/ODG 等导出;
- ArkTS 壳:菜单桥、系统选择器、UDMF 剪贴板、碰一碰/附近导入、分享收图、自动保存;
- AI 默认键位方案与右侧双面板停靠(填充与描边、图层与对象,哨兵机制管理重铺);
- 中文本地化(10657 条翻译)与固定深色主题;
- v1.1.0 自绘版到 v2.0.0 的覆盖升级兼容(实测通过)。

尚未覆盖或规划中的能力(依据 PORTING.md 遗留清单与验证记录):

- S4 手写笔、S8 文件夹授权、S10 碰一碰三项自动化不可达,发布前需人工补验;
- 固定深色主题(设计使然,非缺陷,S11);
- 观感类上游问题:模板卡标题换行、单位混用、dock 窄宽度下的文字省略;
- stage-window-created 固定约 2 秒为冷启动耗时主体,未立项优化。

因此,当前版本更准确的定位是"引擎换代已完成、修复与回归已闭环的轻矢 2.0":Inkscape 原生能力与轻矢品牌、数据、布局完成对齐,剩余项集中在发布前人工验收与上游观感打磨。

▍八、总结

轻矢这次适配的核心动作是承认自绘路线的极限并整体换轨。方案调研把三条路线的工作量、符号风险、GPL 影响与回退性摆上台面,A 路线胜出靠的不是胆量而是供给——同一工作区里 AirScape 已经把 GTK4/Inkscape 全栈在鸿蒙上打磨到 S17 水准,整体移植使轻矢一步获得 3.4 万行自绘代码长期未能企及的文件兼容面。移植过程中沉淀的纪律同样有普适价值:跨二进制契约名清单、clone+overlay 的品牌分叉载体、布局哨兵机制、mo 回验流程,每一条都来自一次真实的踩坑。

后续工作的重心清晰而有限:S4/S8/S10 三个人工项在发布前补验,观感类上游问题按反馈逐步上报或本地修补,与 AirScape 的缺陷同步机制继续维持(P1/P5 均为双向同步修复)。引擎换代完成后的轻矢,迭代重心将从"换引擎"转向"用引擎"。
楼主 8 天前
想参与讨论?登录 或 30 秒注册。