Files
ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBRenderRequest.swift
T
2026-05-26 09:19:37 +08:00

182 lines
6.0 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.
//
// RDEPUBRenderRequest.swift
// RDReaderView
//
// EPUBCore 层渲染请求模型定义文件。
// 包含渲染所需的展示样式(PresentationStyle)、可重排/固定版式渲染请求(RenderRequest)、
// 固定版式适配模式(Fit)和 Spread 模式(SpreadMode)。
// 由 RDEPUBPreferences 构建,传递给 RDEPUBWebView 执行渲染。
//
import UIKit
/// 固定版式页面适配模式
/// - auto: 自动选择最佳适配策略
/// - page: 适配整页(缩放至屏幕大小)
/// - width: 适配宽度(按宽度等比缩放)
public enum RDEPUBFixedLayoutFit: String, Codable {
case auto
case page
case width
}
/// 固定版式 Spread(双页)显示模式
/// - automatic: 根据设备方向和屏幕尺寸自动判断
/// - always: 始终启用双页显示
/// - never: 始终单页显示
public enum RDEPUBFixedLayoutSpreadMode: String, Codable {
case automatic
case always
case never
}
/// 渲染展示样式,WebView 和 Paginator 共用的视觉参数
/// 由 RDEPUBPreferences 根据用户设置构建
public struct RDEPUBPresentationStyle: Equatable {
/// 视口尺寸(容器的可见区域大小)
public var viewportSize: CGSize
/// 内容内边距(上下左右的安全区域偏移)
public var contentInsets: UIEdgeInsets
/// 字号(pt
public var fontSize: CGFloat
/// 行距倍数(1.0 为默认行距)
public var lineHeightMultiple: CGFloat
/// 栏数,对标 WXRead 的多栏分页配置
public var numberOfColumns: Int
/// 栏间距,对标 WXRead 的 columnGap
public var columnGap: CGFloat
/// 主题背景色(CSS 颜色值,如 "#FFFFFF"
public var themeBackgroundColor: String?
/// 主题文字色(CSS 颜色值,如 "#000000"
public var themeTextColor: String?
public init(
viewportSize: CGSize,
contentInsets: UIEdgeInsets,
fontSize: CGFloat,
lineHeightMultiple: CGFloat,
numberOfColumns: Int = 1,
columnGap: CGFloat = 20,
themeBackgroundColor: String? = nil,
themeTextColor: String? = nil
) {
self.viewportSize = viewportSize
self.contentInsets = contentInsets
self.fontSize = fontSize
self.lineHeightMultiple = lineHeightMultiple
self.numberOfColumns = max(1, numberOfColumns)
self.columnGap = max(0, columnGap)
self.themeBackgroundColor = themeBackgroundColor
self.themeTextColor = themeTextColor
}
}
/// 可重排内容渲染请求,包含加载和渲染一个 reflowable spine 项所需的全部参数
public struct RDEPUBReflowableRenderRequest: Equatable {
/// spine 索引
public var spineIndex: Int
/// 资源路径
public var href: String
/// 目标页在章节中的索引
public var pageIndex: Int
/// 该章节的总页数
public var totalPagesInChapter: Int
/// 展示样式
public var presentation: RDEPUBPresentationStyle
/// 目标跳转位置(用于恢复阅读位置或锚点跳转)
public var targetLocation: RDEPUBLocation?
/// 高亮列表
public var highlights: [RDEPUBHighlight]
/// 搜索结果展示信息
public var searchPresentation: RDEPUBSearchPresentation?
public init(
spineIndex: Int,
href: String,
pageIndex: Int,
totalPagesInChapter: Int,
presentation: RDEPUBPresentationStyle,
targetLocation: RDEPUBLocation? = nil,
highlights: [RDEPUBHighlight] = [],
searchPresentation: RDEPUBSearchPresentation? = nil
) {
self.spineIndex = spineIndex
self.href = href
self.pageIndex = pageIndex
self.totalPagesInChapter = totalPagesInChapter
self.presentation = presentation
self.targetLocation = targetLocation
self.highlights = highlights
self.searchPresentation = searchPresentation
}
}
/// 固定版式渲染请求,包含加载和渲染一个 fixed spread 所需的全部参数
public struct RDEPUBFixedRenderRequest: Equatable {
/// 要渲染的 spread(包含 1-2 个资源)
public var spread: EPUBFixedSpread
/// 视口尺寸
public var viewportSize: CGSize
/// 内容内边距
public var contentInset: UIEdgeInsets
/// 背景色 CSS 值
public var backgroundColorCSS: String?
/// 页面适配模式(auto/page/width
public var fit: RDEPUBFixedLayoutFit
/// 搜索结果展示信息
public var searchPresentation: RDEPUBSearchPresentation?
public init(
spread: EPUBFixedSpread,
viewportSize: CGSize,
contentInset: UIEdgeInsets,
backgroundColorCSS: String? = nil,
fit: RDEPUBFixedLayoutFit = .page,
searchPresentation: RDEPUBSearchPresentation? = nil
) {
self.spread = spread
self.viewportSize = viewportSize
self.contentInset = contentInset
self.backgroundColorCSS = backgroundColorCSS
self.fit = fit
self.searchPresentation = searchPresentation
}
}
/// 渲染请求枚举,统一可重排和固定版式两种渲染模式
/// RDEPUBWebView 根据此请求类型选择对应的加载和渲染路径
public enum RDEPUBRenderRequest: Equatable {
/// 可重排内容渲染请求
case reflowable(RDEPUBReflowableRenderRequest)
/// 固定版式渲染请求
case fixed(RDEPUBFixedRenderRequest)
/// 是否为固定版式渲染
public var isFixedLayout: Bool {
if case .fixed = self {
return true
}
return false
}
/// 主资源的 spine 索引
public var primarySpineIndex: Int {
switch self {
case .reflowable(let request):
return request.spineIndex
case .fixed(let request):
return request.spread.primaryResource.spineIndex
}
}
/// 主资源的路径
public var primaryHref: String {
switch self {
case .reflowable(let request):
return request.href
case .fixed(let request):
return request.spread.primaryResource.href
}
}
}