58 lines
2.3 KiB
C++
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
|