ReadViewSDK/.planning/phases/06-page-geometry-and-interaction-hit-layer/06-01-PLAN.md
2026-05-22 14:20:33 +08:00

77 lines
3.7 KiB
Markdown

---
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
<objective>
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.
</objective>
<must_haves>
- `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.
</must_haves>
<tasks>
<task id="06-01-01">
<type>execute</type>
<action>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.</action>
<read_first>
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextPaginationSupport.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
</read_first>
<acceptance_criteria>
- `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.
</acceptance_criteria>
</task>
<task id="06-01-02">
<type>execute</type>
<action>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.</action>
<read_first>
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift
- Sources/RDReaderView/LegacyRDReaderController/RDEPUBTextPaging.swift
</read_first>
<acceptance_criteria>
- `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.
</acceptance_criteria>
</task>
</tasks>
<verification>
- 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.
</verification>
<success_criteria>
- 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.
</success_criteria>