use ::{Raster,RasterMut};
use super::LinScale;
pub const FLI_PSTAMP: u16 = 18;
pub const FPS_XLAT256: u16 = FLI_PSTAMP;
pub const PSTAMP_SIXCUBE: u16 = 1;
pub const STANDARD_PSTAMP_W: u16 = 100;
pub const STANDARD_PSTAMP_H: u16 = 63;
pub fn make_pstamp_pal(dst: &mut RasterMut) {
assert!(dst.pal.len() >= 6 * 6 * 6);
let mut c = 0;
for r in 0..6 {
for g in 0..6 {
for b in 0..6 {
dst.pal[3 * c + 0] = ((r * 256) / 6) as u8;
dst.pal[3 * c + 1] = ((g * 256) / 6) as u8;
dst.pal[3 * c + 2] = ((b * 256) / 6) as u8;
c = c + 1;
}
}
}
}
pub fn make_pstamp_xlat256(pal: &[u8], xlat256: &mut [u8]) {
assert_eq!(pal.len(), 3 * xlat256.len());
for c in 0..xlat256.len() {
let r = pal[3 * c + 0] as u32;
let g = pal[3 * c + 1] as u32;
let b = pal[3 * c + 2] as u32;
xlat256[c]
= (((6 * r) / 256) * 36
+ ((6 * g) / 256) * 6
+ ((6 * b) / 256)) as u8;
}
}
pub fn apply_pstamp_xlat256(xlat256: &[u8], dst: &mut RasterMut) {
assert!(xlat256.len() >= ::std::u8::MAX as usize);
let start = dst.stride * dst.y;
let end = dst.stride * (dst.y + dst.h);
for row in dst.buf[start..end].chunks_mut(dst.stride) {
let start = dst.x;
let end = start + dst.w;
for e in &mut row[start..end] {
*e = xlat256[*e as usize];
}
}
}
pub fn prepare_pstamp(
src: &Raster, xlat256: &[u8], dst_w: usize, dst_h: usize)
-> Vec<u8> {
assert!(xlat256.len() >= ::std::u8::MAX as usize);
dst_w.checked_mul(dst_h).expect("overflow");
let mut pstamp = vec![0; dst_w * dst_h];
for (sy, dy) in LinScale::new(src.h, dst_h) {
let src_start = src.stride * (src.y + sy) + src.x;
let src_end = src_start + src.w;
let dst_start = dst_w * dy;
let dst_end = dst_start + dst_w;
let src_row = &src.buf[src_start..src_end];
let dst_row = &mut pstamp[dst_start..dst_end];
for (sx, dx) in LinScale::new(src.w, dst_w) {
dst_row[dx] = xlat256[src_row[sx] as usize];
}
}
pstamp
}
#[cfg(test)]
mod tests {
use ::{Raster,RasterMut};
use super::*;
#[test]
fn test_make_pstamp_xlat256() {
let src = [
0x00, 0x00, 0x00,
0x00, 0x00, 0xFF,
0x00, 0xFF, 0x00,
0x00, 0xFF, 0xFF,
0xFF, 0x00, 0x00,
0xFF, 0x00, 0xFF,
0xFF, 0xFF, 0x00,
0xFF, 0xFF, 0xFF ];
let expected = [
0, 5, 30, 35, 180, 185, 210, 215 ];
let mut xlat256 = [0; 8];
make_pstamp_xlat256(&src, &mut xlat256);
assert_eq!(&xlat256[..], &expected[..]);
}
#[test]
fn test_apply_pstamp_xlat256() {
let src = [
0, 5, 30, 35, 180, 185, 210, 215 ];
let mut buf = [
7, 6, 5, 4, 3, 2, 1, 0 ];
let expected = [
215, 210, 185, 180, 35, 30, 5, 0 ];
const SCREEN_W: usize = 8;
const SCREEN_H: usize = 1;
let mut pal = [0; 3 * 256];
let mut xlat256 = [0; 256];
xlat256[0..8].copy_from_slice(&src[..]);
apply_pstamp_xlat256(&xlat256,
&mut RasterMut::new(SCREEN_W, SCREEN_H, &mut buf, &mut pal));
assert_eq!(&buf[..], &expected[..]);
}
#[test]
fn test_prepare_pstamp() {
let src = [
11, 11, 12, 12, 13, 13, 14, 14,
11, 11, 12, 12, 13, 13, 14, 14,
21, 21, 22, 22, 23, 23, 24, 24,
21, 21, 22, 22, 23, 23, 24, 24,
31, 31, 32, 32, 33, 33, 34, 34,
31, 31, 32, 32, 33, 33, 34, 34,
41, 41, 42, 42, 43, 43, 44, 44,
41, 41, 42, 42, 43, 43, 44, 44 ];
let expected = [
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44 ];
const SCREEN_W: usize = 8;
const SCREEN_H: usize = 8;
let mut xlat256 = [0; 256];
let pal = [0; 3 * 256];
for i in 0..256 {
xlat256[i] = i as u8;
}
let raster = Raster::new(SCREEN_W, SCREEN_H, &src, &pal);
let pstamp = prepare_pstamp(
&raster, &xlat256, 4, 4);
assert_eq!(&pstamp[..], &expected[..]);
}
}