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<WindowContext>,
colour: Color,
) -> Result<Texture<'a>, 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())
}
}