make fonts generic over GeneralBitmap types
this also includes a semi-important change where the existing BitmaskCharacter draw implementation will now not draw anything if FontRenderOpts::None is passed in, instead of just substituting color 0. this probably makes more sense this way anyway
This commit is contained in:
parent
434bd6dbed
commit
986a2a9677
|
@ -3,6 +3,7 @@ use std::path::Path;
|
|||
use anyhow::Result;
|
||||
|
||||
use ggdt::audio::*;
|
||||
use ggdt::graphics::*;
|
||||
use ggdt::graphics::indexed::*;
|
||||
use ggdt::system::*;
|
||||
use ggdt::utils::rnd_value;
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::Path;
|
|||
use anyhow::Result;
|
||||
|
||||
use ggdt::*;
|
||||
use ggdt::graphics::*;
|
||||
use ggdt::graphics::indexed::*;
|
||||
use ggdt::math::*;
|
||||
use ggdt::system::*;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ggdt::entities::*;
|
||||
use ggdt::events::*;
|
||||
use ggdt::graphics::*;
|
||||
use ggdt::graphics::indexed::*;
|
||||
use ggdt::math::*;
|
||||
use ggdt::states::*;
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::path::Path;
|
|||
|
||||
use ggdt::base::*;
|
||||
use ggdt::entities::*;
|
||||
use ggdt::graphics::font::*;
|
||||
use ggdt::graphics::indexed::*;
|
||||
use ggdt::states::*;
|
||||
use ggdt::system::*;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
|
||||
use ggdt::{SCREEN_BOTTOM, SCREEN_RIGHT};
|
||||
use ggdt::graphics::*;
|
||||
use ggdt::graphics::indexed::*;
|
||||
use ggdt::system::*;
|
||||
use ggdt::utils::rnd_value;
|
||||
|
|
|
@ -35,6 +35,9 @@ pub trait GeneralBitmap: Sized + Clone {
|
|||
/// Returns the height of the bitmap in pixels.
|
||||
fn height(&self) -> u32;
|
||||
|
||||
/// Returns the current clipping region set on this bitmap.
|
||||
fn clip_region(&self) -> &Rect;
|
||||
|
||||
/// Returns a rect representing the full bitmap boundaries, ignoring the current clipping
|
||||
/// region set on this bitmap.
|
||||
fn full_bounds(&self) -> Rect;
|
||||
|
@ -111,6 +114,10 @@ impl GeneralBitmap for indexed::Bitmap {
|
|||
self.height()
|
||||
}
|
||||
|
||||
fn clip_region(&self) -> &Rect {
|
||||
self.clip_region()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn full_bounds(&self) -> Rect {
|
||||
self.full_bounds()
|
||||
|
|
|
@ -4,12 +4,14 @@ use std::io::{BufReader, BufWriter, Cursor};
|
|||
use std::path::Path;
|
||||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use num_traits::{PrimInt, Unsigned};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::graphics::*;
|
||||
use crate::graphics::indexed::*;
|
||||
use crate::math::*;
|
||||
|
||||
pub static VGA_FONT_BYTES: &[u8] = include_bytes!("../../../assets/vga.fnt");
|
||||
pub static VGA_FONT_BYTES: &[u8] = include_bytes!("../../assets/vga.fnt");
|
||||
|
||||
pub const NUM_CHARS: usize = 256;
|
||||
pub const CHAR_HEIGHT: usize = 8;
|
||||
|
@ -25,14 +27,16 @@ pub enum FontError {
|
|||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum FontRenderOpts {
|
||||
Color(u8),
|
||||
pub enum FontRenderOpts<PixelType: PrimInt + Unsigned> {
|
||||
Color(PixelType),
|
||||
None,
|
||||
}
|
||||
|
||||
pub trait Character {
|
||||
fn bounds(&self) -> &Rect;
|
||||
fn draw(&self, dest: &mut Bitmap, x: i32, y: i32, opts: FontRenderOpts);
|
||||
fn draw<BitmapType>(&self, dest: &mut BitmapType, x: i32, y: i32, opts: FontRenderOpts<BitmapType::PixelType>)
|
||||
where
|
||||
BitmapType: GeneralBitmap;
|
||||
}
|
||||
|
||||
pub trait Font {
|
||||
|
@ -41,7 +45,9 @@ pub trait Font {
|
|||
fn character(&self, ch: char) -> &Self::CharacterType;
|
||||
fn space_width(&self) -> u8;
|
||||
fn line_height(&self) -> u8;
|
||||
fn measure(&self, text: &str, opts: FontRenderOpts) -> (u32, u32);
|
||||
fn measure<PixelType>(&self, text: &str, opts: FontRenderOpts<PixelType>) -> (u32, u32)
|
||||
where
|
||||
PixelType: PrimInt + Unsigned;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -56,7 +62,10 @@ impl Character for BitmaskCharacter {
|
|||
&self.bounds
|
||||
}
|
||||
|
||||
fn draw(&self, dest: &mut Bitmap, x: i32, y: i32, opts: FontRenderOpts) {
|
||||
fn draw<BitmapType>(&self, dest: &mut BitmapType, x: i32, y: i32, opts: FontRenderOpts<BitmapType::PixelType>)
|
||||
where
|
||||
BitmapType: GeneralBitmap
|
||||
{
|
||||
// out of bounds check
|
||||
if ((x + self.bounds.width as i32) < dest.clip_region().x)
|
||||
|| ((y + self.bounds.height as i32) < dest.clip_region().y)
|
||||
|
@ -68,7 +77,11 @@ impl Character for BitmaskCharacter {
|
|||
|
||||
let color = match opts {
|
||||
FontRenderOpts::Color(color) => color,
|
||||
_ => 0,
|
||||
// this kind of highlights a weakness of this design i guess. what does it mean to render a BitmaskFont,
|
||||
// which has no inherent colour information in it, when there is no specific render colour passed in?
|
||||
// TODO: is it better to return an error here? should a BitmaskFont have a "default colour" to fall back to?
|
||||
// or, should a Bitmap have a "default colour" property we could fall back to? not sure!
|
||||
_ => return,
|
||||
};
|
||||
|
||||
// TODO: i'm sure this can be optimized, lol
|
||||
|
@ -195,7 +208,10 @@ impl Font for BitmaskFont {
|
|||
self.line_height
|
||||
}
|
||||
|
||||
fn measure(&self, text: &str, _opts: FontRenderOpts) -> (u32, u32) {
|
||||
fn measure<PixelType>(&self, text: &str, _opts: FontRenderOpts<PixelType>) -> (u32, u32)
|
||||
where
|
||||
PixelType: PrimInt + Unsigned
|
||||
{
|
||||
if text.is_empty() {
|
||||
return (0, 0);
|
||||
}
|
||||
|
@ -249,29 +265,29 @@ pub mod tests {
|
|||
{
|
||||
let font = BitmaskFont::load_from_file(Path::new("./assets/vga.fnt"))?;
|
||||
|
||||
assert_eq!((40, 8), font.measure("Hello", FontRenderOpts::None));
|
||||
assert_eq!((40, 16), font.measure("Hello\nthere", FontRenderOpts::None));
|
||||
assert_eq!((88, 24), font.measure("longer line\nshort\nthe end", FontRenderOpts::None));
|
||||
assert_eq!((0, 0), font.measure("", FontRenderOpts::None));
|
||||
assert_eq!((0, 0), font.measure(" ", FontRenderOpts::None));
|
||||
assert_eq!((40, 16), font.measure("\nhello", FontRenderOpts::None));
|
||||
assert_eq!((0, 0), font.measure("\n", FontRenderOpts::None));
|
||||
assert_eq!((40, 8), font.measure("hello\n", FontRenderOpts::None));
|
||||
assert_eq!((40, 24), font.measure("hello\n\nthere", FontRenderOpts::None));
|
||||
assert_eq!((40, 8), font.measure("Hello", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((40, 16), font.measure("Hello\nthere", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((88, 24), font.measure("longer line\nshort\nthe end", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((0, 0), font.measure("", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((0, 0), font.measure(" ", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((40, 16), font.measure("\nhello", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((0, 0), font.measure("\n", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((40, 8), font.measure("hello\n", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((40, 24), font.measure("hello\n\nthere", FontRenderOpts::<u8>::None));
|
||||
}
|
||||
|
||||
{
|
||||
let font = BitmaskFont::load_from_file(Path::new("./test-assets/small.fnt"))?;
|
||||
|
||||
assert_eq!((22, 7), font.measure("Hello", FontRenderOpts::None));
|
||||
assert_eq!((24, 14), font.measure("Hello\nthere", FontRenderOpts::None));
|
||||
assert_eq!((50, 21), font.measure("longer line\nshort\nthe end", FontRenderOpts::None));
|
||||
assert_eq!((0, 0), font.measure("", FontRenderOpts::None));
|
||||
assert_eq!((0, 0), font.measure(" ", FontRenderOpts::None));
|
||||
assert_eq!((21, 14), font.measure("\nhello", FontRenderOpts::None));
|
||||
assert_eq!((0, 0), font.measure("\n", FontRenderOpts::None));
|
||||
assert_eq!((21, 7), font.measure("hello\n", FontRenderOpts::None));
|
||||
assert_eq!((24, 21), font.measure("hello\n\nthere", FontRenderOpts::None));
|
||||
assert_eq!((22, 7), font.measure("Hello", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((24, 14), font.measure("Hello\nthere", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((50, 21), font.measure("longer line\nshort\nthe end", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((0, 0), font.measure("", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((0, 0), font.measure(" ", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((21, 14), font.measure("\nhello", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((0, 0), font.measure("\n", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((21, 7), font.measure("hello\n", FontRenderOpts::<u8>::None));
|
||||
assert_eq!((24, 21), font.measure("hello\n\nthere", FontRenderOpts::<u8>::None));
|
||||
}
|
||||
|
||||
Ok(())
|
|
@ -1,5 +1,6 @@
|
|||
use std::mem::swap;
|
||||
|
||||
use crate::graphics::*;
|
||||
use crate::graphics::indexed::*;
|
||||
use crate::math::*;
|
||||
|
||||
|
@ -76,13 +77,13 @@ impl Bitmap {
|
|||
|
||||
/// Renders a single character using the font given.
|
||||
#[inline]
|
||||
pub fn print_char<T: Font>(&mut self, ch: char, x: i32, y: i32, opts: FontRenderOpts, font: &T) {
|
||||
pub fn print_char<T: Font>(&mut self, ch: char, x: i32, y: i32, opts: FontRenderOpts<u8>, font: &T) {
|
||||
font.character(ch)
|
||||
.draw(self, x, y, opts);
|
||||
}
|
||||
|
||||
/// Renders the string of text using the font given.
|
||||
pub fn print_string<T: Font>(&mut self, text: &str, x: i32, y: i32, opts: FontRenderOpts, font: &T) {
|
||||
pub fn print_string<T: Font>(&mut self, text: &str, x: i32, y: i32, opts: FontRenderOpts<u8>, font: &T) {
|
||||
let mut current_x = x;
|
||||
let mut current_y = y;
|
||||
for ch in text.chars() {
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
|
||||
pub use self::bitmap::*;
|
||||
pub use self::blendmap::*;
|
||||
pub use self::font::*;
|
||||
pub use self::palette::*;
|
||||
|
||||
pub mod bitmap;
|
||||
pub mod blendmap;
|
||||
pub mod font;
|
||||
pub mod palette;
|
|
@ -1,7 +1,9 @@
|
|||
pub use self::bitmap::*;
|
||||
pub use self::bitmapatlas::*;
|
||||
pub use self::font::*;
|
||||
|
||||
pub mod bitmap;
|
||||
pub mod bitmapatlas;
|
||||
pub mod font;
|
||||
pub mod indexed;
|
||||
pub mod rgb;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//! instance to provide something resembling an old DOS VGA mode 13h style experience (there are differences, however).
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use ggdt::graphics::*;
|
||||
//! use ggdt::graphics::indexed::*;
|
||||
//! use ggdt::system::*;
|
||||
//!
|
||||
|
@ -30,6 +31,7 @@
|
|||
use sdl2::video::Window;
|
||||
|
||||
use crate::system::*;
|
||||
use crate::graphics::*;
|
||||
use crate::graphics::indexed::*;
|
||||
|
||||
/// Configuration / builder for configuring and constructing an instance of [`DosLike`].
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::path::Path;
|
|||
use std::rc::Rc;
|
||||
|
||||
use ggdt::{SCREEN_HEIGHT, SCREEN_WIDTH};
|
||||
use ggdt::graphics::*;
|
||||
use ggdt::graphics::indexed::*;
|
||||
|
||||
fn setup() -> (Bitmap, Palette) {
|
||||
|
|
Loading…
Reference in a new issue