freepdfeditor/spike/B1_glyph_unicode/GlyphUnicode.h

58 lines
2.3 KiB
C++

// 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 <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
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<GlyphMap> 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