// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2025 ai-ad4 and the FreePDFEditor contributors // // SubsetGrowth.h — Spike C (§14 step 6): grow an existing embedded subset // font with a new glyph using hb-subset, and verify the result. // // The scenario: a PDF page embeds a subset font containing only the glyphs // originally used (say "Hello"). The user types "Ω" — that glyph is not in // the subset. Per §4.2 resolution ladder step 1, we grow the subset from // the installed full font (DejaVu Sans here) using hb-subset and embed the // new subset. This spike proves the growth works and the result is a valid // font with the new glyph and a correct cmap. #ifndef FREEPDFEDITOR_SPIKE_C_SUBSETGROWTH_H #define FREEPDFEDITOR_SPIKE_C_SUBSETGROWTH_H #include #include #include namespace freepdfeditor::spike::c { struct GrowthResult { bool ok = false; std::string error; std::size_t original_glyph_count = 0; // glyphs in the initial subset std::size_t grown_glyph_count = 0; // glyphs after adding the new char std::size_t original_font_bytes = 0; std::size_t grown_font_bytes = 0; bool new_glyph_present = false; // does the grown subset contain U+03A9? bool new_glyph_renders = false; // can FreeType load its outline? std::string original_subset_tag; // e.g. "AAAAAA+" std::string grown_subset_tag; }; // Run the subset-growth scenario: // 1. Build an initial subset of `font_path` containing the glyphs for // "Hello" (the "originally embedded" subset). // 2. Grow it by adding U+03A9 (GREEK CAPITAL LETTER OMEGA) — the character // the user typed that wasn't in the original subset. // 3. Verify the grown subset: it must contain the new glyph, have a correct // cmap mapping U+03A9 → a glyph id, and FreeType must be able to load // that glyph's outline (it renders). GrowthResult grow_subset(const std::string& font_path); } // namespace freepdfeditor::spike::c #endif // FREEPDFEDITOR_SPIKE_C_SUBSETGROWTH_H