// RDEPUBReaderController+RenderSupport.swift // EPUB 阅读器渲染支持辅助方法 // 提供获取当前布局上下文、偏好设置、页面尺寸、渲染样式、文本布局配置, // 以及构建渲染请求、管理分页宿主视图和回退位置查询等功能。 import UIKit /// RDEPUBReaderController 渲染支持扩展 /// /// 本文件提供阅读器渲染所需的辅助方法,包括获取当前布局上下文、偏好设置、页面尺寸、 /// 渲染样式、文本布局配置,以及构建渲染请求和回退位置查询等功能。 extension RDEPUBReaderController { /// 获取当前导航器布局上下文(视口尺寸、方向等) func currentLayoutContext() -> RDEPUBNavigatorLayoutContext { readerContext.currentLayoutContext() } /// 获取当前阅读偏好设置 func currentPreferences() -> RDEPUBPreferences { readerContext.currentPreferences() } /// 获取当前文本页面尺寸 func currentTextPageSize() -> CGSize { readerContext.currentTextPageSize() } /// 获取当前文本渲染样式(字体、行高等) func currentTextRenderStyle() -> RDEPUBTextRenderStyle { readerContext.currentTextRenderStyle() } /// 获取指定页面尺寸下的文本布局配置 func currentTextLayoutConfig(pageSize: CGSize) -> RDEPUBTextLayoutConfig { readerContext.currentTextLayoutConfig(pageSize: pageSize) } /// 获取已解析的文本渲染器实例 func resolvedTextRenderer() -> RDEPUBTextRenderer { readerContext.resolvedTextRenderer() } /// 确保分页宿主视图已添加到视图层级(位于屏幕外用于预计算分页) func ensurePaginationHostView() -> UIView { let viewportSize = currentLayoutContext().viewportSize let hostFrame = CGRect(x: -viewportSize.width - 32, y: 0, width: viewportSize.width, height: viewportSize.height) if paginationHostView.superview == nil { view.addSubview(paginationHostView) view.sendSubviewToBack(paginationHostView) } paginationHostView.frame = hostFrame return paginationHostView } /// 为指定页面索引构建渲染请求(含位置、高亮、搜索状态) func request(for pageIndex: Int) -> RDEPUBRenderRequest? { guard let publication, activePages.indices.contains(pageIndex) else { return nil } let page = activePages[pageIndex] let pendingLocation = readingSession?.pendingLocation(forPageNumber: pageIndex + 1, spineIndex: page.spineIndex) let pendingHighlightRangeInfo = readingSession?.pendingHighlightRangeInfo( forPageNumber: pageIndex + 1, spineIndex: page.spineIndex ) return currentPreferences().renderRequest( for: page, publication: publication, viewportSize: currentLayoutContext().viewportSize, targetLocation: pendingLocation, targetHighlightRangeInfo: pendingHighlightRangeInfo, highlights: highlights(for: page), searchPresentation: searchPresentation(for: page) ) } /// 获取指定页面索引的回退位置(当无法确定精确位置时使用) func fallbackLocation(for pageIndex: Int) -> RDEPUBLocation? { guard activePages.indices.contains(pageIndex) else { return nil } return readingSession?.fallbackLocation(for: activePages[pageIndex], bookIdentifier: currentBookIdentifier) } /// 获取指定固定布局页面上的高亮标注列表 private func highlights(for page: EPUBPage) -> [RDEPUBHighlight] { guard let publication else { return [] } if let spread = page.fixedSpread { let hrefs = Set(spread.resources.compactMap { publication.resourceResolver.normalizedHref($0.href) }) return activeHighlights.filter { highlight in guard let normalizedHref = publication.resourceResolver.normalizedHref(highlight.location.href) else { return false } return hrefs.contains(normalizedHref) } } guard publication.spine.indices.contains(page.spineIndex) else { return [] } let href = publication.spine[page.spineIndex].href let normalizedHref = publication.resourceResolver.normalizedHref(href) return activeHighlights.filter { highlight in publication.resourceResolver.normalizedHref(highlight.location.href) == normalizedHref } } }