// 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 ) ) } }