--- phase: 6 plan: 06-01 type: execute wave: 1 depends_on: [] files_modified: - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift - Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift autonomous: true requirements: - LAYOUT-01 - LAYOUT-03 --- # Phase 6-01: Page Geometry Model Add a reusable page geometry layer on top of native text pagination so callers can query page-relative rectangles and map rectangles back to text ranges without breaking offset continuity. - `RDEPUBTextLayoutFrame` can expose page geometry derived from CoreText, not guessed from offsets. - `pageStartOffset`, `pageEndOffset`, `fragmentOffsets`, and `RDEPUBTextOffsetRangeInfo` semantics remain stable. - The geometry API is reusable by selection, search, highlight, and tap-locate work in later plans. execute Extend `RDEPUBTextLayoutFrame` and the page model with explicit geometry value types, including a page-level geometry container and line or fragment geometry records. Populate them from `RDEPUBTextLayouter` using CoreText line data so the page can answer range-to-rect and rect-to-range queries without changing pagination break rules. - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift - Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift - `RDEPUBTextLayoutFrame` or its companion geometry type exposes a query path for at least string-range rectangles and reverse lookup from rects to `NSRange`. - Existing metadata fields (`contentRange`, `breakReason`, `blockRange`, `attachmentRanges`, `attachmentKinds`, `trailingFragmentID`, `diagnostics`) remain present and unchanged in meaning. - `RDEPUBTextLayouter` still emits the same page boundaries for the sample books after the geometry data is added. execute Thread the new geometry data through `RDEPUBTextBookBuilder` and `RDEPUBTextBook` so each page retains its geometry alongside `pageStartOffset`, `pageEndOffset`, and `fragmentOffsets`. Keep `pageNumber(for:)` and `location(forPageNumber:)` compatible with the existing absolute-offset contract. - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift - Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift - Sources/RDReaderView/LegacyRDReaderController/RDEPUBTextPaging.swift - `RDEPUBTextBook` pages still map absolute offsets to pages through `pageStartOffset` / `pageEndOffset`. - `RDEPUBTextBook.location(forPageNumber:)` still returns a stable `RDEPUBLocation` for native text pages. - The sample text book builds successfully with the new geometry fields attached to each page. - Build the `ReadViewDemo` workspace with the `ReadViewDemo` scheme. - Confirm the new page geometry API compiles and the sample book still paginates. - Confirm no existing offset-based selection or restore code needs to change to keep building. - Native text pages expose reusable geometry data. - The offset-based page contract remains intact. - Later selection overlay work can consume the geometry layer without re-deriving page boundaries.