pub const UWU_HEIGHT: u32 = 24; pub const UWU_WIDTH: u32 = 16; use std::sync::LazyLock; pub struct Glyph { x: i32, } fn insert_value(arr: &mut Vec<*const Glyph>, idx: usize, glyph: *const Glyph) { if arr.len() <= idx { while arr.len() <= idx { arr.push(0 as *const Glyph); } } arr[idx] = glyph; } 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()) } } pub struct Font<'a> { pub texture: &'a [u8], pub glyphs: Vec<*const Glyph>, } pub const MEOW_FONT: LazyLock = LazyLock::new(|| Font { texture: include_bytes!("../assets/fonts/uwu-logo-20px.png"), glyphs: { let a: &mut Vec<*const Glyph> = &mut Vec::new(); insert_value(a, 32, &Glyph { x: 2 }); a.to_vec() }, }); mod sprite_sheets { use super::{BakedFont, MEOW_FONT, UWU_HEIGHT, UWU_WIDTH}; use sdl2::{ // image::LoadTexture, pixels::PixelFormatEnum, rect::Rect, render::{Canvas, TextureCreator}, surface::Surface, video::WindowContext, }; pub struct UwUFont<'a> { sheet: Surface<'a>, } fn uwu_get_n(n: u32) -> Rect { Rect::new((UWU_WIDTH * n) as i32, 0, UWU_WIDTH, UWU_HEIGHT) } #[inline] fn uwu_u() -> Rect { return uwu_get_n(0); } #[inline] fn uwu_w() -> Rect { return uwu_get_n(1); } #[inline] fn uwu_s() -> Rect { return uwu_get_n(2); } #[inline] fn uwu_p() -> Rect { return uwu_get_n(3); } #[inline] fn uwu_a() -> Rect { return uwu_get_n(4); } #[inline] fn uwu_c() -> Rect { return uwu_get_n(5); } #[inline] fn uwu_e() -> Rect { return uwu_get_n(6); } impl<'a> UwUFont<'a> { pub fn new(texture_creator: &'a TextureCreator) -> UwUFont<'a> { let surface = Surface::new(112, 24, PixelFormatEnum::RGB24).unwrap(); let mut canvas = Canvas::from_surface(surface).unwrap(); let tc = canvas.texture_creator(); // let tx = tc.load_texture_bytes(MEOW_FONT.texture).unwrap(); // canvas.copy(&tx, None, None).unwrap(); canvas.present(); let sheet = canvas.into_surface(); UwUFont { sheet } } pub fn pos_to_rect(x: i32, y: i32) -> Rect { return Rect::new(x, y, UWU_WIDTH, UWU_HEIGHT); } pub fn char_to_surface(&self, char: Rect) -> Surface { let mut char_surface = Surface::new(UWU_WIDTH, UWU_HEIGHT, PixelFormatEnum::RGB24).unwrap(); self .sheet .blit(char, &mut char_surface, Self::pos_to_rect(0, 0)) .unwrap(); char_surface } pub fn u_surface(&self) -> Surface { return self.char_to_surface(uwu_u()); } pub fn w_surface(&self) -> Surface { return self.char_to_surface(uwu_w()); } pub fn p_surface(&self) -> Surface { return self.char_to_surface(uwu_p()); } } } use std::str::Bytes; use sdl2::pixels::{Color, PixelFormatEnum}; use sdl2::rect::Rect; use sdl2::render::{Canvas, Texture, TextureCreator, TextureValueError}; use sdl2::surface::Surface; use sdl2::video::WindowContext; pub use sprite_sheets::UwUFont;