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