Rust Core: - events: global Mutex-buffered event queue (push/export/clear/update_position) - image_meta: use ImageReader::format() for real decoded format instead of extension - search: change match_start/match_end usize→u64 for FFI compatibility - epub/pdf: module-level placeholder comments FFI (UDL exposed, 12 total functions): - Added: search_markdown_blocks, search_text_content, create_note_anchor - Added: push_reading_event, update_reading_position, export_pending_events, clear_exported_events Docs: - README: synced DocumentBlock model (Table.headers + HorizontalRule), simplified dependency recommendations, removed nonexistent doc references - docs/pdf-strategy.md: PDFKit vs PDFium vs MuPDF evaluation, 5 decisions, platform strategy matrix, roadmap Build: - .cargo/config.toml: cargo xtask alias - xtask: CLI implementation (test/build-ios/fixtures commands) - fixtures: markdown/sample.md (9 block types), text/sample.txt - XCFramework rebuilt, Swift bindings regenerated (1977 lines) 58 tests pass, zero warnings. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5.7 KiB
5.7 KiB
PDF 阅读方案评估
概述
PDF 是知习支持的核心文件格式之一。本文档明确 PDF 在各平台的处理策略、技术选型边界和后续路线图。
核心结论
- iOS 第一版继续使用 PDFKit / QuickLook — 系统内置,无需额外依赖
- Rust 暂不接入 PDFium — 增加包体但不创造足够价值
- 文本选择由平台能力承担 — PDFKit(iOS)、PdfRenderer(Android)
- PDF 搜索后置 — 待文本提取方案确定后再做
- 扫描 PDF / OCR 暂缓 — 明确不在第一版范围
方案对比
候选方案
| 方案 | 二进制大小 | 平台支持 | 文本提取 | 搜索 | 标注 | 成熟度 |
|---|---|---|---|---|---|---|
| QuickLook (iOS/macOS) | 0(系统内置) | Apple only | 否 | 否 | 否 | 高 |
| PDFKit (iOS/macOS) | 0(系统内置) | Apple only | 是 | 是 | 是 | 高 |
| Android PdfRenderer | 0(系统内置) | Android only | 部分 | 否 | 否 | 中 |
| pdfium-render (Rust) | ~15MB/平台 | 全平台 | 是 | 可自建 | 否 | 中 |
| MuPDF (C) | ~8MB/平台 | 全平台 | 是 | 可自建 | 部分 | 高 |
评估维度
| 维度 | QuickLook (iOS) | PDFKit (iOS) | pdfium-render (Rust) |
|---|---|---|---|
| 集成成本 | 极低(QLPreviewController) | 低(原生 API) | 高(交叉编译、binding) |
| 包体影响 | 0 | 0 | ~15MB × 平台数 |
| 页面渲染 | ✅ | ✅ | ✅(需要 bitmap pipeline) |
| 文本提取 | ❌ | ✅ | ✅ |
| 文本选择 | ❌(只能看不选) | ✅ | 需自建 UI |
| 搜索 | ❌ | ✅ | 可自建 |
| 阅读位置 | App 侧维护 | App 侧 + delegate | Rust 侧统一 |
| 统一数据模型 | ❌ | ❌ | ✅ |
| 跨平台复用 | ❌ | ❌ | ✅ |
各平台策略
iOS / macOS
当前(M3-M4):PDFKit
MaterialReaderView
→ PreviewMode.platformPreview
→ QuickLook sheet (QLPreviewController)
→ App 侧监听页码变化
→ 生成 ReadingPosition::Pdf { pageNumber, pageProgress, overallProgress }
→ pushReadingEvent
优势:
- 零依赖,系统自带
- 渲染质量高
- 支持系统级文本选择、搜索
- 用户熟悉的交互
局限:
- QuickLook 不暴露页码变化回调(需要 PDFKit 的 PDFView 才能精确跟踪)
- 无法提取文本传给 Rust 做统一搜索
- App 侧需用 PDFView delegate 替代 QLPreviewController 以获得页码回调
后续增强:如果需要文本提取/搜索,把 QuickLook sheet 替换为 PDFView + PDFDocument,通过 PDFDocument.string 提取全文传给 Rust search_text。
Android
当前策略:系统预览 / 外部 App
Android 有 PdfRenderer(API 21+),可渲染页面为 Bitmap。但第一版不做内置 PDF 阅读器。
MaterialReaderView (Android)
→ PreviewMode.platformPreview
→ Intent.ACTION_VIEW + content:// URI
→ 系统 PDF 阅读器 / Chrome
→ 回到 App 后手动记录阅读时长
后续可选:PdfRenderer + RecyclerView 自建阅读器,用 Rust ReadingPosition::Pdf 统一位置模型。
鸿蒙 / Windows / Web
均优先走系统预览或浏览器内置 PDF 阅读器。Rust 只统一 ReadingPosition::Pdf 模型。
阅读位置模型
Rust 已定义统一的 ReadingPosition::Pdf:
ReadingPosition::Pdf {
page_number: u32, // 1-based 页码
page_progress: f32, // 0.0 ~ 1.0,该页内滚动比例
overall_progress: f32, // 0.0 ~ 1.0,全书进度
}
App 侧职责:
- iOS:PDFView.pageChange delegate → 更新位置
- Android:监听页面变化 → 更新位置
- 所有平台:用同一套
ReadingPosition::Pdf模型,不重复造轮子
Rust 侧职责边界
当前(M3-M4)
MaterialType::Pdf— 文件类型识别 ✅ReadingPosition::Pdf— 统一位置模型 ✅PreviewMode::PlatformPreview— 预览模式映射 ✅pdf.rs— 模块占位(注释说明走平台预览)✅
不做的
- 不集成 PDFium
- 不做 PDF 渲染(bitmap 生成)
- 不做 PDF 文本提取
- 不做 PDF 标注
- 不做 OCR
后续评估(M5+)
如果以下条件满足 3 项以上,重新评估 PDFium 集成:
- Android 需要内置 PDF 阅读器
- 搜索需要在 PDF 中定位
- 需要跨平台统一的文本提取
- 用户量大到平台差异成为维护负担
- PDFium 交叉编译经验积累充分
搜索策略
| 阶段 | 方案 | 能力 |
|---|---|---|
| M3-M4 | 不搜索 PDF | 用户在平台预览器中手动使用系统搜索 |
| M5+ | 平台提取 + Rust 搜索 | PDFKit.string / PdfRenderer → 传给 Rust search_text |
| 远期 | PDFium 提取 + Tantivy | 全文索引,支持 PDF 内定位 |
扫描 PDF / OCR
明确不进入知习范围。理由:
- OCR 是独立技术领域,与"阅读内核"定位不符
- 高精度 OCR 需要专门模型(Tesseract / Apple Vision / ML Kit)
- 绝大多数学习资料是原生电子文档,非扫描件
- 扫描件场景可由用户自行 OCR 后导入
后续路线图
M3 ✅ — QuickLook sheet + ReadingPosition::Pdf
M4 ● — pdf-strategy.md(本文档)
M5 ○ — iOS 迁移至 PDFView(获得文本提取和页码回调)
— Rust 接收 PDF 全文做 search_text
M6+ ○ — 评估 PDFium(Android 自建阅读器需求驱动)
— 如集成 PDFium:文本提取 + bitmap 渲染 + 搜索定位
验收确认
- iOS 第一版继续使用 PDFKit / QuickLook
- Rust 暂不接 PDFium
- PDF 文本选择由平台能力承担
- PDF 搜索后置
- 扫描 PDF / OCR 暂缓
- 文档存在,方案决策明确,有后续路线图