use crate::*;
use std::collections::{HashMap, HashSet};
use sdl3::{pixels::Color, render::{Canvas, Texture, TextureCreator, TextureValueError, UpdateTextureError}, video::{Window, WindowContext}, Error};
use ab_glyph::Font;
pub struct TextRenderingSettings<'a, 'b, F: ThreadSafeFont> {
pub size: f32,
#[allow(missing_docs)]
pub h_align: HAlign,
#[allow(missing_docs)]
pub v_align: VAlign,
#[allow(missing_docs)]
pub foreground: Color,
pub background: Color,
#[allow(missing_docs)]
pub canvas: &'a mut Canvas<Window>,
#[allow(missing_docs)]
pub texture_creator: &'b TextureCreator<WindowContext>,
#[allow(missing_docs)]
pub text_cache: &'a mut TextCache<'b, F>,
}
impl<'a, 'b, F: ThreadSafeFont> TextRenderingSettings<'a, 'b, F> {
#[allow(clippy::too_many_arguments)]
pub fn new_regular(size: f32, h_align: impl Into<HAlign>, v_align: impl Into<VAlign>, foreground: impl Into<Color>, canvas: &'a mut Canvas<Window>, texture_creator: &'b TextureCreator<WindowContext>, text_cache: &'a mut TextCache<'b, F>) -> Self {
Self {
size,
h_align: h_align.into(),
v_align: v_align.into(),
foreground: foreground.into(),
background: Color::RGB(127, 127, 127),
canvas,
texture_creator,
text_cache,
}
}
#[allow(clippy::too_many_arguments)]
pub fn new_subpixel(size: u32, h_align: impl Into<HAlign>, v_align: impl Into<VAlign>, foreground: impl Into<Color>, background: impl Into<Color>, canvas: &'a mut Canvas<Window>, texture_creator: &'b TextureCreator<WindowContext>, text_cache: &'a mut TextCache<'b, F>) -> Self {
Self {
size: size as f32,
h_align: h_align.into(),
v_align: v_align.into(),
foreground: foreground.into(),
background: background.into(),
canvas,
texture_creator,
text_cache,
}
}
}
pub trait ThreadSafeFont: Font + Send + Sync {}
impl<F: Font + Send + Sync> ThreadSafeFont for F {}
pub struct TextCache<'a, F: ThreadSafeFont> {
pub(crate) map_regular: HashMap<(char, Color), (Texture<'a>, u32, u32, f32, f32)>,
pub(crate) set_regular: HashSet<(char, Color)>,
pub(crate) map_subpixel: HashMap<(char, u32, Color, Color), (Texture<'a>, u32, u32, f32, f32)>,
pub(crate) set_subpixel: HashSet<(char, u32, Color, Color)>,
pub(crate) font: F,
}
impl<'a, F: ThreadSafeFont> TextCache<'a, F> {
#[inline]
pub fn new(font: F) -> Self {
Self {
map_regular: HashMap::new(),
set_regular: HashSet::new(),
map_subpixel: HashMap::new(),
set_subpixel: HashSet::new(),
font,
}
}
pub fn switch_font(&mut self, new_font: F) {
self.font = new_font;
self.clear();
}
pub fn clear(&mut self) {
self.map_regular.clear();
self.set_regular.clear();
self.map_subpixel.clear();
self.set_subpixel.clear();
}
}
#[derive(Copy, Clone)]
pub enum HAlign {
Left,
Center,
Right,
}
impl HAlign {
pub(crate) fn get_offset(&self, width: f32) -> f32 {
match self {
Self::Left => 0.0,
Self::Center => width * -0.5,
Self::Right => -width,
}
}
}
#[derive(Copy, Clone)]
pub enum VAlign {
Top,
Center,
Bottom,
}
impl VAlign {
pub(crate) fn get_offset(&self, height: f32) -> f32 {
match self {
Self::Top => height * TEXT_HEIGHT_MULT,
Self::Center => height * TEXT_HEIGHT_MULT * 0.5,
Self::Bottom => 0.0,
}
}
}
#[derive(Debug)]
pub enum RenderTextError {
SdlError (Error),
SdlTextureValueError (TextureValueError),
SdlUpdateTextureError (UpdateTextureError),
}
impl From<Error> for RenderTextError {
fn from(value: Error) -> Self {
Self::SdlError (value)
}
}
impl From<TextureValueError> for RenderTextError {
fn from(value: TextureValueError) -> Self {
Self::SdlTextureValueError (value)
}
}
impl From<UpdateTextureError> for RenderTextError {
fn from(value: UpdateTextureError) -> Self {
Self::SdlUpdateTextureError (value)
}
}
impl std::fmt::Display for RenderTextError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::SdlError (err) => write!(f, "Render Text Error: {err}"),
Self::SdlTextureValueError (err) => write!(f, "Render Text Error: {err}"),
Self::SdlUpdateTextureError (err) => write!(f, "Render Text Error: {err}"),
}
}
}
impl std::error::Error for RenderTextError {}