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

16 KiB
Raw Blame History

架构对比分析:微信读书 vs ReadViewSDK

基于微信读书 v10.0.3 (Build 79) 逆向工程,对比当前 ReadViewSDK 项目架构差距。 分析日期: 2026-05-23 当前代码核查日期: 2026-05-24 参考文档: Doc/WXRead/decompiled-doc.mdDoc/WXRead/resources-doc.mdDoc/WXRead/微信读书EPUB阅读器实现架构.md

标注说明:

  • ✅ 已实现:当前代码已经按接近 WXRead 的路径落地
  • ⚠️ 有差异/有问题:已经实现一部分,但仍与 WXRead 有结构差异,或者当前实现仍有已知问题
  • ❌ 未实现:当前代码中仍缺失

核心结论

微信读书使用双渲染引擎架构Path A: 原生 CoreText / Path B: WebView。ReadViewSDK 当前也已经是 CoreText 文本页 + WebView 双路径,但文本页仍保留 UITextView 作为选区代理层,因此“页面绘制”已接近 WXRead“选区/装饰/命中测试”仍未完全收口到同一套 CoreText 页面模型。

核查摘要

已按 WXRead 路径落地

  • 文本页已经改成页面级 CoreText 直绘,不再是单纯 UITextView 展示。
  • RDEPUBTextLayouter 已经接入 RDEPUBTextBookBuilder / RDPlainTextBookBuilder
  • 4 级语义断页、avoidPageBreakInside 页尾回退、分页缓存都已经落地。
  • 5 层 CSS 级联和 EPUB <link> 外部样式表内联都已经落地。

仍未实现

  • CoreText 原生 hit test / 选区命中。
  • 独立 CGContext 标注绘制层与搜索高亮层。
  • WXRead 式字符级位置模型(fileIndex + row + column)。
  • WRChapterData 一体化章节数据模型。
  • UIPageViewController crash patch、多栏、字体动态加载、TTS/DRM 等外围能力。

⚠️ 已实现但仍有问题/差异

  • 当前文本页虽然已直绘,但仍依赖 UITextView 代理选区,页面几何模型没有完全统一。
  • RDEPUBSelectionOverlayView 仍是半成品,尚未形成完整可用的 CoreText 选区/装饰 overlay。
  • 高亮、下划线、搜索命中仍主要靠 attributedString 属性注入,而不是 WXRead 那种页面装饰绘制。
  • inline attachment 已按 WXRead 路径收敛,但仍需要继续结合问题书样验证特殊图片、脚注图标和页内基线细节。

1. 渲染路径对比

维度 微信读书 ReadViewSDK 核查
EPUB 文本渲染 WRPageView.drawRect:CTFrameDraw 到 CGContext RDEPUBTextContentViewRDEPUBDirectCoreTextPageView.draw(_:) + DTCoreTextLayoutFrame.draw(in:) 页面级直绘 已实现
WebView 路径 WKWebView公众号/文集文章) WKWebViewinteractive/fixed-layout EPUB 已实现
文本选区 CTLineGetStringIndexForPosition 坐标级 hit test 仍主要依赖 UITextView 代理选区;RDEPUBSelectionOverlayView 仍是半成品 ⚠️ 有差异/有问题
标注绘制 CTFrame 层叠加绘制CGContext 高亮/下划线仍主要通过 attributedString 属性注入,不是独立 CGContext 装饰层 ⚠️ 有差异/有问题
搜索高亮 WRCoreTextLayoutFrame.highlightSearchResults: 直接绘制 仍是 attributedString 注入临时高亮属性 ⚠️ 有差异/有问题

核查结论: 这段原分析已经过时。当前文本页的底层排版和绘制已经切到 CoreText 页面直绘,但“命中测试、标注装饰层、搜索高亮层”还没有完全像 WXRead 那样归并到同一套页面级 CoreText 几何模型。


2. 分页引擎对比

维度 微信读书 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 处理 已实现

核查结论: 这段原判断已经过时。RDEPUBTextBookBuilderRDPlainTextBookBuilder 已经走 rd_paginatedFrames(size:fragmentOffsets:),不再是“能力已写但未接入”的状态。


3. CSS 处理对比

维度 微信读书 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(断页避让) 已部分支持:pageRelateavoidPageBreakInside、attachment placement 推断;但并非完整 WeRead 属性集 ⚠️ 有差异/有问题
CSS 层级模型 已定义 RDEPUBTextStyleSheetPackage/RDEPUBTextStyleSheetLayer5 种 kind但未完整使用 已实际使用;但和 WXRead 资源体系仍不是同一批 CSS 文件/规则 ⚠️ 有差异/有问题

核查结论: “未处理 <link> 外部 CSS” 这一条已经不成立;但外部 CSS 即使已被内联,规则兼容度和 WXRead 自带 replace/default 体系仍可能存在差异。


4. 位置模型对比

维度 微信读书 ReadViewSDK
位置模型 WREpubPositionConverter(fileIndex, row, column) 三元组 RDEPUBLocationhref + progression 浮点值
精度 字符级精度 章节内比例精度 (0..1)
索引构建 initIndices 预建全书字符索引表 无索引,每次实时计算
双向转换 stringRangeFromFileRange: / fileIndexForCharacterPosition: / localOffsetInFileAtIndex:forGlobalPosition: RDEPUBTextBook.pageNumber(for:) / location(forPageNumber:)

