mirui 0.45.0

A lightweight, no_std ECS-driven UI framework for embedded, desktop, and WebAssembly
Documentation
//! Signed-distance sampling for MIRX scalar glyph planes.

use super::scalar::ScalarField;
use crate::types::Fixed;
use mirx::image::Region;

#[derive(Clone, Copy)]
pub(crate) struct SignedDistanceField<'a> {
    scalar: ScalarField<'a>,
    spread: Fixed,
}

impl<'a> SignedDistanceField<'a> {
    pub(crate) fn new(
        samples: &'a [u8],
        stride: u32,
        region: Region,
        bits: u8,
        spread: u16,
    ) -> Option<Self> {
        Some(Self {
            scalar: ScalarField::new(samples, stride, region, bits)?,
            spread: Fixed::from_int(i32::from(spread)),
        })
    }

    pub(crate) fn width(&self) -> u32 {
        self.scalar.width()
    }

    pub(crate) fn height(&self) -> u32 {
        self.scalar.height()
    }

    pub(crate) fn sample_with_gradient(&self, x: Fixed, y: Fixed) -> (Fixed, Fixed, Fixed) {
        let (sample, dx, dy) = self.scalar.sample_bilinear_with_gradient(x, y);
        let distance_scale = self.spread * 2;
        (
            (sample * 2 - Fixed::ONE) * self.spread,
            dx * distance_scale,
            dy * distance_scale,
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use mirx::image::{ColorDescription, SampleLayout, SurfaceDescriptor};

    #[test]
    fn samples_msb_first_regions_with_row_stride() {
        let surface =
            SurfaceDescriptor::new(4, 2, SampleLayout::A4, ColorDescription::NONE).unwrap();
        let region = surface.region(1, 1, 2, 1).unwrap();
        let samples = [0x00, 0xee, 0x04, 0xfe];
        let field = SignedDistanceField::new(&samples, 2, region, 4, 2).unwrap();

        assert!(field.sample_with_gradient(Fixed::ZERO, Fixed::ZERO).0 < Fixed::ZERO);
        assert!(field.sample_with_gradient(Fixed::ONE, Fixed::ZERO).0 > Fixed::ZERO);
    }
}