#pragma once // The Klammertext font store (infrastructure; see font_store.cpp). #include #include "locator.h" #include struct Resolved_font { std::string family_name {}; // "Crimson Pro" std::string dir_name {}; // "crimson-pro" std::string font_dir {}; // Full path to font directory std::string css_file {}; // Full path to .css file // .ttf filenames for each variant (empty if variant not available): std::string regular {}; std::string bold {}; std::string italic {}; std::string bold_italic {}; float xheight_ratio = 0.0f; // x-height / unitsPerEm from OS/2 table float capheight_ratio = 0.0f; // cap-height / unitsPerEm from OS/2 table }; std::string name_to_dirname(const std::string& name); // Directories searched for installed fonts (KLAMMERTEXT_FONTS, default // ~/.klammertext/fonts); the default font set is searched after them. std::vector installed_font_dirs(); // The distribution's default fonts: $KLAMMERTEXT_HOME/fnt. std::string default_font_dir(); // Every installable font family found across those directories. std::vector available_font_families(); // Every font ONE base directory holds, in directory-name order: each // .css beside a / directory, the family name read from the css // (the directory name when the css declares none), the styles classified. // Empty for a directory that does not exist or holds no fonts; the caller // asks the filesystem which. The store's layout convention lives here, so // a listing of the store (kdesc --typeface) reads it rather than restating it. std::vector fonts_in_directory(const std::string& base); // Whether the store can resolve NAME -- written as the family name or as // the store's directory name, since both resolve. The question a klammer // asks before it names a typeface that is not shipped (a CJK face), so it // can render the text plainly and say how to install the font instead of // failing the document. Never throws; resolve_font() is the error path. bool font_installed(const std::string& name); // The Locator is the DOCUMENT location to blame when the typeface is not // installed: without it the "not installed" error cites font_store.cpp, // a source location no user can act on (the no-.cpp-location rule). Resolved_font resolve_font(const std::string& family_name, const Locator& loc = Locator::none()); void install_resolved_font(const Resolved_font& font, std::string output_dir); // One font file classified by its internal metadata (name table, OS/2). struct Font_file { std::string path {}; std::string family {}; // from name table (nameID 16, else 1) std::string variant {}; // Regular | Bold | Italic | BoldItalic std::string extension {}; // ".ttf" or ".otf" bool variable = false; // has an 'fvar' table int weight = 0; // OS/2 usWeightClass std::string note {}; // reason when the file is not installable }; // Recursively classify every .ttf/.otf under a directory. std::vector classify_font_files(const std::string& directory); // Install the classified families from source_dir into dest_dir (default: // the first KLAMMERTEXT_FONTS directory, created if necessary), in the // canonical relocatable layout //{Variant}.ttf plus a // generated .css with relative urls. Returns a report. std::string install_fonts(const std::string& source_dir, std::string dest_dir = ""); // Write an HTML specimen page for fonts into output_dir. With an empty // source_dir, samples every available font in the store; otherwise // classifies and samples the (possibly uninstalled) fonts in source_dir. std::string write_font_samples(const std::string& output_dir, const std::string& source_dir = "");