use std::sync::LazyLock; use sdl2::{ pixels::{Color, PixelFormatEnum}, rect::{Point, 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], /** The offset to draw the character at */ pub offset: Point, } /** 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 = u16::from_le_bytes(bytes[0..2].try_into().unwrap()); let offset_x = i32::from_le_bytes(bytes[2..6].try_into().unwrap()); let offset_y = i32::from_le_bytes(bytes[6..10].try_into().unwrap()); let data = &bytes[10..]; let height = if data.len() == 0 { 0 } else { data.len() as u16 / width }; RenderableCharacter { width, height, offset: Point::new(offset_x, offset_y), data, } } } impl RenderableCharacter { /** Alpha value of colour is currently ignored! */ pub fn to_surface(&self, colour: Color) -> Surface<'static> { let mut surface = Surface::new( if self.width == 0 { 1 } else { self.width.into() }, if self.height == 0 { 1 } else { self.height.into() }, PixelFormatEnum::RGBA32, ) .unwrap(); if self.width != 0 || self.height != 0 { surface.with_lock_mut(|buffer: &mut [u8]| { let mut idx: usize = 0; 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; } }); } else { // Blank surface.with_lock_mut(|buffer: &mut [u8]| { for index in 0..buffer.len() { buffer[index] = 0; } }) } 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 { println!("{:#?}",self.offset); Rect::new( x + self.offset.x, y + self.offset.y, i32::from(self.width).try_into().unwrap(), i32::from(self.height).try_into().unwrap(), ) } }