Adds curved arrows between consecutive blocks in reading order with numeric labels. Arrows use quadratic bezier curves with control points at midpoint + 10pt downward. Limits to 50 arrows to prevent visual clutter. - Add render_reading_order function returning SVG path and text elements - Include data-* attributes for tooltip consumption - Add comprehensive unit tests (10/10 passing) - Export reading_order module from inspect/render/mod.rs Acceptance criteria: - Helper compiles and produces valid SVG output ✅ - Layer is independently toggleable via CSS class ✅ - data-* attrs populated ✅ - Unit tests pass ✅ Closes: pdftract-6559n
3.2 KiB
3.2 KiB
pdftract-6559n: render_reading_order Implementation
Bead
ID: pdftract-6559n Title: Inspector layer renderer: render_reading_order (curved numbered arrows)
Implementation Summary
Implemented the render_reading_order function that renders curved arrows between consecutive blocks in reading order for the inspector debug viewer.
Files Created
crates/pdftract-cli/src/inspect/render/reading_order.rs(377 lines)
Files Modified
crates/pdftract-cli/src/inspect/render/mod.rs- Addedreading_ordermodule export
Acceptance Criteria Status
PASS
- ✅ Helper compiles and produces valid SVG output
- Function signature:
pub fn render_reading_order(blocks: &[BlockJson], order: &[usize]) -> Vec<String> - Returns
<path>elements for curved arrows and<text>elements for numeric labels
- Function signature:
- ✅ Layer is independently toggleable via CSS class
- Arrows have
class="reading-order-arrow" - Labels have
class="reading-order-label"
- Arrows have
- ✅ data-* attrs populated for downstream UI consumption
data-from-block: index of source blockdata-to-block: index of target blockdata-reading-index: sequence number (1, 2, 3, ...)
- ✅ Unit tests pass (10/10)
- Empty input handling
- Single block (no arrows)
- Two blocks (one arrow)
- Three blocks (two arrows)
- Non-sequential reading order (columnar layouts)
- Max arrows limit (50 arrows to prevent clutter)
- Block center calculation
- CSS class presence
- Out-of-bounds index handling
Technical Details
Arrow rendering:
- Stroke: blue (#3b82f6) with 1.5px width
- Marker-end: url(#arrowhead) - expects arrowhead definition in parent SVG
<defs> - Quadratic bezier curves (
Qcommand) with control point at midpoint + 10pt downward - SVG path format:
M{x1},{y1} Q{cx},{cy} {x2},{y2}
Labels:
- Numeric labels (1, 2, 3, ...) at arrow midpoints
- Positioned 5pt above the midpoint
- Blue (#3b82f6), bold, 10pt font
Performance:
- Limits to first 50 blocks (49 arrows max) to prevent visual clutter
- O(n) complexity where n = number of arrows
Testing
cargo test -p pdftract-cli --lib reading_order
All 10 tests pass:
- test_block_center
- test_block_center_fractional
- test_render_reading_order_empty
- test_render_reading_order_css_class
- test_render_reading_order_out_of_bounds_indices
- test_render_reading_order_non_sequential
- test_render_reading_order_single_block
- test_render_reading_order_three_blocks
- test_render_reading_order_two_blocks
- test_render_reading_order_max_arrows_limit
Integration Notes
This renderer will be called by the inspector layer rendering pipeline (Phase 7.9.4) to generate the reading-order overlay layer. The SVG elements returned by this function are placed inside a <g class="layer-reading-order"> group in the final output.
The parent SVG must define the arrowhead marker in <defs>:
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
<path d="M0,0 L0,6 L9,3 z" fill="#3b82f6" />
</marker>
</defs>
References
- Plan section: Phase 7.9 lines 2836-2845 (layer table)
- Coordinator: pdftract-liq5f (parent — 8 layer renderers bundle)
- Phase 7.9.3 (frontend CSS-toggling)
- Phase 7.9.6 (tooltip/search/tree consume data-* attrs)