diff --git a/src/bmfont.rs b/src/bmfont.rs new file mode 100644 index 0000000..ce016c8 --- /dev/null +++ b/src/bmfont.rs @@ -0,0 +1,109 @@ +use std::collections::HashMap; +use std::io; + +use byteorder::{LE, ReadBytesExt}; + +use crate::ggez::GameError::ResourceLoadError; +use crate::ggez::GameResult; +use crate::str; + +#[derive(Debug)] +pub struct BmChar { + pub x: u16, + pub y: u16, + pub width: u16, + pub height: u16, + pub xoffset: i16, + pub yoffset: i16, + pub xadvance: i16, + pub page: u8, + pub chnl: u8, +} + +#[derive(Debug)] +pub struct BmFont { + pub pages: u16, + pub font_size: i16, + pub line_height: u16, + pub base: u16, + pub chars: HashMap, +} + +const MAGIC: [u8; 4] = [b'B', b'M', b'F', 3]; + +impl BmFont { + pub fn load_from(mut data: R) -> GameResult { + let mut magic = [0u8; 4]; + let mut pages = 0u16; + let mut chars = HashMap::with_capacity(128); + let mut font_size = 0i16; + let mut line_height = 0u16; + let mut base = 0u16; + + data.read_exact(&mut magic)?; + + if magic != MAGIC { + return Err(ResourceLoadError(str!( "Invalid magic"))); + } + + while let Ok(block_type) = data.read_u8() { + let length = data.read_u32::()?; + match block_type { + 1 => { + font_size = data.read_i16::()?; + + data.seek(io::SeekFrom::Current(length as i64 - 2))?; + } + 2 => { + line_height = data.read_u16::()?; + base = data.read_u16::()?; + data.seek(io::SeekFrom::Current(4))?; + pages = data.read_u16::()?; + + data.seek(io::SeekFrom::Current(length as i64 - 10))?; + } + 3 | 5 => { + data.seek(io::SeekFrom::Current(length as i64))?; + } + 4 => { + let count = length / 20; + for _ in 0..count { + let id = data.read_u32::()?; + let x = data.read_u16::()?; + let y = data.read_u16::()?; + let width = data.read_u16::()?; + let height = data.read_u16::()?; + let xoffset = data.read_i16::()?; + let yoffset = data.read_i16::()?; + let xadvance = data.read_i16::()?; + let page = data.read_u8()?; + let chnl = data.read_u8()?; + + if let Some(chr) = std::char::from_u32(id) { + chars.insert(chr, BmChar { + x, + y, + width, + height, + xoffset, + yoffset, + xadvance, + page, + chnl, + }); + } + } + } + _ => { return Err(ResourceLoadError(str!( "Unknown block type."))); } + } + } + + Ok(Self { + pages, + font_size, + line_height, + base, + chars, + }) + } +} diff --git a/src/main.rs b/src/main.rs index e656c94..705fc07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ use log::*; use pretty_env_logger::env_logger::Env; use winit::{ElementState, Event, KeyboardInput, WindowEvent}; +use crate::builtin_fs::BuiltinFS; use crate::caret::{Caret, CaretType}; use crate::common::{Direction, FadeState}; use crate::engine_constants::EngineConstants; @@ -40,8 +41,8 @@ use crate::stage::StageData; use crate::text_script::TextScriptVM; use crate::texture_set::TextureSet; use crate::ui::UI; -use crate::builtin_fs::BuiltinFS; +mod bmfont; mod builtin_fs; mod caret; mod common;