use sdl2::{
ttf::Sdl2TtfContext,
ttf::Font as sdl_Font
};
use std::fs;
use serde::Deserialize;
use crate::base::{
BASE_DIR,
JEXT,
PrependErrorString
};
const FONTS_DIR: &str = "fonts";
const FONTS_FILEPATH_NOEXT: &str = "fonts";
pub struct FontContext {
sdl_context: Sdl2TtfContext
}
pub struct Font<'a> {
pub sdl_font: sdl_Font<'a, 'static>
}
pub struct Fontset<'a> {
fonts: Vec<Font<'a>>
}
#[derive(Deserialize)]
struct FontDesc {
file: String,
size: i32
}
#[derive(Deserialize)]
struct FontsDesc {
system: FontDesc,
meta: FontDesc,
info: FontDesc
}
#[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)]
pub enum CFont {
System,
Meta, Info
}
impl FontContext {
pub fn init() -> Result<FontContext, String> {
let sdl_context = sdl2::ttf::init().map_err(|e| e.to_string())?;
Ok(FontContext{sdl_context})
}
}
impl Font<'_> {
pub fn height(&self) -> i32 {
self.sdl_font.height()
}
}
fn load_font<'a>(font_context: &'a FontContext, filepath: impl ToString, size: i32) -> Result<Font<'a>, String> {
let filepath = filepath.to_string();
Ok(Font{sdl_font: font_context.sdl_context.load_font(format!("{}/{}/{}", BASE_DIR, FONTS_DIR, filepath), size as u16)?})
}
impl<'a> Fontset<'a> {
pub fn load(font_context: &'a FontContext) -> Result<Self, String> {
let b = fs::read(format!("{}/{}/{}.{}", BASE_DIR, FONTS_DIR, FONTS_FILEPATH_NOEXT, JEXT)).pre_err("cannot read fonts file")?;
let fsd: FontsDesc = serde_json::from_slice(&b).pre_err("cannot parse fonts json")?;
let mut fonts = Vec::<Font<'a>>::new();
fonts.push(load_font(font_context, &fsd.system.file, fsd.system.size).pre_err("cannot load System font")?);
fonts.push(load_font(font_context, &fsd.meta.file, fsd.meta.size).pre_err("cannot load Meta font")?);
fonts.push(load_font(font_context, &fsd.info.file, fsd.info.size).pre_err("cannot load Parameters font")?);
Ok(Self{fonts})
}
pub fn get(&self, cfont: CFont) -> &Font<'a> {
& self.fonts[cfont as usize]
}
}