影响分析: progression 是 0..1 浮点值,在跨字号/行距重排后能保持大致位置,但无法精确到字符。微信读书的三元组提供字符级精度,适合精确标注恢复。当前 progression 模式对大部分场景够用,但在密集标注场景下可能出现标注漂移。

核查: ❌ 未实现。当前位置模型仍然不是 WXRead 的字符级三元组。


5. 章节数据模型对比

维度 微信读书 ReadViewSDK
核心模型 WRChapterData — 一个对象承载渲染结果 + 标注 + 目录 + 免费试读截断 RDEPUBTextChapter + RDEPUBHighlight + EPUBChapterInfo 分散在多处
标注内聚 addHighlightInRange: / addUnderLineToAttributedString: 直接在 chapterData 上操作 标注在 RDEPUBReaderController 层管理,与章节数据分离
目录生成 WRChapterData.generateOutlineContents — 从渲染结果反向提取目录 目录从 NCX/Nav 独立解析,不与渲染数据关联

核查: ❌ 未实现。章节数据模型仍未收敛成 WXRead 的 WRChapterData 一体化模式。


6. 翻页控制器对比

维度 微信读书 ReadViewSDK
翻页动画 4 种curl / slide / fade / none 4 种pageCurl / horizontalScroll / verticalScroll / horizontalCoverScroll
UIPageViewController 崩溃修复 3 个 patch 方法处理已知 Apple bug导航方向崩溃、子 VC 丢失、快速翻页动画故障) 无 crash patch
导航方向检测 detectNavigationDirectionCrashWithPageViewController:

核查: ❌ 未实现。这一块目前仍没有 WXRead 那类 page controller crash patch。


7. CSS 资源文件对比

微信读书 CSS 文件(resources/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 场景)

核查:

  • default.css / dark.css / replace.css 思路已落地,但规则集合仍不是 WXRead 原文件的完整镜像,属于 ⚠️ 有差异/有问题
  • replaceForLatinLanguageBook.css 仍是 ❌ 未实现
  • replaceForMPChapter.css 属于非 EPUB 场景,当前可视为 ❌ 未实现(暂不需要)

微信读书 JS 文件(resources/js/

文件 职责 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.jswindow.RDReaderBridge

核查: 这一节整体仍然成立。WebView 路径没有按 WXRead 的 JS 资源体系一一复刻,属于 ⚠️ 有差异/有问题,但对纯 EPUB CoreText 路径不是当前主阻塞。


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

9. 优先级排序与 Roadmap 映射

优先级 问题 核查 对应 Phase / 建议 说明
P0 集成 RDEPUBTextLayouterRDEPUBTextBookBuilder 已完成 已落地 不再是待办
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 / 多栏 未实现 独立功能模块 后续迭代

10. 微信读书关键类职责速查

类名 职责 ReadViewSDK 对应 核查
WRReaderViewController 阅读器主控制器431 方法) RDEPUBReaderController 已有对应
WRPageViewController 翻页控制器(含 3 个 crash patch RDReaderViewpageCurl 模式) ⚠️ 有差异/无 crash patch
WRPageView CoreText 直接绘制页面 RDEPUBTextContentView + RDEPUBDirectCoreTextPageView 已实现
WREpubParser EPUB 解析 RDEPUBParser 已有对应
WREpubTypesetter HTML → NSAttributedStringCSS 级联) RDEPUBDTCoreTextRenderer 已有对应
WRCoreTextLayouter CoreText 排版引擎 RDEPUBTextLayouter 已实现
WRCoreTextLayoutFrame 排版帧(绘制/选区/搜索/装饰) RDEPUBTextLayoutFrame ⚠️ 绘制/分页接近,选区/装饰未闭环
WRChapterData 章节数据模型(渲染+标注+目录一体) RDEPUBTextChapter + RDEPUBHighlight(分散) 未实现
WRChapterPageCount 分页计算器(含缓存 key RDEPUBTextBookBuilder + RDEPUBTextBookCache 已实现
WREpubPositionConverter 字符级位置双向转换 RDEPUBTextBook.pageNumber(for:)(精度较低) 未实现
WRBookmark 5 种标注类型统一模型 RDEPUBHighlight + RDEPUBBookmark ⚠️ 部分对应
DTHTMLAttributedStringBuilder HTML DOM → NSAttributedString 同(复用 DTCoreText 已实现

数据流对比

微信读书

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 分流:
      textReflowable:
        → RDEPUBDTCoreTextRenderer (DTHTMLAttributedStringBuilder + 5 层 CSS + <link> CSS 内联)
        → RDEPUBTextBookBuilder (rd_paginatedFrames + RDEPUBTextBookCache)
        → RDEPUBTextContentView (页面级 CoreText 直绘 + UITextView 选区代理)
      webInteractive:
        → RDEPUBPaginator (离屏 WKWebView 分页)
        → RDEPUBWebContentView (WKWebView 渲染)
      webFixedLayout:
        → RDEPUBWebContentView (WKWebView + fixed-layout template)

分析基础:微信读书 v10.0.3 (Build 79) 逆向工程文档 产出10 个维度对比、14 项差距识别、优先级排序