kahlo 0.0.3

Optimized software rendering library.
Documentation
trait Sealed {}

pub(crate) const NUM_PIXEL_FORMATS: usize = 3;

/// a few places rely on this being exactly 4. a partial list:
/// - op::binary_map_pixel_data_with
#[allow(unused)]
pub(crate) const MAX_PIXEL_STRIDE: usize = 4;

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(u8)]
pub enum PixelFormat {
    A8,
    Abgr32,
    Rgba32,
    // Rgba32P,
}

#[derive(Clone, PartialEq, Debug, Default)]
pub enum PackedLocation {
    #[default]
    None,
    Select(u8),
    Clear(u8),
}

impl PackedLocation {
    const fn empty() -> Self {
        Self::None
    }
    const fn select_byte(index: u8) -> Self {
        Self::Select(index)
    }

    pub const fn index(&self) -> Option<u8> {
        match self {
            Self::None => None,
            Self::Select(ndx) => Some(*ndx),
            Self::Clear(_) => None,
        }
    }
    pub const fn clear_index(&self) -> Option<u8> {
        match self {
            Self::Clear(ndx) => Some(*ndx),
            _ => None,
        }
    }
}

#[allow(private_bounds)]
pub trait PixelFormatSpec: Sealed + Clone + Copy + PartialEq {
    const FORMAT_ENUM: PixelFormat;
    const CHANNELS: usize;
    const PIXEL_STRIDE: usize;
    const PREMULTIPLIED: bool;

    const NAME: &'static str;

    const RED_PACK: PackedLocation;
    const GREEN_PACK: PackedLocation;
    const BLUE_PACK: PackedLocation;
    const ALPHA_PACK: PackedLocation;
}

//-----------------------------------------------------------------------------
// Pixel formats
//-----------------------------------------------------------------------------

/// 8-bit alpha map
#[derive(Clone, Copy, PartialEq)]
pub struct A8;
impl Sealed for A8 {}
impl PixelFormatSpec for A8 {
    const FORMAT_ENUM: PixelFormat = PixelFormat::A8;
    const CHANNELS: usize = 1;
    const PIXEL_STRIDE: usize = 1;
    const PREMULTIPLIED: bool = false;

    const NAME: &'static str = "A8";

    const RED_PACK: PackedLocation = PackedLocation::empty();
    const GREEN_PACK: PackedLocation = PackedLocation::empty();
    const BLUE_PACK: PackedLocation = PackedLocation::empty();
    const ALPHA_PACK: PackedLocation = PackedLocation::select_byte(0);
}

/// RGBA with 8 bits per channel, stored big-endian
///
/// This assumes the following memory layout:
/// ```text
///  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
/// ---+---+---+---+---+---+---+---+---
///  A | B | G | R | A | B | G | R | ...
/// ```
#[derive(Clone, Copy, PartialEq)]
pub struct Abgr32;

impl Sealed for Abgr32 {}
impl PixelFormatSpec for Abgr32 {
    const FORMAT_ENUM: PixelFormat = PixelFormat::Abgr32;
    const CHANNELS: usize = 4;
    const PIXEL_STRIDE: usize = 4;
    const PREMULTIPLIED: bool = false;

    const NAME: &'static str = "Abgr32";

    const RED_PACK: PackedLocation = PackedLocation::select_byte(3);
    const GREEN_PACK: PackedLocation = PackedLocation::select_byte(2);
    const BLUE_PACK: PackedLocation = PackedLocation::select_byte(1);
    const ALPHA_PACK: PackedLocation = PackedLocation::select_byte(0);
}

/// RGBA with 8 bits per channel, stored little-endian
///
/// This assumes the following memory layout:
/// ```text
///  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
/// ---+---+---+---+---+---+---+---+---
///  R | G | B | A | R | G | B | A | ...
/// ```
#[derive(Clone, Copy, PartialEq)]
pub struct Rgba32;

impl Sealed for Rgba32 {}
impl PixelFormatSpec for Rgba32 {
    const FORMAT_ENUM: PixelFormat = PixelFormat::Rgba32;
    const CHANNELS: usize = 4;
    const PIXEL_STRIDE: usize = 4;
    const PREMULTIPLIED: bool = false;

    const NAME: &'static str = "Rgba32";

    const RED_PACK: PackedLocation = PackedLocation::select_byte(0);
    const GREEN_PACK: PackedLocation = PackedLocation::select_byte(1);
    const BLUE_PACK: PackedLocation = PackedLocation::select_byte(2);
    const ALPHA_PACK: PackedLocation = PackedLocation::select_byte(3);
}

/// RGBA with 8 bits per channel, stored little-endian, with premultiplied R/G/B channels.
///
/// This assumes the following memory layout:
/// ```text
///  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
/// ---+---+---+---+---+---+---+---+---
///  R | G | B | A | R | G | B | A | ...
/// ```
#[derive(Clone, Copy, PartialEq)]
pub struct Rgba32P;

impl Sealed for Rgba32P {}
impl PixelFormatSpec for Rgba32P {
    const FORMAT_ENUM: PixelFormat = PixelFormat::Rgba32;
    const CHANNELS: usize = 4;
    const PIXEL_STRIDE: usize = 4;
    const PREMULTIPLIED: bool = true;

    const NAME: &'static str = "Rgba32P";

    const RED_PACK: PackedLocation = PackedLocation::select_byte(0);
    const GREEN_PACK: PackedLocation = PackedLocation::select_byte(1);
    const BLUE_PACK: PackedLocation = PackedLocation::select_byte(2);
    const ALPHA_PACK: PackedLocation = PackedLocation::select_byte(3);
}