// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2025 ai-ad4 and the FreePDFEditor contributors // // Reconstruct.h — the text reconstruction pipeline (plan §4.1). Takes a set // of GlyphRuns and produces Paragraphs, then scores them against ground truth. // // This is the M0 Spike B harness. The full §4.1 pipeline has six steps; this // implementation covers steps 2–5 (run assembly, line detection, reading // order, paragraph grouping) which are the ones the F1 gate scores. Step 1 // (glyph→Unicode) is exercised separately via the font cmap / ToUnicode path; // step 6 (frame geometry) is a post-processing step not needed for the // paragraph-boundary F1 metric. #ifndef FREEPDFEDITOR_SPIKE_B_RECONSTRUCT_H #define FREEPDFEDITOR_SPIKE_B_RECONSTRUCT_H #include "GlyphRun.h" #include namespace freepdfeditor::spike::b { struct ReconstructionResult { std::vector lines; std::vector paragraphs; }; // Run the reconstruction pipeline over `runs`. `font_size_tolerance` controls // the baseline-clustering tolerance (default 0.25 × font size per §4.1 step 3). ReconstructionResult reconstruct(const std::vector& runs, float font_size_tolerance = 0.25f); // Score predicted paragraphs against ground truth by boundary F1: a predicted // paragraph boundary is "correct" if it falls within `tolerance` (in device // units) of a ground-truth boundary. Returns precision, recall and F1. struct BoundaryScore { std::size_t true_boundaries = 0; std::size_t predicted_boundaries = 0; std::size_t matched = 0; double precision = 0.0; double recall = 0.0; double f1 = 0.0; }; BoundaryScore score_boundaries(const std::vector& predicted, const std::vector& truth, float tolerance); } // namespace freepdfeditor::spike::b #endif // FREEPDFEDITOR_SPIKE_B_RECONSTRUCT_H