feat: complete large-book pagination runtime and UI coverage

This commit is contained in:
shenlei
2026-06-03 17:47:16 +08:00
parent 584976ac5f
commit feb05eaf87
53 changed files with 6307 additions and 5126 deletions
@@ -146,6 +146,10 @@ struct RDEPUBChapterPageCounter {
var frames: [RDEPUBTextLayoutFrame] = []
var location = 0
let pageRect = dtLayoutRect
let isDebug = ProcessInfo.processInfo.arguments.contains("--demo-pagination-debug")
if isDebug {
print("[PAGINATION-DEBUG] pageRect=\(pageRect) totalLength=\(attributedString.length)")
}
while location < attributedString.length {
guard let layoutFrame = layouter.layoutFrame(with: pageRect, range: NSRange(location: location, length: 0)) else {
@@ -165,6 +169,16 @@ struct RDEPUBChapterPageCounter {
proposed: lineAdjusted,
lineRanges: lineRanges
)
if isDebug {
let pageCount = frames.count + 1
let previewText = (attributedString.string as NSString).substring(with: NSRange(location: location, length: min(20, attributedString.length - location)))
let avoidRemoved = proposedRange.length - avoidAdjusted.length
let kwNextRemoved = avoidAdjusted.length - lineAdjusted.length
let widowRemoved = lineAdjusted.length - widowOrphanAdjusted.length
let totalRemoved = proposedRange.length - widowOrphanAdjusted.length
print("[PAGINATION-DEBUG] page#\(pageCount) loc=\(location) proposed=\(proposedRange.length) avoid(-\(avoidRemoved)) kwNext(-\(kwNextRemoved)) widowOrphan(-\(widowRemoved)) total(-\(totalRemoved)) lastLine=\"\(previewText)\"")
}
let effectiveLineRanges = lineRangesWithinRange(lineRanges, range: widowOrphanAdjusted)
let adjusted = pageBreakPolicy.adjustedRange(
from: widowOrphanAdjusted,
@@ -146,6 +146,12 @@ struct RDEPUBCoreTextPageFrameFactory: RDEPUBPageFrameBuilding {
let endLocation = lastValidLine.location + lastValidLine.length
let adjustedLength = endLocation - proposed.location
guard adjustedLength > 0 else { return proposed }
if ProcessInfo.processInfo.arguments.contains("--demo-pagination-debug") {
let removedText = (attributedString.string as NSString).substring(with: NSRange(location: endLocation, length: min(proposed.length - adjustedLength, 40)))
print("[PAGINATION-DEBUG] avoidPageBreakInside removed \(linesToRemove) lines: \"\(removedText)\"")
}
return NSRange(location: proposed.location, length: adjustedLength)
}
@@ -180,6 +186,12 @@ struct RDEPUBCoreTextPageFrameFactory: RDEPUBPageFrameBuilding {
let endLocation = lastValidLine.location + lastValidLine.length
let adjustedLength = endLocation - proposed.location
guard adjustedLength > 0 else { return proposed }
if ProcessInfo.processInfo.arguments.contains("--demo-pagination-debug") {
let removedText = (attributedString.string as NSString).substring(with: NSRange(location: endLocation, length: min(proposed.length - adjustedLength, 40)))
print("[PAGINATION-DEBUG] keepWithNext removed \(linesToRemove) lines: \"\(removedText)\"")
}
return NSRange(location: proposed.location, length: adjustedLength)
}
@@ -317,6 +329,12 @@ struct RDEPUBCoreTextPageFrameFactory: RDEPUBPageFrameBuilding {
let keptLine = lineRanges[lineRanges.count - 2]
let adjustedLength = NSMaxRange(keptLine) - proposed.location
guard adjustedLength > 0 else { return nil }
if ProcessInfo.processInfo.arguments.contains("--demo-pagination-debug") {
let removedText = (attributedString.string as NSString).substring(with: NSRange(location: NSMaxRange(keptLine), length: min(proposed.length - adjustedLength, 40)))
print("[PAGINATION-DEBUG] widow control removed 1 line: \"\(removedText)\" paragraphRange=\(NSStringFromRange(paragraphRange))")
}
return NSRange(location: proposed.location, length: adjustedLength)
}