dvd_render/
sequence.rs

1use crate::grid::Grid;
2use std::collections::{HashMap, VecDeque, HashSet};
3use core::num::NonZeroU8;
4
5#[derive(Clone)]
6pub struct Frame<const W: usize, const H: usize> {
7	grid: Grid<W, H>,
8	pub frame_hold: NonZeroU8
9}
10
11impl<const W: usize, const H: usize> Frame<W, H> {
12	/// display a grid for a single frame
13	pub fn single(grid: Grid<W, H>) -> Self {
14		Self { grid, frame_hold: NonZeroU8::MIN }
15	}
16
17	/// hold on a grid for some amount of frames
18	pub fn variable(grid: Grid<W, H>, frame_hold: NonZeroU8) -> Self {
19		Self { grid, frame_hold }
20	}
21
22	pub(crate) fn serialize(self, lut: &HashMap<char, u32>) -> Vec<u8> {
23		self.grid.cells().iter().flat_map(|row| {
24			row.iter().map(|cell| {
25				*lut.get(&cell.character()).expect("invariant upheld by type system")
26			}).flat_map(u32::to_ne_bytes)
27		}).collect()
28	}
29}
30
31pub enum FontSize {
32	Pixel(f32),
33	PixelXY { x: f32, y: f32 },
34	Point(f32)
35}
36
37pub struct Px(pub f32);
38
39impl From<Px> for FontSize {
40	fn from(s: Px) -> FontSize {
41		FontSize::Pixel(s.0)
42	}
43}
44
45impl From<(Px, Px)> for FontSize {
46	fn from(xy: (Px, Px)) -> FontSize {
47		FontSize::PixelXY { x: xy.0.0, y: xy.1.0 }
48	}
49}
50
51impl From<[Px; 2]> for FontSize {
52	fn from(xy: [Px; 2]) -> FontSize {
53		FontSize::PixelXY { x: xy[0].0, y: xy[1].0 }
54	}
55}
56
57pub struct Pt(pub f32);
58
59impl From<Pt> for FontSize {
60	fn from(pt: Pt) -> FontSize {
61		FontSize::Point(pt.0)
62	}
63}
64
65pub struct GridSequence<const W: usize, const H: usize> {
66	pub framerate: NonZeroU8,
67	frames: VecDeque<Frame<W, H>>,
68	pub font_scale: FontSize,
69	glyph_set: HashSet<char>
70}
71
72impl<const W: usize, const H: usize> GridSequence<W, H> {
73	pub fn new(s: impl Into<FontSize>) -> Self {
74		Self {
75			framerate: NonZeroU8::MIN,
76			frames: VecDeque::new(),
77			font_scale: s.into(),
78			glyph_set: HashSet::new()
79		}
80	}
81
82	/// push a frame to the beginning of the sequence
83	pub fn prepend(&mut self, frame: Frame<W, H>) {
84		for c in frame.grid.chars() {
85			self.glyph_set.insert(c);
86		}
87
88		self.frames.push_front(frame);
89	}
90
91	/// push a frame to the end of the sequence
92	pub fn append(&mut self, frame: Frame<W, H>) {
93		for c in frame.grid.chars() {
94			self.glyph_set.insert(c);
95		}
96
97		self.frames.push_back(frame);
98	}
99
100	#[inline]
101	pub fn glyph_set(&self) -> &HashSet<char> {
102		&self.glyph_set
103	}
104
105	#[inline]
106	pub(crate) fn pop(&mut self) -> Option<Frame<W, H>> {
107		self.frames.pop_front()
108	}
109
110	pub(crate) fn resolve_px_scale<F: ab_glyph::Font>(&self, font: F) -> ab_glyph::PxScale {
111		match self.font_scale {
112			FontSize::Pixel(s) => ab_glyph::PxScale::from(s),
113			FontSize::PixelXY { x, y } => ab_glyph::PxScale { x, y },
114			FontSize::Point(pt) => font.pt_to_px_scale(pt).expect("not sure why this would fail?")
115		}
116	}
117}