Use a core::fmt::Write instead

This commit is contained in:
Gwilym Kuiper 2022-04-06 21:13:57 +01:00
parent e3e29ab21b
commit 82c5ebf426
2 changed files with 55 additions and 28 deletions

View file

@ -6,6 +6,8 @@ use agb::{
include_font, include_font,
}; };
use core::fmt::Write;
const FONT: Font = include_font!("examples/font/yoster.ttf", 12); const FONT: Font = include_font!("examples/font/yoster.ttf", 12);
#[agb::entry] #[agb::entry]
@ -35,14 +37,10 @@ fn main(mut gba: agb::Gba) -> ! {
vram.remove_dynamic_tile(background_tile); vram.remove_dynamic_tile(background_tile);
FONT.render_text( let mut writer = FONT.render_text((0u16, 3u16).into(), 1, 2, &mut bg, &mut vram);
(0u16, 3u16).into(),
"Hello, World!\nThis is a font rendering example", writeln!(&mut writer, "Hello, World!").unwrap();
1, writeln!(&mut writer, "This is a font rendering example").unwrap();
2,
&mut bg,
&mut vram,
);
bg.commit(); bg.commit();
bg.show(); bg.show();

View file

@ -1,3 +1,5 @@
use core::fmt::{Error, Write};
use crate::fixnum::Vector2D; use crate::fixnum::Vector2D;
use crate::hash_map::HashMap; use crate::hash_map::HashMap;
@ -53,17 +55,46 @@ impl Font {
} }
impl Font { impl Font {
pub fn render_text( pub fn render_text<'a>(
&self, &'a self,
tile_pos: Vector2D<u16>, tile_pos: Vector2D<u16>,
text: &str,
foreground_colour: u8, foreground_colour: u8,
background_colour: u8, background_colour: u8,
bg: &mut RegularMap, bg: &'a mut RegularMap,
vram_manager: &mut VRamManager, vram_manager: &'a mut VRamManager,
) -> (i32, i32) { ) -> TextRenderer<'a> {
TextRenderer {
current_x_pos: 0,
current_y_pos: 0,
font: self,
tile_pos,
vram_manager,
bg,
background_colour,
foreground_colour,
}
}
}
pub struct TextRenderer<'a> {
current_x_pos: i32,
current_y_pos: i32,
font: &'a Font,
tile_pos: Vector2D<u16>,
vram_manager: &'a mut VRamManager,
bg: &'a mut RegularMap,
background_colour: u8,
foreground_colour: u8,
}
impl<'a> Write for TextRenderer<'a> {
fn write_str(&mut self, text: &str) -> Result<(), Error> {
let mut tiles = HashMap::new(); let mut tiles = HashMap::new();
let vram_manager = &mut self.vram_manager;
let foreground_colour = self.foreground_colour;
let background_colour = self.background_colour;
let mut render_pixel = |x: u16, y: u16| { let mut render_pixel = |x: u16, y: u16| {
let tile_x = (x / 8) as usize; let tile_x = (x / 8) as usize;
let tile_y = (y / 8) as usize; let tile_y = (y / 8) as usize;
@ -81,20 +112,18 @@ impl Font {
tile.tile_data[index / 8] |= colour << ((index % 8) * 4); tile.tile_data[index / 8] |= colour << ((index % 8) * 4);
}; };
let mut current_x_pos = 0i32;
let mut current_y_pos = 0i32;
for c in text.chars() { for c in text.chars() {
if c == '\n' { if c == '\n' {
current_y_pos += self.line_height; self.current_y_pos += self.font.line_height;
current_x_pos = 0; self.current_x_pos = 0;
continue; continue;
} }
let letter = self.letter(c); let letter = self.font.letter(c);
let x_start = (current_x_pos + letter.xmin as i32).max(0); let x_start = (self.current_x_pos + letter.xmin as i32).max(0);
let y_start = current_y_pos + self.ascent - letter.height as i32 - letter.ymin as i32; let y_start =
self.current_y_pos + self.font.ascent - letter.height as i32 - letter.ymin as i32;
for letter_y in 0..(letter.height as i32) { for letter_y in 0..(letter.height as i32) {
for letter_x in 0..(letter.width as i32) { for letter_x in 0..(letter.width as i32) {
@ -109,19 +138,19 @@ impl Font {
} }
} }
current_x_pos += letter.advance_width as i32; self.current_x_pos += letter.advance_width as i32;
} }
for ((x, y), tile) in tiles.into_iter() { for ((x, y), tile) in tiles.into_iter() {
bg.set_tile( self.bg.set_tile(
vram_manager, self.vram_manager,
(tile_pos.x + x as u16, tile_pos.y + y as u16).into(), (self.tile_pos.x + x as u16, self.tile_pos.y + y as u16).into(),
&tile.tile_set(), &tile.tile_set(),
TileSetting::from_raw(tile.tile_index()), TileSetting::from_raw(tile.tile_index()),
); );
vram_manager.remove_dynamic_tile(tile); self.vram_manager.remove_dynamic_tile(tile);
} }
(current_x_pos, current_y_pos + self.line_height) Ok(())
} }
} }