ReadViewSDK/Doc/架构对比分析_WXRead_vs_ReadViewSDK.md

281 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 架构对比分析:读书 vs ReadViewSDK
> 基于读书 v10.0.3 (Build 79) 逆向文档,与当前 ReadViewSDK 代码在 2026-05-24 的核查结果整合。
> 本文档已吸收原 [WXRead剩余问题修复计划.md](/Users/shen/Work/Code/ReadViewSDK/Doc/WXRead剩余问题修复计划.md) 的阶段方案,后续以本文档作为单一真值。
> 标注说明:
> - `✅ 已实现`:当前代码已经按接近 WXRead 的路径落地
> - `⚠️ 有差异/有问题`:已经实现一部分,但仍与 WXRead 有结构差异,或仍有已知问题
> - `❌ 未实现`:当前代码中仍缺失
---
## 核心结论
ReadViewSDK 当前已经不是“旧 UITextView 阅读器”了,文本主链路已经收口到:
- CoreText 页面直绘
- `RDEPUBTextLayouter` 分页
- 5 层 CSS 级联
- `<link>` 样式表内联
- 页面级 hit test / 选区 / 高亮 / 批注
- 字符锚点与 `fileIndex/row/column` 语义的初步位置模型
和 WXRead 现在的主要差距,已经从“能不能工作”收缩成“是否完全同构”:
1. 页面几何模型还没完全等价 `WRCoreTextLayoutFrame`
2. 章节数据模型还没完全收口成 `WRChapterData`
3. 位置模型已进入字符级锚点阶段,但还不是完整 `WREpubPositionConverter`
4. 翻页稳定性、预加载、预测翻页、显示切换一致性已经接入主链路,但还没完全补齐到 WXRead 同构
---
## 核查摘要
### ✅ 已实现
- 文本页已经改成页面级 CoreText 直绘。
- `RDEPUBTextLayouter` 已接入 `RDEPUBTextBookBuilder` / `RDPlainTextBookBuilder`
- 4 级语义断页、`avoidPageBreakInside` 页尾回退、分页缓存都已经落地。
- 5 层 CSS 级联和 EPUB `<link>` 外部样式表内联都已经落地。
- CoreText 页面 hit test、长按选区、菜单锚点、复制/高亮/批注主链路已经接入页面几何。
- CoreText 路径的高亮、注释、搜索命中已经走页面装饰层,而不是继续改正文布局真值。
- WebView 路径的高亮/批注展示链路已经补齐,不再因为 DOM 包裹失败而“有记录但不着色”。
- 分页器已经补上 inline footnote attachment 不整段挪页、标题 `keepWithNext`、`weread-page-relate` 页首借行这几类 WXRead 风格规则。
- 章节尾部“仅空白/段落分隔符”的尾页丢弃,以及极短尾页回并已经落地,`宝山辽墓材料与释读` 第 31 页空白问题已修复。
### ⚠️ 有差异/有问题
- `RDEPUBPageLayoutSnapshot`、overlay、decoration 的对象边界还没完全等价 `WRCoreTextLayoutFrame`
- `RDEPUBSelectionOverlayView.absoluteRange(at:)` 一类回查能力仍不完整,页面几何闭环还差最后一段。
- 位置模型虽然已经有 `rangeAnchor``fileIndex/row/column` 语义,但还不是完整的 WXRead 双向位置转换器。
- `RDEPUBChapterData` 已承担页内高亮/搜索/页码查询职责,但还没完全吸收 controller/book 层的章节语义。
- `RDReaderView` 已有 `pageCurl` fault patch、预加载、预测翻页和显示切换位置恢复但还不是 WXRead 那种完整宿主层补丁集。
- `default.css` / `replace.css` / `dark.css` 的效果已接近,但资源体系和 WXRead 私有 CSS 仍不是一比一镜像。
### ❌ 未实现
- 完整 `WRChapterData` 同构模型
- 完整 `WREpubPositionConverter` 同构模型
- 预加载、预测翻页、显示切换一致性的完整宿主层方案
- 多栏、字体动态加载、繁简转换
- TTS / DRM / Pencil
---
## 1. 渲染路径对比
| 维度 | 读书 | ReadViewSDK | 核查 |
|------|---------|-------------|------|
| EPUB 文本渲染 | `WRPageView.drawRect:``CTFrameDraw` 到 CGContext | `RDEPUBTextContentView``RDEPUBDirectCoreTextPageView.draw(_:)` + `DTCoreTextLayoutFrame.draw(in:)` 页面级直绘 | ✅ 已实现 |
| WebView 路径 | WKWebView公众号/文集文章) | WKWebViewinteractive/fixed-layout EPUB | ✅ 已实现 |
| 文本选区 | `CTLineGetStringIndexForPosition` 坐标级 hit test | `RDEPUBPageInteractionController` + `RDEPUBSelectionOverlayView` 已接入主链路 | ✅ 已实现 |
| 标注绘制 | `CTFrame` 层叠加绘制CGContext | CoreText 路径已走页面装饰层WebView 路径仍是 JS/DOM 高亮 | ⚠️ 有差异/有问题 |
| 搜索高亮 | `WRCoreTextLayoutFrame.highlightSearchResults:` 直接绘制 | CoreText 路径已页面化;不同渲染路径仍不是同一套对象模型 | ⚠️ 有差异/有问题 |
**结论:** 文本页的“是否页面级 CoreText”已经不是问题当前差距是页面装饰对象和双路径一致性。
---
## 2. 分页引擎对比
| 维度 | 读书 | ReadViewSDK | 核查 |
|------|---------|-------------|------|
| 分页核心 | `WRCoreTextLayouter` + `WRCoreTextLayoutFrame` | `RDEPUBTextLayouter` + `RDEPUBTextLayoutFrame` | ✅ 已实现 |
| 断页策略 | 4 级语义断页 | 已启用 4 级语义断页 | ✅ 已实现 |
| `avoidPageBreakInside` | 页尾最多回退若干行避免破碎 | 已实现页尾最多回退 3 行 | ✅ 已实现 |
| inline footnote | 行内脚注不应触发整段挪页 | 已修正为仅块级 attachment 参与整块挪页 | ✅ 已实现 |
| 标题 keep-with-next | 标题不能孤悬页尾 | 已补 `keepWithNext` 语义与页尾回退 | ✅ 已实现 |
| `weread-page-relate` | 页首关联块需要借上一页一行 | 已补页首 `pageRelate` 借行规则 | ✅ 已实现 |
| 章节尾页收口 | 丢弃空白尾页、合并极短尾页 | 已补尾页空白丢弃与超短尾页回并 | ✅ 已实现 |
| 分页配置 | `WRCoreTextLayoutConfig`(含多栏等) | 已有 `RDEPUBTextLayoutConfig`,但多栏等仍缺 | ⚠️ 有差异/有问题 |
| 缓存 | 按书籍 + 排版设置缓存 | 已有 `RDEPUBTextBookCache` 磁盘缓存 | ✅ 已实现 |
**结论:** 当前分页质量问题已经进入问题书细抠阶段,不再是“缺分页器”的阶段;章节尾部空白页这类系统性问题也已经开始按 WXRead 规则收口。
---
## 3. CSS 处理对比
| 维度 | 读书 | ReadViewSDK | 核查 |
|------|---------|-------------|------|
| CSS 级联层级 | 5 级:`default < replace < dark < epub < user` | `RDEPUBTextStyleSheetPackage` 已实际生成并注入 5 | 已实现 |
| EPUB `<link>` CSS | 解析前级联合并外部样式 | 已实现抽取内联URL 重写与诊断 | 已实现 |
| 自定义 CSS 属性 | `wr-vertical-center-style`、`weread-page-relate`、断页相关私有属性 | 已支持 `pageRelate`、`avoidPageBreakInside`、attachment placement仍非完整 WeRead 属性全集 | 有差异/有问题 |
| WXRead 私有 CSS 文件 | 使用 WeRead 自带 `default/replace/dark/...` | 当前是等价策略不是原文件原样镜像 | 有差异/有问题 |
| `replaceForLatinLanguageBook.css` | 拉丁语言专项字体规则 | 无对应 | 未实现 |
**结论:** CSS 主机制已对齐剩下是规则细节和私有资源体系差异
---
## 4. 位置模型对比
| 维度 | 读书 | ReadViewSDK | 核查 |
|------|---------|-------------|------|
| 主模型 | `WREpubPositionConverter` `(fileIndex, row, column)` | `RDEPUBTextAnchor` + `rangeAnchor` + `RDEPUBTextIndexTable` | 有差异/有问题 |
| 恢复精度 | 字符级双向恢复 | 已优先按 anchor 恢复弱化 `progression` | 有差异/有问题 |
| 旧数据兼容 | 兼容历史位置模型 | 已兼容旧 `spineIndex` 等旧字段解码 | 已实现 |
| 全量双向转换 | 文件位置 <-> 全书字符位置 <-> 页码 | 已有一部分,但还不是完整 `WREpubPositionConverter` | ⚠️ 有差异/有问题 |
**结论:** 这一块已经从 `❌` 进入 `⚠️`但还没有达到“WXRead 同构”。
---
## 5. 章节数据模型对比
| 维度 | 读书 | ReadViewSDK | 核查 |
|------|---------|-------------|------|
| 核心模型 | `WRChapterData` 一体化承载渲染结果 + 标注 + 搜索 + 目录 | `RDEPUBChapterData` 已存在,但职责仍未完全收拢 | ⚠️ 有差异/有问题 |
| 页内高亮查询 | 章节对象直接提供 | `RDEPUBChapterData.highlights(on:from:)` 已提供 | ✅ 已实现 |
| 页内搜索查询 | 章节对象直接提供 | `RDEPUBChapterData.searchResults(on:from:)` 已提供 | ✅ 已实现 |
| 页码/位置查询 | 章节对象内聚 | 已部分迁入 `RDEPUBChapterData`,仍有一部分散在 controller/book | ⚠️ 有差异/有问题 |
| 目录与章节语义 | 基于章节数据统一管理 | 仍大量依赖独立 TOC 解析与 controller 调度 | ⚠️ 有差异/有问题 |
**结论:** 章节对象已经不是空白,但也还没收口成 WXRead 那种唯一章节语义中心。
---
## 6. 翻页控制器与宿主层对比
| 维度 | 读书 | ReadViewSDK | 核查 |
|------|---------|-------------|------|
| 翻页动画 | curl / slide / fade / none | 已有多种翻页模式 | ✅ 已实现 |
| `UIPageViewController` crash patch | 3 个以上专项 patch | 已有 pageCurl fault detect + 异步重建 | ⚠️ 有差异/有问题 |
| 预加载 | `WRForecastUtils` 预测 + 后台准备 | 已围绕当前页与预测方向预热相邻页视图 | ⚠️ 有差异/有问题 |
| 预测翻页 | 基于用户方向预测预建内容 | 已按可见 spread 和预测方向预热缓存 | ⚠️ 有差异/有问题 |
| 显示切换一致性 | 翻页模式/单双页/方向切换稳定恢复 | 已接入切换前记录 location、切换后按位置回落 | ⚠️ 有差异/有问题 |
**结论:** Phase 6 已进入“有实现、继续细抠”的阶段,不再是空白;但离 WXRead 的完整宿主层稳定性还有差距。
---
## 7. 资源体系对比
### CSS
| 文件 | 读书职责 | ReadViewSDK 状态 | 核查 |
|------|-------------|-----------------|------|
| `default.css` | 基础 HTML 标签样式 | 已有等价基础 CSS | ⚠️ 有差异/有问题 |
| `replace.css` | 标题、图片、引用、分页控制 | 已有等价 replace 层 | ⚠️ 有差异/有问题 |
| `dark.css` | 暗色主题 | 已有 dark 层 | ⚠️ 有差异/有问题 |
| `replaceForLatinLanguageBook.css` | 拉丁语言字体 | 无 | ❌ 未实现 |
| `replaceForMPChapter.css` | 公众号文章专用 | EPUB 主链路不需要 | ❌ 未实现(暂不需要) |
### JS
| 文件 | 读书职责 | ReadViewSDK 状态 | 核查 |
|------|-------------|-----------------|------|
| `weread-highlighter.js` | Web 高亮引擎 | `epub-bridge.js` 已接住高亮/批注展示 | ⚠️ 有差异/有问题 |
| `rangy-*` | 选区/高亮库 | CoreText 路径不需要Web 路径也未采用 | ⚠️ 有差异/有问题 |
| `cssInjector.js` | 动态 CSS 注入 | 现为原生侧静态注入 | ⚠️ 有差异/有问题 |
| `WeReadApi.js` | JS-Native 桥接 | `window.RDReaderBridge` | ⚠️ 有差异/有问题 |
**结论:** 不建议也不应该把 WXRead 私有 JS/CSS 资源整包原样搬用;当前应继续走“能力等价、实现自有”的路线。
---
## 8. 缺失能力清单
| 能力 | 核查 | 当前优先级 |
|------|------|-----------|
| 页面几何模型完全等价 `WRCoreTextLayoutFrame` | ⚠️ 有差异/有问题 | P1 |
| `RDEPUBChapterData` 最终内聚 | ⚠️ 有差异/有问题 | P2 |
| 完整字符级位置转换器 | ⚠️ 有差异/有问题 | P2 |
| 翻页 crash patch 完整版 | ⚠️ 有差异/有问题 | P3 |
| 预加载 | ⚠️ 有差异/有问题 | P3 |
| 预测翻页 | ⚠️ 有差异/有问题 | P3 |
| 显示切换一致性 | ⚠️ 有差异/有问题 | P3 |
| 多栏排版 | ❌ 未实现 | P4 |
| 字体动态加载 | ❌ 未实现 | P4 |
| 繁简转换 | ❌ 未实现 | P4 |
| TTS / DRM / Pencil | ❌ 未实现 | P4 |
---
## 9. 收口路线(整合原修复计划)
### P1页面几何与分页行为闭环
- `RDEPUBPageLayoutSnapshot` 继续补齐到更接近 `WRCoreTextLayoutFrame`
- overlay / decoration / selection 回查能力继续统一
- 继续结合问题书压平标题、脚注段、`weread-page-relate`、attachment、缩进段等分页细节
当前状态:`⚠️ 进行中`
### P2位置模型与章节数据内聚
-`rangeAnchor` / `fileIndex/row/column` 继续收成完整位置转换器
- 把 controller / book 层散落的正文语义继续迁入 `RDEPUBChapterData`
当前状态:`⚠️ 进行中`
### P3宿主层稳定性
- `pageCurl` crash patch 完整化
- 预加载细化
- 预测翻页细化
- 显示切换一致性继续压平
当前状态:`⚠️ 进行中`
### P4外围能力
- 多栏
- 字体系统
- 繁简转换
- TTS / DRM / Pencil
当前状态:`❌ 未开始`
---
## 10. 读书关键类职责速查
| 类名 | 职责 | ReadViewSDK 对应 | 核查 |
|------|------|-----------------|------|
| `WRReaderViewController` | 阅读器主控制器 | `RDEPUBReaderController` | ✅ 已有对应 |
| `WRPageViewController` | 翻页控制器 + crash patch | `RDReaderView` | ⚠️ 有差异/有问题 |
| `WRPageView` | CoreText 直接绘制页面 | `RDEPUBTextContentView` + `RDEPUBDirectCoreTextPageView` | ✅ 已实现 |
| `WREpubTypesetter` | HTML → NSAttributedStringCSS 级联) | `RDEPUBDTCoreTextRenderer` | ✅ 已实现 |
| `WRCoreTextLayouter` | CoreText 排版引擎 | `RDEPUBTextLayouter` | ✅ 已实现 |
| `WRCoreTextLayoutFrame` | 排版帧(绘制/选区/搜索/装饰) | `RDEPUBTextLayoutFrame` + snapshot/interaction/overlay | ⚠️ 有差异/有问题 |
| `WRChapterData` | 章节数据模型 | `RDEPUBChapterData` | ⚠️ 有差异/有问题 |
| `WRChapterPageCount` | 分页计算 + 缓存 key | `RDEPUBTextBookBuilder` + `RDEPUBTextBookCache` | ✅ 已实现 |
| `WREpubPositionConverter` | 字符级位置双向转换 | `RDEPUBTextAnchor` + `RDEPUBTextIndexTable` | ⚠️ 有差异/有问题 |
| `WRBookmark` | 标注统一模型 | `RDEPUBHighlight` + `RDEPUBBookmark` | ⚠️ 有差异/有问题 |
| `DTHTMLAttributedStringBuilder` | HTML DOM → NSAttributedString | 同(复用 DTCoreText | ✅ 已实现 |
---
## 11. 当前数据流
```text
EPUB 文件
-> RDEPUBParser.parse (container.xml -> OPF -> spine)
-> readingProfile 分流:
textReflowable:
-> RDEPUBDTCoreTextRenderer
-> 5 层 CSS 级联
-> <link> CSS 内联
-> 自定义分页语义注入
-> RDEPUBTextBookBuilder
-> RDEPUBTextLayouter
-> RDEPUBTextBookCache
-> RDEPUBTextContentView
-> RDEPUBDirectCoreTextPageView
-> RDEPUBPageInteractionController
-> RDEPUBSelectionOverlayView
webInteractive:
-> RDEPUBPaginator
-> RDEPUBWebContentView
-> epub-bridge.js
webFixedLayout:
-> RDEPUBWebContentView
```
---
*分析基础:读书 v10.0.3 (Build 79) 逆向文档*
*当前代码核查日期2026-05-24*