Files
ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBPreferences.swift
T
shenandshen 6f75b083f7 feat: EPUB 阅读器搜索、选中注释、书签 chrome 状态及大量重构优化
- 新增 RDEPUBReaderSearchCoordinator 与 RDEPUBSelectionState 管理搜索和选中状态
- 新增 BookmarkChromeStateTests、NavigationBackwardTests、SelectionAnnotateTests 等 UI 测试
- 新增多个边界测试 epub 样本(损坏结构、空归档、缺失文件、流式外链验证)
- 重构阅读器 chrome 状态管理,统一 tool bar 与 search bar 交互
- 优化大书分页缓存策略(RDEPUBChapterSummaryDiskCache、RDEPUBPageCountCache)
- 移除废弃的 RDEPUBLocationConverter 和 RDEPUBPageBreakPolicy
- 更新 epub-bridge.js 与 JS bridge 通信协议
- 全面更新现有 UI 测试以适配新的 helper 和状态管理
2026-06-13 22:48:56 +08:00

115 lines
4.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
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.
// RDEPUBPreferences.swift
// EPUB 阅读偏好设置
// 封装字号、行高、内容内边距、主题颜色、固定版式适配模式等展示参数,
// 并提供从偏好设置生成渲染请求和展示样式的便捷方法。
import UIKit
/// EPUB 阅读偏好设置,包含所有影响渲染效果的展示参数
public struct RDEPUBPreferences: Equatable {
/// 字体大小(pt
public var fontSize: CGFloat
/// 行高倍数(如 1.5 表示 1.5 倍行高)
public var lineHeightMultiple: CGFloat
/// 重排模式下的内容内边距
public var reflowableContentInsets: UIEdgeInsets
/// 固定版式下的内容内边距
public var fixedContentInset: UIEdgeInsets
/// 主题背景色(CSS 颜色值,如 "#FFFFFF"
public var themeBackgroundColor: String?
/// 主题文字色(CSS 颜色值)
public var themeTextColor: String?
/// 固定版式背景色
public var fixedBackgroundColor: String?
/// 固定版式适配模式(page/width/height/contain/cover
public var fixedLayoutFit: RDEPUBFixedLayoutFit
/// 固定版式双页展开模式(never/always/automatic
public var fixedLayoutSpreadMode: RDEPUBFixedLayoutSpreadMode
/// 多栏排版栏数
public var numberOfColumns: Int
/// 多栏排版栏间距
public var columnGap: CGFloat
public init(
fontSize: CGFloat,
lineHeightMultiple: CGFloat,
reflowableContentInsets: UIEdgeInsets,
fixedContentInset: UIEdgeInsets,
numberOfColumns: Int = 1,
columnGap: CGFloat = 20,
themeBackgroundColor: String? = nil,
themeTextColor: String? = nil,
fixedBackgroundColor: String? = nil,
fixedLayoutFit: RDEPUBFixedLayoutFit = .page,
fixedLayoutSpreadMode: RDEPUBFixedLayoutSpreadMode = .automatic
) {
self.fontSize = fontSize
self.lineHeightMultiple = lineHeightMultiple
self.reflowableContentInsets = reflowableContentInsets
self.fixedContentInset = fixedContentInset
self.numberOfColumns = max(1, numberOfColumns)
self.columnGap = max(0, columnGap)
self.themeBackgroundColor = themeBackgroundColor
self.themeTextColor = themeTextColor
self.fixedBackgroundColor = fixedBackgroundColor
self.fixedLayoutFit = fixedLayoutFit
self.fixedLayoutSpreadMode = fixedLayoutSpreadMode
}
/// 从偏好设置生成重排模式的展示样式
public func presentationStyle(viewportSize: CGSize) -> RDEPUBPresentationStyle {
RDEPUBPresentationStyle(
viewportSize: viewportSize,
contentInsets: reflowableContentInsets,
fontSize: fontSize,
lineHeightMultiple: lineHeightMultiple,
numberOfColumns: numberOfColumns,
columnGap: columnGap,
themeBackgroundColor: themeBackgroundColor,
themeTextColor: themeTextColor
)
}
/// 根据页面和偏好设置生成对应的渲染请求(自动区分固定版式和重排)
public func renderRequest(
for page: EPUBPage,
publication: RDEPUBPublication,
viewportSize: CGSize,
targetLocation: RDEPUBLocation? = nil,
targetHighlightRangeInfo: String? = nil,
highlights: [RDEPUBHighlight] = [],
searchPresentation: RDEPUBSearchPresentation? = nil
) -> RDEPUBRenderRequest? {
if publication.layout == .fixed, let fixedSpread = page.fixedSpread {
return .fixed(
RDEPUBFixedRenderRequest(
spread: fixedSpread,
viewportSize: viewportSize,
contentInset: fixedContentInset,
backgroundColorCSS: fixedBackgroundColor,
fit: fixedLayoutFit,
searchPresentation: searchPresentation
)
)
}
guard publication.spine.indices.contains(page.spineIndex) else {
return nil
}
return .reflowable(
RDEPUBReflowableRenderRequest(
spineIndex: page.spineIndex,
href: publication.spine[page.spineIndex].href,
pageIndex: page.pageIndexInChapter,
totalPagesInChapter: page.totalPagesInChapter,
presentation: presentationStyle(viewportSize: viewportSize),
targetLocation: targetLocation,
targetHighlightRangeInfo: targetHighlightRangeInfo,
highlights: highlights,
searchPresentation: searchPresentation
)
)
}
}