aboutsummaryrefslogblamecommitdiffstats
path: root/src/font.rs
blob: fc5217ea97f900aff8ed169be6c251d128c6cd1c (plain) (tree)
1
2
3
4
5
6
7
8
9

                        






                                                       
 
                                
                                                                             
                 


                                                                                 
                          

                                            

   


                                                                                                       
                     


                                                              
                                               








                                                                        
                         
            

                                             
           

     
 



                                                               









                           


                              



















                                                 











                                                       






                                                 

   
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<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 {
    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(),
    )
  }
}