feat(wxread): align pagination, rendering, and docs
This commit is contained in:
+183
-152
@@ -1,249 +1,280 @@
|
||||
# 架构对比分析:微信读书 vs ReadViewSDK
|
||||
# 架构对比分析:读书 vs ReadViewSDK
|
||||
|
||||
> 基于微信读书 v10.0.3 (Build 79) 逆向工程,对比当前 ReadViewSDK 项目架构差距。
|
||||
> 分析日期: 2026-05-23
|
||||
> 当前代码核查日期: 2026-05-24
|
||||
> 参考文档: `Doc/WXRead/decompiled-doc.md`、`Doc/WXRead/resources-doc.md`、`Doc/WXRead/微信读书EPUB阅读器实现架构.md`
|
||||
> 基于读书 v10.0.3 (Build 79) 逆向文档,与当前 ReadViewSDK 代码在 2026-05-24 的核查结果整合。
|
||||
> 本文档已吸收原 [WXRead剩余问题修复计划.md](/Users/shen/Work/Code/ReadViewSDK/Doc/WXRead剩余问题修复计划.md) 的阶段方案,后续以本文档作为单一真值。
|
||||
|
||||
> 标注说明:
|
||||
> - `✅ 已实现`:当前代码已经按接近 WXRead 的路径落地
|
||||
> - `⚠️ 有差异/有问题`:已经实现一部分,但仍与 WXRead 有结构差异,或者当前实现仍有已知问题
|
||||
> - `⚠️ 有差异/有问题`:已经实现一部分,但仍与 WXRead 有结构差异,或仍有已知问题
|
||||
> - `❌ 未实现`:当前代码中仍缺失
|
||||
|
||||
---
|
||||
|
||||
## 核心结论
|
||||
|
||||
微信读书使用**双渲染引擎架构**(Path A: 原生 CoreText / Path B: WebView)。ReadViewSDK 当前也已经是 CoreText 文本页 + WebView 双路径,但文本页仍保留 `UITextView` 作为选区代理层,因此“页面绘制”已接近 WXRead,“选区/装饰/命中测试”仍未完全收口到同一套 CoreText 页面模型。
|
||||
ReadViewSDK 当前已经不是“旧 UITextView 阅读器”了,文本主链路已经收口到:
|
||||
|
||||
- CoreText 页面直绘
|
||||
- `RDEPUBTextLayouter` 分页
|
||||
- 5 层 CSS 级联
|
||||
- `<link>` 样式表内联
|
||||
- 页面级 hit test / 选区 / 高亮 / 批注
|
||||
- 字符锚点与 `fileIndex/row/column` 语义的初步位置模型
|
||||
|
||||
和 WXRead 现在的主要差距,已经从“能不能工作”收缩成“是否完全同构”:
|
||||
|
||||
1. 页面几何模型还没完全等价 `WRCoreTextLayoutFrame`
|
||||
2. 章节数据模型还没完全收口成 `WRChapterData`
|
||||
3. 位置模型已进入字符级锚点阶段,但还不是完整 `WREpubPositionConverter`
|
||||
4. 翻页稳定性、预加载、预测翻页、显示切换一致性已经接入主链路,但还没完全补齐到 WXRead 同构
|
||||
|
||||
---
|
||||
|
||||
## 核查摘要
|
||||
|
||||
### ✅ 已按 WXRead 路径落地
|
||||
### ✅ 已实现
|
||||
|
||||
- 文本页已经改成页面级 CoreText 直绘,不再是单纯 `UITextView` 展示。
|
||||
- `RDEPUBTextLayouter` 已经接入 `RDEPUBTextBookBuilder` / `RDPlainTextBookBuilder`。
|
||||
- 文本页已经改成页面级 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 页空白问题已修复。
|
||||
|
||||
### ❌ 仍未实现
|
||||
### ⚠️ 有差异/有问题
|
||||
|
||||
- CoreText 原生 hit test / 选区命中。
|
||||
- 独立 CGContext 标注绘制层与搜索高亮层。
|
||||
- WXRead 式字符级位置模型(`fileIndex + row + column`)。
|
||||
- `WRChapterData` 一体化章节数据模型。
|
||||
- UIPageViewController crash patch、多栏、字体动态加载、TTS/DRM 等外围能力。
|
||||
- `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 仍不是一比一镜像。
|
||||
|
||||
### ⚠️ 已实现但仍有问题/差异
|
||||
### ❌ 未实现
|
||||
|
||||
- 当前文本页虽然已直绘,但仍依赖 `UITextView` 代理选区,页面几何模型没有完全统一。
|
||||
- `RDEPUBSelectionOverlayView` 仍是半成品,尚未形成完整可用的 CoreText 选区/装饰 overlay。
|
||||
- 高亮、下划线、搜索命中仍主要靠 attributedString 属性注入,而不是 WXRead 那种页面装饰绘制。
|
||||
- inline attachment 已按 WXRead 路径收敛,但仍需要继续结合问题书样验证特殊图片、脚注图标和页内基线细节。
|
||||
- 完整 `WRChapterData` 同构模型
|
||||
- 完整 `WREpubPositionConverter` 同构模型
|
||||
- 预加载、预测翻页、显示切换一致性的完整宿主层方案
|
||||
- 多栏、字体动态加载、繁简转换
|
||||
- TTS / DRM / Pencil
|
||||
|
||||
---
|
||||
|
||||
## 1. 渲染路径对比
|
||||
|
||||
| 维度 | 微信读书 | ReadViewSDK | 核查 |
|
||||
| 维度 | 读书 | ReadViewSDK | 核查 |
|
||||
|------|---------|-------------|------|
|
||||
| EPUB 文本渲染 | `WRPageView.drawRect:` → `CTFrameDraw` 到 CGContext | `RDEPUBTextContentView` → `RDEPUBDirectCoreTextPageView.draw(_:)` + `DTCoreTextLayoutFrame.draw(in:)` 页面级直绘 | ✅ 已实现 |
|
||||
| WebView 路径 | WKWebView(公众号/文集文章) | WKWebView(interactive/fixed-layout EPUB) | ✅ 已实现 |
|
||||
| 文本选区 | `CTLineGetStringIndexForPosition` 坐标级 hit test | 仍主要依赖 `UITextView` 代理选区;`RDEPUBSelectionOverlayView` 仍是半成品 | ⚠️ 有差异/有问题 |
|
||||
| 标注绘制 | `CTFrame` 层叠加绘制(CGContext) | 高亮/下划线仍主要通过 attributedString 属性注入,不是独立 CGContext 装饰层 | ⚠️ 有差异/有问题 |
|
||||
| 搜索高亮 | `WRCoreTextLayoutFrame.highlightSearchResults:` 直接绘制 | 仍是 attributedString 注入临时高亮属性 | ⚠️ 有差异/有问题 |
|
||||
| 文本选区 | `CTLineGetStringIndexForPosition` 坐标级 hit test | `RDEPUBPageInteractionController` + `RDEPUBSelectionOverlayView` 已接入主链路 | ✅ 已实现 |
|
||||
| 标注绘制 | `CTFrame` 层叠加绘制(CGContext) | CoreText 路径已走页面装饰层;WebView 路径仍是 JS/DOM 高亮 | ⚠️ 有差异/有问题 |
|
||||
| 搜索高亮 | `WRCoreTextLayoutFrame.highlightSearchResults:` 直接绘制 | CoreText 路径已页面化;不同渲染路径仍不是同一套对象模型 | ⚠️ 有差异/有问题 |
|
||||
|
||||
**核查结论:** 这段原分析已经过时。当前文本页的底层排版和绘制已经切到 CoreText 页面直绘,但“命中测试、标注装饰层、搜索高亮层”还没有完全像 WXRead 那样归并到同一套页面级 CoreText 几何模型。
|
||||
**结论:** 文本页的“是否页面级 CoreText”已经不是问题,当前差距是页面装饰对象和双路径一致性。
|
||||
|
||||
---
|
||||
|
||||
## 2. 分页引擎对比
|
||||
|
||||
| 维度 | 微信读书 | ReadViewSDK | 核查 |
|
||||
| 维度 | 读书 | ReadViewSDK | 核查 |
|
||||
|------|---------|-------------|------|
|
||||
| 分页核心 | `WRCoreTextLayouter` + `WRCoreTextLayoutFrame` | `RDEPUBTextLayouter` + `RDEPUBTextLayoutFrame`,并已接入 `RDEPUBTextBookBuilder` / `RDPlainTextBookBuilder` | ✅ 已实现 |
|
||||
| 断页策略 | 4 级语义断页:语义边界 > 附件边界 > 块边界 > 帧限制 | `rd_paginatedFrames` 已启用 4 级语义断页,并改为与显示层一致的 `DTCoreTextLayoutFrame.visibleStringRange` | ✅ 已实现 |
|
||||
| 分页配置 | `WRCoreTextLayoutConfig`(列数、栏间距、孤行控制、连字符) | 已有 `RDEPUBTextLayoutConfig`,含 `avoidOrphans`/`avoidWidows`/`avoidPageBreakInsideEnabled`/`imageMaxHeightRatio`,但多栏等能力仍缺 | ⚠️ 有差异/有问题 |
|
||||
| 缓存 | `WRChapterPageCount.currentCacheKeyWithBookId:` 按排版设置缓存 | 已有 `RDEPUBTextBookCache`,按书籍 + 排版设置缓存每章分页结果 | ✅ 已实现 |
|
||||
| 跨页避让 | `avoidPageBreakInsideByRemovingLastLinesIfNeeded` — CSS `avoid-page-break-inside` 实现 | 已实现页尾最多回退 3 行的 WXRead 式 `avoidPageBreakInside` 处理 | ✅ 已实现 |
|
||||
| 分页核心 | `WRCoreTextLayouter` + `WRCoreTextLayoutFrame` | `RDEPUBTextLayouter` + `RDEPUBTextLayoutFrame` | ✅ 已实现 |
|
||||
| 断页策略 | 4 级语义断页 | 已启用 4 级语义断页 | ✅ 已实现 |
|
||||
| `avoidPageBreakInside` | 页尾最多回退若干行避免破碎 | 已实现页尾最多回退 3 行 | ✅ 已实现 |
|
||||
| inline footnote | 行内脚注不应触发整段挪页 | 已修正为仅块级 attachment 参与整块挪页 | ✅ 已实现 |
|
||||
| 标题 keep-with-next | 标题不能孤悬页尾 | 已补 `keepWithNext` 语义与页尾回退 | ✅ 已实现 |
|
||||
| `weread-page-relate` | 页首关联块需要借上一页一行 | 已补页首 `pageRelate` 借行规则 | ✅ 已实现 |
|
||||
| 章节尾页收口 | 丢弃空白尾页、合并极短尾页 | 已补尾页空白丢弃与超短尾页回并 | ✅ 已实现 |
|
||||
| 分页配置 | `WRCoreTextLayoutConfig`(含多栏等) | 已有 `RDEPUBTextLayoutConfig`,但多栏等仍缺 | ⚠️ 有差异/有问题 |
|
||||
| 缓存 | 按书籍 + 排版设置缓存 | 已有 `RDEPUBTextBookCache` 磁盘缓存 | ✅ 已实现 |
|
||||
|
||||
**核查结论:** 这段原判断已经过时。`RDEPUBTextBookBuilder` 和 `RDPlainTextBookBuilder` 已经走 `rd_paginatedFrames(size:fragmentOffsets:)`,不再是“能力已写但未接入”的状态。
|
||||
**结论:** 当前分页质量问题已经进入问题书细抠阶段,不再是“缺分页器”的阶段;章节尾部空白页这类系统性问题也已经开始按 WXRead 规则收口。
|
||||
|
||||
---
|
||||
|
||||
## 3. CSS 处理对比
|
||||
|
||||
| 维度 | 微信读书 | ReadViewSDK | 核查 |
|
||||
| 维度 | 读书 | ReadViewSDK | 核查 |
|
||||
|------|---------|-------------|------|
|
||||
| CSS 级联层级 | 5 级:`default.css < replace.css < dark.css < EPUB 内嵌 < 用户设置` | `RDEPUBTextStyleSheetPackage` 已实际生成 5 层:`default/replace/dark/epub/user`,并分别注入 | ✅ 已实现 |
|
||||
| EPUB `<link>` CSS | `DTHTMLAttributedStringBuilder` 解析前级联合并 `<link>` 引用的 CSS | 已实现 `<link rel="stylesheet">` 抽取、内联、URL 重写与资源诊断 | ✅ 已实现 |
|
||||
| 自定义 CSS 属性 | `wr-vertical-center-style`(图片垂直居中)、`weread-page-relate`(跨页关联)、`DTPageBreakInsideAvoid`(断页避让) | 已部分支持:`pageRelate`、`avoidPageBreakInside`、attachment placement 推断;但并非完整 WeRead 属性集 | ⚠️ 有差异/有问题 |
|
||||
| CSS 层级模型 | 已定义 `RDEPUBTextStyleSheetPackage`/`RDEPUBTextStyleSheetLayer`(5 种 kind),但未完整使用 | 已实际使用;但和 WXRead 资源体系仍不是同一批 CSS 文件/规则 | ⚠️ 有差异/有问题 |
|
||||
| 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` | 拉丁语言专项字体规则 | 无对应 | ❌ 未实现 |
|
||||
|
||||
**核查结论:** “未处理 `<link>` 外部 CSS” 这一条已经不成立;但外部 CSS 即使已被内联,规则兼容度和 WXRead 自带 replace/default 体系仍可能存在差异。
|
||||
**结论:** CSS 主机制已对齐,剩下是规则细节和私有资源体系差异。
|
||||
|
||||
---
|
||||
|
||||
## 4. 位置模型对比
|
||||
|
||||
| 维度 | 微信读书 | ReadViewSDK |
|
||||
|------|---------|-------------|
|
||||
| 位置模型 | `WREpubPositionConverter` — `(fileIndex, row, column)` 三元组 | `RDEPUBLocation` — `href + progression` 浮点值 |
|
||||
| 精度 | 字符级精度 | 章节内比例精度 (0..1) |
|
||||
| 索引构建 | `initIndices` 预建全书字符索引表 | 无索引,每次实时计算 |
|
||||
| 双向转换 | `stringRangeFromFileRange:` / `fileIndexForCharacterPosition:` / `localOffsetInFileAtIndex:forGlobalPosition:` | `RDEPUBTextBook.pageNumber(for:)` / `location(forPageNumber:)` |
|
||||
| 维度 | 读书 | ReadViewSDK | 核查 |
|
||||
|------|---------|-------------|------|
|
||||
| 主模型 | `WREpubPositionConverter` `(fileIndex, row, column)` | `RDEPUBTextAnchor` + `rangeAnchor` + `RDEPUBTextIndexTable` | ⚠️ 有差异/有问题 |
|
||||
| 恢复精度 | 字符级双向恢复 | 已优先按 anchor 恢复,弱化 `progression` | ⚠️ 有差异/有问题 |
|
||||
| 旧数据兼容 | 兼容历史位置模型 | 已兼容旧 `spineIndex` 等旧字段解码 | ✅ 已实现 |
|
||||
| 全量双向转换 | 文件位置 <-> 全书字符位置 <-> 页码 | 已有一部分,但还不是完整 `WREpubPositionConverter` | ⚠️ 有差异/有问题 |
|
||||
|
||||
**影响分析:** progression 是 0..1 浮点值,在跨字号/行距重排后能保持大致位置,但无法精确到字符。微信读书的三元组提供字符级精度,适合精确标注恢复。当前 progression 模式对大部分场景够用,但在密集标注场景下可能出现标注漂移。
|
||||
|
||||
**核查:** `❌ 未实现`。当前位置模型仍然不是 WXRead 的字符级三元组。
|
||||
**结论:** 这一块已经从 `❌` 进入 `⚠️`,但还没有达到“WXRead 同构”。
|
||||
|
||||
---
|
||||
|
||||
## 5. 章节数据模型对比
|
||||
|
||||
| 维度 | 微信读书 | ReadViewSDK |
|
||||
|------|---------|-------------|
|
||||
| 核心模型 | `WRChapterData` — 一个对象承载渲染结果 + 标注 + 目录 + 免费试读截断 | `RDEPUBTextChapter` + `RDEPUBHighlight` + `EPUBChapterInfo` 分散在多处 |
|
||||
| 标注内聚 | `addHighlightInRange:` / `addUnderLineToAttributedString:` 直接在 chapterData 上操作 | 标注在 `RDEPUBReaderController` 层管理,与章节数据分离 |
|
||||
| 目录生成 | `WRChapterData.generateOutlineContents` — 从渲染结果反向提取目录 | 目录从 NCX/Nav 独立解析,不与渲染数据关联 |
|
||||
| 维度 | 读书 | ReadViewSDK | 核查 |
|
||||
|------|---------|-------------|------|
|
||||
| 核心模型 | `WRChapterData` 一体化承载渲染结果 + 标注 + 搜索 + 目录 | `RDEPUBChapterData` 已存在,但职责仍未完全收拢 | ⚠️ 有差异/有问题 |
|
||||
| 页内高亮查询 | 章节对象直接提供 | `RDEPUBChapterData.highlights(on:from:)` 已提供 | ✅ 已实现 |
|
||||
| 页内搜索查询 | 章节对象直接提供 | `RDEPUBChapterData.searchResults(on:from:)` 已提供 | ✅ 已实现 |
|
||||
| 页码/位置查询 | 章节对象内聚 | 已部分迁入 `RDEPUBChapterData`,仍有一部分散在 controller/book | ⚠️ 有差异/有问题 |
|
||||
| 目录与章节语义 | 基于章节数据统一管理 | 仍大量依赖独立 TOC 解析与 controller 调度 | ⚠️ 有差异/有问题 |
|
||||
|
||||
**核查:** `❌ 未实现`。章节数据模型仍未收敛成 WXRead 的 `WRChapterData` 一体化模式。
|
||||
**结论:** 章节对象已经不是空白,但也还没收口成 WXRead 那种唯一章节语义中心。
|
||||
|
||||
---
|
||||
|
||||
## 6. 翻页控制器对比
|
||||
## 6. 翻页控制器与宿主层对比
|
||||
|
||||
| 维度 | 微信读书 | ReadViewSDK |
|
||||
|------|---------|-------------|
|
||||
| 翻页动画 | 4 种:curl / slide / fade / none | 4 种:pageCurl / horizontalScroll / verticalScroll / horizontalCoverScroll |
|
||||
| UIPageViewController 崩溃修复 | 3 个 patch 方法处理已知 Apple bug(导航方向崩溃、子 VC 丢失、快速翻页动画故障) | 无 crash patch |
|
||||
| 导航方向检测 | `detectNavigationDirectionCrashWithPageViewController:` | 无 |
|
||||
| 维度 | 读书 | ReadViewSDK | 核查 |
|
||||
|------|---------|-------------|------|
|
||||
| 翻页动画 | curl / slide / fade / none | 已有多种翻页模式 | ✅ 已实现 |
|
||||
| `UIPageViewController` crash patch | 3 个以上专项 patch | 已有 pageCurl fault detect + 异步重建 | ⚠️ 有差异/有问题 |
|
||||
| 预加载 | `WRForecastUtils` 预测 + 后台准备 | 已围绕当前页与预测方向预热相邻页视图 | ⚠️ 有差异/有问题 |
|
||||
| 预测翻页 | 基于用户方向预测预建内容 | 已按可见 spread 和预测方向预热缓存 | ⚠️ 有差异/有问题 |
|
||||
| 显示切换一致性 | 翻页模式/单双页/方向切换稳定恢复 | 已接入切换前记录 location、切换后按位置回落 | ⚠️ 有差异/有问题 |
|
||||
|
||||
**核查:** `❌ 未实现`。这一块目前仍没有 WXRead 那类 page controller crash patch。
|
||||
**结论:** Phase 6 已进入“有实现、继续细抠”的阶段,不再是空白;但离 WXRead 的完整宿主层稳定性还有差距。
|
||||
|
||||
---
|
||||
|
||||
## 7. CSS 资源文件对比
|
||||
## 7. 资源体系对比
|
||||
|
||||
### 微信读书 CSS 文件(`resources/css/`)
|
||||
### CSS
|
||||
|
||||
| 文件 | 职责 | ReadViewSDK 对应 |
|
||||
|------|------|-----------------|
|
||||
| `default.css` | 基础 HTML 标签样式(font 18px, line-height 30px) | `RDEPUBStyleSheetBuilder` 注入的基础 CSS |
|
||||
| `replace.css` | EPUB 书版排版(6 级标题、首字下沉、引用、图片居中) | `RDEPUBTextRendererSupport.replaceCSS()`(部分覆盖) |
|
||||
| `dark.css` | 暗黑主题(纯黑背景 + 灰色文字) | `RDEPUBReaderTheme` 的 CSS 计算属性 |
|
||||
| `replaceForLatinLanguageBook.css` | 拉丁语言字体 | 无对应 |
|
||||
| `replaceForMPChapter.css` | 公众号文章专用 | 无对应(非 EPUB 场景) |
|
||||
| 文件 | 读书职责 | ReadViewSDK 状态 | 核查 |
|
||||
|------|-------------|-----------------|------|
|
||||
| `default.css` | 基础 HTML 标签样式 | 已有等价基础 CSS | ⚠️ 有差异/有问题 |
|
||||
| `replace.css` | 标题、图片、引用、分页控制 | 已有等价 replace 层 | ⚠️ 有差异/有问题 |
|
||||
| `dark.css` | 暗色主题 | 已有 dark 层 | ⚠️ 有差异/有问题 |
|
||||
| `replaceForLatinLanguageBook.css` | 拉丁语言字体 | 无 | ❌ 未实现 |
|
||||
| `replaceForMPChapter.css` | 公众号文章专用 | EPUB 主链路不需要 | ❌ 未实现(暂不需要) |
|
||||
|
||||
**核查:**
|
||||
- `default.css` / `dark.css` / `replace.css` 思路已落地,但规则集合仍不是 WXRead 原文件的完整镜像,属于 `⚠️ 有差异/有问题`。
|
||||
- `replaceForLatinLanguageBook.css` 仍是 `❌ 未实现`。
|
||||
- `replaceForMPChapter.css` 属于非 EPUB 场景,当前可视为 `❌ 未实现(暂不需要)`。
|
||||
### JS
|
||||
|
||||
### 微信读书 JS 文件(`resources/js/`)
|
||||
| 文件 | 读书职责 | ReadViewSDK 状态 | 核查 |
|
||||
|------|-------------|-----------------|------|
|
||||
| `weread-highlighter.js` | Web 高亮引擎 | `epub-bridge.js` 已接住高亮/批注展示 | ⚠️ 有差异/有问题 |
|
||||
| `rangy-*` | 选区/高亮库 | CoreText 路径不需要,Web 路径也未采用 | ⚠️ 有差异/有问题 |
|
||||
| `cssInjector.js` | 动态 CSS 注入 | 现为原生侧静态注入 | ⚠️ 有差异/有问题 |
|
||||
| `WeReadApi.js` | JS-Native 桥接 | `window.RDReaderBridge` | ⚠️ 有差异/有问题 |
|
||||
|
||||
| 文件 | 职责 | ReadViewSDK 对应 |
|
||||
|------|------|-----------------|
|
||||
| `weread-highlighter.js` | Rangy 高亮引擎,5 种样式 | `epub-bridge.js` + `RDEPUBWebView+JavaScriptBridge.swift` |
|
||||
| `rangy-core.js` / `rangy-highlighter.js` / `rangy-textrange.js` | Rangy 选区/高亮库 | 无(CoreText 路径不需要) |
|
||||
| `Readability.js` | HTML 正文提取 | 无(EPUB spine 直接提供内容) |
|
||||
| `cssInjector.js` | 动态 CSS 注入/移除 | 无(静态注入) |
|
||||
| `WeReadApi.js` | JS-Native 桥接 | `epub-bridge.js`(`window.RDReaderBridge`) |
|
||||
|
||||
**核查:** 这一节整体仍然成立。WebView 路径没有按 WXRead 的 JS 资源体系一一复刻,属于 `⚠️ 有差异/有问题`,但对纯 EPUB CoreText 路径不是当前主阻塞。
|
||||
**结论:** 不建议也不应该把 WXRead 私有 JS/CSS 资源整包原样搬用;当前应继续走“能力等价、实现自有”的路线。
|
||||
|
||||
---
|
||||
|
||||
## 8. 缺失能力对比
|
||||
## 8. 缺失能力清单
|
||||
|
||||
| 能力 | 微信读书 | ReadViewSDK | 核查 | 当前优先级 |
|
||||
|------|---------|-------------|------|-----------|
|
||||
| CoreText 直接绘制 | `WRPageView.drawRect:` + `CTFrameDraw` | 已是页面级 CoreText 直绘,但选区/装饰层还未完全 CoreText 化 | ⚠️ 有差异/有问题 | P1 |
|
||||
| 分页引擎集成 | `WRCoreTextLayouter` 完整集成 | 已集成到 builder | ✅ 已实现 | - |
|
||||
| CSS `<link>` 处理 | 级联合并外部 CSS | 已处理 | ✅ 已实现 | - |
|
||||
| 5 层 CSS 级联 | default/replace/dark/epub/user | 已生成并注入 | ✅ 已实现 | - |
|
||||
| 分页缓存 | `WRChapterPageCount.currentCacheKeyWithBookId:` | 已有磁盘缓存 | ✅ 已实现 | - |
|
||||
| 字符级位置精度 | `WREpubPositionConverter` | progression 浮点值 | ❌ 未实现 | P2 |
|
||||
| 字体动态加载 | CDN + `WRFontsManager` | 仅系统字体 | ❌ 未实现 | P1(延迟) |
|
||||
| 繁简转换 | `WRReaderCht2sManager` | 无 | ❌ 未实现 | P3 |
|
||||
| TTS 朗读 | wxtts 引擎 + 位置标记 | 无 | ❌ 未实现 | P3 |
|
||||
| DRM | 逐章加密 + Keychain 密钥 | 无 | ❌ 未实现 | P3 |
|
||||
| 预加载 | `WRForecastUtils` 预测 + 后台下载 | 无 | ❌ 未实现 | P3 |
|
||||
| Apple Pencil | PencilKit + COS 云同步 | 无 | ❌ 未实现 | P3 |
|
||||
| 多栏排版 | `WRCoreTextLayoutConfig.columns/columnGap` | 无 | ❌ 未实现 | P3 |
|
||||
| 能力 | 核查 | 当前优先级 |
|
||||
|------|------|-----------|
|
||||
| 页面几何模型完全等价 `WRCoreTextLayoutFrame` | ⚠️ 有差异/有问题 | P1 |
|
||||
| `RDEPUBChapterData` 最终内聚 | ⚠️ 有差异/有问题 | P2 |
|
||||
| 完整字符级位置转换器 | ⚠️ 有差异/有问题 | P2 |
|
||||
| 翻页 crash patch 完整版 | ⚠️ 有差异/有问题 | P3 |
|
||||
| 预加载 | ⚠️ 有差异/有问题 | P3 |
|
||||
| 预测翻页 | ⚠️ 有差异/有问题 | P3 |
|
||||
| 显示切换一致性 | ⚠️ 有差异/有问题 | P3 |
|
||||
| 多栏排版 | ❌ 未实现 | P4 |
|
||||
| 字体动态加载 | ❌ 未实现 | P4 |
|
||||
| 繁简转换 | ❌ 未实现 | P4 |
|
||||
| TTS / DRM / Pencil | ❌ 未实现 | P4 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 优先级排序与 Roadmap 映射
|
||||
## 9. 收口路线(整合原修复计划)
|
||||
|
||||
| 优先级 | 问题 | 核查 | 对应 Phase / 建议 | 说明 |
|
||||
|--------|------|------|-------------------|------|
|
||||
| ~~P0~~ | 集成 `RDEPUBTextLayouter` 到 `RDEPUBTextBookBuilder` | ✅ 已完成 | 已落地 | 不再是待办 |
|
||||
| ~~P0~~ | CSS `<link>` 外部样式表处理 | ✅ 已完成 | 已落地 | 不再是待办 |
|
||||
| ~~P0~~ | 5 层 CSS 级联 | ✅ 已完成 | 已落地 | 不再是待办 |
|
||||
| ~~P0~~ | 分页缓存 | ✅ 已完成 | 已落地 | 不再是待办 |
|
||||
| **P1** | CoreText 原生选区 / hit test | ❌ 未实现 | 新增 phase | 当前仍主要依赖 `UITextView` |
|
||||
| **P1** | 标注/搜索独立 CGContext 装饰层 | ❌ 未实现 | 新增 phase | 当前仍用 attributedString 属性注入 |
|
||||
| **P1** | 页面几何与选区 overlay 收口 | ⚠️ 半成品 | 延续 page-geometry phase | `RDEPUBSelectionOverlayView` 仍未闭环 |
|
||||
| **P1** | inline attachment 细节对齐 | ⚠️ 已接近但仍需验书 | 延续 pagination/rendering phase | 尤其脚注图标、特殊 inline image |
|
||||
| **P1** | 字体系统 | ❌ 未实现 | 未来版本 | 内嵌固定字体集,延迟实现 |
|
||||
| **P2** | 位置精度提升 | ❌ 未实现 | 独立重构 | 字符级锚点 / 双向转换 |
|
||||
| **P2** | 章节数据模型内聚 | ❌ 未实现 | 独立重构 | WRChapterData 模式 |
|
||||
| **P3** | TTS / DRM / Pencil / 多栏 | ❌ 未实现 | 独立功能模块 | 后续迭代 |
|
||||
### 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. 微信读书关键类职责速查
|
||||
## 10. 读书关键类职责速查
|
||||
|
||||
| 类名 | 职责 | ReadViewSDK 对应 | 核查 |
|
||||
|------|------|-----------------|------|
|
||||
| `WRReaderViewController` | 阅读器主控制器(431 方法) | `RDEPUBReaderController` | ✅ 已有对应 |
|
||||
| `WRPageViewController` | 翻页控制器(含 3 个 crash patch) | `RDReaderView`(pageCurl 模式) | ⚠️ 有差异/无 crash patch |
|
||||
| `WRReaderViewController` | 阅读器主控制器 | `RDEPUBReaderController` | ✅ 已有对应 |
|
||||
| `WRPageViewController` | 翻页控制器 + crash patch | `RDReaderView` | ⚠️ 有差异/有问题 |
|
||||
| `WRPageView` | CoreText 直接绘制页面 | `RDEPUBTextContentView` + `RDEPUBDirectCoreTextPageView` | ✅ 已实现 |
|
||||
| `WREpubParser` | EPUB 解析 | `RDEPUBParser` | ✅ 已有对应 |
|
||||
| `WREpubTypesetter` | HTML → NSAttributedString(CSS 级联) | `RDEPUBDTCoreTextRenderer` | ✅ 已有对应 |
|
||||
| `WREpubTypesetter` | HTML → NSAttributedString(CSS 级联) | `RDEPUBDTCoreTextRenderer` | ✅ 已实现 |
|
||||
| `WRCoreTextLayouter` | CoreText 排版引擎 | `RDEPUBTextLayouter` | ✅ 已实现 |
|
||||
| `WRCoreTextLayoutFrame` | 排版帧(绘制/选区/搜索/装饰) | `RDEPUBTextLayoutFrame` | ⚠️ 绘制/分页接近,选区/装饰未闭环 |
|
||||
| `WRChapterData` | 章节数据模型(渲染+标注+目录一体) | `RDEPUBTextChapter` + `RDEPUBHighlight`(分散) | ❌ 未实现 |
|
||||
| `WRChapterPageCount` | 分页计算器(含缓存 key) | `RDEPUBTextBookBuilder` + `RDEPUBTextBookCache` | ✅ 已实现 |
|
||||
| `WREpubPositionConverter` | 字符级位置双向转换 | `RDEPUBTextBook.pageNumber(for:)`(精度较低) | ❌ 未实现 |
|
||||
| `WRBookmark` | 5 种标注类型统一模型 | `RDEPUBHighlight` + `RDEPUBBookmark` | ⚠️ 部分对应 |
|
||||
| `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 文件
|
||||
→ WREpubParser.parse (container.xml → OPF → spine)
|
||||
→ WREpubTypesetter (CSS 级联: default < replace < dark < epub < user)
|
||||
→ DTHTMLAttributedStringBuilder (HTML → NSAttributedString)
|
||||
→ WRCoreTextLayouter (CTFramesetter → CTFrame)
|
||||
→ WRChapterPageCount (分页 NSRange)
|
||||
→ WRPageView.drawRect (CTFrameDraw → CGContext)
|
||||
→ 屏幕显示
|
||||
```
|
||||
|
||||
### ReadViewSDK 当前(已按当前代码修正)
|
||||
|
||||
```
|
||||
EPUB 文件
|
||||
→ RDEPUBParser.parse (container.xml → OPF → spine)
|
||||
→ readingProfile 分流:
|
||||
-> RDEPUBParser.parse (container.xml -> OPF -> spine)
|
||||
-> readingProfile 分流:
|
||||
textReflowable:
|
||||
→ RDEPUBDTCoreTextRenderer (DTHTMLAttributedStringBuilder + 5 层 CSS + <link> CSS 内联)
|
||||
→ RDEPUBTextBookBuilder (rd_paginatedFrames + RDEPUBTextBookCache)
|
||||
→ RDEPUBTextContentView (页面级 CoreText 直绘 + UITextView 选区代理)
|
||||
-> RDEPUBDTCoreTextRenderer
|
||||
-> 5 层 CSS 级联
|
||||
-> <link> CSS 内联
|
||||
-> 自定义分页语义注入
|
||||
-> RDEPUBTextBookBuilder
|
||||
-> RDEPUBTextLayouter
|
||||
-> RDEPUBTextBookCache
|
||||
-> RDEPUBTextContentView
|
||||
-> RDEPUBDirectCoreTextPageView
|
||||
-> RDEPUBPageInteractionController
|
||||
-> RDEPUBSelectionOverlayView
|
||||
webInteractive:
|
||||
→ RDEPUBPaginator (离屏 WKWebView 分页)
|
||||
→ RDEPUBWebContentView (WKWebView 渲染)
|
||||
-> RDEPUBPaginator
|
||||
-> RDEPUBWebContentView
|
||||
-> epub-bridge.js
|
||||
webFixedLayout:
|
||||
→ RDEPUBWebContentView (WKWebView + fixed-layout template)
|
||||
-> RDEPUBWebContentView
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*分析基础:微信读书 v10.0.3 (Build 79) 逆向工程文档*
|
||||
*产出:10 个维度对比、14 项差距识别、优先级排序*
|
||||
*分析基础:读书 v10.0.3 (Build 79) 逆向文档*
|
||||
*当前代码核查日期:2026-05-24*
|
||||
|
||||
Reference in New Issue
Block a user