use std::sync::LazyLock; use sdl2::{pixels::{Color, PixelFormatEnum}, rect::Rect, render::{Texture, TextureCreator, TextureValueError}, surface::Surface, video::WindowContext}; pub struct RenderableCharacter { /** The width of the character, indicating where to break into a newline */ pub width: u16, /** The height of the character, derived from data's length divided by width */ pub height: u16, /** The raw alpha layer of the character */ pub data: &'static [u8], } /** A trait describing a generated font. We use traits implemented by each font because it's somehow optimized better in preliminary testing(?) */ pub trait BakedFont { fn has_char(&self, character: char) -> bool; fn get_char_bytes(&self, character: char) -> &'static [u8]; fn get_char(&self, character: char) -> RenderableCharacter { let bytes = self.get_char_bytes(character); let width = (bytes[0] as u16) | (bytes[1] as u16 >> 8); let data = &bytes[2..]; RenderableCharacter { width, height: data.len() as u16 / width, data, } } } impl RenderableCharacter { /** Alpha value of colour is currently ignored! */ pub fn to_surface(&self, colour: Color) -> Surface<'static> { let mut surface = Surface::new( self.width.into(), self.height.into(), PixelFormatEnum::RGBA32, ) .unwrap(); surface.with_lock_mut(|buffer: &mut [u8]| { let mut idx: usize = 0; print!("{} ({}x{})", self.data.len() * 4, self.width, self.height); for pixel in self.data { let index = idx * 4; buffer[index] = colour.r; // Red buffer[index + 1] = colour.g; // Green buffer[index + 2] = colour.b; // Blue buffer[index + 3] = *pixel; // Alpha idx += 1; } }); surface } /** Colour Alpha Channel is ignored */ pub fn to_texture<'a>( &self, texture_creator: &'a TextureCreator, colour: Color, ) -> Result, TextureValueError> { let surface = self.to_surface(colour); surface.as_texture(texture_creator) } pub fn to_rect(&self, x: i32, y: i32) -> Rect { Rect::new(x, y, self.width.into(), self.height.into()) } }