Files
ReadViewSDK/Doc/架构对比分析_WXRead_vs_ReadViewSDK.md
T
2026-05-26 09:19:37 +08:00

15 KiB
Raw Blame History

架构对比分析:读书 vs ReadViewSDK

基于读书 v10.0.3 (Build 79) 逆向文档,与当前 ReadViewSDK 代码在 2026-05-24 的核查结果整合。 本文档已吸收原 WXRead剩余问题修复计划.md 的阶段方案,后续以本文档作为单一真值。

标注说明:

  • ✅ 已实现:当前代码已经按接近 WXRead 的路径落地
  • ⚠️ 有差异/有问题:已经实现一部分,但仍与 WXRead 有结构差异,或仍有已知问题
  • ❌ 未实现:当前代码中仍缺失
  • ❌ 明确不实现:经确认不纳入当前 EPUB 阅读器复刻范围

核心结论

ReadViewSDK 当前已经不是“旧 UITextView 阅读器”了,文本主链路已经收口到:

  • CoreText 页面直绘
  • RDEPUBTextLayouter 分页
  • 5 层 CSS 级联
  • <link> 样式表内联
  • 页面级 hit test / 选区 / 高亮 / 批注
  • 字符锚点与 fileIndex/row/column 语义的完整位置模型

核查结论:在当前约定范围内,ReadViewSDK 已经完成 EPUB 阅读器对 WXRead 文档主链路的复刻。当前文档里不再保留主链路级 ⚠️ 项,剩余仅有两类:

  1. replaceForMPChapter.css 这类公众号文章专用资源,对 EPUB 主链路不适用
  2. 繁简转换、TTS / DRM / Pencil 这类已明确排除在本次复刻范围之外的外围能力

核查摘要

✅ 已实现

  • 文本页已经改成页面级 CoreText 直绘。
  • RDEPUBTextLayouter 已接入 RDEPUBTextBookBuilder / RDPlainTextBookBuilder。
  • 4 级语义断页、avoidPageBreakInside 页尾回退、分页缓存都已经落地。
  • 5 层 CSS 级联和 EPUB <link> 外部样式表内联都已经落地。
  • CoreText 页面 hit test、长按选区、菜单锚点、复制/高亮/批注主链路已经接入页面几何。
  • CoreText 路径的高亮、注释、搜索命中已经走页面装饰层,而不是继续改正文布局真值。
  • WebView 路径的标注绘制、搜索高亮已经改成“JS 产出 rect,原生 overlay 负责 CGContext 绘制”,不再依赖 DOM 包裹着色。
  • 分页器已经补上 inline footnote attachment 不整段挪页、标题 keepWithNext、weread-page-relate 页首借行这几类 WXRead 风格规则。
  • 章节尾部“仅空白/段落分隔符”的尾页丢弃,以及极短尾页回并已经落地,宝山辽墓材料与释读 第 31 页空白问题已修复。
  • RDEPUBTextLayoutConfig 已补齐到 WXRead 同级配置面:frameWidth/frameHeight/edgeInsets/numberOfColumns/columnGap/avoidOrphans/avoidWidows/hyphenation,并已接入分页入口与缓存键。
  • RDEPUBChapterData 已统一承载章节分页结果、位置查询、搜索/高亮回查与目录语义,章节模型主链路已经收口。

⚠️ 有差异/有问题

  • 无主链路遗留项;当前仅保留明确不适用或明确不实现的范围说明。

❌ 未实现

  • 繁简转换(明确不实现)
  • TTS / DRM / Pencil(明确不实现)

1. 渲染路径对比

维度 读书 ReadViewSDK 核查
EPUB 文本渲染 WRPageView.drawRect: → CTFrameDraw 到 CGContext RDEPUBTextContentView → RDEPUBDirectCoreTextPageView.draw(_:) + DTCoreTextLayoutFrame.draw(in:) 页面级直绘 ✅ 已实现
WebView 路径 WKWebView(公众号/文集文章) WKWebView(interactive/fixed-layout EPUB) ✅ 已实现
文本选区 CTLineGetStringIndexForPosition 坐标级 hit test RDEPUBPageInteractionController + RDEPUBSelectionOverlayView 已接入主链路 ✅ 已实现
标注绘制 CTFrame 层叠加绘制(CGContext) CoreText / WebView 两条链路都已收口到原生页面装饰层绘制 ✅ 已实现
搜索高亮 WRCoreTextLayoutFrame.highlightSearchResults: 直接绘制 CoreText / WebView 两条链路都已统一为原生页面装饰对象绘制 ✅ 已实现

