52 lines
3.4 KiB
Markdown
52 lines
3.4 KiB
Markdown
---
|
|
phase: 08-pagination-quality-cache-performance
|
|
plan: 02
|
|
type: summary
|
|
date: 2026-05-23
|
|
---
|
|
|
|
# Phase 08-02 Summary
|
|
|
|
## Objective
|
|
Improve pagination quality by enforcing avoidPageBreakInside, adding orphan/widow line control, and implementing general image fit-to-page sizing.
|
|
|
|
## Tasks Completed
|
|
|
|
### Task 1: RDEPUBTextLayoutConfig struct and wiring
|
|
- Defined `RDEPUBTextLayoutConfig` in `RDEPUBTextRenderer.swift` with 4 properties: `avoidOrphans`, `avoidWidows`, `avoidPageBreakInsideEnabled`, `imageMaxHeightRatio` (default 0.85)
|
|
- Follows the exact `RDEPUBTextRenderStyle` struct pattern: public struct, public stored properties, public init with defaults, static `.default` instance
|
|
- Added `config` parameter to `RDEPUBTextLayouter.init` with `.default` default value
|
|
- Added `config` parameter to `rd_paginatedFrames` extension with `.default` default value
|
|
- All existing call sites continue to work unchanged (backward compatible)
|
|
|
|
### Task 2: avoidPageBreakInside enforcement + orphan/widow control
|
|
- Added `avoidPageBreakInsideBoundary(in:minimumEnd:)` method in `RDEPUBTextLayouter.swift`
|
|
- Detects when page end falls INSIDE an avoidPageBreakInside block (complement to existing check that only handles block start as boundary)
|
|
- Pushes entire block to next page when block start >= minimumEnd
|
|
- Gated on `config.avoidPageBreakInsideEnabled`
|
|
- Added `orphanWidowAdjustedRange(from:minimumEnd:)` method
|
|
- **Orphan control**: When page starts at a paragraph beginning and only 1-2 lines fit, pulls back to include more content from previous page
|
|
- **Widow control**: When page ends with only 1-2 lines of a paragraph remaining, pushes entire paragraph to next page
|
|
- Both gated on `config.avoidOrphans` and `config.avoidWidows` respectively
|
|
- Inserted both checks in `adjustedRange()` between `preferredSemanticBoundary` and `preferredAttachmentBoundary`
|
|
- Diagnostic strings emitted on trigger: "avoidPageBreakInside enforcement", "orphan control: ...", "widow control: ..."
|
|
|
|
### Task 3: General image fit-to-page sizing and diagnostics
|
|
- Added `return` at end of cover image block to prevent fall-through to general handling
|
|
- Added general image sizing block for all non-footnote, non-cover images:
|
|
- Scales images exceeding `maxImageHeight` (screen height * 0.85) or `maxWidth` proportionally
|
|
- Sets `verticalAlignment = .center` for block-level images (bodyPic, qrbodyPic, figure, .block displayStyle)
|
|
- Added diagnostic output:
|
|
- `[EPUB][Attachment] general image ...` with original/display sizes and scaled flag
|
|
- `[EPUB][Attachment] dark mode: image colors preserved ...` when in dark mode
|
|
- `[EPUB][Attachment] background: ...` with hasBackground check for attachment blocks
|
|
|
|
## Files Modified
|
|
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift` — added `RDEPUBTextLayoutConfig` struct
|
|
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift` — added config property, avoidPageBreakInside enforcement, orphan/widow control
|
|
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift` — added config parameter to `rd_paginatedFrames`
|
|
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift` — added general image sizing, cover return, diagnostic output
|
|
|
|
## Build Status
|
|
All three tasks verified with `xcodebuild build -workspace ReadViewDemo/ReadViewDemo.xcworkspace -scheme ReadViewDemo -destination 'platform=iOS Simulator,name=iPhone 17 Pro'` — BUILD SUCCEEDED for each.
|