X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-game%2Fsrc%2Fcodecs%2Fsmush%2Fmod.rs;fp=nihav-game%2Fsrc%2Fcodecs%2Fsmush%2Fmod.rs;h=9274cbab6ecc51dfd1e653eacff47ed54291333a;hp=0000000000000000000000000000000000000000;hb=c17769db76a6effa4c439af78955002f089a73df;hpb=995e421a17b430ded9b6753d70d3b8c9ac106eed diff --git a/nihav-game/src/codecs/smush/mod.rs b/nihav-game/src/codecs/smush/mod.rs new file mode 100644 index 0000000..9274cba --- /dev/null +++ b/nihav-game/src/codecs/smush/mod.rs @@ -0,0 +1,120 @@ +enum GlyphEdge { + Left, + Top, + Right, + Bottom, + None +} + +impl GlyphEdge { + fn get(x: usize, y: usize, size: usize) -> Self { + if y == 0 { + GlyphEdge::Bottom + } else if y == size - 1 { + GlyphEdge::Top + } else if x == 0 { + GlyphEdge::Left + } else if x == size - 1 { + GlyphEdge::Right + } else { + GlyphEdge::None + } + } +} + +enum GlyphDir { + Left, + Up, + Right, + Down, + None +} + +impl GlyphDir { + fn get(edge0: GlyphEdge, edge1: GlyphEdge) -> Self { + match (edge0, edge1) { + (GlyphEdge::Left, GlyphEdge::Right) | + (GlyphEdge::Right, GlyphEdge::Left) => GlyphDir::Up, + (GlyphEdge::Top, GlyphEdge::Bottom) | + (GlyphEdge::Bottom, GlyphEdge::Top) => GlyphDir::Right, + (GlyphEdge::Bottom, _) | + (_, GlyphEdge::Bottom) => GlyphDir::Up, + (GlyphEdge::Top, _) | + (_, GlyphEdge::Top) => GlyphDir::Down, + (GlyphEdge::Left, _) | + (_, GlyphEdge::Left) => GlyphDir::Left, + (GlyphEdge::Right, _) | + (_, GlyphEdge::Right) => GlyphDir::Right, + _ => GlyphDir::None, + } + } +} + +const XVEC4: [usize; 16] = [0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1]; +const YVEC4: [usize; 16] = [0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2]; +const XVEC8: [usize; 16] = [0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0]; +const YVEC8: [usize; 16] = [0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1]; + +fn make_glyphs_47(glyphs4: &mut [[u8; 16]; 256], glyphs8: &mut [[u8; 64]; 256]) { + for (n, glyph) in glyphs4.iter_mut().enumerate() { + let i = n >> 4; + let j = n & 0xF; + make_glyph_47(glyph, XVEC4[i], YVEC4[i], XVEC4[j], YVEC4[j], 4); + } + for (n, glyph) in glyphs8.iter_mut().enumerate() { + let i = n >> 4; + let j = n & 0xF; + make_glyph_47(glyph, XVEC8[i], YVEC8[i], XVEC8[j], YVEC8[j], 8); + } +} +fn make_glyph_47(dst: &mut [u8], xi: usize, yi: usize, xj: usize, yj: usize, size: usize) { + let edge0 = GlyphEdge::get(xi, yi, size); + let edge1 = GlyphEdge::get(xj, yj, size); + let dir = GlyphDir::get(edge0, edge1); + let npoints = if xi > xj { xi - xj } else { xj - xi }.max(if yi > yj { yi - yj } else { yj - yi }); + for ipoint in 0..=npoints { + let (p0, p1) = if npoints > 0 { + (interpolate(xi, xj, ipoint, npoints), + interpolate(yi, yj, ipoint, npoints)) + } else { + (xi, yi) + }; + let off = p0 + p1 * size; + match dir { + GlyphDir::Up => { + for i in 0..=p1 { + dst[off - i * size] = 1; + } + }, + GlyphDir::Down => { + for i in 0..size-p1 { + dst[off + i * size] = 1; + } + }, + GlyphDir::Left => { + for i in 0..=p0 { + dst[off - i] = 1; + } + }, + GlyphDir::Right => { + for i in 0..size-p0 { + dst[off + i] = 1; + } + }, + _ => {}, + }; + } +} +fn interpolate(a: usize, b: usize, pos1: usize, range: usize) -> usize { + (a * pos1 + b * (range - pos1) + range / 2) / range +} + +mod v1; +pub use v1::get_decoder_video_v1; +mod v2; +pub use v2::get_decoder_video_v2; + +mod iact; +pub use iact::get_decoder_iact; +mod vima; +pub use vima::get_decoder_vima;