// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2025 ai-ad4 and the FreePDFEditor contributors // // GlyphUnicode.h — Spike B step 1 (§4.1 step 1): glyph→Unicode mapping via // the priority ladder, scored on a real embedded font. // // The ladder (§4.1 step 1), in priority order: // 1. ToUnicode CMap (correct when present and non-broken) // 2. Simple-font Encoding + Differences → glyph names → Adobe Glyph List // 3. Standard/Symbolic built-in encodings; Identity-H + CIDSystemInfo // 4. Reverse lookup through the embedded font's cmap table // 5. Heuristic fallback: OCR the rendered glyph (out of scope here) // // This harness exercises steps 1 and 4 (the most common paths): parse the // ToUnicode CMap from the PDF via QPDF, and fall back to FreeType's cmap // table access. Each character carries a confidence value (1.0 for ToUnicode, // 0.7 for cmap) — the same confidence the production UI uses to underline // low-confidence characters in edit mode (§4.1). #ifndef FREEPDFEDITOR_SPIKE_B1_GLYPHUNICODE_H #define FREEPDFEDITOR_SPIKE_B1_GLYPHUNICODE_H #include #include #include #include namespace freepdfeditor::spike::b1 { // A glyph→Unicode mapping with its provenance and confidence. struct GlyphMap { std::uint32_t gid = 0; // glyph id in the font std::uint32_t unicode = 0; // resolved Unicode codepoint (0 = unknown) float confidence = 0.0f; // [0,1] — see §4.1 step 1 ladder enum class Source { ToUnicode, Cmap, Unknown } source = Source::Unknown; }; struct MappingResult { bool ok = false; std::string error; std::vector mappings; // per glyph id in the font std::size_t mapped_via_tounicode = 0; std::size_t mapped_via_cmap = 0; std::size_t unmapped = 0; double coverage = 0.0; // fraction of glyphs mapped double avg_confidence = 0.0; }; // Run the glyph→Unicode ladder for the embedded font in `pdf_path`: // - parse the ToUnicode CMap (step 1) via QPDF // - for any glyphs not in the ToUnicode, fall back to the embedded font's // cmap table (step 4) via FreeType // Returns per-glyph mappings with provenance and confidence. MappingResult map_glyphs(const std::string& pdf_path); } // namespace freepdfeditor::spike::b1 #endif // FREEPDFEDITOR_SPIKE_B1_GLYPHUNICODE_H