主题
更新日志
本页按版本号记录一凡OFD(npm 包名 rust-ofd)每次修改与升级的内容,新版本在上。
版本号与 WASM 内核一致:页面端调用 wasmVersion() 可读取当前实际加载的内核版本(阅读器示例顶栏徽标与「授权」面板均有展示,可用于核对部署产物是否为预期版本)。
记录约定
- 内核(Rust crates / WASM)发生功能新增或缺陷修复时,workspace 版本号同步升级。升号须同步四处(缺一处即坏,详见根目录
AGENTS.md「版本号策略」):① 根Cargo.toml的[workspace.package].version;② 同文件[workspace.dependencies]中内部 crate 的version(与全局一字不差,v0.10.0 起为 9 个——新增 ofd-jpx);③packages/ofd/package.json;④Cargo.lock(随构建自动更新)。各 crate 均为version.workspace = true,勿单独改。升号后在本页顶部追加条目,WASM 授权产物须重建才会显示新版本; - 条目须包含:版本号、日期、本次修改与升级的内容(面向使用者的表述,而非提交记录罗列);
- 前端示例(vue-demo 等)与文档站自身的 noteworthy 改动,随所在内核版本一并记录;
- 纯文档错别字等无行为变更可不升版本,直接在对应版本条目下补记。
v0.11.0 — 2026-10-10
对标数科阅读器的可感知差距补全:内核把一批「模型已解析但未导出/未消费」的能力开放出口,阅读器示例(vue-demo)升级为多视图阅读器(默认仍为单页,既有交互零变化)。
渲染内核与 WASM API(core 模块)
- 图层运行时切换:新增
pageLayers(page)枚举页面图层(含声明隐藏层)、setLayerVisible(id, visible)/resetLayerVisibility()即时开关——对 renderCanvas / renderPng / exportImage 等全部渲染出口生效;Rust 侧同能力经RenderOptions::layer_overrides开放(默认空表 = 按文档声明渲染,不传即旧行为); - 视频对象封面渲染:
VideoObject的PosterID封面图照常呈现(数科同观感;此前只画灰色占位框;无封面或封面损坏保留占位框,零 panic); - 多媒体出口:
medias()列出图像/视频/音频资源(类型/格式/时长/自动播放),mediaBytes(id)取任意媒体文件字节;pageVideos(page)导出页内视频区域(供阅读器放播放按钮); - 文档信息补全:
docInfo()新增permissions(打印/拷贝/导出/修改/注释/签名/水印/全屏 8 项国标权限声明)与vPreferences字段;customTags()导出语义标引条目(GB/T 33190 第 16 章——电子发票字段标引等厂商扩展的数据入口)。
工具模块(tool)
- 加密 OFD 浏览器端闭环:
isEncryptedOfd(bytes)检测、decryptOfd(bytes, 私钥hex)解密、encryptOfd(bytes, 公钥hex[])加密(SM4 内容加密 + SM2 数字信封,与 CLI 同底座,字节级一致);npm 包装器rust-ofd已同步导出。
阅读器示例(vue-demo)
- 视图模式:单页(默认,与旧版一致)/ 连续滚动 / 双页对开——流式模式按可见性懒渲染、远离视口自动回收画布,滚动位置实时同步当前页与键盘翻页;
- 视图旋转(90° 步进会话级预览,不改动文档字节;「整理」页的旋转仍是文档级编辑)、夜间模式(界面深色,纸面内容保持原样)、全屏阅读、缩略图导航栏(懒渲染小图,点击跳页);
- 检索导航:上一处 / 下一处顺序巡览命中 + 当前命中行高亮;页码输入框回车跳页(此前为死代码);
- 页面标注工具:在页面上直接拖画高亮 / 矩形 / 椭圆 / 直线(颜色、线宽、透明度随「注释」表单),松开即写回标准注释——替代「表单填 mm 坐标」的旧交互(表单保留可用);连跨页签批不变;
- 信息页补全:主题 / 关键词 / 创建与修改时间 / 制作者 / 自定义数据;文档权限声明徽章(仅展示提示,不拦截);发票字段一键识别卡(extractFields);图层面板(配合 pageLayers 即时开关);
- 导出长图入口接入 exportLongImage(此前 API 已有、界面无入口);打开加密 OFD 失败时自动识别并弹出密钥解锁(配合 tool 模块新导出)。
勘误与文档(不改行为)
Clips/@TransFlag:语料实证 60 文件 / 6788 处几乎全为false(ofdrw 写出件缺省如此)且 ofdrw 读取端不消费——渲染变换链对 true/false 一致为正确口径(94 语料对拍锁定),修正模型注释中「false = 不随宿主变换」的误导描述;- README「已知边界」删除「Canvas 指令流后端不解释图像 CTM」的过时表述(该后端实际已支持图像仿射);
- 文档站全站数字与能力口径随本版本校准:crate 数(13,含 ofd-jpx)、测试数(391)、内核体积(约 3.5MB)、能力矩阵「加密」补 WASM 出口、快速开始页工具模块补加解密触发;价格页企业版不再列示「优先 / 驻场支持」档位;文档站内嵌 Playground 演示内核同步刷新为 0.11.0;
- 测试:workspace 全绿(ofd-render 新增图层覆盖与枚举、视频封面渲染回归测试);vue-demo 生产构建通过。
v0.10.0 — 2026-10-09
OFD 阅读方向两大图像能力补齐(JBIG2 精化全路径 + JPEG2000 渲染):
- OFD 文档内嵌 JPX/JPEG2000 图像可渲染:此前仅 PDF→OFD 转换方向支持 JPX(v0.6.0 起),阅读 OFD 文档时遇到 JPX 图像只画灰色占位框;现解码能力自 ofd-convert 下沉为独立
ofd-jpx模块(vendor openjpeg 2.5.3,含 wasm32 垫片与空 tile 崩溃围堵),渲染管线在 PNG/JPEG/JBIG2 皆不识别时按魔数嗅探尝试 JPX 解码,失败仍回落占位框(零 panic)。印章(SES)位图路径同步受益;core 模块 wasm 体积 gzip 增加约 80KB(feature 门控,可关); - JBIG2 refinement(精化)全路径:此前 symbol dictionary 的 SDREFAGG 聚合与 text region 精化实例降级为「直接复用参考符号」(占位来源之一)。现按 T.88 6.3/6.4/6.5 完整实现:
- 泛型 refinement 区域的 TPGRON 典型预测(SLTP 上下文按 jbig2dec 权威值 0x100/0x40,隐含值九宫格判定;此前两次「失步」实为 pdf.js 位序值未换算 + 模板 1 段头多吞 2 字节 AT 的组合误诊——后者为本轮修复的既有缺陷);
- 符号字典 SDREFAGG=1 单实例聚合(IARDX/IARDY 锚定 + GR 算术重构)与 IAAI>1 内嵌文本区域(与外层共享算术流);
- 文本区域 SBREFINE=1 精化实例(IARDW/RDH/RDX/RDY + GR 重构),以及 SBCOMBOP 全部组合算子(AND/XNOR 此前降级为 OR);
- 已知限制(与 pdf.js 口径一致):SDHUFF=1 × SDREFAGG=1 组合仍拒绝(生态零实现:jbig2enc 不产生、pdf.js 拒绝、jbig2dec 实现的算术流位置语义无法自洽);halftone 区域的 HSKIP/灰度 MMR/非 OR 灰度拼贴仍跳过;
- 迁移与体例:ofd-convert 切换为依赖 ofd-jpx(解码行为零变化,单测像素断言锁定);OFD 包写出的 jp2/jpx/j2k/j2000 媒体改 STORED 打包(已压缩格式不重复 deflate);
- 测试:workspace 全绿(ofd-core 105,新增 TPGRON roundtrip、SDREFAGG 单实例/多实例 e2e、文本区域精化实例 e2e、AND/XNOR 组合算子 e2e、JPX 渲染 e2e);pdf2ofd 语料评测 JBIG2/JPX 相关文件全部转换成功、零 panic、无退化。
v0.9.1 — 2026-10-09
v0.7.0~v0.9.0 三批次代码审查专项修复(双审查代理深读内核与前端,1 项 P0 + 6 项 P1 + 10 项 P2,全部 P0/P1 与 7 项 P2 落地):
- 修复「关闭文档」失效(P0):关闭按钮因一处变量改名残留(
drawPts未声明,严格模式赋值抛错中断后续全部清理)导致界面卡在「幽灵文档」状态——修为当前笔画变量并连带补齐多笔签批与表单状态的清理; - 表单卡时序与翻页(P1):打开新文档时表单字段读取早于页码归位(读到旧文档页码,小文档越界返回空表),且翻页不刷新字段(在错误页填写)——读取移到页码归位后并随翻页刷新;
- 「打印」按钮弹窗拦截兜底(P1):转换耗时超过浏览器用户手势窗口后新标签几乎必被拦截且无提示——拦截时自动降级为下载打印版 PDF,始终有出口;
- 文档站 Playground 三处加固(P1/P2):wasm 改强制绕过缓存(防内核升级后胶水与旧 wasm 版本错配——项目缓存纪律);渲染加序号令牌(快速翻页时旧页后到不再覆盖新页);页面卸载释放 wasm 侧文档内存;
- 手写墨迹防丢失(P2):缩放/字体就绪重绘不再清空未保存笔画(同页保留并按新比例重画预览,仅翻页清空);保存失败时笔画还回累积区可直接重试;
- 内核健壮性(P1/P2):表单字段值拼接的排序比较器改为全序(非全序比较器在新版 Rust 排序实现中可能 panic——零 panic 红线);发票日期扫描去掉平方级后缀复制(超长单行不再卡死);表单填写补正文层的对象 ID 漏递增(防 ID 撞号);填写区坐标 NaN/inf 守卫(防产出损坏文档);长图导出改两遍法(峰值内存约减半);JPEG 质量 0/越界统一归默认 90(JS 传 0 不再得到质量 1 的废图);
- CLI 加固(P2):批量报表 CSV 防公式注入(
=+/−@开头前置引号);同主名消解改哈希查重(数万文件不再平方级);--scale与--dpi两种出现顺序都正确互斥; - 全 workspace 测试通过(新增:表单值阅读序拼接/交错行场景回归);
- 补记(2026-10-09,随本版本一并交付,仅前端界面、内核与 API 无变化,不升号):阅读器示例(vue-demo)界面全面优化并上线——「获取授权」弹窗移除收款二维码,改为联系方式直达(微信 / 邮箱两张联系卡,点击复制、一键发信,portal 在线申请入口保留);侧栏六个功能面板表单布局重构:标签统一上置、控件换行对齐不再参差,数字输入的占位提示不再被步进箭头截断,超长占位规则移至行下方完整可读,面板内容超出一屏时改为内部滚动;另统一表单定焦高亮、检索框弹性伸缩、注释列表长文本不再互相挤压、授权管理弹窗超高内容可滚动;
- 补记(2026-10-09,文档站 SEO 修复):文档站首页标题补齐关键词(原仅"rust-ofd")并修复栏目页 og:title 为空的问题(新增页面无 frontmatter title 时全站兜底);主站 sitemap 更新日期改为构建期自动刷新(原停在首次上线日);清理服务器内部页(授权/部署手册)历史残留 html,并修复文档站不存在路径返回 200 的软 404(现正确返回 404 状态码与 404 页)。SEO 整体方案见
docs/business/SEO优化流程与方案.md。 - 补记(2026-10-09,随本版本一并交付,仅对外品牌与文案,内核/API 无变化,不升号):项目对外定名「一凡OFD」——阅读器示例、文档站与 README 的品牌展示层(站点标题、og/JSON-LD 元数据、顶栏/页脚、正文叙述)统一由 rust-ofd 换为「一凡OFD」;npm 包名、Rust crate 与全部技术标识保持
rust-ofd不变,已安装用户的集成代码不受影响。品牌域名 z1fan.com 已注册,暂不切换站点域名。
v0.9.0 — 2026-10-09
易用与转化批次(《价格与功能优化路线图》v0.9.0,路线图收官):
- CLI 批量转换(
ofd-cli batch):面向档案迁移的非技术用户包装——目录/文件列表批量 PDF↔OFD(按扩展名自动定向,--to可强制方向、--recursive递归);断点续跑(已存在且不早于输入的输出自动跳过,中断重跑零重复劳动);逐文件容错续转(失败记报表不拖垮整批,--stop-on-error可改为即停);CSV 报表(path/direction/status/seconds/error,带 BOM 可直接双击打开)与逐文件进度显示;同名输出自动消解(递归目录撞名加-2/-3后缀)。验收:500 份混合语料实测零 panic(493 成功 + 7 份 vendor 层已知损坏件正常记 fail,进程干净退出); - 打印保真出口(阅读器「打印」按钮):打印专项验收实证「直接 Ctrl+P 打印网页 = 打印应用界面而非文档」(无打印 CSS、单页 canvas 形态),正确出口 = OFD→PDF 矢量转换后打印:一键生成多页全保真、文本可检索的 PDF 并新标签打开,Ctrl+P 即所见即所得。FAQ 补「怎么打印」口径;
- 文档站内嵌 Playground:WASM 快速开始页新增「在线演示」——页内真实内核渲染(非截图),固定演示样张(数科版式文档)可翻页/缩放、显示内核版本与渲染耗时;演示授权与主站同域复用在线续期,本地预览时优雅降级为提示。转化价值:访问者零安装即见内核真实渲染效果;
- 全 workspace 测试通过(本版新增 4 项:batch 规划定向/同名消解、断点续跑 mtime 规则、混合目录端到端含坏文件与续跑断言);
docs站点新增rust-ofd本地包依赖(Playground 用),wasm 演示资产(3.3MB 内核 + 回退字体 + 样张)随 public 目录分发; - 注意:WASM 内核本版无新 API(
wasmVersion()仍 0.9.0 需重建生效);「打印」按钮依赖转换模块(已授权部署自动可用)。
v0.8.0 — 2026-10-09
交互双件(《价格与功能优化路线图》v0.8.0 批次):表单填写 + 原笔迹手写签批。
- 表单字段与填写(
formFields/fillFormFields):前置调研确认 OFD 国标(GB/T 33190-2016)没有表单域标准——生态事实标准是数科AreaHolderBlocks.xml命名填写区(区域名+边界,Document.xml 不引用、按约定发现式加载)。本版落地完整闭环:内核解析填写区(宽容降级,缺失不影响文档打开)→formFields(page)导出字段(区域 ∩ 文本层求交,值文本未嵌入时须先addFallbackFont,与发票提取同因)→fillFormFields(ofd, fills)把值以 TextObject 写入所属页正文层(数科语义:跨阅读器可见、可检索、写回后formFields可取回)→ 未命中字段名明确报错并列出文档全部填写区。填写会修改页内容文件:已签名文档的既有签名摘要将失配(等同修改正文),应在填写后重新签名(前端已提示)。数科真样本往返实测通过(tests/data/areaholder-fields.ofd); - 手写签批(
addAnnotation新增type: "ink"):前置调研确认墨迹的标准表达 =Type="Path"注释 + 外观内 PathObject 线段(GB/T 33190 第 15 章原生表达,数科/ofdrw 均按此渲染注释外观,无需自造格式)。ink为输入别名(落盘标准 Path 注释):strokes: [{points, width}]多笔一次落成一条注释,每笔独立 PathObject 与线宽(压感由前端烘进笔级 width——触屏/手写板轻压细、重压粗),全部笔迹共享总包围盒 Boundary,单点点触自动扩为微线段。阅读器示例「签批」按钮即此形态:页面级 overlay 画布 Pointer Events 采集(指针捕获跨画布书写)、压感实时预览、多笔累积、「保存墨迹 / 清空」操作(原「手绘」单笔即时提交模式升级为多笔累计保存); - 实现落点:ofd-core 新增
form.rs(AreaHolder 解析 + reader 集成);ofd-render 新增form.rs(page_form_fields[_with]区域∩文本层);ofd-tool 注释AnnotationSpec新增strokes: Vec<InkStroke>(Path 分支多 PathObject 输出)与form.rs(fill_form_areas值文本写回,复用水印字体声明机制);wasm coreformFields/ toolfillFormFields+addAnnotation.strokes; - 全 workspace 376 项测试通过(本版新增 9 项:墨迹多笔 PathObject/总包围盒/笔级线宽/点触扩线/可删除、AreaHolder 解析两用例、reader 发现式加载、字段导出与无表单降级、填写往返取回/未命中报错/空值拒绝);node 三模块冒烟扩至 v0.8.0 三链路(formFields 空值 → fillFormFields 往返回读 → ink 注释落盘);
- 注意:WASM 授权产物需重建后
wasmVersion()显示 0.8.0;工具模块(fillFormFields/ink)按需懒加载,core 模块仅增 formFields(含 AreaHolder 解析,体积增长极小,体积表随部署更新)。
v0.7.0 — 2026-10-08
转换增值双 API(《价格与功能优化路线图》v0.7.0 批次):
- OFD→图片产品化(
exportImage/exportLongImage,WASM 新 API + CLI 增强):单页导出支持 PNG / JPEG(jpeg-encoder纯 Rust 编码器,无 C 依赖)、自定义 DPI(默认 96、上限 2540,与渲染守卫同口径)、JPEG 质量 1–100;多页长图竖向拼接(白底、水平居中、窄页居中留白),总画布沿用零 panic 守卫(边长 ≤16384px、总像素 ≤64M,超限返回含实际尺寸的错误);JPEG 单边 65535px 上限(JPEG 标准约束)。CLIrender新增--format png|jpeg、--dpi(与--scale互斥)、--pages 1-3,5(1 起,优先于--page/--all),输出扩展名随格式联动(目录模式/模板模式/缺省命名三路径全覆盖)。renderPng渲染路径重构为公共render_page_skia_target(行为零变化,355+ 既有测试护住); - 电子发票字段提取(
extractFields,WASM 新 API):基于文本层布局的模板化提取——行聚类(y 邻近)→ 标签匹配(行级拼接支持「名」+「称:」拆分书写、排除「项目名称」表头)→ 值提取(列对齐优先 + 度量漂移正则兜底:税号行内 15–20 位大写段、「称:」后段截数字前、代码+号码粘连段前缀切分)。字段覆盖票种/号码(旧 8 位/全电 20 位)/代码/日期/校验码/机器编号/购销方名称与税号(版式顺序分配)/合计金额/税额/价税合计大小写共 15 项;非发票文档不报错(matched=false空字段降级)。百望增值税电子发票实测全部字段正确(native 系统字体与 wasm 回退字体双度量路径均验证;样本tests/data/invoice-baiwang-vat*.ofd入库)。发票字体普遍未嵌入,调用前须addFallbackFont(文档已明示); - 新增依赖:
jpeg-encoder 0.6.1(MIT/Apache-2.0 双许可,纯 Rust)仅进 ofd-render; - 全 workspace 367 项测试通过(本版新增 12 项:图片导出 6——PNG/JPEG 魔数与尺寸、格式别名、长图高度=各页和、空页拒绝、DPI 缩放;发票提取 6——百望双样本字段断言、非发票降级、日期/大写金额/金额正则工具函数)。node 三模块冒烟扩至含三个新 API(
examples/node-demo/smoke.mjs); - 注意:WASM 授权产物已重建部署(线上
wasmVersion()核对 0.7.0);core 模块因 jpeg-encoder 与发票模块体积增长约 70KB(gzip,体积表已更新:core 3.26/1.13 MB、convert 4.68/1.68 MB、tool 2.02/0.71 MB)。
v0.6.1 — 2026-10-08
公网健壮性专项(商业化就绪审查修复):针对「不可信来源文档」场景的两个可崩溃缺陷与授权/交付链路的一批真实缺口。受控输入场景(内部系统、可信语料)本就达标,本版把同一标准补齐到公网/嵌入宿主场景。
- 渲染画布尺寸守卫(零 abort):恶意或损坏 OFD 声明超大 PhysicalBox(如 30000×30000mm,A0 的 100 倍)时,主渲染入口此前无尺寸上限(图案瓦片/转换侧 mesh 均有,唯独主入口缺失),96dpi 下请求约 51GB×2 分配直接 abort 进程——FFI/C#/Java 宿主与 wasm 阅读器全部可达。现与图案守卫同口径(边长 ≤16384px、总像素 ≤64M),超限返回明确错误信息(含实际请求尺寸与上限);印章子文档(OFD 型印章外观)同守卫,超限降级为无印章外观;CLI
render --scale补上限 100px/mm 与非法值校验; - 渐变函数/色彩空间递归深度守卫(防栈溢出):恶意 PDF 以间接引用构造 FunctionType 3 自引用 / Separation 交替空间自引用,此前解析为无限递归栈溢出段错误(catch_unwind 与字节变异 fuzz 均无法拦截)。现函数/色彩空间解析统一携带深度上限 16,超限返回 None 走对象级跳过降级(SkippedObject 警告不变),合法嵌套(两层 stitching 等)不受影响;
- 模糊测试双向化:此前
fuzz_smoke只覆盖 PDF→OFD 单向,OFD 解析→渲染方向(阅读器主业输入面)零 fuzz——本次两个崩溃缺陷恰在此路径。新增ofd-render/tests/fuzz_ofd_smoke(真实样本 + 超大 PhysicalBox 守卫形态种子,canvas/PNG 双后端,默认 800 次、FUZZ_ITERS可加压),并在 PDF 侧种子中加入自引用渐变构造形态; - C ABI 边界 panic 兜底:ofd-ffi 的解析/渲染/转换/验签导出统一经
ffi_guard捕获 panic 转为可读错误(此前 panic 穿越extern "C"边界直接打死 C#/WPF、Java/JNA 宿主进程且无法恢复); - WASM 核心模块授权逐次复验:
OfdDoc的渲染/文本/图像/检索/附件/注释/验签等 14 个内容方法入口补授权复查(此前仅构造时校验一次,token 过期或吊销后已打开的文档可无限期继续用),与 convert/tool 模块及授权文档「每次功能调用复验」的声明对齐;pageText/pageImages在授权失效时抛出授权错误而非静默返回空值,元信息 getter(pageCount 等)不受影响; - 验签「未保护文件」分级:签名后新增的注释/附件文件此前与真实篡改同权重报
digestValid=false(较国标更严的过严规则),线上验签告警噪声大。现此类文件单列新报告字段unprotectedFiles(WASM/FFI/CLI 同步),digestValid只对「References 列举文件摘要不匹配/缺失」判 false;篡改受保护文件仍正确判无效。阅读器验签面板同步展示「签名后新增 N 个未保护文件」;文档补充两条明示:未配信任锚时signatureValid不能单独作为可信结论(内嵌证书可自造)、非浏览器宿主(Node 等)可伪造 hosts 绑定(高价值离线交付应走--did定制构建); - 交付脚本安全化:
build-dist.mjs不再硬编码生产服务器 root 账号与 IP(改为环境变量 /.license-keys/deploy.env读取,示例见scripts/deploy.env.example,缺失时明确报错并建议非 root 受限账号);非 Windows 平台 zip 打包改用系统zip(此前 PowerShell 专属命令必失败);分发包输出根目录跨平台默认到仓库target/(不再绑定特定开发机盘符); - 小修:CLI
pdf2ofd默认输出名只替换末尾.pdf后缀(此前全量替换把a.pdf.and.pdf错改为a.ofd.and.ofd,现保留原文件名大小写);wasm 授权模块锁中毒降级(持锁路径 panic 不再连锁);自签证书生成移除可达路径上的expect改为错误传播;openjpeg 构建脚本的头文件变更也触发重编; - 文档口径:首页与阅读器示例的语料成功率数字更新为 98.1%(与 0.6.0 实测一致,此前的 97.9% 为旧轮数字);「能力边界」页 JPX 条目区分转换端(已真解码)与渲染端(仍占位);
- 全 workspace 355 项测试通过(本版新增回归 9 项:超大画布拒绝与边界、自引用函数/色彩空间拦截与合法嵌套、OFD 方向模糊、FFI panic 兜底与超大画布链路、CLI 输出后缀;样本无需入库——全部运行时构造)。
补记(2026-10-08,商业化定价与运营落地,随本版本一并交付;内核无变化):商用定价调整为公开三档——线上阅读器「获取授权」弹窗由单一 ¥1,999 一口价改为三档价格卡:预览版 ¥999 / 转换版 ¥1,999 / 全功能版 ¥2,999(均在线授权 · 元/年/域名,含子域与标准支持,授权期内次版本与修订版本免费升级),30 天免费测试授权不变;内网离线、多实例、合同发票与 SLA 走企业版询价(portal 申请或微信联系)。文档站新增「价格与授权」与「常见问题」两页(含购买、联系方式与报障材料说明)。免费在线站同日明确使用边界:供个人评估使用(页脚提示 + 单文件 50MB 上限),商用授权的 SDK 与部署产物无任何此类限制。10-08 前按旧价付费的客户按原价规则过渡。
注意:WASM 授权产物需在具备 wasm32 clang/LLVM 工具链与授权密钥的机器上重跑 build-licensed.mjs 才会显示 0.6.1(本版为缺陷修复,转换行为与 0.6.0 一致);部署后以 wasmVersion() 徽标核对。
补记(2026-10-08 晚,阶段三运营加固,随本版本一并交付):
- CI 最小门禁:新增
scripts/ci-check.sh(cargo test --workspace + clippy,Windows 自托管自动 source build-env.sh)与 Gitee Go 流水线.workflow/rust-ci.yml(push main 触发;字段如与本版本面板有出入,按等价步骤可视化配置即可,门禁实体在脚本); - 评测脚本可移植化:
pdf2ofd-eval.py/pdf2ofd-page-verify.py的 poppler 与 xpdf pdftotext 路径改OFD_POPPLER_BIN/OFD_PDFTOTEXT环境变量优先(CI/异地环境免改码),本机安装位回落不变、历史口径可比; - 授权服务监控告警上线(服务器 root cron,
examples/license-server/monitor.mjs,每 5 分钟):healthz 可达与延迟、HTTPS 证书剩余天数(<14 天告警)、/www 磁盘占用(>85%)、服务进程存活(pgrep,pm2 托管自动识别);OFD_ALERT_WEBHOOK配置后推送到群机器人,OFD_ACCESS_LOG配置后启用 429 错误率检查; - 备份恢复演练闭环:数据库每日备份(mysqldump→gzip 校验→滚动 30 份)+ 恢复演练脚本(最新备份恢复进临时库逐表行数对比,每周一自动跑)。首次演练记录(2026-10-08):12 张表行数全部一致,恢复路径验证可用,详见文档站内部页《宝塔部署》监控与备份节;
- 口径与合规:首页测试计数 250+→340+;阅读器示例新增隐私说明页(匿名统计的字段清单、不含文档内容声明、关闭路径)与首页告知入口;
THIRD-PARTY-NOTICES.md完成 OFL-1.1 全文 + 216 项 Rust 依赖完整清单(cargo metadata 全量清点,9 个许可族全文随附),build-dist.mjs打包强制随包 LICENSE 与声明文件(缺失即中止); - WASM 三模块产物已重建至 0.6.1(prod 公钥形态,体积与 0.6.0 持平:core 3.01/1.06MB、convert 4.57/1.65MB、tool 1.97/0.70MB gzip),
.wasm.gz预压缩同步生成;仍待部署上线(线上徽标届时核对 0.6.1)。
v0.6.0 — 2026-10-08
JPX/JP2(JPEG2000)真解码接入 + 渲染语义与零 panic 防线强化:
- JPX/JP2 原生解码:PDF 内嵌 JPEG2000 图像此前走占位图,现以 openjpeg 2.5.3 静态链入转换内核原生解码(灰度/RGB/CMYK/SMaskInData 透明度)。色彩空间按 JP2 colr 声明定位(enumcs=12 走 CMYK 合成)、不透明度通道按 cdef 标注定位(不假定首位——主流编码器在末位、Adobe 系在首位均正确);超大声明的恶意流按尺寸上限拒绝、wasm 下输出缓冲分配失败优雅降级为零 abort 路径。另前置码流结构校验:按段长走查 tile-part,任一 tile 数据段为空或声明越界即拒绝解码走占位——openjpeg 对"结构完整但 tile 数据为空"的码流(pdf.js 模糊样本 bug_jpx 形态)存在堆损坏写(分阶段二分定位在 opj_decode 内部,引爆点随堆布局漂移),结构级围堵零误伤(合法空包也至少 1 字节)。语料 14 份 JPX 文档全部真解码;
- Tr 5/6 描边语义(文本渲染模式):描边+裁剪、填充+描边+裁剪此前按纯填充近似,描边色文本会被画成填充色;现输出带 Stroke 属性与描边色的文本对象(与 Tr 1/2 同形,裁剪行为不变)。另评估了「裁剪不被 Q 恢复」的规范语义修正并暂缓:OFD 将裁剪嵌入每个对象,持久裁剪在生成器典型文件(每对象 q+W+Q)上会按 对象数×累积裁剪数 放大内存,表示法改造前维持与生成器惯例一致的近似;
- 零 panic 防线机制化:新增确定性变异模糊回归(
tests/fuzz_smoke,固定种子对代表性 PDF 做字节翻转/截断/片段复制,常态随测试运行,FUZZ_ITERS可加压);mesh 渐变解码总量守卫(Type 6/7 最小位宽流约 2400 倍内存放大,顶点/三角形超限弃画并告警);字形与路径裁剪统一守卫管线(字形裁剪 64k 独立命令预算);ConvertReport新增守卫遥测字段(max_clip_cmds/max_mesh_verts单页峰值),配套校准工具cargo run -p ofd-convert --example guard-stats -- <PDF 目录>输出语料分布,阈值是否有余量从此有数据可依; - 评测工具:
pdf2ofd-eval.py与pdf2ofd-page-verify.py的 SSIM/文本口径抽取为公共单源scripts/verifylib.py(两套脚本数字必须可比的部分不再双维护); - 全 workspace 347 项测试通过(本版新增回归 12 项:JPX CMYK/SMaskInData 两分支、空 tile 码流围堵、变异模糊、mesh 守卫、lattice 宽行、clip 守卫、CMYK JPEG 像素、Type0 变长切分 4 项;样本
jpx-smaskindata-sample.jp2/jpx-cmyk-sample.jp2/jpx-emptytile-crash.j2k入库)。
补记(2026-10-08,WASM 重建闭环,随本版本一并交付):三模块 WASM 授权产物已按 0.6.0 重建(本机安装 LLVM/clang 后 build-licensed.mjs test+prod 双构建)。wasm32 首次实际编译 openjpeg,为此补齐 freestanding libc 垫片(build.rs 按 wasm 目标注入:标准头、stdio/ getenv 桩、真实现 qsort/strcmp、手工 math——__builtin_pow/floor 等在 wasm32-unknown-unknown 上会降级为对同名符号的库调用,转发即无限自递归,两代踩坑均以 2×1 图/整本文件栈溢出显形),并修正 wasm 分配器垫片一处从未编译过的 realloc 参数错位。验证:wasm wasmVersion()=0.6.0;13 份 JPX 语料 wasm 侧全部转换成功,其中 S2/jpx_smaskindata/issue5481 与原生 CLI 输出字节级一致(手工 sqrt 定点收敛至 IEEE 正确舍入、lrint 半偶舍入后达成);node 三模块冒烟全过(smoke.mjs 补 location 多态与 token 前置激活)。体积(gzip -9):core 3.02/1.06 MB、convert 4.57/1.64 MB(openjpeg 净增约 +190KB)、tool 1.97/0.70 MB,体积表已同步。注意:产物尚在本地 .gen,未部署上线——部署需按既有流程上传(含 .wasm.gz 预压缩产物与配套 gzip_static),wasmVersion() 徽标核对后方可视为 0.6.0 上线。
v0.5.2 — 2026-09-30
PDF→OFD 转换质量专项:对 1018 份语料建立单文件全页面逐页严格对拍管线(scripts/pdf2ofd-page-verify.py,与既有抽前 3~5 页的整体评测互补),基于逐页证据定位并修复一批"整页评测分数不敏感但逐页肉眼可辨"的渲染不一致。样本级验证(css4 配色书、issue3584、text_clip_cff_cid、cmyk-jpeg、annotation_hidden_print 等)全部从 bad 修复至与参考渲染一致;全量复跑与基线对比随并行专项(JPX 解码接入)稳定后另行交付。
- 文本作裁剪(Tr 4~7)语义落地:PDF 文本渲染模式 6/7(填充+描边+裁剪、仅裁剪)此前解析直接报错被跳过,文本按普通填充画出、后续彩色矩形整块盖住版面(css4 配色书页、issue3584 "整页涂蓝")。现字形轮廓按完整变换写入裁剪区,模式 7 的文本本体不再产出绘制对象——"字形颜色的标题/艺术字"版式正确呈现;
- CID/子集字形映射修复(字符大面积变乱码族):
- CIDFontType0 的 CFF charset(GID→CID)反查接入,含裸 CFF 包装路径与 OTF 容器路径——转换型打字机/出版字体的 CID↔GID 不再按 Identity 瞎猜;
- CID-keyed CFF 的 FontMatrix 位于 Font DICT(FDArray 内),此前只读 Top DICT 导致 2000 units 字体按 1000 缩放、字形整体放大 2 倍;
- 嵌入子集字体查形优先级修正:嵌入面(Unicode cmap → 字节 cmap)先于回退字体——此前回退字体的字形会顶掉嵌入字体自身的正确映射(文本层对、视觉错字);
- Unicode 查形只查真正的 Unicode 子表:不再用字符码位去巧合命中 (1,0) 字节映射表('F'=0x46 查到字节表第 0x46 项的相邻字形);
- Type0 混码长 CMap(1/2 字节码并存)按"2 字节命中优先、否则 1 字节"变长切分,替代固定码宽的整段错位;
- 隐藏注释不再渲染:
/F标志位 Hidden(0x2)/NoView(0x20) 的注释此前照常迁移渲染(参考渲染为空白页而我们画出墨迹),现与 pdf.js/poppler 一致不迁移;OCG 隐藏逻辑不变; - CMYK/YCCK JPEG 转换端转码:4 分量 JPEG 此前原样透传,渲染端 jpeg 解码器对 Adobe CMYK/YCCK 的 RGB 转换存在 K 合成缺陷(色块过饱和纯色,cmyk-jpeg 语料 diff 100%)。现转换端用 zune-jpeg 原样解出 4 分量(YCCK 请求原样输出旁路其缺陷路径),按 Adobe 语义自行合成 RGB 后以 PNG 嵌入;带 SMask 的 4 分量图像同管线正确合成透明度;
- 附带:
ofd-cli render --all目录输出的页序按页号数字排序(此前_p10字典序排在_p2前,多页文件逐页对比工具会错位配对)。
全 workspace 328 项测试通过(新增回归:Tr 7 字形裁剪、隐藏注释标志、CID Font DICT FontMatrix、JPEG CMYK 探测各 1 项;tests/data/issue-tr7-text-clip.pdf 最小复现件入库)。
补记(2026-10-08,随本版本一并交付):授权服务 v2.4 上线 + 管理台登录优化(examples/license-server,服务端配套组件,内核无变化):授权服务 v2.4(申请选择授权模块、审核后一键构建分发包、双端界面重构,见 v0.4.6 补记)随本次首次部署生产(license.11m18.cn,存量库执行 upgrade-v2.4.sql)。管理台登录页口令框新增明文显示切换(显示/隐藏按钮);/admin 与 /portal 页面响应统一 Cache-Control: no-cache(每次向服务器再验证,页面更新即时生效,不再受浏览器旧缓存干扰);管理端口令最小长度由 8 位放宽至 6 位;新增运维脚本 server/reset-admin-password.mjs(忘记口令时在服务器上直接重置,重置后作废全部会话)。本地冒烟扩至 69 项断言全过。
补记(2026-10-08,代码审查修复,随本版本一并交付):对上述未发布改动做四路分区代码审查(FFI/渲染/字体/脚本),修复全部高优先级发现,全 workspace 341 项测试通过:
- 注释 /F 位值勘误:NoView 应为 0x20(0x4 是 Print)——按错误位值,生成器默认输出
/F 4的普通可打印注释会被整体丢弃; - Type0 变长切分缺省修正:2 字节码与 1 字节码都无映射证据时按声明码宽(Identity-H 缺省 2 字节)切分——此前缺省 1 字节,Identity-H 无 ToUnicode 的中文文本整段被逐字节错切成乱码;
- JPX 色彩空间常量对齐上游 openjpeg 枚举(CMYK=5 等,此前臆写值使 CMYK 分支不可达、真 CMYK 图被当 SMaskInData 处理);JPX 的 SMaskInData 不透明度通道改为按 cdef 标注定位(不再假定首位);wasm 下超大图输出缓冲分配失败优雅降级;
- 字形裁剪接入 clip 守卫管线(Tr 4-7 与路径裁剪共用去重/深度/命令数三层防御,字形用 64k 独立预算)——"重复画字当镂空模板"类病态输入不再能无界撑爆内存;
- mesh 渐变三处修正:Type 5 lattice 按规范"每行 VerticesPerRow 个顶点、行数由流长决定"解码(此前行列语义颠倒、宽行顶点被静默丢弃);解码加顶点/三角形总量守卫(Type 6/7 最小位宽流约 2400 倍内存放大,超限弃画告警);fill+stroke 双 mesh 底纹不再互相覆盖;
- 工具修复:
pdf2ofd-page-verify.py改用分带 SSIM(超大页不再整图 float64,O(width) 内存)、断点记录按文件内容寻址(--only不再误跳)、补"OFD 多出页面"检测方向;pdf2ofd-eval.pySSIM 同步真分带;管理台"最近访问记录"分页步长对齐(limit 20);vue-demo 文档打开统计改会话级 Set 去重(A→B→A 往返不再重复计数); - 新增回归测试 8 项(变长切分 4、lattice 宽行、mesh 守卫、clip 守卫、CMYK JPEG 像素断言,样本
tests/data/cmyk-ycck-sample.jpg入库);is_cff_without_cid判定结果按面缓存(损坏 charset 不再逐字形放大到分钟级)。
补记(2026-10-08,文档站自身改动,随本版本一并交付):「闭源构建与授权发布」「宝塔面板部署手册」两篇运维文档转为内部交付,不再对外发布——线上文档站不再包含这两页(侧边栏、搜索与 sitemap 同步移除),相关页内入口同步下线,完整内容随授权交付。首页「获取商用授权」按钮改指授权申请站 license.11m18.cn。
v0.5.1 — 2026-09-29
渲染管线两处标准符合性修复(用户报告:intro-数科.ofd 第 9 页渐变进度时间轴整组不可见,WPS 参照正常):
- Clip 内层 Path Boundary 锚定:国标
<Clips><Clip><Area><Path Boundary="…">形式下,裁剪路径数据为该 Boundary 的局部坐标,渲染时须先平移再参与后续变换。此前该属性被解析丢弃,数科 intro 第 9 页负坐标时间轴(对象 Boundary/CTM 左移一个页宽、靠整页矩形裁剪窗锚定)的裁剪窗被推出页外,进度条/圆点/箭头整组渐变对象被裁没; - 渐变轴坐标为 Boundary 局部 mm:AxialShd/RadialShd 的 StartPoint/EndPoint 遵循 OFD 子对象坐标惯例(同 TextCode X/Y),渲染时只平移到 Boundary 原点,不乘宿主 CTM。此前误乘 CTM 全量在正坐标模板上因 CTM.e≈Boundary.x 巧合未暴露;负坐标页渐变轴整体出页、进度条退化为平铺终止色。同文件第 8 页时间轴右半段此前实为平色,现恢复全程渐变;
- 附带:Clips 容器
TransFlag属性解析与 round-trip(此前整属性丢弃);CLI release 构建产物校准。全 workspace 321 项测试通过(含新增解析 round-trip 与渲染行为回归各 2 项),ofdrw 无渐变渲染能力、此类页面对拍不覆盖,语义依据国标坐标惯例与 WPS 实测裁定。
v0.5.0 — 2026-09-29
OFD→PDF 转换商业化完善(68 份真实语料入库评测驱动,逐项对比 ofdrw/Spire/ofdbox 等方案,详见 docs/business/ofd2pdf-商业化对比与达标线.md):
- 转换性能:修复字体去重键逐字形重复哈希整份字体字节的缺陷,2 页文档转换从 224 秒降至 0.1 秒;
- 水印/平铺图案:OFD 平铺图案(数科水印注释等)此前整体丢失,现以 PDF TilingPattern 矢量迁移(瓦片 288dpi 栅格 + 图案空间归一化,45° 旋转水印在 poppler/pdfium 下均正确);
- 文本层全覆盖:CFF/OTF 字体、描边文本、渐变文本此前轮廓化后不可检索,现一律叠加 PDF 隐形文本层(Tr 3 + ToUnicode,同扫描件 OCR-PDF 形态)——可检索、可复制、位置真实,视觉仍为矢量轮廓(视觉零回归)。数科 intro 手册(42 页)文本召回 0.898→0.9998;
- CMYK JPEG 防错色:4 组件 JPEG 原字节透传会被阅读器按 RGB 解码导致全黑(数科手册照片页实测),现探测 JPEG 组件数,仅 1/3 组件透传、CMYK 走解码像素重编码;
- 损坏包降级:
DocRoot目录形式(如Doc_0)可读;全零字节资源/页内容降级为空资源/空白页并记警告,页数保持 1:1,不再整体失败; - CLI:
render命令回退字体与转换命令同源(Windows/macOS/Linux 系统字体自动探测)并新增--fallback <字体文件>参数,无嵌入字体文档在非 Windows 环境不再渲染成空白页; - rotate 修复:旋转操作的图像 CTM 写出改用 Boundary 局部语义(与真实文件一致),修复旋转后图像丢失;
- 测试:新增真实语料回归与上述功能的单元测试,全 workspace 314 用例 100% 通过。
补记(2026-09-29,随本版本一并交付):合并后全面回归验证中的修复——CLI render 的 --out 指向已存在目录时,按 <文件名>_p<N>.png 编号写入该目录(修复:此前目录被当作输出文件路径,Windows 下报「拒绝访问」且报错不含路径;现与文档表述一致,附带 CLI 单元测试);输出路径穿越(..)防护与写失败报错带路径。授权服务本地联调启动器 dev-memory 中和 server/.env 中的真实 SMTP 配置——本地冒烟验证码一律开发模式返回,绝不真发邮件(真实 SMTP 连通性测试走 server/test-mailer.mjs);本地全链路冒烟 56 项断言全过。文档站硬编码数字同步 0.5.0(能力页/性能表/评测口径)。
v0.4.6 — 2026-09-29
PDF→OFD 转换质量专项(评测驱动,十一轮迭代):建立 1018 份公开语料(pdf.js、pypdf、pikepdf、chromium 等来源,覆盖中文正文/嵌入子集字体/扫描件/表单/注释/加密等矩阵)的自动化评测管线与商业化达标线(scripts/pdf2ofd-eval.py + docs/business/pdf2ofd-商业化达标线.md),围绕成功率、视觉还原(SSIM)、文本层保留三项硬指标迭代修复。全量口径下:转换成功率 95.0% → 97.9%、panic 保持 0;视觉还原达标(SSIM≥0.95)文档 494 → 517;文本层保留(相似度≥0.9)文档 356 → 432,丢文本层文档 29 → 30;平均分 52.02 → 56.14。主要能力升级:
- 文本层恢复与反查:嵌入字体 GID→Unicode 反查、BaseFont UTF-16 解码、GBK 全表/GB2312 双字节解码、CID 桩字体按 BaseFont 名反查系统字体(以 /W 宽度校验 ±12% 防错配,宁缺勿错)、ZapfDingbats 符号字体专项——此前转换结果"看着对但复制/检索不出来"的文档大幅减少;
- 值文本可检索化:表单域/注释的值文本由几何绘制升级为真实 TextCode(Visible=false 语义),输出 OFD 中表单已填值、注释文本可复制可检索;Type3 字体双输出(CharProc 轮廓保形状 + 不可见 TextCode 保检索)、旋转/非均匀缩放文本走轮廓退化时并行输出不可见文本层——文本层完全丢失的形态显著收敛;
- 图像保真:JBIG2 refinement 与 halftone(Pattern Dictionary + 灰度图 + 图案拼贴)区域解码、CalRGB/CalGray 线性分量 sRGB 编码、JPX 无法解码时输出占位图并记警告(降级而非静默丢内容);
- 损坏文件解析容错:Catalog/页树三层容错(悬空 /Pages、/Pages 直指 Page、短 xref 表)、截断对象容忍、截断 zlib/ObjStm 部分解压拯救(限修复路径,常规路径保持增量 xref 链干净语义)、内容流逐流容错;修复途中发现的 panic(红线指标)归零;
- 评测语料库
corpus/(1018 份,129MB)随仓库管理,来源与许可见corpus/README.md。
补记(2026-09-29,随本版本一并交付):授权服务 v2.3——管理端与申请端全面升级(examples/license-server,服务端配套组件,内核无变化):
- 管理端改用户名密码登录:首启自动创建管理员(
ADMIN_PASSWORD或随机打印一次),会话 token 仅存 SHA-256 摘要(12h),登录/改密/操作全留痕;原ADMIN_API_KEY降级为可选运维/脚本通道; - 授权记录全生命周期管理:新增编辑(站点/部署 ID/备注/到期日)、归档(过期/吊销记录移出主列表可还原)、回收站(软删除 → 还原/彻底删除,保留 90 天自动清理;生效中授权须先吊销方可删除);每步动作写
admin_audit操作审计; - 授权日志:新增
license_events事件流(创建/编辑/续费/吊销/回收站/在线离线签发与拒绝,按授权/事件/通道过滤),与 token 粒度的签发审计互补; - 申请提醒与到期预警:新申请即时站内通知(顶栏铃铛 + 待审角标);生效授权 7 天内到期与已过期每日扫描提醒(同一到期日只提醒一次);
- 申请端(客户端)邮箱验证码登录:图形验证码(一次性)→ 邮箱验证码(6 位/10 分钟/5 次尝试)→ 会话(7 天);发码限流:同邮箱 60s 冷却/每小时 5/每日 10、同 IP 每日 20;申请须登录提交(联系方式自动绑定邮箱),新增「我的申请」;老申请仍可凭编号/邮箱/手机号/域名免登录查询领取;
- 访问统计:vue-demo 访问打点(
POST /api/v1/stats/beacon,匿名)+ 客户端每次在线续期记录 + 申请端登录记录,管理台「访问统计」页提供按天趋势、今日访问、热门路径、活跃授权 Top 榜;vue-demo 构建配置VITE_OFD_STATS_URL/VITE_OFD_STATS_LIC_NO即启用打点; - 存量库升级执行
upgrade-v2.3.sql(可重复);门户发码需配置 SMTP(SMTP_*),联调可显式开EMAIL_DEV_MODE=yes;本地全链路冒烟 41 项断言全部通过(examples/license-server/smoke-v2.3.mjs)。
补记(2026-09-29,随本版本一并交付):授权服务 v2.4——申请选择授权模块 + 审核后一键构建分发包 + 双端界面重构(examples/license-server,服务端配套组件,内核无变化):
- 申请选择 WASM 授权模块:申请端提交时勾选预览核心/格式转换/文档工具(core/convert/tool,至少一项),审批时管理员可再调整;模块组合随授权记录落库并在构建链路透传,
scripts/build-dist.mjs新增--only参数支持按模块组合出包; - 审核通过直接构建分发包(仅本地实例):管理台对已批准申请一键构建——申请参数自动映射构建配置(trial→测试分发包 / online→正式在线包 / offline→离线激活包;模块→
--only;部署 ID→--did;在线授权自动现签 token 与续期地址;--env双覆盖杜绝混血包),构建任务实时日志、产物 zip 经/builds/<任务号>/下载,构建与领取写授权事件与操作审计;开关ENABLE_LOCAL_BUILD=yes(生产公网实例保持关闭,构建只在本地/内网实例执行); - 管理台与申请端界面全面重构:统一"公文纸墨印"设计语言(暖纸底、衬线标题、票券式编号条、印章状态章),管理台改左侧栏导航(签发/记录/账号分区)+ 大数字统计带;申请端为三步引导(图形验证码 → 邮箱验证码 → 填写申请)+ 授权模块三卡选择;
- 存量库升级执行
upgrade-v2.4.sql(可重复,为 licenses/applications 补 modules 列);本地全链路冒烟扩展至 52 项断言全部通过。
补记(2026-09-29,随本版本一并交付):文档站全面核验修订——以 packages/ofd/index.d.ts、运行时导出、vue-demo 实际用法与 CLI 源码为准逐页校对:API 参考补齐检索/文本布局/附件/注释/文档工具/OFD/A/签名生成等此前缺失的成员,修正 DocInfo 键名(snake_case)、pageSize 语义与内存释放(显式 free())说明;转换页补 OFD→PDF 方向并修正异步示例;Canvas 指令集修正为 23 种(补 createPattern);验签报告 chainStatus 取值表按实现重写;命令行文档修正密钥参数(hex 而非 PEM)并补 machine-id/subset-font 子命令;能力矩阵、crate 清单(12 个)、体积与测试数等过时数字统一。vue-demo 到期提示文案与内嵌 API 文档同步修正;C 头文件补 ofd_machine_id 声明。
同日 vue-demo 产品化改版(阅读器示例站,随本版本交付):主页重构为商业化落地页——三张功能卡直达核心能力(OFD 预览阅读 / PDF→OFD / OFD→PDF)+ 引擎指标条 + 页脚导航(授权入口在顶栏「授权」按钮与页脚「获取授权」,不设功能卡);「使用文档」从站内弹层改为浏览器新窗口打开线上文档站(缺省 https://ofd.11m18.cn/docs/——本地开发与独立部署的分发包没有 /docs/ 目录,相对路径会 404;自建文档站用 VITE_DOCS_URL 覆盖),站内 WASM 文档弹层移除;阅读器顶栏新增「关闭」按钮(释放文档回主页);获取授权弹窗的文档入口同步指向文档站。
同日 阅读器显示修正(vue-demo + npm 包播放器):打开文档的默认视图由"一律适高"改为按纸型智能选择——竖版公文/报告适宽阅读(宽度撑满、纵向滚动,此前 A4 被压到 435px 宽字小不可读),横版发票等宽纸整页可见且最大化(不再留大片空白);缩放百分比改为物理尺寸口径(相对纸面 96DPI),新增「100%」按钮按真实纸面大小核对发票/印章;可视区右下角新增纸型角标(如 240×160mm · 122%),不同纸型一眼可辨。npm 包 canvas-player.js 增加画布面积上限保护(Safari 单画布 16.7M 像素上限,高倍缩放 × 高 DPR 屏此前会静默渲染成空白页)。另修正侧栏功能 Tab 换行错位(六 Tab 一行放下);主页去功能重复(hero 区不放任何操作按钮,「打开 OFD」唯一入口在功能卡与顶栏,商用授权/使用文档入口收敛到页脚与顶栏);打开文档首帧即按最终缩放渲染(从页面尺寸直接预定初始视图档位,消除"先渲一版小的再放大"的二段闪变)。28 份样例 + PDF 转换产物 + 旋转/翻页全链路实测零空白零报错。
v0.4.5 — 2026-09-28
预览渲染两项标准符合性修复(来自 94 份公开语料与 ofdrw 参考实现的逐页对拍摸底,另见仓库外审计报告):
- 路径填充缺省语义修正:
PathObject只声明FillColor而未写Fill属性时,此前会按"有填充色就填"错误填充——电子发票表格网格、椭圆印章等仅靠描边成形的装饰路径被整块涂黑。现按 GB/T 33190 9.6.2 的缺省语义(Fill缺省即不填充,与 ofdrw、数科阅读器一致)修正:FillColor只是显式Fill="true"时的取色来源,不触发填充。预览渲染与 OFD→PDF 转换共用同一绘制路径,一并生效;回归样本examples/resources/issue37-fill-default.ofd(另一开源查看器的同类缺陷复现件)纳入测试; - 渐变分段位置可选化:
AxialShd/RadialShd的Segment Position是国标 8.3.4.2 的可选属性(缺省时首段取 0、末段取 1.0、中间段区间均分),此前按必填解析,遇到不带Position的文件(如 XilouReader 的渐变测试样例)直接整页报错拒绝渲染;现在按缺省规则补齐后正常渲出渐变。回归样本examples/resources/axialshd-no-position.ofd纳入测试。
v0.4.4 — 2026-09-28
OFD/A 修复的字体查找支持子集前缀回退:此前按声明名精确匹配,遇到 PDF/OFD 常见的子集字体名(如 BAAAAA+KaiTi、DAAAAA+KaiTi)时,系统里不可能存在同名字体,「读取系统字体重试」必然仍报缺字体,只能手工安装改名的特殊字体;现在查找字节来源时自动补剥前缀的基字体名(KaiTi)作为回退候选,装了普通楷体即可完成嵌入:
- WASM
ofdaRepair:候选名取FontName/FamilyName原名优先、剥XXXXXX+前缀的基名回退(内核库层新增font_candidate_names/strip_subset_prefix辅助函数,原生端调用方可直接复用);文档内的字体声明、检测报告与修复报告仍显示原名,不受影响; collectSystemFonts:按缺失字体名读取系统字体时同步支持前缀剥离——基名参与匹配,命中后该字体名的两个候选一并消除,missing不再误报;
v0.4.3 — 2026-09-24
OFD/A 归档合规产品化:阅读器「归档」页新增一键合规检测、自动修复另存与校验报告导出(GB/T 42133-2022),浏览器本地完成。此前 ofd-archive 仅是内核里的一个 Rust 库,无任何外部入口;本次补齐三项核心修复能力并接入 WASM 工具模块与网页端:
- 合规检测:九条规则逐项检查(DocType=OFD-A、单文档、未加密、无权限控制/视图首选项、图像格式白名单、字型全部嵌入、页块嵌套层数、无音视频、无非 Goto 动作),报告含每项通过状态与明细;未嵌入字型直接给出字体名清单,供提示安装;
- 自动修复:在去技术化(置 DocType、去加密/权限/音视频/脚本动作)之上,新增未嵌入字型的子集化嵌入(按用字文本子集化后写入包内并回填声明,CFF 等无法子集化的字体整包嵌入)、非白名单图像转码(GIF 等可解码格式自动转 PNG,包内缺失的悬空图像引用保留原状并记入报告);
- 字体来源双通道:原生端(CLI/FFI 场景)Rust 按名直读系统字体目录;浏览器端无文件系统,页面在缺字体时提供「读取系统字体重试」(Chromium Local Font Access,需用户授权),均不可得时明确提示"请先在系统安装字体 X"——不会静默用回退字体替代导致字形走样;
- 另存与报告:修复产物一键下载 OFD/A 文件;校验报告可下载 JSON(含逐项修复动作明细 + 修复前后两份复检结果),页内同步展示;
- 新增 WASM API:
ofdaCheck(ofd)与ofdaRepair(ofd, fonts?)(工具模块,随授权),配套collectSystemFonts(names)辅助函数与完整 TypeScript 类型。
已知边界:多文档(DocBody>1)仅处理首个文档(检测会提示 single-doc 不合规);浏览器端字体嵌入依赖用户授权读取系统字体,未授权时仅报告不嵌入。
同版本内的文本选择体验重构(阅读器拖选/复制/检索高亮共用同一文本层):
- 选区高低不齐修复:此前逐字符盒取"字体度量∪字形边界",假度量字体下汉字盒高、标点/西文盒矮,整行拖选时高亮带参差不齐、标点命中区只有小点;现在内核在出口处做行盒归一——同一视觉行的字符盒不分 run/字体统一为整行行带(按盒间垂直重叠聚类,对发票/扫描版式常见的 0.1~0.4mm 基线抖动不敏感),与浏览器行盒模型和 PDF.js textLayer 一致;
- 跨行拖选吞行尾修复:命中判定从"矩形∩字符墨迹盒"改为原生光标语义——锚点与光标各定位到(行, 字符边界)两个光标位,两位置之间按阅读序全选:中间行整行选中(拖到下一行时上一行行尾不会被截掉),只有首末行按 x 截取;自右向左/自下而上拖动自动互换首末;
- 零宽字符盒修复:同位堆叠字形(如发票左侧竖排标签"购买方"逐字同 x 排布)此前被切成 0 宽盒、完全无法选中;现在退用本字形 advance 兜底,横排/竖排分支同修;
- 窄盒字符修复(逐字定位排版):zsbk 等审计/证照类文档逐字独立定位(每字符一个 TextCode),字符盒宽回退到字体 advance,而子集字体 advance 常为假值(实测 0.08em),选中盒只有 1~2px 宽、与显示字形完全不符;现在行盒归一时做行内宽度补齐——同行字符盒至少延伸到下一字符起点(空隙归属前一字,与原生选区一致),行末字符取行内中位步进,
max保证不收缩已正确的盒; - 新增内核文本坐标探针校验口径:pageTextLayout 字符盒与渲染墨迹逐字符对拍(盒内非白墨迹覆盖 + 行带一致性 + 行内大间隙),发票样张 560/560 字符盒全部命中。
同版本内的 PDF→OFD 转换引擎专项修复(三批共 30+ 项,以 146 份标准测试语料对拍验证,同口径渲染对拍 OK 56 → 72):
- 图形与色彩:Type 4 PostScript 计算器函数完整支持(三角/条件/位运算,DeviceN/Separation 专色按 tintTransform 精确着色,图像色彩空间同样适用);平铺图案(Tiling Pattern)与底纹图案(shading pattern)转换落地,复用渲染端 Pattern 语义,支持周期归一、巨型瓦片退化;图像色键掩码(/Mask)生效;CCITT Group 3(K=0/1)传真图自研解码(此前仅 Group 4);
- 文本:Type3 字体(CharProc 内容流字形)矢量渲染;非嵌入字体按 /BaseEncoding(WinAnsi/MacRoman)恢复 0x80 以上码位(弯引号/破折号/重音字符此前丢失);
- 注释与表单:无外观流注释按几何近似绘制(Ink 手写/Line/高亮/下划线/方形/圆/Caret/附件图标/PolyLine/Polygon,含 /BS 线宽与虚线);表单域值文本渲染(/V + /DA 规格,AcroForm /DR 字体解析,复选框矢量勾);FreeText 正文渲染;
- 透明与软掩码:ExtGState /SMask(/Alpha 软掩码)经离屏栅格化与逐像素合成生效(亮度掩码与非隔离组暂按无掩码基线渲染);
- 已知边界:JPX/JPEG2000 图像暂不支持(转换时保留占位并告警);亮度型软掩码与非隔离混合组按基线渲染。
补记(2026-09-24,无内核行为变更,不升版本):项目许可变更——rust-ofd 由 MIT OR Apache-2.0 双许可改为专有商业许可(闭源)。根目录新增 LICENSE(专有软件许可协议)与 THIRD-PARTY-NOTICES.md(第三方组件声明,含 vendored pdf fork 的 MIT 声明与字体 OFL 义务),删除原双许可文本;Cargo / npm / Python 包清单同步改为专有标识;文档站页脚、指南「许可证」与授权手册的"开源构建"表述统一改为"无授权校验构建(仅限内部评估,不得对外分发)"。授权申请入口:https://license.11m18.cn。
v0.4.2 — 2026-09-24
网页阅读器(WASM 无系统字体环境)下的字型变换兼容修复——浏览器没有系统字体可扫描,文档只声明字体名(Times New Roman / Tahoma / Latha 等)而不嵌入字体时,此前会丢字、组合形态错误;现在 z.ofd 字型变换示例四页在网页端与数科阅读器观感一致:
- 连字缺字:多对一变换组(如 fi 连字)在字体缺失整组按字符回退绘制时,被吞字符此前与组首字符叠成一团墨("He affixed" 显示成 "aff xed");现在按前字形自然步进右移补画,偏移不写入笔位(文件增量以连字字形原点为起点,组后字符位置不受影响);
- 一对多组合形态:声明字体解析不到时变换组此前被整体跳过,泰文 ำ 的"记号+基座"两段字形被画成单个压窄的预组合字形且与前置字符分离;现在变换组布局语义(组首消耗转移、组内转移逐段消费、pitch 收紧豁免)在字体缺失时同样生效,回退按 Unicode 分解形逐段绘制(ำ→◌ํ 记号悬于 า 基座正上方),与数科阅读器形态一致;
- 一对一变换组回退对齐:编号组回退只画本字符(画整组会让组内每个字符把全组重叠画一遍,intro-数科 "2012" 即此回归;签名字符间距变化亦同步消除),且保持参与格宽收紧,与无变换组的按字符路径行为完全一致;
- 回退字体链(新 API
addFallbackFont):主回退字体之后的按序补位字体(主字体未覆盖的泰文 / 泰米尔等语种依序查找);浏览器环境无系统字体兜底,小语种字形靠链上字体补覆盖。阅读器示例(vue-demo)已内置 Noto Sans Thai / Noto Sans Tamil(OFL 许可,共约 540KB,独立缓存); - 阅读器示例 wasm 下载改为
cache: "reload"强制回源:内核重建后不再命中浏览器磁盘缓存里的旧版本(此前版本号会停在旧内核); - 桌面端(有系统字体解析)行为不变:z.ofd 第 2 页逐字节一致;全语料对拍 371 页渲染零差异(其余差异为并行任务重新生成的转换产物源文件变化,与本内核无关)。
v0.4.1 — 2026-09-23
字型变换(CGTransform,GB/T 33190 11.4)渲染修复——以字型变换测试文档 z.ofd 对齐数科裁定,四类变换关系(一对一 / 多对一 / 一对多 / 多对多)全部正确:
- 字形收紧判定的格宽索引错位:DeltaX 按可见字形序列给值(被吞字符不占项),按字符下标直接取数组会在第一个连字之后错位,把后续字符误判"放不下"压成半宽(连字行 "h"/"n"/"e" 被 0.55/0.78/0.63 压缩;y.ofd、阿拉伯文样本潜伏同类问题一并修复);
- 变换组改为整组判定:组内字形编号与解析字体全部同源才按编号绘制;不同源(非内嵌字体按名解析到的版本与制件不同)时整组按字符回退,杜绝"半组编号半组回退"的拼接错字(泰文 ำ 两段字形、泰米尔 போ 三段字形被画成乱字即此因);
- 一对多 / 多对多展开组:组内非首字符不再重复消耗增量(此前越界重复末值使组后字符偏移);整组回退少画的字形补吞等量增量,保持游标对齐;
- 包内嵌入字体的编号直接采信(不参与同源判定),修复 pdf2ofd 产物含 PUA/未知码位(
gid 1)时被误判回退、字形错变; - 回退路径补齐每字形实际字符标注(文本层/检索不再把组内第二字形标成组首字符)。
v0.4.0 — 2026-09-23
授权体系 v2.2(授权锚点迁移):
- 部署标识(Deployment ID)改为编译期烘焙进 WASM(供应商定制构建):授权对"部署"生效而非对"终端浏览器"生效,用户清缓存、换设备均不影响授权;部署即用,续费/换绑通过重新构建交付;
- 授权面板改为只读展示(移除终端粘贴激活码入口),新增部署标识与是否烘焙展示;
- 授权服务端配套放宽:offline / trial 授权 hosts 与 did 至少一项即可签发;
- 版本号 0.3.0 → 0.4.0(workspace / npm 包 / 文档四处同步)。
渲染引擎兼容性批量修复(对齐标准与主流实现裁定):
- Path 缺省描边语义:无
Stroke属性按标准缺省勾边(黑),修复模板类文档缺框子/缺下划线; - 图像 Clip 在对象 CTM 下按 Boundary 局部坐标解释,修复部分文档图像与印章背景不显示;
- 位图印章白底抠图(近白像素透明、过渡带渐隐),修复印章白底遮挡正文;
- Tiling Pattern 平铺填充支持(涂黑/水印类),Pattern 与纯色并存时 Pattern 优先,栅格化失败弃填不回退黑块;
- 数科模板文档文本:
\r\n占位 DeltaX、多对一字形的增量游标、CGTransform 嵌入门、系统字体按名解析 + 码位覆盖兜底(并子集化嵌入防体积膨胀); - 数科注释 Appearance Boundary 宽松解析 + 页块平移烘焙,修复签批/印章跑到页面原点;
- 支持 GIF 图像;文本层字符盒度量对子集字体假 hhea 做兜底,修复选区/检索定位偏移;
- 矢量印章 DrawParam 继承不再误触发默认填充,修复百望发票矢量印章整片红。
站点与交付:
- 文档站(
/docs/)与下载中心首次上线; - 三缺陷修复:多
<MultiMedias>容器丢图、检索对空白视图的匹配与偏移映射、隐藏文本层pageTextLayout(page, includeHidden); - 阅读器顶栏与授权面板显示内核版本号;本页(更新日志)上线。
v0.3.0 — 2026-09-22
- WASM 授权 v2:在线续期 + 离线 IP/CIDR 激活码、test/prod 双密钥、公钥掩码嵌入;
- 授权服务 license.11m18.cn 上线(Express + MySQL),含管理台
/admin与申请端/portal(申请号流程); - 完整功能授权分发包三形态(测试 30 天 / 正式在线 / 离线激活码)。
v0.2.0 — 2026-09-22
- 版本基建:新增
wasmVersion()查询接口,分发包与线上站可校验内核版本; - 分发包 0.2.0 三形态打包与
build-dist统一构建入口。
v0.1.x — 2026-09 上中旬
引擎全功能首发(早期迭代未逐版留档,列要点):
- 解析 / 渲染(PNG 位图 + Canvas 指令流)/ 文本提取与检索 / 验签(SM2、SES v1/v4 电子签章)/ 签名 / 加密(SM4-CBC + SM2 数字信封);
- OFD→PDF 矢量转换、PDF→OFD(文本双模式、页码范围)、合并 / 拆分 / 旋转 / 水印 / 注释增删 / 附件 / OFD 生成全家桶;
- WASM 拆三模块(core / convert / tool 按需加载)、vue-demo 产品化阅读器、C ABI / C# / Java / Python 绑定、ofd-cli 命令行;
- JBIG2(含符号字典与 MQ 算术解码)、OFD 字体子集化保真嵌入、73 份真实样例全功能回归。