cotis-raylib 0.1.0-alpha

Raylib-backed renderer for Cotis
Documentation
//! Font loading and lazy size management for raylib text drawing.

use raylib::consts::TextureFilter;
use raylib::error::RaylibError;
use raylib::prelude::*;
use raylib::{RaylibHandle, RaylibThread};
use std::collections::HashMap;

/// A font file loaded at an initial size, with lazy loading of additional pixel sizes.
///
/// Created by [`RaylibRender::load_font_ex_and_keep`](crate::renderer::RaylibRender::load_font_ex_and_keep)
/// and stored in the renderer's font table. Queued sizes are flushed at the start of each frame.
///
/// This type has no public methods; interact through font IDs on [`TextConfig`](cotis_defaults::element_configs::text_config::TextConfig).
pub struct ScalableFont {
    file_name: String,
    chars: Option<String>,
    filter: Option<TextureFilter>,
    default_font: Font,
    default_size: usize,
    map: HashMap<usize, Font>,
    to_load: Vec<usize>,
}

impl ScalableFont {
    pub(crate) fn new(
        file_name: String,
        chars: Option<String>,
        filter: Option<TextureFilter>,
        rl: &mut RaylibHandle,
        raylib_thread: &RaylibThread,
        font_size: usize,
    ) -> Result<Self, RaylibError> {
        let font = rl.load_font_ex(
            raylib_thread,
            &file_name,
            font_size as i32,
            chars.as_deref(),
        )?;
        if let Some(tex_filter) = filter {
            font.texture().set_texture_filter(raylib_thread, tex_filter);
        }
        let res = Self {
            file_name,
            chars,
            filter,
            default_font: font,
            default_size: font_size,
            map: Default::default(),
            to_load: vec![],
        };
        Ok(res)
    }

    fn load(
        &mut self,
        font_size: usize,
        rl: &mut RaylibHandle,
        raylib_thread: &RaylibThread,
    ) -> Result<(), RaylibError> {
        if self.default_size == font_size {
            return Ok(());
        }
        if self.map.contains_key(&font_size) {
            return Ok(());
        }
        let font = rl.load_font_ex(
            raylib_thread,
            &self.file_name,
            font_size as i32,
            self.chars.as_deref(),
        )?;
        if let Some(filter) = self.filter {
            font.texture().set_texture_filter(raylib_thread, filter);
        }
        self.map.insert(font_size, font);
        Ok(())
    }

    pub(crate) fn get_font_for_size(&mut self, font_size: usize) -> &Font {
        if !self.map.contains_key(&font_size) {
            if font_size > 0 {
                self.to_load.push(font_size);
            }
            &self.default_font
        } else {
            self.map.get(&font_size).unwrap()
        }
    }

    pub(crate) fn get_font_for_size_borrow(&self, font_size: usize) -> &Font {
        if !self.map.contains_key(&font_size) {
            &self.default_font
        } else {
            self.map.get(&font_size).unwrap()
        }
    }

    pub(crate) fn load_queued_fonts(
        &mut self,
        rl: &mut RaylibHandle,
        raylib_thread: &RaylibThread,
    ) -> Result<(), RaylibError> {
        for size in self.to_load.clone().into_iter() {
            self.load(size, rl, raylib_thread)?;
        }
        self.to_load.clear();
        Ok(())
    }
}