using FontStashSharp; using Microsoft.Xna.Framework.Graphics; namespace Theriapolis.Game.CodexUI.Core; /// /// Static font registry for CodexUI. Loaded once at game startup via /// ; widgets read from these fields. The slots map to /// the design's typographic ladder: /// - DisplayLarge / Medium / Small → Cinzel-Bold (fallback: Georgia Bold) — all-caps headings /// - SerifBody / SerifItalic → Cormorant Garamond (fallback: Georgia / Georgia Italic) /// - MonoTag / MonoTagSmall → JetBrains Mono (fallback: Consolas) /// /// FontStashSharp loads TTF files into a runtime atlas. We try /// Content/Fonts/ first (project-supplied fonts), then fall back to /// Windows system fonts so the game runs without bundling Cinzel/Cormorant. /// public static class CodexFonts { public static SpriteFontBase DisplayLarge = null!; // ~32 px, codex header public static SpriteFontBase DisplayMedium = null!; // ~22 px, h2 public static SpriteFontBase DisplaySmall = null!; // ~16 px, h3 public static SpriteFontBase SerifBody = null!; // ~16 px, body text public static SpriteFontBase SerifItalic = null!; // ~14 px, italic body / trait names public static SpriteFontBase MonoTag = null!; // ~10 px, eyebrow + tag text public static SpriteFontBase MonoTagSmall = null!; // ~9 px, sub-tags private static FontSystem? _serif; private static FontSystem? _italic; private static FontSystem? _mono; /// /// Load every font slot. Throws on failure — fonts are required for the /// codex screen to render anything legible. /// public static void LoadAll(GraphicsDevice gd, string contentRoot) { _serif = LoadFontSystem(contentRoot, new[] { "Fonts/Cinzel-Bold.ttf", "Fonts/CormorantGaramond-Bold.ttf" }, new[] { @"C:\Windows\Fonts\georgiab.ttf", @"C:\Windows\Fonts\timesbd.ttf" }); _italic = LoadFontSystem(contentRoot, new[] { "Fonts/CormorantGaramond-Italic.ttf", "Fonts/CormorantGaramond-Regular.ttf" }, new[] { @"C:\Windows\Fonts\georgiai.ttf", @"C:\Windows\Fonts\timesi.ttf", @"C:\Windows\Fonts\georgia.ttf" }); _mono = LoadFontSystem(contentRoot, new[] { "Fonts/JetBrainsMono-Medium.ttf" }, new[] { @"C:\Windows\Fonts\consola.ttf", @"C:\Windows\Fonts\consolab.ttf", @"C:\Windows\Fonts\cour.ttf" }); DisplayLarge = _serif.GetFont(32f); DisplayMedium = _serif.GetFont(22f); DisplaySmall = _serif.GetFont(16f); SerifBody = _italic.GetFont(15f); SerifItalic = _italic.GetFont(14f); MonoTag = _mono.GetFont(11f); MonoTagSmall = _mono.GetFont(9f); } private static FontSystem LoadFontSystem(string contentRoot, string[] preferred, string[] fallbacks) { var fs = new FontSystem(); // Try project-supplied fonts first (Content/Fonts/*). foreach (var rel in preferred) { string path = System.IO.Path.Combine(contentRoot, rel); if (System.IO.File.Exists(path)) { fs.AddFont(System.IO.File.ReadAllBytes(path)); return fs; } } // Fall back to a system font — guaranteed available on the target // platforms (Windows Georgia/Times/Consolas; future: macOS / Linux // would need their own fallback list). foreach (var path in fallbacks) { if (System.IO.File.Exists(path)) { fs.AddFont(System.IO.File.ReadAllBytes(path)); return fs; } } throw new System.IO.FileNotFoundException( "CodexFonts: no font found in either project Content/Fonts/ or system fallback locations. " + $"Preferred: {string.Join(", ", preferred)}; fallbacks: {string.Join(", ", fallbacks)}"); } }