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<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())
}
}
pub struct Font<'a> {
pub texture: &'a [u8],
pub glyphs: Vec<*const Glyph>,
}
pub const MEOW_FONT: LazyLock<Font> = 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<WindowContext>) -> 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;