ReadViewSDK/Sources/RDEpubReaderView/EPUBUI/Settings/RDEPUBReaderConfiguration.swift
shenlei d7fcda345d refactor: rename RDReaderView -> RDEpubReaderView, update pod config and docs
- Rename source module from RDReaderView to RDEpubReaderView
- Move all source files from Sources/RDReaderView/ to Sources/RDEpubReaderView/
- Update podspec: RDReaderView.podspec -> RDEpubReaderView.podspec
- Update Podfile, demo project, and CocoaPods config for new pod name
- Delete old RDReaderView pod support files from ReadViewDemo/Pods
- Add new RDEpubReaderView pod support files
- Update documentation (API ref, architecture, UML, conventions, etc.)
- Add FixedLayoutRotationTests
- Update .gitignore: exclude .DS_Store, manual unpack backups, _ssoft-output
2026-07-10 19:44:53 +09:00

216 lines
7.9 KiB
Swift
Raw Permalink 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.

import UIKit
public enum RDEPUBTextRenderingEngine: Equatable {
case dtCoreText
}
public enum RDEPUBReaderFontChoice: String, Codable, CaseIterable, Equatable {
case system
case serif
case rounded
case monospaced
public var displayName: String {
switch self {
case .system:
return "系统"
case .serif:
return "宋体"
case .rounded:
return "圆体"
case .monospaced:
return "等宽"
}
}
public func font(ofSize size: CGFloat) -> UIFont {
switch self {
case .system:
return UIFont.systemFont(ofSize: size)
case .serif:
let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
.withDesign(.serif) ?? UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
return UIFont(descriptor: descriptor, size: size)
case .rounded:
let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
.withDesign(.rounded) ?? UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
return UIFont(descriptor: descriptor, size: size)
case .monospaced:
return UIFont.monospacedSystemFont(ofSize: size, weight: .regular)
}
}
}
/// UI 宿 delegate
public struct RDEPUBReaderTrialPolicy: Equatable {
/// spine 0..<readableChapterCount
/// nil = readoor epub
/// epub + bookPageMap
public var readableChapterCount: Int?
public init(readableChapterCount: Int? = nil) {
self.readableChapterCount = readableChapterCount
}
}
public struct RDEPUBReaderConfiguration: Equatable {
public var fontSize: CGFloat
public var lineHeightMultiple: CGFloat
public var fontChoice: RDEPUBReaderFontChoice
public var numberOfColumns: Int
public var columnGap: CGFloat
public var displayType: RDEpubReaderView.DisplayType
public var landscapeDualPageEnabled: Bool
public var showsTableOfContents: Bool
public var allowsHighlights: Bool
public var showsSettingsPanel: Bool
public var reflowableContentInsets: UIEdgeInsets
public var fixedContentInset: UIEdgeInsets
public var theme: RDEPUBReaderTheme
public var darkImageAdjustmentEnabled: Bool
public var darkImageBlendRatio: CGFloat
public var fixedLayoutFit: RDEPUBFixedLayoutFit
public var fixedLayoutSpreadMode: RDEPUBFixedLayoutSpreadMode
public var textRenderingEngine: RDEPUBTextRenderingEngine
public var onDemandChapterWindowSize: Int
public var metadataParsingConcurrency: Int
public var jumpSessionPolicy: RDEPUBJumpSessionPolicy
public var allowedExternalURLSchemes: Set<String>
public var requiresExternalLinkConfirmation: Bool
public var allowsInspectableWebViews: Bool
public var enablesVerboseWebViewLogging: Bool
/// nil =
public var trialPolicy: RDEPUBReaderTrialPolicy?
public init(
fontSize: CGFloat = 15,
lineHeightMultiple: CGFloat = 1.6,
fontChoice: RDEPUBReaderFontChoice = .system,
numberOfColumns: Int = 1,
columnGap: CGFloat = 20,
displayType: RDEpubReaderView.DisplayType = .pageCurl,
landscapeDualPageEnabled: Bool = true,
showsTableOfContents: Bool = true,
allowsHighlights: Bool = true,
showsSettingsPanel: Bool = true,
reflowableContentInsets: UIEdgeInsets = RDEPUBSafeArea.defaultReflowableContentInsets(),
fixedContentInset: UIEdgeInsets = .zero,
theme: RDEPUBReaderTheme = .light,
darkImageAdjustmentEnabled: Bool = true,
darkImageBlendRatio: CGFloat = 0.15,
fixedLayoutFit: RDEPUBFixedLayoutFit = .page,
fixedLayoutSpreadMode: RDEPUBFixedLayoutSpreadMode = .automatic,
textRenderingEngine: RDEPUBTextRenderingEngine = .dtCoreText,
onDemandChapterWindowSize: Int = 3,
metadataParsingConcurrency: Int = ProcessInfo.processInfo.activeProcessorCount,
jumpSessionPolicy: RDEPUBJumpSessionPolicy = .default,
allowedExternalURLSchemes: Set<String> = ["https"],
requiresExternalLinkConfirmation: Bool = true,
allowsInspectableWebViews: Bool = false,
enablesVerboseWebViewLogging: Bool = false,
trialPolicy: RDEPUBReaderTrialPolicy? = nil
) {
self.fontSize = fontSize
self.lineHeightMultiple = lineHeightMultiple
self.fontChoice = fontChoice
self.numberOfColumns = max(1, numberOfColumns)
self.columnGap = max(0, columnGap)
self.displayType = displayType
self.landscapeDualPageEnabled = landscapeDualPageEnabled
self.showsTableOfContents = showsTableOfContents
self.allowsHighlights = allowsHighlights
self.showsSettingsPanel = showsSettingsPanel
self.reflowableContentInsets = reflowableContentInsets
self.fixedContentInset = fixedContentInset
self.theme = theme
self.darkImageAdjustmentEnabled = darkImageAdjustmentEnabled
self.darkImageBlendRatio = max(0, min(0.35, darkImageBlendRatio))
self.fixedLayoutFit = fixedLayoutFit
self.fixedLayoutSpreadMode = fixedLayoutSpreadMode
self.textRenderingEngine = textRenderingEngine
self.onDemandChapterWindowSize = Self.normalizedChapterWindowSize(onDemandChapterWindowSize)
self.metadataParsingConcurrency = max(1, metadataParsingConcurrency)
self.jumpSessionPolicy = jumpSessionPolicy
self.allowedExternalURLSchemes = allowedExternalURLSchemes
self.requiresExternalLinkConfirmation = requiresExternalLinkConfirmation
self.allowsInspectableWebViews = allowsInspectableWebViews
self.enablesVerboseWebViewLogging = enablesVerboseWebViewLogging
self.trialPolicy = trialPolicy
}
public static let `default` = RDEPUBReaderConfiguration()
}
extension RDEPUBReaderConfiguration {
static func normalizedChapterWindowSize(_ size: Int) -> Int {
let clamped = max(3, min(15, size))
return clamped % 2 == 0 ? clamped + 1 : clamped
}
var chapterWindowRadius: Int {
onDemandChapterWindowSize / 2
}
}
extension RDEPUBReaderConfiguration {
func makePreferences(safeAreaInsets: UIEdgeInsets = .zero) -> RDEPUBPreferences {
// Use the larger of reflowableContentInsets and safeAreaInsets for each edge
// to prevent content from being hidden under Dynamic Island / home indicator.
// Falls back to the key-window safe area when the caller has no laid-out view.
let resolvedSafeAreaInsets = RDEPUBSafeArea.resolve(safeAreaInsets)
let safeInsets = UIEdgeInsets(
top: max(reflowableContentInsets.top, resolvedSafeAreaInsets.top),
left: max(reflowableContentInsets.left, resolvedSafeAreaInsets.left),
bottom: max(reflowableContentInsets.bottom, resolvedSafeAreaInsets.bottom),
right: max(reflowableContentInsets.right, resolvedSafeAreaInsets.right)
)
return RDEPUBPreferences(
fontSize: fontSize,
lineHeightMultiple: lineHeightMultiple,
reflowableContentInsets: safeInsets,
fixedContentInset: fixedContentInset,
numberOfColumns: numberOfColumns,
columnGap: columnGap,
themeBackgroundColor: theme.themeBackgroundColorCSS,
themeTextColor: theme.themeTextColorCSS,
fixedBackgroundColor: theme.themeBackgroundColorCSS,
fixedLayoutFit: fixedLayoutFit,
fixedLayoutSpreadMode: fixedLayoutSpreadMode
)
}
}