import UIKit enum RDEPUBTextPageLayoutMetrics { static let pageNumberTrailingPadding: CGFloat = 4 static let pageNumberFooterPadding: CGFloat = 8 static let pageNumberReservedHeight: CGFloat = ceil(UIFont.systemFont(ofSize: 13).lineHeight) + pageNumberFooterPadding static func contentInsets( configuration: RDEPUBReaderConfiguration, safeAreaInsets: UIEdgeInsets ) -> UIEdgeInsets { let configInsets = configuration.reflowableContentInsets return UIEdgeInsets( top: max(configInsets.top, safeAreaInsets.top), left: max(configInsets.left, safeAreaInsets.left), bottom: max(configInsets.bottom, safeAreaInsets.bottom) + pageNumberReservedHeight, right: max(configInsets.right, safeAreaInsets.right) ) } } final class RDEPUBReaderEnvironment { weak var controller: RDEPUBReaderController? weak var readerView: RDReaderView? var displayEnvironment: any RDEPUBReaderDisplayEnvironment init( controller: RDEPUBReaderController, readerView: RDReaderView, displayEnvironment: any RDEPUBReaderDisplayEnvironment ) { self.controller = controller self.readerView = readerView self.displayEnvironment = displayEnvironment } func currentLayoutContext(configuration: RDEPUBReaderConfiguration) -> RDEPUBNavigatorLayoutContext { let containerSize = readerView?.bounds.size ?? .zero let viewSize = controller?.view.bounds.size ?? containerSize let resolvedSize = containerSize == .zero ? viewSize : containerSize return RDEPUBNavigatorLayoutContext( containerSize: resolvedSize, pagesPerScreen: readerView?.pagesPerScreen ?? 1, safeAreaInsets: RDEPUBSafeArea.resolve(controller?.view.safeAreaInsets), userInterfaceIdiom: controller?.traitCollection.userInterfaceIdiom ?? .phone, reflowableContentInsets: configuration.reflowableContentInsets ) } func currentTextRenderStyle(configuration: RDEPUBReaderConfiguration) -> RDEPUBTextRenderStyle { let font = configuration.fontChoice.font(ofSize: configuration.fontSize) let lineSpacing = max(font.lineHeight * (configuration.lineHeightMultiple - 1), 4) return RDEPUBTextRenderStyle( font: font, lineSpacing: lineSpacing, textColor: configuration.theme.contentTextColor, backgroundColor: configuration.theme.contentBackgroundColor ) } func currentTextLayoutConfig( configuration: RDEPUBReaderConfiguration, pageSize: CGSize ) -> RDEPUBTextLayoutConfig { let safeAreaInsets = RDEPUBSafeArea.resolve(controller?.view.safeAreaInsets) return RDEPUBTextLayoutConfig( frameWidth: max(pageSize.width, 1), frameHeight: max(pageSize.height, 1), edgeInsets: RDEPUBTextPageLayoutMetrics.contentInsets( configuration: configuration, safeAreaInsets: safeAreaInsets ), numberOfColumns: configuration.numberOfColumns, columnGap: configuration.columnGap, avoidOrphans: false, avoidWidows: false, avoidPageBreakInsideEnabled: true, hyphenation: true, imageMaxHeightRatio: 0.85, fallbackViewportSize: displayEnvironment.fallbackViewportSize ) } var currentBrightness: CGFloat { get { displayEnvironment.currentBrightness } set { displayEnvironment.currentBrightness = newValue } } var fallbackViewportSize: CGSize { displayEnvironment.fallbackViewportSize } }