epub问题修改

This commit is contained in:
shen
2026-05-26 23:27:52 +08:00
parent 22adb76332
commit ea21c6a831
8 changed files with 257 additions and 144 deletions
@@ -13,18 +13,12 @@ final class RDEPUBPageInteractionController {
var snapshot: RDEPUBPageLayoutSnapshot?
private var dtLayoutFrame: DTCoreTextLayoutFrame?
private var contentOffsetBase: Int = 0
#if canImport(DTCoreText)
func configure(layoutFrame: DTCoreTextLayoutFrame?, page: RDEPUBTextPage?, contentOffsetBase: Int = 0) {
func configure(layoutFrame: DTCoreTextLayoutFrame?, page: RDEPUBTextPage?) {
dtLayoutFrame = layoutFrame
self.contentOffsetBase = contentOffsetBase
if let layoutFrame, let page {
snapshot = RDEPUBPageLayoutSnapshot.build(
from: layoutFrame,
page: page,
contentOffsetBase: contentOffsetBase
)
snapshot = RDEPUBPageLayoutSnapshot.build(from: layoutFrame, page: page)
} else {
snapshot = nil
}
@@ -53,11 +47,7 @@ final class RDEPUBPageInteractionController {
)
let idx = dtLine.stringIndex(forPosition: relativePoint)
guard idx != NSNotFound, idx >= 0 else { return nil }
return normalizedIndex(
absoluteIndex(for: idx),
lineRange: line.stringRange,
pageRange: snapshot.pageContentRange
)
return normalizedIndex(idx, lineRange: line.stringRange, pageRange: snapshot.pageContentRange)
#else
return nil
#endif
@@ -85,9 +75,9 @@ final class RDEPUBPageInteractionController {
#if canImport(DTCoreText)
guard let dtLine = dtLineContaining(range: line.stringRange) else { continue }
let startX = dtLine.offset(forStringIndex: localIndex(for: overlap.location))
let startX = dtLine.offset(forStringIndex: overlap.location)
let endIdx = overlap.location + overlap.length
let endX = dtLine.offset(forStringIndex: localIndex(for: endIdx))
let endX = dtLine.offset(forStringIndex: endIdx)
#else
let startX: CGFloat = 0
let endX: CGFloat = line.frame.width
@@ -145,7 +135,7 @@ final class RDEPUBPageInteractionController {
#if canImport(DTCoreText)
guard let dtLine = dtLineContaining(range: line.stringRange) else { return nil }
let offsetX = dtLine.offset(forStringIndex: localIndex(for: index))
let offsetX = dtLine.offset(forStringIndex: index)
#else
let offsetX: CGFloat = 0
#endif
@@ -197,18 +187,10 @@ final class RDEPUBPageInteractionController {
#if canImport(DTCoreText)
private func dtLineContaining(range: NSRange) -> DTCoreTextLayoutLine? {
guard let dtLayoutFrame else { return nil }
return dtLayoutFrame.lineContaining(UInt(max(localIndex(for: range.location), 0)))
return dtLayoutFrame.lineContaining(UInt(range.location))
}
#endif
private func localIndex(for absoluteIndex: Int) -> Int {
absoluteIndex - contentOffsetBase
}
private func absoluteIndex(for localIndex: Int) -> Int {
localIndex + contentOffsetBase
}
private func mergeAdjacentRects(_ rects: [CGRect]) -> [CGRect] {
guard rects.count > 1 else { return rects }
@@ -130,8 +130,7 @@ struct RDEPUBPageLayoutSnapshot {
#if canImport(DTCoreText)
static func build(
from layoutFrame: DTCoreTextLayoutFrame,
page: RDEPUBTextPage,
contentOffsetBase: Int
page: RDEPUBTextPage
) -> RDEPUBPageLayoutSnapshot? {
guard let dtLines = layoutFrame.lines as? [DTCoreTextLayoutLine], !dtLines.isEmpty else {
return nil
@@ -140,7 +139,7 @@ struct RDEPUBPageLayoutSnapshot {
var lines: [RDEPUBPageLine] = []
var runs: [RDEPUBPageRun] = []
var attachments: [RDEPUBPageAttachment] = []
let pageOffset = contentOffsetBase
let pageOffset = page.pageStartOffset
for dtLine in dtLines {
let lineRange = offset(dtLine.stringRange(), by: pageOffset)
@@ -1267,6 +1267,9 @@ public final class RDEPUBReaderController: UIViewController {
private func currentTextPageSize() -> CGSize {
let pageNum = readerView.currentPage >= 0 ? readerView.currentPage : nil
let resolvedSize = readerView.resolvedSinglePageSize(pageNum: pageNum)
if ProcessInfo.processInfo.arguments.contains("--demo-pagination-debug") {
print("[PaginationDebug] currentTextPageSize currentPage=\(readerView.currentPage) resolved=\(NSCoder.string(for: resolvedSize)) readerBounds=\(NSCoder.string(for: readerView.bounds)) viewBounds=\(NSCoder.string(for: view.bounds)) safe=\(NSCoder.string(for: view.safeAreaInsets))")
}
if resolvedSize.width > 0, resolvedSize.height > 0 {
return resolvedSize
}
@@ -114,7 +114,6 @@ final class RDEPUBTextContentView: UIView {
private var coreTextDisplayContent: NSAttributedString?
private var coreTextDisplayRange: NSRange?
private var coreTextDisplayOffsetBase: Int = 0
#endif
private let interactionController = RDEPUBPageInteractionController()
@@ -266,10 +265,7 @@ final class RDEPUBTextContentView: UIView {
)
#if canImport(DTCoreText)
let usesChapterContextDisplay = shouldUseChapterContextDisplay(for: page)
let displayContent = usesChapterContextDisplay
? NSMutableAttributedString(attributedString: page.chapterContent)
: normalizedPageContent(from: page)
let displayContent = normalizedPageContent(from: page)
let fullRange = NSRange(location: 0, length: displayContent.length)
displayContent.addAttribute(
.foregroundColor,
@@ -279,8 +275,7 @@ final class RDEPUBTextContentView: UIView {
coreTextContentView.isHidden = false
coreTextContentView.backgroundColor = .clear
coreTextDisplayContent = displayContent
coreTextDisplayRange = usesChapterContextDisplay ? page.contentRange : NSRange(location: 0, length: displayContent.length)
coreTextDisplayOffsetBase = usesChapterContextDisplay ? 0 : page.pageStartOffset
coreTextDisplayRange = NSRange(location: 0, length: displayContent.length)
textView.isHidden = true
textView.isUserInteractionEnabled = false
textView.attributedText = nil
@@ -688,10 +683,6 @@ final class RDEPUBTextContentView: UIView {
return !CharacterSet.newlines.contains(previousScalar)
}
private func shouldUseChapterContextDisplay(for page: RDEPUBTextPage) -> Bool {
page.metadata.attachmentRanges.isEmpty
}
#if canImport(DTCoreText)
private func updateCoreTextLayoutFrameIfNeeded() {
guard !coreTextContentView.isHidden,
@@ -712,11 +703,7 @@ final class RDEPUBTextContentView: UIView {
layouter.shouldCacheLayoutFrames = false
let layoutFrame = layouter.layoutFrame(with: coreTextContentView.bounds, range: displayRange)
coreTextContentView.layoutFrame = layoutFrame
interactionController.configure(
layoutFrame: layoutFrame,
page: page,
contentOffsetBase: coreTextDisplayOffsetBase
)
interactionController.configure(layoutFrame: layoutFrame, page: page)
overlayView.updateSnapshot(interactionController.snapshot)
backgroundOverlayView.updateSnapshot(interactionController.snapshot)
}