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 pub(crate) fn serialize_colors(&self) -> Vec<u8> {
31 self.grid.cells().iter().flat_map(|row| {
32 row.iter().flat_map(|cell| {
33 [cell.fg_color().0, cell.bg_color().0]
34 }).flatten()
35 }).collect()
36 }
37}
38
39pub enum FontSize {
40 Pixel(f32),
41 PixelXY { x: f32, y: f32 },
42 Point(f32)
43}
44
45pub struct Px(pub f32);
46
47impl From<Px> for FontSize {
48 fn from(s: Px) -> FontSize {
49 FontSize::Pixel(s.0)
50 }
51}
52
53impl From<(Px, Px)> for FontSize {
54 fn from(xy: (Px, Px)) -> FontSize {
55 FontSize::PixelXY { x: xy.0.0, y: xy.1.0 }
56 }
57}
58
59impl From<[Px; 2]> for FontSize {
60 fn from(xy: [Px; 2]) -> FontSize {
61 FontSize::PixelXY { x: xy[0].0, y: xy[1].0 }
62 }
63}
64
65pub struct Pt(pub f32);
66
67impl From<Pt> for FontSize {
68 fn from(pt: Pt) -> FontSize {
69 FontSize::Point(pt.0)
70 }
71}
72
73pub struct GridSequence<const W: usize, const H: usize> {
74 pub framerate: NonZeroU8,
75 frames: VecDeque<Frame<W, H>>,
76 pub font_scale: FontSize,
77 glyph_set: HashSet<char>
78}
79
80impl<const W: usize, const H: usize> GridSequence<W, H> {
81 pub fn new(s: impl Into<FontSize>) -> Self {
82 Self {
83 framerate: NonZeroU8::MIN,
84 frames: VecDeque::new(),
85 font_scale: s.into(),
86 glyph_set: HashSet::new()
87 }
88 }
89
90 pub fn prepend(&mut self, frame: Frame<W, H>) {
92 for c in frame.grid.chars() {
93 self.glyph_set.insert(c);
94 }
95
96 self.frames.push_front(frame);
97 }
98
99 pub fn append(&mut self, frame: Frame<W, H>) {
101 for c in frame.grid.chars() {
102 self.glyph_set.insert(c);
103 }
104
105 self.frames.push_back(frame);
106 }
107
108 #[inline]
109 pub fn glyph_set(&self) -> &HashSet<char> {
110 &self.glyph_set
111 }
112
113 #[inline]
114 pub(crate) fn pop(&mut self) -> Option<Frame<W, H>> {
115 self.frames.pop_front()
116 }
117
118 pub(crate) fn resolve_px_scale<F: ab_glyph::Font>(&self, font: F) -> ab_glyph::PxScale {
119 match self.font_scale {
120 FontSize::Pixel(s) => ab_glyph::PxScale::from(s),
121 FontSize::PixelXY { x, y } => ab_glyph::PxScale { x, y },
122 FontSize::Point(pt) => font.pt_to_px_scale(pt).expect("not sure why this would fail?")
123 }
124 }
125}