结论: 渲染层里“页面级绘制 + 页面装饰对象收口”这一块已经完成,页面几何回查也已经补到与 WXRead 同一路径的页面快照闭环。


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、断页相关私有属性 已按 WXRead 语义接入 wr-vertical-center-style、weread-page-relate、page-break-* / break-*、avoidPageBreakInside 与 attachment placement ✅ 已实现
WXRead 私有 CSS 文件 使用 WeRead 自带 default/replace/dark/... 已把 default/replace/dark 作为 SDK 内置资源镜像注入 5 层级联 ✅ 已实现
replaceForLatinLanguageBook.css 拉丁语言专项字体规则 已按章节语言 / 正文拉丁字符占比自动切换 Latin replace 层 ✅ 已实现

结论: CSS 主机制、私有资源层和拉丁语言分支都已经按 WXRead 路径收口;这一节当前不再是剩余差距。


4. 位置模型对比

维度 读书 ReadViewSDK 核查
主模型 WREpubPositionConverter (fileIndex, row, column) RDEPUBTextPositionConverter + RDEPUBTextAnchor/rangeAnchor,已补齐全书字符位置与页码双向转换 ✅ 已实现
恢复精度 字符级双向恢复 当前位置、选区、高亮、搜索命中都已优先走 rangeAnchor / fileIndex-row-column 恢复,progression 仅作回退 ✅ 已实现
旧数据兼容 兼容历史位置模型 已兼容旧 spineIndex 等旧字段解码 ✅ 已实现
全量双向转换 文件位置 <-> 全书字符位置 <-> 页码 RDEPUBTextPositionConverter / RDEPUBTextIndexTable 已补齐 fileIndex,row,column <-> chapterOffset <-> globalOffset <-> pageNumber <-> location ✅ 已实现

结论: 位置模型这条链路已经按 WXRead 的 PositionConverter 思路收口,当前不再是位置恢复能力缺失的问题。


5. 章节数据模型对比

维度 读书 ReadViewSDK 核查
核心模型 WRChapterData 一体化承载渲染结果 + 标注 + 搜索 + 目录 RDEPUBChapterData 现已统一承载章节分页结果、位置查询、搜索/高亮回查与目录语义 ✅ 已实现
页内高亮查询 章节对象直接提供 RDEPUBChapterData.highlights(on:from:) 已提供 ✅ 已实现
页内搜索查询 章节对象直接提供 RDEPUBChapterData.searchResults(on:from:) 已提供 ✅ 已实现
页码/位置查询 章节对象内聚 RDEPUBChapterData 已统一提供 chapter/page/location/searchMatch 双向回查 ✅ 已实现
目录与章节语义 基于章节数据统一管理 已由 RDEPUBChapterData 统一提供 TOC 命中、主目录项解析与章节页码定位 ✅ 已实现

结论: 章节对象这条链路已经按 WXRead 的 WRChapterData 思路收口,章节分页、位置、搜索、高亮与目录语义现在都围绕 RDEPUBChapterData 统一组织。


6. 翻页控制器与宿主层对比

维度 读书 ReadViewSDK 核查
翻页动画 curl / slide / fade / none 已有多种翻页模式 ✅ 已实现
UIPageViewController crash patch 3 个以上专项 patch 已补 pageCurl 异常检测、转场期间跳转排队、动画后校验与异步重建恢复 ✅ 已实现
预加载 WRForecastUtils 预测 + 后台准备 已围绕当前页、当前 spread 和可见方向预热相邻页视图,并在布局环境变化时裁剪缓存 ✅ 已实现
预测翻页 基于用户方向预测预建内容 已按手势/滚动方向和 pending target 预测下一屏,优先向预测方向额外预热一屏 ✅ 已实现
显示切换一致性 翻页模式/单双页/方向切换稳定恢复 已补切换前位置快照、切换后按 location 恢复,以及横竖屏过渡期间的延迟恢复链路 ✅ 已实现

结论: 翻页控制器与宿主层这条链路已经按 WXRead 的主实现思路收口,pageCurl 稳定性、预测预加载和显示切换恢复现在都走统一闭环。


7. 资源体系对比

CSS

文件 读书职责 ReadViewSDK 状态 核查
default.css 基础 HTML 标签样式 已以内置资源镜像接入 ✅ 已实现
replace.css 标题、图片、引用、分页控制 已以内置资源镜像接入 ✅ 已实现
dark.css 暗色主题 已以内置资源镜像接入,并保留主题色覆盖层 ✅ 已实现
replaceForLatinLanguageBook.css 拉丁语言字体 已接入章节语言自动切换 ✅ 已实现
replaceForMPChapter.css 公众号文章专用 EPUB 主链路不需要 ✅ EPUB 主链路不适用

JS

文件 读书职责 ReadViewSDK 状态 核查
weread-highlighter.js Web 高亮引擎 epub-bridge.js 现只负责 rect 解析与桥接,最终由原生 overlay 绘制 ✅ 已实现
rangy-* 选区/高亮库 CoreText 路径不需要;webInteractive / webFixedLayout 已接入 rangy-core.js + rangy-serializer.js 等价层,统一负责 DOM range 序列化与 iframe 文档回放 ✅ 已实现
cssInjector.js 动态 CSS 注入 已接入 cssInjector.js,由 WeReadApi 在 webInteractive / webFixedLayout 路径按需向主文档和 iframe 文档注入主题/分页样式 ✅ 已实现
WeReadApi.js JS-Native 桥接 已接入 WeReadApi.js,并由 window.WeReadApi 统一封装分页、主题、搜索、高亮和 progression bridge ✅ 已实现

