split configuration for audio and video SMUSH decoders
[nihav.git] / nihav-game / src / codecs / smush / mod.rs
1 #[cfg(feature="decoder_smush_video")]
2 enum GlyphEdge {
3 Left,
4 Top,
5 Right,
6 Bottom,
7 None
8 }
9
10 #[cfg(feature="decoder_smush_video")]
11 impl GlyphEdge {
12 fn get(x: usize, y: usize, size: usize) -> Self {
13 if y == 0 {
14 GlyphEdge::Bottom
15 } else if y == size - 1 {
16 GlyphEdge::Top
17 } else if x == 0 {
18 GlyphEdge::Left
19 } else if x == size - 1 {
20 GlyphEdge::Right
21 } else {
22 GlyphEdge::None
23 }
24 }
25 }
26
27 #[cfg(feature="decoder_smush_video")]
28 enum GlyphDir {
29 Left,
30 Up,
31 Right,
32 Down,
33 None
34 }
35
36 #[cfg(feature="decoder_smush_video")]
37 impl GlyphDir {
38 fn get(edge0: GlyphEdge, edge1: GlyphEdge) -> Self {
39 match (edge0, edge1) {
40 (GlyphEdge::Left, GlyphEdge::Right) |
41 (GlyphEdge::Right, GlyphEdge::Left) => GlyphDir::Up,
42 (GlyphEdge::Top, GlyphEdge::Bottom) |
43 (GlyphEdge::Bottom, GlyphEdge::Top) => GlyphDir::Right,
44 (GlyphEdge::Bottom, _) |
45 (_, GlyphEdge::Bottom) => GlyphDir::Up,
46 (GlyphEdge::Top, _) |
47 (_, GlyphEdge::Top) => GlyphDir::Down,
48 (GlyphEdge::Left, _) |
49 (_, GlyphEdge::Left) => GlyphDir::Left,
50 (GlyphEdge::Right, _) |
51 (_, GlyphEdge::Right) => GlyphDir::Right,
52 _ => GlyphDir::None,
53 }
54 }
55 }
56
57 #[cfg(feature="decoder_smush_video")]
58 const XVEC4: [usize; 16] = [0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1];
59 #[cfg(feature="decoder_smush_video")]
60 const YVEC4: [usize; 16] = [0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2];
61 #[cfg(feature="decoder_smush_video")]
62 const XVEC8: [usize; 16] = [0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0];
63 #[cfg(feature="decoder_smush_video")]
64 const YVEC8: [usize; 16] = [0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1];
65
66 #[cfg(feature="decoder_smush_video")]
67 fn make_glyphs_47(glyphs4: &mut [[u8; 16]; 256], glyphs8: &mut [[u8; 64]; 256]) {
68 for (n, glyph) in glyphs4.iter_mut().enumerate() {
69 let i = n >> 4;
70 let j = n & 0xF;
71 make_glyph_47(glyph, XVEC4[i], YVEC4[i], XVEC4[j], YVEC4[j], 4);
72 }
73 for (n, glyph) in glyphs8.iter_mut().enumerate() {
74 let i = n >> 4;
75 let j = n & 0xF;
76 make_glyph_47(glyph, XVEC8[i], YVEC8[i], XVEC8[j], YVEC8[j], 8);
77 }
78 }
79 #[cfg(feature="decoder_smush_video")]
80 fn make_glyph_47(dst: &mut [u8], xi: usize, yi: usize, xj: usize, yj: usize, size: usize) {
81 let edge0 = GlyphEdge::get(xi, yi, size);
82 let edge1 = GlyphEdge::get(xj, yj, size);
83 let dir = GlyphDir::get(edge0, edge1);
84 let npoints = if xi > xj { xi - xj } else { xj - xi }.max(if yi > yj { yi - yj } else { yj - yi });
85 for ipoint in 0..=npoints {
86 let (p0, p1) = if npoints > 0 {
87 (interpolate(xi, xj, ipoint, npoints),
88 interpolate(yi, yj, ipoint, npoints))
89 } else {
90 (xi, yi)
91 };
92 let off = p0 + p1 * size;
93 match dir {
94 GlyphDir::Up => {
95 for i in 0..=p1 {
96 dst[off - i * size] = 1;
97 }
98 },
99 GlyphDir::Down => {
100 for i in 0..size-p1 {
101 dst[off + i * size] = 1;
102 }
103 },
104 GlyphDir::Left => {
105 for i in 0..=p0 {
106 dst[off - i] = 1;
107 }
108 },
109 GlyphDir::Right => {
110 for i in 0..size-p0 {
111 dst[off + i] = 1;
112 }
113 },
114 _ => {},
115 };
116 }
117 }
118 #[cfg(feature="decoder_smush_video")]
119 fn interpolate(a: usize, b: usize, pos1: usize, range: usize) -> usize {
120 (a * pos1 + b * (range - pos1) + range / 2) / range
121 }
122
123 #[cfg(feature="decoder_smush_video")]
124 mod v1;
125 #[cfg(feature="decoder_smush_video")]
126 pub use v1::get_decoder_video_v1;
127 #[cfg(feature="decoder_smush_video")]
128 mod v2;
129 #[cfg(feature="decoder_smush_video")]
130 pub use v2::get_decoder_video_v2;
131
132 #[cfg(feature="decoder_smush_audio")]
133 mod iact;
134 #[cfg(feature="decoder_smush_audio")]
135 pub use iact::get_decoder_iact;
136 #[cfg(feature="decoder_smush_audio")]
137 mod vima;
138 #[cfg(feature="decoder_smush_audio")]
139 pub use vima::get_decoder_vima;