Skip to content

更新日志

PDF Oxide 的所有重要变更都记录在此。


v0.3.38 – 2026-04-22

DocumentBuilder 登陆每个绑定;写入路径上的 AES-256;签名验证;多目标 WASM;Go purego 后端

所有绑定上的写入端 API 一致性 (#384)

  • DocumentBuilder + FluentPageBuilder + EmbeddedFont 现在与 Rust 一道在 Python、Node/TypeScript、C#、Go 和 WASM 中提供。通过嵌入字体进行多页构建,全面支持 CJK / 西里尔文 / 希腊文。跨语言关闭 #382。
  • 每个绑定上的 15 种注释方法link_url / link_page / link_namedhighlightunderlinestrikeoutsquiggly、便签、印章(14 种标准 + 自定义)、自由文本、watermark(自定义 / DRAFT / CONFIDENTIAL)。
  • 每个绑定上的 5 种 AcroForm 控件类型text_fieldcheckboxcombo_boxradio_grouppush_button
  • 每个绑定上的图形基元rectfilled_rectline
  • HTML+CSS 管线 — 在每个绑定中通过 Pdf.from_html_css(...)from_html_css_with_fonts(...) 支持多字体级联。

写入路径上的 AES-256 加密 (#386)

  • 每个绑定的 DocumentBuilder 上的 save_encrypted(path, user_pw, owner_pw) / to_bytes_encrypted(user_pw, owner_pw)
  • Rust 中用于自定义算法 + 权限的 save_with_encryption

真正的字体子集化 (#385 / FONT-3b)

  • CJK 字型现在以子集而非完整字型嵌入。由约 17 MB 的 CJK 字体构建的 5 字符 PDF 通常小于 100 KB。内容流、/W 宽度和 ToUnicode CMap 都被重新映射到子集 GID 空间;extract_text 往返保持不变。
  • 内部写入器 API 变更:EmbeddedFont::encode_string / encode_shaped_run 返回 Vec<u16>build_embedded_font_objects 返回一个供调用方传给 ContentStreamBuilder::build_with_remappersGlyphRemapper。高层 API 没有变化。

数字签名验证 (#208,验证部分)

  • 每个绑定中的 Signature.verify()Signature.verify_detached(pdf_bytes)(以及各绑定的原生等价物)。RFC 5652 §5.4 签名者属性 + §11.2 messageDigest 检查。
  • 基于 SHA-1 / SHA-256 / SHA-384 / SHA-512 的 RSA-PKCS#1 v1.5 返回 Valid / InvalidRSA-PSSECDSA 表现为 Unknown / UnsupportedFeatureException;调用方仍可读取证书并运行自己的检查。
  • Certificate — 通过 x509-parser 进行 DER 检查(subject、issuer、序列号、有效期、is_valid)— 每个绑定
  • Signature — 枚举 + 检查 + .get_certificate()每个绑定
  • Timestamp — RFC 3161 TSTInfo 解析(时间、序列号、策略、TSA 名称、哈希算法、消息印记)— 每个绑定
  • TsaClient — 在 tsa-client Cargo 特性后面,带 nonce 和 HTTP Basic 认证的 RFC 3161 HTTP POST — 除 WASM 外的每个绑定。有意未在 WASM 上接通(ureq 与 wasm 不兼容)。
  • DocumentEditor::set_producer / set_creation_date 元数据写入器。
  • render_page_regionrender_page_fit — 裁剪和适配的渲染表面。
  • 双三次图像滤波(与 pdf.js #19978 一致)— 带 Multiply 混合叠加的扫描 / 二值页面在缩小时不再压扁其灰度范围。

签名本身(与验证相对)不在此次覆盖范围内;该部分仍由 #208 保持开放。

多目标 WASM 打包 (#392)

  • pdf-oxide-wasm 现在通过 package.json 的条件导出并排提供三种构建:nodejs/bundler/(Vite / webpack / Rollup / esbuild / Bun)和 web/(浏览器 / Deno / Cloudflare Workers)。
  • 修复了在浏览器打包器下抛出的 ReferenceError: Can't find variable: __dirname
  • 提供子路径导入(pdf-oxide-wasm/web/nodejs/bundler)以便手动路由。

Go 绑定 — purego 后端 + 缓存目录安装

  • 通过 ebitengine/purego 实现的第二个后端在运行时 dlopen libpdf_oxide.{so,dylib,dll}CGO_ENABLED=0 构建现在可以工作了。 后端选择是自动的 — //go:build cgo → 完整 CGo API,//go:build !cgo → purego。
  • Purego 覆盖面: PdfDocument 打开(路径 / 字节 / 密码)、页数、版本、文本 / Markdown / HTML / 纯文本提取、字体、注释、页面元素、搜索、页面尺寸、日志,以及用于测试固件的 PdfCreator.FromMarkdown
  • 仅 CGo(在 !cgo 下为编译时错误): DocumentEditorDocumentBuilder、条形码、签名、TSA、渲染、OCR、表单变更。
  • 安装程序:新的 -shared 标志获取 cdylib 而非 staticlib,并打印需导出的 CGO_ENABLED=0 + PDF_OXIDE_LIB_PATH=…
  • 安装目录已移至 os.UserCacheDir()~/.cache/pdf_oxide(Linux)、~/Library/Caches/pdf_oxide(macOS)、%LocalAppData%\pdf_oxide(Windows)。与 Go 自身的 GOCACHE 惯例一致。
  • 发布资产现在为每个 Tier-1 平台包含 pdf_oxide-go-ffi-shared-<platform>.tar.gz,与现有的 staticlib 归档并存。

缺陷修复

  • #395 – 当页面包含无法解析的签名字段元数据但没有交互式签名控件时,RenderPage 不再抛出 SignatureException。由 @gevorgter 报告。

致谢

  • @sparkyandrew – #382(通过 DocumentBuilder 的 CJK)、#385(子集化器)。
  • @arthurlassagne – #392(浏览器构建中断)。
  • @gevorgter – #395(RenderPage 签名异常)。

v0.3.37 – 2026-04-20

HTML + CSS → PDF (#248) — 首条可信的纯 Rust 管线

新 API — Pdf::from_html_css

let font = std::fs::read("DejaVuSans.ttf")?;
let pdf = Pdf::from_html_css(
    "<h1>Hello</h1><p>World</p>",
    "h1 { color: blue; font-size: 24pt }",
    font,
)?;
pdf.save("out.pdf")?;

传入 HTML + CSS + 字体字节,得到一份分页的 PDF。纯 Rust,仅 MIT/Apache(无 MPL 传递依赖),extract_text 往返逐字节相等,因此生成的 PDF 可参与现有的测试基础设施。

此次交付的内容

  • 字体子系统 — 带 Type 0 / CIDFontType2 / Identity-H / ToUnicode 发射的 TTF/OTF 嵌入;拉丁文、西里尔文、希腊文、希伯来文、阿拉伯文通过 extract_text 往返。通过 fontdb 发现系统字体,通过 rustybuzz 进行文本整形。
  • 手写 CSS 引擎(约 6,500 行代码,零 MPL 依赖)-- 词法分析器、解析器、L3+L4 选择器(:is/:where/:not/:has)、匹配器、级联、calc() / min() / max() / clamp()、带循环检测的 var()、带类型的属性值、at 规则(@media print、带 :first/:left/:right/:blank@page@font-face@import@supports)、计数器、伪元素内容。
  • HTML – HTML5 词法分析器、扁平 arena DOM、样式表提取(<style><link rel="stylesheet">、内联 style="")、资源提取(<img> + srcset、<picture>/<source><a href>)。
  • 布局 – 基于 Taffy 的 block / flex / grid、UAX #14 断行、外边距折叠、多列、表格(auto + fixed)。
  • 绘制 – 文本 + 边框、通过 rustybuzz 的 RTL、<a href>/Link 注释、<img> data-URI → /XObject::before / ::afterpage-break-{before,after}: alwaysopacitytransform: translate*()<ul> / <ol> 列表标记、通过 DocumentBuilder::register_embedded_font 的嵌入字体 (#382)。

多字体级联

  • Pdf::from_html_css_with_fonts(html, css, Vec<(family, bytes)>) — 任意元素上的 CSS font-family 都会针对已注册的字体族解析(不区分大小写,带/不带引号,未加引号的多词)。

边角情况修复

  • Base-14 粗体文本现在渲染为粗体(针对 Tf /Helvetica-Bold 的资源字典键不匹配)。
  • TTC 系统字体(Helvetica.ttc、msgothic.ttc)现在通过 fontdbSource::SharedFile 解析。
  • 未加引号的多词 font-family 现在正确词法化。
  • 关闭了 Pdf::from_html_css 工厂中的内存泄漏(四处 Box::leak 被替换为作用域内的局部变量)。
  • PNG alpha / 软蒙版(SMask)现在可以渲染。
  • 整形后的文本通过 extract_text 往返(encode_shaped_run 将字形簇映射回源码点)。
  • PdfWriter::finish 现在按注册顺序嵌入字体(此前为 HashMap 随机顺序)。
  • 嵌入字体名称冲突通过单调递增的 EFn 资源名隔离。
  • fontdb 的 Mutex 不再在字体字节的 fs::read 期间被持有。

不在范围内

CSS 滤镜、3D 变换、动画、HTML 中的 SVG(每个可用的 Rust SVG crate 都是 MPL)、MathML、hyphens: autoshape-outside、JavaScript、全矩阵 transform(scale/rotate)、渐变、box-shadow

许可证审计

cargo deny check licenses MPL 传递依赖通过。Mozilla 的 CSS 技术栈(cssparserselectorshtml5everlightningcssstylo)全部为 MPL-2.0;v0.3.37 手写了等价实现,以使 pdf_oxide 完全处于 MIT/Apache 之下。

致谢

  • @jmriebold – #248(“CSS 支持”)是本次发布整个 HTML+CSS→PDF 管线的根源。

v0.3.36 – 2026-04-19

Markdown 结构提取 — 标记式 PDF 的标题/列表发射、多列阅读顺序、更安全的 RTL 处理

Markdown 结构提取 (#377)

to_markdown() 现在将 /StructTreeRoot 直接接入 Markdown 管线,而不再从字号启发式重新推导标题级别、从字形检测重新推导列表标记:

  • /StructTreeRoot 发射标题和列表。 附加到每个 span 的新 StructRoleHeading(1..6)ListItemListItemLabelListItemBody)。Word 标记的文档恢复其完整的标题层级;列表在每次角色转换处带段落断点发射 - item
  • 角色在嵌套 MCR 中传播。 H1 → Span → MCRLI → LBody → Span → MCR 模式现在通过 InheritedContext { heading_level, list_role } 携带正确的语义角色。
  • 每个 /StructTreeRoot 块边界强制段落断点。 OrderedContent.block_id 在每次进入 /P/H1..6/LI/Lbl/LBody/Sect/Div/Art/TR/TH/TD/Note/Reference/BibEntry/Code 时递增;紧凑间距的布局不再合并。
  • 针对表单标题过度碎片化的同基线门控 — 同基线的 span 重新合并为一个标题。
  • 多列栏间空隙检测 — 由 > max(3 × font_size, 30 pt) 分隔的同基线 span 被视为跨列。
  • 逆向 x 阅读顺序换行检测 — 列优先阅读顺序(第 1 列最后一个 span 在 x=976 → 第 2 列第一个 span 在同基线 x=192)现在断开段落而非连接。
  • 针对未标记文档的几何标题 + 列表前缀检测。 粗体 + 5 % 的字号增幅提升为 H4。新的 is_ordered_list_marker 识别 1. / 12. / a) / iv. / A.,同时拒绝图注和年份。

RTL 文本 — 默认安全

  • 阿拉伯文上下文字形周围多余的 **bold** 标记现在被剥除(整形转换曾使字重检测器误判)。
  • Bidi 重排序默认关闭。 早先的草稿曾对每一行 RTL 文本运行 unicode-bidi 的视觉→逻辑重排序,这破坏了此前正确的逻辑顺序 PDF(希伯来文名字 בנימין 被反转了)。重排序辅助函数仍保留在 text::bidi::reorder_visual_to_logical,供输入为视觉顺序的调用方使用。

Markdown 输出

  • 内联图像的 base64 data URI 上限为 200 KB。 含高分辨率图表的 PDF 此前会将 Markdown 输出膨胀 10–20 倍(一份 1.9 MB 的论文产生了 11.3 MB 的 Markdown)。超出上限的图像发射一个带原始大小的 HTML 注释占位符。基于文件的图像输出(image_output_dir)不受影响。

实证影响

针对横跨学术、政府、表单、报纸、技术、学位论文、IRS、pdfium、pdfjs、safedocs 和慢速语料子集的 369 个 PDF 回归集,相对 v0.3.35 进行了验证:

  • 0 个灾难性回归。
  • 相对 pdfium 和 pdftotext 的 Token Jaccard:中位数 1.000,在 106 个固件中有 95 个 ≥0.95。
  • 相对 pymupdf4llm 的 Token Jaccard:中位数 0.978,在 106 个固件中有 65 个 ≥0.95。
  • 在整个语料中发射的标题约为 pymupdf4llm 的 2 倍。

致谢

  • @Goldziherkreuzberg)-- 提交了 #377,附带一套 727 文档的基准方法论以及 9 个复现用 PDF。其框定(“TF1 在 ±3 % 以内,所以文本内容没问题,问题在结构”)让整个调查变得可处理。

v0.3.35 – 2026-04-19

文本提取中窄字形二连体的保留

文本提取正确性

  • 小字号下相邻的窄字形二连体不再被压扁 (#378,PR #379)。 TextExtractor::deduplicate_overlapping_charsdeduplicate_overlapping_spans 曾使用硬编码的 2 pt 绝对阈值;对于紧凑字体小字号下的窄字形(lrIi),每字形的步进宽度降至 ≤ 2 pt(Helvetica 的 l 在 9 pt 时约 2.5 pt),因此相隔整整一个步进的合法相邻二连体落入了去重窗口内,两个字形中的一个被悄无声息地丢弃。可见的损坏包括 controller → controlerbilled → biledwarranty → warrntyfollowing → folowingVIII → VII。阈值现在随每个字形自身的 advance_width 缩放,为 min(advance_width * 0.30, 2.0)。可调参数提升至 TextExtractor::DEDUP_OVERLAP_RATIO / DEDUP_OVERLAP_CAP_PT 关联常量。

致谢

  • @Hugues-DTANKOUO – 以精确的根因分析报告了 #378,并撰写了 PR #379,其中带有按步进缩放的阈值和一套参数化的回归矩阵(4 个窄字形 × 3 种正文字号)。

v0.3.34 – 2026-04-17

所有绑定上惯用的页面 API;结构化表格提取

新特性

  • 页面 API (#371) – Python、Node.js、C# 和 Go 现在都暴露一个 PdfPage 对象。用 for page in docfor (const p of doc)foreach (var p in doc.Pages)doc.Pages() 迭代;用 doc[i]doc.page(i)doc[i]doc.Page(i) 索引。每个页面都暴露惰性的 textmarkdown()html()wordslinestablesimagespathsannotationssearch() 等。
  • 结构化表格提取 (#289)extract_tables()(Python)、ExtractTables()(C#/Go)和 extractTables()(Node.js)现在返回带文本及边界框的行和单元格,而不仅仅是 Markdown。在 PdfDocument 和新的 PdfPage 上均可用。
  • Node.js 一致性extractWordsextractTextLinesextractTablesextractPathsgetEmbeddedImagesocrExtractText 接入了 TypeScript 层(此前仅原生)。
  • ExtractedTableTable – Rust 核心重命名;去掉了冗余的 Extracted 前缀。面向 FFI 的类型已更新。

文本提取质量

  • 混合布局页面上的 XY-cut 列检测 (#319)is_multi_column_page 守卫收紧为每列至少需要 15 个 span;按列排序的 span 不再被 extract_text 中的行感知排序重新排序。

致谢

  • 感谢 @SeanPedersen 提出页面优先 API (#371)。感谢 @pdenapo 请求结构化表格提取 (#289)。

v0.3.33 – 2026-04-16

文本提取、图像正确性和内存安全修复

缺陷修复

  • ToUnicode CMap 缺失 (#363) – 当 ToUnicode CMap 中缺少某 CID 时,子集 Type0 字体现在发射 U+FFFD,而不是落到 Identity-H 密文(例如 %B+$%8A//$2*%01*1%6APP)。
  • 词内 TJ 字距不再拆分单词 (#365) – 单个单词内 0.10–0.20 em 的字符对字距([(diffe) -150 (rent)])不再触发空格插入。
  • 西里尔文 UTF-8 乱码已恢复 (#317) – 带仅拉丁文编码和原始 UTF-8 字节序列的字体现在能正确解码。
  • FlateDecode 部分恢复拒绝垃圾输出 (#364) – 内容流在解压中途失败的 MS Reporting Services PDF 不再返回 128 字节的伪随机数据。
  • Indexed + ICCBased 调色板 (#373) – Indexed 基础数组内未解析的 ICC 流引用不再将 /N 默认为 3 而非 CMYK 的 4,修复了对角条纹伪影。由 @Charltsing 报告。
  • 基于 Lab 的 Indexed 调色板 → sRGB (#337) – CIE L*a*b* 调色板字节现在转换为 Lab→XYZ→sRGB,而不再被重新解释为原始 RGB。

内存与性能

  • 所有内部缓存均有界 (PR #369、#354) – 对象缓存(64 MB)、字体缓存(256–512 项)、XObject span/图像缓存(1024 项)和全局 CMap 缓存(1024 项)现在使用 FIFO 淘汰。
  • 修复图表密集 PDF 上路径提取的 OOM (#369) – 添加了 CTM 感知的 XObject 去重,因此同一位置的同一 XObject 被去重,而不同位置的同一 XObject 单独处理。
  • Mutex 中毒韧性MutexExt::lock_or_recover() 替换了 72 处 .lock().unwrap() 调用点。

依赖项

  • RustCrypto cipher 0.5 生态(PR #352、#295、#291):aes 0.8→0.9、cbc 0.1→0.2、sha2/sha1/md-5 0.10→0.11。

测试套件

  • 移除了 13 个失效/陈旧的被忽略测试;修复了 3 个此前被忽略的测试。为上述每个缺陷修复添加了回归测试。套件现为 6,300 通过、0 失败、228 忽略。

致谢

  • 感谢 @Charltsing 报告 Indexed + CMYK 图像提取缺陷 (#373)。
  • 感谢 @ddxtanx 剖析多页提取期间的无界内存增长 (#354)。
  • 感谢 @andrewjradcliffe 贡献 PR #369:有界 FIFO 缓存、CTM 感知的 XObject 去重、MutexExt 中毒恢复 trait、Python 绑定加固。

v0.3.32 – 2026-04-15

针对 Windows-x64 Go FFI tarball 的发布管线修复

发布管线

  • 修复使 v0.3.31 发布失败的 x86_64-pc-windows-gnu 原生库构建scripts/shrink-staticlib.sh 曾对每个归档成员运行 objcopy --strip-debug,但 MinGW 交叉编译工具链会发射含 DWARF 段的分离调试 .dwo 成员;剥离后该成员没有任何段剩余,objcopy 中止了整个归档。修复:在调用 objcopy 之前用 ar d 删除 .dwo 归档成员。对 Rust、Python、Node、WASM 或 C# 制品没有功能性变更 – 本次发布仅为解锁 Windows-x64 的 Go 安装路径而存在。

v0.3.31 – 2026-04-13

缺陷修复、Go 构建变更、发布基础设施改进

缺陷修复

  • Xref 恢复 – 修复了对被误标记的空闲页面对象以及偏差几字节的 xref 偏移项的恢复。

破坏性变更

  • Go 原生库 – 原生库不再提交到 go/lib/。使用者必须在每台机器上运行一次 go run github.com/yfedoseev/pdf_oxide/go/cmd/install@latest

发布基础设施

  • 将 Rust staticlib 缩小 63%(71 MB 至 26 MB)、剥离 npm .node 插件、从 npm 去除 sourcemap、修复 crate sdist 泄漏、收紧 NuGet snupkg 打包。

v0.3.27 – 2026-04-12

Go staticlib、Node.js 原生绑定、C# NativeAOT、OCR FFI、重大缺陷修复

新特性

  • Go staticlib 迁移 – 从 cdylib 切换到 staticlib,以获得自包含的 Go 二进制文件。
  • Node.js 原生绑定 – 通过 napi-rs 风格分发的预构建平台子包。
  • C# LibraryImport – 为 NativeAOT 兼容性,将 881 个 P/Invoke 声明从 DllImport 迁移到 LibraryImport。
  • OCR FFI 桥接 – OCR 支持现在在 Go、C# 和 Node.js 绑定中可用。
  • 回归测试框架 – 用于自动化质量测试的 60-PDF 精选语料。

缺陷修复

  • Indexed 色彩空间图像、AES-256(V=5、R=6)加密、单列和表格内容的阅读顺序、阿拉伯文文本提取、单词分隔、字体宽度回退、对象缓存失效、渲染改进。

v0.3.24 – 2026-04-09

面向 JavaScript/TypeScript、Go 和 C# 的官方绑定

新特性

  • JavaScript/TypeScript 绑定 – 在 npm 上发布,具备完整 API 覆盖。
  • Go 绑定 – 具备完整 API 面的原生 Go 包。
  • C# 绑定 – 在 NuGet 上发布的 .NET 包。
  • C FFI 层 – 270+ 个 extern "C" 函数,带共享的 pdf_oxide.h 头文件。
  • 全局日志级别控制 – 可在所有绑定中配置。

v0.3.23 – 2026-04-09

关键稳定性修复

缺陷修复

  • 修复了带有旋转 dvips PDF 退化 CTM 的页面上的 SIGABRT。
  • 修复了保存时图像/XObject 被剥离的问题。
  • 修复了在缺少常见字体的系统上的乱码渲染。
  • 修复了表单字段页面索引始终返回 0 的问题。

v0.3.22 – 2026-04-08

线程安全文档、异步 Python、自由线程 Python、单词/行分割调优

新特性

  • 线程安全的 PdfDocument – 通过 Mutex 实现 Send + Sync(替换 RefCell)。
  • 异步 Python APIAsyncPdfDocumentAsyncPdfAsyncOfficeConverter
  • 自由线程 Python – 支持 cp314t(无 GIL 构建)。
  • 分割阈值 – 用于调优单词/行检测的 word_gap_thresholdline_gap_thresholdprofile

缺陷修复

  • CLI 拆分/合并空白页、对格式错误图像的渲染跳过、结构树循环 SIGSEGV、表格策略门控。

性能

  • 缓存结构树和解压后的内容流、O(1) MCID 查找、O(log n) 页面树遍历、惰性页面树填充。

v0.3.21 – 2026-04-04

多架构 Python wheel、日志级别修复

缺陷修复

  • 日志级别现在在 Python 中得到完全尊重(宏被转发到 log crate)。

新特性

  • 多架构 Python wheel – Linux aarch64、musl x86_64/aarch64、Windows ARM64;将 glibc 要求降至 2_28。

v0.3.20 – 2026-04-04

重大的表格提取重写、文本质量改进、默认静默日志

新特性

  • 表格提取引擎重写 – 交叉管线、文本边缘检测、扩展网格、列感知文本检测、点线/虚线重构、混合行检测。
  • 文本提取质量 – 相邻值间距、拆分小数合并、粗体 span 合并、HTML 标题层级、标签-值配对、列分组合并。
  • 静默日志 – 日志现在在所有绑定中默认静默;Python 日志通过 pyo3-log 流入 logging 模块。

缺陷修复

  • 加密 PDF 的明确错误消息、ObjStm/XRef 流解密、流解析器尾随换行处理。

v0.3.19 – 2026-04-02

单次调用页面提取、列感知阅读顺序、逐字符边界框

新特性

  • extract_page_text() – 用于精简页面提取的单次调用 DTO。
  • 列感知阅读顺序 – 用于多列文档的 XY-Cut 空间分区。
  • 逐字符边界框 – 由字体度量推导,用于精确的字符定位。
  • is_monospace 标志 – 在 TextSpanTextChar 上可用。
  • Pdf::from_bytes() – 跨所有绑定的新构造函数。
  • 路径操作 – Python 绑定中的 extract_paths()

缺陷修复

  • 多字节调试日志上的 UTF-8 panic、Markdown 间距、Form XObject /Matrix、旋转文本矩阵、预扫描 CTM 丢失、去重、Tm 缩放文本丢失、Markdown 单词合并、CLI 合并空白文档。

破坏性变更

  • WASM – JSON 字段名现在使用 camelCase。

v0.3.18 – 2026-04-01

渲染引擎大修、新的 Python 和 WASM API、开箱即用的 Python

新特性

  • 渲染引擎大修 – 正确的字符间距、嵌入字体支持、标准字体度量、填充与描边、裁剪路径、渐变着色、alpha 透明度、模板图像蒙版、页面旋转、分色色彩空间。
  • 新的 Python APIvalidate_pdf_avalidate_pdf_uavalidate_pdf_xextract_pagesdelete_pagemove_pageflatten_to_images、密码构造函数、merge
  • 新的 WASM APIvalidatePdfAdeletePageextractPagessave、密码构造函数、merge
  • 开箱即用的 Python – 渲染、并行、签名和 Office 转换默认启用。

缺陷修复

  • 退化 CTM 中止、FlateDecode 压缩炸弹保护(256 MB 上限)、裁剪栈同步。

v0.3.17 – 2026-03-08

表格检测细化、标记式 PDF 优化

改进

  • 细化的表格检测 – 要求 2+ 列,减少误报。
  • 优化的标记式 PDF 提取管线。

缺陷修复

  • 修复了递归 Form XObject 处理上的 RefCell already borrowed panic。

v0.3.16 – 2026-03-08

智能混合表格提取、Python 类型存根、pathlib 支持

新特性

  • 智能混合表格提取 – 并查集聚类、可视线分析、可视 span/表头。
  • 专业 ASCII 表格 – 用于终端输出的多行换行。
  • Python 类型存根 – 通过 mypy stubgen 自动生成。
  • Python PdfDocument – 接受 pathlib.Path 并支持上下文管理器。

缺陷修复

  • 嵌套 Form XObject 中的段错误、Python 坐标缩放、ASCII 表格 UTF-8 panic。

v0.3.15 – 2026-03-06

页眉/页脚管理、页面模板、范围化提取

新特性

  • 页眉/页脚管理 API – 添加、移除和编辑 PDF 制品(artifact)。
  • 页面模板 – 用于页码、日期等的动态占位符。
  • 范围化提取 – 尊重 erase_regions 以获得过滤后的输出。
  • PdfDocument.from_bytes() – 新的 Python 构造函数。

缺陷修复

  • 多列阅读顺序(XY-Cut)、字体标识冲突、Lines 表格策略误报。

v0.3.14 – 2026-03-03

高层渲染、单词/行提取、几何基元、混合表格

新特性

  • 高层渲染 API – Rust、Python 和 WASM 中的 Pdf::render_page
  • 单词和行提取 – 跨所有绑定的 extract_wordsextract_text_lines
  • 几何基元提取extract_rectsextract_lines
  • 混合表格检测 – 矢量线提示改善表格边界检测。
  • API 协调 – 流畅的 .within(page, rect) 模式。
  • CLI 命令 – 带 --area 过滤的 renderpaths 命令。

缺陷修复

  • OCR 特性门控发现、XObject span 缓存污染、V=4 加密滤镜、加密的 CIDToGIDMap。

v0.3.13 – 2026-03-02

CJK 文本提取修复

缺陷修复

  • CJK/Type0 字体在 extract_chars 中的多字节解码、改进的字符定位精度、字符间距缩放。

v0.3.12 – 2026-03-01

文本提取质量、Markdown 转换、性能

改进

  • 文本提取质量 – CID 字体宽度计算、字体变化处的单词边界检测、非标准 CID 映射回退、RTL 文本方向性。
  • Markdown 转换 – XY-Cut 递归空间分区、标题检测、列表重构。

性能

  • 零拷贝页面树遍历、结构树缓存、BT 操作符提前退出、更大的 I/O 缓冲区、移除 xref 重建阈值。

v0.3.10 – 2026-02-26

并行提取、WASM/JavaScript 支持、批处理、文本质量改进

新特性

  • WASM/JavaScript 支持 – 通过 wasm-bindgen 的 WebAssembly 绑定。完整的文本提取、PDF 创建、编辑、表单字段和搜索可在浏览器和 Node.js 中使用。以 pdf-oxide-wasm 在 npm 上发布。

  • 并行页面提取 – 新的 parallel 特性标志,带基于 rayon 的多线程提取。ParallelExtractor 将页面分发到工作线程。全局字体缓存确保字体仅解析一次。

  • 批处理 API – 新的 BatchProcessor,用于带进度回调和错误收集的多 PDF 工作流。支持顺序和并行处理。

  • OCR 混合检测 – 新的 PageType 枚举(NativeTextScannedPageHybridPage),带多启发式检测,用于智能 OCR 回退。

  • 完整的 WASM/Python API 一致性 – 跨 WASM 和 Python 绑定的 10 个新方法组:表单字段 get/set、图像字节提取、由图像生成 PDF、表单扁平化、PDF 合并、文件嵌入、页面标签、XMP 元数据。

缺陷修复

  • 循环 XObject 段错误 – 修复了图像提取期间循环 Form XObject 引用导致的段错误
  • XRef /Prev 链溢出 – 将 XRef /Prev 链解析从递归重写为带循环检测的迭代
  • 断裂的连字文本repair_ligatures() 后处理器修复来自 LaTeX PDF 的损坏文本
  • 文本提取质量 – 注释文本提取、引导点规范化、Priority 3 CMap 支持
  • 表格提取 – 合并单元格、多行单元格内容、基于字体的表头检测
  • 表单字段持久化 – 增量保存现在正确持久化表单字段值的变更

性能

  • 仅图像页面跳过page_cannot_have_text() 预检查跳过对无字体页面的解压
  • SmallVec 操作符操作数 – 栈分配的操作数消除了逐操作符的堆分配
  • 跨文档字体缓存 – 在所有 PdfDocument 实例间共享的进程级 LRU 字体缓存

v0.3.9 – 2026-02-24

20+ 项微优化 – 文本提取速度提升 40%

性能

  • O(n^2) 字符串拼接修复 – 预分配的 Vec<&str> 在末尾连接,替换了二次方的 String::push_str() 累加
  • 仅图像的内容流解析器extract_images() 的新快速路径,跳过文本和图形操作符(快 3-5 倍)
  • 基于指纹的字体缓存 – 通过对 encoding+widths+flags 哈希来标识字体,而非完整结构体比较
  • 流式解析器 – 内容流操作符以流式处理,而非收集到 Vec
  • 针对 BT/ET 的快速内联解析器 – 对常见文本操作符进行直接字节匹配
  • 字节到字符查找表 – 256 项查找表替换热路径中的 HashMap
  • 宽度查找表 – 固定大小数组替换字形宽度的 HashMap
  • 缩小 Operator 枚举 – 通过装箱大变体从 112 字节降至 40 字节(缩小 64%)
  • zlib-rs 后端 – 通过 zlib-ng 移植使流解压快 15-25%

缺陷修复

  • 带嵌入程序的字体编码 – 按 PDF 规范正确解析基础编码
  • 辅助 Unicode(U+10000+) – 修复了辅助码点的截断
  • StandardEncoding 连字映射 – 通过 Adobe Glyph List 正确映射 fi、fl、ff、ffi、ffl
  • 康熙部首规范化 – 完整的 U+2F00-U+2FD5 映射表
  • RTL 文本字符顺序 – 阿拉伯文/希伯来文以逻辑阅读顺序提取
  • 多列文本分离 – 通过间隙分析改进列检测

特性

  • extract_all_text() – 用于全页文本提取的新便捷方法
  • StructElem 的 source_role – 在角色映射前保留原始 PDF 角色名

v0.3.8 – 2026-02-20

仅文本解析器 – 图形密集页面快 10-30 倍

性能

  • 仅文本内容流解析器 – 新的 parse_content_stream_text_only() 快速路径,使用字节级扫描而非完整 nom 解析,跳过 BT/ET 块外的图形操作符
  • 字节级图形扫描器 – 原始索引运算替换基于 nom 的操作数循环,以接近 memcpy 的速度处理
  • 跳过颜色操作符 – 将 12 个颜色操作符加入字节级跳过列表
  • 延迟 q/cm/Q 发射 – 在确认有文本之前延迟图形状态操作,消除约 75% 的回溯开销
  • Arc 包裹的 FontInfo 缓存 – 避免在缓存命中时克隆完整的 FontInfo 结构体
  • O(n) 页面映射构建 – 单遍遍历替换递归下降
  • XObject 名到引用缓存 – 消除 XObject 密集页面上 O(n^2) 的字典克隆

v0.3.7 – 2026-02-19

文本提取质量:洁净率从 95.7% 提升至 99.6%

已验证 – 3,829-PDF 语料

指标 v0.3.6 v0.3.7 变化
洁净率 95.7% 99.6% 3,829 个 PDF 中的 3,812 个
脏 PDF 165 17 -90%

新增 – 解析器与解码器

  • BrotliDecode 流滤镜(PDF 2.0)-- 用于 Brotli 压缩流的新解码器
  • Xref trailer 选择 – 存在多个 trailer 时的正确 trailer 选择
  • 无头部 PDF 恢复 – 当 %PDF- 头部缺失时搜索第一个对象标记

新增 – 字体编码

  • CFF 字体编码解析器 – 解析 CFF/OpenType 字体程序以获取字符编码
  • Type1 字体编码解析器 – 解析嵌入的 Type 1 字体程序以获取字形映射
  • 80K+ CID 到 Unicode 映射 – 扩展了 Adobe-CNS1、Adobe-GB1、Adobe-Japan1、Adobe-Korea1
  • Shift-JIS/RKSJ 解码 – 日文 Shift-JIS 编码的 CMap 流支持
  • Identity-H cmap 传播 – 从 CIDFont 后代传播 TrueType cmap 表

修复 – 文本提取管线

  • Tf 缓冲刷新 – 在字体切换时刷新待处理文本以防止文本丢失
  • 自适应空格阈值 – 用基于 bbox 的间距替换固定的 0.25em 阈值
  • Span 去重 – 对为粗体/阴影效果而渲染的重叠 span 去重
  • 字符去重 – 移除同一行内 2pt 以内的重复字符
  • 移除 BT 操作符检查 – 修复了跳过有效文本块的错误验证
  • ByteMode 解码 – 正确的 1 字节、2 字节和可变宽度字符码解码
  • 注释文本提取 – 从 Widget、FreeText 和外观流提取文本

v0.3.6 – 2026-02-16

快 10 倍 – 消除两个 O(n) 瓶颈

性能

  • 批量页面树缓存 – 在首次访问页面时,整个页面树被遍历一次,所有页面都被缓存。此前 get_page() 为每个未缓存页面从根遍历,导致每页 O(n)、顺序访问总计 O(n^2)。现在在单次 O(n) 遍历后每页 O(1)。一个 10,000 页的 veraPDF 测试文件从 55,667ms 降至 332ms(快 168 倍)。

  • 对象扫描偏移缓存 – 当对象在 xref 表中缺失时,scan_for_object() 此前为每个缺失对象读取整个 PDF 文件。带有数百个不在 xref 中的结构树元素的标记式 PDF 会触发数百次整文件读取。现在文件被扫描一次,所有对象偏移都被缓存。一个 10 页的标记式 PDF 从约 10s 降至 68ms(快 146 倍)。一个带 571 个字体的 154 页学术 PDF 从约 18s 降至 405ms(快 44 倍)。

  • 单遍文本提取extract_spans() 不再运行两遍(先分类文档类型,再提取)。分类遍被完全消除;自适应的字体感知阈值现在在单遍中产生相等或更好的结果。

  • 内容流 Vec 预分配parse_content_stream() 根据流大小预分配操作符 Vec 容量,减少大型内容流的重新分配。

已验证 – 3,830-PDF 语料(v0.3.5 至 v0.3.6)

指标 v0.3.5 v0.3.6 变化
通过率 99.8% 99.8% 3,830 个有效 PDF 中的 3,823 个
慢(>5s) 2 0 已消除
平均 23.3ms 2.1ms -91%
p50 0.6ms 0.6ms
p90 3.0ms 2.6ms -13%
p99 33.2ms 18.0ms -46%
最大 68,722ms 625ms -99%
合计(全部 PDF) 89.1s 8.0s -91%

文本输出在 11 个 PDF(862 KB 提取文本)上验证为逐字节相同。4 个 PDF 因自适应间距而显示出提取质量的提升。


v0.3.5 – 2026-02-15

性能、3,830-PDF 稳定性和错误恢复

性能

  • 跨页面字体缓存 – 以 ObjectRef 为键的文档级字体缓存避免在每页重新解析共享字体
  • 页面对象缓存get_page() 缓存已解析的页面对象,消除多页提取的重复页面树遍历
  • 结构树缓存 – 结构树结果在首次访问后被缓存,避免在每次 extract_text() 调用时的冗余解析
  • BT 操作符提前退出 – 文本提取对不含 BT(Begin Text)操作符的仅图像页面跳过完整管线
  • 大文件的更大 I/O 缓冲区 – 对超过 100 MB 的文件,BufReader 容量从 8 KB 增至 256 KB
  • 移除 Xref 重建阈值 – 消除了在对象很少的有效组合 PDF 上触发整文件重建的启发式

已验证 – 3,830-PDF 语料

  • 在横跨 veraPDF(2,907)、Mozilla pdf.js(897)、SafeDocs(26)的 3,830 个 PDF 上 100% 通过率
  • 零超时、零 panic
  • p50 = 0.6ms、p90 = 3.0ms、p99 = 33ms

新增 – 加密

  • 所有者密码认证 – R<=4 用算法 7,R>=5 用算法 12
  • 带 SASLprep 的 R>=5 用户密码验证 – 使用 SHA-256 的完整 AES-256 密码验证
  • 公开密码认证 APIPdf::authenticate(password)PdfDocument::authenticate(password)

新增 – PDF/A 合规验证

  • XMP 元数据验证 – 检查 pdfaid:partpdfaid:conformance
  • 色彩空间验证 – 扫描页面内容流以查找无输出意图的设备相关颜色操作符
  • AFRelationship 验证 – PDF/A-3 嵌入文件规范验证

新增 – PDF/X 合规验证

  • XMP PDF/X 标识 – 验证 pdfxid:GTS_PDFXVersion
  • 页面框关系验证 – TrimBox 在 BleedBox 内,BleedBox 在 MediaBox 内
  • ExtGState 透明度检测 – SMask、CA/ca、BM 检查
  • 设备相关颜色检测 – 标记不受支持的色彩空间
  • ICC 配置文件验证 – 验证 ICCBased 配置文件流

新增 – 渲染

  • 符合规范的裁剪 – 裁剪状态作用域限定于 q/Q 保存/恢复
  • 字形步进宽度计算 – 按 PDF 规范 9.4.4 节
  • Form XObject 渲染 – 解析 /Matrix 变换,使用表单的 /Resources

修复 – 错误恢复(28+ 个真实世界 PDF)

  • 缺失对象按 PDF 规范 7.3.10 节解析为 Null
  • 对不寻常版本字符串的宽容头部版本解析
  • 非标准加密算法匹配(V=1、R=3 组合)
  • 非字典的 Resources 被视为空而非报错
  • 优雅地跳过页面树中的 Null 节点
  • 损坏的内容流返回空内容而非错误
  • 通过 /Resources+/Parent 启发式的增强页面树扫描

修复 – DoS 防护

  • 页数针对 PDF 规范附录 C.2 上限(8,388,607)进行验证

修复 – 图像提取

  • 通过 Do 操作符的内容流图像提取
  • 带循环检测的嵌套 Form XObject 图像
  • 内联图像(BI…ID…EI 序列)
  • 用于图像定位的 CTM 变换
  • ColorSpace 间接引用解析

修复 – 解析器健壮性

  • 多行对象头部(Google 生成 PDF 使用的 1 0\nobj 格式)
  • 头部搜索从 1024 扩展到 8192 字节
  • 对格式错误头部的宽容版本解析

修复 – 页面访问健壮性

  • 无 /Contents 的页面返回空内容
  • 循环页面树检测防止栈溢出
  • 优雅处理 Null 流引用
  • 无 /Type 项的页面通过 /MediaBox 或 /Contents 键找到

修复 – 加密健壮性

  • 用过小密钥进行 AES 解密返回错误而非 panic
  • 针对格式错误项加固 Xref 流解析
  • 在解析前解析间接的 /Encrypt 引用

修复 – 内容流处理

  • 针对裸字典的 Dictionary-as-Stream 回退
  • 缩写滤镜名(AHx、A85、LZW、Fl、RL、CCF、DCT)
  • 内容流操作符上限(默认 1,000,000)

修复 – 代码质量

  • 结构树间接对象引用在解析时解析
  • Lexer 的 R/RG 词元消歧
  • 流空白修剪不再从二进制数据剥除 NUL 字节或空格

测试

  • 8 个此前被忽略的测试被取消忽略并修复

移除

  • 空的 PdfImage 存根(提取使用 ImageInfo
  • 被注释掉的 DocumentType::detect() 测试块

v0.3.4 – 2026-02-12

解析健壮性、字符提取和 XObject 路径

破坏性变更

  • parse_header() 签名从 (u8, u8) 改为 (u8, u8, u64) 以包含字节偏移

修复 – PDF 解析健壮性(Issue #41)

  • 带二进制前缀或 BOM 头部的 PDF 现在能成功打开
  • 头部搜索在前 1024 字节中扫描 %PDF- 标记
  • 支持 UTF-8 BOM、电子邮件头部和其他前导二进制数据
  • 宽容模式处理真实世界的格式错误 PDF;严格模式用于合规测试

新增 – 字符级文本提取(Issue #39)

  • extract_chars() 返回带逐字符定位的 Vec<TextChar>
  • 包含变换矩阵、旋转角度、步进宽度
  • 按阅读顺序排序,带重叠字符去重
  • 对仅字符的用例比 span 提取快 30-50%
  • 在 Rust 和 Python API 中均暴露

新增 – XObject 路径提取(Issue #40)

  • extract_paths() 通过 Do 操作符递归处理 Form XObject
  • 通过 /Matrix 正确应用坐标变换
  • 图形状态被正确隔离(保存/恢复)
  • 重复 XObject 检测防止无限循环
  • 支持嵌套 XObject

变更

  • 将 nom 解析器库从 7.1 升级到 8.0

v0.3.3 – 2026-02-11

CJK 支持、结构树增强和合规基础

包含 v0.2.5 和 v0.2.6 的所有变更,作为一次合并发布。

亮点

  • TagSuspect/MarkInfo 支持 – 从文档目录解析 MarkInfo 字典
  • 用于 CJK 文本的 Word Break /WB 结构元素
  • 针对 Adobe-GB1(简体中文)、Adobe-Japan1(日文)、Adobe-CNS1(繁体中文)、Adobe-Korea1(韩文)的预定义 CMap 支持
  • 缩写展开 /E 支持
  • 用于 CIDFont 字形宽度的 Type 0 /W 数组解析
  • 软连字符(U+00AD)处理修复
  • 带子类型支持的增强制品过滤
  • HTML 和 Markdown 输出中的图像嵌入(base64 data URI)
  • embed_images=falseimage_output_dir图像文件导出
  • PdfImage::to_base64_data_uri()to_png_bytes() 方法

v0.3.2 – 2026-02-01

编辑、加密和文档安全

新增 – PDF 编辑

  • 用于修改现有 PDF 的 DocumentEditor
  • 完整的注释支持(文本标记、形状、印章、墨迹、文件附件、密文涂改)
  • 交互式表单字段创建(文本、复选框、单选、下拉、列表、按钮)
  • 表单扁平化
  • 链接注释(URL、内部页面导航)
  • 大纲/书签构建器
  • PDF 图层(可选内容组)

新增 – 加密

  • 写入时加密(AES-256、AES-128、RC4-128、RC4-40)
  • 权限控制(打印、复制、修改、注释)
  • EncryptionAlgorithmPermissionsEncryptionConfig 构建器
  • 数字签名基础

v0.3.1 – 2026-01-14

表单字段、多媒体、创建工具和搜索

新增 – PDF 创建

  • Pdf::from_markdown()Pdf::from_html()Pdf::from_text()Pdf::from_image()
  • 用于元数据和布局配置的 PdfBuilder 流畅模式
  • 用于程序化 PDF 生成的 DocumentBuilder
  • TableRenderer 进行表格渲染
  • 图形 API:颜色、渐变、图案、混合模式、透明度
  • 带页眉、页脚、页码、水印的页面模板
  • 条形码生成(QR、Code128、EAN-13、UPC-A、Code39、ITF)

新增 – 搜索

  • 带正则、区分/不区分大小写、整词、页面范围的文本搜索
  • SearchOptionsSearchResult 类型
  • 带页面/坐标的位置追踪

新增 – 表单字段覆盖(95%)

  • 层级字段创建(带点分名称的父/子结构)
  • 字段属性修改(只读、必填、矩形、工具提示、最大长度、对齐、默认值)
  • 用于表单数据交换的 FDF/XFDF 导出

新增 – 多媒体注释

  • MovieAnnotation、SoundAnnotation、ScreenAnnotation、RichMediaAnnotation
  • 带 U3D 和 PRC 格式支持的 ThreeDAnnotation

新增 – XFA 表单支持

  • XfaExtractor、XfaParser、XfaConverter(XFA 到 AcroForm 转换)

变更 – Python 绑定

  • 通过 abi3-py38 真正支持 Python 3.8-3.14
  • 现代化工具:uv、pdm、ruff 集成

v0.3.0 – 2026-01-10

提取基础 – 统一 API 与核心能力

新增 – 统一 Pdf API

  • 用于读取现有 PDF 的 Pdf::open()
  • 通过 pdf.page(0) 的类 DOM 页面导航
  • 用于高级用例的 PdfDocument 低层句柄

新增 – 文本提取

  • extract_text() – 全页纯文本
  • extract_spans() – 带字体元数据的样式化文本段
  • 用于标记式 PDF 的基于结构树的阅读顺序
  • 用于未标记 PDF 的智能断行和空格检测

新增 – 图像提取

  • extract_images() – 从页面提取所有图像
  • 格式检测(JPEG、PNG、TIFF、JBIG2、CCITT)
  • 色彩空间处理(DeviceRGB、DeviceCMYK、DeviceGray、ICCBased)

新增 – 元数据提取

  • 文档信息字典(标题、作者、主题、关键词)
  • XMP 元数据读/写
  • 页面信息(尺寸、旋转、media/crop/trim 框)

新增 – 表单提取

  • 用于 AcroForm 字段枚举的 extract_form_fields()
  • 文本、按钮、选择和签名字段类型

新增 – 转换

  • to_markdown() – 页面级 Markdown 转换
  • to_html() – 页面级 HTML 转换
  • to_plain_text() – 可配置的纯文本输出

新增 – 合规

  • PDF/A 验证(ISO 19005,级别 1a 至 3b)
  • PDF/X 验证(ISO 15930,级别 X-1a 至 X-6p)
  • PDF/UA 验证(ISO 14289,级别 UA-1 和 UA-2)

新增 – 渲染(需要 rendering 特性)

  • 通过 tiny-skia 将页面渲染为 PNG/JPEG
  • 可配置的 DPI 和缩放

新增 – Python 绑定

  • 带完整提取 API 的 PdfDocument
  • 带创建和高层 API 的 Pdf
  • 基于 PyO3,以 pdf_oxide 发布到 PyPI

v0.2.4 – 2026-01-09

  • 用于文本定位的 CTM 变换修复
  • 结构树 /Alt/Pg 解析
  • 用于公式图像的 FormulaRenderer

v0.2.3 – 2026-01-07

  • 按 PDF 规范的 BT/ET 矩阵重置
  • Markdown 转换器中的几何间距检测
  • 用于连字和断字的 apply_intelligent_text_processing()

v0.2.2 – 2025-12-15

  • 用于可发现性的关键词优化

v0.2.1 – 2025-12-15

  • 加密流解码改进

v0.1.4 – 2025-12-12

  • 加密流解码修复

v0.1.0 – 2025-11-06

  • 首次发布
  • 带符合规范的 Unicode 映射的 PDF 文本提取
  • 智能阅读顺序检测
  • 通过 PyO3 的 Python 绑定
  • 加密 PDF 支持
  • 表单字段提取
  • 图像提取