结论: CoreText 路径不需要 rangy / cssInjector / WeReadApi;但 webInteractive 和 webFixedLayout 两条 Web 路径都需要。当前资源体系已经把这套 Web 资源层完整接回 SDK,JS 侧职责也已按 WXRead 思路收口。


8. 缺失能力清单

能力 核查 当前优先级
页面几何模型完全等价 WRCoreTextLayoutFrame ✅ 已实现 -
WRBookmark 统一标注模型 ✅ 已实现 -
多栏排版 ✅ 已实现 -
字体动态加载 ✅ 已实现 -
繁简转换 ❌ 明确不实现 -
TTS / DRM / Pencil ❌ 明确不实现 -

9. 收口路线(整合原修复计划)

P1:页面几何与分页行为闭环

  • RDEPUBPageLayoutSnapshot 已补齐 line/run/attachment/contentBounds 与 absoluteRange 命中闭环
  • overlay / decoration / selection 回查已经统一到页面快照层
  • 问题书分页细节已回收到现有分页规则,不再构成架构缺口

当前状态:✅ 已实现

P2:位置模型与章节数据内聚

  • rangeAnchor / fileIndex/row/column 双向位置转换已完成
  • RDEPUBChapterData 章节语义内聚已完成
  • RDEPUBAnnotation 已把书签/高亮统一收口到单一标注语义层

当前状态:✅ 已实现

P3:宿主层稳定性

  • 宿主层 pageCurl 修复、预测预加载和显示切换恢复已完成
  • 剩余工作不再是主链路缺失,而是问题书和极端交互场景的持续回归

当前状态:✅ 已实现

P4:外围能力

  • 多栏阅读器开关 / UI 暴露已完成
  • EPUB 内嵌字体动态注册已完成
  • 繁简转换、TTS / DRM / Pencil 明确不实现,不纳入收口范围

当前状态:✅ 范围内已实现


10. 读书关键类职责速查

类名 职责 ReadViewSDK 对应 核查
WRReaderViewController 阅读器主控制器 RDEPUBReaderController ✅ 已有对应
WRPageViewController 翻页控制器 + crash patch RDReaderView ✅ 已实现
WRPageView CoreText 直接绘制页面 RDEPUBTextContentView + RDEPUBDirectCoreTextPageView ✅ 已实现
WREpubTypesetter HTML → NSAttributedString(CSS 级联) RDEPUBDTCoreTextRenderer ✅ 已实现
WRCoreTextLayouter CoreText 排版引擎 RDEPUBTextLayouter ✅ 已实现
WRCoreTextLayoutFrame 排版帧(绘制/选区/搜索/装饰) RDEPUBTextLayoutFrame + snapshot/interaction/overlay ✅ 已实现
WRChapterData 章节数据模型 RDEPUBChapterData ✅ 已实现
WRChapterPageCount 分页计算 + 缓存 key RDEPUBTextBookBuilder + RDEPUBTextBookCache ✅ 已实现
WREpubPositionConverter 字符级位置双向转换 RDEPUBTextPositionConverter + RDEPUBTextIndexTable ✅ 已实现
WRBookmark 标注统一模型 RDEPUBAnnotation(兼容 RDEPUBHighlight / RDEPUBBookmark) ✅ 已实现
DTHTMLAttributedStringBuilder HTML DOM → NSAttributedString 同(复用 DTCoreText) ✅ 已实现

11. 当前数据流

EPUB 文件
  -> RDEPUBParser.parse (container.xml -> OPF -> spine)
  -> readingProfile 分流:
      textReflowable:
        -> RDEPUBDTCoreTextRenderer
           -> 5 层 CSS 级联
           -> <link> CSS 内联
           -> 自定义分页语义注入
        -> RDEPUBTextBookBuilder
           -> RDEPUBTextLayouter
           -> RDEPUBTextBookCache
        -> RDEPUBTextContentView
           -> RDEPUBDirectCoreTextPageView
           -> RDEPUBPageInteractionController
           -> RDEPUBSelectionOverlayView
      webInteractive:
        -> RDEPUBPaginator
        -> RDEPUBWebContentView
        -> rangy-core.js / rangy-serializer.js
        -> cssInjector.js
        -> WeReadApi.js
        -> epub-bridge.js
      webFixedLayout:
        -> RDEPUBWebContentView
        -> rangy-core.js / rangy-serializer.js
        -> cssInjector.js
        -> WeReadApi.js
        -> epub-bridge.js

分析基础:读书 v10.0.3 (Build 79) 逆向文档 当前代码核查日期:2026-05-24