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 pub fn single(grid: Grid<W, H>) -> Self {
14 Self { grid, frame_hold: NonZeroU8::MIN }
15 }
16
17 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 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 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}