diff --git a/eg-bdf-examples/examples/font_viewer.rs b/eg-bdf-examples/examples/font_viewer.rs index e0664e9..1fae14a 100644 --- a/eg-bdf-examples/examples/font_viewer.rs +++ b/eg-bdf-examples/examples/font_viewer.rs @@ -2,12 +2,16 @@ use anyhow::{anyhow, Context, Result}; use eg_bdf::BdfTextStyle; use eg_font_converter::{FontConverter, Mapping}; use embedded_graphics::{ + geometry::AnchorPoint, + mono_font::{ascii::FONT_6X10, MonoTextStyle}, pixelcolor::Rgb888, prelude::*, primitives::{Line, PrimitiveStyle}, - text::{Baseline, Text}, + text::{renderer::TextRenderer, Alignment, Baseline, Text, TextStyleBuilder}, +}; +use embedded_graphics_simulator::{ + sdl2::Keycode, OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, }; -use embedded_graphics_simulator::{OutputSettingsBuilder, SimulatorDisplay, Window}; fn main() { if let Err(e) = try_main() { @@ -15,7 +19,11 @@ fn main() { } } -fn draw_text(display: &mut SimulatorDisplay, text: &Text>) -> Point { +/// Draws a text and its bounding box. +fn draw_text>( + display: &mut SimulatorDisplay, + text: &Text, +) -> Point { text.bounding_box() .into_styled(PrimitiveStyle::with_stroke(Rgb888::CSS_DARK_ORANGE, 1)) .draw(display) @@ -24,25 +32,11 @@ fn draw_text(display: &mut SimulatorDisplay, text: &Text Result<()> { - let file = std::env::args() - .nth(1) - .ok_or_else(|| anyhow!("missing filename"))?; - - let output = FontConverter::with_file(&file, "BDF_FILE") - .glyphs(Mapping::Ascii) - .missing_glyph_substitute('?') - .convert_eg_bdf() - .with_context(|| "couldn't convert font")?; - - let font = output.as_font(); - let style = BdfTextStyle::new(&font, Rgb888::WHITE); - - let settings = OutputSettingsBuilder::new().scale(3).build(); - let mut window = Window::new("Font viewer", &settings); - - let mut display = SimulatorDisplay::::new(Size::new(600, 200)); - +fn draw + Copy>( + display: &mut SimulatorDisplay, + style: S, + line_height: u32, +) { let abc = ('a'..='z').collect::(); let digits = ('0'..='9').collect::(); let string = format!( @@ -52,30 +46,31 @@ fn try_main() -> Result<()> { digits ); - let position = Point::new(20, 20); + let position = Point::new(5, 5 + line_height as i32); Line::with_delta(position.y_axis(), Point::zero() + display.size().x_axis()) .into_styled(PrimitiveStyle::with_stroke(Rgb888::CSS_DIM_GRAY, 1)) - .draw(&mut display) + .draw(display) .unwrap(); let text = Text::new(&string, position, style); - draw_text(&mut display, &text); + draw_text(display, &text); - let position = Point::new(20, 150); + let position = display.bounding_box().anchor_point(AnchorPoint::BottomLeft) + + Point::new(5, -(line_height as i32) * 3 / 2); Line::with_delta(position.y_axis(), Point::zero() + display.size().x_axis()) .into_styled(PrimitiveStyle::with_stroke(Rgb888::CSS_DIM_GRAY, 1)) - .draw(&mut display) + .draw(display) .unwrap(); let p = draw_text( - &mut display, + display, &Text::with_baseline("Top ", position, style, Baseline::Top), ); let p = draw_text( - &mut display, + display, &Text::with_baseline( "Middle ", Point::new(p.x, position.y), @@ -85,7 +80,7 @@ fn try_main() -> Result<()> { ); let p = draw_text( - &mut display, + display, &Text::with_baseline( "Bottom ", Point::new(p.x, position.y), @@ -95,7 +90,7 @@ fn try_main() -> Result<()> { ); draw_text( - &mut display, + display, &Text::with_baseline( "Alphabetic", Point::new(p.x, position.y), @@ -103,8 +98,87 @@ fn try_main() -> Result<()> { Baseline::Alphabetic, ), ); +} + +fn try_main() -> Result<()> { + let file = std::env::args() + .nth(1) + .ok_or_else(|| anyhow!("missing filename"))?; + + let converted_font = FontConverter::with_file(&file, "BDF_FILE") + .glyphs(Mapping::Ascii) + .missing_glyph_substitute('?'); + + let output = converted_font + .convert_eg_bdf() + .with_context(|| "couldn't convert font")?; + let bdf_font = output.as_font(); - window.show_static(&display); + let output = converted_font + .convert_mono_font() + .with_context(|| "couldn't convert font")?; + let mono_font = output.as_font(); + + let hints_style = MonoTextStyle::new(&FONT_6X10, Rgb888::CSS_DIM_GRAY); + let bottom_right = TextStyleBuilder::new() + .baseline(Baseline::Bottom) + .alignment(Alignment::Right) + .build(); + + // TODO: add metrics getter + let line_height = bdf_font.ascent + bdf_font.descent; + let display_height = line_height * 8; + let display_width = (line_height * 25).max(display_height); + let display_size = Size::new(display_width, display_height); + + let mut display = SimulatorDisplay::::new(display_size); + + let scale = (1200 / display_size.width).max(1); + + let settings = OutputSettingsBuilder::new().scale(scale).build(); + let mut window = Window::new("Font viewer", &settings); + + let mut use_mono_font = false; + + 'main_loop: loop { + window.update(&display); + + for event in window.events() { + match event { + SimulatorEvent::KeyDown { keycode, .. } => match keycode { + Keycode::M => { + use_mono_font = !use_mono_font; + } + _ => {} + }, + SimulatorEvent::Quit => break 'main_loop, + _ => {} + } + } + + let mut hint = "Press M to toggle".to_string(); + + display.clear(Rgb888::BLACK).unwrap(); + if use_mono_font { + let style = MonoTextStyle::new(&mono_font, Rgb888::WHITE); + draw(&mut display, style, line_height); + + hint.insert_str(0, "Mono | "); + } else { + let style = BdfTextStyle::new(&bdf_font, Rgb888::WHITE); + draw(&mut display, style, line_height); + + hint.insert_str(0, "Bdf | "); + } + + let corner = display + .bounding_box() + .offset(-3) + .anchor_point(AnchorPoint::BottomRight); + Text::with_text_style(&hint, corner, hints_style, bottom_right) + .draw(&mut display) + .unwrap(); + } Ok(()) } diff --git a/eg-font-converter/src/lib.rs b/eg-font-converter/src/lib.rs index 10cbc03..f476d30 100644 --- a/eg-font-converter/src/lib.rs +++ b/eg-font-converter/src/lib.rs @@ -312,7 +312,7 @@ impl<'a> FontConverter<'a> { .try_get::(Property::FontAscent) .ok() .filter(|v| *v >= 0) - .unwrap() as u32; //TODO: convert to error + .unwrap_or_default() as u32; //TODO: convert to error let descent = bdf .metadata @@ -320,7 +320,7 @@ impl<'a> FontConverter<'a> { .try_get::(Property::FontDescent) .ok() .filter(|v| *v >= 0) - .unwrap() as u32; //TODO: convert to error + .unwrap_or_default() as u32; //TODO: convert to error // TODO: read from BDF and use correct fallbacks (https://www.x.org/docs/XLFD/xlfd.pdf 3.2.30) let underline_position = ascent + 1;