1use async_channel::Sender;
20use endbasic_std::Signal;
21use endbasic_std::console::{Console, ConsoleSpec, Resolution};
22use std::cell::RefCell;
23use std::fs::File;
24use std::io::{self, Write};
25use std::num::NonZeroU32;
26use std::path::PathBuf;
27use std::rc::Rc;
28use tempfile::TempDir;
29
30mod console;
31mod font;
32mod host;
33
34const DEFAULT_RESOLUTION_PIXELS: (u32, u32) = (800, 600);
36
37const DEFAULT_FONT_BYTES: &[u8] = include_bytes!("IBMPlexMono-Regular-6.0.0.ttf");
39
40const DEFAULT_FONT_SIZE: u16 = 16;
42
43fn string_error_to_io_error(e: String) -> io::Error {
45 io::Error::other(e)
46}
47
48pub(crate) struct TempFont {
50 dir: TempDir,
51}
52
53impl TempFont {
54 pub(crate) fn default_font() -> io::Result<Self> {
56 let dir = tempfile::tempdir()?;
57 let mut file = File::create(dir.path().join("font.ttf"))?;
58 file.write_all(DEFAULT_FONT_BYTES)?;
59 Ok(Self { dir })
60 }
61
62 pub(crate) fn path(&self) -> PathBuf {
64 self.dir.path().join("font.ttf")
65 }
66}
67
68pub fn setup(
70 spec: &mut ConsoleSpec,
71 signals_tx: Sender<Signal>,
72) -> io::Result<Rc<RefCell<dyn Console>>> {
73 let resolution: Resolution = spec.take_keyed_flag("resolution")?.unwrap_or_else(|| {
74 let width = NonZeroU32::new(DEFAULT_RESOLUTION_PIXELS.0).unwrap();
75 let height = NonZeroU32::new(DEFAULT_RESOLUTION_PIXELS.1).unwrap();
76 Resolution::Windowed((width, height))
77 });
78
79 let default_fg_color = spec.take_keyed_flag::<u8>("fg_color")?;
80 let default_bg_color = spec.take_keyed_flag::<u8>("bg_color")?;
81
82 let font_path = spec.take_keyed_flag::<PathBuf>("font_path")?;
83
84 let font_size = spec.take_keyed_flag("font_size")?.unwrap_or(DEFAULT_FONT_SIZE);
85
86 let console = match font_path {
87 None => {
88 let default_font = TempFont::default_font()?;
89 console::SdlConsole::new(
90 resolution,
91 default_fg_color,
92 default_bg_color,
93 default_font.path(),
94 font_size,
95 signals_tx,
96 )?
97 }
100 Some(font_path) => console::SdlConsole::new(
101 resolution,
102 default_fg_color,
103 default_bg_color,
104 font_path.to_owned(),
105 font_size,
106 signals_tx,
107 )?,
108 };
109 Ok(Rc::from(RefCell::from(console)))
110}